Index: /tags/start/DataStore/.cvsignore
===================================================================
--- /tags/start/DataStore/.cvsignore	(revision 12606)
+++ /tags/start/DataStore/.cvsignore	(revision 12606)
@@ -0,0 +1,6 @@
+Build
+META.yml
+Makefile
+Makefile.PL
+_build
+blib
Index: /tags/start/DataStore/Build.PL
===================================================================
--- /tags/start/DataStore/Build.PL	(revision 12606)
+++ /tags/start/DataStore/Build.PL	(revision 12606)
@@ -0,0 +1,24 @@
+use Module::Build;
+# See perldoc Module::Build for details of how this works
+
+Module::Build->new(
+    module_name         => 'DataStore',
+    dist_version_from   => 'lib/DataStore/Parser.pm',
+    author              => 'Joshua Hoblitt <jhoblitt@cpan.org>',
+    license             => 'gpl',
+    create_makefile_pl  => 'passthrough',
+    requires            => {
+        'Carp'                  => 0,
+        'Data::Validate::URI'   => '0.01',
+        'LWP::UserAgent'        => 0,
+        'Params::Validate'      => '0.77',
+        'Regexp::Common'        => '2.113',
+    },
+    build_requires      => {
+        'Test::Warn'            => '0.08',
+    },
+    recommends          => {
+        'Test::Distribution'    => '1.22',
+    },
+#    script_files        => [qw()],
+)->create_build_script;
Index: /tags/start/DataStore/Changes
===================================================================
--- /tags/start/DataStore/Changes	(revision 12606)
+++ /tags/start/DataStore/Changes	(revision 12606)
@@ -0,0 +1,6 @@
+Revision history for Perl module DataStore
+
+0.01 Thu Feb 23 13:55:57 2006
+    - original version; created by ExtUtils::ModuleMaker 0.44
+
+
Index: /tags/start/DataStore/LICENSE
===================================================================
--- /tags/start/DataStore/LICENSE	(revision 12606)
+++ /tags/start/DataStore/LICENSE	(revision 12606)
@@ -0,0 +1,260 @@
+The General Public License (GPL)
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave,
+Cambridge, MA 02139, USA. Everyone is permitted to copy and distribute
+verbatim copies of this license document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share
+and change it. By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to most of
+the Free Software Foundation's software and to any other program whose
+authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom
+to distribute copies of free software (and charge for this service if you wish), that
+you receive source code or can get it if you want it, that you can change the
+software or use pieces of it in new free programs; and that you know you can do
+these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights. These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for a
+fee, you must give the recipients all the rights that you have. You must make
+sure that they, too, receive or can get the source code. And you must show
+them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer
+you this license which gives you legal permission to copy, distribute and/or
+modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced by
+others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We wish
+to avoid the danger that redistributors of a free program will individually obtain
+patent licenses, in effect making the program proprietary. To prevent this, we
+have made it clear that any patent must be licensed for everyone's free use or
+not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+GNU GENERAL PUBLIC LICENSE
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND
+MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License. The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or translated
+into another language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope. The act of running the Program is not
+restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program). Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as
+you receive it, in any medium, provided that you conspicuously and appropriately
+publish on each copy an appropriate copyright notice and disclaimer of warranty;
+keep intact all the notices that refer to this License and to the absence of any
+warranty; and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may at
+your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus
+forming a work based on the Program, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you also
+meet all of these conditions:
+
+a) You must cause the modified files to carry prominent notices stating that you
+changed the files and the date of any change.
+
+b) You must cause any work that you distribute or publish, that in whole or in
+part contains or is derived from the Program or any part thereof, to be licensed
+as a whole at no charge to all third parties under the terms of this License.
+
+c) If the modified program normally reads commands interactively when run, you
+must cause it, when started running for such interactive use in the most ordinary
+way, to print or display an announcement including an appropriate copyright
+notice and a notice that there is no warranty (or else, saying that you provide a
+warranty) and that users may redistribute the program under these conditions,
+and telling the user how to view a copy of this License. (Exception: if the
+Program itself is interactive but does not normally print such an announcement,
+your work based on the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Program, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to
+work written entirely by you; rather, the intent is to exercise the right to control
+the distribution of derivative or collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and 2
+above provided that you also do one of the following:
+
+a) Accompany it with the complete corresponding machine-readable source
+code, which must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange; or,
+
+b) Accompany it with a written offer, valid for at least three years, to give any
+third party, for a charge no more than your cost of physically performing source
+distribution, a complete machine-readable copy of the corresponding source
+code, to be distributed under the terms of Sections 1 and 2 above on a medium
+customarily used for software interchange; or,
+
+c) Accompany it with the information you received as to the offer to distribute
+corresponding source code. (This alternative is allowed only for noncommercial
+distribution and only if you received the program in object code or executable
+form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it. For an executable work, complete source code means all the
+source code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the
+executable. However, as a special exception, the source code distributed need
+not include anything that is normally distributed (in either source or binary form)
+with the major components (compiler, kernel, and so on) of the operating system
+on which the executable runs, unless that component itself accompanies the
+executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source
+code from the same place counts as distribution of the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License. Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License. However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so long
+as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it.
+However, nothing else grants you permission to modify or distribute the Program
+or its derivative works. These actions are prohibited by law if you do not accept
+this License. Therefore, by modifying or distributing the Program (or any work
+based on the Program), you indicate your acceptance of this License to do so,
+and all its terms and conditions for copying, distributing or modifying the
+Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program),
+the recipient automatically receives a license from the original licensor to copy,
+distribute or modify the Program subject to these terms and conditions. You
+may not impose any further restrictions on the recipients' exercise of the rights
+granted herein. You are not responsible for enforcing compliance by third parties
+to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent infringement
+or for any other reason (not limited to patent issues), conditions are imposed on
+you (whether by court order, agreement or otherwise) that contradict the
+conditions of this License, they do not excuse you from the conditions of this
+License. If you cannot distribute so as to satisfy simultaneously your obligations
+under this License and any other pertinent obligations, then as a consequence
+you may not distribute the Program at all. For example, if a patent license would
+not permit royalty-free redistribution of the Program by all those who receive
+copies directly or indirectly through you, then the only way you could satisfy
+both it and this License would be to refrain entirely from distribution of the
+Program.
+
+If any portion of this section is held invalid or unenforceable under any particular
+circumstance, the balance of the section is intended to apply and the section as
+a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other
+property right claims or to contest validity of any such claims; this section has
+the sole purpose of protecting the integrity of the free software distribution
+system, which is implemented by public license practices. Many people have
+made generous contributions to the wide range of software distributed through
+that system in reliance on consistent application of that system; it is up to the
+author/donor to decide if he or she is willing to distribute software through any
+other system and a licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain countries
+either by patents or by copyrighted interfaces, the original copyright holder who
+places the Program under this License may add an explicit geographical
+distribution limitation excluding those countries, so that distribution is permitted
+only in or among countries not thus excluded. In such case, this License
+incorporates the limitation as if written in the body of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the
+General Public License from time to time. Such new versions will be similar in
+spirit to the present version, but may differ in detail to address new problems or
+concerns.
+
+Each version is given a distinguishing version number. If the Program specifies a
+version number of this License which applies to it and "any later version", you
+have the option of following the terms and conditions either of that version or of
+any later version published by the Free Software Foundation. If the Program does
+not specify a version number of this License, you may choose any version ever
+published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission. For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of all
+derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS
+NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
+COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
+"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR
+IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED
+TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY
+WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS
+PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
+(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
+OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
Index: /tags/start/DataStore/MANIFEST
===================================================================
--- /tags/start/DataStore/MANIFEST	(revision 12606)
+++ /tags/start/DataStore/MANIFEST	(revision 12606)
@@ -0,0 +1,10 @@
+MANIFEST
+README
+LICENSE
+Todo
+Changes
+Build.PL
+Makefile.PL
+lib/DataStore/Parser.pm
+t/00_distribution.t
+t/01_load.t
Index: /tags/start/DataStore/README
===================================================================
--- /tags/start/DataStore/README	(revision 12606)
+++ /tags/start/DataStore/README	(revision 12606)
@@ -0,0 +1,15 @@
+pod2text DataStore.pm > README
+
+If this is still here it means the programmer was too lazy to create the readme file.
+
+You can create it now by using the command shown above from this directory.
+
+At the very least you should be able to use this set of instructions
+to install the module...
+
+perl Build.PL
+./Build
+./Build test
+./Build install
+
+If you are on a windows box you should use 'nmake' rather than 'make'.
Index: /tags/start/DataStore/Todo
===================================================================
--- /tags/start/DataStore/Todo	(revision 12606)
+++ /tags/start/DataStore/Todo	(revision 12606)
@@ -0,0 +1,5 @@
+TODO list for Perl module DataStore
+
+- Nothing yet
+
+
Index: /tags/start/DataStore/lib/DataStore/Parser.pm
===================================================================
--- /tags/start/DataStore/lib/DataStore/Parser.pm	(revision 12606)
+++ /tags/start/DataStore/lib/DataStore/Parser.pm	(revision 12606)
@@ -0,0 +1,111 @@
+package DataStore;
+use strict;
+
+BEGIN {
+    use Exporter ();
+    use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+    $VERSION     = '0.01';
+    @ISA         = qw(Exporter);
+    #Give a hoot don't pollute, do not export more than needed by default
+    @EXPORT      = qw();
+    @EXPORT_OK   = qw();
+    %EXPORT_TAGS = ();
+}
+
+
+#################### subroutine header begin ####################
+
+=head2 sample_function
+
+ Usage     : How to use this function/method
+ Purpose   : What it does
+ Returns   : What it returns
+ Argument  : What it wants to know
+ Throws    : Exceptions and other anomolies
+ Comment   : This is a sample subroutine header.
+           : It is polite to include more pod and fewer comments.
+
+See Also   : 
+
+=cut
+
+#################### subroutine header end ####################
+
+
+sub new
+{
+    my ($class, %parameters) = @_;
+
+    my $self = bless ({}, ref ($class) || $class);
+
+    return $self;
+}
+
+
+#################### main pod documentation begin ###################
+## Below is the stub of documentation for your module. 
+## You better edit it!
+
+
+=head1 NAME
+
+DataStore - Module abstract (<= 44 characters) goes here
+
+=head1 SYNOPSIS
+
+  use DataStore;
+  blah blah blah
+
+
+=head1 DESCRIPTION
+
+Stub documentation for this module was created by ExtUtils::ModuleMaker.
+It looks like the author of the extension was negligent enough
+to leave the stub unedited.
+
+Blah blah blah.
+
+
+=head1 USAGE
+
+
+
+=head1 BUGS
+
+
+
+=head1 SUPPORT
+
+
+
+=head1 AUTHOR
+
+    A. U. Thor
+    CPAN ID: MODAUTHOR
+    XYZ Corp.
+    a.u.thor@a.galaxy.far.far.away
+    http://a.galaxy.far.far.away/modules
+
+=head1 COPYRIGHT
+
+This program is free software licensed under the...
+
+	The General Public License (GPL)
+	Version 2, June 1991
+
+The full text of the license can be found in the
+LICENSE file included with this module.
+
+
+=head1 SEE ALSO
+
+perl(1).
+
+=cut
+
+#################### main pod documentation end ###################
+
+
+1;
+# The preceding line will help the module return a true value
+
Index: /tags/start/DataStore/t/00_distribution.t
===================================================================
--- /tags/start/DataStore/t/00_distribution.t	(revision 12606)
+++ /tags/start/DataStore/t/00_distribution.t	(revision 12606)
@@ -0,0 +1,25 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2005  Joshua Hoblitt
+#
+# $Id: 00_distribution.t,v 1.1.1.1 2006-02-24 00:03:06 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use lib qw( ./lib ./t );
+
+use Test::More;
+
+# example taken from Test::Distribution Pod
+
+BEGIN {
+    eval {
+        require Test::Distribution;
+    };
+    if($@) {
+        plan skip_all => 'Test::Distribution not installed';
+    } else {
+        import Test::Distribution not => qw( podcover );
+    }
+}
Index: /tags/start/DataStore/t/01_load.t
===================================================================
--- /tags/start/DataStore/t/01_load.t	(revision 12606)
+++ /tags/start/DataStore/t/01_load.t	(revision 12606)
@@ -0,0 +1,12 @@
+# -*- perl -*-
+
+# t/001_load.t - check module loading and create testing directory
+
+use Test::More tests => 2;
+
+BEGIN { use_ok( 'DataStore::Parser' ); }
+
+my $object = DataStore::Parser->new ();
+isa_ok ($object, 'DataStore::Parser');
+
+
Index: /tags/start/Nebulous-Server/Build.PL
===================================================================
--- /tags/start/Nebulous-Server/Build.PL	(revision 12606)
+++ /tags/start/Nebulous-Server/Build.PL	(revision 12606)
@@ -0,0 +1,30 @@
+use Module::Build;
+# See perldoc Module::Build for details of how this works
+
+my $build_pkg   = eval { require Apache::TestMB }
+                ? 'Apache::TestMB'
+                : 'Module::Build';
+
+$build_pkg->new(
+    module_name         => 'PS::IPP::IData',
+    dist_version_from   => 'lib/PS/IPP/IData/Server.pm',
+    author              => 'Joshua Hoblitt <jhoblitt@cpan.org>',
+    license             => 'gpl',
+    requires            => {
+        'URI'                   => 1.30,
+        'SOAP::Lite'            => 0.60,
+        'Log::Log4perl'         => 0.48,
+        'DBI'                   => 1.42,
+        'DBD::mysql'            => 2.9004,
+        'Class::Accessor::Fast' => 0,
+        'Params::Validate'      => 0,
+        'Apache::Test'          => 1.12,
+        'Test::More'            => 0.49,
+    },
+    recommends          => {
+        'Apache::DBI'           => 0.94,
+    },
+    build_requires      => {
+        'File::Temp'            => 0,
+    },
+)->create_build_script;
Index: /tags/start/Nebulous-Server/Changes
===================================================================
--- /tags/start/Nebulous-Server/Changes	(revision 12606)
+++ /tags/start/Nebulous-Server/Changes	(revision 12606)
@@ -0,0 +1,5 @@
+Revision history for Perl module Poi::PixelData
+
+0.01 Fri Sep  3 10:23:31 2004
+    - first working version
+	- original version; created by ExtUtils::ModuleMaker 0.32
Index: /tags/start/Nebulous-Server/LICENSE
===================================================================
--- /tags/start/Nebulous-Server/LICENSE	(revision 12606)
+++ /tags/start/Nebulous-Server/LICENSE	(revision 12606)
@@ -0,0 +1,260 @@
+The General Public License (GPL)
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave,
+Cambridge, MA 02139, USA. Everyone is permitted to copy and distribute
+verbatim copies of this license document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share
+and change it. By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to most of
+the Free Software Foundation's software and to any other program whose
+authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom
+to distribute copies of free software (and charge for this service if you wish), that
+you receive source code or can get it if you want it, that you can change the
+software or use pieces of it in new free programs; and that you know you can do
+these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights. These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for a
+fee, you must give the recipients all the rights that you have. You must make
+sure that they, too, receive or can get the source code. And you must show
+them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer
+you this license which gives you legal permission to copy, distribute and/or
+modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced by
+others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We wish
+to avoid the danger that redistributors of a free program will individually obtain
+patent licenses, in effect making the program proprietary. To prevent this, we
+have made it clear that any patent must be licensed for everyone's free use or
+not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+GNU GENERAL PUBLIC LICENSE
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND
+MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License. The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or translated
+into another language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope. The act of running the Program is not
+restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program). Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as
+you receive it, in any medium, provided that you conspicuously and appropriately
+publish on each copy an appropriate copyright notice and disclaimer of warranty;
+keep intact all the notices that refer to this License and to the absence of any
+warranty; and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may at
+your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus
+forming a work based on the Program, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you also
+meet all of these conditions:
+
+a) You must cause the modified files to carry prominent notices stating that you
+changed the files and the date of any change.
+
+b) You must cause any work that you distribute or publish, that in whole or in
+part contains or is derived from the Program or any part thereof, to be licensed
+as a whole at no charge to all third parties under the terms of this License.
+
+c) If the modified program normally reads commands interactively when run, you
+must cause it, when started running for such interactive use in the most ordinary
+way, to print or display an announcement including an appropriate copyright
+notice and a notice that there is no warranty (or else, saying that you provide a
+warranty) and that users may redistribute the program under these conditions,
+and telling the user how to view a copy of this License. (Exception: if the
+Program itself is interactive but does not normally print such an announcement,
+your work based on the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Program, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to
+work written entirely by you; rather, the intent is to exercise the right to control
+the distribution of derivative or collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and 2
+above provided that you also do one of the following:
+
+a) Accompany it with the complete corresponding machine-readable source
+code, which must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange; or,
+
+b) Accompany it with a written offer, valid for at least three years, to give any
+third party, for a charge no more than your cost of physically performing source
+distribution, a complete machine-readable copy of the corresponding source
+code, to be distributed under the terms of Sections 1 and 2 above on a medium
+customarily used for software interchange; or,
+
+c) Accompany it with the information you received as to the offer to distribute
+corresponding source code. (This alternative is allowed only for noncommercial
+distribution and only if you received the program in object code or executable
+form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it. For an executable work, complete source code means all the
+source code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the
+executable. However, as a special exception, the source code distributed need
+not include anything that is normally distributed (in either source or binary form)
+with the major components (compiler, kernel, and so on) of the operating system
+on which the executable runs, unless that component itself accompanies the
+executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source
+code from the same place counts as distribution of the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License. Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License. However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so long
+as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it.
+However, nothing else grants you permission to modify or distribute the Program
+or its derivative works. These actions are prohibited by law if you do not accept
+this License. Therefore, by modifying or distributing the Program (or any work
+based on the Program), you indicate your acceptance of this License to do so,
+and all its terms and conditions for copying, distributing or modifying the
+Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program),
+the recipient automatically receives a license from the original licensor to copy,
+distribute or modify the Program subject to these terms and conditions. You
+may not impose any further restrictions on the recipients' exercise of the rights
+granted herein. You are not responsible for enforcing compliance by third parties
+to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent infringement
+or for any other reason (not limited to patent issues), conditions are imposed on
+you (whether by court order, agreement or otherwise) that contradict the
+conditions of this License, they do not excuse you from the conditions of this
+License. If you cannot distribute so as to satisfy simultaneously your obligations
+under this License and any other pertinent obligations, then as a consequence
+you may not distribute the Program at all. For example, if a patent license would
+not permit royalty-free redistribution of the Program by all those who receive
+copies directly or indirectly through you, then the only way you could satisfy
+both it and this License would be to refrain entirely from distribution of the
+Program.
+
+If any portion of this section is held invalid or unenforceable under any particular
+circumstance, the balance of the section is intended to apply and the section as
+a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other
+property right claims or to contest validity of any such claims; this section has
+the sole purpose of protecting the integrity of the free software distribution
+system, which is implemented by public license practices. Many people have
+made generous contributions to the wide range of software distributed through
+that system in reliance on consistent application of that system; it is up to the
+author/donor to decide if he or she is willing to distribute software through any
+other system and a licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain countries
+either by patents or by copyrighted interfaces, the original copyright holder who
+places the Program under this License may add an explicit geographical
+distribution limitation excluding those countries, so that distribution is permitted
+only in or among countries not thus excluded. In such case, this License
+incorporates the limitation as if written in the body of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the
+General Public License from time to time. Such new versions will be similar in
+spirit to the present version, but may differ in detail to address new problems or
+concerns.
+
+Each version is given a distinguishing version number. If the Program specifies a
+version number of this License which applies to it and "any later version", you
+have the option of following the terms and conditions either of that version or of
+any later version published by the Free Software Foundation. If the Program does
+not specify a version number of this License, you may choose any version ever
+published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission. For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of all
+derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS
+NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
+COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
+"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR
+IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED
+TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY
+WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS
+PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
+(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
+OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
Index: /tags/start/Nebulous-Server/MANIFEST
===================================================================
--- /tags/start/Nebulous-Server/MANIFEST	(revision 12606)
+++ /tags/start/Nebulous-Server/MANIFEST	(revision 12606)
@@ -0,0 +1,53 @@
+Build.PL
+Changes
+LICENSE
+MANIFEST
+META.yml
+Makefile.PL
+README
+TODO
+Todo
+bootstrap.sh
+docs/apache_setup.txt
+docs/c_api.h
+docs/calc_gid.c
+docs/database_setup.txt
+docs/design.txt
+docs/requirements.txt
+docs/setup.txt
+docs/tmp.txt
+iData.wsdl
+lib/PS/IPP/IData/Client.pm
+lib/PS/IPP/IData/Client/HTTP.pm
+lib/PS/IPP/IData/Client/Log.pm
+lib/PS/IPP/IData/Server.pm
+lib/PS/IPP/IData/Server/Apache.pm
+lib/PS/IPP/IData/Server/Log.pm
+lib/PS/IPP/IData/Server/SQL.pm
+lib/PS/IPP/IData/Util.pm
+scripts/bench_test.pl
+scripts/imageserver.pl
+scripts/ptest.pl
+scripts/stest.pl
+t/01_load.t
+t/02_server_setup.t
+t/03_server_create_object.t
+t/04_server_replicate_object.t
+t/05_server_lock_object.t
+t/06_server_unlock_object.t
+t/07_server_find_instances.t
+t/08_server_delete_instance.t
+t/09_server_stat_object.t
+t/10_client_new.t
+t/11_client_create.t
+t/12_client_replicate.t
+t/13_client_cull.t
+t/14_client_lock.t
+t/15_client_unlock.t
+t/16_client_find_instances.t
+t/TEST.PL
+t/Test/IData.pm
+t/apache_03_server_create_object.x
+t/apache_04_server_replicate_object.x
+t/apache_05_server_lock_object.x
+t/conf/extra.conf.in
Index: /tags/start/Nebulous-Server/Makefile.PL
===================================================================
--- /tags/start/Nebulous-Server/Makefile.PL	(revision 12606)
+++ /tags/start/Nebulous-Server/Makefile.PL	(revision 12606)
@@ -0,0 +1,27 @@
+unless (eval "use Module::Build::Compat 0.02; 1" ) {
+  print "This module requires Module::Build to install itself.\n";
+
+  require ExtUtils::MakeMaker;
+  my $yn = ExtUtils::MakeMaker::prompt
+    ('  Install Module::Build from CPAN?', 'y');
+
+  if ($yn =~ /^y/i) {
+    require Cwd;
+    require File::Spec;
+    require CPAN;
+
+    # Save this 'cause CPAN will chdir all over the place.
+    my $cwd = Cwd::cwd();
+    my $makefile = File::Spec->rel2abs($0);
+
+    CPAN::Shell->install('Module::Build::Compat');
+
+    chdir $cwd or die "Cannot chdir() back to $cwd: $!";
+    exec $^X, $makefile, @ARGV;  # Redo now that we have Module::Build
+  } else {
+    warn " *** Cannot install without Module::Build.  Exiting ...\n";
+    exit 1;
+  }
+}
+Module::Build::Compat->run_build_pl(args => \@ARGV);
+Module::Build::Compat->write_makefile();
Index: /tags/start/Nebulous-Server/README
===================================================================
--- /tags/start/Nebulous-Server/README	(revision 12606)
+++ /tags/start/Nebulous-Server/README	(revision 12606)
@@ -0,0 +1,16 @@
+pod2text Poi::PixelData.pm > README
+
+If this is still here it means the programmer was too lazy to create the readme file.
+
+You can create it now by using the command shown above from this directory.
+
+At the very least you should be able to use this set of instructions
+to install the module...
+
+perl Build.PL
+./Build
+./Build test
+./Build install
+
+
+If you are on a windows box you should use 'nmake' rather than 'make'.
Index: /tags/start/Nebulous-Server/TODO
===================================================================
--- /tags/start/Nebulous-Server/TODO	(revision 12606)
+++ /tags/start/Nebulous-Server/TODO	(revision 12606)
@@ -0,0 +1,17 @@
+cache some database tables (updated at some interval) 
+reuse/cache database statement handles
+code tiding/consistency
+volume handling for instance placement
+file creation retrying
+server config file
+make Apache::DBI behave
+WSDL
+split SOAP out of Client.pm
+error string support
+
+distant future
+--
+volume size/% in-use discovery
+server side per client lock tracking
+client side lookup table of filehandles/locks
+Perl only?, scoped lock release/filehandle destruction
Index: /tags/start/Nebulous-Server/Todo
===================================================================
--- /tags/start/Nebulous-Server/Todo	(revision 12606)
+++ /tags/start/Nebulous-Server/Todo	(revision 12606)
@@ -0,0 +1,5 @@
+TODO list for Perl module Poi::PixelData
+
+- Nothing yet
+
+
Index: /tags/start/Nebulous-Server/bootstrap-moa-mp1.sh
===================================================================
--- /tags/start/Nebulous-Server/bootstrap-moa-mp1.sh	(revision 12606)
+++ /tags/start/Nebulous-Server/bootstrap-moa-mp1.sh	(revision 12606)
@@ -0,0 +1,1 @@
+perl Build.PL -http_conf /usr/local/apache/conf/httpd.conf -apxs /usr/local/apache/bin/apxs -httpd /usr/local/apache/bin/httpd 
Index: /tags/start/Nebulous-Server/docs/apache_setup.txt
===================================================================
--- /tags/start/Nebulous-Server/docs/apache_setup.txt	(revision 12606)
+++ /tags/start/Nebulous-Server/docs/apache_setup.txt	(revision 12606)
@@ -0,0 +1,37 @@
+- add the "idata" group to /etc/group
+- configure Apache to run as the idata group. 
+
+#
+# CGI interface
+#
+
+ScriptAlias /idata /usr/local/apache/perl/imageserver.pl
+
+<Directory "/usr/local/apache/perl">
+        AllowOverride None
+        Options None
+        Order allow,deny
+        Allow from all
+</Directory>
+
+PerlModule Apache::PerlRun
+<Location /perl>
+        SetHandler perl-script
+        PerlHandler Apache::PerlRun
+        Options ExecCGI
+        allow from all
+        PerlSendHeader On
+</Location>
+
+#
+# PS::IPP::IData::Apache interface
+#
+
+PerlModule Apache::DBI
+PerlModule PS::IPP::IData::Apache
+
+<Location /idata>
+        SetHandler perl-script
+        PerlHandler PS::IPP::IData::Apache
+</Location>
+
Index: /tags/start/Nebulous-Server/docs/c_api.h
===================================================================
--- /tags/start/Nebulous-Server/docs/c_api.h	(revision 12606)
+++ /tags/start/Nebulous-Server/docs/c_api.h	(revision 12606)
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2004 Joshua Hoblitt
+ *
+ * $Id: c_api.h,v 1.1.1.1 2004-12-22 02:16:23 jhoblitt Exp $
+ */
+
+// should there be an argument for "suggested" storage location?
+int add( const char *ext_id, const char *data, int size )
+
+int delete( const char *ext_id )
+
+// should there be an argument for "suggested" storage location?
+int update( const char *ext_id, const char *data, int size )
+
+// should there be an argument for "suggested" storage location?
+int move( const char *old_ext_id, const char *new_ext_id )
+
+// open returns a fd 
+int open( const char *ext_id )
+
+int close( const char *ext_id )
+
+// maybe open and close are a bad idea, perhaps...
+int read( const char *ext_id, char *data )
Index: /tags/start/Nebulous-Server/docs/calc_gid.c
===================================================================
--- /tags/start/Nebulous-Server/docs/calc_gid.c	(revision 12606)
+++ /tags/start/Nebulous-Server/docs/calc_gid.c	(revision 12606)
@@ -0,0 +1,5 @@
+#include <stdio.h>
+
+main () {
+    printf( "%d\n", 'i'+'m'+'a'+'g'+'e'+'d'+'a'+'t'+'a' + 's'+'e'+'r'+'v'+'e'+'r' );
+}
Index: /tags/start/Nebulous-Server/docs/database_setup.txt
===================================================================
--- /tags/start/Nebulous-Server/docs/database_setup.txt	(revision 12606)
+++ /tags/start/Nebulous-Server/docs/database_setup.txt	(revision 12606)
@@ -0,0 +1,147 @@
+# Copyright (C) 2004  Joshua Hoblitt
+#
+# $Id: database_setup.txt,v 1.1.1.1 2004-12-22 02:16:23 jhoblitt Exp $
+
+### Database Setup
+
+DROP DATABASE IF EXISTS pixel;
+CREATE DATABASE pixel;
+INSERT INTO db VALUES ('%','pixel','pixel','y','y','y','y','y','y','y','y','y','y','y','y');
+INSERT INTO user
+(Host,User,Password,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Index_priv,Alter_priv,Show_db_priv)
+VALUES ('%','pixel',password('pixel'),'y','y','y','y','y','y','y','y','y');
+INSERT INTO user
+(Host,User,Password,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Index_priv,Alter_priv,Show_db_priv)
+VALUES ('localhost','pixel',password('pixel'),'y','y','y','y','y','y','y','y','y');
+FLUSH PRIVILEGES;
+
+USE pixel;
+
+### MySQL 4.0
+
+DROP TABLE IF EXISTS storage_object;
+CREATE TABLE storage_object (
+    so_id BIGINT NOT NULL AUTO_INCREMENT,
+    ext_id VARCHAR(255) BINARY NOT NULL UNIQUE,
+    class_id TINYINT NOT NULL,
+    comment VARCHAR(255),
+    read_lock TINYINT DEFAULT 0 NOT NULL,
+    write_lock ENUM( 'write' ),
+    epoch TIMESTAMP NOT NULL,
+    PRIMARY KEY(so_id),
+    KEY(ext_id(64)),
+    KEY(class_id)
+) ENGINE=innodb;
+
+DROP TABLE IF EXISTS instance;
+CREATE TABLE instance ( 
+    ins_id BIGINT NOT NULL AUTO_INCREMENT,
+    so_id BIGINT NOT NULL,
+    uri VARCHAR(255) BINARY NOT NULL UNIQUE,
+    sha1sum CHAR(40),
+    assigned_location BOOL,
+    epoch TIMESTAMP NOT NULL,
+    atime TIMESTAMP NOT NULL,
+    PRIMARY KEY(ins_id),
+    KEY(so_id),
+    KEY(uri(64))
+) ENGINE=innodb;
+
+DROP TABLE IF EXISTS lock_record;
+CREATE TABLE lock_record (
+        so_id BIGINT NOT NULL,
+        type ENUM( 'read', 'write' ) NOT NULL,
+        epoch TIMESTAMP,
+        KEY(so_ID)
+    ) ENGINE=innodb;
+
+DROP TABLE IF EXISTS volume;
+CREATE TABLE volume (
+        vol_id INT NOT NULL AUTO_INCREMENT,
+        name VARCHAR(255) UNIQUE BINARY NOT NULL,
+        uri VARCHAR(255) BINARY NOT NULL,
+        key(vol_id)
+    ) ENGINE=innodb;
+
+DROP TABLE IF EXISTS class;
+CREATE TABLE class (
+        class_id TINYINT NOT NULL AUTO_INCREMENT,
+        instance TINYINT NOT NULL,
+        priority TINYINT,
+        comment VARCHAR(255),
+        key(class_id)
+    ) ENGINE=innodb;
+
+### MySQL 4.1
+
+DROP TABLE IF EXISTS storage_object;
+CREATE TABLE storage_object (
+        so_id BIGINT NOT NULL AUTO_INCREMENT,
+        ext_id VARCHAR(255) UNIQUE BINARY NOT NULL,
+        comment VARCHAR(255),
+        epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+        PRIMARY KEY(so_id),
+        KEY(ext_id(20))
+    ) ENGINE=innodb;
+
+
+DROP TABLE IF EXISTS instance;
+CREATE TABLE instance ( 
+        ins_id BIGINT NOT NULL AUTO_INCREMENT,
+        so_id BIGINT NOT NULL,
+        uri VARCHAR(255) BINARY NOT NULL,
+        sha1sum CHAR(40) ASCII,
+        read_lock TINYINT NOT NULL,
+        write_lock ENUM( 'write', 'wait' ),
+        atime TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+        PRIMARY KEY(ins_id),
+        KEY(so_id)
+    ) ENGINE=innodb;
+
+DROP TABLE IF EXISTS lock_record;
+CREATE TABLE lock_record (
+        ins_id BIGINT NOT NULL,
+        type ENUM( 'read', 'write', 'wait' ) NOT NULL,
+        epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+    ) ENGINE=innodb;
+
+        epoch TIMESTAMP,
+
+### Initialization
+
+# NFS
+
+INSERT INTO volume VALUES (1,'po01','file:/tmp/po01');
+INSERT INTO volume VALUES (2,'po02','file:/tmp/po02');
+INSERT INTO volume VALUES (3,'po03','file:/tmp/po03');
+INSERT INTO volume VALUES (4,'po04','file:/tmp/po04');
+INSERT INTO volume VALUES (5,'po05','file:/tmp/po05');
+INSERT INTO volume VALUES (6,'po06','file:/tmp/po06');
+INSERT INTO volume VALUES (7,'po07','file:/tmp/po07');
+INSERT INTO volume VALUES (8,'po08','file:/tmp/po08');
+
+INSERT INTO class VALUES (1,3,0,'raw image data');
+
+### Example queries
+
+LOAD DATA INFILE '/home/moa/jhoblitt/tmp/storage_objects.txt' INTO TABLE storage_object; 
+LOAD DATA INFILE '/home/moa/jhoblitt/tmp/instances.txt' INTO TABLE instance; 
+
+SELECT * FROM storage_object LEFT JOIN instance ON storage_object.so_id=instance.so_id WHERE storage_object.ext_id = "foobarbaz1.fits";
+SELECT * FROM storage_object LEFT JOIN instance USING (so_id) WHERE storage_object.ext_id = "foobarbaz1.fits";
+
+SET AUTOCOMMIT = 0;
+BEGIN;
+UPDATE instance SET read_lock=read_lock+1 WHERE ins_id=1;
+INSERT INTO lock_record values (1, 'read', NULL);
+COMMIT;
+
+SET AUTOCOMMIT = 0;
+BEGIN;
+INSERT INTO storage_object values (NULL, 'myfooedbar.fits', 'mr. wizard made this', NULL);
+INSERT INTO instance values (NULL, LAST_INSERT_ID(), 'file://tmp/bat/man/12345a', 'da39a3ee5e6b4b0d3255bfef95601890afd80709',0, NULL, NULL);
+COMMIT;
+
+IF select write_lock from instance WHERE id=1 THEN
+ELSE
+ENDIF
Index: /tags/start/Nebulous-Server/docs/design.txt
===================================================================
--- /tags/start/Nebulous-Server/docs/design.txt	(revision 12606)
+++ /tags/start/Nebulous-Server/docs/design.txt	(revision 12606)
@@ -0,0 +1,163 @@
+# Copryight (C) 2004  Joshua Hoblitt
+#
+# $Id: design.txt,v 1.1.1.1 2004-12-22 02:16:23 jhoblitt Exp $
+
+Terminology
+--
+    - Storage Object
+There is one Storage Object per resource (a file) that is being managed by the
+IPP Pixel Data Server.  A Storage Object maps an External Identifier (eg.
+file name) to a Storage ID that is internal to the IPP Pixel Data Server.  In
+addition, creation time and comments may be stored in a Storage Object.
+Storage Objects /do not/ contain the storage location of a resource as we need
+to allow for N copies of a resource to be stored.  The actual storage location
+of a resource is held in a Storage Object Instance, which maps to a Storage ID
+in a many-to-one relationship.
+
+    - [Storage Object] Instance
+A Storage Object Instance, or just Instance, represents a single copy of a
+resource being managed by the IPP Pixel Data Server. An Instance contains an
+Instance ID, the location of the resource as a URI, a checksum of the
+resource, a Storage ID, a read lock semaphore (unsigned integer), a write lock
+mutex (enum( 'write', 'wait', 'free' ) - is this better then using an int and
+constants?), and a UTC timestamp of the last modification date & time.
+
+    - Lock Record
+A Lock Record is used to double check the indicated lock state of an Instance
+and can be used to identify system failures.  It must contain the Instance ID
+of of the locked instance and the type of lock, eg, enum( 'read', 'write').
+
+Locking semantics
+--
+A lock is required to either read from or write to a Storage Object Instance
+being managed by the IPP Pixel Data Server.  Stated another way, locking
+granularity is managed on the level of Storage Object Instances instead of on
+the more abstract Storage Objects.  Although, from the client perspective,
+operations are carried out on a Storage Object.   The locking state of a
+Storage Object Instance is maintained by in the Storage Object Instance and a
+Lock Record.
+
+Two types of locks are used on an Instance, a semaphore is used to track read
+locks and an exclusive mutex is for write locking.
+
+    - Read lock
+In order to read from a Storage Object Instance the Read Lock semaphore must
+first be incremented by one and a Lock Record created.  After the read is
+completed the Lock Record must be deleted and the Read Lock semaphore
+decremented by one.  The incrementation of the Read Lock and Lock Record
+creation or the decrementation of the Read Lock and the Lock Record deletion
+must happen atomically.  A Read lock can not be aquired unless the Write mutex
+is in the state of 'free'.  If a Read lock can not be aquired, a client must
+not "spin lock" on the Instanace ID as it may be in the process of being
+removed.  Instead, the "spin lock" should be re-resolving the external
+identifier to a Storage ID, and the Storage ID to Storage Instances.
+
+    - Write lock
+In order to obtain a Write lock on a Storage Object Instance the Write Lock
+mutex must be in the state of 'free' and the Read lock semaphore must have a
+value of zero.  A client should either "spin lock" or fail if all the Lock
+mutex is set or the Read Semaphore has a non-zero value.  A Lock Record must
+be created atomically with the setting of the Write mutex.  The setting of the
+Write mutex and Lock Record insertion or the clearing of the Write mutex and
+the Lock Record deletion must happen atomically.  If the Write lock has a
+state of 'free' and the Read lock has a non-zero value, the Write lock may be
+set to the 'wait' state to prevent new Read locks from being aquired.
+
+Storage Object Operations
+--
+    - Add
+The resource must already be on disk (having been named through some sort of
+mechanism to generate new filenames).  A new Storage Object must be created with a new/unqiue  Storage ID and has
+an associated with an External Identifier.  At least one Instance must be
+created atomicaly at the same time.  Each new Instance must be initially created with a Write lock.
+The resource may then be written to it's storage location.  When the writing
+of the resource is completed the Write lock must be cleared as early as is
+feasible.  The association of an External Identifier must wait until Instance
+creation is completed
+
+    - Delete
+In order to remove a Storage Object, a Write lock must be obtained on
+/all/ associated Instances.  Then the resources are removed.  As each resource
+is deleted the corresponding Instance must be deleted.  After all Instances are
+removed the Storage Object must then be deleted.
+
+    - Update
+Storage Object Instances are not truly written to.  Instead, a new set of
+Storage Object Instances and a new Storage Object are created in parallel.
+
+Write locks must be aquired on all the orignal Intances of a Storage Object.
+Then an Add operation is performed to create a new Storage Object and
+associated Instances.  Then the External Identifier must be atomically moved
+from the original Storage Object to the new Storage Object.  After the
+External Identifier migration, the original Storage Object and it's Instances
+should be removed with a special case of the Delete operation (one that will
+operate on already held locks).  If the old Storage Object is merely
+abandoned, ie. it still exists but doesn't have an External Identifier, it and
+the associated Instances will be removed during the next Consistency Sweep.
+If a Delete is not peformed, the Write locks on the orignal Instances must be
+released. [use a dead Storage Object table or flag, similar to mark and sweep
+garbage collection?]
+
+    - Move
+This is the same operation as an Update except the new Instances are identical
+to the old.
+
+    - Open
+Sets a Read lock on an Instances of a Storage Object and determines it's
+storage location.  A Read lock must only be placed on one Instance of a
+Storage Object.  All Instances of a Storage Object should be iterated through
+in a "spin lock" until a Read lock is aquired.
+
+    - Close
+Releases a Read lock aquired with open.
+
+The lock must be released as soon as is feasible.
+
+Lock sweeping
+--
+In the event that a Storage Object operation fails to complete successfully
+stale locks will have to be identified and removed from the IPP Pixel Data
+Server Database.  This should be done periodically by comparing the entries
+in the Lock table to the list of active nodes maintained by the IPP
+Controller.  It should also happen as soon as possible after a node goes
+offline (triggered by the IPP Controller marking a node as offline?).  A sweep
+must be /completed/ before an offline node can be marked on-line.
+
+Once a node is determined to be offline all entries in the Lock table set by
+that node should be identified.   The locks on the Storage Object
+Instances pointed to by those entries should then be rolled back and Lock
+Record entries themselves must be removed from the lock table.
+
+Consistency sweeping
+--
+Periodically the IPP Pixel Data Server meta-data and Storage Object will need
+to be checked for sanity.  This would be similar to running fsck on a modern
+filesystem.  Consistency sweeping should include Lock sweeping and should be
+considered a superset.
+
+All Storage Objects must have at least once associated Instance.
+
+All Storage Object Instances must be associated with a Storage Object.
+
+All Storage Object Instances with a lock set must have the correct number of
+corresponding Lock Records.
+
+All Lock Records must be plausible, ie. the Instance pointed at must be in a
+corresponding state.
+
+Storage ID Allocation
+--
+Storage IDs are a signed 64-bit integer.  Negative values are considered
+reserved for future use.  Allocation should be incremental and, as we are
+unlikely to exceed 2^63 Storage Objects in the life time of the project, never
+reused.
+
+Allocated via [SQL auto-increment/stored procedure/app server?]
+
+Instance ID Allocation
+--
+Indentical to a Storage ID but exists in a unique namespace.
+
+Storage Location determination
+--
+???
Index: /tags/start/Nebulous-Server/docs/requirements.txt
===================================================================
--- /tags/start/Nebulous-Server/docs/requirements.txt	(revision 12606)
+++ /tags/start/Nebulous-Server/docs/requirements.txt	(revision 12606)
@@ -0,0 +1,23 @@
+# Copyright (C) 2004  Joshua Hoblitt
+#
+# $Id: requirements.txt,v 1.1.1.1 2004-12-22 02:16:23 jhoblitt Exp $
+
+- store all image data aquired during the first two years of PS1's
+  operations.  Approximately 10^8 files (OTA level).
+
+- injest new data from the summit at the same rate it is produced when
+  operating at a cadence of 40s between integrations.  Approximately 400Mb/s.
+
+- support phase 1 & 2 processing. x files per t_min
+
+- support phase 3 & 4 processing. x files per t_min
+
+- support accessing small blocks of a file (ie., seek)
+
+what are the science drivers for these 3?
+--
+- data corruption is guarenteed to be detectable.
+
+- relibably store xx.x% of files 
+
+- xx.x% of stored images must be retreivable in xs.
Index: /tags/start/Nebulous-Server/docs/setup.txt
===================================================================
--- /tags/start/Nebulous-Server/docs/setup.txt	(revision 12606)
+++ /tags/start/Nebulous-Server/docs/setup.txt	(revision 12606)
@@ -0,0 +1,33 @@
+
+- building and install the Perl modules (see: README)
+
+- create and initialize the database (see: docs/database_setup.txt)
+
+- setup the server
+
+As a CGI, work with either Apache 1.3.x or 2.0.x
+
+cp scripts/imagesever.pl /var/www/localhost/cgi-bin
+chmod 755 /var/www/localhost/cgi-bin/imageserver.pl
+touch /tmp/imageserver.log
+chmod 1777 /tmp/imageserver.log
+
+- test the imageserver.pl is working
+
+telnet localhost 80
+Trying 127.0.0.1...
+Connected to localhost.
+Escape character is '^]'.
+GET /cgi-bin/imageserver.pl HTTP/1.0
+
+HTTP/1.1 411 Length Required
+Date: Tue, 28 Sep 2004 21:15:58 GMT
+Server: Apache/2.0.49 (Gentoo/Linux)
+Content-Length: 0
+Connection: close
+Content-Type: text/plain; charset=ISO-8859-1
+
+Connection closed by foreign host.
+
+- if you get an HTTP 5xx code check your apache error_log
+
Index: /tags/start/Nebulous-Server/docs/tmp.txt
===================================================================
--- /tags/start/Nebulous-Server/docs/tmp.txt	(revision 12606)
+++ /tags/start/Nebulous-Server/docs/tmp.txt	(revision 12606)
@@ -0,0 +1,44 @@
+client
+--
+new
+
+new_file
+                new_file
+                open_file
+
+find_file
+    find_instance
+
+open_file
+    find_file
+
+delete_file
+                delete_file
+    nuke
+
+copy_file
+    open_file
+    new_file
+
+move_file
+    copy_file
+    delete_file
+
+replicate_file
+    open_file
+                replicate_file
+
+cull_file
+    find_instance
+    delete_instance
+
+delete_instance
+    nuke
+                delete_instance
+
+find_instance
+                find_instance
+
+# missing
+file_stat
+lock ?
Index: /tags/start/Nebulous-Server/lib/Nebulous/Server.pm
===================================================================
--- /tags/start/Nebulous-Server/lib/Nebulous/Server.pm	(revision 12606)
+++ /tags/start/Nebulous-Server/lib/Nebulous/Server.pm	(revision 12606)
@@ -0,0 +1,660 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: Server.pm,v 1.1.1.1 2004-12-22 02:16:24 jhoblitt Exp $
+
+package PS::IPP::IData::Server;
+
+use strict;
+use warnings;
+no warnings qw( uninitialized );
+
+our $VERSION = '0.01';
+
+use DBI;
+use PS::IPP::IData::Util qw( :standard );
+use PS::IPP::IData::Server::Log;
+use PS::IPP::IData::Server::SQL;
+use Log::Log4perl;
+use Params::Validate qw( validate_pos SCALAR );
+
+my %class = (
+    raw => 1,
+);
+
+my $log;
+my $sql;
+my $db;
+
+sub setup {
+    my $self = shift;
+
+    my ( $dsn, $user, $passwd ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+        },
+    );
+
+    $log = Log::Log4perl::get_logger( "PS::IPP::IData::Server" );
+    $sql = PS::IPP::IData::Server::SQL->new;
+
+    $log->debug( "entered - @_" );
+
+    eval {
+        $db = DBI->connect(
+            $dsn,
+            $user,
+            $passwd,
+            {
+                RaiseError => 1,
+                PrintError => 0,
+                AutoCommit => 0,
+            },
+        );
+
+        $db->do( $sql->set_transaction_model );
+
+        $db->commit;
+    };
+    if ( $@ ) {
+        $db->rollback if $db;
+        $log->logdie( "database error: $@" );
+    }
+
+    $log->debug( "connected to database: ", sub { $db->data_sources; } );
+
+    $log->debug( "leaving" );
+
+    return 1;
+}
+
+sub create_object {
+    my $self = shift;
+
+    $log->debug( "entered - @_" );
+
+    my ( $key, $class, $volume, $comment ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is + integer' => sub { $_[0] =~ /^\d+$/ },
+            },
+            default     => 0,
+        },
+        {
+            type        => SCALAR,
+            optional    => 1,
+        },
+        {
+            type        => SCALAR,
+            optional    => 1,
+        },
+    );
+
+    # TODO do some intelligent volume allocated 
+    # add hooks to make this decision based on avaiable space
+    $volume = _get_storage_volume( $volume );
+
+    # check that the comment isn't too long
+    # check that the class requested is valid
+    # check that the volume requested is valid
+
+    my $uri;
+    my $ins_id;
+
+    eval {
+        {
+            # create storage_object
+            my $query = $db->prepare( $sql->new_object ); 
+            $query->execute( $key, $class, $comment );
+        }
+
+        {
+            # create instance with no URI
+            my $query = $db->prepare( $sql->new_object_instance );
+            $query->execute;
+        }
+
+        {
+            # get instance ID
+            my $query = $db->prepare( $sql->last_insert_id );
+            $query->execute;
+            ( $ins_id ) = $query->fetchrow_array;
+        }
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->logdie( "database error: $@" );
+    }
+
+    $uri = "$volume/$key.$ins_id";
+
+    $log->debug( "generated uri $uri");
+
+    my $path = _get_file_path( $uri );
+
+    # TODO add some stuff here to retry if unsucessful
+    eval {
+        _create_empty_file( $path );
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->logdie( $@ );
+    }
+
+    eval {
+        {
+            my $query = $db->prepare( $sql->update_instance_uri );
+            $query->execute( $uri, $ins_id );
+        }
+
+        $db->commit;
+    };
+    $log->logdie( "database error: $@" ) if $@;
+
+    $log->debug( "leaving" );
+
+    return $uri;
+}
+
+sub replicate_object {
+    my $self = shift;
+
+    $log->debug( "entered - @_" );
+
+    my ( $key, $volume ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            optional    => 1,
+        },
+    );
+
+    # TODO
+    $volume = _get_storage_volume();
+
+    my $path;
+    my $uri;
+
+    my $so_id;
+    my $ins_id;
+    eval {
+        {
+            my $query = $db->prepare( $sql->get_object_instances );
+            my $rows = $query->execute( $key );
+
+            unless ( $rows > 0 ) {
+                $db->rollback;
+                $log->logdie( "storage object does not exist" );
+            }
+
+            $so_id = $query->fetchrow_hashref->{ 'so_id' };
+        }
+
+        {
+            my $query = $db->prepare( $sql->new_instance );
+            $query->execute( $so_id );
+        }
+
+        {
+            my $query = $db->prepare( $sql->last_insert_id );
+            $query->execute();
+
+            ( $ins_id ) = $query->fetchrow_array;
+        }
+
+        {
+            $uri = "$volume/$key.$ins_id";
+            $log->debug( "generated uri $uri");
+
+            my $query = $db->prepare( $sql->update_instance_uri );
+            $query->execute( $uri, $ins_id );
+        }
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->logdie( "database error: $@" );
+    }
+
+
+    eval {
+        $path = _get_file_path( $uri );
+        $path = _create_empty_file( $path );
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->logdie( $@ );
+    }
+
+    $db->commit;
+
+    $log->debug( "leaving" );
+
+    return $uri;
+}
+
+sub lock_object {
+    my $self = shift;
+
+    $log->debug( "entered - @_" );
+
+    my ( $key, $type ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is read or write' => sub { $_[0] =~ /^(?:read|write)$/ },
+            },
+        },
+    );
+
+    my $so_id;
+    my $read_lock;
+    my $write_lock;
+
+    eval {
+        # this will set update locks
+        my $query = $db->prepare( $sql->get_object_locks );
+        my $rows = $query->execute( $key );
+        unless ( $rows == 1 ) {
+            $log->logdie( "storage object does not exist" );
+        }
+
+        my $row = $query->fetchrow_hashref;
+
+        $so_id      = $row->{ 'so_id' };
+        $read_lock  = $row->{ 'read_lock' };
+        $write_lock = $row->{ 'write_lock' };
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->logdie( "database error: $@" );
+    }
+
+    if ( $type eq 'write' ) {
+        # can't set a write lock twice and
+        # can't set a write lock if there are read locks
+        if ( $write_lock ) {
+            eval { $db->rollback; };
+            $log->logdie( "database error: $@" ) if $@;
+
+            $log->logdie( "can not write lock twice" );
+        }
+            
+        if ( $read_lock > 0 ) {
+            eval { $db->rollback; };
+            $log->logdie( "database error: $@" ) if $@;
+
+            $log->logdie( "can not write lock after read lock" );
+        }
+
+        eval {
+            my $query = $db->prepare( $sql->set_write_lock );
+            my $rows = $query->execute( $key );
+        
+            # if we affected more then one row something very bad has happened.
+            unless ( $rows == 1 ) {
+                $log->logdie( "affected row count is $rows instead of 1" );
+            }
+
+            $db->commit;
+        };
+        if ( $@ ) {
+            $db->rollback;
+            $log->logdie( "database error: $@" );
+        }
+
+        $log->debug( "leaving" );
+
+        return 1;
+    }
+
+    if ( $type eq 'read' ) {
+        # can't set a read lock if there's a write lock
+        if ( $write_lock ) {
+            eval { $db->rollback; };
+            $log->logdie( "database error: $@" ) if $@;
+
+            $log->logdie( "can not read lock after write lock" );
+        }
+
+        eval {
+            my $query = $db->prepare( $sql->increment_read_lock );
+            my $rows = $query->execute( $key );
+        
+            # if we affected more then one row something very bad has happened.
+            unless ( $rows == 1 ) {
+                $log->logdie( "affected row count is $rows instead of 1" );
+            }
+
+            $db->commit;
+        };
+        if ( $@ ) {
+            $db->rollback;
+            $log->logdie( "database error: $@" );
+        }
+
+        $log->debug( "leaving" );
+
+        return 1;
+    }
+
+    # never reached
+    $log->logdie( "this should never happen" );
+}
+
+sub unlock_object {
+    my $self = shift;
+
+    $log->debug( "entered - @_" );
+
+    my ( $key, $type ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is read or write' => sub { $_[0] =~ /^(?:read|write)$/ },
+            },
+        },
+    );
+
+    my $so_id;
+    my $read_lock;
+    my $write_lock;
+
+    eval {
+        # this will set update locks
+        my $query = $db->prepare( $sql->get_object_locks );
+        my $rows = $query->execute( $key );
+        unless ( $rows == 1 ) {
+            $log->logdie( "storage object does not exist" );
+        }
+
+        my $row = $query->fetchrow_hashref;
+
+        $so_id      = $row->{ 'so_id' };
+        $read_lock  = $row->{ 'read_lock' };
+        $write_lock = $row->{ 'write_lock' };
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->logdie( "database error: $@" );
+    }
+
+    if ( $type eq 'write' ) {
+        # can't remove a write lock if it doesn't exist
+        if ( $read_lock ) {
+            eval { $db->rollback; };
+            $log->logdie( "database error: $@" ) if $@;
+           
+            $log->logdie( "can not have a write lock under a read lock" );
+        }
+        unless ( $write_lock ) {
+            eval { $db->rollback; };
+            $log->logdie( "database error: $@" ) if $@;
+
+            $log->logdie( "can not remove non-existant write lock" );
+        }
+
+        eval {
+            my $query = $db->prepare( $sql->delete_write_lock );
+            my $rows = $query->execute( $key );
+        
+            # if we affected more then one row something very bad has happened.
+            unless ( $rows == 1 ) {
+                $log->logdie( "affected row count is $rows instead of 1" );
+            }
+
+            $db->commit;
+        };
+        if ( $@ ) {
+            $db->rollback;
+            $log->logdie( "database error: $@" );
+        }
+
+        $log->debug( "leaving" );
+
+        return 1;
+    }
+
+    if ( $type eq 'read' ) {
+        # can't remove a read lock if there's a write lock and
+        # can't remove a read lock if there aren't any
+        if ( $write_lock ) {
+            eval { $db->rollback; };
+            $log->logdie( "database error: $@" ) if $@;
+           
+            $log->logdie( "can not have a read lock under a write lock" );
+        }
+           
+        if ( $read_lock == 0 ) {
+            eval { $db->rollback; };
+            $log->logdie( "database error: $@" ) if $@;
+           
+            $log->logdie( "can not remove non-existant read lock" );
+        }
+
+        eval {
+            my $query = $db->prepare( $sql->decrement_read_lock );
+            my $rows = $query->execute( $key );
+        
+            # if we affected more then one row something very bad has happened.
+            unless ( $rows == 1 ) {
+
+                $log->logdie( "affected row count is $rows instead of 1" );
+            }
+
+            $db->commit;
+        };
+        if ( $@ ) {
+            $db->rollback;
+            $log->logdie( "database error: $@" );
+        }
+
+        $log->debug( "leaving" );
+
+        return 1;
+    }
+
+    # never reached
+    $log->logdie( "this should never happen" );
+}
+
+
+sub find_instances {
+    my $self = shift;
+
+    $log->debug( "entered - @_" );
+
+    my ( $key, $volume ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            optional    => 1,
+        },
+    );
+
+    # TODO restrict search to a volume
+
+    my $query;
+
+    eval {
+        $query = $db->prepare( $sql->get_object_instances );
+        $query->execute( $key );
+    };
+    $log->logdie( "database error: $@" ) if $@;
+
+    my @locations;
+
+    while ( my $row = $query->fetchrow_hashref ) {
+        my $instance = $row->{ 'uri' };
+        push @locations, $instance if $instance;
+    }
+
+    $log->logdie( "no instances found" ) unless ( scalar @locations );
+
+    $log->debug( "leaving" );
+
+    return \@locations;
+}
+
+sub delete_instance {
+    my $self = shift;
+
+    $log->debug( "entered - @_" );
+
+    my ( $uri ) = validate_pos( @_,
+        {
+            type => SCALAR,
+        },
+    );
+
+    eval {
+        my $so_id;
+        my $instances;
+        # get so_id
+        {
+            my $query = $db->prepare( $sql->get_object_from_uri );
+            my $rows = $query->execute( $uri );
+
+            unless ( $rows > 0 ) {
+                $log->logdie( "no instance is associated with uri" );
+            }
+
+            $so_id = $query->fetchrow_hashref->{ 'so_id' };
+        }
+
+        {
+            my $query = $db->prepare( $sql->get_instance_count );
+            $query->execute( $so_id );
+
+            $instances = $query->fetchrow_hashref->{ 'count(ins_id)' };
+        }
+
+        # remove instance
+        {
+            my $query = $db->prepare( $sql->delete_instance );
+            my $rows = $query->execute( $uri );
+            
+            # if we affected something other then one row something very bad has happened
+            unless ( $rows == 1 ) {
+                $log->logdie( "affected row count is $rows instead of 1" );
+            }
+        }
+
+        # if we just deleted the last instance associated with a storage object
+        # remove it too
+        if ( $instances == 1 ) {
+            # we just removed the last instance
+            my $query = $db->prepare( $sql->delete_object );
+            my $rows = $query->execute( $so_id );
+
+            # if we affected something other then one row something very bad has happened
+            unless ( $rows == 1 ) {
+                $log->logdie( "affected row count is $rows instead of 1" );
+            }
+        }
+
+        $db->commit;
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->logdie( "database error: $@" );
+    }
+
+    $log->debug( "leaving" );
+
+    return 1;
+}
+
+sub stat_object {
+    my $self = shift;
+
+    $log->debug( "entered - @_" );
+
+    my ( $key ) = validate_pos( @_,
+        {
+            type => SCALAR,
+        },
+    );
+
+    my $stat;
+    eval {
+        my $query = $db->prepare( $sql->get_object );
+        my $rows = $query->execute( $key );
+
+        unless ( $rows == 1 ) {
+            $log->logdie( "no storage object found" );
+        }
+
+        $stat = $query->fetchrow_arrayref;
+
+        $db->commit;
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->logdie( "database error: $@" );
+    }
+
+    $log->debug( "leaving" );
+
+    return $stat;
+}
+
+sub _get_storage_volume {
+    $log->debug( "entered - @_" );
+
+    my $name = shift;
+
+    my $volume;
+    {
+        my $query;
+        eval {
+            # TODO cache this?
+            my $rows;
+            if ( $name ) {
+                $query = $db->prepare( qq{ SELECT uri FROM volume WHERE name = ? ORDER BY rand() LIMIT 1 } );
+                $rows = $query->execute( $name );
+            } else {
+                $query = $db->prepare( qq{ SELECT uri FROM volume ORDER BY rand() LIMIT 1 } );
+                $rows = $query->execute;
+            }
+
+            # there has to be atleast one storage volume
+            unless ( $rows > 0 ) {
+                $db->rollback;
+
+                $log->logdie( "affected row count is $rows instead of 1" );
+            } else {
+                $db->commit;
+            }
+        };
+        $log->logdie( "database error: $@" ) if $@;
+
+        $volume = $query->fetchrow_hashref->{ 'uri' };
+    }
+
+    $log->debug( "leaving" );
+
+    return $volume;
+}
+
+1;
+
+__END__
Index: /tags/start/Nebulous-Server/lib/Nebulous/Server/Apache.pm
===================================================================
--- /tags/start/Nebulous-Server/lib/Nebulous/Server/Apache.pm	(revision 12606)
+++ /tags/start/Nebulous-Server/lib/Nebulous/Server/Apache.pm	(revision 12606)
@@ -0,0 +1,21 @@
+# Copyright (C) 2004  Joshua Hoblitt
+#
+# $Id
+
+package PS::IPP::IData::Server::Apache;
+
+use strict;
+
+our $VERSION = 0.01;
+
+use SOAP::Transport::HTTP;
+
+my $server = SOAP::Transport::HTTP::Apache
+    ->dispatch_to( 'PS::IPP::IData::Server' )
+    ->options({ compress_threshold => 10 * 1024 });
+
+sub handler { $server->handler(@_); }
+
+1;
+
+__END__
Index: /tags/start/Nebulous-Server/lib/Nebulous/Server/Log.pm
===================================================================
--- /tags/start/Nebulous-Server/lib/Nebulous/Server/Log.pm	(revision 12606)
+++ /tags/start/Nebulous-Server/lib/Nebulous/Server/Log.pm	(revision 12606)
@@ -0,0 +1,27 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: Log.pm,v 1.1.1.1 2004-12-22 02:16:24 jhoblitt Exp $
+
+package PS::IPP::IData::Server::Log;
+
+use strict;
+
+our $VERSION = '0.01';
+
+use Log::Log4perl;
+                                                                                                                                          
+my $conf = q(
+    log4perl.category.PS.IPP.IData.Server = DEBUG, SERVERLOGFILE
+
+    log4perl.appender.SERVERLOGFILE           = Log::Log4perl::Appender::File
+    log4perl.appender.SERVERLOGFILE.filename  = /tmp/idata_server.log
+    log4perl.appender.SERVERLOGFILE.mode      = append
+    log4perl.appender.SERVERLOGFILE.layout    = Log::Log4perl::Layout::PatternLayout
+    log4perl.appender.SERVERLOGFILE.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} | %H | %p | %M - %m%n
+);
+                                                                                                                          
+Log::Log4perl::init( \$conf );
+
+1;
+
+__END__
Index: /tags/start/Nebulous-Server/lib/Nebulous/Server/SQL.pm
===================================================================
--- /tags/start/Nebulous-Server/lib/Nebulous/Server/SQL.pm	(revision 12606)
+++ /tags/start/Nebulous-Server/lib/Nebulous/Server/SQL.pm	(revision 12606)
@@ -0,0 +1,107 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: SQL.pm,v 1.1.1.1 2004-12-22 02:16:24 jhoblitt Exp $
+
+package PS::IPP::IData::Server::SQL;
+
+use strict;
+
+our $VERSION = '0.01';
+
+use base qw( Class::Accessor::Fast );
+
+my %sql = (
+    set_transaction_model   => qq{
+        SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
+    },
+    update_instance_uri => qq{
+        UPDATE instance SET uri = ? WHERE ins_id = ?
+    },
+    last_insert_id      => qq{
+        SELECT LAST_INSERT_ID()
+    },
+    new_object          => qq{
+        INSERT INTO storage_object
+        VALUES (NULL, ?, ?, ?, 0, NULL, NULL)
+    },
+    delete_object       => qq{
+        DELETE FROM storage_object
+        WHERE so_id = ?
+    },
+    new_object_instance  => qq{
+        INSERT INTO instance 
+        VALUES (NULL, LAST_INSERT_ID(), 'error', NULL, NULL, NULL, NULL)
+    },
+    new_instance        => qq{
+        INSERT INTO instance
+        VALUES (NULL, ?, 'error', NULL,NULL, NULL, NULL)
+    },
+    get_object          => qq{
+        SELECT *
+        FROM storage_object
+        WHERE ext_id = ?
+    },
+    get_object_locks    => qq{
+        SELECT so_id, read_lock, write_lock 
+        FROM storage_object
+        WHERE ext_id = ?
+        FOR UPDATE
+    },
+    set_write_lock      => qq{
+        UPDATE storage_object
+        SET write_lock = 'write'
+        WHERE ext_id = ?
+    },
+    delete_write_lock   => qq{
+        UPDATE storage_object
+        SET write_lock = NULL
+        WHERE ext_id = ?
+    },
+    increment_read_lock => qq{
+        UPDATE storage_object
+        SET read_lock = read_lock+1
+        WHERE ext_id = ?
+    },
+    decrement_read_lock => qq{
+        UPDATE storage_object
+        SET read_lock = read_lock-1
+        WHERE ext_id = ?
+    },
+    delete_instance     => qq{
+        DELETE FROM instance
+        WHERE uri = ?
+    },
+    get_object_from_uri   => qq{
+        SELECT so_id
+        FROM instance
+        WHERE uri = ?
+    },
+    get_instance_count   => qq{
+        SELECT count(ins_id)
+        FROM instance
+        WHERE so_id = ?
+    },
+    get_object_instances    => qq{
+        SELECT storage_object.so_id, uri, assigned_location
+        FROM storage_object
+        LEFT JOIN instance
+        USING (so_id)
+        WHERE storage_object.ext_id = ?
+    },
+);
+
+__PACKAGE__->mk_ro_accessors( keys %sql );
+
+sub new {
+    my $class = shift;
+
+    my $self = \%sql;
+
+    bless $self, $class || ref $class;
+
+    return $self;
+}
+
+1;
+
+__END__
Index: /tags/start/Nebulous-Server/nebulous.wsdl
===================================================================
--- /tags/start/Nebulous-Server/nebulous.wsdl	(revision 12606)
+++ /tags/start/Nebulous-Server/nebulous.wsdl	(revision 12606)
@@ -0,0 +1,96 @@
+<?xml version="1.0"?>
+
+<definitions name="idata" targetNamespace="http://pan-starrs.ifa.hawaii.edu/PS/IPP/IData/Server">
+
+    <types>
+        <schema targetNamespace="http://pan-starrs.ifa.hawaii.edu/PS/IPP/IData/Server"
+            xmlns="http://www.w3.org/1999/XMLSchema">
+
+            <element name="create_object">
+                <complexType>
+                    <sequence>
+                        <element name="key"     type="string"/>
+                        <element name="class"   type="int"/>
+                        <element name="volume"  type="string"/>
+                        <element name="comment" type="string"/>
+                    </sequence>
+                </complexType>
+            </element>
+
+            <element name="create_objectResponse">
+                <complexType>
+                    <all>
+                        <element name="uri" type="string"/>
+                    </all>
+                </complexType>
+            </element>
+
+            <element name="create_objectFault">
+                <complexType>
+                    <all>
+                        <element name="errorMessage" type="string"/>
+                    </all>
+                </complexType>
+            </element>
+
+        </schema>
+    </types>
+
+    <message name="create_objectRequest">
+        <part name="body" element="esxsd:create_object"/>
+    </message>
+
+    <message name="create_objectResponse">
+        <part name="body" element="esxsd:create_objectResponse"/>
+    </message>
+
+    <portType name="create_objectPortType">
+        <operation name="create_object">
+            <input message ="es:create_objectRequest"/>
+            <output message="es:create_objectResponse"/>
+            <fault message ="es:create_objectFault"/>
+        </operation>
+    </portType>
+
+    <binding name="idataSoapBinding"
+        type="es:GetidatarPortType">
+
+        <soap:binding style="document"
+            transport="http://schemas.xmlsoap.org/soap/http"/>
+
+        <operation name="Getidata">
+            <soap:operation
+                soapAction="http://www.snowboard-info.com/EndorsementSearch"/>
+            <input>
+                <soap:body use="literal"
+                    namespace="http://schemas.snowboard-info.com/EndorsementSearch.xsd"/>
+            </input>
+
+            <output>
+                <soap:body use="literal"
+                    namespace="http://schemas.snowboard-info.com/EndorsementSearch.xsd"/>
+            </output>
+
+            <fault>
+                <soap:body use="literal"
+                    namespace="http://schemas.snowboard-info.com/EndorsementSearch.xsd"/>
+            </fault>
+        </operation>
+    </binding>
+
+
+  <service name="EndorsementSearchService">
+
+    <documentation>snowboarding-info.com Endorsement Service</documentation> 
+
+    <port name="GetEndorsingBoarderPort"
+          binding="es:EndorsementSearchSoapBinding">
+
+      <soap:address
+location="http://www.snowboard-info.com/EndorsementSearch"/>
+
+    </port>
+
+  </service>
+
+</definitions>
Index: /tags/start/Nebulous-Server/scripts/bench_test.pl
===================================================================
--- /tags/start/Nebulous-Server/scripts/bench_test.pl	(revision 12606)
+++ /tags/start/Nebulous-Server/scripts/bench_test.pl	(revision 12606)
@@ -0,0 +1,28 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use lib "./lib";
+use Benchmark qw( cmpthese );
+
+use PS::IPP::IData::Client;
+
+my $idata = PS::IPP::IData::Client->new(
+    proxy   => 'http://localhost:80/idata'
+);
+
+my $key = "foobarbazbongbungbutufu";
+cmpthese( 10, {
+        'Image Server' => sub {
+            {
+                my $fh = $idata->create( $key );
+                close $fh;
+                $idata->unlock( $key, 'write' );
+            }
+
+            $idata->delete( $key );
+        },
+    },
+    'all',
+);
Index: /tags/start/Nebulous-Server/scripts/imageserver.pl
===================================================================
--- /tags/start/Nebulous-Server/scripts/imageserver.pl	(revision 12606)
+++ /tags/start/Nebulous-Server/scripts/imageserver.pl	(revision 12606)
@@ -0,0 +1,14 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2004  Joshua Hoblitt
+#
+# $Id
+ 
+use strict;
+
+use SOAP::Transport::HTTP;
+use PS::IPP::IData::Server;
+   
+SOAP::Transport::HTTP::CGI
+    -> dispatch_to( 'PS::IPP::IData::Server' )
+    -> handle;
Index: /tags/start/Nebulous-Server/scripts/ptest.pl
===================================================================
--- /tags/start/Nebulous-Server/scripts/ptest.pl	(revision 12606)
+++ /tags/start/Nebulous-Server/scripts/ptest.pl	(revision 12606)
@@ -0,0 +1,51 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use lib "./lib";
+
+use PS::IPP::IData::Client;
+
+my $idata = PS::IPP::IData::Client->new(
+    uri     => 'http://localhost:80/PS/IPP/IData/Server',
+    proxy   => 'http://localhost:80/idata'
+);
+
+my $key = shift;
+
+my $kids = shift || 1;
+
+foreach my $id ( 1..$kids ) {
+    my $pid = fork;
+
+    unless ( $pid )  {
+        my $fname = "${key}_$id";
+        my $fh = $idata->create( $fname );
+        die "can't create file $fname" unless $fh;
+
+        print $fh "fooby\n";
+
+        close $fh;
+        $idata->unlock( $fname, 'write' );
+
+        $fh = $idata->open( $fname, 'read' ) or die "can't open file";
+        close $fh;
+        $idata->unlock( $fname, 'read' );
+
+        $idata->replicate( $fname );
+        $idata->cull( $fname );
+        $idata->find( $fname );
+        $idata->copy( $fname, $fname . "_copy" );
+        $idata->move( $fname, $fname . "_move" );
+        $idata->delete( $fname . "_copy" );
+        $idata->delete( $fname . "_move" );
+
+        exit 0;
+    }
+}
+
+while ( $kids ) {
+    wait();
+    $kids --;
+}
Index: /tags/start/Nebulous-Server/scripts/stest.pl
===================================================================
--- /tags/start/Nebulous-Server/scripts/stest.pl	(revision 12606)
+++ /tags/start/Nebulous-Server/scripts/stest.pl	(revision 12606)
@@ -0,0 +1,33 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use lib "./lib";
+
+use PS::IPP::IData::Client; # trace => 'debug';
+
+my $idata = PS::IPP::IData::Client->new(
+    proxy   => 'http://localhost:80/idata'
+);
+
+my $fname = shift;
+
+#my $fh = $idata->create( $fname );
+#$idata->unlock( $fname, 'write' );
+
+$idata->create( $fname, 1 );
+$idata->unlock( $fname, 'write' );
+$idata->delete( $fname );
+
+__END__
+
+{
+    my $fh = $pd->create( $key );
+    die "can't create file $fname" unless $fh;
+    print $fh "fooby\n";
+    close $fh;
+    #$idata->unlock( $fname, 'write' );
+    my $filesize =  (stat( $key ))[7];
+    print "created file $key, ${filesize}bytes\n";
+}
Index: /tags/start/Nebulous-Server/t/01_load.t
===================================================================
--- /tags/start/Nebulous-Server/t/01_load.t	(revision 12606)
+++ /tags/start/Nebulous-Server/t/01_load.t	(revision 12606)
@@ -0,0 +1,19 @@
+# -*- perl -*-
+
+# t/001_load.t - check module loading and create testing directory
+
+use strict;
+use warnings;
+
+use lib qw( ./t ./lib );
+
+use Test::More tests => 8;
+
+BEGIN { use_ok( 'PS::IPP::IData::Client' ); }
+BEGIN { use_ok( 'PS::IPP::IData::Client::Log' ); }
+BEGIN { use_ok( 'PS::IPP::IData::Client::HTTP' ); }
+BEGIN { use_ok( 'PS::IPP::IData::Util' ); }
+BEGIN { use_ok( 'PS::IPP::IData::Server' ); }
+BEGIN { use_ok( 'PS::IPP::IData::Server::Apache' ); }
+BEGIN { use_ok( 'PS::IPP::IData::Server::SQL' ); }
+BEGIN { use_ok( 'PS::IPP::IData::Server::Log' ); }
Index: /tags/start/Nebulous-Server/t/02_server_setup.t
===================================================================
--- /tags/start/Nebulous-Server/t/02_server_setup.t	(revision 12606)
+++ /tags/start/Nebulous-Server/t/02_server_setup.t	(revision 12606)
@@ -0,0 +1,35 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 2;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Server;
+use Test::IData;
+
+Test::IData->setup;
+
+ok(
+    PS::IPP::IData::Server->setup(
+        "DBI:mysql:database=test:host=localhost",
+        "test",
+        "",
+    ),
+    "connect",
+);
+
+Test::IData->setup;
+
+eval {
+    PS::IPP::IData::Server->setup(
+        "DBI:mysql:database=foobar:host=localhost",
+        "baz",
+        "boo",
+    );
+};
+like( $@, qr/DBI connect.*? failed/, "bad dsn/user/pass" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous-Server/t/03_server_create_object.t
===================================================================
--- /tags/start/Nebulous-Server/t/03_server_create_object.t	(revision 12606)
+++ /tags/start/Nebulous-Server/t/03_server_create_object.t	(revision 12606)
@@ -0,0 +1,84 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 11;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Server;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $idata = "PS::IPP::IData::Server";
+
+$idata->setup(
+    "DBI:mysql:database=test:host=localhost",
+    "test",
+    "",
+);
+
+Test::IData->setup;
+
+{
+    # key
+    my $uri = $idata->create_object( "foo" );
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, class
+    my $uri = $idata->create_object( "foo", 0 );
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, class, volume
+    my $uri = $idata->create_object( "foo", 0, "node01" );
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, class, volume, comment
+    my $uri = $idata->create_object( "foo", 0, "node01", "this is foo" );
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object( "foo" );
+    $idata->create_object( "foo" );
+};
+like( $@, qr/Duplicate entry/, "object already exists" );
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object();
+};
+like( $@, qr/2 - 4 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object( 1, 2, 3, 4, 5 );
+};
+like( $@, qr/2 - 4 were expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous-Server/t/04_server_replicate_object.t
===================================================================
--- /tags/start/Nebulous-Server/t/04_server_replicate_object.t	(revision 12606)
+++ /tags/start/Nebulous-Server/t/04_server_replicate_object.t	(revision 12606)
@@ -0,0 +1,79 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 11;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Server;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $idata = "PS::IPP::IData::Server";
+
+$idata->setup(
+    "DBI:mysql:database=test:host=localhost",
+    "test",
+    "",
+);
+
+Test::IData->setup;
+
+{
+    # key
+    $idata->create_object( "foo" );
+    my $uri = $idata->replicate_object( "foo" );
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, $volume
+    $idata->create_object( "foo" );
+    my $uri = $idata->replicate_object( "foo", "node01" );
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, $volume
+    $idata->create_object( "foo" );
+    my $uri1 = $idata->replicate_object( "foo", "node01" );
+    my $uri2 = $idata->replicate_object( "foo", "node02" );
+
+    ok( -e _get_file_path( $uri1 ), "file exists" );
+    ok( -e _get_file_path( $uri2 ), "file exists" );
+    like( $uri1, qr/^file:\//, "valid URI" );
+    like( $uri2, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+eval {
+    $idata->replicate_object( "foo" );
+};
+like( $@, qr/storage object does not exist/, "storage object does not exist" );
+
+Test::IData->setup;
+
+eval {
+    $idata->replicate_object();
+};
+like( $@, qr/1 - 2 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    $idata->replicate_object( 1, 2, 3 );
+};
+like( $@, qr/1 - 2 were expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous-Server/t/05_server_lock_object.t
===================================================================
--- /tags/start/Nebulous-Server/t/05_server_lock_object.t	(revision 12606)
+++ /tags/start/Nebulous-Server/t/05_server_lock_object.t	(revision 12606)
@@ -0,0 +1,119 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 13;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Server;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $idata = "PS::IPP::IData::Server";
+
+$idata->setup(
+    "DBI:mysql:database=test:host=localhost",
+    "test",
+    "",
+);
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    ok( $idata->lock_object( "foo", "read" ), "read lock" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    ok( $idata->lock_object( "foo", "read" ), "read lock" );
+    ok( $idata->lock_object( "foo", "read" ), "read lock" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    ok( $idata->lock_object( "foo", "write" ), "write lock" );
+}
+
+Test::IData->setup;
+
+eval {
+    $idata->lock_object( "foo", "read" );
+};
+like( $@, qr/storage object does not exist/, "storage object does not exist" );
+
+Test::IData->setup;
+
+eval {
+    $idata->lock_object( "foo", "write" );
+};
+like( $@, qr/storage object does not exist/, "storage object does not exist" );
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object( "foo" );
+
+    $idata->lock_object( "foo", "write" );
+    $idata->lock_object( "foo", "write" );
+};
+like( $@, qr/can not write lock twice/, "can not write lock twice" );
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object( "foo" );
+
+    $idata->lock_object( "foo", "read" );
+    $idata->lock_object( "foo", "write" );
+};
+like( $@, qr/can not write lock after read lock/, "can not write lock after read lock" );
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object( "foo" );
+
+    $idata->lock_object( "foo", "write" );
+    $idata->lock_object( "foo", "read" );
+};
+like( $@, qr/can not read lock after write lock/, "can not read lock after write lock" );
+
+Test::IData->setup;
+
+eval {
+    $idata->lock_object();
+};
+like( $@, qr/2 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    $idata->lock_object( "foo" );
+};
+like( $@, qr/2 were expected/, "not enough params" );
+
+Test::IData->setup;
+
+eval {
+    $idata->lock_object( "foo", "both" );
+};
+like( $@, qr/is read or write/, "not read or write" );
+
+Test::IData->setup;
+
+eval {
+    $idata->lock_object( "foo", 'read', 3 );
+};
+like( $@, qr/2 were expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous-Server/t/06_server_unlock_object.t
===================================================================
--- /tags/start/Nebulous-Server/t/06_server_unlock_object.t	(revision 12606)
+++ /tags/start/Nebulous-Server/t/06_server_unlock_object.t	(revision 12606)
@@ -0,0 +1,134 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 14;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Server;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $idata = "PS::IPP::IData::Server";
+
+$idata->setup(
+    "DBI:mysql:database=test:host=localhost",
+    "test",
+    "",
+);
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    $idata->lock_object( "foo", "read" );
+
+    ok( $idata->unlock_object( "foo", "read" ), "read unlock" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    $idata->lock_object( "foo", "read" );
+    $idata->lock_object( "foo", "read" );
+
+    ok( $idata->unlock_object( "foo", "read" ), "read unlock" );
+    ok( $idata->unlock_object( "foo", "read" ), "read unlock" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    $idata->lock_object( "foo", "write" );
+
+    ok( $idata->unlock_object( "foo", "write" ), "write unlock" );
+}
+
+Test::IData->setup;
+
+eval {
+    $idata->unlock_object( "foo", "read" );
+};
+like( $@, qr/storage object does not exist/, "storage object does not exist" );
+
+Test::IData->setup;
+
+eval {
+    $idata->unlock_object( "foo", "write" );
+};
+like( $@, qr/storage object does not exist/, "storage object does not exist" );
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object( "foo" );
+
+    $idata->unlock_object( "foo", "read" );
+};
+like( $@, qr/can not remove non-existant read lock/, "no lock set" );
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object( "foo" );
+
+    $idata->unlock_object( "foo", "write" );
+};
+like( $@, qr/can not remove non-existant write lock/, "no lock set" );
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object( "foo" );
+    $idata->lock_object( "foo", "write" );
+
+    $idata->unlock_object( "foo", "read" );
+};
+like( $@, qr/can not have a read lock under a write lock/, "read unlock under write lock" );
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object( "foo" );
+    $idata->lock_object( "foo", "read" );
+
+    $idata->unlock_object( "foo", "write" );
+};
+like( $@, qr/can not have a write lock under a read lock/, "write unlock under read lock" );
+
+Test::IData->setup;
+
+eval {
+    $idata->unlock_object();
+};
+like( $@, qr/2 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    $idata->unlock_object( "foo" );
+};
+like( $@, qr/2 were expected/, "not enough params" );
+
+Test::IData->setup;
+
+eval {
+    $idata->unlock_object( "foo", "both" );
+};
+like( $@, qr/is read or write/, "not read or write" );
+
+Test::IData->setup;
+
+eval {
+    $idata->unlock_object( "foo", 'read', 3 );
+};
+like( $@, qr/2 were expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous-Server/t/07_server_find_instances.t
===================================================================
--- /tags/start/Nebulous-Server/t/07_server_find_instances.t	(revision 12606)
+++ /tags/start/Nebulous-Server/t/07_server_find_instances.t	(revision 12606)
@@ -0,0 +1,90 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 7;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Server;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $idata = "PS::IPP::IData::Server";
+
+$idata->setup(
+    "DBI:mysql:database=test:host=localhost",
+    "test",
+    "",
+);
+
+Test::IData->setup;
+
+{
+    # key
+    my $uri = $idata->create_object( "foo" );
+
+    my $locations = $idata->find_instances( "foo" );
+
+    is( $uri, $locations->[0], "URIs match" );
+}
+
+Test::IData->setup;
+
+{
+    # key
+    my $uri1 = $idata->create_object( "foo" );
+    my $uri2 = $idata->replicate_object( "foo" );
+
+    my $locations = $idata->find_instances( "foo" );
+
+    ok( eq_set( [$uri1, $uri2], $locations ), "URIs match" );
+}
+
+Test::IData->setup;
+
+{
+    # key, volume
+    my $uri = $idata->create_object( "foo" );
+
+    my $locations = $idata->find_instances( "foo", "node01" );
+
+    is( $uri, $locations->[0], "URIs match" );
+}
+
+Test::IData->setup;
+
+{
+    # key
+    my $uri1 = $idata->create_object( "foo" );
+    my $uri2 = $idata->replicate_object( "foo" );
+
+    my $locations = $idata->find_instances( "foo", "node01" );
+
+    ok( eq_set( [$uri1, $uri2], $locations ), "URIs match" );
+}
+
+
+Test::IData->setup;
+
+eval {
+    $idata->find_instances( "foo" );
+};
+like( $@, qr/no instances found/, "storage object does not exist" );
+
+Test::IData->setup;
+
+eval {
+    $idata->find_instances();
+};
+like( $@, qr/1 - 2 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    $idata->find_instances( "foo", 'read', 3 );
+};
+like( $@, qr/1 - 2 were expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous-Server/t/08_server_delete_instance.t
===================================================================
--- /tags/start/Nebulous-Server/t/08_server_delete_instance.t	(revision 12606)
+++ /tags/start/Nebulous-Server/t/08_server_delete_instance.t	(revision 12606)
@@ -0,0 +1,71 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 8;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Server;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $idata = "PS::IPP::IData::Server";
+
+$idata->setup(
+    "DBI:mysql:database=test:host=localhost",
+    "test",
+    "",
+);
+
+Test::IData->setup;
+
+{
+    my $uri = $idata->create_object( "foo" );
+
+    ok( $idata->delete_instance( $uri ), "delete instance" );
+}
+
+Test::IData->setup;
+
+{
+    my $uri1 = $idata->create_object( "foo" );
+    my $uri2 = $idata->replicate_object( "foo" );
+
+    ok( $idata->delete_instance( $uri1 ), "delete instance" );
+
+    my $locations = $idata->find_instances( "foo" );
+
+    is( $locations->[0], $uri2, "instance remains" );
+
+    ok( $idata->delete_instance( $uri2 ), "delete instance" );
+
+    eval {
+        $idata->find_instances( "foo" );
+    };
+    like( $@, qr/no instances found/, "storage object was deleted" );
+}
+
+Test::IData->setup;
+
+eval {
+    $idata->delete_instance( "file:/foo" );
+};
+like( $@, qr/no instance is associated with uri/, "uri does not exist" );
+
+Test::IData->setup;
+
+eval {
+    $idata->delete_instance();
+};
+like( $@, qr/1 was expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    $idata->delete_instance( "foo", 2 );
+};
+like( $@, qr/1 was expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous-Server/t/09_server_stat_object.t
===================================================================
--- /tags/start/Nebulous-Server/t/09_server_stat_object.t	(revision 12606)
+++ /tags/start/Nebulous-Server/t/09_server_stat_object.t	(revision 12606)
@@ -0,0 +1,70 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 12;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Server;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $idata = "PS::IPP::IData::Server";
+
+$idata->setup(
+    "DBI:mysql:database=test:host=localhost",
+    "test",
+    "",
+);
+
+Test::IData->setup;
+
+{
+    my $uri = $idata->create_object( "foo" );
+
+    my $info = $idata->stat_object( "foo" );
+
+    is( scalar @$info, 7, "number of columns" );
+}
+
+Test::IData->setup;
+
+{
+    my $uri = $idata->create_object( "foo", 9, "node01", "foobar" );
+
+    my $info = $idata->stat_object( "foo" );
+
+    is( scalar @$info, 7,                       "number of columns" );
+    is( @$info[0], 1,                           "so_id" );
+    is( @$info[1], "foo",                       "ext_id" );
+    is( @$info[2], 9,                           "class_id" );
+    is( @$info[3], "foobar",                    "comment" );
+    is( @$info[4], 0,                           "read lock" );
+    is( @$info[5], undef,                       "write lock" );
+    like( @$info[6], qr/....-..-.. ..:..:../,   "epoch" );
+}
+
+Test::IData->setup;
+
+eval {
+    $idata->stat_object( "foo" );
+};
+like( $@, qr/no storage object found/, "object does not exist" );
+
+Test::IData->setup;
+
+eval {
+    $idata->stat_object();
+};
+like( $@, qr/1 was expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    $idata->stat_object( "foo", 2 );
+};
+like( $@, qr/1 was expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous-Server/t/10_client_new.t
===================================================================
--- /tags/start/Nebulous-Server/t/10_client_new.t	(revision 12606)
+++ /tags/start/Nebulous-Server/t/10_client_new.t	(revision 12606)
@@ -0,0 +1,56 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 4;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Client;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    isa_ok( $idata, "PS::IPP::IData::Client" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+        uri   => "http://example.com/PS/IPP/IData/Client",
+    );
+
+    isa_ok( $idata, "PS::IPP::IData::Client" );
+}
+
+Test::IData->setup;
+
+eval {
+    PS::IPP::IData::Client->new;
+};
+like( $@, qr/Mandatory parameter/, "no proxy" );
+
+Test::IData->setup;
+
+eval {
+    PS::IPP::IData::Client->new(
+        proxy => "foo",
+        dog => "do"
+    );
+};
+like( $@, qr/not listed in the validation options/, "bad param" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous-Server/t/11_client_create.t
===================================================================
--- /tags/start/Nebulous-Server/t/11_client_create.t	(revision 12606)
+++ /tags/start/Nebulous-Server/t/11_client_create.t	(revision 12606)
@@ -0,0 +1,103 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 7;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Client;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::IData->setup;
+
+{
+    # key
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    my $fh = $idata->create( "foo" );
+
+    is( ref $fh, 'GLOB', "good filehandle" );
+}
+
+Test::IData->setup;
+
+{
+    # key, class
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    my $fh = $idata->create( "foo", 0 );
+
+    is( ref $fh, 'GLOB', "good filehandle" );
+}
+
+Test::IData->setup;
+
+{
+    # key, class, volume
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    my $fh = $idata->create( "foo", 0, "node01" );
+
+    is( ref $fh, 'GLOB', "good filehandle" );
+}
+
+Test::IData->setup;
+
+{
+    # key, class, volume, comment
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    my $fh = $idata->create( "foo", 0, "node01", "this is foo" );
+
+    is( ref $fh, 'GLOB', "good filehandle" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->create( "foo" );
+    is( $idata->create( "foo" ), undef, "object already exists" );
+}
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->create();
+};
+like( $@, qr/2 - 4 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->create( 1, 2, 3, 4, 5 );
+};
+like( $@, qr/2 - 4 were expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous-Server/t/12_client_replicate.t
===================================================================
--- /tags/start/Nebulous-Server/t/12_client_replicate.t	(revision 12606)
+++ /tags/start/Nebulous-Server/t/12_client_replicate.t	(revision 12606)
@@ -0,0 +1,97 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 11;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Client;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::IData->setup;
+
+{
+    # key
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    my $uri = $idata->replicate( "foo" );
+
+    ok( $uri, "good replication" );
+    ok( -e _get_file_path( $uri ), "file exists" );
+}
+
+Test::IData->setup;
+
+{
+    # key, $volume
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    my $uri = $idata->replicate( "foo", "node01" );
+
+    ok( $uri, "good replication" );
+    ok( -e _get_file_path( $uri ), "file exists" );
+}
+
+Test::IData->setup;
+
+{
+    # key, $volume
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    my $uri1 = $idata->replicate( "foo", "node01" );
+    my $uri2 = $idata->replicate( "foo", "node02" );
+
+    ok( $uri1, "good replication" );
+    ok( $uri2, "good replication" );
+    ok( -e _get_file_path( $uri1 ), "file exists" );
+    ok( -e _get_file_path( $uri2 ), "file exists" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    my $uri = $idata->replicate( "foo" );
+
+    is( $uri, undef, "storage object does not exist" );
+}
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->replicate();
+};
+like( $@, qr/1 - 2 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->replicate( 1, 2, 3 );
+};
+like( $@, qr/1 - 2 were expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous-Server/t/13_client_cull.t
===================================================================
--- /tags/start/Nebulous-Server/t/13_client_cull.t	(revision 12606)
+++ /tags/start/Nebulous-Server/t/13_client_cull.t	(revision 12606)
@@ -0,0 +1,127 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 15;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Client;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::IData->setup;
+
+{
+    # key
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+    $idata->replicate( "foo" );
+
+    my $uri = $idata->cull( "foo" );
+
+    ok( $uri, "good cull" );
+    ok( ! -e _get_file_path( $uri ), "file doesn't exist" );
+}
+
+Test::IData->setup;
+
+SKIP: {
+    skip "unsure if this should be part of the API", 2;
+
+    # key, $volume
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+    $idata->replicate( "foo", "node01" );
+
+    my $uri = $idata->cull( "foo", "node01" );
+
+    ok( $uri, "good cull" );
+    ok( ! -e _get_file_path( $uri ), "file exists" );
+}
+
+Test::IData->setup;
+
+{
+    # key
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    $idata->replicate( "foo", "node01" );
+    $idata->replicate( "foo", "node02" );
+
+    my $uri1 = $idata->cull( "foo" );
+    my $uri2 = $idata->cull( "foo" );
+
+    ok( $uri1, "good cull" );
+    ok( $uri2, "good cull" );
+    ok( ! -e _get_file_path( $uri1 ), "file exists" );
+    ok( ! -e _get_file_path( $uri2 ), "file exists" );
+}
+
+Test::IData->setup;
+
+SKIP: {
+    skip "unsure if this should be part of the API", 4;
+
+    # key, $volume
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    $idata->replicate( "foo", "node01" );
+    $idata->replicate( "foo", "node02" );
+
+    my $uri1 = $idata->cull( "foo", "node01" );
+    my $uri2 = $idata->cull( "foo", "node02" );
+
+    ok( $uri1, "good cull" );
+    ok( $uri2, "good cull" );
+    ok( ! -e _get_file_path( $uri1 ), "file exists" );
+    ok( ! -e _get_file_path( $uri2 ), "file exists" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    my $uri = $idata->cull( "foo" );
+
+    is( $uri, undef, "storage object does not exist" );
+}
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->cull();
+};
+like( $@, qr/1 was expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->cull( 1, 2 );
+};
+like( $@, qr/1 was expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous-Server/t/14_client_lock.t
===================================================================
--- /tags/start/Nebulous-Server/t/14_client_lock.t	(revision 12606)
+++ /tags/start/Nebulous-Server/t/14_client_lock.t	(revision 12606)
@@ -0,0 +1,269 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 19;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Client;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::IData->setup;
+
+{
+    # key, type
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    ok( $idata->lock( "foo", "read" ), "read lock" );
+}
+
+Test::IData->setup;
+
+{
+    # key, type, timeout
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    ok( $idata->lock( "foo", "read", 10 ), "read lock" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    ok( $idata->lock( "foo", "read" ), "read lock" );
+    ok( $idata->lock( "foo", "read" ), "read lock" );
+}
+
+Test::IData->setup;
+
+{
+    # key, type
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    ok( $idata->lock( "foo", "write" ), "write lock" );
+}
+
+Test::IData->setup;
+
+{
+    # key, type, timeout
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    ok( $idata->lock( "foo", "write", 10 ), "write lock" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    is( $idata->lock( "foo", "read" ), undef, "storage object does not exist" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    is( $idata->lock( "foo", "write" ), undef, "storage object does not exist" );
+}
+
+Test::IData->setup;
+
+diag "testing a spinlock, this will be a litle slow...";
+
+eval {
+    local $SIG{ALRM} = sub { alarm 0; die "timeout"; };
+    alarm 8;
+
+    # key, type, timeout
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    $idata->lock( "foo", "read" );
+    $idata->lock( "foo", "write" );
+
+    alarm 0;
+};
+like( $@, qr/timeout/, "default spinlock" );
+
+Test::IData->setup;
+
+diag "testing a spinlock, this will be a litle slow...";
+
+eval {
+    local $SIG{ALRM} = sub { alarm 0; die "timeout"; };
+    alarm 12;
+
+    # key, type, timeout
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    $idata->lock( "foo", "read" );
+    unless ( $idata->lock( "foo", "write" ) ) {
+        alarm 0;
+        die "gaveup";
+    }
+
+    alarm 0;
+};
+like( $@, qr/gaveup/, "default spinlock" );
+
+Test::IData->setup;
+
+diag "testing a spinlock, this will be a litle slow...";
+
+eval {
+    local $SIG{ALRM} = sub { alarm 0; die "timeout"; };
+    alarm 3;
+
+    # key, type, timeout
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    $idata->lock( "foo", "read" );
+    $idata->lock( "foo", "write", 5 );
+
+    alarm 0;
+};
+like( $@, qr/timeout/, "specified spinlock" );
+
+Test::IData->setup;
+
+diag "testing a spinlock, this will be a litle slow...";
+
+eval {
+    local $SIG{ALRM} = sub { alarm 0; die "timeout"; };
+    alarm 7;
+
+    # key, type, timeout
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    $idata->lock( "foo", "read" );
+    unless ( $idata->lock( "foo", "write", 5 ) ) {
+        alarm 0;
+        die "gaveup";
+    }
+
+    alarm 0;
+};
+
+like( $@, qr/gaveup/, "specified spinlock" );
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    $idata->lock( "foo", "write" );
+    is( $idata->lock( "foo", "write", 1 ), undef, "can not write lock twice" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    $idata->lock( "foo", "read" );
+    is( $idata->lock( "foo", "write", 1 ), undef, "can not write lock after read lock" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    $idata->lock( "foo", "write" );
+    is( $idata->lock( "foo", "read", 1 ), undef, "can not read lock after write lock" );
+}
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->lock();
+};
+like( $@, qr/2 - 3 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->lock( "foo" );
+};
+like( $@, qr/2 - 3 were expected/, "not enough params" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->lock( "foo", "both" );
+};
+like( $@, qr/is read or write/, "not read or write" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->lock( "foo", 'read', 3, "bar" );
+};
+like( $@, qr/2 - 3 were expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous-Server/t/15_client_unlock.t
===================================================================
--- /tags/start/Nebulous-Server/t/15_client_unlock.t	(revision 12606)
+++ /tags/start/Nebulous-Server/t/15_client_unlock.t	(revision 12606)
@@ -0,0 +1,166 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 14;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Client;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+    $idata->lock( "foo", "read" );
+
+    ok( $idata->unlock( "foo", "read" ), "read unlock" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+    $idata->lock( "foo", "read" );
+    $idata->lock( "foo", "read" );
+
+    ok( $idata->unlock( "foo", "read" ), "read unlock" );
+    ok( $idata->unlock( "foo", "read" ), "read unlock" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+    $idata->lock( "foo", "write" );
+
+    ok( $idata->unlock( "foo", "write" ), "write unlock" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    is( $idata->unlock( "foo", "read" ), undef, "storage object does not exist" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    is( $idata->unlock( "foo", "write" ), undef, "storage object does not exist" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    is( $idata->unlock( "foo", "read" ), undef, "no lock set" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    is( $idata->unlock( "foo", "write" ), undef, "no lock set" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+    $idata->lock( "foo", "write" );
+
+    is( $idata->unlock( "foo", "read" ), undef, "read unlock under write lock" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+    $idata->lock( "foo", "read" );
+
+    is( $idata->unlock( "foo", "write" ), undef, "write unlock under read lock" );
+}
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->unlock();
+};
+like( $@, qr/2 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->unlock( "foo" );
+};
+like( $@, qr/2 were expected/, "not enough params" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->unlock( "foo", "both" );
+};
+like( $@, qr/is read or write/, "not read or write" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->unlock( "foo", 'read', 3 );
+};
+like( $@, qr/2 were expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous-Server/t/16_client_find_instances.t
===================================================================
--- /tags/start/Nebulous-Server/t/16_client_find_instances.t	(revision 12606)
+++ /tags/start/Nebulous-Server/t/16_client_find_instances.t	(revision 12606)
@@ -0,0 +1,114 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 7;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Client;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::IData->setup;
+
+SKIP: {
+    skip "need to write a module to validate URIs", 7;
+
+{
+    # key
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    my $uri = $idata->create( "foo" );
+
+    my $locations = $idata->find_instances( "foo" );
+
+    is( $uri, @$locations[0], "URIs match" );
+}
+
+Test::IData->setup;
+
+{
+    # key
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    my $uri1 = $idata->create( "foo" );
+    my $uri2 = $idata->replicate( "foo" );
+
+    my $locations = $idata->find_instances( "foo" );
+
+    ok( eq_set( [$uri1, $uri2], $locations ), "URIs match" );
+}
+
+Test::IData->setup;
+
+{
+    # key, volume
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    my $uri = $idata->create( "foo" );
+
+    my $locations = $idata->find_instances( "foo", "node01" );
+
+    is( $uri, $locations->[0], "URIs match" );
+}
+
+Test::IData->setup;
+
+{
+    # key
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    my $uri1 = $idata->create( "foo" );
+    my $uri2 = $idata->replicate( "foo" );
+
+    my $locations = $idata->find_instances( "foo", "node01" );
+
+    ok( eq_set( [$uri1, $uri2], $locations ), "URIs match" );
+}
+
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    is( $idata->find_instances( "foo" ), undef, "storage object does not exist" );
+}
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->find_instances();
+};
+like( $@, qr/1 - 2 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->find_instances( "foo", 'read', 3 );
+};
+like( $@, qr/1 - 2 were expected/, "too many params" );
+
+Test::IData->cleanup;
+
+}
Index: /tags/start/Nebulous-Server/t/apache_03_server_create_object.x
===================================================================
--- /tags/start/Nebulous-Server/t/apache_03_server_create_object.x	(revision 12606)
+++ /tags/start/Nebulous-Server/t/apache_03_server_create_object.x	(revision 12606)
@@ -0,0 +1,95 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw(-withtestmore);
+
+plan tests => 11;
+
+use lib qw( ./t ./lib );
+
+use Apache::TestUtil;
+use PS::IPP::IData::Util qw( :standard );
+use SOAP::Lite;
+use Test::IData;
+
+my $hostport = Apache::Test::config()->{ 'hostport' };
+my $idata = SOAP::Lite->new(
+    proxy   => "http://$hostport/idata",
+    uri     => "http://pan-starrs.ifa.hawaii.edu/PS/IPP/IData/Server",
+);
+
+Test::IData->setup;
+
+{
+    # key
+    my $uri = $idata->create_object( "foo" )->result;
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, class
+    my $uri = $idata->create_object( "foo", 0 )->result;
+    $idata->delete_instance( $uri );
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, class, volume
+    my $uri = $idata->create_object( "foo", 0, "node01" )->result;
+    $idata->delete_instance( $uri );
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, class, volume, comment
+    my $uri = $idata->create_object( "foo", 0, "node01", "this is foo" )->result;
+    $idata->delete_instance( $uri );
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+    my $response = $idata->create_object( "foo" );
+
+    like( $response->faultstring, qr/Duplicate entry/, "object already exists" );
+}
+
+Test::IData->setup;
+
+{
+    my $response = $idata->create_object();
+
+    like( $response->faultstring, qr/2 - 4 were expected/, "no params" );
+}
+
+Test::IData->setup;
+
+{
+    my $response = $idata->create_object( 1, 2, 3, 4, 5 );
+
+    like( $response->faultstring, qr/2 - 4 were expected/, "too many params" );
+}
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous-Server/t/apache_04_server_replicate_object.x
===================================================================
--- /tags/start/Nebulous-Server/t/apache_04_server_replicate_object.x	(revision 12606)
+++ /tags/start/Nebulous-Server/t/apache_04_server_replicate_object.x	(revision 12606)
@@ -0,0 +1,86 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw(-withtestmore);
+
+plan tests => 11;
+
+use lib qw( ./t ./lib );
+
+use Apache::TestUtil;
+use PS::IPP::IData::Util qw( :standard );
+use SOAP::Lite;
+use Test::IData;
+
+my $hostport = Apache::Test::config()->{ 'hostport' };
+my $idata = SOAP::Lite->new(
+    proxy   => "http://$hostport/idata",
+    uri     => "http://pan-starrs.ifa.hawaii.edu/PS/IPP/IData/Server",
+);
+
+Test::IData->setup;
+
+{
+    # key
+    $idata->create_object( "foo" );
+    my $uri = $idata->replicate_object( "foo" )->result;
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, $volume
+    $idata->create_object( "foo" );
+    my $uri = $idata->replicate_object( "foo", "node01" )->result;
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, $volume
+    $idata->create_object( "foo" );
+    my $uri1 = $idata->replicate_object( "foo", "node01" )->result;
+    my $uri2 = $idata->replicate_object( "foo", "node02" )->result;
+
+    ok( -e _get_file_path( $uri1 ), "file exists" );
+    ok( -e _get_file_path( $uri2 ), "file exists" );
+
+    like( $uri1, qr/^file:\//, "valid URI" );
+    like( $uri2, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    my $response = $idata->replicate_object();
+
+    like( $response->faultstring, qr/1 - 2 were expected/, "no params" );
+}
+
+Test::IData->setup;
+
+{
+    my $response = $idata->replicate_object( 1, 2, 3 );
+
+    like( $response->faultstring, qr/1 - 2 were expected/, "too many params" );
+}
+
+Test::IData->setup;
+
+{
+    my $response = $idata->replicate_object( "foo" );
+
+    like( $response->faultstring, qr/storage object does not exist/, "storage object does not exist" );
+}
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous-Server/t/apache_05_server_lock_object.x
===================================================================
--- /tags/start/Nebulous-Server/t/apache_05_server_lock_object.x	(revision 12606)
+++ /tags/start/Nebulous-Server/t/apache_05_server_lock_object.x	(revision 12606)
@@ -0,0 +1,129 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw(-withtestmore);
+
+plan tests => 13;
+
+use lib qw( ./t ./lib );
+
+use Apache::TestUtil;
+use PS::IPP::IData::Util qw( :standard );
+use SOAP::Lite;
+use Test::IData;
+
+my $hostport = Apache::Test::config()->{ 'hostport' };
+my $idata = SOAP::Lite->new(
+    proxy   => "http://$hostport/idata",
+    uri     => "http://pan-starrs.ifa.hawaii.edu/PS/IPP/IData/Server",
+);
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    ok( $idata->lock_object( "foo", "read" )->result, "read lock" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    ok( $idata->lock_object( "foo", "read" )->result, "read lock" );
+    ok( $idata->lock_object( "foo", "read" )->result, "read lock" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    ok( $idata->lock_object( "foo", "write" )->result, "write lock" );
+}
+
+Test::IData->setup;
+
+{
+    my $result = $idata->lock_object( "foo", "read" );
+
+    like( $result->faultstring, qr/storage object does not exist/, "storage object does not exist" );
+}
+
+Test::IData->setup;
+
+{
+    my $result = $idata->lock_object( "foo", "write" );
+
+    like( $result->faultstring, qr/storage object does not exist/, "storage object does not exist" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    $idata->lock_object( "foo", "write" );
+    my $result = $idata->lock_object( "foo", "write" );
+
+    like( $result->faultstring, qr/can not write lock twice/, "can not write lock twice" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    $idata->lock_object( "foo", "read" );
+    my $result = $idata->lock_object( "foo", "write" );
+
+    like( $result->faultstring, qr/can not write lock after read lock/, "can not write lock after read lock" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    $idata->lock_object( "foo", "write" );
+    my $result = $idata->lock_object( "foo", "read" );
+
+    like( $result->faultstring, qr/can not read lock after write lock/, "can not read lock after write lock" );
+}
+
+Test::IData->setup;
+
+{
+    my $result = $idata->lock_object();
+
+    like( $result->faultstring, qr/2 were expected/, "no params" );
+}
+
+Test::IData->setup;
+
+{
+    my $result = $idata->lock_object( "foo" );
+
+    like( $result->faultstring, qr/2 were expected/, "not enough params" );
+}
+
+Test::IData->setup;
+
+{
+    my $result = $idata->lock_object( "foo", "both" );
+
+    like( $result->faultstring, qr/is read or write/, "not read or write" );
+}
+
+Test::IData->setup;
+
+{
+    my $result = $idata->lock_object( "foo", 'read', 3 );
+
+    like( $result->faultstring, qr/2 were expected/, "too many params" );
+}
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous/Build.PL
===================================================================
--- /tags/start/Nebulous/Build.PL	(revision 12606)
+++ /tags/start/Nebulous/Build.PL	(revision 12606)
@@ -0,0 +1,30 @@
+use Module::Build;
+# See perldoc Module::Build for details of how this works
+
+my $build_pkg   = eval { require Apache::TestMB }
+                ? 'Apache::TestMB'
+                : 'Module::Build';
+
+$build_pkg->new(
+    module_name         => 'PS::IPP::IData',
+    dist_version_from   => 'lib/PS/IPP/IData/Server.pm',
+    author              => 'Joshua Hoblitt <jhoblitt@cpan.org>',
+    license             => 'gpl',
+    requires            => {
+        'URI'                   => 1.30,
+        'SOAP::Lite'            => 0.60,
+        'Log::Log4perl'         => 0.48,
+        'DBI'                   => 1.42,
+        'DBD::mysql'            => 2.9004,
+        'Class::Accessor::Fast' => 0,
+        'Params::Validate'      => 0,
+        'Apache::Test'          => 1.12,
+        'Test::More'            => 0.49,
+    },
+    recommends          => {
+        'Apache::DBI'           => 0.94,
+    },
+    build_requires      => {
+        'File::Temp'            => 0,
+    },
+)->create_build_script;
Index: /tags/start/Nebulous/Changes
===================================================================
--- /tags/start/Nebulous/Changes	(revision 12606)
+++ /tags/start/Nebulous/Changes	(revision 12606)
@@ -0,0 +1,5 @@
+Revision history for Perl module Poi::PixelData
+
+0.01 Fri Sep  3 10:23:31 2004
+    - first working version
+	- original version; created by ExtUtils::ModuleMaker 0.32
Index: /tags/start/Nebulous/LICENSE
===================================================================
--- /tags/start/Nebulous/LICENSE	(revision 12606)
+++ /tags/start/Nebulous/LICENSE	(revision 12606)
@@ -0,0 +1,260 @@
+The General Public License (GPL)
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave,
+Cambridge, MA 02139, USA. Everyone is permitted to copy and distribute
+verbatim copies of this license document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share
+and change it. By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to most of
+the Free Software Foundation's software and to any other program whose
+authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom
+to distribute copies of free software (and charge for this service if you wish), that
+you receive source code or can get it if you want it, that you can change the
+software or use pieces of it in new free programs; and that you know you can do
+these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights. These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for a
+fee, you must give the recipients all the rights that you have. You must make
+sure that they, too, receive or can get the source code. And you must show
+them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer
+you this license which gives you legal permission to copy, distribute and/or
+modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced by
+others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We wish
+to avoid the danger that redistributors of a free program will individually obtain
+patent licenses, in effect making the program proprietary. To prevent this, we
+have made it clear that any patent must be licensed for everyone's free use or
+not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+GNU GENERAL PUBLIC LICENSE
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND
+MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License. The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or translated
+into another language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope. The act of running the Program is not
+restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program). Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as
+you receive it, in any medium, provided that you conspicuously and appropriately
+publish on each copy an appropriate copyright notice and disclaimer of warranty;
+keep intact all the notices that refer to this License and to the absence of any
+warranty; and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may at
+your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus
+forming a work based on the Program, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you also
+meet all of these conditions:
+
+a) You must cause the modified files to carry prominent notices stating that you
+changed the files and the date of any change.
+
+b) You must cause any work that you distribute or publish, that in whole or in
+part contains or is derived from the Program or any part thereof, to be licensed
+as a whole at no charge to all third parties under the terms of this License.
+
+c) If the modified program normally reads commands interactively when run, you
+must cause it, when started running for such interactive use in the most ordinary
+way, to print or display an announcement including an appropriate copyright
+notice and a notice that there is no warranty (or else, saying that you provide a
+warranty) and that users may redistribute the program under these conditions,
+and telling the user how to view a copy of this License. (Exception: if the
+Program itself is interactive but does not normally print such an announcement,
+your work based on the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Program, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to
+work written entirely by you; rather, the intent is to exercise the right to control
+the distribution of derivative or collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and 2
+above provided that you also do one of the following:
+
+a) Accompany it with the complete corresponding machine-readable source
+code, which must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange; or,
+
+b) Accompany it with a written offer, valid for at least three years, to give any
+third party, for a charge no more than your cost of physically performing source
+distribution, a complete machine-readable copy of the corresponding source
+code, to be distributed under the terms of Sections 1 and 2 above on a medium
+customarily used for software interchange; or,
+
+c) Accompany it with the information you received as to the offer to distribute
+corresponding source code. (This alternative is allowed only for noncommercial
+distribution and only if you received the program in object code or executable
+form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it. For an executable work, complete source code means all the
+source code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the
+executable. However, as a special exception, the source code distributed need
+not include anything that is normally distributed (in either source or binary form)
+with the major components (compiler, kernel, and so on) of the operating system
+on which the executable runs, unless that component itself accompanies the
+executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source
+code from the same place counts as distribution of the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License. Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License. However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so long
+as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it.
+However, nothing else grants you permission to modify or distribute the Program
+or its derivative works. These actions are prohibited by law if you do not accept
+this License. Therefore, by modifying or distributing the Program (or any work
+based on the Program), you indicate your acceptance of this License to do so,
+and all its terms and conditions for copying, distributing or modifying the
+Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program),
+the recipient automatically receives a license from the original licensor to copy,
+distribute or modify the Program subject to these terms and conditions. You
+may not impose any further restrictions on the recipients' exercise of the rights
+granted herein. You are not responsible for enforcing compliance by third parties
+to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent infringement
+or for any other reason (not limited to patent issues), conditions are imposed on
+you (whether by court order, agreement or otherwise) that contradict the
+conditions of this License, they do not excuse you from the conditions of this
+License. If you cannot distribute so as to satisfy simultaneously your obligations
+under this License and any other pertinent obligations, then as a consequence
+you may not distribute the Program at all. For example, if a patent license would
+not permit royalty-free redistribution of the Program by all those who receive
+copies directly or indirectly through you, then the only way you could satisfy
+both it and this License would be to refrain entirely from distribution of the
+Program.
+
+If any portion of this section is held invalid or unenforceable under any particular
+circumstance, the balance of the section is intended to apply and the section as
+a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other
+property right claims or to contest validity of any such claims; this section has
+the sole purpose of protecting the integrity of the free software distribution
+system, which is implemented by public license practices. Many people have
+made generous contributions to the wide range of software distributed through
+that system in reliance on consistent application of that system; it is up to the
+author/donor to decide if he or she is willing to distribute software through any
+other system and a licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain countries
+either by patents or by copyrighted interfaces, the original copyright holder who
+places the Program under this License may add an explicit geographical
+distribution limitation excluding those countries, so that distribution is permitted
+only in or among countries not thus excluded. In such case, this License
+incorporates the limitation as if written in the body of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the
+General Public License from time to time. Such new versions will be similar in
+spirit to the present version, but may differ in detail to address new problems or
+concerns.
+
+Each version is given a distinguishing version number. If the Program specifies a
+version number of this License which applies to it and "any later version", you
+have the option of following the terms and conditions either of that version or of
+any later version published by the Free Software Foundation. If the Program does
+not specify a version number of this License, you may choose any version ever
+published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission. For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of all
+derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS
+NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
+COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
+"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR
+IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED
+TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY
+WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS
+PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
+(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
+OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
Index: /tags/start/Nebulous/MANIFEST
===================================================================
--- /tags/start/Nebulous/MANIFEST	(revision 12606)
+++ /tags/start/Nebulous/MANIFEST	(revision 12606)
@@ -0,0 +1,53 @@
+Build.PL
+Changes
+LICENSE
+MANIFEST
+META.yml
+Makefile.PL
+README
+TODO
+Todo
+bootstrap.sh
+docs/apache_setup.txt
+docs/c_api.h
+docs/calc_gid.c
+docs/database_setup.txt
+docs/design.txt
+docs/requirements.txt
+docs/setup.txt
+docs/tmp.txt
+iData.wsdl
+lib/PS/IPP/IData/Client.pm
+lib/PS/IPP/IData/Client/HTTP.pm
+lib/PS/IPP/IData/Client/Log.pm
+lib/PS/IPP/IData/Server.pm
+lib/PS/IPP/IData/Server/Apache.pm
+lib/PS/IPP/IData/Server/Log.pm
+lib/PS/IPP/IData/Server/SQL.pm
+lib/PS/IPP/IData/Util.pm
+scripts/bench_test.pl
+scripts/imageserver.pl
+scripts/ptest.pl
+scripts/stest.pl
+t/01_load.t
+t/02_server_setup.t
+t/03_server_create_object.t
+t/04_server_replicate_object.t
+t/05_server_lock_object.t
+t/06_server_unlock_object.t
+t/07_server_find_instances.t
+t/08_server_delete_instance.t
+t/09_server_stat_object.t
+t/10_client_new.t
+t/11_client_create.t
+t/12_client_replicate.t
+t/13_client_cull.t
+t/14_client_lock.t
+t/15_client_unlock.t
+t/16_client_find_instances.t
+t/TEST.PL
+t/Test/IData.pm
+t/apache_03_server_create_object.x
+t/apache_04_server_replicate_object.x
+t/apache_05_server_lock_object.x
+t/conf/extra.conf.in
Index: /tags/start/Nebulous/Makefile.PL
===================================================================
--- /tags/start/Nebulous/Makefile.PL	(revision 12606)
+++ /tags/start/Nebulous/Makefile.PL	(revision 12606)
@@ -0,0 +1,27 @@
+unless (eval "use Module::Build::Compat 0.02; 1" ) {
+  print "This module requires Module::Build to install itself.\n";
+
+  require ExtUtils::MakeMaker;
+  my $yn = ExtUtils::MakeMaker::prompt
+    ('  Install Module::Build from CPAN?', 'y');
+
+  if ($yn =~ /^y/i) {
+    require Cwd;
+    require File::Spec;
+    require CPAN;
+
+    # Save this 'cause CPAN will chdir all over the place.
+    my $cwd = Cwd::cwd();
+    my $makefile = File::Spec->rel2abs($0);
+
+    CPAN::Shell->install('Module::Build::Compat');
+
+    chdir $cwd or die "Cannot chdir() back to $cwd: $!";
+    exec $^X, $makefile, @ARGV;  # Redo now that we have Module::Build
+  } else {
+    warn " *** Cannot install without Module::Build.  Exiting ...\n";
+    exit 1;
+  }
+}
+Module::Build::Compat->run_build_pl(args => \@ARGV);
+Module::Build::Compat->write_makefile();
Index: /tags/start/Nebulous/README
===================================================================
--- /tags/start/Nebulous/README	(revision 12606)
+++ /tags/start/Nebulous/README	(revision 12606)
@@ -0,0 +1,16 @@
+pod2text Poi::PixelData.pm > README
+
+If this is still here it means the programmer was too lazy to create the readme file.
+
+You can create it now by using the command shown above from this directory.
+
+At the very least you should be able to use this set of instructions
+to install the module...
+
+perl Build.PL
+./Build
+./Build test
+./Build install
+
+
+If you are on a windows box you should use 'nmake' rather than 'make'.
Index: /tags/start/Nebulous/TODO
===================================================================
--- /tags/start/Nebulous/TODO	(revision 12606)
+++ /tags/start/Nebulous/TODO	(revision 12606)
@@ -0,0 +1,17 @@
+cache some database tables (updated at some interval) 
+reuse/cache database statement handles
+code tiding/consistency
+volume handling for instance placement
+file creation retrying
+server config file
+make Apache::DBI behave
+WSDL
+split SOAP out of Client.pm
+error string support
+
+distant future
+--
+volume size/% in-use discovery
+server side per client lock tracking
+client side lookup table of filehandles/locks
+Perl only?, scoped lock release/filehandle destruction
Index: /tags/start/Nebulous/Todo
===================================================================
--- /tags/start/Nebulous/Todo	(revision 12606)
+++ /tags/start/Nebulous/Todo	(revision 12606)
@@ -0,0 +1,5 @@
+TODO list for Perl module Poi::PixelData
+
+- Nothing yet
+
+
Index: /tags/start/Nebulous/bootstrap-moa-mp1.sh
===================================================================
--- /tags/start/Nebulous/bootstrap-moa-mp1.sh	(revision 12606)
+++ /tags/start/Nebulous/bootstrap-moa-mp1.sh	(revision 12606)
@@ -0,0 +1,1 @@
+perl Build.PL -http_conf /usr/local/apache/conf/httpd.conf -apxs /usr/local/apache/bin/apxs -httpd /usr/local/apache/bin/httpd 
Index: /tags/start/Nebulous/docs/apache_setup.txt
===================================================================
--- /tags/start/Nebulous/docs/apache_setup.txt	(revision 12606)
+++ /tags/start/Nebulous/docs/apache_setup.txt	(revision 12606)
@@ -0,0 +1,37 @@
+- add the "idata" group to /etc/group
+- configure Apache to run as the idata group. 
+
+#
+# CGI interface
+#
+
+ScriptAlias /idata /usr/local/apache/perl/imageserver.pl
+
+<Directory "/usr/local/apache/perl">
+        AllowOverride None
+        Options None
+        Order allow,deny
+        Allow from all
+</Directory>
+
+PerlModule Apache::PerlRun
+<Location /perl>
+        SetHandler perl-script
+        PerlHandler Apache::PerlRun
+        Options ExecCGI
+        allow from all
+        PerlSendHeader On
+</Location>
+
+#
+# PS::IPP::IData::Apache interface
+#
+
+PerlModule Apache::DBI
+PerlModule PS::IPP::IData::Apache
+
+<Location /idata>
+        SetHandler perl-script
+        PerlHandler PS::IPP::IData::Apache
+</Location>
+
Index: /tags/start/Nebulous/docs/c_api.h
===================================================================
--- /tags/start/Nebulous/docs/c_api.h	(revision 12606)
+++ /tags/start/Nebulous/docs/c_api.h	(revision 12606)
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2004 Joshua Hoblitt
+ *
+ * $Id: c_api.h,v 1.1.1.1 2004-12-22 02:16:23 jhoblitt Exp $
+ */
+
+// should there be an argument for "suggested" storage location?
+int add( const char *ext_id, const char *data, int size )
+
+int delete( const char *ext_id )
+
+// should there be an argument for "suggested" storage location?
+int update( const char *ext_id, const char *data, int size )
+
+// should there be an argument for "suggested" storage location?
+int move( const char *old_ext_id, const char *new_ext_id )
+
+// open returns a fd 
+int open( const char *ext_id )
+
+int close( const char *ext_id )
+
+// maybe open and close are a bad idea, perhaps...
+int read( const char *ext_id, char *data )
Index: /tags/start/Nebulous/docs/calc_gid.c
===================================================================
--- /tags/start/Nebulous/docs/calc_gid.c	(revision 12606)
+++ /tags/start/Nebulous/docs/calc_gid.c	(revision 12606)
@@ -0,0 +1,5 @@
+#include <stdio.h>
+
+main () {
+    printf( "%d\n", 'i'+'m'+'a'+'g'+'e'+'d'+'a'+'t'+'a' + 's'+'e'+'r'+'v'+'e'+'r' );
+}
Index: /tags/start/Nebulous/docs/database_setup.txt
===================================================================
--- /tags/start/Nebulous/docs/database_setup.txt	(revision 12606)
+++ /tags/start/Nebulous/docs/database_setup.txt	(revision 12606)
@@ -0,0 +1,147 @@
+# Copyright (C) 2004  Joshua Hoblitt
+#
+# $Id: database_setup.txt,v 1.1.1.1 2004-12-22 02:16:23 jhoblitt Exp $
+
+### Database Setup
+
+DROP DATABASE IF EXISTS pixel;
+CREATE DATABASE pixel;
+INSERT INTO db VALUES ('%','pixel','pixel','y','y','y','y','y','y','y','y','y','y','y','y');
+INSERT INTO user
+(Host,User,Password,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Index_priv,Alter_priv,Show_db_priv)
+VALUES ('%','pixel',password('pixel'),'y','y','y','y','y','y','y','y','y');
+INSERT INTO user
+(Host,User,Password,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Index_priv,Alter_priv,Show_db_priv)
+VALUES ('localhost','pixel',password('pixel'),'y','y','y','y','y','y','y','y','y');
+FLUSH PRIVILEGES;
+
+USE pixel;
+
+### MySQL 4.0
+
+DROP TABLE IF EXISTS storage_object;
+CREATE TABLE storage_object (
+    so_id BIGINT NOT NULL AUTO_INCREMENT,
+    ext_id VARCHAR(255) BINARY NOT NULL UNIQUE,
+    class_id TINYINT NOT NULL,
+    comment VARCHAR(255),
+    read_lock TINYINT DEFAULT 0 NOT NULL,
+    write_lock ENUM( 'write' ),
+    epoch TIMESTAMP NOT NULL,
+    PRIMARY KEY(so_id),
+    KEY(ext_id(64)),
+    KEY(class_id)
+) ENGINE=innodb;
+
+DROP TABLE IF EXISTS instance;
+CREATE TABLE instance ( 
+    ins_id BIGINT NOT NULL AUTO_INCREMENT,
+    so_id BIGINT NOT NULL,
+    uri VARCHAR(255) BINARY NOT NULL UNIQUE,
+    sha1sum CHAR(40),
+    assigned_location BOOL,
+    epoch TIMESTAMP NOT NULL,
+    atime TIMESTAMP NOT NULL,
+    PRIMARY KEY(ins_id),
+    KEY(so_id),
+    KEY(uri(64))
+) ENGINE=innodb;
+
+DROP TABLE IF EXISTS lock_record;
+CREATE TABLE lock_record (
+        so_id BIGINT NOT NULL,
+        type ENUM( 'read', 'write' ) NOT NULL,
+        epoch TIMESTAMP,
+        KEY(so_ID)
+    ) ENGINE=innodb;
+
+DROP TABLE IF EXISTS volume;
+CREATE TABLE volume (
+        vol_id INT NOT NULL AUTO_INCREMENT,
+        name VARCHAR(255) UNIQUE BINARY NOT NULL,
+        uri VARCHAR(255) BINARY NOT NULL,
+        key(vol_id)
+    ) ENGINE=innodb;
+
+DROP TABLE IF EXISTS class;
+CREATE TABLE class (
+        class_id TINYINT NOT NULL AUTO_INCREMENT,
+        instance TINYINT NOT NULL,
+        priority TINYINT,
+        comment VARCHAR(255),
+        key(class_id)
+    ) ENGINE=innodb;
+
+### MySQL 4.1
+
+DROP TABLE IF EXISTS storage_object;
+CREATE TABLE storage_object (
+        so_id BIGINT NOT NULL AUTO_INCREMENT,
+        ext_id VARCHAR(255) UNIQUE BINARY NOT NULL,
+        comment VARCHAR(255),
+        epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+        PRIMARY KEY(so_id),
+        KEY(ext_id(20))
+    ) ENGINE=innodb;
+
+
+DROP TABLE IF EXISTS instance;
+CREATE TABLE instance ( 
+        ins_id BIGINT NOT NULL AUTO_INCREMENT,
+        so_id BIGINT NOT NULL,
+        uri VARCHAR(255) BINARY NOT NULL,
+        sha1sum CHAR(40) ASCII,
+        read_lock TINYINT NOT NULL,
+        write_lock ENUM( 'write', 'wait' ),
+        atime TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+        PRIMARY KEY(ins_id),
+        KEY(so_id)
+    ) ENGINE=innodb;
+
+DROP TABLE IF EXISTS lock_record;
+CREATE TABLE lock_record (
+        ins_id BIGINT NOT NULL,
+        type ENUM( 'read', 'write', 'wait' ) NOT NULL,
+        epoch TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+    ) ENGINE=innodb;
+
+        epoch TIMESTAMP,
+
+### Initialization
+
+# NFS
+
+INSERT INTO volume VALUES (1,'po01','file:/tmp/po01');
+INSERT INTO volume VALUES (2,'po02','file:/tmp/po02');
+INSERT INTO volume VALUES (3,'po03','file:/tmp/po03');
+INSERT INTO volume VALUES (4,'po04','file:/tmp/po04');
+INSERT INTO volume VALUES (5,'po05','file:/tmp/po05');
+INSERT INTO volume VALUES (6,'po06','file:/tmp/po06');
+INSERT INTO volume VALUES (7,'po07','file:/tmp/po07');
+INSERT INTO volume VALUES (8,'po08','file:/tmp/po08');
+
+INSERT INTO class VALUES (1,3,0,'raw image data');
+
+### Example queries
+
+LOAD DATA INFILE '/home/moa/jhoblitt/tmp/storage_objects.txt' INTO TABLE storage_object; 
+LOAD DATA INFILE '/home/moa/jhoblitt/tmp/instances.txt' INTO TABLE instance; 
+
+SELECT * FROM storage_object LEFT JOIN instance ON storage_object.so_id=instance.so_id WHERE storage_object.ext_id = "foobarbaz1.fits";
+SELECT * FROM storage_object LEFT JOIN instance USING (so_id) WHERE storage_object.ext_id = "foobarbaz1.fits";
+
+SET AUTOCOMMIT = 0;
+BEGIN;
+UPDATE instance SET read_lock=read_lock+1 WHERE ins_id=1;
+INSERT INTO lock_record values (1, 'read', NULL);
+COMMIT;
+
+SET AUTOCOMMIT = 0;
+BEGIN;
+INSERT INTO storage_object values (NULL, 'myfooedbar.fits', 'mr. wizard made this', NULL);
+INSERT INTO instance values (NULL, LAST_INSERT_ID(), 'file://tmp/bat/man/12345a', 'da39a3ee5e6b4b0d3255bfef95601890afd80709',0, NULL, NULL);
+COMMIT;
+
+IF select write_lock from instance WHERE id=1 THEN
+ELSE
+ENDIF
Index: /tags/start/Nebulous/docs/design.txt
===================================================================
--- /tags/start/Nebulous/docs/design.txt	(revision 12606)
+++ /tags/start/Nebulous/docs/design.txt	(revision 12606)
@@ -0,0 +1,163 @@
+# Copryight (C) 2004  Joshua Hoblitt
+#
+# $Id: design.txt,v 1.1.1.1 2004-12-22 02:16:23 jhoblitt Exp $
+
+Terminology
+--
+    - Storage Object
+There is one Storage Object per resource (a file) that is being managed by the
+IPP Pixel Data Server.  A Storage Object maps an External Identifier (eg.
+file name) to a Storage ID that is internal to the IPP Pixel Data Server.  In
+addition, creation time and comments may be stored in a Storage Object.
+Storage Objects /do not/ contain the storage location of a resource as we need
+to allow for N copies of a resource to be stored.  The actual storage location
+of a resource is held in a Storage Object Instance, which maps to a Storage ID
+in a many-to-one relationship.
+
+    - [Storage Object] Instance
+A Storage Object Instance, or just Instance, represents a single copy of a
+resource being managed by the IPP Pixel Data Server. An Instance contains an
+Instance ID, the location of the resource as a URI, a checksum of the
+resource, a Storage ID, a read lock semaphore (unsigned integer), a write lock
+mutex (enum( 'write', 'wait', 'free' ) - is this better then using an int and
+constants?), and a UTC timestamp of the last modification date & time.
+
+    - Lock Record
+A Lock Record is used to double check the indicated lock state of an Instance
+and can be used to identify system failures.  It must contain the Instance ID
+of of the locked instance and the type of lock, eg, enum( 'read', 'write').
+
+Locking semantics
+--
+A lock is required to either read from or write to a Storage Object Instance
+being managed by the IPP Pixel Data Server.  Stated another way, locking
+granularity is managed on the level of Storage Object Instances instead of on
+the more abstract Storage Objects.  Although, from the client perspective,
+operations are carried out on a Storage Object.   The locking state of a
+Storage Object Instance is maintained by in the Storage Object Instance and a
+Lock Record.
+
+Two types of locks are used on an Instance, a semaphore is used to track read
+locks and an exclusive mutex is for write locking.
+
+    - Read lock
+In order to read from a Storage Object Instance the Read Lock semaphore must
+first be incremented by one and a Lock Record created.  After the read is
+completed the Lock Record must be deleted and the Read Lock semaphore
+decremented by one.  The incrementation of the Read Lock and Lock Record
+creation or the decrementation of the Read Lock and the Lock Record deletion
+must happen atomically.  A Read lock can not be aquired unless the Write mutex
+is in the state of 'free'.  If a Read lock can not be aquired, a client must
+not "spin lock" on the Instanace ID as it may be in the process of being
+removed.  Instead, the "spin lock" should be re-resolving the external
+identifier to a Storage ID, and the Storage ID to Storage Instances.
+
+    - Write lock
+In order to obtain a Write lock on a Storage Object Instance the Write Lock
+mutex must be in the state of 'free' and the Read lock semaphore must have a
+value of zero.  A client should either "spin lock" or fail if all the Lock
+mutex is set or the Read Semaphore has a non-zero value.  A Lock Record must
+be created atomically with the setting of the Write mutex.  The setting of the
+Write mutex and Lock Record insertion or the clearing of the Write mutex and
+the Lock Record deletion must happen atomically.  If the Write lock has a
+state of 'free' and the Read lock has a non-zero value, the Write lock may be
+set to the 'wait' state to prevent new Read locks from being aquired.
+
+Storage Object Operations
+--
+    - Add
+The resource must already be on disk (having been named through some sort of
+mechanism to generate new filenames).  A new Storage Object must be created with a new/unqiue  Storage ID and has
+an associated with an External Identifier.  At least one Instance must be
+created atomicaly at the same time.  Each new Instance must be initially created with a Write lock.
+The resource may then be written to it's storage location.  When the writing
+of the resource is completed the Write lock must be cleared as early as is
+feasible.  The association of an External Identifier must wait until Instance
+creation is completed
+
+    - Delete
+In order to remove a Storage Object, a Write lock must be obtained on
+/all/ associated Instances.  Then the resources are removed.  As each resource
+is deleted the corresponding Instance must be deleted.  After all Instances are
+removed the Storage Object must then be deleted.
+
+    - Update
+Storage Object Instances are not truly written to.  Instead, a new set of
+Storage Object Instances and a new Storage Object are created in parallel.
+
+Write locks must be aquired on all the orignal Intances of a Storage Object.
+Then an Add operation is performed to create a new Storage Object and
+associated Instances.  Then the External Identifier must be atomically moved
+from the original Storage Object to the new Storage Object.  After the
+External Identifier migration, the original Storage Object and it's Instances
+should be removed with a special case of the Delete operation (one that will
+operate on already held locks).  If the old Storage Object is merely
+abandoned, ie. it still exists but doesn't have an External Identifier, it and
+the associated Instances will be removed during the next Consistency Sweep.
+If a Delete is not peformed, the Write locks on the orignal Instances must be
+released. [use a dead Storage Object table or flag, similar to mark and sweep
+garbage collection?]
+
+    - Move
+This is the same operation as an Update except the new Instances are identical
+to the old.
+
+    - Open
+Sets a Read lock on an Instances of a Storage Object and determines it's
+storage location.  A Read lock must only be placed on one Instance of a
+Storage Object.  All Instances of a Storage Object should be iterated through
+in a "spin lock" until a Read lock is aquired.
+
+    - Close
+Releases a Read lock aquired with open.
+
+The lock must be released as soon as is feasible.
+
+Lock sweeping
+--
+In the event that a Storage Object operation fails to complete successfully
+stale locks will have to be identified and removed from the IPP Pixel Data
+Server Database.  This should be done periodically by comparing the entries
+in the Lock table to the list of active nodes maintained by the IPP
+Controller.  It should also happen as soon as possible after a node goes
+offline (triggered by the IPP Controller marking a node as offline?).  A sweep
+must be /completed/ before an offline node can be marked on-line.
+
+Once a node is determined to be offline all entries in the Lock table set by
+that node should be identified.   The locks on the Storage Object
+Instances pointed to by those entries should then be rolled back and Lock
+Record entries themselves must be removed from the lock table.
+
+Consistency sweeping
+--
+Periodically the IPP Pixel Data Server meta-data and Storage Object will need
+to be checked for sanity.  This would be similar to running fsck on a modern
+filesystem.  Consistency sweeping should include Lock sweeping and should be
+considered a superset.
+
+All Storage Objects must have at least once associated Instance.
+
+All Storage Object Instances must be associated with a Storage Object.
+
+All Storage Object Instances with a lock set must have the correct number of
+corresponding Lock Records.
+
+All Lock Records must be plausible, ie. the Instance pointed at must be in a
+corresponding state.
+
+Storage ID Allocation
+--
+Storage IDs are a signed 64-bit integer.  Negative values are considered
+reserved for future use.  Allocation should be incremental and, as we are
+unlikely to exceed 2^63 Storage Objects in the life time of the project, never
+reused.
+
+Allocated via [SQL auto-increment/stored procedure/app server?]
+
+Instance ID Allocation
+--
+Indentical to a Storage ID but exists in a unique namespace.
+
+Storage Location determination
+--
+???
Index: /tags/start/Nebulous/docs/requirements.txt
===================================================================
--- /tags/start/Nebulous/docs/requirements.txt	(revision 12606)
+++ /tags/start/Nebulous/docs/requirements.txt	(revision 12606)
@@ -0,0 +1,23 @@
+# Copyright (C) 2004  Joshua Hoblitt
+#
+# $Id: requirements.txt,v 1.1.1.1 2004-12-22 02:16:23 jhoblitt Exp $
+
+- store all image data aquired during the first two years of PS1's
+  operations.  Approximately 10^8 files (OTA level).
+
+- injest new data from the summit at the same rate it is produced when
+  operating at a cadence of 40s between integrations.  Approximately 400Mb/s.
+
+- support phase 1 & 2 processing. x files per t_min
+
+- support phase 3 & 4 processing. x files per t_min
+
+- support accessing small blocks of a file (ie., seek)
+
+what are the science drivers for these 3?
+--
+- data corruption is guarenteed to be detectable.
+
+- relibably store xx.x% of files 
+
+- xx.x% of stored images must be retreivable in xs.
Index: /tags/start/Nebulous/docs/setup.txt
===================================================================
--- /tags/start/Nebulous/docs/setup.txt	(revision 12606)
+++ /tags/start/Nebulous/docs/setup.txt	(revision 12606)
@@ -0,0 +1,33 @@
+
+- building and install the Perl modules (see: README)
+
+- create and initialize the database (see: docs/database_setup.txt)
+
+- setup the server
+
+As a CGI, work with either Apache 1.3.x or 2.0.x
+
+cp scripts/imagesever.pl /var/www/localhost/cgi-bin
+chmod 755 /var/www/localhost/cgi-bin/imageserver.pl
+touch /tmp/imageserver.log
+chmod 1777 /tmp/imageserver.log
+
+- test the imageserver.pl is working
+
+telnet localhost 80
+Trying 127.0.0.1...
+Connected to localhost.
+Escape character is '^]'.
+GET /cgi-bin/imageserver.pl HTTP/1.0
+
+HTTP/1.1 411 Length Required
+Date: Tue, 28 Sep 2004 21:15:58 GMT
+Server: Apache/2.0.49 (Gentoo/Linux)
+Content-Length: 0
+Connection: close
+Content-Type: text/plain; charset=ISO-8859-1
+
+Connection closed by foreign host.
+
+- if you get an HTTP 5xx code check your apache error_log
+
Index: /tags/start/Nebulous/docs/tmp.txt
===================================================================
--- /tags/start/Nebulous/docs/tmp.txt	(revision 12606)
+++ /tags/start/Nebulous/docs/tmp.txt	(revision 12606)
@@ -0,0 +1,44 @@
+client
+--
+new
+
+new_file
+                new_file
+                open_file
+
+find_file
+    find_instance
+
+open_file
+    find_file
+
+delete_file
+                delete_file
+    nuke
+
+copy_file
+    open_file
+    new_file
+
+move_file
+    copy_file
+    delete_file
+
+replicate_file
+    open_file
+                replicate_file
+
+cull_file
+    find_instance
+    delete_instance
+
+delete_instance
+    nuke
+                delete_instance
+
+find_instance
+                find_instance
+
+# missing
+file_stat
+lock ?
Index: /tags/start/Nebulous/lib/Nebulous/Client.pm
===================================================================
--- /tags/start/Nebulous/lib/Nebulous/Client.pm	(revision 12606)
+++ /tags/start/Nebulous/lib/Nebulous/Client.pm	(revision 12606)
@@ -0,0 +1,631 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: Client.pm,v 1.1.1.1 2004-12-22 02:16:23 jhoblitt Exp $
+
+package PS::IPP::IData::Client;
+
+use strict;
+use warnings;
+
+our $VERSION = '0.01';
+
+use File::Copy qw();
+use Log::Log4perl qw(get_logger :levels);
+use PS::IPP::IData::Client::Log;
+use PS::IPP::IData::Util qw( :standard );
+use Params::Validate qw( validate validate_pos SCALAR );
+use SOAP::Lite +trace => [qw( debug )];
+use Time::HiRes qw( sleep );
+use URI;
+
+use constant LOCK_INTERVAL  => 1;
+use constant LOCK_DEFAULT   => 10;    # default to a 10s lock timeout
+
+my $log = get_logger( "PS::IPP::IData::Client" );
+
+$SOAP::Constants::PATCH_HTTP_KEEPALIVE = 1;
+
+# TODO remove most of the logdies
+
+sub import {
+    my $class = shift;
+
+    $log->debug( "entered - args: @_" );
+
+	my %args = validate( @_,
+        {
+            trace => {
+                type        => SCALAR,
+                default     => $ERROR,
+                callbacks   => {
+                    'is valid level' => sub {
+                        defined $LEVELS{ lc $_[0] };
+                    },
+                },
+            },
+        },
+    );
+
+    $log->level( $LEVELS{ lc $args{ 'trace' } } );
+
+    return 1;
+}
+
+sub new {
+    my $class = shift;
+
+    my %args = validate( @_,
+        {
+            proxy   => {
+                type        => SCALAR,
+            },
+            uri     => {
+                type        => SCALAR,
+                optional    => 1,
+            },
+        },
+    );
+
+    $log->debug( "entered - args: @{[ %args ]}" );
+
+    my $lite = SOAP::Lite->new(
+            proxy => $args{ 'proxy' },
+            uri   => $args{ 'uri' } || "http://pan-starrs.ifa.hawaii.edu/PS/IPP/IData/Server",
+    );
+
+    $log->logdie( "can not create SOAP::Lite object" ) unless $lite;
+
+    my $self = bless( { server => $lite }, ref $class || $class );
+
+    $log->debug( "leaving" );
+
+    return $self;
+}
+
+sub create {
+    my $self = shift;
+
+    my ( $key, @params ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is + integer' => sub { $_[0] =~ /^\d+$/ },
+            },
+            default     => 0,
+        },
+        {
+            type        => SCALAR,
+            optional    => 1,
+        },
+        {
+            type        => SCALAR,
+            optional    => 1,
+        },
+    );
+
+    $log->debug( "entered - key: $key, params: @params" );
+
+    # how should already existing files be handled?
+
+    my $response = $self->{ 'server' }->create_object( $key, @params );
+    if ( $response->fault ) {
+        $log->error( $response->faultcode, " - ", $response->faultstring );
+        $log->debug( "leaving" );
+
+        return undef;
+    }
+
+    my $uri = $response->result;
+
+    $log->debug( "server allocated $uri" );
+
+#    unless( $self->lock( $key, "write"  )) {
+#        $log->debug( "can not lock object" );
+#        $log->debug( "leaving" );
+#
+#        return undef;
+#    }
+
+    my $fh;
+    eval {
+        $fh = _open_uri( $uri, '+<' );
+    };
+    $log->logdie( $@ ) if $@;
+
+    $log->debug( "leaving" );
+
+    return $fh;
+}
+
+sub replicate {
+    my $self = shift;
+
+    my ( $key, @params ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            # volume
+            type        => SCALAR,
+            optional    => 1,
+        },
+    );
+
+    $log->debug( "entered - key: $key, params: @params" );
+
+    my $response = $self->{ 'server' }->replicate_object( $key, @params );
+    if ( $response->fault ) {
+        $log->error( $response->faultcode, " - ", $response->faultstring );
+        $log->debug( "leaving" );
+
+        return undef;
+    }
+
+    # don't let anybody start reading the new instance before it's fully
+    # written
+    my $fh  = $self->open( $key, 'write' );
+    unless ( $fh ) {
+        $log->debug( "can't open $key" );
+        $log->debug( "leaving" );
+
+        return undef;
+    }
+
+    $log->debug( "server allocated new instance" );
+
+    my $uri = $response->result;
+
+    my $new_fh;
+    eval {
+        $new_fh = _open_uri( $uri, '>' );
+    };
+    $log->logdie( $@ ) if $@;
+
+    File::Copy::copy( $fh, $new_fh ) or $log->logdie( "can not copy instance $uri" );
+
+    $log->debug( "copied instance" );
+
+    close( $fh ) or $log->logdie( "can not close $key" );
+    close( $new_fh ) or $log->logdie( "can not close $key" );
+
+#    unless ($self->unlock( $key, "write" )) {
+#        $log->debug( "can not lock object" );
+#        $log->debug( "leaving" );
+#
+#        return undef;
+#    }
+
+    $log->debug( "leaving" );
+
+    return $uri;
+}
+
+sub cull {
+    my $self = shift;
+
+    my ( $key ) = validate_pos( @_,
+        {
+            type => SCALAR,
+        },
+    );
+
+    $log->debug( "entered - key: $key" );
+
+    # need some way to determine which is the best instance to remove
+    my $locations = $self->find_instances( $key );
+    unless ( $locations ) {
+            $log->debug( "no instances" );
+            $log->debug( "leaving" );
+
+            return undef;
+    }
+
+    if ( scalar @{ $locations } < 2 ) {
+        $log->debug( "can not cull - not enough instances" );
+        $log->debug( "leaving" );
+
+        return undef;
+    }
+
+    # make sure nobody is reading while we are deleting
+    unless ($self->lock( $key, "write" )) {
+        $log->debug( "can not lock object" );
+        $log->debug( "leaving" );
+
+        return undef;
+    }
+
+    my $status = $self->delete_instance( $locations->[0] );
+
+    unless ($self->unlock( $key, "write" )) {
+        $log->debug( "can not lock object" );
+        $log->debug( "leaving" );
+
+        return undef;
+    }
+
+    $log->debug( "leaving" );
+
+    return $status;
+}
+
+sub lock {
+    my $self = shift;
+
+    my ( $key, $type, $timeout ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is read or write' => sub { $_[0] =~ /^(?:read|write)$/ },
+            },
+        },
+        {
+            type        => SCALAR,
+            default     => LOCK_DEFAULT,
+            optional    => 1,
+            callbacks   => {
+                'is + integer' => sub { $_[0] =~ /^\d+$/ },
+            },
+        },
+    );
+
+    my $endtime = time() + $timeout;
+
+    $log->debug( "entered - key: $key, type: $type, timeout: $timeout" );
+
+    my $locked;
+
+    while ( time() < $endtime ) {
+        $log->debug( "trying to get a $type lock..." );
+
+        my $response = $self->{ 'server' }->lock_object( $key, $type );
+        if ( $response->fault ) {
+            $log->error( $response->faultcode, " - ", $response->faultstring );
+            $log->debug( "leaving" );
+            
+            # don't bother to spin lock if the object doesn't exist
+            if ( $response->faultstring =~ /storage object does not exist/ ) {
+                return undef;
+            }
+
+            next;
+        }
+
+        $locked = $response->result;
+        if ( $locked ) {
+            $log->debug( "got a $type lock" );
+            last;
+        }
+    } continue {
+        $log->debug( "sleeping..." );
+        sleep LOCK_INTERVAL;
+    }
+
+    $log->debug( "can not get a lock" ) unless $locked;
+
+    $log->debug( "leaving" );
+    
+    return $locked ? 1 : undef;
+}
+
+sub unlock {
+    my $self = shift;
+
+    my ( $key, $type ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is read or write' => sub { $_[0] =~ /^(?:read|write)$/ },
+            },
+        },
+    );
+
+    $log->debug( "entered - key: $key, type: $type" );
+
+    my $unlocked;
+
+    $log->debug( "trying to release a $type lock..." );
+
+    my $response = $self->{ 'server' }->unlock_object( $key, $type );
+    if ( $response->fault ) {
+        $log->error( $response->faultcode, " - ", $response->faultstring );
+        $log->debug( "leaving" );
+
+        return undef;
+    }
+
+    $unlocked = $response->result;
+    if ( $unlocked ) {
+        $log->debug( "released a $type lock" );
+    } else {
+        $log->debug( "can not release $type lock" );
+    }
+
+    $log->debug( "leaving" );
+    
+    return $unlocked ? 1 : undef;
+}
+
+sub find_instances {
+    my $self = shift;
+
+    my ( $key, @params ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            #volume
+            type        => SCALAR,
+            optional    => 1,
+        },
+    );
+
+    $log->debug( "entered - key: $key" );
+
+    my $response = $self->{ 'server' }->find_instances( $key, @params );
+    if ( $response->fault ) {
+        $log->error( $response->faultcode, " - ", $response->faultstring );
+        $log->debug( "leaving" );
+
+        return undef;
+    }
+
+    my $uris = $response->result;
+
+    $log->debug( "server found: @$uris" );
+
+#    foreach my $path ( @{ $uris } ) {
+#        $path = _get_file_path( $path );
+#    }
+
+    $log->debug( "leaving" );
+
+    return $uris;
+}
+
+sub find {
+    my $self = shift;
+
+    my ( $key ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+    );
+
+    $log->debug( "entered - key: $key" );
+
+    my $locations = $self->find_instances( $key );
+
+    my $path;
+    eval {
+        $path = _get_file_path( $locations->[0] );
+    };
+    $log->logdie( $@ ) if $@;
+
+    $log->debug( "leaving" );
+
+    return $path;
+}
+
+sub open {
+    my $self = shift;
+
+    my ( $key, $type ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is read or write' => sub { $_[0] =~ /^(?:read|write)$/ },
+            },
+        },
+    );
+
+    $log->debug( "entered - key: $key, type: $type" );
+
+    my $fh;
+
+    # need to figure out which is the most optimal copy to open
+    my $locations = $self->find_instances( $key );
+
+    my $path;
+    eval {
+        $path = _get_file_path( $locations->[0] );
+    };
+    $log->logdie( $@ ) if $@;
+
+    unless ( $path ) {
+        $log->debug( "no instances" );
+
+        if ( $type eq 'write' ) {
+            $log->debug( "creating a new storage object" );
+
+            my $ret = $self->create( $key );
+
+            $log->debug( "leaving" );
+
+            return $ret;
+        } else {
+            $log->debug( "leaving" );
+            return undef;
+        }
+    }
+
+    if ( $type eq 'write' ) {
+#        unless ($self->lock( $key, $type )) {
+#            $log->debug( "can not lock object" );
+#            $log->debug( "leaving" );
+#
+#            return undef;
+#        }
+
+        eval {
+            $fh = _get_filehandle( $path, '+<' );
+        };
+        $log->logdie( $@ ) if $@;
+    } elsif ( $type eq 'read' ) {
+#            unless ($self->lock( $key, $type )) {
+#            $log->debug( "can not lock object" );
+#            $log->debug( "leaving" );
+#
+#            return undef;
+#        }
+
+        eval {
+            $fh = _get_filehandle( $path, '<' );
+        };
+        $log->logdie( $@ ) if $@;
+    }
+
+    $log->debug( "leaving" );
+
+    return $fh;
+}
+
+sub delete {
+    my $self = shift;
+
+    my ( $key ) = validate_pos( @_,
+        {
+            type => SCALAR,
+        },
+    );
+
+    $log->debug( "entered - key: $key" );
+
+    unless ($self->lock( $key, "write" )) {
+        $log->debug( "can not lock object" );
+        $log->debug( "leaving" );
+
+        return undef;
+    }
+
+    my $locations = $self->find_instances( $key );
+        
+    foreach my $uri ( @$locations ) {
+        $self->delete_instance( $uri );
+    }
+
+    # lock is implicitly removed when the last storage object is deleted
+
+    $log->debug( "leaving" );
+
+    return 1;
+}
+
+sub copy {
+    my $self = shift;
+
+    my ( $key, $new_key ) = validate_pos( @_,
+        {
+            type => SCALAR,
+        },
+        {
+            type => SCALAR,
+        },
+    );
+
+    $log->debug( "entered - key: $key, new_key: $new_key" );
+
+    my $fh      = $self->open( $key, 'read' );
+    my $new_fh  = $self->create( $new_key );
+
+    File::Copy::copy( $fh, $new_fh ) or $log->logdie( "can not copy object $key" );
+
+    close( $fh ) or $log->logdie->( "can not close $key" );
+    close( $new_fh ) or $log->logdie->( "can not close $new_key" );
+
+    unless ($self->unlock( $key, "read" )) {
+        $log->debug( "can not lock object" );
+        $log->debug( "leaving" );
+
+        return undef;
+    }
+
+    unless ($self->unlock( $new_key, "write" )) {
+        $log->debug( "can not lock object" );
+        $log->debug( "leaving" );
+
+        return undef;
+    }
+
+    $log->debug( "leaving" );
+
+    return 1;
+}
+
+sub move {
+    my $self = shift;
+
+    my ( $key, $new_key ) = validate_pos( @_,
+        {
+            type => SCALAR,
+        },
+        {
+            type => SCALAR,
+        },
+    );
+
+    $log->debug( "entered - key: $key, new_key: $new_key" );
+
+    $self->copy( $key, $new_key );
+    $self->delete( $key );
+
+    $log->debug( "leaving" );
+
+    return 1;
+}
+
+sub delete_instance {
+    my $self = shift;
+
+    my ( $uri ) = validate_pos( @_,
+        {
+            type => SCALAR,
+        },
+    );
+
+    $log->debug( "entered - uri: $uri" );
+
+    # it is being assumed here that it is better to have files on disk and not in
+    # the database then the inverse.
+
+    my $path;
+    eval {
+        $path = _get_file_path( $uri );
+    };
+    $log->logdie( $@ ) if $@;
+
+    my $response = $self->{ 'server' }->delete_instance( $uri );
+    if ( $response->fault ) {
+        $log->error( $response->faultcode, " - ", $response->faultstring );
+        $log->debug( "leaving" );
+
+        return undef;
+    }
+
+    $log->debug( "server deleted instance" );
+
+    eval {
+        _nuke_file( $path );
+    };
+    $log->logdie( $@ ) if $@;
+
+    $log->debug( "leaving" );
+
+    return $uri;
+}
+
+1;
+
+__END__
Index: /tags/start/Nebulous/lib/Nebulous/Client/HTTP.pm
===================================================================
--- /tags/start/Nebulous/lib/Nebulous/Client/HTTP.pm	(revision 12606)
+++ /tags/start/Nebulous/lib/Nebulous/Client/HTTP.pm	(revision 12606)
@@ -0,0 +1,26 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: HTTP.pm,v 1.1.1.1 2004-12-22 02:16:24 jhoblitt Exp $
+
+package PS::IPP::IData::Client::HTTP;
+
+use strict;
+
+our $VERSION = '0.01';
+
+use base qw( SOAP::Lite );
+
+sub call {
+    my $result = $_[0]->SUPER::call( @_ );
+
+    if (( UNIVERSAL::isa( $result, 'SOAP::SOM' )) && $result->fault ) {
+
+        return $result->faultstring;
+    }
+
+    return $result;
+}
+
+1;
+
+__END__
Index: /tags/start/Nebulous/lib/Nebulous/Client/Log.pm
===================================================================
--- /tags/start/Nebulous/lib/Nebulous/Client/Log.pm	(revision 12606)
+++ /tags/start/Nebulous/lib/Nebulous/Client/Log.pm	(revision 12606)
@@ -0,0 +1,33 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: Log.pm,v 1.1.1.1 2004-12-22 02:16:24 jhoblitt Exp $
+
+package PS::IPP::IData::Client::Log;
+
+use strict;
+
+our $VERSION = '0.01';
+
+use Log::Log4perl;
+
+my $conf = q(
+    log4perl.category.PS.IPP.IData.Client = DEBUG, Screen
+#log4perl.category.PS.IPP.IData.Client = DEBUG, CLIENTLOGFILE, Screen
+
+    log4perl.appender.Screen        = Log::Log4perl::Appender::Screen
+    log4perl.appender.Screen.stderr = 0
+    log4perl.appender.Screen.layout = Log::Log4perl::Layout::PatternLayout
+    log4perl.appender.Screen.layout.ConversionPattern = %d | %H | %p | %M - %m%n
+
+    log4perl.appender.CLIENTLOGFILE           = Log::Log4perl::Appender::File
+    log4perl.appender.CLIENTLOGFILE.filename  = /tmp/idata_client.log
+    log4perl.appender.CLIENTLOGFILE.mode      = append
+    log4perl.appender.CLIENTLOGFILE.layout    = Log::Log4perl::Layout::PatternLayout
+    log4perl.appender.CLIENTLOGFILE.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} | %H | %p | %M - %m%n
+);
+
+Log::Log4perl::init( \$conf );
+
+1;
+
+__END__
Index: /tags/start/Nebulous/lib/Nebulous/Server.pm
===================================================================
--- /tags/start/Nebulous/lib/Nebulous/Server.pm	(revision 12606)
+++ /tags/start/Nebulous/lib/Nebulous/Server.pm	(revision 12606)
@@ -0,0 +1,660 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: Server.pm,v 1.1.1.1 2004-12-22 02:16:24 jhoblitt Exp $
+
+package PS::IPP::IData::Server;
+
+use strict;
+use warnings;
+no warnings qw( uninitialized );
+
+our $VERSION = '0.01';
+
+use DBI;
+use PS::IPP::IData::Util qw( :standard );
+use PS::IPP::IData::Server::Log;
+use PS::IPP::IData::Server::SQL;
+use Log::Log4perl;
+use Params::Validate qw( validate_pos SCALAR );
+
+my %class = (
+    raw => 1,
+);
+
+my $log;
+my $sql;
+my $db;
+
+sub setup {
+    my $self = shift;
+
+    my ( $dsn, $user, $passwd ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+        },
+    );
+
+    $log = Log::Log4perl::get_logger( "PS::IPP::IData::Server" );
+    $sql = PS::IPP::IData::Server::SQL->new;
+
+    $log->debug( "entered - @_" );
+
+    eval {
+        $db = DBI->connect(
+            $dsn,
+            $user,
+            $passwd,
+            {
+                RaiseError => 1,
+                PrintError => 0,
+                AutoCommit => 0,
+            },
+        );
+
+        $db->do( $sql->set_transaction_model );
+
+        $db->commit;
+    };
+    if ( $@ ) {
+        $db->rollback if $db;
+        $log->logdie( "database error: $@" );
+    }
+
+    $log->debug( "connected to database: ", sub { $db->data_sources; } );
+
+    $log->debug( "leaving" );
+
+    return 1;
+}
+
+sub create_object {
+    my $self = shift;
+
+    $log->debug( "entered - @_" );
+
+    my ( $key, $class, $volume, $comment ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is + integer' => sub { $_[0] =~ /^\d+$/ },
+            },
+            default     => 0,
+        },
+        {
+            type        => SCALAR,
+            optional    => 1,
+        },
+        {
+            type        => SCALAR,
+            optional    => 1,
+        },
+    );
+
+    # TODO do some intelligent volume allocated 
+    # add hooks to make this decision based on avaiable space
+    $volume = _get_storage_volume( $volume );
+
+    # check that the comment isn't too long
+    # check that the class requested is valid
+    # check that the volume requested is valid
+
+    my $uri;
+    my $ins_id;
+
+    eval {
+        {
+            # create storage_object
+            my $query = $db->prepare( $sql->new_object ); 
+            $query->execute( $key, $class, $comment );
+        }
+
+        {
+            # create instance with no URI
+            my $query = $db->prepare( $sql->new_object_instance );
+            $query->execute;
+        }
+
+        {
+            # get instance ID
+            my $query = $db->prepare( $sql->last_insert_id );
+            $query->execute;
+            ( $ins_id ) = $query->fetchrow_array;
+        }
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->logdie( "database error: $@" );
+    }
+
+    $uri = "$volume/$key.$ins_id";
+
+    $log->debug( "generated uri $uri");
+
+    my $path = _get_file_path( $uri );
+
+    # TODO add some stuff here to retry if unsucessful
+    eval {
+        _create_empty_file( $path );
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->logdie( $@ );
+    }
+
+    eval {
+        {
+            my $query = $db->prepare( $sql->update_instance_uri );
+            $query->execute( $uri, $ins_id );
+        }
+
+        $db->commit;
+    };
+    $log->logdie( "database error: $@" ) if $@;
+
+    $log->debug( "leaving" );
+
+    return $uri;
+}
+
+sub replicate_object {
+    my $self = shift;
+
+    $log->debug( "entered - @_" );
+
+    my ( $key, $volume ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            optional    => 1,
+        },
+    );
+
+    # TODO
+    $volume = _get_storage_volume();
+
+    my $path;
+    my $uri;
+
+    my $so_id;
+    my $ins_id;
+    eval {
+        {
+            my $query = $db->prepare( $sql->get_object_instances );
+            my $rows = $query->execute( $key );
+
+            unless ( $rows > 0 ) {
+                $db->rollback;
+                $log->logdie( "storage object does not exist" );
+            }
+
+            $so_id = $query->fetchrow_hashref->{ 'so_id' };
+        }
+
+        {
+            my $query = $db->prepare( $sql->new_instance );
+            $query->execute( $so_id );
+        }
+
+        {
+            my $query = $db->prepare( $sql->last_insert_id );
+            $query->execute();
+
+            ( $ins_id ) = $query->fetchrow_array;
+        }
+
+        {
+            $uri = "$volume/$key.$ins_id";
+            $log->debug( "generated uri $uri");
+
+            my $query = $db->prepare( $sql->update_instance_uri );
+            $query->execute( $uri, $ins_id );
+        }
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->logdie( "database error: $@" );
+    }
+
+
+    eval {
+        $path = _get_file_path( $uri );
+        $path = _create_empty_file( $path );
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->logdie( $@ );
+    }
+
+    $db->commit;
+
+    $log->debug( "leaving" );
+
+    return $uri;
+}
+
+sub lock_object {
+    my $self = shift;
+
+    $log->debug( "entered - @_" );
+
+    my ( $key, $type ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is read or write' => sub { $_[0] =~ /^(?:read|write)$/ },
+            },
+        },
+    );
+
+    my $so_id;
+    my $read_lock;
+    my $write_lock;
+
+    eval {
+        # this will set update locks
+        my $query = $db->prepare( $sql->get_object_locks );
+        my $rows = $query->execute( $key );
+        unless ( $rows == 1 ) {
+            $log->logdie( "storage object does not exist" );
+        }
+
+        my $row = $query->fetchrow_hashref;
+
+        $so_id      = $row->{ 'so_id' };
+        $read_lock  = $row->{ 'read_lock' };
+        $write_lock = $row->{ 'write_lock' };
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->logdie( "database error: $@" );
+    }
+
+    if ( $type eq 'write' ) {
+        # can't set a write lock twice and
+        # can't set a write lock if there are read locks
+        if ( $write_lock ) {
+            eval { $db->rollback; };
+            $log->logdie( "database error: $@" ) if $@;
+
+            $log->logdie( "can not write lock twice" );
+        }
+            
+        if ( $read_lock > 0 ) {
+            eval { $db->rollback; };
+            $log->logdie( "database error: $@" ) if $@;
+
+            $log->logdie( "can not write lock after read lock" );
+        }
+
+        eval {
+            my $query = $db->prepare( $sql->set_write_lock );
+            my $rows = $query->execute( $key );
+        
+            # if we affected more then one row something very bad has happened.
+            unless ( $rows == 1 ) {
+                $log->logdie( "affected row count is $rows instead of 1" );
+            }
+
+            $db->commit;
+        };
+        if ( $@ ) {
+            $db->rollback;
+            $log->logdie( "database error: $@" );
+        }
+
+        $log->debug( "leaving" );
+
+        return 1;
+    }
+
+    if ( $type eq 'read' ) {
+        # can't set a read lock if there's a write lock
+        if ( $write_lock ) {
+            eval { $db->rollback; };
+            $log->logdie( "database error: $@" ) if $@;
+
+            $log->logdie( "can not read lock after write lock" );
+        }
+
+        eval {
+            my $query = $db->prepare( $sql->increment_read_lock );
+            my $rows = $query->execute( $key );
+        
+            # if we affected more then one row something very bad has happened.
+            unless ( $rows == 1 ) {
+                $log->logdie( "affected row count is $rows instead of 1" );
+            }
+
+            $db->commit;
+        };
+        if ( $@ ) {
+            $db->rollback;
+            $log->logdie( "database error: $@" );
+        }
+
+        $log->debug( "leaving" );
+
+        return 1;
+    }
+
+    # never reached
+    $log->logdie( "this should never happen" );
+}
+
+sub unlock_object {
+    my $self = shift;
+
+    $log->debug( "entered - @_" );
+
+    my ( $key, $type ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is read or write' => sub { $_[0] =~ /^(?:read|write)$/ },
+            },
+        },
+    );
+
+    my $so_id;
+    my $read_lock;
+    my $write_lock;
+
+    eval {
+        # this will set update locks
+        my $query = $db->prepare( $sql->get_object_locks );
+        my $rows = $query->execute( $key );
+        unless ( $rows == 1 ) {
+            $log->logdie( "storage object does not exist" );
+        }
+
+        my $row = $query->fetchrow_hashref;
+
+        $so_id      = $row->{ 'so_id' };
+        $read_lock  = $row->{ 'read_lock' };
+        $write_lock = $row->{ 'write_lock' };
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->logdie( "database error: $@" );
+    }
+
+    if ( $type eq 'write' ) {
+        # can't remove a write lock if it doesn't exist
+        if ( $read_lock ) {
+            eval { $db->rollback; };
+            $log->logdie( "database error: $@" ) if $@;
+           
+            $log->logdie( "can not have a write lock under a read lock" );
+        }
+        unless ( $write_lock ) {
+            eval { $db->rollback; };
+            $log->logdie( "database error: $@" ) if $@;
+
+            $log->logdie( "can not remove non-existant write lock" );
+        }
+
+        eval {
+            my $query = $db->prepare( $sql->delete_write_lock );
+            my $rows = $query->execute( $key );
+        
+            # if we affected more then one row something very bad has happened.
+            unless ( $rows == 1 ) {
+                $log->logdie( "affected row count is $rows instead of 1" );
+            }
+
+            $db->commit;
+        };
+        if ( $@ ) {
+            $db->rollback;
+            $log->logdie( "database error: $@" );
+        }
+
+        $log->debug( "leaving" );
+
+        return 1;
+    }
+
+    if ( $type eq 'read' ) {
+        # can't remove a read lock if there's a write lock and
+        # can't remove a read lock if there aren't any
+        if ( $write_lock ) {
+            eval { $db->rollback; };
+            $log->logdie( "database error: $@" ) if $@;
+           
+            $log->logdie( "can not have a read lock under a write lock" );
+        }
+           
+        if ( $read_lock == 0 ) {
+            eval { $db->rollback; };
+            $log->logdie( "database error: $@" ) if $@;
+           
+            $log->logdie( "can not remove non-existant read lock" );
+        }
+
+        eval {
+            my $query = $db->prepare( $sql->decrement_read_lock );
+            my $rows = $query->execute( $key );
+        
+            # if we affected more then one row something very bad has happened.
+            unless ( $rows == 1 ) {
+
+                $log->logdie( "affected row count is $rows instead of 1" );
+            }
+
+            $db->commit;
+        };
+        if ( $@ ) {
+            $db->rollback;
+            $log->logdie( "database error: $@" );
+        }
+
+        $log->debug( "leaving" );
+
+        return 1;
+    }
+
+    # never reached
+    $log->logdie( "this should never happen" );
+}
+
+
+sub find_instances {
+    my $self = shift;
+
+    $log->debug( "entered - @_" );
+
+    my ( $key, $volume ) = validate_pos( @_,
+        {
+            type        => SCALAR,
+        },
+        {
+            type        => SCALAR,
+            optional    => 1,
+        },
+    );
+
+    # TODO restrict search to a volume
+
+    my $query;
+
+    eval {
+        $query = $db->prepare( $sql->get_object_instances );
+        $query->execute( $key );
+    };
+    $log->logdie( "database error: $@" ) if $@;
+
+    my @locations;
+
+    while ( my $row = $query->fetchrow_hashref ) {
+        my $instance = $row->{ 'uri' };
+        push @locations, $instance if $instance;
+    }
+
+    $log->logdie( "no instances found" ) unless ( scalar @locations );
+
+    $log->debug( "leaving" );
+
+    return \@locations;
+}
+
+sub delete_instance {
+    my $self = shift;
+
+    $log->debug( "entered - @_" );
+
+    my ( $uri ) = validate_pos( @_,
+        {
+            type => SCALAR,
+        },
+    );
+
+    eval {
+        my $so_id;
+        my $instances;
+        # get so_id
+        {
+            my $query = $db->prepare( $sql->get_object_from_uri );
+            my $rows = $query->execute( $uri );
+
+            unless ( $rows > 0 ) {
+                $log->logdie( "no instance is associated with uri" );
+            }
+
+            $so_id = $query->fetchrow_hashref->{ 'so_id' };
+        }
+
+        {
+            my $query = $db->prepare( $sql->get_instance_count );
+            $query->execute( $so_id );
+
+            $instances = $query->fetchrow_hashref->{ 'count(ins_id)' };
+        }
+
+        # remove instance
+        {
+            my $query = $db->prepare( $sql->delete_instance );
+            my $rows = $query->execute( $uri );
+            
+            # if we affected something other then one row something very bad has happened
+            unless ( $rows == 1 ) {
+                $log->logdie( "affected row count is $rows instead of 1" );
+            }
+        }
+
+        # if we just deleted the last instance associated with a storage object
+        # remove it too
+        if ( $instances == 1 ) {
+            # we just removed the last instance
+            my $query = $db->prepare( $sql->delete_object );
+            my $rows = $query->execute( $so_id );
+
+            # if we affected something other then one row something very bad has happened
+            unless ( $rows == 1 ) {
+                $log->logdie( "affected row count is $rows instead of 1" );
+            }
+        }
+
+        $db->commit;
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->logdie( "database error: $@" );
+    }
+
+    $log->debug( "leaving" );
+
+    return 1;
+}
+
+sub stat_object {
+    my $self = shift;
+
+    $log->debug( "entered - @_" );
+
+    my ( $key ) = validate_pos( @_,
+        {
+            type => SCALAR,
+        },
+    );
+
+    my $stat;
+    eval {
+        my $query = $db->prepare( $sql->get_object );
+        my $rows = $query->execute( $key );
+
+        unless ( $rows == 1 ) {
+            $log->logdie( "no storage object found" );
+        }
+
+        $stat = $query->fetchrow_arrayref;
+
+        $db->commit;
+    };
+    if ( $@ ) {
+        $db->rollback;
+        $log->logdie( "database error: $@" );
+    }
+
+    $log->debug( "leaving" );
+
+    return $stat;
+}
+
+sub _get_storage_volume {
+    $log->debug( "entered - @_" );
+
+    my $name = shift;
+
+    my $volume;
+    {
+        my $query;
+        eval {
+            # TODO cache this?
+            my $rows;
+            if ( $name ) {
+                $query = $db->prepare( qq{ SELECT uri FROM volume WHERE name = ? ORDER BY rand() LIMIT 1 } );
+                $rows = $query->execute( $name );
+            } else {
+                $query = $db->prepare( qq{ SELECT uri FROM volume ORDER BY rand() LIMIT 1 } );
+                $rows = $query->execute;
+            }
+
+            # there has to be atleast one storage volume
+            unless ( $rows > 0 ) {
+                $db->rollback;
+
+                $log->logdie( "affected row count is $rows instead of 1" );
+            } else {
+                $db->commit;
+            }
+        };
+        $log->logdie( "database error: $@" ) if $@;
+
+        $volume = $query->fetchrow_hashref->{ 'uri' };
+    }
+
+    $log->debug( "leaving" );
+
+    return $volume;
+}
+
+1;
+
+__END__
Index: /tags/start/Nebulous/lib/Nebulous/Server/Apache.pm
===================================================================
--- /tags/start/Nebulous/lib/Nebulous/Server/Apache.pm	(revision 12606)
+++ /tags/start/Nebulous/lib/Nebulous/Server/Apache.pm	(revision 12606)
@@ -0,0 +1,21 @@
+# Copyright (C) 2004  Joshua Hoblitt
+#
+# $Id
+
+package PS::IPP::IData::Server::Apache;
+
+use strict;
+
+our $VERSION = 0.01;
+
+use SOAP::Transport::HTTP;
+
+my $server = SOAP::Transport::HTTP::Apache
+    ->dispatch_to( 'PS::IPP::IData::Server' )
+    ->options({ compress_threshold => 10 * 1024 });
+
+sub handler { $server->handler(@_); }
+
+1;
+
+__END__
Index: /tags/start/Nebulous/lib/Nebulous/Server/Log.pm
===================================================================
--- /tags/start/Nebulous/lib/Nebulous/Server/Log.pm	(revision 12606)
+++ /tags/start/Nebulous/lib/Nebulous/Server/Log.pm	(revision 12606)
@@ -0,0 +1,27 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: Log.pm,v 1.1.1.1 2004-12-22 02:16:24 jhoblitt Exp $
+
+package PS::IPP::IData::Server::Log;
+
+use strict;
+
+our $VERSION = '0.01';
+
+use Log::Log4perl;
+                                                                                                                                          
+my $conf = q(
+    log4perl.category.PS.IPP.IData.Server = DEBUG, SERVERLOGFILE
+
+    log4perl.appender.SERVERLOGFILE           = Log::Log4perl::Appender::File
+    log4perl.appender.SERVERLOGFILE.filename  = /tmp/idata_server.log
+    log4perl.appender.SERVERLOGFILE.mode      = append
+    log4perl.appender.SERVERLOGFILE.layout    = Log::Log4perl::Layout::PatternLayout
+    log4perl.appender.SERVERLOGFILE.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} | %H | %p | %M - %m%n
+);
+                                                                                                                          
+Log::Log4perl::init( \$conf );
+
+1;
+
+__END__
Index: /tags/start/Nebulous/lib/Nebulous/Server/SQL.pm
===================================================================
--- /tags/start/Nebulous/lib/Nebulous/Server/SQL.pm	(revision 12606)
+++ /tags/start/Nebulous/lib/Nebulous/Server/SQL.pm	(revision 12606)
@@ -0,0 +1,107 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: SQL.pm,v 1.1.1.1 2004-12-22 02:16:24 jhoblitt Exp $
+
+package PS::IPP::IData::Server::SQL;
+
+use strict;
+
+our $VERSION = '0.01';
+
+use base qw( Class::Accessor::Fast );
+
+my %sql = (
+    set_transaction_model   => qq{
+        SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
+    },
+    update_instance_uri => qq{
+        UPDATE instance SET uri = ? WHERE ins_id = ?
+    },
+    last_insert_id      => qq{
+        SELECT LAST_INSERT_ID()
+    },
+    new_object          => qq{
+        INSERT INTO storage_object
+        VALUES (NULL, ?, ?, ?, 0, NULL, NULL)
+    },
+    delete_object       => qq{
+        DELETE FROM storage_object
+        WHERE so_id = ?
+    },
+    new_object_instance  => qq{
+        INSERT INTO instance 
+        VALUES (NULL, LAST_INSERT_ID(), 'error', NULL, NULL, NULL, NULL)
+    },
+    new_instance        => qq{
+        INSERT INTO instance
+        VALUES (NULL, ?, 'error', NULL,NULL, NULL, NULL)
+    },
+    get_object          => qq{
+        SELECT *
+        FROM storage_object
+        WHERE ext_id = ?
+    },
+    get_object_locks    => qq{
+        SELECT so_id, read_lock, write_lock 
+        FROM storage_object
+        WHERE ext_id = ?
+        FOR UPDATE
+    },
+    set_write_lock      => qq{
+        UPDATE storage_object
+        SET write_lock = 'write'
+        WHERE ext_id = ?
+    },
+    delete_write_lock   => qq{
+        UPDATE storage_object
+        SET write_lock = NULL
+        WHERE ext_id = ?
+    },
+    increment_read_lock => qq{
+        UPDATE storage_object
+        SET read_lock = read_lock+1
+        WHERE ext_id = ?
+    },
+    decrement_read_lock => qq{
+        UPDATE storage_object
+        SET read_lock = read_lock-1
+        WHERE ext_id = ?
+    },
+    delete_instance     => qq{
+        DELETE FROM instance
+        WHERE uri = ?
+    },
+    get_object_from_uri   => qq{
+        SELECT so_id
+        FROM instance
+        WHERE uri = ?
+    },
+    get_instance_count   => qq{
+        SELECT count(ins_id)
+        FROM instance
+        WHERE so_id = ?
+    },
+    get_object_instances    => qq{
+        SELECT storage_object.so_id, uri, assigned_location
+        FROM storage_object
+        LEFT JOIN instance
+        USING (so_id)
+        WHERE storage_object.ext_id = ?
+    },
+);
+
+__PACKAGE__->mk_ro_accessors( keys %sql );
+
+sub new {
+    my $class = shift;
+
+    my $self = \%sql;
+
+    bless $self, $class || ref $class;
+
+    return $self;
+}
+
+1;
+
+__END__
Index: /tags/start/Nebulous/lib/Nebulous/Util.pm
===================================================================
--- /tags/start/Nebulous/lib/Nebulous/Util.pm	(revision 12606)
+++ /tags/start/Nebulous/lib/Nebulous/Util.pm	(revision 12606)
@@ -0,0 +1,104 @@
+# Copyright (c) 2004  Joshua Hoblitt
+#
+# $Id: Util.pm,v 1.1.1.1 2004-12-22 02:16:24 jhoblitt Exp $
+
+package PS::IPP::IData::Util;
+
+use strict;
+
+our $VERSION = '0.01';
+
+use base qw( Exporter );
+
+use Log::Log4perl qw( :levels );
+use URI;
+
+my @symbols = qw(
+    %LEVELS
+    _nuke_file
+    _get_file_path
+    _get_filehandle
+    _open_uri
+    _create_empty_file
+);
+
+our @EXPORT_OK      = @symbols;
+our %EXPORT_TAGS    = ( standard => [ @symbols ] );
+
+our %LEVELS = (
+    off     => $OFF,
+    fatal   => $FATAL,
+    error   => $ERROR,
+    warn    => $WARN,
+    info    => $INFO,
+    debug   => $DEBUG,
+    all     => $ALL,
+);
+
+sub _nuke_file {
+    my $path = shift;
+
+    die "can't unlink file $path: it's a directory" 
+        if -d $path;
+    die "can't unlink file $path: it doesn't exist"
+        unless -e $path;
+    unlink $path or die "can't unlink file $path: $!";
+
+    return 1;
+}
+
+sub _get_file_path {
+    my $uri = shift;
+
+    my $path = URI->new( $uri )->path;
+
+    return $path;
+}
+
+sub _get_filehandle {
+    my ( $path, $flags ) = @_;
+
+    die "can't open file $path: file doesn't exist" 
+        unless -e $path;
+    CORE::open( my $fh, $flags, $path )
+        or die "can't open file $path: $!";
+
+    return $fh;
+}
+
+sub _open_uri {
+    my ( $uri , $flags ) = @_;
+
+    my $path = _get_file_path( $uri );
+    my $fh = _get_filehandle( $path, $flags );
+
+    return $fh;
+}
+
+sub _create_empty_file {
+    my $path = shift;
+
+    # perl's open() can't do an O_CREAT | O_EXCL
+    if ( -e $path ) {
+        die "file $path already exists";
+    }
+
+    my $fh;
+    unless ( open( $fh, '>', $path ) ) {
+        die "can not open $path: $!";
+    } 
+
+    unless ( close( $fh ) ) {
+        die "can not close $path: $!";
+    }
+
+    unless ( chmod 0664, $path ) {
+        die "can not chmod $path: $!";
+    }
+
+    return $path;
+}
+
+1;
+
+__END__
Index: /tags/start/Nebulous/nebclient/tests/tap/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/.cvsignore	(revision 12606)
@@ -0,0 +1,13 @@
+.in
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+config.log
+config.status
+configure
+libtool
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/INSTALL
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/INSTALL	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/INSTALL	(revision 12606)
@@ -0,0 +1,8 @@
+Quick Installation
+
+    ./configure
+    make
+    make check
+    make install
+
+Run "configure --help" for additional options.
Index: /tags/start/Nebulous/nebclient/tests/tap/LICENSE
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/LICENSE	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/LICENSE	(revision 12606)
@@ -0,0 +1,23 @@
+Copyright (c) 2004 Nik Clayton
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
Index: /tags/start/Nebulous/nebclient/tests/tap/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/Makefile.am	(revision 12606)
@@ -0,0 +1,5 @@
+SUBDIRS  = src
+#SUBDIRS += tests
+
+prove:
+	prove -v -r
Index: /tags/start/Nebulous/nebclient/tests/tap/README
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/README	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/README	(revision 12606)
@@ -0,0 +1,11 @@
+NAME
+     tap -- write tests that implement the Test Anything Protocol
+
+SYNOPSIS
+     #include <tap.h>
+
+DESCRIPTION
+     The tap library provides functions for writing test scripts that produce
+     output consistent with the Test Anything Protocol.  A test harness that
+     parses this protocol can run these tests and produce useful reports indi-
+     cating their success or failure.
Index: /tags/start/Nebulous/nebclient/tests/tap/bootstrap.sh
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/bootstrap.sh	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/bootstrap.sh	(revision 12606)
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+set -x
+aclocal19 -I /usr/local/share/aclocal || aclocal || exit 1
+autoheader259 || autoheader || exit 1
+libtoolize15 -c -f || libtoolize -c -f || glibtoolize -c -f || exit 1
+automake19 -a -c || automake -a -c || exit 1
+autoconf259 || autoconf || exit 1
Index: /tags/start/Nebulous/nebclient/tests/tap/compile
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/compile	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/compile	(revision 12606)
@@ -0,0 +1,142 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand `-c -o'.
+
+scriptversion=2004-10-12.08
+
+# Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+case $1 in
+  '')
+     echo "$0: No command.  Try \`$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand `-c -o'.
+Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file `INSTALL'.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit 0
+    ;;
+  -v | --v*)
+    echo "compile $scriptversion"
+    exit 0
+    ;;
+esac
+
+ofile=
+cfile=
+eat=
+
+for arg
+do
+  if test -n "$eat"; then
+    eat=
+  else
+    case $1 in
+      -o)
+	# configure might choose to run compile as `compile cc -o foo foo.c'.
+	# So we strip `-o arg' only if arg is an object.
+	eat=1
+	case $2 in
+	  *.o | *.obj)
+	    ofile=$2
+	    ;;
+	  *)
+	    set x "$@" -o "$2"
+	    shift
+	    ;;
+	esac
+	;;
+      *.c)
+	cfile=$1
+	set x "$@" "$1"
+	shift
+	;;
+      *)
+	set x "$@" "$1"
+	shift
+	;;
+    esac
+  fi
+  shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+  # If no `-o' option was seen then we might have been invoked from a
+  # pattern rule where we don't need one.  That is ok -- this is a
+  # normal compilation that the losing compiler can handle.  If no
+  # `.c' file was seen then we are probably linking.  That is also
+  # ok.
+  exec "$@"
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use `[/.-]' here to ensure that we don't use the same name
+# that we are using for the .o file.  Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d
+while true; do
+  if mkdir "$lockdir" >/dev/null 2>&1; then
+    break
+  fi
+  sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir '$lockdir'; exit 1" 1 2 15
+
+# Run the compile.
+"$@"
+ret=$?
+
+if test -f "$cofile"; then
+  mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+  mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
Index: /tags/start/Nebulous/nebclient/tests/tap/configure.in
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/configure.in	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/configure.in	(revision 12606)
@@ -0,0 +1,44 @@
+AC_INIT(tap, 1.01)
+AC_CONFIG_SRCDIR(src/tap.c)
+AM_INIT_AUTOMAKE([foreign])
+AC_CONFIG_HEADERS([src/config.h])
+AC_GNU_SOURCE
+AC_PROG_CC
+AC_PROG_LIBTOOL
+AC_PROG_INSTALL
+
+# Checks for libraries
+case "$host" in
+	*-*-*freebsd4*)
+		LDFLAGS="$LDFLAGS -pthread"
+		HAVE_LIBPTHREAD=1
+		;;
+	*)
+		AC_CHECK_LIB(pthread, main)
+		;;
+esac
+
+dnl build tests at the same time as the source code
+AC_ARG_ENABLE(tests,
+  [AS_HELP_STRING(--enable-tests,build tests at same time as source)],
+  [AC_MSG_RESULT(test building enabled)
+   tests=true],
+   [tests=false])
+AM_CONDITIONAL(BUILD_TESTS, test x$tests = xtrue)
+
+# Checks for header files
+AC_HEADER_STDC
+AC_CHECK_HEADERS([stdlib.h])
+AC_CHECK_HEADERS([pthread.h])
+
+# Checks for  typedefs, structures, and compiler characteristics.
+AC_C_CONST
+
+# Checks for library functions.
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS([atexit])
+
+AC_CONFIG_FILES([Makefile
+		 src/Makefile
+		])
+AC_OUTPUT
Index: /tags/start/Nebulous/nebclient/tests/tap/src/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/src/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/src/.cvsignore	(revision 12606)
@@ -0,0 +1,13 @@
+.deps
+.libs
+Makefile
+Makefile.in
+libtap.la
+tap.lo
+config.h
+config.h.in
+stamp-h1
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/src/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/src/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/src/Makefile.am	(revision 12606)
@@ -0,0 +1,9 @@
+TEST_LTLIBS = libtap.la
+libtap_la_SOURCES = tap.c tap.h
+noinst_HEADERS = tap.h
+
+noinst_LTLIBRARIES = $(TEST_LTLIBS)
+
+#man_MANS = tap.3
+EXTRA_DIST = $(man_MANS)
+
Index: /tags/start/Nebulous/nebclient/tests/tap/src/tap.3
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/src/tap.3	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/src/tap.3	(revision 12606)
@@ -0,0 +1,380 @@
+.Dd December 20, 2004
+.Os
+.Dt TAP 3
+.Sh NAME
+.Nm tap
+.Nd write tests that implement the Test Anything Protocol
+.Sh SYNOPSIS
+.In tap.h
+.Sh DESCRIPTION
+The
+.Nm
+library provides functions for writing test scripts that produce output
+consistent with the Test Anything Protocol.  A test harness that parses
+this protocol can run these tests and produce useful reports indicating
+their success or failure.
+.Ss PRINTF STRINGS
+In the descriptions that follow, for any function that takes as the
+last two parameters
+.Dq Fa char * , Fa ...
+it can be assumed that the
+.Fa char *
+is a
+.Fn printf
+-like format string, and the optional arguments are values to be placed
+in that string.
+.Ss TEST PLANS
+.Bl -tag -width indent
+.It Xo
+.Ft int
+.Fn plan_tests "unsigned int"
+.Xc
+.It Xo
+.Ft int
+.Fn plan_no_plan "void"
+.Xc
+.It Xo
+.Ft int
+.Fn plan_skip_all "char *" "..."
+.Xc
+.El
+.Pp
+You must first specify a test plan.  This indicates how many tests you
+intend to run, and allows the test harness to notice if any tests were
+missed, or if the test program exited prematurely.
+.Pp
+To do this, use
+.Fn plan_tests ,
+which returns the number of planned tests.  The function will cause
+your program to exit prematurely if you specify 0 tests.
+.Pp
+In some situations you may not know how many tests you will be running, or
+you are developing your test program, and do not want to update the
+.Fn plan_tests
+parameter every time you make a change.  For those situations use
+.Fn plan_no_plan .
+It returns 1, and indicates to the test harness that an indeterminate number
+of tests will be run.
+.Pp
+Both
+.Fn plan_tests
+and
+.Fn plan_no_plan
+will cause your test program to exit prematurely with a diagnostic
+message if they are called more than once.
+.Pp
+If your test program detects at run time that some required functionality
+is missing (for example, it relies on a database connection which is not
+present, or a particular configuration option that has not been included
+in the running kernel) use
+.Fn plan_skip_all ,
+passing as parameters a string to display indicating the reason for skipping
+the tests.
+.Ss SIMPLE TESTS
+.Bl -tag -width indent
+.It Xo
+.Ft unsigned int
+.Fn ok "expression" "char *" "..."
+.Xc
+.It Xo
+.Ft unsigned int
+.Fn ok1 "expression"
+.Xc
+.It Xo
+.Ft unsigned int
+.Fn pass "char *" "..."
+.Xc
+.It Xo
+.Ft unsigned int
+.Fn fail "char *" "..."
+.Xc
+.El
+.Pp
+Tests are implemented as expressions checked by calls to the
+.Fn ok
+and
+.Fn ok1
+macros.  In both cases
+.Fa expression
+should evaluate to true if the test succeeded.
+.Pp
+.Fn ok
+allows you to specify a name, or comment, describing the test which will
+be included in the output.
+.Fn ok1
+is for those times when the expression to be tested is self
+explanatory and does not need an associated comment.  In those cases
+the test expression becomes the comment.
+.Pp
+These four calls are equivalent:
+.Bd -literal -offset indent
+int i = 5;
+
+ok(i == 5, "i equals 5");      /* Overly verbose */
+ok(i == 5, "i equals %d", i);  /* Just to demonstrate printf-like
+                                  behaviour of the test name */
+ok(i == 5, "i == 5");          /* Needless repetition */
+ok1(i == 5);                   /* Just right */
+.Ed
+.Pp
+It is good practice to ensure that the test name describes the meaning
+behind the test rather than what you are testing.  Viz
+.Bd -literal -offset indent
+ok(db != NULL, "db is not NULL");            /* Not bad, but */
+ok(db != NULL, "Database conn. succeeded");  /* this is better */
+.Ed
+.Pp
+.Fn ok
+and
+.Fn ok1
+return 1 if the expression evaluated to true, and 0 if it evaluated to
+false.  This lets you chain calls from
+.Fn ok
+to
+.Fn diag
+to only produce diagnostic output if the test failed.  For example, this
+code will include diagnostic information about why the database connection
+failed, but only if the test failed.
+.Bd -literal -offset indent
+ok(db != NULL, "Database conn. succeeded") ||
+    diag("Database error code: %d", dberrno);
+.Ed
+.Pp
+You also have
+.Fn pass
+and
+.Fn fail .
+From the Test::More documentation:
+.Bd -literal -offset indent
+Sometimes you just want to say that the tests have passed.
+Usually the case is you've got some complicated condition
+that is difficult to wedge into an ok().  In this case,
+you can simply use pass() (to declare the test ok) or fail
+(for not ok).
+
+Use these very, very, very sparingly.
+.Ed
+.Pp
+These are synonyms for ok(1, ...) and ok(0, ...).
+.Ss SKIPPING TESTS
+.Bl -tag -width indent
+.It Xo
+.Ft int
+.Fn skip "unsigned int" "char *" "..."
+.Xc
+.It Xo
+.Fn skip_start "expression" "unsigned int" "char *" "..."
+.Xc
+.It Xo
+.Fn skip_end
+.Xc
+.El
+.Pp
+Sets of tests can be skipped.  Ordinarily you would do this because
+the test can't be run in this particular testing environment.
+.Pp
+For example, suppose some tests should be run as root.  If the test is
+not being run as root then the tests should be skipped.  In this 
+implementation, skipped tests are flagged as being ok, with a special
+message indicating that they were skipped.  It is your responsibility
+to ensure that the number of tests skipped (the first parameter to
+.Fn skip )
+is correct for the number of tests to skip.
+.Pp
+One way of implementing this is with a
+.Dq do { } while(0);
+loop, or an
+.Dq if( ) { } else { }
+construct, to ensure that there are no additional side effects from the
+skipped tests.
+.Bd -literal -offset indent
+if(getuid() != 0) {
+        skip(1, "because test only works as root");
+} else {
+        ok(do_something_as_root() == 0, "Did something as root");
+}
+.Ed
+.Pp
+Two macros are provided to assist with this.  The previous example could
+be re-written as follows.
+.Bd -literal -offset indent
+skip_start(getuid() != 0, 1, "because test only works as root");
+
+ok(do_something_as_root() == 0, "Did something as root");
+
+skip_end();
+.Ed
+.Ss MARKING TESTS AS Dq TODO
+.Bl -tag -width indent
+.It Xo
+.Ft void
+.Fn todo_start "char *" "..."
+.Xc
+.It Xo
+.Ft void
+.Fn todo_end "void"
+.Xc
+.El
+.Pp
+Sets of tests can be flagged as being
+.Dq TODO .
+These are tests that you expect to fail, probably because you haven't
+fixed a bug, or finished a new feature yet.  These tests will still be
+run, but with additional output that indicates that they are expected
+to fail.  Should a test start to succeed unexpectedly, tools like
+.Xr prove 1
+will indicate this, and you can move the test out of the todo
+block.  This is much more useful than simply commenting out (or
+.Dq #ifdef 0 ... #endif )
+the tests.
+.Bd -literal -offset indent
+todo_start("dwim() not returning true yet");
+
+ok(dwim(), "Did what the user wanted");
+
+todo_end();
+.Ed
+.Pp
+Should
+.Fn dwim
+ever start succeeding you will know about it as soon as you run the
+tests.  Note that
+.Em unlike
+the
+.Fn skip_*
+family, additional code between
+.Fn todo_start
+and
+.Fn todo_end
+.Em is
+executed.
+.Ss SKIP vs. TODO
+From the Test::More documentation;
+.Bd -literal -offset indent
+If it's something the user might not be able to do, use SKIP.
+This includes optional modules that aren't installed, running
+under an OS that doesn't have some feature (like fork() or
+symlinks), or maybe you need an Internet connection and one
+isn't available.
+
+If it's something the programmer hasn't done yet, use TODO.
+This is for any code you haven't written yet, or bugs you have
+yet to fix, but want to put tests in your testing script 
+(always a good idea).
+.Ed
+.Ss DIAGNOSTIC OUTPUT
+.Bl -tag -width indent
+.It Xo
+.Fr unsigned int
+.Fn diag "char *" "..."
+.Xc
+.El
+.Pp
+If your tests need to produce diagnostic output, use
+.Fn diag .
+It ensures that the output will not be considered by the TAP test harness.
+.Fn diag
+adds the necessary trailing
+.Dq \en
+for you.
+.Bd -literal -offset indent
+diag("Expected return code 0, got return code %d", rcode);
+.Ed
+.Pp
+.Fn diag
+always returns 0.
+.Ss EXIT STATUS
+.Bl -tag -width indent
+.It Xo
+.Fr int
+.Fn exit_status void
+.Xc
+.El
+.Pp
+For maximum compatability your test program should return a particular
+exit code.  This is calculated by
+.Fn exit_status
+so it is sufficient to always return from
+.Fn main
+with either
+.Dq return exit_status();
+or
+.Dq exit(exit_status());
+as appropriate.
+.Sh ENVIRONMENT
+The following environment variables affect
+.Nm .
+.Bl -tag -width indent
+.It Ev HARNESS_ACTIVE
+Causes an extra
+.Dq \en
+to be printed before any diagnostic failure output generated by
+.Nm .
+This variable is normally set if tests are being run under Perl's
+Test::Harness.
+.El
+.Sh EXAMPLES
+The
+.Pa tests
+directory in the source distribution contains numerous tests of
+.Nm
+functionality, written using
+.Nm .
+Examine them for examples of how to construct test suites.
+.Sh COMPATABILITY
+.Nm
+strives to be compatible with the Perl Test::More and Test::Harness 
+modules.  The test suite verifies that
+.Nm
+is bug-for-bug compatible with their behaviour.  This is why some
+functions which would more naturally return nothing return constant
+values.
+.Pp
+If the
+.Lb libpthread
+is found at compile time,
+.Nm
+.Em should
+be thread safe.  Indications to the contrary (and test cases that expose
+incorrect behaviour) are very welcome.
+.Sh SEE ALSO
+.Xr Test::More 1 ,
+.Xr Test::Harness 1 ,
+.Xr prove 1
+.Sh STANDARDS
+.Nm
+requires a
+.St -isoC-99
+compiler.  Some of the
+.Nm
+functionality is implemented as variadic macros, and that functionality
+was not formally codified until C99.  Patches to use
+.Nm
+with earlier compilers that have their own implementation of variadic
+macros will be gratefully received.
+.Sh HISTORY
+.Nm
+was written to help improve the quality and coverage of the FreeBSD
+regression test suite, and released in the hope that others find it
+a useful tool to help improve the quality of their code.
+.Sh AUTHORS
+.An "Nik Clayton" Aq nik@ngo.org.uk ,
+.Aq nik@FreeBSD.org
+.Pp
+.Nm
+would not exist without the efforts of
+.An "Michael G Schwern" Aq schqern@pobox.com ,
+.An "Andy Lester" Aq andy@petdance.com ,
+and the countless others who have worked on the Perl QA programme.
+.Sh BUGS
+Ideally, running the tests would have no side effects on the behaviour
+of the application you are testing.  However, it is not always possible
+to avoid them.  The following side effects of using
+.Nm
+are known.
+.Bl -bullet -offset indent
+.It
+stdout is set to unbuffered mode after calling any of the
+.Fn plan_*
+functions.
+.El
Index: /tags/start/Nebulous/nebclient/tests/tap/src/tap.c
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/src/tap.c	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/src/tap.c	(revision 12606)
@@ -0,0 +1,430 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "tap.h"
+
+static int no_plan = 0;
+static int skip_all = 0;
+static int have_plan = 0;
+static unsigned int test_count = 0; /* Number of tests that have been run */
+static unsigned int e_tests = 0; /* Expected number of tests to run */
+static unsigned int failures = 0; /* Number of tests that failed */
+static char *todo_msg = NULL;
+static char *todo_msg_fixed = "libtap malloc issue";
+static int todo = 0;
+static int test_died = 0;
+
+/* Encapsulate the pthread code in a conditional.  In the absence of
+   libpthread the code does nothing */
+#ifdef HAVE_LIBPTHREAD
+#include <pthread.h>
+static pthread_mutex_t M = PTHREAD_MUTEX_INITIALIZER;
+# define LOCK pthread_mutex_lock(&M);
+# define UNLOCK pthread_mutex_unlock(&M);
+#else
+# define LOCK
+# define UNLOCK
+#endif
+
+static void _expected_tests(unsigned int);
+static void _tap_init(void);
+static void _cleanup(void);
+
+/*
+ * Generate a test result.
+ *
+ * ok -- boolean, indicates whether or not the test passed.
+ * test_name -- the name of the test, may be NULL
+ * test_comment -- a comment to print afterwards, may be NULL
+ */
+unsigned int
+_gen_result(int ok, const char *func, char *file, unsigned int line,
+            char *test_name, ...)
+{
+    va_list ap;
+    char *local_test_name = NULL;
+    char *c;
+    int name_is_digits;
+
+    LOCK;
+
+    test_count++;
+
+    /* Start by taking the test name and performing any printf()
+       expansions on it */
+    if(test_name != NULL) {
+        va_start(ap, test_name);
+        vasprintf(&local_test_name, test_name, ap);
+        va_end(ap);
+
+        /* Make sure the test name contains more than digits
+           and spaces.  Emit an error message and exit if it
+           does */
+        if(local_test_name) {
+            name_is_digits = 1;
+            for(c = local_test_name; *c != '\0'; c++) {
+                if(!isdigit(*c) && !isspace(*c)) {
+                    name_is_digits = 0;
+                    break;
+                }
+            }
+
+            if(name_is_digits) {
+                diag("    You named your test '%s'.  You shouldn't use numbers for your test names.", local_test_name);
+                diag("    Very confusing.");
+            }
+        }
+    }
+
+    if(!ok) {
+        printf("not ");
+        failures++;
+    }
+
+    printf("ok %d", test_count);
+
+    if(test_name != NULL) {
+        printf(" - ");
+
+        /* Print the test name, escaping any '#' characters it
+           might contain */
+        if(local_test_name != NULL) {
+            flockfile(stdout);
+            for(c = local_test_name; *c != '\0'; c++) {
+                if(*c == '#')
+                    fputc('\\', stdout);
+                fputc((int)*c, stdout);
+            }
+            funlockfile(stdout);
+        } else { /* vasprintf() failed, use a fixed message */
+            printf("%s", todo_msg_fixed);
+        }
+    }
+
+    /* If we're in a todo_start() block then flag the test as being
+       TODO.  todo_msg should contain the message to print at this
+       point.  If it's NULL then asprintf() failed, and we should
+       use the fixed message.
+
+       This is not counted as a failure, so decrement the counter if
+       the test failed. */
+    if(todo) {
+        printf(" # TODO %s", todo_msg ? todo_msg : todo_msg_fixed);
+        if(!ok)
+            failures--;
+    }
+
+    printf("\n");
+
+    if(!ok) {
+        if(getenv("HARNESS_ACTIVE") != NULL)
+            fputs("\n", stderr);
+
+        diag("    Failed %stest (%s:%s() at line %d)",
+             todo ? "(TODO) " : "", file, func, line);
+    }
+    free(local_test_name);
+
+    UNLOCK;
+
+    /* We only care (when testing) that ok is positive, but here we
+       specifically only want to return 1 or 0 */
+    return ok ? 1 : 0;
+}
+
+/*
+ * Initialise the TAP library.  Will only do so once, however many times it's
+ * called.
+ */
+void
+_tap_init(void)
+{
+    static int run_once = 0;
+
+    if(!run_once) {
+        atexit(_cleanup);
+
+        /* stdout needs to be unbuffered so that the output appears
+           in the same place relative to stderr output as it does 
+           with Test::Harness */
+        setbuf(stdout, 0);
+        run_once = 1;
+    }
+}
+
+/*
+ * Note that there's no plan.
+ */
+int
+plan_no_plan(void)
+{
+
+    LOCK;
+
+    _tap_init();
+
+    if(have_plan != 0) {
+        fprintf(stderr, "You tried to plan twice!\n");
+        test_died = 1;
+        UNLOCK;
+        exit(255);
+    }
+
+    have_plan = 1;
+    no_plan = 1;
+
+    UNLOCK;
+
+    return 1;
+}
+
+/*
+ * Note that the plan is to skip all tests
+ */
+int
+plan_skip_all(char *reason)
+{
+
+    LOCK;
+
+    _tap_init();
+
+    skip_all = 1;
+
+    printf("1..0");
+
+    if(reason != NULL)
+        printf(" # Skip %s", reason);
+
+    printf("\n");
+
+    UNLOCK;
+
+    exit(0);
+}
+
+/*
+ * Note the number of tests that will be run.
+ */
+int
+plan_tests(unsigned int tests)
+{
+
+    LOCK;
+
+    _tap_init();
+
+    if(have_plan != 0) {
+        fprintf(stderr, "You tried to plan twice!\n");
+        test_died = 1;
+        UNLOCK;
+        exit(255);
+    }
+
+    if(tests == 0) {
+        fprintf(stderr, "You said to run 0 tests!  You've got to run something.\n");
+        test_died = 1;
+        UNLOCK;
+        exit(255);
+    }
+
+    have_plan = 1;
+
+    _expected_tests(tests);
+
+    UNLOCK;
+
+    return e_tests;
+}
+
+unsigned int
+diag(char *fmt, ...)
+{
+    va_list ap;
+
+    fputs("# ", stderr);
+
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+
+    fputs("\n", stderr);
+
+    return 0;
+}
+
+void
+_expected_tests(unsigned int tests)
+{
+
+    printf("1..%d\n", tests);
+    e_tests = tests;
+}
+
+int
+skip(unsigned int n, char *fmt, ...)
+{
+    va_list ap;
+    char *skip_msg;
+
+    LOCK;
+
+    va_start(ap, fmt);
+    asprintf(&skip_msg, fmt, ap);
+    va_end(ap);
+
+    while(n-- > 0) {
+        test_count++;
+        printf("ok %d # skip %s\n", test_count,
+               skip_msg != NULL ?
+               skip_msg : "libtap():malloc() failed");
+    }
+
+    free(skip_msg);
+
+    UNLOCK;
+
+    return 1;
+}
+
+void
+todo_start(char *fmt, ...)
+{
+    va_list ap;
+
+    LOCK;
+
+    va_start(ap, fmt);
+    vasprintf(&todo_msg, fmt, ap);
+    va_end(ap);
+
+    todo = 1;
+
+    UNLOCK;
+}
+
+void
+todo_end(void)
+{
+
+    LOCK;
+
+    todo = 0;
+    free(todo_msg);
+
+    UNLOCK;
+}
+
+int
+exit_status(void)
+{
+    int r;
+
+    LOCK;
+
+    /* If there's no plan, just return the number of failures */
+    if(no_plan || !have_plan) {
+        UNLOCK;
+        return failures;
+    }
+
+    /* Ran too many tests?  Return the number of tests that were run
+       that shouldn't have been */
+    if(e_tests < test_count) {
+        r = test_count - e_tests;
+        UNLOCK;
+        return r;
+    }
+
+    /* Return the number of tests that failed + the number of tests
+       that weren't run */
+    r = failures + e_tests - test_count;
+    UNLOCK;
+
+    return r;
+}
+
+/*
+ * Cleanup at the end of the run, produce any final output that might be
+ * required.
+ */
+void
+_cleanup(void)
+{
+
+    LOCK;
+
+    /* If plan_no_plan() wasn't called, and we don't have a plan,
+       and we're not skipping everything, then something happened
+       before we could produce any output */
+    if(!no_plan && !have_plan && !skip_all) {
+        diag("Looks like your test died before it could output anything.");
+        UNLOCK;
+        return;
+    }
+
+    if(test_died) {
+        diag("Looks like your test died just after %d.", test_count);
+        UNLOCK;
+        return;
+    }
+
+
+    /* No plan provided, but now we know how many tests were run, and can
+       print the header at the end */
+    if(!skip_all && (no_plan || !have_plan)) {
+        printf("1..%d\n", test_count);
+    }
+
+    if((have_plan && !no_plan) && e_tests < test_count) {
+        diag("Looks like you planned %d %s but ran %d extra.",
+             e_tests, e_tests == 1 ? "test" : "tests", test_count - e_tests);
+        UNLOCK;
+        return;
+    }
+
+    if((have_plan || !no_plan) && e_tests > test_count) {
+        diag("Looks like you planned %d %s but only ran %d.",
+             e_tests, e_tests == 1 ? "test" : "tests", test_count);
+        UNLOCK;
+        return;
+    }
+
+    if(failures)
+        diag("Looks like you failed %d %s of %d.",
+             failures, failures == 1 ? "test" : "tests", test_count);
+
+    UNLOCK;
+}
Index: /tags/start/Nebulous/nebclient/tests/tap/src/tap.h
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/src/tap.h	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/src/tap.h	(revision 12606)
@@ -0,0 +1,89 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* '## __VA_ARGS__' is a gcc'ism. C99 doesn't allow the token pasting
+   and requires the caller to add the final comma if they've ommitted
+   the optional arguments */
+#ifdef __GNUC__
+# define ok(e, test, ...) ((e) ?					\
+			   _gen_result(1, __func__, __FILE__, __LINE__,	\
+				       test, ## __VA_ARGS__) :		\
+			   _gen_result(0, __func__, __FILE__, __LINE__,	\
+				       test, ## __VA_ARGS__))
+
+# define ok1(e) ((e) ?							\
+		 _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \
+		 _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e))
+
+# define pass(test, ...) ok(1, test, ## __VA_ARGS__);
+# define fail(test, ...) ok(0, test, ## __VA_ARGS__);
+
+# define skip_start(test, n, fmt, ...)			\
+	do {						\
+		if((test)) {				\
+			skip(n, fmt, ## __VA_ARGS__);	\
+			continue;			\
+		}
+#elif __STDC_VERSION__ >= 199901L /* __GNUC__ */
+# define ok(e, ...) ((e) ?						\
+		     _gen_result(1, __func__, __FILE__, __LINE__,	\
+				 __VA_ARGS__) :				\
+		     _gen_result(0, __func__, __FILE__, __LINE__,	\
+				 __VA_ARGS__))
+
+# define ok1(e) ((e) ?							\
+		 _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \
+		 _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e))
+
+# define pass(...) ok(1, __VA_ARGS__);
+# define fail(...) ok(0, __VA_ARGS__);
+
+# define skip_start(test, n, ...)			\
+	do {						\
+		if((test)) {				\
+			skip(n,  __VA_ARGS__);		\
+			continue;			\
+		}
+#else /* __STDC_VERSION__ */
+# error "Needs gcc or C99 compiler for variadic macros."
+#endif /* __STDC_VERSION__ */
+
+#define skip_end() } while(0);
+
+unsigned int _gen_result(int, const char *, char *, unsigned int, char *, ...);
+
+int plan_no_plan(void);
+int plan_skip_all(char *);
+int plan_tests(unsigned int);
+
+unsigned int diag(char *, ...);
+
+int skip(unsigned int, char *, ...);
+
+void todo_start(char *, ...);
+void todo_end(void);
+
+int exit_status(void);
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/.cvsignore	(revision 12606)
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/Makefile.am	(revision 12606)
@@ -0,0 +1,7 @@
+SUBDIRS=	diag
+SUBDIRS+=	fail
+SUBDIRS+=	ok
+SUBDIRS+=	pass
+SUBDIRS+=	plan
+SUBDIRS+=	skip
+SUBDIRS+=	todo
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/README
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/README	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/README	(revision 12606)
@@ -0,0 +1,12 @@
+Most of the tests follow the same pattern.
+
+ * test.pl that uses Test::More, and demonstrates whatever functionality 
+   that we're trying to test.  This is the reference code.
+
+ * test.c, which tests the libtap reimplementation of the same functionality.
+
+ * test.t, which compiles the .c program, runs both test scripts, and then 
+   diffs their output to make sure it's identical.
+
+   Right now, test.t is identical in every directory.  This sucks somewhat.
+   It should either be a symlink to a common script
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/diag/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/diag/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/diag/.cvsignore	(revision 12606)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/diag/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/diag/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/diag/Makefile.am	(revision 12606)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/diag/test.c
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/diag/test.c	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/diag/test.c	(revision 12606)
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	plan_tests(2);
+
+	rc = diag("A diagnostic message");
+	diag("Returned: %d", rc);
+
+	/* Make sure the failure is passed through */
+	ok(1, "test 1") || diag("ok() failed, and shouldn't");
+	ok(0, "test 2") || diag("ok() passed, and shouldn't");
+
+	return exit_status();
+}
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/diag/test.pl
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/diag/test.pl	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/diag/test.pl	(revision 12606)
@@ -0,0 +1,16 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+plan tests => 2;
+
+$rc = diag("A diagnostic message");
+diag("Returned: $rc");
+
+ok(1, 'test 1') or diag "ok() failed, and shouldn't";
+ok(0, 'test 2') or diag "ok() passed, and shouldn't";
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/diag/test.t
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/diag/test.t	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/diag/test.t	(revision 12606)
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+echo '1..7'
+
+perl $srcdir/test.pl 2>/dev/null >test.pl.out
+perlstatus=$?
+
+./test > test.c.out 2>&1
+cstatus=$?
+
+if grep "^# A diagnostic message$" test.c.out > /dev/null ; then
+    echo "ok 1 - found a diagnostic message"
+else
+    echo "not ok 1 - found a diagnostic message"
+    retval=1
+fi
+
+if grep "^# Returned: 0$" test.c.out > /dev/null ; then
+    echo "ok 2 - diag() expected return value" 
+else
+    echo "not ok 2 - diag() expected return value" 
+    retval=1
+fi
+
+if grep "^#     Failed test (.*test.c:main() at line 43)$" test.c.out > /dev/null ; then
+    echo "ok 3 - 'failed test at line' diag" 
+else
+    echo "not ok 3 - 'failed test at line' diag" 
+    retval=1
+fi
+
+if grep "^# ok() passed, and shouldn't$" test.c.out > /dev/null ; then
+    echo "ok 4 - expected diag"
+else
+    echo "ok 4 - expected diag"
+    retval=1
+fi
+
+if grep "^# Looks like you failed 1 test of 2.$" test.c.out > /dev/null ; then
+    echo "ok 5 - failed 1 test"
+ else
+    echo "ok 5 - failed 1 test"
+    retval=1
+fi
+
+sed -e '/^#/D' test.c.out > tmp
+mv tmp test.c.out
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 6 - TAP output is identical'
+else
+	retval=1
+	echo 'not ok 6 - TAP output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 7 - status code'
+else
+	retval=1
+	echo 'not ok 7 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/fail/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/fail/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/fail/.cvsignore	(revision 12606)
@@ -0,0 +1,15 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/fail/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/fail/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/fail/Makefile.am	(revision 12606)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/fail/test.c
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/fail/test.c	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/fail/test.c	(revision 12606)
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(2);
+	diag("Returned: %d", rc);
+
+	rc = fail("test to fail");
+	diag("Returned: %d", rc);
+
+	rc = fail("test to fail %s", "with extra string");
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/fail/test.pl
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/fail/test.pl	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/fail/test.pl	(revision 12606)
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 2;
+diag("Returned: " . sprintf('%d', $rc));
+
+$rc = fail('test to fail');
+diag("Returned: $rc");
+
+$rc = fail('test to fail with extra string');
+diag("Returned: $rc");
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/fail/test.t
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/fail/test.t	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/fail/test.t	(revision 12606)
@@ -0,0 +1,74 @@
+#!/bin/sh
+
+echo '1..8'
+
+perl $srcdir/test.pl 2>/dev/null > test.pl.out
+perlstatus=$?
+
+./test > test.c.out 2>&1 
+cstatus=$?
+
+if grep "^# Returned: 2$" test.c.out >/dev/null ; then
+  echo "ok 1 - expected return value";
+else
+  echo "not ok 1 - expected return value";
+  retval=1
+fi
+
+if grep "^#     Failed test (.*test.c:main() at line 39)$" test.c.out >/dev/null ; then
+  echo "ok 2 - failed expected test";
+else
+  echo "not ok 2 - failed expected test";
+  retval=1
+fi
+
+if grep "^# Returned: 0$" test.c.out >/dev/null ; then
+  echo "ok 3 - expected return value";
+else
+  echo "not ok 3 - expected return value";
+  retval=1
+fi
+
+if grep "^#     Failed test (.*test.c:main() at line 42)$" test.c.out >/dev/null ; then
+  echo "ok 4 - failed expected test";
+else
+  echo "not ok 4 - failed expected test";
+  retval=1
+fi
+  
+if grep "^# Returned: 0$" test.c.out >/dev/null ; then
+  echo "ok 5 - expected return value";
+else
+  echo "not ok 5 - expected return value";
+  retval=1
+fi
+
+if grep "^# Looks like you failed 2 tests of 2.$" test.c.out >/dev/null ; then
+  echo "ok 6 - expected return value";
+else
+  echo "not ok 6 - expected return value";
+  retval=1
+fi
+
+sed -e '/^#/D' test.c.out > tmp
+mv tmp test.c.out
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 7 - output is identical'
+else
+	retval=1
+	echo 'not ok 7 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 8 - status code'
+else
+	retval=1
+	echo 'not ok 8 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/ok/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/ok/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/ok/.cvsignore	(revision 12606)
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/ok/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/ok/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/ok/Makefile.am	(revision 12606)
@@ -0,0 +1,3 @@
+SUBDIRS  =	ok
+SUBDIRS +=	ok-hash
+SUBDIRS +=	ok-numeric
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/.cvsignore	(revision 12606)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/Makefile.am	(revision 12606)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/test.c
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/test.c	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/test.c	(revision 12606)
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(4);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, "Test with no hash");
+	diag("Returned: %d", rc);
+
+	rc = ok(1, "Test with one # hash");
+	diag("Returned: %d", rc);
+
+        rc = ok(1, "Test with # two # hashes");
+	diag("Returned: %d", rc);
+
+	rc = ok(1, "Test with ## back to back hashes");
+	diag("Returned: %d", rc);
+	
+	return exit_status();
+}
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/test.pl
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/test.pl	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/test.pl	(revision 12606)
@@ -0,0 +1,24 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 4;
+diag("Returned: " . sprintf("%d", $rc));
+
+
+$rc = ok(1, 'Test with no hash');
+diag("Returned: $rc");
+
+$rc = ok(1, 'Test with one # hash');
+diag("Returned: $rc");
+
+$rc = ok(1, 'Test with # two # hashes');
+diag("Returned: $rc");
+
+$rc = ok(1, 'Test with ## back to back hashes');
+diag("Returned: $rc");
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/test.t
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/test.t	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-hash/test.t	(revision 12606)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/.cvsignore	(revision 12606)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/Makefile.am	(revision 12606)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/test.c
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/test.c	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/test.c	(revision 12606)
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(3);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, "First test");
+	diag("Returned: %d", rc);
+
+	rc = ok(1, "1");
+	diag("Returned: %d", rc);
+
+	rc = ok(1, "Third test");
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/test.pl
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/test.pl	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/test.pl	(revision 12606)
@@ -0,0 +1,21 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 3;
+diag("Returned: " . sprintf("%d", $rc));
+
+
+$rc = ok(1, 'First test');
+diag("Returned: $rc");
+
+$rc = ok(1, '1');
+diag("Returned: $rc");
+
+$rc = ok(1, 'Third test');
+diag("Returned: $rc");
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/test.t
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/test.t	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok-numeric/test.t	(revision 12606)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok/.cvsignore	(revision 12606)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok/Makefile.am	(revision 12606)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok/test.c
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok/test.c	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok/test.c	(revision 12606)
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(5);
+	diag("Returned: %d", rc);
+
+	rc = ok(1 == 1, "1 equals 1");
+	diag("Returned: %d", rc);
+
+	rc = ok(1 == 1, "1 equals %d", 1);
+	diag("Returned: %d", rc);
+
+	rc = ok1(1 == 1);
+	diag("Returned: %d", rc);
+
+	rc = ok(1 == 2, "1 equals 2");
+	diag("Returned: %d", rc);
+
+	rc = ok1(1 == 2);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok/test.pl
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok/test.pl	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok/test.pl	(revision 12606)
@@ -0,0 +1,27 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 5;
+diag("Returned: " . sprintf("%d", $rc));
+
+
+$rc = ok(1 == 1, '1 equals 1');	# Test ok() passes when it should
+diag("Returned: $rc");
+
+$rc = ok(1 == 1, '1 equals 1'); # Used for %d testing in test.c
+diag("Returned: $rc");
+
+$rc = ok(1 == 1, '1 == 1');	# Test ok1() passes when it should
+diag("Returned: $rc");
+
+$rc = ok(1 == 2, '1 equals 2');	# Test ok() fails when it should
+diag("Returned: $rc");
+
+$rc = ok(1 == 2, '1 == 2');	# Test ok1() fails when it should
+diag("Returned: $rc");
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok/test.t
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok/test.t	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/ok/ok/test.t	(revision 12606)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/pass/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/pass/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/pass/.cvsignore	(revision 12606)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/pass/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/pass/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/pass/Makefile.am	(revision 12606)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/pass/test.c
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/pass/test.c	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/pass/test.c	(revision 12606)
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(2);
+	diag("Returned: %d", rc);
+
+	rc = pass("test to pass");
+	diag("Returned: %d", rc);
+
+	rc = pass("test to pass %s", "with extra string");
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/pass/test.pl
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/pass/test.pl	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/pass/test.pl	(revision 12606)
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 2;
+diag("Returned: " . sprintf('%d', $rc));
+
+$rc = pass('test to pass');
+diag("Returned: $rc");
+
+$rc = pass('test to pass with extra string');
+diag("Returned: $rc");
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/pass/test.t
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/pass/test.t	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/pass/test.t	(revision 12606)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/.cvsignore	(revision 12606)
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/Makefile.am	(revision 12606)
@@ -0,0 +1,7 @@
+SUBDIRS  =	no-tests
+SUBDIRS +=	no_plan
+SUBDIRS +=	not-enough-tests
+SUBDIRS +=	too-many-plans
+SUBDIRS +=	too-many-tests
+SUBDIRS +=	sane
+SUBDIRS +=	skip_all
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no-tests/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no-tests/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no-tests/.cvsignore	(revision 12606)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no-tests/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no-tests/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no-tests/Makefile.am	(revision 12606)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no-tests/test.c
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no-tests/test.c	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no-tests/test.c	(revision 12606)
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(0);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no-tests/test.pl
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no-tests/test.pl	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no-tests/test.pl	(revision 12606)
@@ -0,0 +1,14 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 0;
+diag("Returned: " . sprintf("%d", $rc));
+
+$rc = ok(1);
+diag("Returned: $rc");
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no-tests/test.t
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no-tests/test.t	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no-tests/test.t	(revision 12606)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no_plan/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no_plan/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no_plan/.cvsignore	(revision 12606)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no_plan/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no_plan/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no_plan/Makefile.am	(revision 12606)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no_plan/test.c
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no_plan/test.c	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no_plan/test.c	(revision 12606)
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_no_plan();
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no_plan/test.pl
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no_plan/test.pl	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no_plan/test.pl	(revision 12606)
@@ -0,0 +1,14 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+my $rc = 0;
+
+use Test::More;
+
+$rc = plan qw(no_plan);
+diag("Returned: " . sprintf("%d", $rc));
+
+$rc = ok(1);
+diag("Returned: $rc");
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no_plan/test.t
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no_plan/test.t	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/no_plan/test.t	(revision 12606)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/.cvsignore	(revision 12606)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/Makefile.am	(revision 12606)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/test.c
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/test.c	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/test.c	(revision 12606)
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(1);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/test.pl
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/test.pl	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/test.pl	(revision 12606)
@@ -0,0 +1,20 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 1;
+diag("Returned: " . sprintf("%d", $rc));
+
+$rc = ok(1);
+diag("Returned: $rc");
+
+$rc = ok(1);
+diag("Returned: $rc");
+
+$rc = ok(1);
+diag("Returned: $rc");
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/test.t
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/test.t	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/not-enough-tests/test.t	(revision 12606)
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	# comment this out until we're exit-code compatible with Test::More
+	#retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/sane/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/sane/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/sane/.cvsignore	(revision 12606)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/sane/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/sane/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/sane/Makefile.am	(revision 12606)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/sane/test.c
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/sane/test.c	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/sane/test.c	(revision 12606)
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(1);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/sane/test.pl
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/sane/test.pl	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/sane/test.pl	(revision 12606)
@@ -0,0 +1,14 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 1;
+diag("Returned: " . sprintf("%d", $rc));
+
+$rc = ok(1);
+diag("Returned: $rc");
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/sane/test.t
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/sane/test.t	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/sane/test.t	(revision 12606)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/skip_all/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/skip_all/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/skip_all/.cvsignore	(revision 12606)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/skip_all/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/skip_all/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/skip_all/Makefile.am	(revision 12606)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/skip_all/plan.c
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/skip_all/plan.c	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/skip_all/plan.c	(revision 12606)
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "tap.h"
+
+/* Run pre-defined tests on the test library to make sure that the basic
+   functionality works, and it can be used to test itself afterwards */
+
+int
+main(int argc, char *argv[])
+{
+	plan_skip_all("No good reason");
+}
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/skip_all/test.c
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/skip_all/test.c	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/skip_all/test.c	(revision 12606)
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_skip_all("No good reason");
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/skip_all/test.pl
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/skip_all/test.pl	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/skip_all/test.pl	(revision 12606)
@@ -0,0 +1,11 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan skip_all => "No good reason";
+diag("Returned: " . sprintf("%d", $rc));
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/skip_all/test.t
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/skip_all/test.t	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/skip_all/test.t	(revision 12606)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/.cvsignore	(revision 12606)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/Makefile.am	(revision 12606)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/test.c
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/test.c	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/test.c	(revision 12606)
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(1);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	rc = plan_tests(1);
+	diag("Returned: %d", rc);
+
+	rc = ok(0, NULL);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/test.pl
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/test.pl	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/test.pl	(revision 12606)
@@ -0,0 +1,20 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 1;
+diag("Returned: " . sprintf("%d", $rc));
+
+$rc = ok(1);
+diag("Returned: $rc");
+
+$rc = plan tests => 1;
+diag("Returned: $rc");
+
+$rc = ok(0);
+diag("Returned: $rc");
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/test.t
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/test.t	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-plans/test.t	(revision 12606)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/.cvsignore	(revision 12606)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/Makefile.am	(revision 12606)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/test.c
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/test.c	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/test.c	(revision 12606)
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(5);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	rc = ok(0, NULL);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/test.pl
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/test.pl	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/test.pl	(revision 12606)
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 5;
+diag("Returned: " . sprintf("%d", $rc));
+
+$rc = ok(1);
+diag("Returned: $rc");
+
+$rc = ok(0);
+diag("Returned: $rc");
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/test.t
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/test.t	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/plan/too-many-tests/test.t	(revision 12606)
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+    # we're not exit-status compatible with Test::More yet
+	#retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/skip/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/skip/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/skip/.cvsignore	(revision 12606)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/skip/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/skip/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/skip/Makefile.am	(revision 12606)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/skip/test.c
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/skip/test.c	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/skip/test.c	(revision 12606)
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+	unsigned int side_effect = 0;
+
+	rc = plan_tests(4);
+	diag("Returned: %d", rc);
+
+	rc = ok(1 == 1, "1 equals 1");	/* Should always work */
+	diag("Returned: %d", rc);
+
+	do {
+		if(1) {
+			rc = skip(1, "Testing skipping");
+			continue;
+		}
+		
+		side_effect++;
+
+		ok(side_effect == 1, "side_effect checked out");
+
+	} while(0);
+
+	diag("Returned: %d", rc);
+
+	skip_start(1 == 1, 1, "Testing skipping #2");
+
+	side_effect++;
+	rc = ok(side_effect == 1, "side_effect checked out");
+	diag("Returned: %d", rc);
+
+	skip_end();
+
+	rc = ok(side_effect == 0, "side_effect is %d", side_effect);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/skip/test.pl
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/skip/test.pl	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/skip/test.pl	(revision 12606)
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 4;
+diag("Returned: " . sprintf("%d", $rc));
+
+my $side_effect = 0;		# Check whether skipping has side effects
+
+$rc = ok(1 == 1, '1 equals 1');	# Test ok() passes when it should
+diag("Returned: $rc");
+
+# Start skipping
+SKIP: {
+	$rc = skip "Testing skipping", 1;
+
+	$side_effect++;
+
+	$rc = ok($side_effect == 1, '$side_effect checked out');
+}
+
+diag("Returned: $rc");
+
+SKIP: {
+	$rc = skip "Testing skipping #2", 1;
+	diag("Returned: $rc");
+
+	$side_effect++;
+
+	$rc = ok($side_effect == 1, '$side_effect checked out');
+	diag("Returned: $rc");
+}
+
+$rc = ok($side_effect == 0, "side_effect is $side_effect");
+diag("Returned: $rc");
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/skip/test.t
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/skip/test.t	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/skip/test.t	(revision 12606)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/todo/.cvsignore
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/todo/.cvsignore	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/todo/.cvsignore	(revision 12606)
@@ -0,0 +1,11 @@
+.deps
+Makefile
+Makefile.in
+.libs
+test
+test.c.out
+test.pl.out
+*.bb
+*.bbg
+*.da
+gmon.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/todo/Makefile.am
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/todo/Makefile.am	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/todo/Makefile.am	(revision 12606)
@@ -0,0 +1,13 @@
+
+TESTS = 		test.t
+TESTS_ENVIRONMENT =	$(SHELL)
+
+EXTRA_DIST = 		$(TESTS) test.pl
+
+check_PROGRAMS = 	test
+
+test_CFLAGS = 		-g -I$(top_srcdir)/src
+test_LDFLAGS = 		-L$(top_builddir)/src
+test_LDADD = 		-ltap
+
+CLEANFILES =	test.o test.c.out test.pl.out
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/todo/test.c
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/todo/test.c	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/todo/test.c	(revision 12606)
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+	unsigned int side_effect = 0;
+
+	rc = plan_tests(5);
+	diag("Returned: %d", rc);
+
+	rc = ok(1 == 1, "1 equals 1");	/* Should always work */
+	diag("Returned: %d", rc);
+
+	todo_start("For testing purposes");
+
+	side_effect++;
+
+	/* This test should fail */
+	rc = ok(side_effect == 0, "side_effect checked out");
+	diag("Returned: %d", rc);
+
+	/* This test should unexpectedly succeed */
+	rc = ok(side_effect == 1, "side_effect checked out");
+	diag("Returned: %d", rc);
+
+	todo_end();
+
+	todo_start("Testing printf() %s in todo_start()", "expansion");
+
+	rc = ok(0, "dummy test");
+	diag("Returned: %d", rc);
+
+	todo_end();
+
+	rc = ok(side_effect == 1, "side_effect is %d", side_effect);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/todo/test.pl
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/todo/test.pl	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/todo/test.pl	(revision 12606)
@@ -0,0 +1,41 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 5;
+diag("Returned: " . sprintf("%d", $rc));
+
+my $side_effect = 0;		# Check whether TODO has side effects
+
+$rc = ok(1 == 1, '1 equals 1');	# Test ok() passes when it should
+diag("Returned: $rc");
+
+# Start TODO tests
+TODO: {
+	local $TODO = 'For testing purposes';
+
+	$side_effect++;
+
+	# This test should fail
+	$rc = ok($side_effect == 0, 'side_effect checked out');
+	diag("Returned: $rc");
+
+	# This test should unexpectedly succeed
+	$rc = ok($side_effect == 1, 'side_effect checked out');
+	diag("Returned: $rc");
+}
+
+TODO: {
+	local $TODO = 'Testing printf() expansion in todo_start()';
+
+	$rc = ok(0, 'dummy test');
+	diag("Returned: $rc");
+}
+
+$rc = ok($side_effect == 1, "side_effect is $side_effect");
+diag("Returned: $rc");
Index: /tags/start/Nebulous/nebclient/tests/tap/tests/todo/test.t
===================================================================
--- /tags/start/Nebulous/nebclient/tests/tap/tests/todo/test.t	(revision 12606)
+++ /tags/start/Nebulous/nebclient/tests/tap/tests/todo/test.t	(revision 12606)
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+# Test:;More prints diagnostic from TODO tests on stdout
+# http://rt.cpan.org/Ticket/Display.html?id=14982
+sed '/^#/D' test.pl.out > tmp
+mv tmp test.pl.out
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /tags/start/Nebulous/nebulous.wsdl
===================================================================
--- /tags/start/Nebulous/nebulous.wsdl	(revision 12606)
+++ /tags/start/Nebulous/nebulous.wsdl	(revision 12606)
@@ -0,0 +1,96 @@
+<?xml version="1.0"?>
+
+<definitions name="idata" targetNamespace="http://pan-starrs.ifa.hawaii.edu/PS/IPP/IData/Server">
+
+    <types>
+        <schema targetNamespace="http://pan-starrs.ifa.hawaii.edu/PS/IPP/IData/Server"
+            xmlns="http://www.w3.org/1999/XMLSchema">
+
+            <element name="create_object">
+                <complexType>
+                    <sequence>
+                        <element name="key"     type="string"/>
+                        <element name="class"   type="int"/>
+                        <element name="volume"  type="string"/>
+                        <element name="comment" type="string"/>
+                    </sequence>
+                </complexType>
+            </element>
+
+            <element name="create_objectResponse">
+                <complexType>
+                    <all>
+                        <element name="uri" type="string"/>
+                    </all>
+                </complexType>
+            </element>
+
+            <element name="create_objectFault">
+                <complexType>
+                    <all>
+                        <element name="errorMessage" type="string"/>
+                    </all>
+                </complexType>
+            </element>
+
+        </schema>
+    </types>
+
+    <message name="create_objectRequest">
+        <part name="body" element="esxsd:create_object"/>
+    </message>
+
+    <message name="create_objectResponse">
+        <part name="body" element="esxsd:create_objectResponse"/>
+    </message>
+
+    <portType name="create_objectPortType">
+        <operation name="create_object">
+            <input message ="es:create_objectRequest"/>
+            <output message="es:create_objectResponse"/>
+            <fault message ="es:create_objectFault"/>
+        </operation>
+    </portType>
+
+    <binding name="idataSoapBinding"
+        type="es:GetidatarPortType">
+
+        <soap:binding style="document"
+            transport="http://schemas.xmlsoap.org/soap/http"/>
+
+        <operation name="Getidata">
+            <soap:operation
+                soapAction="http://www.snowboard-info.com/EndorsementSearch"/>
+            <input>
+                <soap:body use="literal"
+                    namespace="http://schemas.snowboard-info.com/EndorsementSearch.xsd"/>
+            </input>
+
+            <output>
+                <soap:body use="literal"
+                    namespace="http://schemas.snowboard-info.com/EndorsementSearch.xsd"/>
+            </output>
+
+            <fault>
+                <soap:body use="literal"
+                    namespace="http://schemas.snowboard-info.com/EndorsementSearch.xsd"/>
+            </fault>
+        </operation>
+    </binding>
+
+
+  <service name="EndorsementSearchService">
+
+    <documentation>snowboarding-info.com Endorsement Service</documentation> 
+
+    <port name="GetEndorsingBoarderPort"
+          binding="es:EndorsementSearchSoapBinding">
+
+      <soap:address
+location="http://www.snowboard-info.com/EndorsementSearch"/>
+
+    </port>
+
+  </service>
+
+</definitions>
Index: /tags/start/Nebulous/scripts/bench_test.pl
===================================================================
--- /tags/start/Nebulous/scripts/bench_test.pl	(revision 12606)
+++ /tags/start/Nebulous/scripts/bench_test.pl	(revision 12606)
@@ -0,0 +1,28 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use lib "./lib";
+use Benchmark qw( cmpthese );
+
+use PS::IPP::IData::Client;
+
+my $idata = PS::IPP::IData::Client->new(
+    proxy   => 'http://localhost:80/idata'
+);
+
+my $key = "foobarbazbongbungbutufu";
+cmpthese( 10, {
+        'Image Server' => sub {
+            {
+                my $fh = $idata->create( $key );
+                close $fh;
+                $idata->unlock( $key, 'write' );
+            }
+
+            $idata->delete( $key );
+        },
+    },
+    'all',
+);
Index: /tags/start/Nebulous/scripts/imageserver.pl
===================================================================
--- /tags/start/Nebulous/scripts/imageserver.pl	(revision 12606)
+++ /tags/start/Nebulous/scripts/imageserver.pl	(revision 12606)
@@ -0,0 +1,14 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2004  Joshua Hoblitt
+#
+# $Id
+ 
+use strict;
+
+use SOAP::Transport::HTTP;
+use PS::IPP::IData::Server;
+   
+SOAP::Transport::HTTP::CGI
+    -> dispatch_to( 'PS::IPP::IData::Server' )
+    -> handle;
Index: /tags/start/Nebulous/scripts/ptest.pl
===================================================================
--- /tags/start/Nebulous/scripts/ptest.pl	(revision 12606)
+++ /tags/start/Nebulous/scripts/ptest.pl	(revision 12606)
@@ -0,0 +1,51 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use lib "./lib";
+
+use PS::IPP::IData::Client;
+
+my $idata = PS::IPP::IData::Client->new(
+    uri     => 'http://localhost:80/PS/IPP/IData/Server',
+    proxy   => 'http://localhost:80/idata'
+);
+
+my $key = shift;
+
+my $kids = shift || 1;
+
+foreach my $id ( 1..$kids ) {
+    my $pid = fork;
+
+    unless ( $pid )  {
+        my $fname = "${key}_$id";
+        my $fh = $idata->create( $fname );
+        die "can't create file $fname" unless $fh;
+
+        print $fh "fooby\n";
+
+        close $fh;
+        $idata->unlock( $fname, 'write' );
+
+        $fh = $idata->open( $fname, 'read' ) or die "can't open file";
+        close $fh;
+        $idata->unlock( $fname, 'read' );
+
+        $idata->replicate( $fname );
+        $idata->cull( $fname );
+        $idata->find( $fname );
+        $idata->copy( $fname, $fname . "_copy" );
+        $idata->move( $fname, $fname . "_move" );
+        $idata->delete( $fname . "_copy" );
+        $idata->delete( $fname . "_move" );
+
+        exit 0;
+    }
+}
+
+while ( $kids ) {
+    wait();
+    $kids --;
+}
Index: /tags/start/Nebulous/scripts/stest.pl
===================================================================
--- /tags/start/Nebulous/scripts/stest.pl	(revision 12606)
+++ /tags/start/Nebulous/scripts/stest.pl	(revision 12606)
@@ -0,0 +1,33 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use lib "./lib";
+
+use PS::IPP::IData::Client; # trace => 'debug';
+
+my $idata = PS::IPP::IData::Client->new(
+    proxy   => 'http://localhost:80/idata'
+);
+
+my $fname = shift;
+
+#my $fh = $idata->create( $fname );
+#$idata->unlock( $fname, 'write' );
+
+$idata->create( $fname, 1 );
+$idata->unlock( $fname, 'write' );
+$idata->delete( $fname );
+
+__END__
+
+{
+    my $fh = $pd->create( $key );
+    die "can't create file $fname" unless $fh;
+    print $fh "fooby\n";
+    close $fh;
+    #$idata->unlock( $fname, 'write' );
+    my $filesize =  (stat( $key ))[7];
+    print "created file $key, ${filesize}bytes\n";
+}
Index: /tags/start/Nebulous/t/01_load.t
===================================================================
--- /tags/start/Nebulous/t/01_load.t	(revision 12606)
+++ /tags/start/Nebulous/t/01_load.t	(revision 12606)
@@ -0,0 +1,19 @@
+# -*- perl -*-
+
+# t/001_load.t - check module loading and create testing directory
+
+use strict;
+use warnings;
+
+use lib qw( ./t ./lib );
+
+use Test::More tests => 8;
+
+BEGIN { use_ok( 'PS::IPP::IData::Client' ); }
+BEGIN { use_ok( 'PS::IPP::IData::Client::Log' ); }
+BEGIN { use_ok( 'PS::IPP::IData::Client::HTTP' ); }
+BEGIN { use_ok( 'PS::IPP::IData::Util' ); }
+BEGIN { use_ok( 'PS::IPP::IData::Server' ); }
+BEGIN { use_ok( 'PS::IPP::IData::Server::Apache' ); }
+BEGIN { use_ok( 'PS::IPP::IData::Server::SQL' ); }
+BEGIN { use_ok( 'PS::IPP::IData::Server::Log' ); }
Index: /tags/start/Nebulous/t/02_server_setup.t
===================================================================
--- /tags/start/Nebulous/t/02_server_setup.t	(revision 12606)
+++ /tags/start/Nebulous/t/02_server_setup.t	(revision 12606)
@@ -0,0 +1,35 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 2;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Server;
+use Test::IData;
+
+Test::IData->setup;
+
+ok(
+    PS::IPP::IData::Server->setup(
+        "DBI:mysql:database=test:host=localhost",
+        "test",
+        "",
+    ),
+    "connect",
+);
+
+Test::IData->setup;
+
+eval {
+    PS::IPP::IData::Server->setup(
+        "DBI:mysql:database=foobar:host=localhost",
+        "baz",
+        "boo",
+    );
+};
+like( $@, qr/DBI connect.*? failed/, "bad dsn/user/pass" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous/t/03_server_create_object.t
===================================================================
--- /tags/start/Nebulous/t/03_server_create_object.t	(revision 12606)
+++ /tags/start/Nebulous/t/03_server_create_object.t	(revision 12606)
@@ -0,0 +1,84 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 11;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Server;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $idata = "PS::IPP::IData::Server";
+
+$idata->setup(
+    "DBI:mysql:database=test:host=localhost",
+    "test",
+    "",
+);
+
+Test::IData->setup;
+
+{
+    # key
+    my $uri = $idata->create_object( "foo" );
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, class
+    my $uri = $idata->create_object( "foo", 0 );
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, class, volume
+    my $uri = $idata->create_object( "foo", 0, "node01" );
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, class, volume, comment
+    my $uri = $idata->create_object( "foo", 0, "node01", "this is foo" );
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object( "foo" );
+    $idata->create_object( "foo" );
+};
+like( $@, qr/Duplicate entry/, "object already exists" );
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object();
+};
+like( $@, qr/2 - 4 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object( 1, 2, 3, 4, 5 );
+};
+like( $@, qr/2 - 4 were expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous/t/04_server_replicate_object.t
===================================================================
--- /tags/start/Nebulous/t/04_server_replicate_object.t	(revision 12606)
+++ /tags/start/Nebulous/t/04_server_replicate_object.t	(revision 12606)
@@ -0,0 +1,79 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 11;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Server;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $idata = "PS::IPP::IData::Server";
+
+$idata->setup(
+    "DBI:mysql:database=test:host=localhost",
+    "test",
+    "",
+);
+
+Test::IData->setup;
+
+{
+    # key
+    $idata->create_object( "foo" );
+    my $uri = $idata->replicate_object( "foo" );
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, $volume
+    $idata->create_object( "foo" );
+    my $uri = $idata->replicate_object( "foo", "node01" );
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, $volume
+    $idata->create_object( "foo" );
+    my $uri1 = $idata->replicate_object( "foo", "node01" );
+    my $uri2 = $idata->replicate_object( "foo", "node02" );
+
+    ok( -e _get_file_path( $uri1 ), "file exists" );
+    ok( -e _get_file_path( $uri2 ), "file exists" );
+    like( $uri1, qr/^file:\//, "valid URI" );
+    like( $uri2, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+eval {
+    $idata->replicate_object( "foo" );
+};
+like( $@, qr/storage object does not exist/, "storage object does not exist" );
+
+Test::IData->setup;
+
+eval {
+    $idata->replicate_object();
+};
+like( $@, qr/1 - 2 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    $idata->replicate_object( 1, 2, 3 );
+};
+like( $@, qr/1 - 2 were expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous/t/05_server_lock_object.t
===================================================================
--- /tags/start/Nebulous/t/05_server_lock_object.t	(revision 12606)
+++ /tags/start/Nebulous/t/05_server_lock_object.t	(revision 12606)
@@ -0,0 +1,119 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 13;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Server;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $idata = "PS::IPP::IData::Server";
+
+$idata->setup(
+    "DBI:mysql:database=test:host=localhost",
+    "test",
+    "",
+);
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    ok( $idata->lock_object( "foo", "read" ), "read lock" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    ok( $idata->lock_object( "foo", "read" ), "read lock" );
+    ok( $idata->lock_object( "foo", "read" ), "read lock" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    ok( $idata->lock_object( "foo", "write" ), "write lock" );
+}
+
+Test::IData->setup;
+
+eval {
+    $idata->lock_object( "foo", "read" );
+};
+like( $@, qr/storage object does not exist/, "storage object does not exist" );
+
+Test::IData->setup;
+
+eval {
+    $idata->lock_object( "foo", "write" );
+};
+like( $@, qr/storage object does not exist/, "storage object does not exist" );
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object( "foo" );
+
+    $idata->lock_object( "foo", "write" );
+    $idata->lock_object( "foo", "write" );
+};
+like( $@, qr/can not write lock twice/, "can not write lock twice" );
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object( "foo" );
+
+    $idata->lock_object( "foo", "read" );
+    $idata->lock_object( "foo", "write" );
+};
+like( $@, qr/can not write lock after read lock/, "can not write lock after read lock" );
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object( "foo" );
+
+    $idata->lock_object( "foo", "write" );
+    $idata->lock_object( "foo", "read" );
+};
+like( $@, qr/can not read lock after write lock/, "can not read lock after write lock" );
+
+Test::IData->setup;
+
+eval {
+    $idata->lock_object();
+};
+like( $@, qr/2 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    $idata->lock_object( "foo" );
+};
+like( $@, qr/2 were expected/, "not enough params" );
+
+Test::IData->setup;
+
+eval {
+    $idata->lock_object( "foo", "both" );
+};
+like( $@, qr/is read or write/, "not read or write" );
+
+Test::IData->setup;
+
+eval {
+    $idata->lock_object( "foo", 'read', 3 );
+};
+like( $@, qr/2 were expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous/t/06_server_unlock_object.t
===================================================================
--- /tags/start/Nebulous/t/06_server_unlock_object.t	(revision 12606)
+++ /tags/start/Nebulous/t/06_server_unlock_object.t	(revision 12606)
@@ -0,0 +1,134 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 14;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Server;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $idata = "PS::IPP::IData::Server";
+
+$idata->setup(
+    "DBI:mysql:database=test:host=localhost",
+    "test",
+    "",
+);
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    $idata->lock_object( "foo", "read" );
+
+    ok( $idata->unlock_object( "foo", "read" ), "read unlock" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    $idata->lock_object( "foo", "read" );
+    $idata->lock_object( "foo", "read" );
+
+    ok( $idata->unlock_object( "foo", "read" ), "read unlock" );
+    ok( $idata->unlock_object( "foo", "read" ), "read unlock" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    $idata->lock_object( "foo", "write" );
+
+    ok( $idata->unlock_object( "foo", "write" ), "write unlock" );
+}
+
+Test::IData->setup;
+
+eval {
+    $idata->unlock_object( "foo", "read" );
+};
+like( $@, qr/storage object does not exist/, "storage object does not exist" );
+
+Test::IData->setup;
+
+eval {
+    $idata->unlock_object( "foo", "write" );
+};
+like( $@, qr/storage object does not exist/, "storage object does not exist" );
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object( "foo" );
+
+    $idata->unlock_object( "foo", "read" );
+};
+like( $@, qr/can not remove non-existant read lock/, "no lock set" );
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object( "foo" );
+
+    $idata->unlock_object( "foo", "write" );
+};
+like( $@, qr/can not remove non-existant write lock/, "no lock set" );
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object( "foo" );
+    $idata->lock_object( "foo", "write" );
+
+    $idata->unlock_object( "foo", "read" );
+};
+like( $@, qr/can not have a read lock under a write lock/, "read unlock under write lock" );
+
+Test::IData->setup;
+
+eval {
+    $idata->create_object( "foo" );
+    $idata->lock_object( "foo", "read" );
+
+    $idata->unlock_object( "foo", "write" );
+};
+like( $@, qr/can not have a write lock under a read lock/, "write unlock under read lock" );
+
+Test::IData->setup;
+
+eval {
+    $idata->unlock_object();
+};
+like( $@, qr/2 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    $idata->unlock_object( "foo" );
+};
+like( $@, qr/2 were expected/, "not enough params" );
+
+Test::IData->setup;
+
+eval {
+    $idata->unlock_object( "foo", "both" );
+};
+like( $@, qr/is read or write/, "not read or write" );
+
+Test::IData->setup;
+
+eval {
+    $idata->unlock_object( "foo", 'read', 3 );
+};
+like( $@, qr/2 were expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous/t/07_server_find_instances.t
===================================================================
--- /tags/start/Nebulous/t/07_server_find_instances.t	(revision 12606)
+++ /tags/start/Nebulous/t/07_server_find_instances.t	(revision 12606)
@@ -0,0 +1,90 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 7;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Server;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $idata = "PS::IPP::IData::Server";
+
+$idata->setup(
+    "DBI:mysql:database=test:host=localhost",
+    "test",
+    "",
+);
+
+Test::IData->setup;
+
+{
+    # key
+    my $uri = $idata->create_object( "foo" );
+
+    my $locations = $idata->find_instances( "foo" );
+
+    is( $uri, $locations->[0], "URIs match" );
+}
+
+Test::IData->setup;
+
+{
+    # key
+    my $uri1 = $idata->create_object( "foo" );
+    my $uri2 = $idata->replicate_object( "foo" );
+
+    my $locations = $idata->find_instances( "foo" );
+
+    ok( eq_set( [$uri1, $uri2], $locations ), "URIs match" );
+}
+
+Test::IData->setup;
+
+{
+    # key, volume
+    my $uri = $idata->create_object( "foo" );
+
+    my $locations = $idata->find_instances( "foo", "node01" );
+
+    is( $uri, $locations->[0], "URIs match" );
+}
+
+Test::IData->setup;
+
+{
+    # key
+    my $uri1 = $idata->create_object( "foo" );
+    my $uri2 = $idata->replicate_object( "foo" );
+
+    my $locations = $idata->find_instances( "foo", "node01" );
+
+    ok( eq_set( [$uri1, $uri2], $locations ), "URIs match" );
+}
+
+
+Test::IData->setup;
+
+eval {
+    $idata->find_instances( "foo" );
+};
+like( $@, qr/no instances found/, "storage object does not exist" );
+
+Test::IData->setup;
+
+eval {
+    $idata->find_instances();
+};
+like( $@, qr/1 - 2 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    $idata->find_instances( "foo", 'read', 3 );
+};
+like( $@, qr/1 - 2 were expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous/t/08_server_delete_instance.t
===================================================================
--- /tags/start/Nebulous/t/08_server_delete_instance.t	(revision 12606)
+++ /tags/start/Nebulous/t/08_server_delete_instance.t	(revision 12606)
@@ -0,0 +1,71 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 8;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Server;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $idata = "PS::IPP::IData::Server";
+
+$idata->setup(
+    "DBI:mysql:database=test:host=localhost",
+    "test",
+    "",
+);
+
+Test::IData->setup;
+
+{
+    my $uri = $idata->create_object( "foo" );
+
+    ok( $idata->delete_instance( $uri ), "delete instance" );
+}
+
+Test::IData->setup;
+
+{
+    my $uri1 = $idata->create_object( "foo" );
+    my $uri2 = $idata->replicate_object( "foo" );
+
+    ok( $idata->delete_instance( $uri1 ), "delete instance" );
+
+    my $locations = $idata->find_instances( "foo" );
+
+    is( $locations->[0], $uri2, "instance remains" );
+
+    ok( $idata->delete_instance( $uri2 ), "delete instance" );
+
+    eval {
+        $idata->find_instances( "foo" );
+    };
+    like( $@, qr/no instances found/, "storage object was deleted" );
+}
+
+Test::IData->setup;
+
+eval {
+    $idata->delete_instance( "file:/foo" );
+};
+like( $@, qr/no instance is associated with uri/, "uri does not exist" );
+
+Test::IData->setup;
+
+eval {
+    $idata->delete_instance();
+};
+like( $@, qr/1 was expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    $idata->delete_instance( "foo", 2 );
+};
+like( $@, qr/1 was expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous/t/09_server_stat_object.t
===================================================================
--- /tags/start/Nebulous/t/09_server_stat_object.t	(revision 12606)
+++ /tags/start/Nebulous/t/09_server_stat_object.t	(revision 12606)
@@ -0,0 +1,70 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 12;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Server;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $idata = "PS::IPP::IData::Server";
+
+$idata->setup(
+    "DBI:mysql:database=test:host=localhost",
+    "test",
+    "",
+);
+
+Test::IData->setup;
+
+{
+    my $uri = $idata->create_object( "foo" );
+
+    my $info = $idata->stat_object( "foo" );
+
+    is( scalar @$info, 7, "number of columns" );
+}
+
+Test::IData->setup;
+
+{
+    my $uri = $idata->create_object( "foo", 9, "node01", "foobar" );
+
+    my $info = $idata->stat_object( "foo" );
+
+    is( scalar @$info, 7,                       "number of columns" );
+    is( @$info[0], 1,                           "so_id" );
+    is( @$info[1], "foo",                       "ext_id" );
+    is( @$info[2], 9,                           "class_id" );
+    is( @$info[3], "foobar",                    "comment" );
+    is( @$info[4], 0,                           "read lock" );
+    is( @$info[5], undef,                       "write lock" );
+    like( @$info[6], qr/....-..-.. ..:..:../,   "epoch" );
+}
+
+Test::IData->setup;
+
+eval {
+    $idata->stat_object( "foo" );
+};
+like( $@, qr/no storage object found/, "object does not exist" );
+
+Test::IData->setup;
+
+eval {
+    $idata->stat_object();
+};
+like( $@, qr/1 was expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    $idata->stat_object( "foo", 2 );
+};
+like( $@, qr/1 was expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous/t/10_client_new.t
===================================================================
--- /tags/start/Nebulous/t/10_client_new.t	(revision 12606)
+++ /tags/start/Nebulous/t/10_client_new.t	(revision 12606)
@@ -0,0 +1,56 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 4;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Client;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    isa_ok( $idata, "PS::IPP::IData::Client" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+        uri   => "http://example.com/PS/IPP/IData/Client",
+    );
+
+    isa_ok( $idata, "PS::IPP::IData::Client" );
+}
+
+Test::IData->setup;
+
+eval {
+    PS::IPP::IData::Client->new;
+};
+like( $@, qr/Mandatory parameter/, "no proxy" );
+
+Test::IData->setup;
+
+eval {
+    PS::IPP::IData::Client->new(
+        proxy => "foo",
+        dog => "do"
+    );
+};
+like( $@, qr/not listed in the validation options/, "bad param" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous/t/11_client_create.t
===================================================================
--- /tags/start/Nebulous/t/11_client_create.t	(revision 12606)
+++ /tags/start/Nebulous/t/11_client_create.t	(revision 12606)
@@ -0,0 +1,103 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 7;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Client;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::IData->setup;
+
+{
+    # key
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    my $fh = $idata->create( "foo" );
+
+    is( ref $fh, 'GLOB', "good filehandle" );
+}
+
+Test::IData->setup;
+
+{
+    # key, class
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    my $fh = $idata->create( "foo", 0 );
+
+    is( ref $fh, 'GLOB', "good filehandle" );
+}
+
+Test::IData->setup;
+
+{
+    # key, class, volume
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    my $fh = $idata->create( "foo", 0, "node01" );
+
+    is( ref $fh, 'GLOB', "good filehandle" );
+}
+
+Test::IData->setup;
+
+{
+    # key, class, volume, comment
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    my $fh = $idata->create( "foo", 0, "node01", "this is foo" );
+
+    is( ref $fh, 'GLOB', "good filehandle" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->create( "foo" );
+    is( $idata->create( "foo" ), undef, "object already exists" );
+}
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->create();
+};
+like( $@, qr/2 - 4 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->create( 1, 2, 3, 4, 5 );
+};
+like( $@, qr/2 - 4 were expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous/t/12_client_replicate.t
===================================================================
--- /tags/start/Nebulous/t/12_client_replicate.t	(revision 12606)
+++ /tags/start/Nebulous/t/12_client_replicate.t	(revision 12606)
@@ -0,0 +1,97 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 11;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Client;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::IData->setup;
+
+{
+    # key
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    my $uri = $idata->replicate( "foo" );
+
+    ok( $uri, "good replication" );
+    ok( -e _get_file_path( $uri ), "file exists" );
+}
+
+Test::IData->setup;
+
+{
+    # key, $volume
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    my $uri = $idata->replicate( "foo", "node01" );
+
+    ok( $uri, "good replication" );
+    ok( -e _get_file_path( $uri ), "file exists" );
+}
+
+Test::IData->setup;
+
+{
+    # key, $volume
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    my $uri1 = $idata->replicate( "foo", "node01" );
+    my $uri2 = $idata->replicate( "foo", "node02" );
+
+    ok( $uri1, "good replication" );
+    ok( $uri2, "good replication" );
+    ok( -e _get_file_path( $uri1 ), "file exists" );
+    ok( -e _get_file_path( $uri2 ), "file exists" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    my $uri = $idata->replicate( "foo" );
+
+    is( $uri, undef, "storage object does not exist" );
+}
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->replicate();
+};
+like( $@, qr/1 - 2 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->replicate( 1, 2, 3 );
+};
+like( $@, qr/1 - 2 were expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous/t/13_client_cull.t
===================================================================
--- /tags/start/Nebulous/t/13_client_cull.t	(revision 12606)
+++ /tags/start/Nebulous/t/13_client_cull.t	(revision 12606)
@@ -0,0 +1,127 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 15;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Client;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::IData->setup;
+
+{
+    # key
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+    $idata->replicate( "foo" );
+
+    my $uri = $idata->cull( "foo" );
+
+    ok( $uri, "good cull" );
+    ok( ! -e _get_file_path( $uri ), "file doesn't exist" );
+}
+
+Test::IData->setup;
+
+SKIP: {
+    skip "unsure if this should be part of the API", 2;
+
+    # key, $volume
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+    $idata->replicate( "foo", "node01" );
+
+    my $uri = $idata->cull( "foo", "node01" );
+
+    ok( $uri, "good cull" );
+    ok( ! -e _get_file_path( $uri ), "file exists" );
+}
+
+Test::IData->setup;
+
+{
+    # key
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    $idata->replicate( "foo", "node01" );
+    $idata->replicate( "foo", "node02" );
+
+    my $uri1 = $idata->cull( "foo" );
+    my $uri2 = $idata->cull( "foo" );
+
+    ok( $uri1, "good cull" );
+    ok( $uri2, "good cull" );
+    ok( ! -e _get_file_path( $uri1 ), "file exists" );
+    ok( ! -e _get_file_path( $uri2 ), "file exists" );
+}
+
+Test::IData->setup;
+
+SKIP: {
+    skip "unsure if this should be part of the API", 4;
+
+    # key, $volume
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    $idata->replicate( "foo", "node01" );
+    $idata->replicate( "foo", "node02" );
+
+    my $uri1 = $idata->cull( "foo", "node01" );
+    my $uri2 = $idata->cull( "foo", "node02" );
+
+    ok( $uri1, "good cull" );
+    ok( $uri2, "good cull" );
+    ok( ! -e _get_file_path( $uri1 ), "file exists" );
+    ok( ! -e _get_file_path( $uri2 ), "file exists" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    my $uri = $idata->cull( "foo" );
+
+    is( $uri, undef, "storage object does not exist" );
+}
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->cull();
+};
+like( $@, qr/1 was expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->cull( 1, 2 );
+};
+like( $@, qr/1 was expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous/t/14_client_lock.t
===================================================================
--- /tags/start/Nebulous/t/14_client_lock.t	(revision 12606)
+++ /tags/start/Nebulous/t/14_client_lock.t	(revision 12606)
@@ -0,0 +1,269 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 19;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Client;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::IData->setup;
+
+{
+    # key, type
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    ok( $idata->lock( "foo", "read" ), "read lock" );
+}
+
+Test::IData->setup;
+
+{
+    # key, type, timeout
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    ok( $idata->lock( "foo", "read", 10 ), "read lock" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    ok( $idata->lock( "foo", "read" ), "read lock" );
+    ok( $idata->lock( "foo", "read" ), "read lock" );
+}
+
+Test::IData->setup;
+
+{
+    # key, type
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    ok( $idata->lock( "foo", "write" ), "write lock" );
+}
+
+Test::IData->setup;
+
+{
+    # key, type, timeout
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    ok( $idata->lock( "foo", "write", 10 ), "write lock" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    is( $idata->lock( "foo", "read" ), undef, "storage object does not exist" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    is( $idata->lock( "foo", "write" ), undef, "storage object does not exist" );
+}
+
+Test::IData->setup;
+
+diag "testing a spinlock, this will be a litle slow...";
+
+eval {
+    local $SIG{ALRM} = sub { alarm 0; die "timeout"; };
+    alarm 8;
+
+    # key, type, timeout
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    $idata->lock( "foo", "read" );
+    $idata->lock( "foo", "write" );
+
+    alarm 0;
+};
+like( $@, qr/timeout/, "default spinlock" );
+
+Test::IData->setup;
+
+diag "testing a spinlock, this will be a litle slow...";
+
+eval {
+    local $SIG{ALRM} = sub { alarm 0; die "timeout"; };
+    alarm 12;
+
+    # key, type, timeout
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    $idata->lock( "foo", "read" );
+    unless ( $idata->lock( "foo", "write" ) ) {
+        alarm 0;
+        die "gaveup";
+    }
+
+    alarm 0;
+};
+like( $@, qr/gaveup/, "default spinlock" );
+
+Test::IData->setup;
+
+diag "testing a spinlock, this will be a litle slow...";
+
+eval {
+    local $SIG{ALRM} = sub { alarm 0; die "timeout"; };
+    alarm 3;
+
+    # key, type, timeout
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    $idata->lock( "foo", "read" );
+    $idata->lock( "foo", "write", 5 );
+
+    alarm 0;
+};
+like( $@, qr/timeout/, "specified spinlock" );
+
+Test::IData->setup;
+
+diag "testing a spinlock, this will be a litle slow...";
+
+eval {
+    local $SIG{ALRM} = sub { alarm 0; die "timeout"; };
+    alarm 7;
+
+    # key, type, timeout
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    $idata->lock( "foo", "read" );
+    unless ( $idata->lock( "foo", "write", 5 ) ) {
+        alarm 0;
+        die "gaveup";
+    }
+
+    alarm 0;
+};
+
+like( $@, qr/gaveup/, "specified spinlock" );
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    $idata->lock( "foo", "write" );
+    is( $idata->lock( "foo", "write", 1 ), undef, "can not write lock twice" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    $idata->lock( "foo", "read" );
+    is( $idata->lock( "foo", "write", 1 ), undef, "can not write lock after read lock" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    $idata->lock( "foo", "write" );
+    is( $idata->lock( "foo", "read", 1 ), undef, "can not read lock after write lock" );
+}
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->lock();
+};
+like( $@, qr/2 - 3 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->lock( "foo" );
+};
+like( $@, qr/2 - 3 were expected/, "not enough params" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->lock( "foo", "both" );
+};
+like( $@, qr/is read or write/, "not read or write" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->lock( "foo", 'read', 3, "bar" );
+};
+like( $@, qr/2 - 3 were expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous/t/15_client_unlock.t
===================================================================
--- /tags/start/Nebulous/t/15_client_unlock.t	(revision 12606)
+++ /tags/start/Nebulous/t/15_client_unlock.t	(revision 12606)
@@ -0,0 +1,166 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 14;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Client;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+    $idata->lock( "foo", "read" );
+
+    ok( $idata->unlock( "foo", "read" ), "read unlock" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+    $idata->lock( "foo", "read" );
+    $idata->lock( "foo", "read" );
+
+    ok( $idata->unlock( "foo", "read" ), "read unlock" );
+    ok( $idata->unlock( "foo", "read" ), "read unlock" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+    $idata->lock( "foo", "write" );
+
+    ok( $idata->unlock( "foo", "write" ), "write unlock" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    is( $idata->unlock( "foo", "read" ), undef, "storage object does not exist" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    is( $idata->unlock( "foo", "write" ), undef, "storage object does not exist" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    is( $idata->unlock( "foo", "read" ), undef, "no lock set" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+
+    is( $idata->unlock( "foo", "write" ), undef, "no lock set" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+    $idata->lock( "foo", "write" );
+
+    is( $idata->unlock( "foo", "read" ), undef, "read unlock under write lock" );
+}
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    $idata->create( "foo" );
+    $idata->lock( "foo", "read" );
+
+    is( $idata->unlock( "foo", "write" ), undef, "write unlock under read lock" );
+}
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->unlock();
+};
+like( $@, qr/2 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->unlock( "foo" );
+};
+like( $@, qr/2 were expected/, "not enough params" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->unlock( "foo", "both" );
+};
+like( $@, qr/is read or write/, "not read or write" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->unlock( "foo", 'read', 3 );
+};
+like( $@, qr/2 were expected/, "too many params" );
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous/t/16_client_find_instances.t
===================================================================
--- /tags/start/Nebulous/t/16_client_find_instances.t	(revision 12606)
+++ /tags/start/Nebulous/t/16_client_find_instances.t	(revision 12606)
@@ -0,0 +1,114 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 7;
+
+use lib qw( ./t ./lib );
+
+use PS::IPP::IData::Client;
+use PS::IPP::IData::Util qw( :standard );
+use Test::IData;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::IData->setup;
+
+SKIP: {
+    skip "need to write a module to validate URIs", 7;
+
+{
+    # key
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    my $uri = $idata->create( "foo" );
+
+    my $locations = $idata->find_instances( "foo" );
+
+    is( $uri, @$locations[0], "URIs match" );
+}
+
+Test::IData->setup;
+
+{
+    # key
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    my $uri1 = $idata->create( "foo" );
+    my $uri2 = $idata->replicate( "foo" );
+
+    my $locations = $idata->find_instances( "foo" );
+
+    ok( eq_set( [$uri1, $uri2], $locations ), "URIs match" );
+}
+
+Test::IData->setup;
+
+{
+    # key, volume
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    my $uri = $idata->create( "foo" );
+
+    my $locations = $idata->find_instances( "foo", "node01" );
+
+    is( $uri, $locations->[0], "URIs match" );
+}
+
+Test::IData->setup;
+
+{
+    # key
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+    my $uri1 = $idata->create( "foo" );
+    my $uri2 = $idata->replicate( "foo" );
+
+    my $locations = $idata->find_instances( "foo", "node01" );
+
+    ok( eq_set( [$uri1, $uri2], $locations ), "URIs match" );
+}
+
+
+Test::IData->setup;
+
+{
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    is( $idata->find_instances( "foo" ), undef, "storage object does not exist" );
+}
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->find_instances();
+};
+like( $@, qr/1 - 2 were expected/, "no params" );
+
+Test::IData->setup;
+
+eval {
+    my $idata = PS::IPP::IData::Client->new(
+        proxy => "http://$hostport/idata",
+    );
+
+    $idata->find_instances( "foo", 'read', 3 );
+};
+like( $@, qr/1 - 2 were expected/, "too many params" );
+
+Test::IData->cleanup;
+
+}
Index: /tags/start/Nebulous/t/TEST.PL
===================================================================
--- /tags/start/Nebulous/t/TEST.PL	(revision 12606)
+++ /tags/start/Nebulous/t/TEST.PL	(revision 12606)
@@ -0,0 +1,12 @@
+#file:t/TEST.PL
+#--------------
+#!perl
+
+use strict;
+use warnings FATAL => 'all';
+
+use lib qw(lib);
+
+use Apache::TestRunPerl ();
+
+Apache::TestRunPerl->new->run(@ARGV);
Index: /tags/start/Nebulous/t/Test/Nebulous.pm
===================================================================
--- /tags/start/Nebulous/t/Test/Nebulous.pm	(revision 12606)
+++ /tags/start/Nebulous/t/Test/Nebulous.pm	(revision 12606)
@@ -0,0 +1,113 @@
+# Copyright (C) 2004  Joshua Hoblitt
+#
+# $Id: Nebulous.pm,v 1.1.1.1 2004-12-22 02:16:23 jhoblitt Exp $
+
+package Test::IData;
+
+use strict;
+
+use DBI;
+use File::Path qw( mkpath rmtree );
+use File::Temp qw( tempdir );
+
+my $dsn     = "DBI:mysql:database=test:host=localhost";
+my $user    = "test";
+my $passwd  = "";
+
+my $dbh = DBI->connect( $dsn, $user, $passwd );
+
+#my $dir1 = tempdir( CLEANUP => 0 );
+#my $dir2 = tempdir( CLEANUP => 0 );
+
+my $dir1 = "/tmp/foo1";
+my $dir2 = "/tmp/foo1";
+
+
+sub setup {
+    my $self = shift;
+
+    $self->cleanup;
+
+    mkpath([$dir1, $dir2]);
+
+    local $/ = ';';
+
+    my $pos = tell DATA;
+
+    foreach my $statement (<DATA>) {
+        last unless ( $statement =~ /\S+/ );
+        $dbh->do( $statement );
+    }
+
+    seek DATA, $pos, 0;
+
+    # FIXME
+    $dbh->do( qq{ INSERT INTO volume VALUES (1,'node01',?) }, undef, 'file:' . $dir1 );
+    $dbh->do( qq{ INSERT INTO volume VALUES (2,'node02',?) }, undef, 'file:' . $dir2 );
+}
+
+sub cleanup {
+    $dbh->do( "DROP TABLE IF EXISTS storage_object" );
+    $dbh->do( "DROP TABLE IF EXISTS instance" );
+    $dbh->do( "DROP TABLE IF EXISTS lock_record" );
+    $dbh->do( "DROP TABLE IF EXISTS volume" );
+    $dbh->do( "DROP TABLE IF EXISTS class" );
+
+    rmtree([$dir1, $dir2], 0, 1);
+}
+
+1;
+
+__DATA__
+DROP TABLE IF EXISTS storage_object;
+CREATE TABLE storage_object (
+    so_id BIGINT NOT NULL AUTO_INCREMENT,
+    ext_id VARCHAR(255) BINARY NOT NULL UNIQUE,
+    class_id TINYINT NOT NULL,
+    comment VARCHAR(255),
+    read_lock TINYINT DEFAULT 0 NOT NULL,
+    write_lock ENUM( 'write' ),
+    epoch TIMESTAMP NOT NULL,
+    PRIMARY KEY(so_id),
+    KEY(ext_id(64)),
+    KEY(class_id)
+) ENGINE=innodb;
+
+DROP TABLE IF EXISTS instance;
+CREATE TABLE instance (
+    ins_id BIGINT NOT NULL AUTO_INCREMENT,
+    so_id BIGINT NOT NULL,
+    uri VARCHAR(255) BINARY NOT NULL UNIQUE,
+    sha1sum CHAR(40),
+    assigned_location BOOL,
+    epoch TIMESTAMP NOT NULL,
+    atime TIMESTAMP NOT NULL,
+    PRIMARY KEY(ins_id),
+    KEY(so_id),
+    KEY(uri(64))
+) ENGINE=innodb;
+
+DROP TABLE IF EXISTS lock_record;
+CREATE TABLE lock_record (
+        so_id BIGINT NOT NULL,
+        type ENUM( 'read', 'write' ) NOT NULL,
+        epoch TIMESTAMP,
+        KEY(so_ID)
+    ) ENGINE=innodb;
+
+DROP TABLE IF EXISTS volume;
+CREATE TABLE volume (
+        vol_id INT NOT NULL AUTO_INCREMENT,
+        name VARCHAR(255) UNIQUE BINARY NOT NULL,
+        uri VARCHAR(255) BINARY NOT NULL,
+        key(vol_id)
+    ) ENGINE=innodb;
+
+DROP TABLE IF EXISTS class;
+CREATE TABLE class (
+        class_id TINYINT NOT NULL AUTO_INCREMENT,
+        instance TINYINT NOT NULL,
+        priority TINYINT,
+        comment VARCHAR(255),
+        key(class_id)
+    ) ENGINE=innodb;
Index: /tags/start/Nebulous/t/apache_03_server_create_object.x
===================================================================
--- /tags/start/Nebulous/t/apache_03_server_create_object.x	(revision 12606)
+++ /tags/start/Nebulous/t/apache_03_server_create_object.x	(revision 12606)
@@ -0,0 +1,95 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw(-withtestmore);
+
+plan tests => 11;
+
+use lib qw( ./t ./lib );
+
+use Apache::TestUtil;
+use PS::IPP::IData::Util qw( :standard );
+use SOAP::Lite;
+use Test::IData;
+
+my $hostport = Apache::Test::config()->{ 'hostport' };
+my $idata = SOAP::Lite->new(
+    proxy   => "http://$hostport/idata",
+    uri     => "http://pan-starrs.ifa.hawaii.edu/PS/IPP/IData/Server",
+);
+
+Test::IData->setup;
+
+{
+    # key
+    my $uri = $idata->create_object( "foo" )->result;
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, class
+    my $uri = $idata->create_object( "foo", 0 )->result;
+    $idata->delete_instance( $uri );
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, class, volume
+    my $uri = $idata->create_object( "foo", 0, "node01" )->result;
+    $idata->delete_instance( $uri );
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, class, volume, comment
+    my $uri = $idata->create_object( "foo", 0, "node01", "this is foo" )->result;
+    $idata->delete_instance( $uri );
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+    my $response = $idata->create_object( "foo" );
+
+    like( $response->faultstring, qr/Duplicate entry/, "object already exists" );
+}
+
+Test::IData->setup;
+
+{
+    my $response = $idata->create_object();
+
+    like( $response->faultstring, qr/2 - 4 were expected/, "no params" );
+}
+
+Test::IData->setup;
+
+{
+    my $response = $idata->create_object( 1, 2, 3, 4, 5 );
+
+    like( $response->faultstring, qr/2 - 4 were expected/, "too many params" );
+}
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous/t/apache_04_server_replicate_object.x
===================================================================
--- /tags/start/Nebulous/t/apache_04_server_replicate_object.x	(revision 12606)
+++ /tags/start/Nebulous/t/apache_04_server_replicate_object.x	(revision 12606)
@@ -0,0 +1,86 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw(-withtestmore);
+
+plan tests => 11;
+
+use lib qw( ./t ./lib );
+
+use Apache::TestUtil;
+use PS::IPP::IData::Util qw( :standard );
+use SOAP::Lite;
+use Test::IData;
+
+my $hostport = Apache::Test::config()->{ 'hostport' };
+my $idata = SOAP::Lite->new(
+    proxy   => "http://$hostport/idata",
+    uri     => "http://pan-starrs.ifa.hawaii.edu/PS/IPP/IData/Server",
+);
+
+Test::IData->setup;
+
+{
+    # key
+    $idata->create_object( "foo" );
+    my $uri = $idata->replicate_object( "foo" )->result;
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, $volume
+    $idata->create_object( "foo" );
+    my $uri = $idata->replicate_object( "foo", "node01" )->result;
+
+    ok( -e _get_file_path( $uri ), "file exists" );
+
+    like( $uri, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    # key, $volume
+    $idata->create_object( "foo" );
+    my $uri1 = $idata->replicate_object( "foo", "node01" )->result;
+    my $uri2 = $idata->replicate_object( "foo", "node02" )->result;
+
+    ok( -e _get_file_path( $uri1 ), "file exists" );
+    ok( -e _get_file_path( $uri2 ), "file exists" );
+
+    like( $uri1, qr/^file:\//, "valid URI" );
+    like( $uri2, qr/^file:\//, "valid URI" );
+}
+
+Test::IData->setup;
+
+{
+    my $response = $idata->replicate_object();
+
+    like( $response->faultstring, qr/1 - 2 were expected/, "no params" );
+}
+
+Test::IData->setup;
+
+{
+    my $response = $idata->replicate_object( 1, 2, 3 );
+
+    like( $response->faultstring, qr/1 - 2 were expected/, "too many params" );
+}
+
+Test::IData->setup;
+
+{
+    my $response = $idata->replicate_object( "foo" );
+
+    like( $response->faultstring, qr/storage object does not exist/, "storage object does not exist" );
+}
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous/t/apache_05_server_lock_object.x
===================================================================
--- /tags/start/Nebulous/t/apache_05_server_lock_object.x	(revision 12606)
+++ /tags/start/Nebulous/t/apache_05_server_lock_object.x	(revision 12606)
@@ -0,0 +1,129 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Apache::Test qw(-withtestmore);
+
+plan tests => 13;
+
+use lib qw( ./t ./lib );
+
+use Apache::TestUtil;
+use PS::IPP::IData::Util qw( :standard );
+use SOAP::Lite;
+use Test::IData;
+
+my $hostport = Apache::Test::config()->{ 'hostport' };
+my $idata = SOAP::Lite->new(
+    proxy   => "http://$hostport/idata",
+    uri     => "http://pan-starrs.ifa.hawaii.edu/PS/IPP/IData/Server",
+);
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    ok( $idata->lock_object( "foo", "read" )->result, "read lock" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    ok( $idata->lock_object( "foo", "read" )->result, "read lock" );
+    ok( $idata->lock_object( "foo", "read" )->result, "read lock" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    ok( $idata->lock_object( "foo", "write" )->result, "write lock" );
+}
+
+Test::IData->setup;
+
+{
+    my $result = $idata->lock_object( "foo", "read" );
+
+    like( $result->faultstring, qr/storage object does not exist/, "storage object does not exist" );
+}
+
+Test::IData->setup;
+
+{
+    my $result = $idata->lock_object( "foo", "write" );
+
+    like( $result->faultstring, qr/storage object does not exist/, "storage object does not exist" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    $idata->lock_object( "foo", "write" );
+    my $result = $idata->lock_object( "foo", "write" );
+
+    like( $result->faultstring, qr/can not write lock twice/, "can not write lock twice" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    $idata->lock_object( "foo", "read" );
+    my $result = $idata->lock_object( "foo", "write" );
+
+    like( $result->faultstring, qr/can not write lock after read lock/, "can not write lock after read lock" );
+}
+
+Test::IData->setup;
+
+{
+    $idata->create_object( "foo" );
+
+    $idata->lock_object( "foo", "write" );
+    my $result = $idata->lock_object( "foo", "read" );
+
+    like( $result->faultstring, qr/can not read lock after write lock/, "can not read lock after write lock" );
+}
+
+Test::IData->setup;
+
+{
+    my $result = $idata->lock_object();
+
+    like( $result->faultstring, qr/2 were expected/, "no params" );
+}
+
+Test::IData->setup;
+
+{
+    my $result = $idata->lock_object( "foo" );
+
+    like( $result->faultstring, qr/2 were expected/, "not enough params" );
+}
+
+Test::IData->setup;
+
+{
+    my $result = $idata->lock_object( "foo", "both" );
+
+    like( $result->faultstring, qr/is read or write/, "not read or write" );
+}
+
+Test::IData->setup;
+
+{
+    my $result = $idata->lock_object( "foo", 'read', 3 );
+
+    like( $result->faultstring, qr/2 were expected/, "too many params" );
+}
+
+Test::IData->cleanup;
Index: /tags/start/Nebulous/t/conf/extra.conf.in
===================================================================
--- /tags/start/Nebulous/t/conf/extra.conf.in	(revision 12606)
+++ /tags/start/Nebulous/t/conf/extra.conf.in	(revision 12606)
@@ -0,0 +1,31 @@
+#file:t/conf/extra.conf.in
+#-------------------------
+# this file will be Include-d by @ServerRoot@/httpd.conf
+
+# where PS::IPP::IData::Server::Apache can be found
+#PerlSwitches -I@ServerRoot@/../lib
+<perl>
+use lib qw( @ServerRoot@/../lib );
+</perl>
+
+PerlModule Apache::DBI
+PerlModule DBI
+PerlModule PS::IPP::IData::Server::Apache
+PerlModule PS::IPP::IData::Server
+
+<perl>
+Apache->push_handlers(
+    PerlChildInitHandler => sub {
+        PS::IPP::IData::Server->setup(
+            "DBI:mysql:database=test:host=localhost",
+            "test",
+            "",
+        );
+    },
+);
+</perl>
+
+<Location /idata>
+    SetHandler perl-script
+    PerlHandler PS::IPP::IData::Server::Apache
+</Location>
Index: /tags/start/Ohana/doc/README
===================================================================
--- /tags/start/Ohana/doc/README	(revision 12606)
+++ /tags/start/Ohana/doc/README	(revision 12606)
@@ -0,0 +1,46 @@
+Documenation for Ohana:
+
+ Ohana includes:
+
+   1) fits - FITS I/O library (Eugene Magnier) (V 1.0)
+	These are clean, C-like FITS interaction routines which are
+	meant to be easy to program with and easy to read, etc.
+
+   2) readline - the GNU readline library. (FSF / GNU) (V1.1)
+	This routines allow for easy emacs / vi-like cursor interactions.
+
+   3) opihi - a shell template program (Eugene Magnier) (V1.0)
+      This program provides a tcsh-like interaction with macros
+	and math capabilities.  It is meant to be a template for any
+	program which may require a shell-like interaction, macros, and math.
+
+   4) mana - an image manipulation program. (Eugene Magnier) (V1.0)
+	This program is in someways similar to MIDAS, IRAF, or Vista (the standard
+	astrophysics analysis packages).  However, mana is meant to be more 
+	stripped down (it is not a "do everything in the world" program!).
+	Mana also has three major advantages over the large programs:
+	  a) it is easy to modify (clean, friendly code!)
+	  b) it has a nice macro language with math at the shell input
+	  c) it has a tcsh-like cursor interaction
+
+   5) kii - display program for mana.
+	This is the X window display tool used by mana.  It is not meant to be run
+	by the user, only by mana.
+
+
+
+-----------------------------------------------------------------------------------------
+Notes
+
+Compiled successfully for HP730, gcc & cc
+
+Compiled successfully for Sparc 
+
+
+
+
+-----------------------------------------------------------------------------------------
+Problems / Bugs
+
+mana / kii are rather slow in general - can we do anything about this?
+
Index: /tags/start/Ohana/doc/README.mana
===================================================================
--- /tags/start/Ohana/doc/README.mana	(revision 12606)
+++ /tags/start/Ohana/doc/README.mana	(revision 12606)
@@ -0,0 +1,133 @@
+
+ April 26, 2000
+
+ I am providing the first release of 'mana' and the supporting
+ packages.  Here I will describe the needed steps to get the program
+ compiled and running. 
+
+Directory organization and Architecture selection:
+
+ Mana is part of a large collection of software called 'ohana'.  This
+ distribution of mana only includes the components of ohana needed for
+ mana.  The ohana collection is contained within a directory tree that
+ eases the use of the package on a multi-system network.  To this end,
+ there are separate bin and lib directories for different architecture
+ machines.  At the top level of 'ohana' there are the src, bin, lib,
+ and include directories.  bin and lib have subdirectories named
+ e.g. bin/linux, bin/sol, or bin/hp.  The Makefiles throughout 'ohana'
+ use an environment variable ARCH to decide which of these directories
+ is the appropriate destination.  Therefore:
+
+ BEFORE compiling any of the ohana programs, please set the ARCH
+ environment variable appropriately for your machine.  To do this
+ automatically, I use the following lines in my .cshrc:
+ 
+     ### automatically setting the ARCH variable:
+     set sys=`uname -s` 
+     switch ($sys)
+      case IRIX64:
+        setenv ARCH irix;
+        breaksw;
+      case SunOS:
+        set ver=`uname -r | awk '{print substr($1,1,1)}'`;
+        if ($ver == 5) then
+          setenv ARCH sol
+        else 
+          setenv ARCH sun4
+        endif
+        breaksw;
+      case Linux:
+        setenv ARCH linux;
+        breaksw;
+      case HP-UX:
+        setenv ARCH hp;
+        breaksw;
+      default:
+        echo "unknown architecture";
+        setenv ARCH unknown;
+        breaksw;
+     endsw
+
+  This mechanism also lets you set your PATH correctly, no matter what
+  architecture you are on.  just include in your PATH
+  /h/fred/src/ohana/bin/{$ARCH} (or whatever the path is to the ohana
+  package!).  
+
+  In order to configure the ohana package for your local installation,
+  edit the file ohana/Configure.  Change the entry for ROOT to point
+  to the correct location of the ohana package.  Also in Configure,
+  you can tell ohana to install things in a different location from
+  the ohana directory structure.
+
+  
+Necessary Libraries:
+
+  I've included in this distribution all of the necessary libraries to
+  compile mana.  Two of these are part of the ohana package: the fits
+  and ohana libraries.  These two should compile trivially when you
+  run make.  There are several other libraries that are typically
+  included in various UNIX installations, but are sometimes missing.
+  I've included them in this distribution in case you need them, but
+  the Makefiles are not well tuned to fit with the ohana layout.  In
+  particular, libjpeg and libpng you will have to compile by hand (ie,
+  by going into those directories and compiling there, not from the
+  top level ohana directory).  Install the resulting libraries and
+  include files in the appropriate locations (either in your system,
+  or just in the appropriate lib and include directores in ohana).
+  The readline library might compile correctly from the ohana
+  Makefile, but I am not sure of this. 
+
+  It is a good idea to try the mana compilation without dealing with
+  these libraries.  You'll find out soon enough which ones your
+  systems doesn't have!
+
+  The other oddity is the situation with libnsl and libsocket.  These
+  are required libraries for Suns, but not available (not even needed)
+  under linux.  To keep the same link lines in the Makefiles, I have
+  made a dummy version of libnsl and libsocket, which should be put in
+  ohana/lib/linux.  see the ohana/src/libdummy/Makefile for details.  
+
+Compiling and installing:
+
+  First of all, move Makefile.mana to Makefile.
+
+  If the libaries are all OK, then you should be able to compile and
+  install mana and the display programs kapa and kii with the command:
+
+  make install
+
+  
+Running Mana:
+
+  Just a couple of notes about running mana.  I'm hoping the commands
+  are generally obvious and the help files helpful...
+
+  When mana starts, it loads a resource file ~/.manarc.  This is just
+  a file with a bunch of mana commands.  They can include common macro
+  definitions, defining variables, or whatever.  I've included an
+  example as mana.rc in ohana/src/mana/doc/
+
+  Mana uses two external programs to display images and vector plots,
+  nominally called 'kii' and 'kapa'.  By default, it assumes those two
+  names, but user may change the names if needed.  Mana looks at the
+  variables (mana variables, not env variables) KAPA and KII to decide
+  the program names.  By default these are set to 'kapa' and 'kii'.
+  Type "echo $KAPA" or "echo $KII" in mana to see the current values.
+  If you need to place these programs outside your path or give them
+  different names, just assign these variables (perhaps in the
+  .manarc) to the correct names and they should work fine.
+
+  In the same way, mana looks for the help files in a preset location,
+  specifically the directory of the mana executable, subdirectory
+  mana.hlp.  So, if you have mana in /usr/local/bin, mana will look
+  for the help files in /usr/local/bin/mana.hlp.  But again, this can
+  be reassigned by the user by changing the mana variable HELPDIR.  
+
+  Two useful mana commands are ? and ??.  The first lists all commands
+  and gives a little helpline.  the second lists are currently defined
+  mana variables.
+
+
+
+  Eugene Magnier
+
Index: /tags/start/Ohana/doc/Todo
===================================================================
--- /tags/start/Ohana/doc/Todo	(revision 12606)
+++ /tags/start/Ohana/doc/Todo	(revision 12606)
@@ -0,0 +1,21 @@
+Things to do / fix in the ohana release
+
+1- error handling in FITS (fits_error_message)
+
+2- ohana PS overlay needs to be cleaned
+
+3- kii needs to handle ieee errors in the image without crshing
+
+4- check for kii errors if there is no image displayed
+
+5- loops in mana 
+
+6- better mana image math?  (parse expressions into RPN)
+
+7- mana logical image assignments
+
+8- mana: function to read a line from file into a variable
+
+9- variables from the image header
+
+10- more than 1 mana at a time
Index: /tags/start/Ohana/doc/allocate.txt
===================================================================
--- /tags/start/Ohana/doc/allocate.txt	(revision 12606)
+++ /tags/start/Ohana/doc/allocate.txt	(revision 12606)
@@ -0,0 +1,40 @@
+
+# define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+# define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+
+# ifndef ALLOCATE
+# define ALLOCATE(X,T,S)  \
+  X=(T *)malloc((unsigned) ((S)*sizeof(T)));\
+  if(X==NULL) \
+    { \
+      fprintf(stderr,"failed to malloc\n");\
+        exit(0);\
+    } 
+# define REALLOCATE(X,T,S) \
+  X=(T *)realloc(X,(unsigned) ((S)*sizeof(T))); \
+  if(X==NULL) \
+    { \
+       fprintf(stderr,"failed to realloc\n"); \
+       exit(0); \
+    }
+# endif /* ALLOCATE */
+
+example () {
+
+  float *fred;
+  int Nfred, NFRED, i;
+
+  NFRED = 100;
+  ALLOCATE (fred, float, NFRED);
+
+  for (i = 0; fscanf (stdin, "%f", &fred[i]) != EOF; i++) {
+    if (i == NFRED - 1) {
+      NFRED += 100;
+      REALLOCATE (fred, float, NFRED);
+    }
+  }
+  Nfred = i;
+  REALLOCATE (fred, float, MAX (Nfred, 1));
+
+}
+
Index: /tags/start/Ohana/doc/analysis.txt
===================================================================
--- /tags/start/Ohana/doc/analysis.txt	(revision 12606)
+++ /tags/start/Ohana/doc/analysis.txt	(revision 12606)
@@ -0,0 +1,25 @@
+
+major analysis steps:
+
+bias, flat, dark:	images (*.f)
+check images
+doscript:		parameter files (*.par_in)
+dophot:			object lists (*.obj_out), misc files (*.par_out, *.dout, *.shd_out)
+striphead:		header files (*.head)
+astro
+rastro
+relphot
+lightcurve
+absphot
+
+
+1) bias, dark, flat, zero bad columns
+2) create a file containing all image names (*.f)
+3) dosetup files:  this will
+    1) strip the headers (*.head),
+    2) run mana and ask you to choose a star for every image 
+	  (a good time to check the quality of each image)
+    3) create a script to run dophot (dophot.script)
+4) dophot.script
+5) 
+
Index: /tags/start/Ohana/doc/arguments.txt
===================================================================
--- /tags/start/Ohana/doc/arguments.txt	(revision 12606)
+++ /tags/start/Ohana/doc/arguments.txt	(revision 12606)
@@ -0,0 +1,63 @@
+# include <stdio.h>
+
+int get_argument (int argc, char **argv, char *arg) {
+
+  int i;
+
+  for (i = 0; i < argc; i++) {
+    if (!strcmp(argv[i], arg))
+      return (i);
+  }
+  
+  return ((int) NULL);
+}
+
+int remove_argument (int N, int *argc, char **argv) {
+
+  int i;
+
+  if ((N != (int) NULL) && (N != 0)) {
+    (*argc)--;
+    for (i = N; i < *argc; i++) {
+      argv[i] = argv[i+1];
+    }
+  }
+
+  return (N);
+    
+}
+
+main (int argc, char **argv) {
+
+  int VERBOSE;
+  float size;
+
+  /* example of an optional argument */
+  VERBOSE = FALSE;
+  if (N = get_argument (argc, argv, "-v")) {
+    remove_argument (i, &argc, argv);
+    VERBOSE = TRUE;
+  }
+
+  /* one way to do an required argument */
+  size = -1;
+  if (N = get_argument (argc, argv, "-s")) {
+    remove_argument (i, &argc, argv);
+    size = atof (argv[N]);
+    remove_argument (i, &argc, argv);
+  }
+  if (size < 0) {
+    fprintf (stderr, "USAGE: program (file) -s (size) \n");
+    exit (1);
+  }
+
+  /* another way to demand an argument */
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: program (file) -s (size) \n");
+    exit (1);
+  }
+
+}
+
+
+   
Index: /tags/start/Ohana/doc/compiling.txt
===================================================================
--- /tags/start/Ohana/doc/compiling.txt	(revision 12606)
+++ /tags/start/Ohana/doc/compiling.txt	(revision 12606)
@@ -0,0 +1,24 @@
+
+There are a few steps needed to compile spicam.  First, untar the
+ohana.tgz file.  Edit the file Configure in the top-level directory.
+ROOT should be the path of the top-level directory.  There are some
+destination directories, places where compiled things will go.  there
+are also two lines for the X library and include directories, though
+spicam does not require this information.  
+
+There are a couple of libraries that need to be compiled to make
+spicam.  first,  type "make install.ohana".  this will compile a set
+of miscellaneous libraries and install the file libohana.a in your
+LDIR (defined in Configure).  Next, type "make install.fits".  this
+will compile the FITS library and install libFITS.a in LDIR (note that
+this is not the Goddard fitsio package...).  Next, you need readline,
+so if you don't have it already, type "make install.readline".  same
+thing.  
+
+finally, you are ready to compile spicam.  type "make install.spicam"
+and it should compile OK.  
+
+good luck!
+
+gene
+ 
Index: /tags/start/Ohana/doc/elixir-todo.txt
===================================================================
--- /tags/start/Ohana/doc/elixir-todo.txt	(revision 12606)
+++ /tags/start/Ohana/doc/elixir-todo.txt	(revision 12606)
@@ -0,0 +1,26 @@
+
+Cleaning the Ohana portion of Elixir:
+
+Goals: 
+  - enable CVS
+  - allow for tarball releases of ohana & subsets
+  - clean up the software configuration
+
+- identify external dependencies
+  * libpng
+  * libjpeg
+  * readline
+
+- move notes & documentation to a single location
+
+- fix the compile system for 'misc' to match the others
+
+- remove the links / save links in a tarball
+
+- compilation should be possible with just:
+
+  configure
+  make
+
+  do this by hand
+
Index: /tags/start/Ohana/doc/exclude
===================================================================
--- /tags/start/Ohana/doc/exclude	(revision 12606)
+++ /tags/start/Ohana/doc/exclude	(revision 12606)
@@ -0,0 +1,4 @@
+find ohana -name "*.o" -print > exclude.files 
+find ohana -name "bin" -print >> exclude.files
+find ohana -name "*.a" -print >> exclude.files
+tar cvfX - exclude.files ohana | gzip > ohana.tgz.8.97 
Index: /tags/start/Ohana/doc/exclude.list
===================================================================
--- /tags/start/Ohana/doc/exclude.list	(revision 12606)
+++ /tags/start/Ohana/doc/exclude.list	(revision 12606)
@@ -0,0 +1,19 @@
+Configure
+bin
+*.sol*
+*.sid*
+*.linux*
+*.lin64*
+*.o
+*.a
+*.so
+*~
+#*
+.mana
+.status
+.dvo
+RCS
+lib/sol
+lib/sid
+lib/linux
+lib/lin64
Index: /tags/start/Ohana/doc/gnu.license
===================================================================
--- /tags/start/Ohana/doc/gnu.license	(revision 12606)
+++ /tags/start/Ohana/doc/gnu.license	(revision 12606)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: /tags/start/Ohana/doc/graphics.info
===================================================================
--- /tags/start/Ohana/doc/graphics.info	(revision 12606)
+++ /tags/start/Ohana/doc/graphics.info	(revision 12606)
@@ -0,0 +1,1595 @@
+This is Info file graphics.info, produced by Makeinfo-1.55 from the
+input file graphics.texi.
+
+   This file documents GNU graphics.
+
+   Copyright (C) 1989 Free Software Foundation, Inc.
+
+
+File: graphics.info,  Node: Top,  Up: (dir)
+
+* Menu:
+
+* introduction::         About the GNU graphics utilities
+* graph examples::       Using Graph to create plot files from data
+* graph invocation::     Command line options for Graph.
+* plot2ps examples::     converting plot files to PostScript
+* plot2ps invocation::   Plot2ps Command Line Options
+* xplot::                a plot file previewer for X11
+* xplot invocation::     xplot command line options and X11 resources
+* plot2fig examples::    converting plot files to Fig graphics editor format
+* plot2fig invocation::  command line options for plot2fig
+* plot2tek invocation::  Tektronix 4010 output
+* latex example::        Including a Figure in an Article
+* psfig::                Options to `psfig' for Including Figures
+* atend.pl::             A perl script for use with psfig
+* dvips::                How to Get `dvips'
+* idraw::                How to Get `idraw'
+* ghostscript::          an X11 PostScript interpreter/previewer
+* libps::                The Library of Plot Functions for PostScript Output
+* files::                The Plot File Format
+* Acknowledgements::     The Contributors
+* Function Index::       An Index to the libps Functions
+
+
+File: graphics.info,  Node: introduction,  Next: graph examples,  Up: Top
+
+The GNU Graphics Utilities
+**************************
+
+   The GNU graphics utilities are a set of programs for plotting
+scientific data.  The program `graph' reads data files and writes a
+stream of plotting commands in a device independent format refered to
+below as a GNU plot file.  The remaining programs provide support for
+displaying GNU plot files on tektronix 4010, PostScript (TM)*, and X
+window system compatible output devices.
+
+   `graph' reads both ascii and binary data files and writes a plot
+file with or without axes and labels.  You can specify labels and ranges
+for the axes, and you can set the sizes and position of the plot on the
+page.  Each invocation of graph produces a plot with single set of axes
+and data.  You can place an arbitrary number of plots on the page by
+concatenating the plot output of several invocations.
+
+   `plot2ps' is a utility for converting plot files into PostScript.
+The `plot2ps' utility reads plotting commands from named files or the
+standard input and writes PostScript to the standard output.  You can
+then print the PostScript output on a printer, or edit it using the
+`idraw' graphics editor.  You can also easily include the output in
+LaTeX documents using `dvips' and the LaTeX command `psfig'.
+
+   Why is this useful? The plot file format is a common standard on un*x
+systems.  To produces figures for publication, you might need to take
+data sets, and produce labeled figures from them.  This can be done
+using `graph', `plot2ps' and the `idraw' editor.  You can also include
+these figures in LaTeX documents using the `dvips' utility.  All of
+these utilities, as well as the plot file format and plot library, are
+discussed in the following sections.
+
+   This documentation is under revision.  Any comments, suggestions, or
+additions would greatly benifit GNU users.  Please mail them to either
+`bug-gnu-utils@prep.ai.mit.edu' or `Rich@Rice.edu'.
+
+   * PostScript is a trademark of Adobe Systems Incorporated.
+
+
+File: graphics.info,  Node: graph examples,  Next: graph invocation,  Prev: introduction,  Up: Top
+
+`graph' Examples
+================
+
+   Each invocation of `graph' plots data read from stdin or named files
+togeather in a single plot with or without axes and labels.  The
+following sections show common usage of `graph'.
+
+* Menu:
+
+* Invocation::		Simple examples using graph
+* Input Files::		What the input looks like
+* Overlaying::		Combining several data sets in one plot
+* Multiple Plots::	Multiple plots on one page
+* Binary Data::		Reading other data formats
+
+
+File: graphics.info,  Node: Invocation,  Next: Input Files,  Up: graph examples
+
+Simple examples using graph
+===========================
+
+   By default, `graph' reads ascii data from the standard input or
+files specified on the command line.  `graph' reads pairs of values, x
+and y coordinates:
+
+     0.0  0.0
+     1.0  0.2
+     2.0  0.0
+     3.0  0.4
+     4.0  0.2
+     5.0  0.6
+
+   To plot this data, you might use
+
+     graph < ascii_data_file |plot
+
+   where ascii_data_file could contain data similar to the above
+example.  You can replace the command `plot' with `plot2tek' if you have
+a tektronix 4010 compatible graphics terminal, `plot2ps' if you have a
+postscript compatible printer or previewer, or `xplot' if you have an X
+window system display.
+
+   Note that `graph' is commonly supplied with some operating systems.
+If so, some confusion may arise if the system supplied version is
+executed mistakenly.  On unix systems, you can determine which version
+you invoke by typing the command `which graph', which prints the file
+name of the version you invoke by default.
+
+   To reduce the change the size of the plot and position it in the
+middle of the display, you could use
+
+     graph -h .4 -w .4 -r .2 -u .2 < ascii_data_file |plot
+
+   where `h' and `w' are the height and width of the plot and `r' and
+`u' indicate how far up and to the right the plot is positioned.
+
+   You can put symbols at each data point using
+
+     graph -S 2 .01 < ascii_data_file |plot
+
+   where 2 indicates which symbol to plot, and .01 indicates it's size.
+
+   You can choose the type of line draw on each curve:
+
+     graph -m 2 < ascii_data_file |plot
+
+   where 2 indicates what kind of line connects the data points.
+
+
+File: graphics.info,  Node: Input Files,  Next: Overlaying,  Prev: Invocation,  Up: graph examples
+
+The format of input to `graph'
+==============================
+
+   As mentioned above, by default `graph' reads ascii pairs of values,
+x and y coordinates, from the standard input or files specified on the
+command line.  Optional labels may be placed after each coordinate in
+the data file.  The label ends at the end of the line:
+
+     3.0  0.4 this is a label for point (3.0, 0.4).
+
+   The label must be enclosed in double quotes if it would otherwise be
+appear to be a coordinate:
+
+     3.0  0.4 "5.0 looks like a value."
+
+   You can use the `-b' to break lines after each label in the input.
+Use a pair of empty double quotes if you need to break a line, but do
+not need a label.
+
+     0.0  0.0
+     2.0  0.0
+     1.0  0.2
+     ""
+     0.0  0.1
+     2.0  0.2
+     4.0  0.3
+
+   You can also break cuves using `-M' option to break lines whenever
+the abscissal values between successive pairs of points decrease.  When
+using `-M', each continuous curve has monotonicly increasing abscissal
+values.
+
+     0.0  0.0 first data set
+     2.0  0.0
+     4.0  0.2
+     0.0  0.1 second data set
+     2.0  0.2
+     4.0  0.3
+
+   `graph' will automaticly generate abscissal values for you if you
+specify the `-a' option.  Only ordinate values are given in the data,
+and the data is then assumed to be equally sampled along the abscissa.
+The values following `-a' on the command line specify the sampling
+interval and the abscissal value of the first data point.
+
+     0.0
+     0.1
+     0.2 label for point (2.0, 0.2)
+     0.3
+     0.2
+     0.3
+
+
+File: graphics.info,  Node: Overlaying,  Next: Multiple Plots,  Prev: Input Files,  Up: graph examples
+
+Combining several data sets in one plot
+=======================================
+
+   There are cases where you will want to superimpose several data sets
+or several plots on top of each other.  If for example, the data sets
+are in seperate files, you can specify each by it's name on the command
+line.  Since `graph' reads the standard input only if no files are
+named on the command line, you must add the name `--' if you want
+`graph' to read the standard input as well.
+
+     graph data-file-one data-file-two data-file-three |plot
+
+   For comparison sake, you might wish to distinguish the data in one
+set from another either by using different symbols at each point or by
+distinguishing the type of line draw.  You can do this by preceeding
+each file name with options affecting the synbol or line style used to
+plot that data.
+
+     graph -S 1 data-file-one -S 3 data-file-two -S 4 data-file-three |plot
+     
+     or
+     
+     graph -m 1 data-file-one -m 3 data-file-two -S 4 data-file-three |plot
+
+   If you need to superimpose several data sets, but must invoke graph
+seperately for each, you will have to specify the limits of the axes.
+
+     graph -x 0 100 -y -3 3 -S 3 -m -1 < ascii_data_file_1 >> plot_file
+
+   where `-x 0 100' specifies the limits on the x axis, `-y -3 3'
+specifies the limits on the y axis, `-S 2' specifies a box to be drawn
+at each point, and `-m -1' specifies that no line is to be draw
+connecting the points.  You can overlay a second data set on the first
+by using:
+
+     graph -s -g 0 -x 0 100 -y -3 3 -m 0 < ascii_data_file_1 >> plot_file
+
+   where `-s' avoids erasing the page, `-g 0' avoids drawing the axis,
+tick marks and labels which were drawn previously, and `-m 0' specifies
+that solid lines are draw connecting the points.
+
+
+File: graphics.info,  Node: Multiple Plots,  Next: Binary Data,  Prev: Overlaying,  Up: graph examples
+
+How to put multiple plots on one page
+=====================================
+
+   The command
+     graph -h .4 -w .4 -r .1 -u .1 < ascii_data_file_1 >  plot_file
+
+   will put a single box containing the plot in the lower left hand
+quarter of the page.  You can add another plot to the upper left hand
+corner of the page using the command
+
+     graph -s -h .4 -w .4 -r .1 -u .6 < ascii_data_file_2 >> plot_file
+
+   Be sure you use the `-s' option so the the first plot isn't erased.
+
+   Likewise you can add plots to the right hand side of the page using
+
+     graph -s -h .4 -w .4 -r .6 -u .1 < ascii_data_file_3 >> plot_file
+     graph -s -h .4 -w .4 -r .6 -u .6 < ascii_data_file_4 >> plot_file
+
+   The tick marks can be moved inside the box and labels moved to the
+opposite sides using
+
+     graph -T -.005 < ascii_data_file >> plot_file
+
+
+File: graphics.info,  Node: Binary Data,  Prev: Multiple Plots,  Up: graph examples
+
+Reading other data formats
+==========================
+
+   `graph' will read binary data in integer, short integer, float, and
+double float format when you use the `-d' option followed by `f', or
+`d', respectively.  There are two advantage to using binary data: 1)
+`graph' runs significantly faster because the computational overhead
+for converting data from ascii to binary is eliminated, and 2) the
+input files can be significantly smaller than the ascii format would
+be.  Double float is the fastest format to read, while short integer is
+the most space conservative.  If you have very large data sets, using a
+binary format can reduce storage and runtime costs.
+
+   For example, you can create double float data as output from C
+language programs:
+
+     #include <stdio.h>
+     void write_point (x, y)
+       double x, y;
+     {
+       fwrite(&x, sizeof (double), 1, stdout);
+       fwrite(&y, sizeof (double), 1, stdout);
+     }
+
+   You can then plot data written this way using:
+
+     graph -d d <datafile >plotfile
+
+
+File: graphics.info,  Node: graph invocation,  Next: plot2ps examples,  Prev: graph examples,  Up: Top
+
+Graph Command Line Options
+==========================
+
+   The following table describes each of the command line arguments to
+graph.  Each option which takes an argument is followed by the type and
+default values of the argument in parentheses.
+
+`-a [STEP_SIZE [LOWER_LIMIT]]'
+`+auto-abscissa [STEP_SIZE [LOWER_LIMIT]]'
+     (floats, defaults 1 and 0) Automaticly generate abscissa (x)
+     values.  This option specifies that the data contains only
+     ordinate (y) values.  The difference between successive x values
+     will be STEP_SIZE, and the first x value will be LOWER_LIMIT.  To
+     return to reading abscissal values from the input you can specify
+     `-a 0', which disables automatic generation of the abscissa and
+     returns STEP_SIZE and LOWER_LIMIT to their default values.
+
+`-b'
+`+break-on-labels'
+     Assumes multiple data sets are in the data file, and the data sets
+     are separated by a label.  The default is don't break on labels.
+
+`-M'
+`+break-non-monotone'
+     When successive abscissa (x) values decrease, a separate data set
+     is assumed.  This allows multiple data sets in each file.  Similar
+     to `-b'.
+
+`-f SIZE'
+`+fontsize SIZE'
+     Specify the size of the desired font as SIZE points.  Not all
+     display devices will honor this command.
+
+`-N X|Y'
+`+no-label X|Y'
+     By default, values at each tick mark are labeled beside the axis.
+     This option removes the labeling of the tick marks on the specified
+     axis.
+
+`-R'
+`+dont-round-to-next-tick'
+     By default, the ends of the axes are extended to the next tick
+     mark.  This option prohibits rounding the limits of the axes to
+     the next tick mark.
+
+`-c STRING'
+`+point-label STRING'
+     This option defines STRING as the default label for each point.
+     Any label in the input will override this default.
+
+`-S SYMBOL_NUMBER [SYMBOL_SIZE]'
+`+symbol SYMBOL_NUMBER [SYMBOL_SIZE]'
+     (integer and float, defaults -1 and 0.01) Draw a symbol at each
+     point in the data. SYMBOL_NUMBER specifies the shape of the symbol
+     according to the following table and SYMBOL_SIZE specifies the
+     fractional size of the symbol with respect to the height and width
+     of the plot.  Note that you can specify symbols to be drawn
+     without any line connecting them by specifying the option `-m -1'.
+    -1 no symbol at all
+    0 plus sign (+)
+    1 cross (x)
+    2 star (*)
+    3 box
+    4 diamond
+    5 circle
+`-T TICK_SIZE'
+`+ticksize TICK_SIZE'
+     (float, default .01) TICK_SIZE is the fractional size of the tick
+     marks on each axis.  A value of 1.0 produces tick marks on the x
+     (y) axis whose length is equal to the width (height) of the plot.
+
+`-X X_LABEL'
+`+xtitle X_LABEL'
+     (string, default blank) X_LABEL is a label printed below the x
+     axis.
+
+`-Y Y_LABEL'
+`+ytitle Y_LABEL'
+     (string, default blank) Y_LABEL is a label printed to the right of
+     the y axis.
+
+`-d DATA-FORMAT'
+`+data-format DATA-FORMAT'
+     This specifies what format the input data is in.  Note labels can
+     be used only in ascii format input files.
+    `a'
+    `A'
+          ascii data
+
+    `i'
+    `I'
+          binary integer data
+
+    `s'
+    `S'
+          binary short integer data
+
+    `f'
+    `F'
+          binary float data
+
+    `d'
+    `D'
+          binary double data
+
+`+debug'
+     Debugging information, including the data read in, is sent to the
+     standard error output.
+
+`-g GRID_STYLE'
+`+grid GRID_STYLE'
+     (integer, default 1) GRID_STYLE specifies the type of box framing
+     the plot and whether grid lines are drawn inside the box.
+    0 no box around plot, no axes, no labels.
+    1 box containing a grid and axes with tick marks and labels.
+    2 box around plot, tick marks around the box and labels.
+    3 box around plot, ticks on left and lower sides only and labels.
+    4 axes intersect at the origin without a box or grid.
+`-h HEIGHT'
+`+height-plot HEIGHT'
+     (float, default 0.8) HEIGHT specifies the fractional height of the
+     plot with respect to the height of the plotting area.  A value of
+     1.0 will produce a box which fills the available area.  Note that
+     the tick marks and labels are outside this area so that values
+     less than 1.0 are generally used.
+
+`-L TOP_LABEL'
+`+toptitle TOP_LABEL'
+     (string, default blank) TOP_LABEL is a label placed above the plot.
+
+`-m LINE_MODE'
+`+linestyle LINE_MODE'
+     (integer, default 0) LINE_MODE specifies the mode (or style) of
+     lines drawn between data points.
+    -1 no line at all
+    0 solid
+    1 dotted
+    2 shortdashed
+    3 dotdashed
+    4 longdashed
+    5 disconnected
+`-r RIGHT'
+`+right-margin-posn RIGHT'
+     (float, default 0.1) Move the plot to the right by a fractional
+     amount RIGHT with respect to the width of the plotting area.  This
+     produces a margin on the left hand side of the plot.  A value of
+     0.5 will produce a margin half the width of the available area.
+     Note that the tick marks and labels are drawn in the margin.
+
+`-u UP'
+`+bottom-margin-posn UP'
+     (float, default 0.1) Move the plot up by a fractional amount UP
+     with respect to the height of the plotting area.  This produces a
+     margin below the plot.  A value of 0.5 will produce a margin half
+     the height of the available area.  Note that the tick marks and
+     labels are drawn in the margin.
+
+`-s'
+`+save-screen'
+     Save the screen. This option prevent graph from erasing the
+     previous contents of the graphics window or device.
+
+`-t'
+`+transpose'
+     Transpose the abscissa and ordinate.  This option causes the axes
+     to be interchanged, and the options which apply to each axis to be
+     applied to the opposite axis.  That is, data is read in as (y, x)
+     pairs and `-x', `-X' and `-lx' apply to the y axis.
+
+`-w WIDTH'
+`+width-plot WIDTH'
+     (float, default 0.8) WIDTH specifies the fractional width of the
+     plot with respect to the width of the plotting area.  A value of
+     1.0 will produce a box which fills the available area.  Note that
+     the tick marks and labels are outside this area, so values less
+     than 1.0 are generally used.
+
+`-x LOWER_LIMIT UPPER_LIMIT'
+`+xlimits LOWER_LIMIT UPPER_LIMIT'
+     (floats) The arguments LOWER_LIMIT and UPPER_LIMIT specify the
+     limits of the x axis. By default the upper and lower limits are
+     taken from the data.  If unspecified the limits of the data are
+     used.
+
+`-y LOWER_LIMIT UPPER_LIMIT'
+`+ylimits LOWER_LIMIT UPPER_LIMIT'
+     These arguments specify the scale and limits of the y axis as for
+     the x axis above.
+
+`-l X|Y'
+`+log-axis X|Y'
+     The argument indicates which axis should be a log axis.  Either
+     one or both x- and y-axes can be specified by using the
+     appropriate letter.  Use XY or YX to specify both.
+
+`+high-byte-first'
+`+low-byte-first'
+     These options force graph to use the specified byte order when
+     writing out the plot file.  By default the byte order is host
+     dependent.
+
+
+File: graphics.info,  Node: plot2ps examples,  Next: plot2ps invocation,  Prev: graph invocation,  Up: Top
+
+Examples Using `plot2ps'
+========================
+
+   To produce a plot of data arranged in ordered pairs of x and y
+coordinates in an ASCII file, you can use:
+
+     graph <asciiDataFile | plot2ps | lpr -Plw
+
+   To create a simple PostScript figure you can use:
+
+     echo 0 0 1 1 2 0 | spline | graph | plot2ps > test.ps
+
+   To edit the plot:
+
+     idraw test.ps
+
+   To use the previewer to look at the plot:
+
+     gs test.ps
+
+
+File: graphics.info,  Node: plot2ps invocation,  Next: xplot,  Prev: plot2ps examples,  Up: Top
+
+Plot2ps Command Line Options
+============================
+
+   `plot2ps' is a relatively simple utility in that there are few
+command line options to choose from.  The plot file format does not
+contain methods for specifying font or font size, so you must specify
+these things with options.  There are no other options for controlling
+the picture.
+
+   The plot file format is machine dependent on the byte order of
+unformatted, signed, two byte integer coordinates contained in plot
+commands.  The `-high-byte-first' or `-low-byte-first' option specifies
+this order explicitly.  `plot2ps' attempts to determine the byte order
+from commands early in the plot file, but the method is heuristic and
+is not foolproof.  Several standard plot sizes specified by the `open'
+command are used to recognize byte order by `plot2ps'.  If these sizes
+are recognized in byte reversed order, `plot2ps' adjusts accordingly.
+These sizes include 504x504, 2048x2048 (versatek plotters), 2100x2100,
+3120x3120(tektronix 4010 terminals) and 4096x4096 (gsi 300 terminals).
+
+   The remaining command line options may be used specify an alternate
+PostScript prologue and to print the licensing information.
+
+   Input plot files names may be specified anywhere on the command line.
+If no file names are specified, or the name `-' is specified, the
+standard input is read for plotting instructions.  Only the font or
+font size options which precede a file name will affect the text for
+that file.
+`-H'
+`+help'
+     The help option prints a summary of command line syntax for
+     `plot2ps', a list of the font names (the standard builtin
+     PostScript fonts), and version, copyright and warranty information.
+     Specifying this options causes plot2ps to ignore files on the
+     standard input.  You can specify a file on the standard input
+     explicitly with the option `-' if you want it to read the standard
+     input as well.
+
+`-v'
+`-V'
+`+version'
+     This option prints version, copyright and warranty information.
+
+`-fontsize SIZE'
+`-f SIZE'
+     The fontsize options specifies the default size in printer's points
+     (1/72 inch) of all text appearing in the plot.  If unspecified, the
+     size defaults to 14 points.
+
+     Some sizes are supported better than others under X windows.  The
+     standard sizes distributed with X windows are 8, 10, 12, 14, 18,
+     and 24 points.  Text at these point sizes will display correctly
+     in the `idraw' editor.  Other font sizes will print correctly on a
+     PostScript device such as the laserwriter, but may not appear at
+     the correct size in the `idraw' editor.
+
+`-font NAME'
+`-fo NAME'
+     The font name option specifies the name of the default font for all
+     text appearing in the plot.  `plot2ps -help' prints a listing of
+     the font names on the standard output.  These names include the
+     available builtin fonts on standard PostScript printers.
+
+`-high-byte-first'
+`-h'
+     The high-byte-first option specifies explicitly that the higher
+     order byte of each signed, two byte integer occurs first in the
+     file.  It disables determination of byte order from the file
+     itself.
+
+`-line-width WIDTH'
+     WIDTH is the width of lines drawn in the plot, and defaults to a
+     value of 0.  A value of 0 will produce the thinest line possible
+     in a device dependent fashion, however this is known to cause
+     problems for older versions of idraw.  The line width is device
+     independent for a positive values of WIDTH.
+
+`-low-byte-first'
+`-l'
+     The low-byte-first option specifies explicitly that the lower order
+     byte of each signed, two byte integer occurs first in the file.  It
+     disables determination of byte order from the file itself.
+
+`-prologue FILENAME'
+`-p FILENAME'
+     The prologue option specifies the name of an alternate PostScript
+     prologue FILENAME to be used in place of the default `idraw'
+     prologue.  The prologue declares procedures used to draw each
+     graphic object.  The default prologue was generously provided by
+     John Interante and is a part of the InterViews distribution,
+     version 2.5.
+
+`-copying'
+`-warranty'
+     The copying and warranty options print a copy of the GNU General
+     Public License on the standard error output.  Included is
+     conditions for copying `plot2ps' and information on the lack of any
+     warranty.
+
+     These conditions do not cover the output of `plot2ps'.  The only
+     conditions imposed on the output are those which come from the
+     prologue that you are using.
+
+`-signed'
+`-unsigned'
+     The signed and unsigned options specify whether coordinates in the
+     plot file are signed.  By convention, coordinates are always
+     signed.  Some plot files do not follow this convention, and you
+     can use the unsigned option to convert those files.
+
+`-bbox'
+     The bbox option specifies that a bounding box comment will be
+     written at the end of the output file.  This information is useful
+     for document preparation systems which determine how to size and
+     place the figure using the bounding box.  See also the atend
+     script.
+
+
+File: graphics.info,  Node: xplot,  Next: xplot invocation,  Prev: plot2ps invocation,  Up: Top
+
+A plot file previewer for X11
+=============================
+
+   `xplot' is a plot file previewer for the X window system.  It reads
+GNU plot commands from its standard input and draws the resulting
+graphics in an X window.
+
+   After xplot reaches the end-of-file on the input, it puts itself in
+the background (forks).  Control returns to the calling program, while
+xplot continues, remaining on screen.
+
+   To exit, click the left mouse button in the xplot window.  Note that
+xplot ignores SIGHUP signals, so you must use another signal to kill
+xplot if necessary.
+
+
+File: graphics.info,  Node: xplot invocation,  Next: Plot2fig Examples,  Prev: xplot,  Up: Top
+
+Xplot Options
+=============
+
+   `xplot' accepts all of the standard X toolkit command line options,
+and the initial geometry specification determines the resolution, with a
+default geometry of 500x500 pixels.
+
+   The following standard X Toolkit command line arguments may be used
+with `xplot':
+`-bg COLOR'
+     This specifies the color to use for the background of the window.
+     The default is WHITE.
+
+`-bd COLOR'
+     This specifies the color to use for the border of the window.  The
+     default is BLACK.
+
+`-bw NUMBER'
+     This specifies the width in pixels of the border surrounding the
+     window.
+
+`-fg COLOR'
+     This specifies the color to use for displaying text.  The default
+     is BLACK.
+
+`-fn FONT'
+     This specifies the font to be used for displaying normal text.  The
+     default is 6X10.
+
+`-rv'
+     This indicates that reverse video should be simulated by swapping
+     the foreground and background colors.
+
+`-geometry GEOMETRY'
+     This specifies the preferred size and position of the plot window.
+
+`-display HOST:DISPLAY'
+     This specifies the X server to contact.
+
+`-xrm RESOURCESTRING'
+     This specifies a toolkit resource property.  See the manual page
+     for xrdb.
+
+   `xplot' uses the athena Command widget in the X Toolkit.  So, it
+understands all of the core resource names and classes as well as:
+`reverseVideo'
+     (class ReverseVideo) Specifies that the foreground and background
+     colors should be reversed.
+
+Example
+-------
+
+   The resources:
+
+     Xplot.font: 6x9
+     Xplot.geometry: 300x300
+
+   will set the font used in the plot window to `6x9' and the size of
+the window to 300 by 300 pixels.
+
+
+File: graphics.info,  Node: Plot2fig Examples,  Next: plot2fig invocation,  Prev: xplot invocation,  Up: Top
+
+Using Plot2fig
+==============
+
+   To create a simple plot file one can use:
+
+     echo 0 0 1 1 2 0 | spline | graph | plot2fig > test.fig
+
+   To edit the plot:
+
+     fig test.fig
+
+   To convert the fig file into dvi code, create a latex file containing
+a document which includes the figure:
+
+     \\documentstyle\[\]{article}
+     \\begin{document}
+     \\input{test}
+     \\end{document}
+
+   Then, run transfig on the figure and latex on the document:
+
+     % transfig -L latex test.fig
+     % make test.tex
+     % latex t.tex
+
+   To edit a plot of data arranged in ordered pairs of x and y
+coordinates in an ascii file, one can use:
+
+     % graph <asciiDataFile | plot2fig >file.fig
+     % fig file.fig
+
+
+File: graphics.info,  Node: plot2fig invocation,  Next: plot2tek invocation,  Prev: plot2fig examples,  Up: Top
+
+A plot file to fig file translator
+==================================
+
+   `plot2fig' reads plotting instructions from the specified input
+files and/or the standard input and produces `Fig' compatible code on
+it's standard output.  This output file can be edited with the fig
+(Facility for Interactive Generation of figures) graphics editor.  The
+output can subsequently be converted to pictex, PostScript, latex, epic,
+eepic, and tpic languages using the `transfig' translator.
+
+   Any unrecognized options on the command line are assumed to be input
+files.  The standard input is read by default only if no other files
+specified on the command line are successfully opened.  A single dash
+(-) on the command line indicates the standard input is to be read.
+Each option is set and each file read in the order they are specified on
+the command line.
+
+   For compatibility with pic2fig, plot2fig ignores leading white space
+in labels.  Labels containing all white space are ignored.
+
+`-fn NAME'
+`-fontname NAME'
+     Default: the default font of the transfig output device.  This
+     option sets the font for all subsequent text to NAME.  Recognized
+     font names are typewriter, modern, italic, bold, and times.  In
+     addition, courier is an alias for typewriter and roman is an alias
+     for times.  Note that the fonts are device dependent.
+
+`-fs SIZE'
+`-fontsize SIZE'
+     Default: 12. This option sets the size of subsequent text to SIZE
+     (in printer's points).
+
+`-h'
+`-high-byte-first'
+     This option specifies that the byte ordering of two byte integers
+     in the input plot file is high byte first.
+
+`-l'
+`-low-byte-first'
+     This option specifies that the byte ordering of two byte integers
+     in the input plot file is low byte first.
+
+`-warranty'
+`-copying'
+     This option prints out the copying conditions and warranty
+     information.
+
+`-signed'
+`-unsigned'
+     Default: signed.  This option specifies whether two byte integers
+     in the input plot file are unsigned or signed.
+
+`-'
+     This option specifies explicitly that the standard input should be
+     read for plotting instructions.
+
+
+File: graphics.info,  Node: plot2tek invocation,  Next: latex example,  Prev: plot2fig invocation,  Up: Top
+
+Tektronix 4010 output
+=====================
+
+`-H'
+`+help'
+     The help option prints a summary of command line syntax, a list of
+     the known font names, and version, copyright and warranty
+     information.  Specifying this options causes plot to ignore the
+     standard input, so you must specify the option `-' if you want it
+     to read the standard input as well.
+
+`-v'
+`-V'
+`+version'
+     This option prints version, copyright and warranty information.
+
+`-f SIZE'
+`+fontsize SIZE'
+     The fontsize options specifies the default size in printer's points
+     (1/72 inch) of all text appearing in the plot.  If unspecified, the
+     size defaults to 14 points.
+
+`+high-byte-first'
+`+low-byte-first'
+     These options force graph to use the specified byte order when
+     writing out the plot file.  By default the byte order is host
+     dependent.
+
+`-F NAME'
+`+fontname NAME'
+     The font name option specifies the name of the default font for all
+     text appearing in the plot.  `plot -help' prints a listing of the
+     font names on the standard output.  These names include the
+     available builtin fonts on standard PostScript printers.
+
+`-h'
+`+high-byte-first'
+     The high-byte-first option specifies explicitly that the higher
+     order byte of each signed, two byte integer occurs first in the
+     file.  It disables determination of byte order from the file
+     itself.
+
+`-l'
+`+low-byte-first'
+     The low-byte-first option specifies explicitly that the lower order
+     byte of each signed, two byte integer occurs first in the file.  It
+     disables determination of byte order from the file itself.
+
+`-p FILENAME'
+`+prologue FILENAME'
+     The prologue option specifies the name of an alternate PostScript
+     prologue FILENAME to be used in place of the default `idraw'
+     prologue.  The prologue declares procedures used to draw each
+     graphic object.  The default prologue was generously provided by
+     John Interante and is a part of the InterViews distribution,
+     version 2.5.
+
+`+copying'
+`+C'
+`+warranty'
+`+W'
+     The copying and warranty options print a copy of the GNU General
+     Public License on the standard error output.  Included is
+     conditions for copying `plot' and information on the lack of any
+     warranty.
+
+`-s'
+`+signed-input'
+`-u'
+`+unsigned-input'
+     The signed and unsigned options specify whether coordinates in the
+     plot file are signed.  By convention, coordinates are always
+     signed.  Some plot files do not follow this convention, and you
+     can use the unsigned option to convert those files.
+
+
+File: graphics.info,  Node: latex example,  Next: psfig,  Prev: plot2tek invocation,  Up: Top
+
+Including a Figure in an Article
+================================
+
+   This is an example of LaTeX code which places the figure generated in
+the previous example in a page of text.
+
+     \documentstyle[]{article}
+     \input{psfig}
+     \begin{document}
+     \title{Title of the article.}
+     \author{The Author's name}
+     \maketitle
+     This is an example of how to include PostScript figures in LaTeX documents.
+     \begin{figure}[h]
+     \centerline{\psfig{figure=test.ps,height=3in}}
+     \caption{Here is a description of the figure which will appear below it.}
+     \end{figure}
+     Note that the above figure was included using dvips.
+     \end{document}
+
+   If the above LaTeX code is contained in a file called `mytext.tex'
+you can use the commands
+
+     latex mytext
+     dvips mytext.dvi >mytext.ps
+     lpr -Plw mytext.ps
+
+   to format and print the example text.
+
+
+File: graphics.info,  Node: psfig,  Next: atend.pl,  Prev: latex example,  Up: Top
+
+Options to `psfig' for Including Figures
+========================================
+
+   `psfig' is a LaTeX command used to insert a PostScript figure into a
+document.
+
+   `psfig' can be used to insert `plot2ps' generated PostScript into a
+LaTeX document.  The placement of the `psfig' command tells LaTeX where
+in the document to place the PostScript, and arguments to the command
+give the name of the file containing the PostScript, and the desired
+size of the figure.  Arguments are separated by commas or blanks, and
+are of the form `KEYWORD=VALUE'.  The following is a list of valid
+arguments for the `psfig' command:
+
+`file=NAME'
+     The file name of the PostScript figure.
+
+`height=SIZE'
+     The height of the figure (eg. 3in).  If you specify only a height
+     or only a width, the width and height are scaled equally.  If you
+     specify both a width and a height the aspect ratio will be
+     affected.
+
+`width=SIZE'
+     The width of the figure (eg. 3in).
+
+`bbllx=COORDINATE'
+     The bounding box lower left-hand x coordinate.  Any PostScript file
+     which conforms to the PostScript Document Structuring Conventions
+     version 2.0 should contain a bounding box information at the head
+     of the file.  `plot2ps' output conforms to the version 2.0
+     conventions so that you should not need to use any of the bounding
+     box options.
+
+`bblly=COORDINATE'
+     The bounding box lower left-hand y coordinate.
+
+`bburx=COORDINATE'
+     The bounding box upper right-hand x coordinate.
+
+`bbury=COORDINATE'
+     The bounding box upper right-hand y coordinate.
+
+`rheight=SIZE'
+     Horizontal space to reserve for the figure.
+
+`rwidth=SIZE'
+     Vertical space to reserve for the figure.
+
+`clip='
+     Clip the figure.  `clip=' is a switch and takes no value, but the
+     `=' must be present.  This option is useful for including
+     PostScript figures which use the size of the clipping path to size
+     themselves.
+
+
+File: graphics.info,  Node: atend.pl,  Next: dvips,  Prev: psfig,  Up: Top
+
+A perl script for use with psfig
+================================
+
+   `atend.pl' is a perl script which moves the bounding box comment
+from the trailer to the header.  Although either is legal, most document
+preparation software, such as `psfig', will only accept bounding box
+comments in the header.  If you use `psfig' and the `-bbox' option
+togeather, run `atend.pl' on the output of `plot2ps' before importing
+the graphics using `psfig'.
+
+   `atend.pl' can be used as a filter:
+
+     echo 0 0 1 1 2 0 | spline | graph >spline.pl
+     plot2ps -bbox |atend.pl - >spline.ps
+
+   Or, `atend.pl' can be used to fix the output file in place:
+
+     echo 0 0 1 1 2 0 | spline | graph |plot2ps -bbox >spline.ps
+     atend.pl spline.ps
+
+
+File: graphics.info,  Node: dvips,  Next: idraw,  Prev: atend.pl,  Up: Top
+
+How to Get `dvips'
+==================
+
+   The `dvips' utility mentioned previously is used convert dvi files
+generated by LaTeX into post-script.  It also has support for inclusion
+of PostScript figures into LaTeX documents.  It is available via
+anonymous ftp from `labrea.stanford.edu' (36.8.0.47).  Look for
+`pub/dvips.tar.Z'.
+
+
+File: graphics.info,  Node: idraw,  Next: ghostscript,  Prev: dvips,  Up: Top
+
+How to Get `idraw'
+==================
+
+   The `idraw' utility mentioned previously is an interactive graphics
+editor which is distributed with InterViews.  InterViews is available
+via anonymous ftp from `interviews.stanford.edu' (36.22.0.175) in the
+file `InterViews/2.5.tar.Z'.
+
+
+File: graphics.info,  Node: ghostscript,  Next: libps,  Prev: idraw,  Up: Top
+
+How to Get `ghostscript'
+========================
+
+   Ghostscript is a previewer which is intended to be compatible with
+the PostScript language.  It supports several output devices including
+the X window system and ega displays.  Version 2.0 is suitable for
+previewing LaTeX documents with imbedded encapsulated PostScript
+figures, the type of PostScript figures generated by plot2ps and idraw.
+It is available via anonymous ftp from `prep.ai.mit.edu' (18.71.0.38)
+- Look for `pub/gnu/ghostscript.tar.Z'.
+
+
+File: graphics.info,  Node: libps,  Next: files,  Prev: ghostscript,  Up: Top
+
+`libps', a Library of Plot Functions
+====================================
+
+   Libps is a library of plot functions for drawing graphic object
+using PostScript.  Before drawing any objects or using any of the other
+functions, a program should call `openpl'.  Before exiting and after
+all other libps calls a program should call `closepl'.
+
+* Menu:
+
+The standard plot library includes:
+
+* arc::          draw an arc
+* circle::       draw a circle
+* closepl::      close the device for output
+* cont::	 continue a line
+* erase::        erase the page
+* label::        print a label
+* line::         draw a line
+* linemod::      change the line mode (style)
+* move::         move to a new coordinate
+* openpl::       open the device for output
+* point::        draw a point
+* space::        define the user's plot space (size)
+
+The extensions provided only in libps to take advantage of PostScript
+features include:
+
+* alabel::       print a vertically or horizontally justified label
+* color::        change the color
+* fill::         fill pattern for closed paths
+* fontname::     set the font name
+* fontsize::     set the font size
+* rotate::       rotate subsequent text
+
+
+File: graphics.info,  Node: alabel,  Next: arc,  Up: libps
+
+`alabel'
+--------
+
+   int `alabel' (char X_JUSTIFY, char Y_JUSTIFY, char *LABEL);
+
+   `alabel' takes three arguments X_JUSTIFY, Y_JUSTIFY, and LABEL and
+places the label according to the x and y axis adjustments specified in
+X_JUSTIFY and Y_JUSTIFY respectively.  X_JUSTIFY is a character
+containing either `l', `c', or `r' for left, center or right justified
+with respect to the current x coordinate.  Y_JUSTIFY is a character
+containing either `b', `c', or `t' for placing the bottom center or top
+of the label even with the current y coordinate.  *LABEL is a string
+containing the label.  The current point is moved to follow the end of
+the text.
+
+   *Note fontname:: on how to change the default font.  *Note
+fontsize:: on how to change the font size.
+
+
+File: graphics.info,  Node: arc,  Next: circle,  Prev: alabel,  Up: libps
+
+`arc'
+-----
+
+   int `arc' (int X, int Y, int X0, int Y0, int X1, int Y1)
+
+   `arc' takes six integer arguments specifying the coordinates of the
+center (X, Y), beginning (X0, Y0), and ending (X1, Y1) of a circular
+arc.  The current point becomes (X, Y).
+
+
+File: graphics.info,  Node: circle,  Next: closepl,  Prev: arc,  Up: libps
+
+`circle'
+--------
+
+   int `circle' (int X, int Y, int R)
+
+   `circle' takes three integer arguments specifying the center (X, Y)
+of the circle and its radius (R).  The current point becomes (X, Y).
+
+
+File: graphics.info,  Node: closepl,  Next: color,  Prev: circle,  Up: libps
+
+`closepl'
+---------
+
+   int `closepl' ()
+
+   `closepl' takes no arguments.  It merely outputs the PostScript
+trailer containing a `showpage' command.
+
+
+File: graphics.info,  Node: color,  Next: cont,  Prev: closepl,  Up: libps
+
+`color'
+-------
+
+   int `color' (int RED, int GREEN, int BLUE);
+
+   `color' sets the foreground color of all the following objects.  The
+arguments RED, GREEN and BLUE indicate the intensity of red, green and
+blue components of the foreground color respectively.  Each is a
+unsigned integer specifying an intensity in the range from 0 to 0xFFFF.
+A value of (0, 0, 0) represents black and a value of (0xFFFF, 0xFFFF,
+0xFFFF) indicates white.
+
+
+File: graphics.info,  Node: cont,  Next: erase,  Prev: color,  Up: libps
+
+`cont'
+------
+
+   int `cont' (int X, int Y)
+
+   `cont' takes two integer arguments specifying the coordinate (X, Y)
+for the continuation of a line.  This draws a line segment from the
+current point to the point (X, Y).  The current point then becomes (X,
+Y).
+
+
+File: graphics.info,  Node: erase,  Next: fill,  Prev: cont,  Up: libps
+
+`erase'
+-------
+
+   int `erase' ()
+
+   `erase' normally erases all the graphics from the display before a
+plot is viewed.  Since we start off with a blank page in PostScript and
+`idraw' this function does nothing.
+
+
+File: graphics.info,  Node: fill,  Next: fontname,  Prev: erase,  Up: libps
+
+`fill'
+------
+
+   int `fill' (int LEVEL);
+
+   `fill' sets the intensity of the filler for closed paths.  The
+argument LEVEL indicates the grey level of the fill pattern.  It's
+value ranges from 1 to 0xFFFF.  A value of 1 represents black and a
+value of 0xFFFF indicates white.  A value of 0 represents no fill, or
+transparent.
+
+
+File: graphics.info,  Node: fontname,  Next: fontsize,  Prev: fill,  Up: libps
+
+`fontname'
+----------
+
+   int `fontname' (char *FONT_NAME);
+
+   `fontname' takes a single string argument, FONT_NAME, specifying the
+name of the font to be used for following text.  The laser writer
+builtin fonts are supported:
+
+             courier-bold
+             courier-boldoblique
+             courier-oblique
+             courier
+             helvetica-bold
+             helvetica-boldoblique
+             helvetica-oblique
+             helvetica
+             symbol
+             times-bold
+             times-bolditalic
+             times-italic
+             times-roman
+
+
+File: graphics.info,  Node: fontsize,  Next: label,  Prev: fontname,  Up: libps
+
+`fontsize'
+----------
+
+   int `fontsize' (int SIZE);
+
+   `fontsize' takes a single integer argument SIZE in printer's points
+(1/72 inch) and sets the font size accordingly.
+
+
+File: graphics.info,  Node: label,  Next: line,  Prev: fontsize,  Up: libps
+
+`label'
+-------
+
+   int `label' (char *S)
+
+   `label' takes a single string argument S and draws the text
+contained in S at the most recently used coordinate in the current
+font.  By default the text is left justified and centered vertically
+with respect to the current coordinate.
+
+
+File: graphics.info,  Node: line,  Next: linemod,  Prev: label,  Up: libps
+
+`line'
+------
+
+   int `line' (int X1, int y1, int X2, int Y2)
+
+   `line' takes four integer arguments specifying the beginning (X1,
+Y1) and ending (X2, Y2) points of a line.  The current point becomes
+(X2, Y2).
+
+   *Note linemod:: for how to specify the style or pattern of line.
+
+
+File: graphics.info,  Node: linemod,  Next: move,  Prev: line,  Up: libps
+
+`linemod'
+---------
+
+   int `linemod' (char *S)
+
+   `linemod' takes a single string argument S containing the name of
+the line style desired.  The names supported are longdashed,
+disconnected, dotdashed, dotted, solid and shortdashed.  These
+correspond to the following sixteen bit patterns:
+
+     solid             --------------------------------
+     longdashed        -------         -------
+     disconnected      -               -
+     dotdashed         -----------  -  -----------  -
+     dotted            - - - - - - - - - - - - - - - -
+     shortdashed       --              --
+
+
+File: graphics.info,  Node: move,  Next: openpl,  Prev: linemod,  Up: libps
+
+`move'
+------
+
+   int `move' (int X, int Y)
+
+   `move' takes two integer arguments specifying the coordinate (X, Y)
+for the beginning of a new line.  This is equivalent to lifting the pen
+on a plotter and moving it to a new position without drawing any line.
+The current point becomes (X, Y).
+
+
+File: graphics.info,  Node: openpl,  Next: point,  Prev: move,  Up: libps
+
+`openpl'
+--------
+
+   int `openpl' ()
+
+   `openpl' normally opens the device.  For PostScript we just print
+out the PostScript prologue.  The following global variables defined in
+`openpl' specify what prologue is written to the output.
+
+   USER_HAS_PROLOGUE is a flag.  If it is non-zero then the open
+routine should output the user specified prologue contained in the file
+specified in the string USERS_PROLOGUE.
+
+   USERS_PROLOGUE is a string containing the file name for any user
+specified PostScript prologue.  This file is a substitute for the
+default prologue.
+
+
+File: graphics.info,  Node: point,  Next: rotate,  Prev: openpl,  Up: libps
+
+`point'
+-------
+
+   int `point' (int X, int Y)
+
+   `point' takes a pair of integer arguments specifying the coordinate
+(X, Y) for a single point.  The current point then becomes (X, Y).
+
+
+File: graphics.info,  Node: rotate,  Next: space,  Prev: point,  Up: libps
+
+`rotate'
+--------
+
+   int `rotate' (int ANGLE);
+
+   `rotate' takes three integer arguments.  The last argument, ANGLE,
+specifies the angle in degrees counter-clockwise from the x
+(horizontal) axis following text.
+
+
+File: graphics.info,  Node: space,  Prev: rotate,  Up: libps
+
+`space'
+-------
+
+   int `space' (int X0, int Y0, int X1, int Y1)
+
+   `space' takes two pair of integers arguments specifying the lower,
+left-hand and upper, right-hand limits of the range of plot
+coordinates.  The scaling of input to output coordinate conversion is
+adjusted to fit these ranges into the page.  Note however that if the
+ranges of x and y coordinates are different the smallest scaling of the
+two is used to avoid affecting the aspect ratio of the plot.  This
+means that although the plot is scaled to fit on the page, the axes are
+not stretched with respect to each other.
+
+
+File: graphics.info,  Node: files,  Next: Acknowledgements,  Prev: libps,  Up: Top
+
+The Plot File Format
+====================
+
+   The plot file is a set of plotting commands and data.  Each command
+is a single ascii character indicating which operation is to be
+performed.  The data following a command is either a newline terminated
+ascii string or several signed, two byte integers in binary format.
+For example, the command to move the current point to the coordinate
+(3,5) would be `m\000\003\000\005'.
+
+   Note that the byte order of the binary representation of the signed,
+two byte integers is machine dependent, so on some machines, this
+command might appear as `m\003\000\005\000'.  `plot2ps' tries to guess
+the byte order from the arguments to the `openpl' command and adjust
+the order accordingly.
+
+   The following table lists each single character commands followed by
+the name of the corresponding libps function called to handle the data
+and a description of the command and data.
+
+`Command'
+     Description
+
+`a'
+     The arc command is followed by three pair of signed, two byte
+     integers indicating the center, starting and ending points for a
+     circular arc.  The center becomes the the current point.  This is
+     equivalent to the `arc' function (*note arc::.).
+
+`c'
+     The circle command is followed by three signed, two byte integers.
+     The first two indicate the x and y coordinates of the center of
+     the circle and the third indicates the radius of the circle.  The
+     center becomes the the current point.  This is equivalent to the
+     `circle' function (*note circle::.).
+
+`C'
+     The color command is followed by three unsigned, two byte integer
+     which indicate the intensity of RED, GREEN and BLUE components
+     respectively of the background color.  For each component the
+     range of intensity is from 0 to 65535.  A value of (0, 0, 0)
+     represents black and (65535, 65535, 65535) represents white. This
+     is equivalent to the `color' function (*note color::.).
+
+`e'
+     The erase command is followed by no data.  The erase command is not
+     needed since in `idraw' and PostScript we start off with a blank
+     page.  For this reason the erase command does not actually output
+     any PostScript. This is equivalent to the `erase' function (*note
+     erase::.).
+
+`f'
+     The linemod command is followed by a newline terminated string
+     containing the name of the line mode (or style) for all subsequent
+     lines, circles and arcs. This is equivalent to the `linemod'
+     function (*note linemod::.) which describes the line styles and
+     their names.
+
+`F'
+     The the fontname command is followed by a newline terminated string
+     containing the name of the font to be used for all subsequent
+     text. This is equivalent to the `fontname' function (*note
+     fontname::.).
+
+`l'
+     The line command is followed by two pair of signed, two byte
+     integers which indicate the starting and ending points of the
+     line.  The second pair becomes the the current point. This is
+     equivalent to the `line' function (*note line::.).
+
+`L'
+     The fill command is followed by an unsigned, two byte integer
+     indicating the intensity of the fill for closed paths.  A value of
+     1 represents black and a value of 0xFFFF indicates white.  The
+     value 0 is special in that is indicates that no solid fill should
+     occur, and that the interior of the respective path is
+     transparent. This is equivalent to the `fill' function (*note
+     fill::.).
+
+`m'
+     The move command is followed by a pair of signed, two byte integers
+     containing the location of the new current point.  No line is
+     drawn to this point as opposed to the continue command (`c') which
+     draws a line.  This is equivalent to the `move' function (*note
+     move::.).
+
+`n'
+     The continue command is followed by pair of signed, two byte
+     integers containing the coordinates of the endpoint of a line
+     segment.  A line is drawn from the previous current point if it
+     was set using a command such as move or continue.  This then
+     becomes the the current point. This is equivalent to the `cont'
+     function (*note cont::.).
+
+`p'
+     The point command is followed by pair of signed, two byte integers
+     containing the location of single point to be drawn.  This then
+     becomes the the current point. This is equivalent to the `point'
+     function (*note point::.).
+
+`r'
+     The rotate command is followed by one signed, two byte integer.  It
+     indicates the rotation of all subsequent text.  The rotation is in
+     degrees counter-clockwise from the x (horizontal) axis. This is
+     equivalent to the `rotate' function (*note rotate::.).
+
+`s'
+     The space command is followed by two pair of signed, two byte
+     integers which indicate the the lower right-hand and upper
+     left-hand corners of the range of plot coordinate space.
+     `plot2ps' uses the third signed, two byte integer (the right-hand
+     limit) to try to determine the byte order. This is equivalent to
+     the `space' function (*note space::.) which describes the
+     recognized sizes.
+
+`S'
+     The fontsize command is followed by an signed, two byte integer
+     containing the size in printers points of all subsequent text.
+     This is equivalent to the `fontsize' function (*note fontsize::.).
+
+`t'
+     The label command is followed by a newline terminated string
+     contains a label which is printed at the current point.  It is
+     left justified and centered vertically with respect to the current
+     point.  The current point is then set at the end of the text. This
+     is equivalent to the `label' function (*note label::.).
+
+`T'
+     The adjusted label command is followed by two characters which
+     indicate the horizontal and vertical justification respectively
+     and a newline terminated string containing the label.  The label
+     is drawn with the specified justification and the current point is
+     set at the end of the text.  This is equivalent to the `alabel'
+     function (*note alabel::.) which describes how to specify
+     justification.
+
+
+File: graphics.info,  Node: Acknowledgements,  Next: Function Index,  Prev: files,  Up: Top
+
+Acknowledgements
+================
+
+   Rich Murphey <Rich@Rice.edu> wrote the first version of the graph,
+plot2tek, plot2ps and tek2plot and the documentation.  Richard Stallman
+<Rms@ai.mit.edu> further directed development of the programs and
+editorial support for the documentation.  John Interrante generously
+provided the PostScript prologue and helpful comments on the program.
+
+   Arthur Smith (Lassp, Cornell University)
+<arthur@helios.tn.cornell.edu> has generously provided his code for the
+xplot utility.
+
+   Ray Toy <toy@dino.ecse.rpi.edu> provided code for graph and tek 4011
+and rewrote the tick mark spacing code, incorporated gnu getopt and
+provided the statistics package.
+
+   David B. Rosen <rosen@bu.edu>, jeffrey templon
+<templon@copper.ucs.indiana.edu> and David W. Forslund
+<dwf%hope.ACL@lanl.gov> tested alpha versions.
+
+
+File: graphics.info,  Node: Function Index,  Prev: Acknowledgements,  Up: Top
+
+Function Index
+==============
+
+* Menu:
+
+* alabel (char X_JUSTIFY, char Y_JUSTIFY, char *LABEL): alabel.
+* arc (int X, int Y, int X0, int Y0, int X1, int Y1): arc.
+* circle (int X, int Y, int R):         circle.
+* closepl ():                           closepl.
+* color (int RED, int GREEN, int BLUE): color.
+* cont (int X, int Y):                  cont.
+* erase():                              erase.
+* fill (int LEVEL):                     fill.
+* fontname (char *FONT_NAME):           fontname.
+* fontsize (int SIZE):                  fontsize.
+* label (char *S):                      label.
+* linemod (char *S):                    linemod.
+* line (int X1, int y1, int X2, int Y2): line.
+* move (int X, int Y):                  move.
+* openpl():                             openpl.
+* point (int X, int Y):                 point.
+* rotate (int W, int H, int ANGLE):     rotate.
+* space (int X0, int Y0, int X1, int Y1): space.
+
+
+
+Tag Table:
+Node: Top187
+Node: introduction1407
+Node: graph examples3457
+Node: Invocation4024
+Node: Input Files5739
+Node: Overlaying7374
+Node: Multiple Plots9252
+Node: Binary Data10198
+Node: graph invocation11307
+Node: plot2ps examples18376
+Node: plot2ps invocation18914
+Node: xplot24137
+Node: xplot invocation24803
+Node: Plot2fig Examples26556
+Node: plot2fig invocation27374
+Node: plot2tek invocation29619
+Node: latex example32322
+Node: psfig33301
+Node: atend.pl35322
+Node: dvips36130
+Node: idraw36538
+Node: ghostscript36899
+Node: libps37487
+Node: alabel38741
+Node: arc39560
+Node: circle39892
+Node: closepl40169
+Node: color40400
+Node: cont40919
+Node: erase41255
+Node: fill41545
+Node: fontname41952
+Node: fontsize42615
+Node: label42872
+Node: line43234
+Node: linemod43593
+Node: move44259
+Node: openpl44632
+Node: point45278
+Node: rotate45544
+Node: space45836
+Node: files46490
+Node: Acknowledgements52660
+Node: Function Index53597
+
+End Tag Table
Index: /tags/start/Ohana/doc/keywords.txt
===================================================================
--- /tags/start/Ohana/doc/keywords.txt	(revision 12606)
+++ /tags/start/Ohana/doc/keywords.txt	(revision 12606)
@@ -0,0 +1,129 @@
+
+here are keywords used in Elixir:
+
+Elixir defined keywords:
+(detrend dB)
+TVSTART
+TVSTOP
+FILTER
+EXPTIME
+OBSTYPE
+NENTRY - values in dB
+
+(phot dB)
+NIMAGES 
+
+(imregister / iminfo)
+EXPTIME-KEYWORD   : ExptimeKeyword   : EXPTIME : Exposure time
+IMAGETYPE-KEYWORD : ImagetypeKeyword : OBSTYPE / EXPTYPE : Image type (DARK, OBJECT, etc)
+CCDNUM-KEYWORD    : CCDnumKeyword    : IMAGEID : CCD number
+FILTER-KEYWORD    : FilterKeyword    : FILTER  : filter name
+AIRMASS-KEYWORD   : AirmassKeyword   : AIRMASS : airmass
+FOCUS-KEYWORD     : FocusKeyword     : TELFOCUS: telescope focus setting
+ROTATION-KEYWORD  : RotationKeyword  : ROTANGLE: rotation angle
+DETTEMP-KEYWORD   : DettempKeyword   : DETTEM  : detector temperature
+TELDATA1-KEYWORD  : Teldata1Keyword  : XPROBE  : bonnette probe x position
+TELDATA2-KEYWORD  : Teldata2Keyword  : YPROBE  : bonnette probe y position
+TELDATA3-KEYWORD  : Teldata3Keyword  : ZPROBE  : bonnette focus
+RA-DDD-KEYWORD    : RADecDegKeyword  : CRVAL1  : RA in dec. degrees
+DEC-DDD-KEYWORD   : DECDecDegKeyword : CRVAL2  : DEC in dec. degrees
+RA-HMS-KEYWORD    : RASexigKeyword   : CRVAL1  : RA in hour,min,sec
+DEC-DMS-KEYWORD   : DECSexigKeyword  : CRVAL2  : DEC in dec,min,sec
+CAMERA-KEYWORD    : CameraKeyword    : INSTRUME: unique name of camera
+
+(time keywords already abstracted)
+DATE-KEYWORD	  : DateKeyword	     : DATE-OBS   : date
+DATE-MODE	  : DateMode	     : yyyy-mm-dd : format for DATE-KEYWORD
+UT-KEYWORD	  : UTKeyword	     : UTC-OBS	  : UT
+JD-KEYWORD	  : JDKeyword	     : NONE	  : JD
+MJD-KEYWORD	  : MJDKeyword	     : NONE	  : MJD
+
+(photcode)
+CAMERA-KEYWORD    : CameraKeyword    : DETECTOR: unique name of camera
+FILTER-KEYWORD    : FilterKeyword    : FILTER  : filter name
+CCDNUM-KEYWORD    : CCDnumKeyword    : IMAGEID : CCD number
+
+
+EXTEND  : extensions present (FITS required keyword for MEF)
+NEXTEND : extension number (not necessarily IMAGEID)
+
+(gophot)
+SATVALUE: saturation value for this image
+GAIN    : gain (e/DN) for this image
+NEWGAIN : a stupid name for an altered gain.
+RDNOISE : read noise (in electrons) ***
+DNNOISE : read noise (in DN)        ***
+
+(gastro / coordops in ohana)
+WCS keywords (these do not need to be abstracted)
+CD1_1
+CD1_2
+CD2_1
+CD2_2
+CDELT1
+CDELT2
+CROTA2
+CRPIX1
+CRPIX2
+CRVAL1
+CRVAL2
+CTYPE2
+NPLYTERM
+PC001001
+PC001002
+PC002001
+PC002002
+PCA1X0Y2
+PCA1X0Y3
+PCA1X1Y1
+PCA1X1Y2
+PCA1X2Y0
+PCA1X2Y1
+PCA1X3Y0
+PCA2X0Y2
+PCA2X0Y3
+PCA2X1Y1
+PCA2X1Y2
+PCA2X2Y0
+PCA2X2Y1
+PCA2X3Y0
+DEC_O
+DEC_X
+DEC_Y
+RA_O
+RA_X
+RA_Y
+EPOCH
+EQUINOX
+
+NAXIS1  : FITS mandatory keyword
+NAXIS2  : FITS mandatory keyword
+RA	: RA in sexigesimal (for rough astrometry)
+DEC	: DEC in sexigesimal (for rough astrometry)
+NSTARS  : elixir-added keyword (number of stars, from imclean)
+
+EXPTIME
+AIRMASS 
+IMAGEID
+
+ZERO_PT : Elixir-added keyword (imclean)
+NASTRO  : Elixir-added keyword (imclean)
+CERROR  : Elixir-added keyword (gastro)
+PHOTCODE: Elixir-added keyword (imclean)
+APMIFIT : Elixir-added keyword (imclean)
+dAPMIFIT: Elixir-added keyword (imclean)
+FLIMIT  : Elixir-added keyword (imclean)
+FSATUR  : Elixir-added keyword (imclean)
+FWHM_X  : Elixir-added keyword (imclean)
+FWHM_Y  : Elixir-added keyword (imclean)
+TZERO   : Elixir-added keyword (imclean)
+TRATE   : Elixir-added keyword (imclean)
+NSTARS  : Elixir-added keyword (imclean)
+
+NIMAGES : (Elixir keyword for phot db)
+
+parse_time.c:    fits_scan (header, JDKeyword, "%lf", 1, &jd);
+parse_time.c:    fits_scan (header, MJDKeyword, "%lf", 1, &jd);
+parse_time.c:  fits_scan (header, UTKeyword, "%s", 1, line);
+parse_time.c:  fits_scan (header, DateKeyword, "%s",  1, line);
+wimage.c:  fits_scan (&header, "NIMAGES", "%d", 1, &Nimages);
Index: /tags/start/Ohana/doc/linux.txt
===================================================================
--- /tags/start/Ohana/doc/linux.txt	(revision 12606)
+++ /tags/start/Ohana/doc/linux.txt	(revision 12606)
@@ -0,0 +1,148 @@
+From jht@ing.iac.es Mon Jul 21 03:58 PDT 1997
+Return-Path: <jht@ing.iac.es>
+Received: from ing.iac.es by pikake.astro.washington.edu
+	(8.6.12/UW-NDC Revision: 2.33 ) id DAA16312;
+	Mon, 21 Jul 1997 03:58:40 -0700
+Received: by ing.iac.es (4.1/1.0)
+	id AA20304; Mon, 21 Jul 97 11:58:27 BST
+Date: Mon, 21 Jul 1997 11:58:26 +0100 (BST)
+From: John Telting <jht@ing.iac.es>
+To: Eugene Magnier <gene@pikake.astro.washington.edu>
+Cc: Saskia Prins <stp@ing.iac.es>, John Telting <jht@ing.iac.es>
+Subject: Re: fits tools on linux
+In-Reply-To: <199706101748.KAA22094@pikake.astro.washington.edu>
+Message-Id: <Pine.SUN.3.91.970721114404.19653B-100000@vega.ing.iac.es>
+Mime-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=US-ASCII
+Content-Length: 3744
+Status: O
+
+hi gene,
+
+HOWZIT?
+we saw lots of dreamcatchers on indian territory, but only few
+were 3D like the one you gave us.  Stunning views in and in between
+the national parks/monuments.  Great vacation behind us!!
+
+gdb is useful!
+apparently the linux C compiler reads the FITS bytes into the
+variables in the reverse order (NOT a byteswap!!).
+i only tested SIGNED bitpix=16,32,-32.
+for bitpix=8 there is a sign problem.
+
+we had a closer look at sas's linux mana version, and all data values
+are affected by the same problem. (So Sas cannot really use it conveniently.)
+
+below a hack in the 1D vector routine you made especially for my use
+when we both were in amsterdam.  I guess you can make use of my hacking.
+if/when you are going to do a port to linux, please let us know!!!
+
+See You!!
+John
+
+ps. the compiler gives warnings about the way i coded the pointers.
+dont know how to do it the way it likes it, sorry.
+
+----------------------------------------------------------------
+file: F_get_V_value.c
+----------------------------------------------------------------
+# include "fits.h"
+
+/***************** fits get matrix value *******************/
+double fits_get_vector_value (matrix, x) 
+Matrix *matrix; 
+int x;
+{
+
+  double value;
+  float float1, float2;
+  int pixel, int1, int2;
+  short short1, short2;
+  char yyy[3], zzz[3];
+
+  if ((x < 0) || (x >= matrix[0].Naxis[0])) {
+    fprintf (stderr, "%6d %d\n", x, matrix[0].Naxis[0]);
+    return (0.0);
+  }
+  pixel = x;
+  value = fmod (1.0,0.0);
+
+  if (pixel==0) {
+    fprintf(stderr,"\n\n!!  fits_get_vector_value  !!\n");
+    fprintf(stderr,"!!  USE THIS hack ONLY UNDER linux !!\n");
+    fprintf(stderr,"!!  DONT USE FOR bitpix=8  !!\n");
+    fprintf(stderr,"!!  DONT USE FOR bitpix=-64  !!\n");
+    fprintf(stderr,"!!  DONT USE FOR UNSIGNED TYPES  !!\n");
+  }
+
+  if (matrix[0].unsign) {
+    switch (matrix[0].bitpix) {
+    case 8:
+      value = *((unsigned char  *) matrix[0].buffer + pixel);
+      fprintf(stderr,"!!  DONT USE FOR UNSIGNED TYPES  !!\n");
+      break;
+    case 16:
+      value = *((unsigned short *) matrix[0].buffer + pixel);
+      fprintf(stderr,"!!  DONT USE FOR UNSIGNED TYPES  !!\n");
+      break;
+    case 32:
+      value = *((unsigned int   *) matrix[0].buffer + pixel);
+      fprintf(stderr,"!!  DONT USE FOR UNSIGNED TYPES  !!\n");
+      break;
+    case -32:
+      value = *((float          *) matrix[0].buffer + pixel);
+      fprintf(stderr,"!!  DONT USE FOR UNSIGNED TYPES  !!\n");
+      break;
+    case -64:
+      value = *((double         *) matrix[0].buffer + pixel);
+      fprintf(stderr,"!!  DONT USE FOR UNSIGNED TYPES  !!\n");
+      break;
+    }
+  }
+  else {
+    switch (matrix[0].bitpix) {
+    case 8:
+      value = *((char  *) matrix[0].buffer + pixel);
+      fprintf(stderr,"!!  DONT USE FOR bitpix=8  !!\n");
+      break;
+    case 16:
+      short1 = *((short *) matrix[0].buffer + pixel);
+      short2 = 0;
+      swab(&short1,&short2,2);
+      value = short2;
+      break;
+    case 32:
+      int1 = *((int   *) matrix[0].buffer + pixel);
+      int2 = 0;
+      bcopy(&int1,&zzz[0],4);
+      yyy[0] = zzz[3];
+      yyy[1] = zzz[2];
+      yyy[2] = zzz[1];
+      yyy[3] = zzz[0];
+      bcopy(&yyy[0],&int2,4);
+      value = int2;
+      break;
+    case -32:
+      float1 = *((float          *) matrix[0].buffer + pixel);
+      float2 = 0;
+      bcopy(&float1,&zzz[0],4);
+      yyy[0] = zzz[3];
+      yyy[1] = zzz[2];
+      yyy[2] = zzz[1];
+      yyy[3] = zzz[0];
+      bcopy(&yyy[0],&float2,4);
+      value = float2;
+      break;
+    case -64:
+      value = *((double         *) matrix[0].buffer + pixel);
+      fprintf(stderr,"!!  DONT USE FOR bitpix=-64  !!\n");
+      break;
+    }
+  }
+
+  value = matrix[0].bscale*value + matrix[0].bzero;
+  return (value);
+
+}
+
+
Index: /tags/start/Ohana/doc/locks.txt
===================================================================
--- /tags/start/Ohana/doc/locks.txt	(revision 12606)
+++ /tags/start/Ohana/doc/locks.txt	(revision 12606)
@@ -0,0 +1,70 @@
+
+NFS locks & file locks in ohana / elixir
+
+There are three types of locks in use in the elixir system:
+
+SOFT, XCLD, HARD
+
+SOFT - a soft lock on a file prevents a xcld or hard lock on that
+       file,  but allows other soft locks to be set.  the soft lock
+       uses NFS locking and is ephmeral, vanishing if the holding
+       program ends, whether or not the program explicitly removes the
+       lock. 
+
+XCLD - an xcld lock on a file prevents all other locks: soft, xcld, or
+       hard; only one xcld lock may be active on a file at a time.
+       The xcld lock uses NFS locking is ephemeral, vanisihing when
+       the program exits.
+
+HARD - a hard lock on a file prevents all other locks: soft, xcld, or
+       hard; only one hard lock may be active on a file at a time.
+       The hard lock is sticky and will remain unless the program
+       actively removes the lock.  It is implemented by first setting
+       an XCLD lock in NFS and then creating a lock file (.file.lck)
+       which contains the work BUSY.  until this file is removed or
+       the contents changed, the lock remains.
+
+basic lock APIs:
+
+int setlockfile2 (char *filename, double timeout, int type, int *state)
+FILE *fsetlockfile (char *filename, double timeout, int type, int *state)
+
+setlockfile2 sets a lock of the requested type on the given file,
+  returning an open file descriptor to the file.  If the requested
+  lock is SOFT and the file does not exist, setlockfile2 returns -1
+  and sets the state to  LCK_EMPTY - the lock is not set.  In the case
+  of XCLD or HARD locks, if the file does not exist, it is created.
+  If the lock cannot be set immediately, setlockfile2 will block for
+  up to 'timeout' seconds, at which point it will return -1 and exit
+  with state LCK_TIMEOUT.  
+
+fsetlockfile behaves identically to setlockfile2, but generates and
+returns a stream associated with the open file descriptor.  An error
+will result in the return of (FILE *) NULL.
+
+int clearlockfile2 (char *filename, int fd, int type, int *state)
+int fclearlockfile (char *filename, FILE *f, int type, int *state)
+
+clearlockfile2 clears the lock associated with a file and file
+descriptor.  If the type is HARD, it will clear the associated hard
+lock file before removing the NFS level file lock.  If only the
+filename is passed to clearlockfile2, the NFS-level locks cannot be
+unset, but the hardlock will be unset.  this is useful if a program is
+known to then exit.
+
+fclearlockfile behaves identically to setlockfile2, but requires the
+associated stream, rather than the file descriptor.  
+
+
+-----
+
+
+int lock_catalog (Catalog *catalog, int lockmode)
+
+lock_catalog attempts to set a lock on the specified photometry
+catalog file.  If successful, the catalog file pointer is set to the
+beginning of the catalog and the function returns the value 1.  If the
+file is empty, the return value is 2.  This only indicates an error if
+the file pointer is NULL, which occurs if the requested locktype is
+SOFT. 
+
Index: /tags/start/Ohana/doc/notes.trange.txt
===================================================================
--- /tags/start/Ohana/doc/notes.trange.txt	(revision 12606)
+++ /tags/start/Ohana/doc/notes.trange.txt	(revision 12606)
@@ -0,0 +1,119 @@
+
+---- info on locks ----
+
+addrefs/src/addrefs.c:  fd = setlockfile2 (ImageCat, 3600.0, LCK_HARD, &dbstate);
+addspphot/src/addspphot.c:  fd = setlockfile2 (ImageCat, 3600.0, LCK_HARD, &dbstate);
+addstar/src/addstar.c:  fd = setlockfile2 (ImageCat, 3600.0, LCK_HARD, &dbstate);
+elixir/src/DumpStatus.c:    fd = setlockfile2 (filename, 0.1, LCK_XCLD, &state);
+elixir/src/LoadPending.c:    fd = setlockfile2 (filename, 1.0, LCK_XCLD, &lockstate);
+elixir/src/MachineOps.c:    fd = setlockfile2 (filename, 0.1, LCK_XCLD, &state);
+elixir/src/MsgOps.c:  fd = setlockfile2 (fifo, 0.1, LCK_XCLD, &state);
+elixir/src/MsgOps.c:  fd = setlockfile2 (fifo, 0.1, LCK_XCLD, &state);
+imregister/old/imregister1.c:  fd = setlockfile2 (DataBase, 120.0, LCK_HARD, &dbstate);
+imregister/old/imsort1.c:  fd = setlockfile2 (DataBase, 120.0, LCK_HARD, &dbstate);
+imregister/old/imstatreg1.c:  fd = setlockfile2 (DataBase, 120.0, LCK_HARD, &dbstate);
+imregister/old/photreg1.c:  fd = setlockfile2 (dBFile, 120.0, LCK_HARD, &dbstate);
+imregister/old/photsearch1.c:  fd = setlockfile2 (dBFile, 300.0, lockstate, &dbstate);
+imregister/old/transearch1.c:  fd = setlockfile2 (dBFile, 300.0, lockstate, &dbstate);
+imregister/old/transreg1.c:  fd = setlockfile2 (dBFile, 120.0, LCK_HARD, &dbstate);
+imregister/old/imregister1b.c:  fd = setlockfile2 (DataBase, 120.0, LCK_HARD, &dbstate);
+imregister/old/imsearch.c:  fd = setlockfile2 (DataBase, 300.0, lockstate, &dbstate);
+imregister/old/imsort.c:  fd = setlockfile2 (DataBase, 600.0, LCK_HARD, &dbstate);
+imregister/old/imstatreg.c:  fd = setlockfile2 (DataBase, 600.0, LCK_HARD, &dbstate);
+imregister/base/WriteFIFO.c:  fd = setlockfile2 (filename, 20.0, LCK_XCLD, &state);
+imregister/detrend/detregister2.c:    fd = setlockfile2 (fullname, 2.0, LCK_XCLD, &filestate);
+imregister-1.0/src/old/imdbset.c:  fd = setlockfile2 (DataBase, 120.0, LCK_HARD, &dbstate);
+imregister-1.0/src/old/detsearch1.c:  fd = setlockfile2 (dBFile, 300.0, lockstate, &dbstate);
+imregister-1.0/src/WriteFIFO.c:  fd = setlockfile2 (filename, 20.0, LCK_XCLD, &state);
+imregister-1.0/src/photsearch1.c:  fd = setlockfile2 (dBFile, 300.0, lockstate, &dbstate);
+imregister-1.0/src/detsearch1.c:  fd = setlockfile2 (dBFile, 300.0, lockstate, &dbstate);
+imregister-1.0/src/imstatreg1.c:  fd = setlockfile2 (DataBase, 120.0, LCK_HARD, &dbstate);
+imregister-1.0/src/imregister1.c:  fd = setlockfile2 (DataBase, 120.0, LCK_HARD, &dbstate);
+imregister-1.0/src/photreg1.c:  fd = setlockfile2 (dBFile, 120.0, LCK_HARD, &dbstate);
+imregister-1.0/src/detregister1.c:  fd = setlockfile2 (dBFile, 600.0, LCK_HARD, &dbstate);
+imregister-1.0/src/transearch1.c:  fd = setlockfile2 (dBFile, 300.0, lockstate, &dbstate);
+imregister-1.0/src/transreg1.c:  fd = setlockfile2 (dBFile, 120.0, LCK_HARD, &dbstate);
+imregister-1.0/src/detregister.c:    fd = setlockfile2 (fullname, 2.0, LCK_XCLD, &filestate);
+imregister-1.0/src/imsort1.c:  fd = setlockfile2 (DataBase, 120.0, LCK_HARD, &dbstate);
+imregister-1.0/src/imregister.c:  fd = setlockfile2 (DataBase, 120.0, LCK_HARD, &dbstate);
+imregister-1.0/src/imsearch.c:  fd = setlockfile2 (DataBase, 300.0, lockstate, &dbstate);
+imregister-1.0/src/imsort.c:  fd = setlockfile2 (DataBase, 600.0, LCK_HARD, &dbstate);
+imregister-1.0/src/detregister2.c:    fd = setlockfile2 (fullname, 2.0, LCK_XCLD, &filestate);
+imregister-1.0/src/imstatreg.c:  fd = setlockfile2 (DataBase, 600.0, LCK_HARD, &dbstate);
+imregister-1.0/src/mknames.c:  fd = setlockfile2 (argv[1], 60.0, LCK_XCLD, &dbstate);
+libohana/src/glockfile.c:   setlockfile2 returns a file descriptor to an open READ/WRITE access file,
+libohana/src/glockfile.c:  fd = setlockfile2 (filename, timeout, type, state);
+libohana/src/glockfile.c:  /* setlockfile2 returns a pointer to a vile open for update */
+libohana/src/glockfile.c:int setlockfile2 (char *filename, double timeout, int type, int *state) {
+libohana/src/phot_catalog.c:  fd = setlockfile2 (catalog[0].filename, 3600.0, lockmode, &dbstate);
+misc/src/dbtest.c:int setlockfile2 (char *filename, double timeout, int hard, int *state);
+misc/src/dbtest.c:  if ((fd = setlockfile2 (dbfile, 60.0, LCK_HARD, &dbstate)) == -1) {
+misc/src/glockfile2.c:int setlockfile2 (char *filename, double timeout, int type, int *state) {
+status/user/elixir.c:  fd = setlockfile2 (fifo, 2.0, LCK_XCLD, &state);
+status/user/elixir.c:  fd = setlockfile2 (fifo, 2.0, LCK_XCLD, &state);
+
+---- info on -time -trange ----
+
+
+convert to a single usage: -trange (start) (stop||range), -time (time)
+allow multiple entries
+
+-time vs -trange:
+
+./imregister/src/photsearch.c:   if (N = get_argument (argc, argv, "-trange")) {
+./imregister/src/transreg.c:     if (N = get_argument (argc, argv, "-trange")) {
+./imregister/src/imsearch.c:     if (N = get_argument (argc, argv, "-trange")) {
+./imregister/src/photsearch2.c:  if (N = get_argument (argc, argv, "-trange")) {
+./status/user/detrend.c:         if (N = get_argument (argc, argv, "-trange")) {
+./status/user/images.c:          if (N = get_argument (argc, argv, "-trange")) {
+./status/user/imrough.c:         if (N = get_argument (argc, argv, "-trange")) {
+
+elixir2: grep -- -time `find . -name "*.c"`
+./addrefs/src/args.c:  if ((i = get_argument (argc, argv, "-time"))) {
+./imregister/src/old/detsearch.new.c:  if (N = get_argument (argc, argv, "-time")) {
+./imregister/src/old/imsearchrough.c:  if (N = get_argument (argc, argv, "-time")) {
+./imregister/src/old/detregister.old2.c:  if (N = get_argument (argc, argv, "-time")) {
+./imregister/src/old/detregister.old.c:  if (N = get_argument (argc, argv, "-time")) {
+./imregister/src/old/detsearch1.c:  if (N = get_argument (argc, argv, "-time")) {
+./imregister/src/detsearch.c:  if (N = get_argument (argc, argv, "-time")) {
+./imregister/src/detregister.c:  if (N = get_argument (argc, argv, "-time")) {
+./imregister/src/photsearch.c:  if (N = get_argument (argc, argv, "-time")) {
+./imregister/src/transearch.c:  if (N = get_argument (argc, argv, "-time")) {
+./imregister/src/imsearch.c:  if (N = get_argument (argc, argv, "-time")) {
+./imregister/src/photsearch2.c:  if (N = get_argument (argc, argv, "-time")) {
+./scatfit/src/initialize.c:  if (N = get_argument (argc, argv, "-time")) {
+./status/user/gimages.c:  if (N = get_argument (argc, argv, "-time")) {
+./status/user/detrend.c:  if (N = get_argument (argc, argv, "-time")) {
+./status/user/dmags.c:  if (N = get_argument (argc, argv, "-time")) {
+./status/user/elixir.c:  if (N = get_argument (argc, argv, "-time")) {
+./status/user/ddmags.c:  if (N = get_argument (argc, argv, "-time")) {
+./status/user/resid.c:  if (N = get_argument (argc, argv, "-time")) {
+./status/user/photresid.c:  if (N = get_argument (argc, argv, "-time")) {
+./status/user/images.c:  if (N = get_argument (argc, argv, "-time")) {
+./status/user/imdata.c:  if (N = get_argument (argc, argv, "-time")) {
+./status/user/imextract.c:  if (N = get_argument (argc, argv, "-time")) {
+./status/user/imlist.c:  if (N = get_argument (argc, argv, "-time")) {
+./status/user/imrough.c:  if (N = get_argument (argc, argv, "-time")) {
+./status/user/imsearch.c:  if (N = get_argument (argc, argv, "-time")) {
+./status/user/photcodes.c:  if (N = get_argument (argc, argv, "-time")) {
+./status/user/zeropts.c:  if (N = get_argument (argc, argv, "-time")) {
+./status/user/ddmagsextract.c:  if (N = get_argument (argc, argv, "-time")) {
+./status/user/ddmagextract.c:  if (N = get_argument (argc, argv, "-time")) {
+
+
+haka1: grep -- -trange *
+dt.select:    $line = "-type flat -filter $name -mode $mode -trange $start $stop";
+fr.select:    $line = "-type object -mode $mode -trange $start $stop -filter $name";
+imselect:     $line = "-type flat -filter $name -mode $mode -trange $ARGV[3] $ARGV[4]";
+mktrans:      @list = `photsearch -trange $start $stop -photcode $code`;
+
+haka1: grep -- -time *
+normalize:    if ($ARGV[0] eq "-time") {
+
+haka1: grep -- -trange *
+mk.ptlist:  imsearch $config $type -trange $start $stop | awk '{n=substr($6,0,7)}{printf "%s/%s %s/%s%s %s %s\n", $5, $6, n, n, $4, $4, $3}'
+phot.by.night: transreg $code $zp $dzp $date 1d -trange
+
+haka1: grep -- -time *
+fr.smooth:set mask=`detsearch -ccd $ccd -type mask -time $start -select -quiet`
+phot.by.night:set answer=`photsearch -time $date 1d -photcode $code | awk '{f+=$3}{f2+=$3*$3}END{print f/NR, sqrt (f2/NR - f*f/NR/NR)}'`
Index: /tags/start/Ohana/doc/pipeline/.mana
===================================================================
--- /tags/start/Ohana/doc/pipeline/.mana	(revision 12606)
+++ /tags/start/Ohana/doc/pipeline/.mana	(revision 12606)
@@ -0,0 +1,2 @@
+99/11/12 12:22:43: echo {1280 / (25.4*8)}
+99/11/12 12:46:39: quit
Index: /tags/start/Ohana/doc/pipeline/elixir.fig
===================================================================
--- /tags/start/Ohana/doc/pipeline/elixir.fig	(revision 12606)
+++ /tags/start/Ohana/doc/pipeline/elixir.fig	(revision 12606)
@@ -0,0 +1,76 @@
+#FIG 3.2
+Portrait
+Center
+Inches
+Letter 
+90.00
+Single
+-2
+1200 2
+1 1 0 1 0 7 0 0 -1 4.000 1 0.0000 5175 3000 1650 975 5175 3000 6825 3975
+1 1 0 1 0 7 0 0 -1 4.000 1 0.0000 8400 10575 1350 825 8400 10575 9750 11400
+1 1 0 1 0 7 0 0 -1 4.000 1 0.0000 2475 10650 1350 825 2475 10650 3825 11475
+2 4 0 1 0 7 0 0 20 0.000 0 0 7 0 0 5
+	 8400 8700 6600 8700 6600 6375 8400 6375 8400 8700
+2 4 0 1 0 7 2 0 20 0.000 0 0 7 0 0 5
+	 9450 8250 7650 8250 7650 5925 9450 5925 9450 8250
+2 4 0 1 0 7 0 0 20 0.000 0 0 7 0 0 5
+	 7425 9150 5625 9150 5625 6825 7425 6825 7425 9150
+2 4 0 1 0 7 0 0 -1 4.000 0 0 7 0 0 5
+	 3300 9150 3300 6825 1500 6825 1500 9150 3300 9150
+2 1 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 1
+	 5850 3900
+2 1 0 1 0 7 0 0 -1 4.000 0 0 -1 1 0 2
+	1 0 1.00 60.00 120.00
+	 6225 3750 7950 5925
+2 1 0 1 0 7 20 0 -1 0.000 0 0 -1 1 0 2
+	1 0 1.00 60.00 120.00
+	 4275 3900 2400 6825
+2 1 0 1 0 7 0 0 -1 4.000 0 0 -1 1 1 2
+	1 0 1.00 60.00 120.00
+	1 0 1.00 60.00 120.00
+	 2475 9150 2475 9825
+2 1 0 1 0 7 0 0 -1 4.000 0 0 -1 1 0 2
+	1 0 1.00 60.00 120.00
+	 7350 9150 7875 9825
+2 1 0 1 0 7 0 0 -1 4.000 0 0 -1 1 0 2
+	1 0 1.00 60.00 120.00
+	 9150 8250 8475 9750
+2 1 0 1 0 7 0 0 -1 4.000 0 0 -1 1 0 2
+	1 0 1.00 60.00 120.00
+	 7950 8700 8175 9750
+2 1 1 1 0 7 0 0 -1 4.000 0 0 -1 1 0 2
+	1 0 1.00 60.00 120.00
+	 3300 9975 5625 8325
+2 1 1 1 0 7 0 0 -1 4.000 0 0 -1 1 0 2
+	1 0 1.00 60.00 120.00
+	 7050 10500 3300 8325
+2 2 0 1 7 7 1 0 20 0.000 0 0 -1 0 0 5
+	 2925 4875 4275 4875 4275 5625 2925 5625 2925 4875
+2 1 0 1 0 7 1 0 -1 0.000 0 0 -1 1 0 2
+	1 0 1.00 60.00 120.00
+	 5550 3975 6000 6825
+2 1 0 1 0 7 2 0 -1 0.000 0 0 -1 1 0 2
+	1 0 1.00 60.00 120.00
+	 5850 3900 6975 6375
+2 2 0 1 7 7 1 0 20 0.000 0 0 -1 0 0 5
+	 5775 4575 7125 4575 7125 5400 5775 5400 5775 4575
+4 0 0 0 0 0 36 0.0000 4 375 8385 1200 1500 Elixir: Calibration and Data Evaluation\001
+4 0 0 0 0 0 18 0.0000 4 255 915 5850 7425 Ptolemy\001
+4 0 0 0 0 0 18 0.0000 4 195 465 5850 8175 data\001
+4 0 0 0 0 0 18 0.0000 4 195 1155 5850 8550 evaluation\001
+4 0 0 0 0 0 18 0.0000 4 195 720 1650 7425 FLIPS\001
+4 0 0 0 0 0 18 0.0000 4 255 1320 7650 10350 Photometry\001
+4 0 0 0 0 0 18 0.0000 4 255 1320 7725 10875 Astrometry\001
+4 0 0 0 0 0 18 0.0000 4 195 1260 1800 10425 Calibration\001
+4 0 0 0 0 0 18 0.0000 4 255 780 2025 10875 Images\001
+4 0 0 0 0 0 18 0.0000 4 225 720 4800 3075 and/or\001
+4 0 0 0 0 0 18 0.0000 4 255 1110 3975 2625 Telescope\001
+4 0 0 0 0 0 18 0.0000 4 195 930 5325 3525 Archive\001
+4 0 0 0 0 0 18 0.0000 4 195 1185 1650 8550 creation &\001
+4 0 0 0 0 0 18 0.0000 4 195 1155 1650 8865 evaluation\001
+4 0 0 0 0 0 18 0.0000 4 195 1200 1650 8175 calibration\001
+4 0 0 0 0 0 18 0.0000 4 255 765 6225 5250 images\001
+4 0 0 0 0 0 18 0.0000 4 255 765 3225 5475 images\001
+4 0 0 0 0 0 18 0.0000 4 195 1200 3000 5175 calibration\001
+4 0 0 0 0 0 18 0.0000 4 195 870 6000 4875 science \001
Index: /tags/start/Ohana/doc/pipeline/flags.fig
===================================================================
--- /tags/start/Ohana/doc/pipeline/flags.fig	(revision 12606)
+++ /tags/start/Ohana/doc/pipeline/flags.fig	(revision 12606)
@@ -0,0 +1,29 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter  
+100.00
+Single
+-2
+1200 2
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 3
+	 2400 975 4050 975 4050 4125
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 3
+	 6525 1425 7650 1425 7650 4200
+4 0 0 0 0 2 14 0.0000 4 195 1695 600 975 Bit 15: ID_Moving\001
+4 0 0 0 0 2 14 0.0000 4 180 1590 600 1425 Bit 14: ID_USNO\001
+4 0 0 0 0 2 14 0.0000 4 195 2085 4275 1425 Bit 14: ID_Bad_Object\001
+4 0 0 0 0 2 14 0.0000 4 195 1695 7875 1875 Lower Byte Values\001
+4 0 0 0 0 2 14 0.0000 4 150 1095 8025 2325 0x01: Ghost\001
+4 0 0 0 0 2 14 0.0000 4 150 1005 8025 2625 0x02: Trail\001
+4 0 0 0 0 2 14 0.0000 4 150 1050 8025 2925 0x03: Bleed\001
+4 0 0 0 0 2 14 0.0000 4 180 1785 600 1875 Bit 13: ID_Variable\001
+4 0 0 0 0 2 14 0.0000 4 180 1875 600 2325 Bit 12: ID_Transient\001
+4 0 0 0 0 2 14 0.0000 4 180 1905 600 2775 Bit 11: ID_Bad_Data\001
+4 0 0 0 0 2 14 0.0000 4 195 1635 600 3225 Bit 10: ID_Proper\001
+4 0 0 0 0 2 14 0.0000 4 150 1620 600 3675 Bit 09: Undefined\001
+4 0 0 0 0 2 14 0.0000 4 150 1620 600 4125 Bit 08: Undefined\001
+4 0 0 0 0 0 12 0.0000 4 180 510 6750 1350 (if yes)\001
+4 0 0 0 0 0 12 0.0000 4 180 510 2925 900 (if yes)\001
+4 0 0 0 0 2 14 0.0000 4 180 1770 4275 1875 Bit 13: ID_Asteroid\001
Index: /tags/start/Ohana/doc/pipeline/loneos.fig
===================================================================
--- /tags/start/Ohana/doc/pipeline/loneos.fig	(revision 12606)
+++ /tags/start/Ohana/doc/pipeline/loneos.fig	(revision 12606)
@@ -0,0 +1,174 @@
+#FIG 3.2
+Portrait
+Center
+Inches
+Letter 
+90.00
+Single
+-2
+1200 2
+6 2775 9450 8325 11250
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 5475 10500 825 450 5475 10500 6300 10950
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 3675 10500 825 450 3675 10500 4500 10950
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 7275 10500 825 450 7275 10500 8100 10950
+2 4 1 1 0 7 0 0 -1 4.000 0 0 7 0 0 5
+	 8325 11250 8325 9450 2775 9450 2775 11250 8325 11250
+2 1 1 1 0 7 0 0 -1 4.000 0 0 -1 0 0 2
+	 6375 9450 6375 11250
+4 0 0 0 0 0 18 0.0000 4 195 840 5025 10650 Star dB\001
+4 0 0 0 0 0 18 0.0000 4 255 1050 3150 10650 Image dB\001
+4 0 0 0 0 0 18 0.0000 4 195 945 6825 10650 Rock dB\001
+4 0 0 0 0 0 18 0.0000 4 195 1440 3825 9900    Photom dB\001
+-6
+6 3975 8400 5175 8850
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 3975 8400 5175 8400 5175 8850 3975 8850 3975 8400
+4 0 0 0 0 0 18 0.0000 4 195 810 4125 8775 addstar\001
+-6
+6 2100 3150 3075 3525
+2 2 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 2100 3150 3075 3150 3075 3525 2100 3525 2100 3150
+4 0 0 0 0 0 18 0.0000 4 195 735 2175 3450 flatten\001
+-6
+6 375 10050 1725 11250
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 1050 10650 675 600 1050 10650 1725 11250
+4 0 0 0 0 0 18 0.0000 4 195 750 750 10725 USNO\001
+-6
+6 375 8625 1725 9825
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 1050 9225 675 600 1050 9225 1725 9825
+4 0 0 0 0 0 18 0.0000 4 195 1125 450 9300 HST GSC\001
+-6
+6 3225 6525 4425 6975
+6 3225 6525 4425 6975
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 3225 6525 4425 6525 4425 6975 3225 6975 3225 6525
+4 0 0 0 0 0 18 0.0000 4 195 495 3525 6825 fstat\001
+-6
+-6
+6 2550 4800 3750 5250
+6 2550 4800 3750 5250
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 2550 4800 3750 4800 3750 5250 2550 5250 2550 4800
+4 0 0 0 0 0 18 0.0000 4 255 780 2700 5175 dophot\001
+-6
+-6
+6 2925 5475 4125 6225
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 3525 5850 600 375 3525 5850 4125 6225
+4 0 0 0 0 0 18 0.0000 4 255 345 3300 5925 obj\001
+-6
+6 2250 3825 3450 4575
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 2850 4200 600 375 2850 4200 3450 4575
+4 0 0 0 0 0 18 0.0000 4 195 255 2700 4275 flt\001
+-6
+6 3600 7275 4800 8025
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 4200 7650 600 375 4200 7650 4800 8025
+4 0 0 0 0 0 18 0.0000 4 195 480 3975 7725 cmp\001
+-6
+6 5925 8325 7125 8775
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 5925 8325 7125 8325 7125 8775 5925 8775 5925 8325
+4 0 0 0 0 0 18 0.0000 4 195 660 6075 8625 filters\001
+-6
+6 6150 6375 7800 7575
+6 6150 6375 7800 7575
+1 1 0 1 0 7 0 0 -1 4.000 1 0.0000 6975 6975 825 600 6975 6975 7800 7575
+4 0 0 0 0 0 18 0.0000 4 195 510 6750 6900 alert\001
+-6
+4 0 0 0 0 0 18 0.0000 4 195 465 6750 7275 files\001
+-6
+6 1650 7425 2850 7875
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 1650 7425 2850 7425 2850 7875 1650 7875 1650 7425
+4 0 0 0 0 0 18 0.0000 4 225 675 1800 7800 gastro\001
+-6
+6 2775 12600 3975 13050
+6 2925 12750 3825 12975
+4 0 0 0 0 0 18 0.0000 4 195 915 2925 12975 addusno\001
+-6
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 2775 12600 3975 12600 3975 13050 2775 13050 2775 12600
+-6
+6 4200 12600 5400 13050
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 4200 12600 5400 12600 5400 13050 4200 13050 4200 12600
+4 0 0 0 0 0 18 0.0000 4 195 1005 4350 12975 markstar\001
+-6
+6 5625 12600 6825 13050
+6 5625 12600 6825 13050
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 5625 12600 6825 12600 6825 13050 5625 13050 5625 12600
+-6
+4 0 0 0 0 0 18 0.0000 4 195 1080 5775 12975 markrock\001
+-6
+6 7050 12600 8250 13050
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 7050 12600 8250 12600 8250 13050 7050 13050 7050 12600
+4 0 0 0 0 0 18 0.0000 4 255 765 7200 12975 nrphot\001
+-6
+6 8100 6450 9750 7650
+1 1 0 1 0 7 0 0 -1 4.000 1 0.0000 8925 7050 825 600 8925 7050 9750 7650
+4 0 0 0 0 0 18 0.0000 4 255 885 8475 7290 pictures\001
+4 0 0 0 0 0 18 0.0000 4 240 795 8475 6975 results,\001
+-6
+6 7725 8250 8925 8700
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 7725 8250 8925 8250 8925 8700 7725 8700 7725 8250
+4 0 0 0 0 0 18 0.0000 4 165 645 7875 8625 status\001
+-6
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 1425 1950 750 525 1425 1950 2175 2475
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 3750 1950 750 525 3750 1950 4500 2475
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 3525 7650 2850 7650
+2 4 1 1 0 7 0 0 -1 4.000 0 0 7 0 0 5
+	 2025 12375 2025 8550 150 8550 150 12375 2025 12375
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 3375 11250 3375 12600
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 0 1 2
+	0 0 1.00 60.00 120.00
+	 2250 3075 1425 2475
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 0 1 2
+	0 0 1.00 60.00 120.00
+	 2850 3075 3750 2475
+2 1 1 1 0 7 0 0 -1 4.000 0 0 -1 1 0 2
+	0 0 1.20 100.00 200.00
+	 2550 3525 4875 9450
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 4800 11250 4800 12600
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 6225 11250 6225 12600
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 7575 11250 7575 12600
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 0 1 3
+	0 0 1.00 60.00 120.00
+	 2775 12825 1050 12825 1050 12375
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 0 1 3
+	0 0 1.00 60.00 120.00
+	 1650 7650 1050 7650 1050 8550
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 6525 8325 6675 7500
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 6225 9450 6361 8772
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 8039 9453 8189 8703
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 8339 8253 8489 7503
+4 0 0 0 0 0 18 0.0000 4 195 1155 525 12075 references\001
+4 0 0 0 0 0 18 0.0000 4 165 840 675 11775 astrom.\001
+4 0 0 0 0 0 18 0.0000 4 195 825 3375 2025 archive\001
+4 0 0 0 0 0 18 0.0000 4 255 1020 900 2025 telescope\001
+4 0 0 0 0 0 36 0.0000 4 495 4200 5250 4425 Variability Pipeline\001
+4 0 0 0 0 0 36 0.0000 4 435 3870 5550 3450 U.W. / LONEOS \001
Index: /tags/start/Ohana/doc/pipeline/params.txt
===================================================================
--- /tags/start/Ohana/doc/pipeline/params.txt	(revision 12606)
+++ /tags/start/Ohana/doc/pipeline/params.txt	(revision 12606)
@@ -0,0 +1,125 @@
+# Configuration file for Loneos analysis pipeline 
+
+# important files and directories
+IN_DIR			/pallas
+OUT_DIR			/irene/d11/workspace
+#
+CATDIR			/hebe/d27/database
+IMAGE_CATALOG		/hebe/d27/database/Images.dat
+IMAGE_CATALOG_TEMPLATE	/hebe/d27/database/template.cat
+CATALOG_TEMPLATE	/hebe/d27/database/template.cat
+ROCK_CATALOG		/hebe/d27/database/Rocks.dat
+#
+GSCFILE			/metis/d11/references/GSC/GSCregions.tbl
+GSC_DIR			/metis/d11/references/GSC
+USNO_CDROM		/metis/d11/references/USNO
+DOPHOT_PARAMS		/metis/d11/references/config/default_parameters
+FLATTEN_SCRIPT		/metis/d11/references/config/flatten.pro
+LONEOS_REGIONS		/metis/d11/references/config/regions.map
+
+# parameters for "fstat"
+# instrumental mag zero point
+ZERO_PT			24.5
+DOPHOT_CHAR_LINE	129
+DOPHOT_TYPE_FIELD	5
+DOPHOT_AP_FIELD		91
+DOPHOT_PSF_FIELD	52
+MIN_SN_FSTAT		6.0
+
+# parameters for "gastro"
+DEFAULT_RADIUS   32.0
+MINIMUM_RADIUS   1.5
+MIN_ERROR	 0.6
+MIN_PRECISE	 0.12
+CCD_PC1_1	 1
+CCD_PC2_2	 -1    # for loneos
+CCD_PC1_2	 0
+CCD_PC2_1	 0
+ASEC_PIX	 2.82
+NFIELD		 3.0
+MMIN		 6.0
+ROT_ZERO	 0
+dROT		 1.0
+NROT		 2
+POLAR_AXIS_RA	 -90.0
+POLAR_AXIS_DEC   89.88
+RA_OFFSET        -90.0
+DEC_OFFSET        0.0
+
+# parameters for "addstar"
+# airmass extinction coefficient (in mag / airmass)
+NSIGMA			3.0
+ALPHA			0.03
+XOVERSCAN		60
+YOVERSCAN		50
+
+# parameters for "controller"
+NEW_IMAGES		images.dat
+USERNAME		gene
+PASSWORD		gene
+
+# here we list all available machines
+NMACHINES		6
+MACHINE0		metis
+MACHINE1		hebe
+MACHINE2		iris
+MACHINE3		irene
+#MACHINE4		juno
+MACHINE4		ceres
+MACHINE5		vesta
+
+# here we define which machines which are always free
+fMACHINE0		1
+fMACHINE1		1
+fMACHINE2		1
+fMACHINE3		1
+fMACHINE4		0
+fMACHINE5		0
+fMACHINE6		0
+
+LOCAL_MACHINE		1  # machine with catalog on local disk
+
+# parameters for "status"
+TIME_REFERENCE		90/01/01 00:00:00
+
+# parameters for "nrphot"
+# make this one small to boost change of getting an early region 
+TAU			3.0  		
+SCATTER_LIM		15.0
+MAG_LIM			17.0
+IMAGE_SCATTER		0.075
+NIMAGE_SCATTER		1.5
+STAR_SCATTER		0.05
+
+### parameters for "markstar"
+SEARCH_RADIUS		360   # region for initial trail hunt, in arcsec 
+TRAIL_WIDTH		5.0   # expected trail width, in arcsec
+NANGLE_BINS		180   # Number of angular bins in 180 degrees
+NPTSINLINE		5     # minimum points needed for trail
+MIN_DENSITY		0.025 # minimum linear density in star/arcsec
+SPACE_SIGMA		10.0  # how much denser than average for trail?
+# parameters defining bright star exclusion regions
+BRIGHT_XTRAIL_WIDTH	  5.0 # faintest sat. star
+BRIGHT_XTRAIL_MAG	  9.5 # faintest sat. star
+BRIGHT_XTRAIL_SLOPE	-80.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_YTRAIL_WIDTH	  5.0 # faintest sat. star
+BRIGHT_YTRAIL_MAG	 11.0 # faintest sat. star
+BRIGHT_YTRAIL_SLOPE    -400.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_HALO_MAG		  8.5 # faintest sat. star
+BRIGHT_HALO_SLOPE	-28.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+# parameters which define the ghosts
+GHOST_MAG		7.5
+GHOST_RADIUS		200   # in arcsec
+OPTICAL_AXIS1		2154.0
+OPTICAL_AXIS2		2193.0
+
+# parameters for "addusno"
+USNO_RADIUS		5.0   # in arcsec
+USNO_PROPER		20.0   # in arcsec
+USNO_RED		1000  # code for USNO Red data
+USNO_BLUE		1001  # code for USNO Blue data
+
+# parameters for "markrock"
+ROCK_RADIUS		2.0   # in arcsec
+ROCK_MAX_RADIUS		20.0  # in arcsec
+ROCK_MAX_SPEED          0.1   # in arcsec / sec
Index: /tags/start/Ohana/doc/pipeline/pipeline.c
===================================================================
--- /tags/start/Ohana/doc/pipeline/pipeline.c	(revision 12606)
+++ /tags/start/Ohana/doc/pipeline/pipeline.c	(revision 12606)
@@ -0,0 +1,22 @@
+\documentstyle[astro]{article]
+\GoodMargins
+\title{Variability Pipeline}
+\author{Eugene Magnier}
+\begin{document}
+\maketitle
+
+\section{Overview}
+
+\section{Photometry -- Dophot}
+
+\section{Astrometry -- gastro}
+
+\section{The Photometry Database}
+
+\section{Visualization Tools}
+
+\section{Software Distribution}
+
+\section{Programming Details}
+
+\end{document}
Index: /tags/start/Ohana/doc/pipeline/pipeline.tex
===================================================================
--- /tags/start/Ohana/doc/pipeline/pipeline.tex	(revision 12606)
+++ /tags/start/Ohana/doc/pipeline/pipeline.tex	(revision 12606)
@@ -0,0 +1,997 @@
+%\documentstyle[astro,psfig]{article}
+\documentclass{article}
+\usepackage{psfig}
+\usepackage{astro}
+\usepackage{times}
+\GoodMargins
+\newcommand{\note}[1]{({\bf #1})}
+\title{Variability Pipeline}
+\author{Eugene Magnier}
+\begin{document}
+\maketitle
+
+\section{Overview}
+
+The Loneos Pipeline provides automated reduction of images, including
+photometry and astrometry, with the final data stored in a photometry
+database organized by star position on the sky.
+
+Fig.~\ref{pipeline} shows a schematic of the analysis pipeline.
+Images are written to the disk from the camera by the software which
+runs it, {\tt astrocam}.  The resulting images are FITS files (which
+may be arbitrarily sized) and have header keyword parameters RA and
+DEC specifying rough celestial coordinates.  Images are first analyzed
+by {\tt dophot}, which produces instrumental photometry and pixel
+coordinate positions for stars and other objects in the images,
+writing files with a particular format, called OBJ files in this
+discussion.  The results from {\tt dophot} are cleaned up by a program
+called {\tt fstat} which merges the header information from the image
+with the most relevant parts of the OBJ file, creating a new file with
+the CMP format.  Astrometry is performed on the CMP file with the
+program {\tt gastro}.  {\tt Gastro} makes a comparison with an
+astrometric reference database and only changes CMP header keywords as
+a result.  Finally, the processed image CMP file is added to the
+photometry database with the program {\tt addstar}.  The photometry
+database is maintained in a large number of files (CPT files), each
+representing a small region of sky.  There is no relationship between
+the image locations and the boundaries of CPT file.  All of these
+processes occur on individual image, and would typically be performed
+while the observations are occuring, or during the day following, but
+may be performed at any time to add new or archived data to the
+database.
+
+Once large batches of images have been processed, a series of programs
+should be run to clean up the photometry database.  Typically, these
+routines would be run at the end of a night on all of the CPT files to
+which new data were added.  First, {\tt markstar} identifies bad data
+(the trails of satelites, the bleeding columns from stars, ghost
+images), and flags these data points appropriately.  Second, {\tt
+  addusno} matches the catalog stars with stars from the USNO database
+and adds the USNO magnitudes to the photometry database.  Next, {\tt
+  markrock} searches for likely asteroids in the CPT file, marks them,
+and writes the asteroid observations to an asteroid database.  It also
+notes measurements which are likely to be noise and cosmic rays.
+Finally, {\tt nrphot} determines relative photometric calibrations for
+observations in a set of CPT files.  
+
+With the exception of {\tt dophot}, all of the programs in the
+pipeline refer to a single configuration file to determine the large
+number of parameters necessary in the process.  The default parameter
+file is hardwired into the programs, but an alternate configuration
+file may be specified with the environment variable {\tt
+  PIPE\_CONFIG}.  This option makes independent processing of multiple
+data sources trivial.  For example, if the pipeline is to be used for
+both Loneos and SDSS image analysis and display, there could be two
+configuration files (eg, {\tt loneos.txt} and {\tt sdss.txt}), one for
+each data source.  Several important parameters would be different
+between these two, for example, the initial plate scale guess for the
+astrometry routine, or the parameters which define the rough chip
+orientation.  This scheme allows for analysis of different types of
+images, with a common destination photometry database, or for
+independent photometry databases.
+
+\begin{figure}
+\psfig{file=schematic.eps,width=9cm}
+\caption{\label{pipeline} 
+Schematic of the photometry pipeline.  Rectangles represent programs,
+while ovals represent data products.  Arrows show the direction of
+travel of information.  The flatten routine is a filter whose position
+may change as the pipeline matures.
+}
+\end{figure}
+
+Data from different sources can be processed by the pipeline and
+stored in the same photometry database, since all photometry is tagged
+with a source ID in the database (as are the images in the image
+database).  This allows us to include, for example, the USNO catalog
+magnitude measurements (or a subset) in the photometry database for a
+quick comparion.  Different sources may be considered different
+filters, so color-color and color-magnitude diagrams could be
+extracted by specifying choices for source catalog.  Currently each
+object has a single primary photometric system, and individual
+observations may be combined to determine that average (eg, if they
+are different photometry sources with roughly the filter bandpass) or
+they may be ignored when calculating relative magnitudes (eg, the USNO
+magnitudes would be ignored).  This may be expanded upon by defining
+multiple average magnitudes and allowing different measurements to
+contribute only to the appropriate average.  The determination of the
+photometry code for a particular image is currently not well defined.
+There are several points in the analysis where the user (or the
+controlling program) may specify the photometry source.  A table
+should be kept in the photometry catalog to define the various
+photometry codes.  
+
+\section{Image Analysis Pipeline}
+\subsection{Photometry -- Dophot}
+
+Photometry is performed using a varient of {\tt Dophot}.  The version
+of dophot is based on Dophot 2.0, but it has been adapted to
+streamline processing of many files.  First, with this version of
+dophot, any FITS format data is safely read in.  Instead of compiling
+to a fixed maximum size, only the memory needed to contain the image
+matrix is allocated.  The image is also converted to REAL*32 from
+whatever BITPIX for processing.  Finally, only a single, complete
+parameter file is loaded by dophot.  There is no option for a modified
+and a default parameter file.  The parameter file to be used is
+defined, along with the input image and the output object list on the
+command line when the program is run: \\
+{\tt dophot image.fits image.obj parameter\_file} \\
+To achive this, the code from dophot was wrapped within a C program
+which interprets the command line arguments, allocates the necessary
+memory, and reads in the image.  The rest of the processing is
+performed by dophot in the standad manner.  Notice that we use a
+consistent naming convention through the pipeline reductions.  The
+image is called {\tt foo.fits}, while the resulting dophot-produced
+photometry list is called {\tt foo.obj}.  
+
+\subsection{Cleanup -- fstat}
+
+After an image is processed by dophot, the object file ({\tt foo.obj})
+is converted to a more-compact, more-complete file called a CMP file,
+with a name of the form ({\tt foo.cmp}).  This conversion is done with
+the program {\tt fstat}.  The CMP file consists of the FITS header
+from the original image ({\tt foo.fits}), with some additional
+keywords to be used at later stages in the analysis, followed by an
+ASCII list of the interesting data from ({\tt foo.obj}).  In this
+list, types 6 and 8 are excluded, and only the following values are
+kept:
+\begin{verbatim}
+X       Y     Mag   dMag t log(sky) 
+1342.0  106.1 14.166 000 4 3.2
+\end{verbatim}
+Objects with a signal-to-noise ratio lower than a specified cutoff
+({\tt MIN\_SN\_FSTAT}) are also excluded.  Some general information
+about the image is derived by {\tt fstat} (FWHM, saturation and
+completeness limits, number of each dophot type) and stored as
+keywords in the header.  The photometry source must be specified at
+this stage as one of the command line arguments, though the value used
+may be overridden in one of the stages belowe.  The resulting file can
+now stand on its own without reference to the original image.  The
+keywords used by {\tt fstat} include the minimum signal to noise, a
+rough guess at the zero point ({\tt ZERO\_PT}), and four numbers
+defining the format of the {\tt dophot} OBJ file.
+
+\subsection{Astrometry -- gastro}
+
+Astrometry is performed automatically by the program {\tt gastro}.
+{\tt gastro} loads a CMP file and determines an initial guess for the
+center coordinates (based on the RA and DEC header keywords).  The
+program also uses the configuration information about the plate scale
+and rough orientation of the image to get a close to the final
+solution.  Also, the true sky position of the telescope pole may be
+defined to allow astrometry on images taken close to the pole.  The
+comparison is made with the astrometric catalog, which may be the HST
+Guide Star Catalog, or it may be any source if the data is placed in
+the correct format.
+
+\section{The Photometry Database}
+
+\subsection{Photometry File Format}
+The photometry database consists of a large number of photometry files
+representing sections of the sky and a file containing information on
+the images incorporated in the database.  These files are called
+alternatively ``region files'' or CPT files (because they have the
+extension {\tt .cpt}).  The photometry files are sorted by Declination
+into different directories, each consisting of a band 7.5\degree\ 
+wide.  These directories have names like n0730, representing the band
+starting at a Declination of +07:30.  The image database (Images.dat)
+is stored in the upper level directory of this directory tree.  In
+fact, the locations of the Images.dat file, the photometry database,
+and such are all flexible and may be changed by altering the
+configuration file.
+
+The name and location of each sky region comes from the Hubble Space
+Telescope Guide Star Catalog.  There is a file, GSCregions.tbl, which
+can be used to find the region file appropriate for any location on
+the sky.  A number of routines exist to make such a query.  
+
+Each photometry file in the photometry database contains all
+observations and all average values for all stars observed within the
+appropriate region on the sky.  The identity of stars is essentially
+determined by the RA and DEC coordinates.  In very crowded regions,
+the end user may need to double check that a neighboring star is not
+contaminating individual detections (see the discusion on {\tt
+  addstar} below).
+
+The photometry files are stored in a binary format, both to reduce the
+volume and to speed access.  As a result, the interpretation of the
+data is machine dependent: little endian machines need to swap the
+data intelligently.  Fortunately, this operation is taken care of
+appropriately, if the programs are compiled with the BYTESWAP option
+set as needed, which is automatically set by the Makefile in the case
+of a Linux machine.  For reference, Suns, SGI, and HP are all big
+endian, while PCs and DECs are little endian.  The automatic
+conversion takes place by using the funcions {\tt Fread} and {\tt Fwrite}
+to substitute for the standard C library {\tt fread} and {\tt fwrite}
+functions.  {\tt Fread} and {\tt Fwrite} are told the datatype being read,
+and they know the layout of the bytes for a particular datatype.
+Anytime the definitions of the relevant structures (see below) are
+changed, {\tt Fread} and {\tt Fwrite} must be updated.  Fortunately, there
+is only one file ({\tt Fread.c}), and it has a single byteswapping
+section, making it easy to adjust the code appropriately.
+
+The format of a single photometry database file consists four
+sections:  
+\begin{itemize}
+\item {\bf header} -- this is a standard FITS header with room for comments
+  about the file or whatever.  Since the rest of the file is not a
+  standard FITS file, the SIMPLE keyword is set to False.  The three
+  necessary keywords are NSTARS, NMEAS, and NMISS, which define the
+  sizes of the next three sections.
+\item {\bf average} -- this section contains all average measurement
+  quantities for each star in the file.  There are NSTARS entries, and
+  each entry is the data from a structure of type Average (defined in
+  loneos.h, and discussed in more detail below).  Thus, the total size
+  in bytes of this section can be found by NSTARS*sizeof(Average).
+\item {\bf measure} -- this section contains the individual
+  measurements for each star in the database.  There are NMEAS
+  entries, and like the average section, each entry is a single
+  structure, in this case of type Measure (in loneos.h, see below).
+  All measurements of a single star are consecutive.  The number of
+  measurements for a single star is defined by average.Nm and the
+  starting entry for a single star is given by average.offset.
+  Therefore, the first measurement of a specific star average[500]
+  would be given by measure[average[500].offset], while the second is 
+  measure[average[500].offset + 1], and so forth.  
+\item {\bf missing} -- this section contains references to all missing
+  measurements of a star.  This means all of those occasions when an
+  image enclosed the location of a star in the database, but no star
+  was detected on the image.  Similar to the case of the measure
+  section, each star has a number of missing entries (which may be 0)
+  given by average.Nn, and the first missing entry is given by
+  average.missing.  Each missing entry value is again a structure of
+  type Missing.  Currently, the only data in the structure is the time
+  of the observation, which allows for an unambiguous recovery of the
+  image where the star was missed.
+\end{itemize}
+
+\subsubsection*{Average Structure defined in loneos.h}
+\begin{verbatim}
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm, Nn;  /* number of measurements, missing */
+  short int Xp, Xm;           /* log(chisq) values in tenths */
+  unsigned short int code;    /* an ID code (ie, star, ghost, satelite, etc) */
+  signed int offset;          /* offset to first measurement */
+  signed int missing;         /* offset to first missing obs */
+} Average; /* 28 bytes / Average */
+\end{verbatim}
+The structure above defines the average data stored in the photometry
+database for each star.  Most of the entries are self-explantory, but
+some need a bit of clarification.  The two $\chi^2$ entries ({\tt Xp}
+and {\tt Xm}) are the $\chi^2$ values of the average position and the
+average magnitude.  These are stored as logarthmic quantities because
+high dynamic range is not needed.  For the magnitude, the assumption
+is that the star brightness is constant and the $\chi^2$ incorporates
+the photometric errors on each measurement.  For the postion, the
+a default constant error is used \note{True?} and again the assumption
+is that the postion is constant.  As discussed above, the values of
+{\tt Nm} and {\tt Nn} give the number of measurements and missing
+observations for this star, while the entries {\tt offset} and {\tt
+  missing} point to the first {\bf measure} and {\bf missing} entry
+for this star.  The entry {\tt M} is the current best average
+magnitude solution for this star (see the section on Relative
+Photometry).  Finally, the entry {\tt code} is an ID code for each
+object, which may define a variety of things about the object.  For
+example, if the object is known to be variable, or if the object is
+associated with a USNO star, or if the object is a measurement of an
+asteroid.  See below for details of these definitions.
+
+\subsubsection*{Measure Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  short int dR, dD;           /* 1/100 of arcsec (-327.67 to +327.67 valid range) */
+  short int M;                /* thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mcal;             /* image cal mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 to 0.255 valid range) */
+  char dophot;                /* dophot type (1-9) */
+  unsigned short int source;  /* code to identify photometry source */
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+  unsigned int average;       /* reference to corresponding average entry */
+  /* upper byte of Measure.average stores flags:
+   limit of 16,777,215 stars (Naverage) in a file (=0xFFFFFF) 
+   flags: average & 0x1000000 */
+} Measure; /* 20 bytes / Measure */
+\end{verbatim}
+}
+The structure above defines the individual measurement data stored for
+each observation of each star.  The first two entries, dR and dD, are
+the difference between the average coordinates for this star and the
+coordinates determined for this observation.  Clearly, if this
+residual is too large, the individual measurement will not be
+successfully matched with the average star position.  {\tt M} and {\tt
+  dM} are the instrumental magnitude and error for this measurement,
+after correction for the exposure time and a zero point (defined in
+the configuration file as ZERO\_PT).  The entry {\tt t} determines the
+time of the individual observation.  This is important not only for
+timing purposes, but also to determine the source image for this
+observation.  The time and the entry {\tt source} uniquely determine
+the image in the image database that generated this measurement.
+Furthermore, this correspondence allows for determination of the pixel
+coordinates on the chip, by going throught the image astrometry stored
+in the Image database (see below).  The entry {\tt source} is a code which
+identifies the particular CCD/Telescope/Filter setup.  Each unique
+{\tt source} should be treated as an independent filter set for the
+purposes of accurate relative photometric comparisons.  This entry
+also allows external catalog data, such as the USNO or Sloan
+photometry, to be added to the database, as desired.  The entry {\tt
+  average} is a pointer back to the {\bf average} section to allow
+determination of the star from the measurements, in addition to the
+reverse.  The bits of the upper byte of this value are reserved for
+flags used to define particular situations for this measurement.
+Possible values are:
+\begin{itemize}
+\item 1 = BLEND\_IMAGE - the star on the image matched more than one
+  catalog star
+\item 2 = BLEND\_CATALOG - the star in the catalog matched more than
+  one image star
+\item 4 = UPPER\_LIMIT - \note{not really used?}
+\item 8 = CALIBRATED - relative photometry has been performed at least
+  once.
+\end{itemize}
+The entry {\tt dophot} stores the dophot type for this particular
+measurement (1-9: four extra bits in this field).   
+Finally, the value {\tt Mcal} determines the photometric calibration
+of this specific measurment.  This value is an offset appropriate to
+this image (and if needed, this point in time and this chip position)
+to bring the observations of the stars on multiple images to a common
+system (see the section on relative photometry).
+
+\subsection{Image Database}
+
+All images for which photometry has been included in the photometry
+database also have entries in an image database.  The image database
+is (currently) a single file in the upper directory of the photometry
+database.  The name of the file is determined by the IMAGE\_CATALOG
+entry in the configuration file, and is currently set to Images.dat.
+Like the photometry database files, the image database consists of a
+FITS header followed by binary data.  There is only one type of binary
+data: each image has an entry, which is the data from a structure of
+type Image (loneos.h).  The number of images in the file is determined
+by the {\tt NIMAGES} keyword.  If the number of images becomes too
+large, extrapolation of the system to a set of image database files
+with a reference list is quite straightforeward, and could be modeled
+on the organization of the region files (eg, one image database file
+for each Declination directory).
+
+\subsubsection*{Image Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  Coords         coords;            /* 120 bytes */
+  unsigned int   tzero;             /* readout time row 0 in sec (0 - 142 years valid range) */
+  unsigned int   nstar;             /* number of stars on image */
+  short int      secz;              /* thousanths of airmass (valid range -32.000 -- 32.000) */
+  short int      NX, NY;            /* dimensions of image */
+  short int      apmifit, dapmifit; /* aperture correction and error in thousandths of mag */
+  short int      source;            /* identifier for CCD (each ever used will have a unique letter) */
+  short int      Mcal;              /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      dMcal;             /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      Xm;                /* 10*log(image chi-square) */
+  char           name[32];          /* name of original image */
+  unsigned char  detection_limit;   /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  saturation_limit;  /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  cerror;            /* astrometric error: 1/50 of arcsec (0 -- 5.12 valid range) */
+  unsigned char  fwhm_x, fwhm_y;    /* PSF terms in 25*arcsec (valid range 0.0 -- 10.2" ") */
+  unsigned char  trate;             /* 10000 * scan rate in sec/pix (0 -- 0.0256 valid range, 
+                                       typically 0.0146. this is used only to determine the time
+                                       of the observation, not to find the coordinates.  1 byte
+                                       gives 0.11 sec accuracy */
+  char           code;              /* flag to mark an image as bad or whatever */
+  char           dummy[7];          /* extra space for the future?  (seems like a lot!) */
+  float          exptime;           /* exposure time, seconds */
+} Image;  /* 192 bytes / Image */
+\end{verbatim}}
+The structure above lists all of the data stored for each image.  A
+substantial amount of information is stored for each image.  First,
+the astrometric calibration information is stored in a {\tt Coords}
+structure (see coordinate systems, above).  The upper and lower limits
+of the photometry in the database (in instrumental magnitudes) is
+stored in {\tt detection\_limit} and {\tt saturation\_limit}.  These
+values are useful for comparison for those stars where observations
+are missing.  The relationship between time and pixel coordinates is
+given by {\tt tzero} and {\tt trate}.  Drift images will have a scan
+rate stored in {\tt trate}, while staring images will have a value of
+0.0 for this entry ({\tt tzero} then applies to the whole image).
+Other important parameters are kept: the astrometric error ({\tt
+  cerror}), the airmass ({\tt secz}), the exposure time ({\tt
+  exptime}), the number of stars detected ({\tt nstar}), the FWHM
+values ({\tt fwhm\_x, fwhm\_y}), the image name ({\tt name}), and the
+size of the image ({\tt NX, NY}).  The entry {\tt source} is used as
+above to define the CCD/Telescope/Filter used for this observation.
+The entry {\tt code} is used to flag images in various ways.
+Currently, only one bit is used, to define if the image has
+unacceptable photometric scatter.  Seven extra bytes are stored for
+future additions.
+
+\subsection{Data Incorporation -- {\tt addstar}}
+
+Images which are completely processed ({\tt dophot, fstat, gastro}) are
+then incorporated into the photometry database with the program {\tt 
+addstar}.  This program decides which region files are appropriate
+for this particular image, then one-by-one adds stars from the image
+to the appropriate region file.  Stars already in the catalog are
+matched with stars in the new image purely by a positional comparison.
+In order to avoid the difficulty of comparisons in the RA and DEC
+coordinate frame, a cartesian projection is performed.  The stars from
+the image being processed and the database stars in the same area are
+projected onto a tangent plane and positional comparisons made in this
+(locally cartesian) coordinate frame.  This avoids the dangerous
+singularities at the pole and also makes the RA 0,360\degree\ boundary
+a trivial problem.  
+
+Several choices must be made in the comparison process.  If a star in
+the catalog is matched with a star in the image, the new measurements
+of that star are added to the database.  If a star in the database
+lies in the field of the image, but is not detected, this information
+is added to the list of missing data.  The only data stored in this
+case is the time and source, which is sufficient to unambiguously
+identify the source image from the image database.  This allows later
+programs to find relevant statistics from the image database, if
+necessary.  If a star is detected in the image, but is not already in
+the database, a new entry is added to the database.  In addition, the
+same ``missing data'' from all previous observations images which have
+covered this location (ie, images already in the image database) are
+included.  This last step is necessary so that the image processing
+order is not important.  
+
+Stars also run the danger of being crowded together.  Since all
+comparisons are performed on the basis of position alone, crowded
+fields may make for ambiguous cross-identifications.  A pair of stars
+are matched if the difference in their positions is less than a
+specified search radius (usually dependent on the astrometric for the
+image).  If more than one catalog stars is correlated with a star in
+an image, the new measurement is added to {\em both} catalog stars,
+and a flag is set noting that this observation had a blended IMAGE.
+Conversely, if a single catalog star is matched with more than one
+image star, both new measurements are added to the one catalog star,
+and a different flat is set, noting that this observation had a
+blended CATALOG.   
+
+\section{Catalog Update and Cleaning}
+
+Occasionally, once a large number of images have been added to the
+photometry database, a set of programs should be run to clean and
+update the CPT files.  This may best be done on CPT files after a
+night's worth of data is incorporated.  These routines define bad
+data, identify the USNO catalog stars, and search for asteroids and
+other junk.  Most of the results from these routines are the addition
+of object flags to the Average data structures (Average.code).  Most
+of these routines process data within a single CPT file at a time.
+
+\subsection{Markstar}
+
+The first of the update programs, {\tt markstar}, identifies bad data
+and flags it.  It makes three types of identifications: bright stars,
+ghost stars, and trails.  In the first case, it searches the HST guide
+star catalog for bright stars within the field of the current CPT
+file.  Three types of pixels are flagged for bright stars.  Any
+measurements within a circular region centered on the star are suspect
+(the ``halo'' of the bright star).  Second, points along the X axis
+are likely to contain flux from the diffraction spikes.  Finally,
+points along the Y axis are likely to have bleeding in addition to the
+diffraction spikes.  Each of these three regions has a different size
+and range which must be defined in the configuration file.  The
+regions are represented by a representative magnitude and a scale
+parameter.  For example, the diameter $d$ of the halo for a star with
+magnitude $m$ is defined as 
+$d = \mbox{BRIGHT\_HALO\_SLOPE} (m - \mbox{BRIGHT\_HALO\_MAG})$.  The X and
+Y axis points are defined by the length of the diffraction spike, with
+an equivalent formula, and the width of the spike.  Since these are
+each independent, there are 8 parameters to define the exclusion
+regions of bright stars.  One of the current drawbacks of this system
+is the reliance on the HST Guide Star photometry.  In the HST Guide
+Star Catalog, only one photometry band is given, so no color
+information is available.  The parameters currently used were defined
+based on a large number of bright stars, with no adjustment for the
+different effective filter system of the Loneos telescope and the HST
+GSC.  Thus, occasionally very red stars will be several magnitudes
+brighter in the real data than reported in the catalog.  As a result,
+large numbers of bad data points in these halos and spikes may be
+missed.  
+
+The second type of bad data flagged by {\tt markstar} are the trails
+from satelite and other space junk.  This portion of the program
+searches for objects which land along a line and which have a high
+linear density.  Parameters may be adjusted to define the width and
+the necessary density or number of points in the line.  Objects in
+lines are also only identified if all observations come from a common
+image.  If an object only has one measurement and it is in a trail,
+the entire Average is flagged to be bad.  However, if an object has
+many measurements and only one is bad, the object is only flagged as
+having some bad data points.  
+
+The third type of bad dat are ghost star images.  The HST GSC is
+searched for stars projected across the telescope optical axis, which
+is defined by the user.  All objects within a region of fixed size is
+marked for ghost stars brighter than a specific cutoff magnitude.
+Similar to the trails, the average is marked as bad only if all
+detections of an object are ghost images.  Otherwise, it is noted that
+some data may be bad.
+
+\subsection{Addusno}
+
+The program {\tt addusno} makes two types of identifications of stars
+with the USNO catalog.  First, it searches for coincidences within a
+small, specified radius.  The choice of this radius is somewhat
+tricky: it is important to catch the association, but also to avoid
+making too many associations.  Unfortunately, astrometric errors in
+the USNO catalog make it necessary to choose a surprisingly large
+radius of 5\asec.  To avoid making double matches (matching the two
+USNO stars to the same photometry database object), only the USNO
+object closest to the object is associated.  There are also a
+substantial number of stars with significant proper motion between the
+USNO epochs and the current date.  It is not unusual to see 8-15\asec\ 
+discrepancy for specific stars.  To catch these objects, any objects
+which do not match the USNO database, but which have more than a
+minimum number of measurements (2 or 3?) are searched for more distant
+USNO companions.  A large, user-specified radius is used for this
+search.  Of course, only USNO stars which are not already matched to
+the database may be candidates for the proper motion match.  This
+stage is suceptible to errors in that a slow-moving solar-system
+object may be associated with a faint USNO star.  For this reason,
+objects flagged as high proper motion stars should be taken with some
+caution.  Of course, during the {\tt addusno} stage, no objects
+already flagged as bad by {\tt markstar} will be matched with USNO
+stars.  
+
+\subsection{Markrock}
+
+Once stars have been identified with the USNO database, it is possible
+to search for asteroid detections.  The program {\tt markrock}
+searches within a specific CPT file for objects which are moving along
+straight lines in (X,Y,t) space.  In order for an object to be found
+by {\tt markrock}, it must have three points, each with only single
+measurements.  The third point must land within a specified distance
+of the line projected from the first two data points.  These
+comparisons are made in the three dimensional space of image position
+and time.  Also, objects are only accepted if they have a speed less
+than a threshold.  If an object is moving too fast, it will make a
+streak on each individual image and will probably be missed anyway.
+Moving objects detected in this way are flagged in the photometry
+database and are also written to a Rock database.  Currently, the Rock
+database just contains ASCII lists of the RA, DEC, Mag, and time for
+each detection.  In fact, the data are stored in pairs of detections,
+with the middle detection saved twice.  This format makes it easy to
+plot lines connecting the points using the connect-the-dots plotting
+style of status/kapa (see below).
+
+One of the current drawbacks of {\tt markrock} is the insistence on
+three observations with only 1 measurement each.  If an object is
+moving too slowly, two of the dectections of the object may be merged
+together.  Enough data is stored in the database to extract these
+individual measurements, so a more sophisticated search is possible.
+It is also currently the case that USNO proper motion stars are
+ignored, but some of these will be asteroid detections which are
+simply too close to a faint USNO stars (it has to be faint because it
+would otherwise be associated with a star in the photometry
+database).  
+
+\begin{figure}
+\psfig{file=flags.eps,width=9cm}
+\caption{\label{flags} 
+Pictoral representation of the Average.code flags.  The lower byte
+value is used for specific definitions of object types.
+}
+\end{figure}
+
+\subsection{Data Flags}
+
+The identifications made by the above routines are noted as a set of
+flags in the Average.code structure entry.  Some of these flags are
+mutually exclusive, so a certain bit may have more than one meaning,
+depending on the value of other bits.  Figure~\ref{flags} shows a
+pictoral representation of the meaning of the different bit fields.
+The uppermost bit (bit 15) determines if the object may be considered
+a ``fixed'' star or something which has no fixed location.  If it is
+not fixed, and this bit is 1, then there are several options.  The
+second uppermost bit (bit 14) will be set if this object is one of the
+three types of bad data flagged by {\tt markstar}.  The lower byte of
+code is used to define the type of bad data: ghost, trail, or bleed.
+Thus, any datapoints determined to be a satelite trail will have a
+code value of 0xc002 (49154 decimal).  If an object is a moving
+object, but not a bad datapoint, it may be identified as a ``rock''
+(an asteroid) by the program {\tt markrock}.  In this case, the flag
+for an asteroid is turned on (bit 13).  Thus anything identified as a
+rock by {\tt markrock} will have a code value of 0xa000.  The lower
+byte of code is not yet defined for asteroids, but could be reserved
+for distinguishing different classes of asteroids (ie, on the basis of
+orbital speeds, and so forth).  Objects which are fixed may have a
+variety of possible flags.  First, an object may be identified with a
+USNO star (bit 14).  It may be found to exhibit variability (bit 13),
+implying that the relative photometry routine should ignore it.  If
+may be a transient object (bit 12).  Note that, while an object
+associated with a USNO object may not be transient, an object which is
+variable may also not be associated with a USNO object.  Thus, we need
+seperate bits for variable vs transient.  Different types of variable
+objects may be represented with different values of the lower byte.
+For example, a Cepheid may have a specific lower byte code of 0x01,
+which an RR Lyra may have a lower byte code of 0x02.  Thus a Cepheid
+associated with the USNO catalog would have a total code value of
+0x6001. Finally, any of these types of non-moving objects may have
+some bad individual measurements (bit 12) or may be found to have a
+significant proper motion (bit 11).
+
+\section{Visualization -- Status}
+
+Visualization of the data in the photometry database can best be
+performed with the program {\tt status}.  This is a command-line
+driven program with a math and macro language which makes it easy to
+perform complex tasks.  
+
+First, a few notes about the user interface.  The interface has an
+interaction similar to {\tt tcsh}.  The arrows allow editing of
+previous commands.  You can also use emacs-like commands such as
+cntl-a to reach the beginning of the line and cntl-e to reach the end.
+There is command and file completion: if you type part of a command
+(as the first thing on a line) and then type tab, it will fill in as
+much as possible, until the word is not unique.  Typing tab twice at
+that point will list the possible endings.  For any but the first word
+on a line, the same thing will happen for the files in the current
+directory.  It is also possible to type just a fraction of a command,
+as long as it is unique.  An ambiguous command will list the possible
+alternatives.  For example:
+\begin{verbatim}
+status: c
+ambiguous command: c ( catalog cgrid clear create cursor )
+\end{verbatim}
+
+The shell is essentially an interpretive programming language.
+Variables are set as follows:
+\begin{verbatim}
+status: $fred = 10
+\end{verbatim}
+Any expression within curly brackets \{\} is assumed
+to be an arithmetical expression and is evaluated before the line is
+executed.  For example:
+\begin{verbatim}
+echo {$fred*dcos(45)}
+\end{verbatim}
+would give the response 7.07107.  There are math functions cos, sin,
+and tan, which operate on radian expressions, and also dcos, dsin,
+dtan, which operate on degree expressions.  There are also the
+equivalent inverse functions: eg., asin and dasin return radians and
+degrees, respectively.  The help section on Math defines all of the
+available math functions.  
+
+\subsection{Miscellaneous Commands}
+\begin{verbatim}
+!                         -- system call
+?                         -- list commands 
+??                        -- list variables 
+echo                      -- type this line 
+exec                      -- system call
+exit                      -- exit program 
+help                      -- get help on a function 
+output                    -- redirect output to file
+quit                      -- exit program 
+scan                      -- scan line from keyboard or file to variable 
+wait                      -- wait until return is typed
+which                     -- show command 
+\end{verbatim}
+Most of these are self-explanatory.  The command ?? prints the system
+variables.  The {\tt help} command will provide help on a single
+command or, without any arguments, will list all available help
+files (this includes general help not associated with a specific
+command).  
+
+\subsection{Shell Programing}
+\begin{verbatim}
+break                     -- escape from function 
+for                       -- loops 
+if                        -- logical cases 
+input                     -- read command lines from a file 
+macro                     -- deal with the macros 
+\end{verbatim}
+
+There are several options for programming in {\tt status}.  First, a
+file which contains a series of commands can be executed with {\tt
+  input (filename)}.  It is also possible to define macros which will
+behave much like regular commands.  A macro is defined by typing {\tt
+  macro name} or {\tt macro create name} followed by the commands.
+Arguments to the macro are assigned to the variables \$1 .. \$N and
+the number of arguments is given by \$0.  Macros may be defined in
+{\tt input} files, and in fact when {\tt status} is started, it loads
+the file {\tt \~/.statusrc} which may contain default macros.  Simple
+loops and if statements can be performed, and are quite useful for
+complex macros.  
+
+``If'' statements are similar in syntax to C if statements, but only
+the following logical operators are available: $>$, $<$, $=$, !, $|$,
+and \&.  Notice that (currently) there is no $>=$ or $<=$ symbol.  The
+operator ! means ``not equal to'', but cannot be used to negate a
+logical value.  The operators $|$ and \& have the meaning of ``or'' and
+``and'' respectively.  Math expresions in the if statement must be
+contained in curly braces, as elsewhere.  Variables with string values
+may use the logical $=$ operator to test if two strings are the same.
+``For'' loops are quite simplistic.  The form is:
+\begin{verbatim}
+for var first last delta
+ (commands)
+end
+\end{verbatim}
+The value of {\tt \$var} will start at the value {\tt first} and increment by
+{\tt delta} after each loop.  The loop will stop after {\tt \$var} is greater
+than {\tt stop}.  The value {\tt delta} is optional, with 1 assumed.
+The value of {\tt \$var} may be changed during the loop, and if set
+beyong the value of {\tt last} will end the loop early.  
+
+\subsection{Vector Plotting}
+
+\begin{verbatim}
+box                       -- draw a box on the plot
+clear                     -- erase plot
+create                    -- create a new vector
+cursor                    -- get coords from cursor
+grid                      -- plot cartesian grid
+hist                      -- create histogram from a vector
+labels                    -- define labels for plot
+limits                    -- define plot limits
+plot                      -- plot a pair of vectors
+print                     -- write vectors to file
+ps                        -- define labels for plot
+set                       -- vector math
+style                     -- set the style for graph plots
+vectors                   -- list vectors
+zplot                     -- plot scaled points 
+\end{verbatim}
+
+In addition to scalar variables, {\tt status} can manipulate and
+display 1-D vector variables.  Many of the commands which extract data
+from the photometry database place the data in vectors as well as
+plotting them.  A vector can also be created based on a number
+sequence with the command {\tt create name Nelements start delta}.
+The resulting vector has $Nelements$ entries, starting at a value of
+$start$ and running until $start + delta*Nelements$.  If $delta$ is
+0.0, all elements will have the value of $start$.  A histogram of a vector
+may be made with the command {\tt hist}, which creates a new vector
+containing the histogram of the first vector.  The data range and bin
+size of the histogram are defined in same way as with create.  This
+makes it easy to create the index vector that goes with a histogram
+vector:  
+\begin{verbatim}
+hist y Ny 1 100 0.1
+create dx 1 100 0.1
+\end{verbatim}
+The above will create a histogram of y in Ny and the index in dx.
+Plotting this with {\tt plot dx Ny} will show the histogram.
+
+Vector math is performed with a command of the form {\tt set new =
+  (expression)}.  The expression is some math function employing
+vectors and scalars.  A complete listing of the math operators
+available in {\tt set} can be found in the help for {\tt set}.
+
+Once vectors are defined, they may be plotted.  A pair of vectors can
+be plotted against each other if they have the same number of entries.
+The plotting is performed on the graphics window, Kapa.  There are
+actually several graphics windows available to {\tt status}, any of
+which may be used to plot at any time.  Some of the more complex
+operations default to either graphics window 0 or 1, depending on the
+context.  Except for those functions with a pre-defined window, all
+plotting functions apply to the current graphics window unless an
+option {\tt -n N} is given to specify a different window.  The
+plotting style is determined by the command {\tt style} which can set
+the line width, the line type (solid, dashed, dotted, etc), the point
+type (box, cross, etc), the point size, the color, and whether a pair
+of vectors is plotted as a sequence of points, a set of connected
+lines, or a histogram.  Some functions which make plots use their own
+styles, as discussed below.  The function {\tt limits} lets the user
+set the range of the plot axes, or check the current setting.  The
+command {\tt plot} will plot a pair of vectors on the current graphics
+window using the current plotting style for that window.  The command
+{\tt zplot} will plot a pair of vectors with the point size scaled by
+a third vector, with maximum and minimum point sizes representing
+specified values.  The {\tt cursor} command goes the other way: this
+command puts the Kapa window in cursor mode and waits for input from
+Kapa.  The user can then type any alphanumeric key on the graphics
+windows and will be told both the pointer location (in the graphics
+coordinates) and will have the coordinates stored in {\tt status}
+variables.  For example, by typing ``1'' in the sky display window,
+the RA and DEC of the pointer are stored in the variables {\tt \$R1}
+and {\tt \$D1}.  This command can be used to let the user define
+locations or regions of interest on the Kapa window. (Future addition:
+{\tt button}, which does the same with the mouse buttons).  
+
+\subsection{Database Functions}
+
+\begin{verbatim}
+gcat                        -- get catalog at location
+gimages                     -- get images at location
+gstar                       -- get star statistics
+extract                     -- extract average vectors from catalogs
+mextract                    -- extract measurement vectors from catalogs
+imstats                    -- plot image statistics
+imextract                   -- extract image vectors from database
+lcat                        -- list catalogs in display region
+cmatch                      -- match two catalogs
+\end{verbatim}
+
+There are a variety of other commands which directly refer to the
+photometry database.  Some of these functions extract data of various
+types from the database, others perform more complex plotting
+operations.  The commands listed above are those which simply extract
+data from the database.  The first three list information relevant to
+a specific RA, DEC location on the sky: {\tt gcat (RA) (DEC)} lists
+the catalog at the specified location and places the name in the
+variable {\tt \$CATNAME}, {\tt gimages (RA) (DEC)} lists all images
+which overlap the specified location, , {\tt gstars (RA) (DEC)
+  (RADIUS)} lists data about the stars within a specified radius of
+the specified location (all numbers above are given in decimal
+degrees).  Similarly, {\tt lcat} lists the catalogs in the region.
+Imstats lists statistics about each image
+
+The next three commands extract a specific piece of information from
+the photometry database and places it in a vector.  First, {\tt
+  extract} will extract average values for each star and place it in a
+vector.  Next, {\tt mextract} will extract measurement values for each
+star and place it in a vector: as a result a single star may have
+multiple entries in the measurement vectors.  Finally, {\tt imextract}
+will extract image statistics into vectors (not yet implemented).
+
+
+\begin{verbatim}
+catalog                    -- plot catalog stars
+cgrid                      -- plot sky coordinate grid
+cplot                      -- plot vectors in sky coordinates
+czplot                     -- plot scaled vectors in sky coordinates
+images                     -- plot image boxes
+imdense                    -- image density plot
+lcurve                     -- plot lightcurve for a star
+pcat                       -- plot catalog boundaries
+region                     -- define sky region for plot
+resid                      -- plot residuals
+simage                     -- plot stars in an image
+\end{verbatim}
+
+There are two types of database plotting functions: those that display
+or refer to the spatial charateristics of the data and those that
+refer to other types of charatersitics, such as the time domain.  The
+graphics window 0 is reserved for all plots of objects on the sky.
+The command {\tt region} defines the current sky coordinates for plots
+in graphic window 0.  The command {\tt pcat} plots the outline of all
+photometry database files which are within the currently defined
+region (and by default, only those with data).  {\tt images} plots the
+outline of the images in the image database, while {\tt imdense} shows
+the number of images at a location by randomly spacing dots within the
+boundary of the images.  The command {\tt cgrid}
+draws a grid in celestial coordinates on the for the current region.
+
+The most complex, but also one of the most useful command is {\tt
+  catalog}, which plots the positions of stars in the photometry
+database (and others) on the sky.  There are many options to this
+command.  One set allows the user to plot stars from the photometry
+database (the default), from the HST GSC, or from an ASCII text file
+with RA, DEC, and Mag in specified columns.  If the ASCII file has a
+fixed number of bytes per line, the data can be more quickly loaded.
+The size of the points may be scaled by the star magnitude, by the
+number of observations of the star, or by the number of missing
+datapoints for the star.  In addition, points may be plotted only if
+they land in specified magnitude ranges, or with specified numbers of
+measurements, or missed measurements.  Also, objects may be plotted
+only if they have a specified Average.code, so that only asteroids or
+only perfect stars may be plotted.  The plotted vectors may be saved,
+if desired, and the source catalog epoch may be specified as different
+from J2000 (only valid for ASCII data).
+
+Several other commands relate to non-spatial charateristics of images
+and stars.  {\tt lcurve} will plot a light curve for all stars within
+some radius of a point.  {\tt resid} plots the photometry residuals
+for a particular region file.  
+
+\section{Some Examples}
+
+\begin{figure}
+\psfig{file=allsky.ps,width=16cm}
+\caption{\label{allsky} 
+Map of the entire sky, and images added to database.
+}
+\end{figure}
+
+Fig.~\ref{allsky} shows a map of the entire sky, and the location
+of the images currently in the database.  This picture was made with
+the following commands: (output is not shown) \\
+\begin{verbatim}
+status: region 0 0 90 gls
+status: cgrid
+status: style -lw 2 -c red 
+status: images
+status: ps
+\end{verbatim}
+In this example, on the graphics window, the image boxes are shown in
+red.  The user now has the possiblitiy of using the cursor command to
+narrow in on a specific region, and so forth.  
+
+\begin{figure}
+\psfig{file=catalog.ps,width=9cm}
+\caption{\label{catalog} 
+Comparison between HST GSC and photometry database astrometry. 
+}
+\end{figure}
+
+Fig.~\ref{catalog} shows an example comparison of the photometry
+database star positions and the HST Guide Star Catalog star
+positions.  The crosses are from the photometry database while the
+boxes are from the HST GSC.  The size of both points is a function of
+brightness.  This plot was made with the following commands (starting
+from the previous image):
+\begin{verbatim}
+status: cursor  (typed 1 on region of interest)
+1 137.097858 22.698305
+q 137.097858 22.698305
+status: region $R1 $D1 0.5 TAN
+status: cgrid
+status: box
+status: style -pt 0 
+status: gcat $R1 $D1 
+  0 n2230/1951.cpt *
+status: catalog n2230/1951.cpt -m 12 18
+status: style -pt 2
+status: catalog n2230/1951.cpt -m 12 18 -g
+\end{verbatim}
+
+\begin{figure}
+\psfig{file=lightcurve.ps,width=9cm}
+\caption{\label{lightcurve} 
+Lightcurve for several image stars.
+}
+\end{figure}
+
+Fig.~\ref{lightcurve} shows an example lightcurve from three stars in
+the above field.  The x axis shows the time in seconds, which the y
+axis shows the star magnitudes.  This plot was made with the following commands (starting
+from the previous image):
+{\small
+\begin{verbatim}
+status: cursor
+1 137.062562 22.791860
+q 137.062562 22.791860
+status: lcurve $R1 $D1 0.01 -l
+status: box
+status: gstar $R1 $D1 0.01
+read 11318 stars from catalog file /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt (22462 total measurements)
+508 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.068619 22.785400 18.438000  1 (2)  1.000000 1.000000
+498 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.062820 22.792747 12.882000  3 (0)  1.000000 1.000000
+501 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.064499 22.800817 15.480000  3 (0)  1.000000 1.000000
+\end{verbatim}}
+The last lines show the database information on the three stars.  
+
+\section{Software Distribution}
+
+\section{Programming Details}
+
+\section {Comparison with USNO catalog}
+
+I have made several comparisons between the USNO catalog and results
+from running images from Loneos through the photometry pipeline.  In
+general, there is a good agreement between the astrometry of the two
+datasets.  There are specfic areas where the two disagree, however.
+First, as discussed above, the USNO star positions may be
+significantly different from the observed star positions simply
+because of proper motion.  The first picure in the ``Comparisons
+between Loneos + USNO'' pages shows several stars with significant
+proper motion.  These are currently being flagged in the photometry
+database as discussed.  Other differences evident in this first
+picture include the classification of bright stars and the splitting
+of faint and bright stars.  In the upper right of the image, two
+bright stars are visible, one of which is actually a double.  The USNO
+catalog does a good job of detecting both, but it also detects and
+includes as stars several diffraction spike points.  The HST GSC only
+detected a single point and did not split the star at all.  The Loneos
+data in our pipeline did not detect the star at all due to saturation.
+A star in the upper left corner shows the ability of {\tt dophot} in
+the Loneos pipeline to split double stars.  This star is, on close
+inspection, clearly a double.  The USNO catalog only detects one.  The
+Pipeline not only splits the two stars, but it also makes the correct
+cross-identification of the stars.  
+
+The second set of pictures shows the ability of the Loneos pipeline to
+deal with small galaxies.  There are two small galaxies in this field,
+both of which are broken into 4 or 5 objects by the USNO catalog, but
+maintained as single objects in the Loneos pipeline.  In another
+example (not shown) a bright star within the disk of a small galaxies
+was clearly split from the galaxy by the pipeline (and also by USNO).
+
+\end{document}
Index: /tags/start/Ohana/doc/pipeline/pipeline2.tex
===================================================================
--- /tags/start/Ohana/doc/pipeline/pipeline2.tex	(revision 12606)
+++ /tags/start/Ohana/doc/pipeline/pipeline2.tex	(revision 12606)
@@ -0,0 +1,1284 @@
+%\documentstyle[astro,psfig]{article}
+\documentclass{article}
+\usepackage{psfig}
+\usepackage{astro}
+\usepackage{times}
+\GoodMargins
+\newcommand{\note}[1]{({\bf #1})}
+\title{Variability Pipeline}
+\author{Eugene Magnier}
+\begin{document}
+\maketitle
+
+\section{Overview}
+
+The Loneos Pipeline provides automated reduction of images, including
+photometry and astrometry, with the final data stored in a photometry
+database organized by star position on the sky.
+
+Fig.~\ref{pipeline} shows a schematic of the analysis pipeline.
+Images are written to the disk from the camera by the software which
+runs it, {\tt astrocam}.  The resulting images are FITS files (which
+may be arbitrarily sized) and have header keyword parameters RA and
+DEC specifying rough celestial coordinates.  Images are first analyzed
+by {\tt dophot}, which produces instrumental photometry and pixel
+coordinate positions for stars and other objects in the images,
+writing files with a particular format, called OBJ files in this
+discussion.  The results from {\tt dophot} are cleaned up by a program
+called {\tt fstat} which merges the header information from the image
+with the most relevant parts of the OBJ file, creating a new file with
+the CMP format.  Astrometry is performed on the CMP file with the
+program {\tt gastro}.  {\tt Gastro} makes a comparison with an
+astrometric reference database and only changes CMP header keywords as
+a result.  Finally, the processed image CMP file is added to the
+photometry database with the program {\tt addstar}.  The photometry
+database is maintained in a large number of files (CPT files), each
+representing a small region of sky.  There is no relationship between
+the image locations and the boundaries of CPT file.  All of these
+processes occur on individual image, and would typically be performed
+while the observations are occuring, or during the day following, but
+may be performed at any time to add new or archived data to the
+database.
+
+Once large batches of images have been processed, a series of programs
+should be run to clean up the photometry database.  Typically, these
+routines would be run at the end of a night on all of the CPT files to
+which new data were added.  First, {\tt markstar} identifies bad data
+(the trails of satelites, the bleeding columns from stars, ghost
+images), and flags these data points appropriately.  Second, {\tt
+  addusno} matches the catalog stars with stars from the USNO database
+and adds the USNO magnitudes to the photometry database.  Next, {\tt
+  markrock} searches for likely asteroids in the CPT file, marks them,
+and writes the asteroid observations to an asteroid database.  It also
+notes measurements which are likely to be noise and cosmic rays.
+Finally, {\tt nrphot} determines relative photometric calibrations for
+observations in a set of CPT files.  
+
+With the exception of {\tt dophot}, all of the programs in the
+pipeline refer to a single configuration file to determine the large
+number of parameters necessary in the process.  The default parameter
+file is hardwired into the programs, but an alternate configuration
+file may be specified with the environment variable {\tt
+  PIPE\_CONFIG}.  This option makes independent processing of multiple
+data sources trivial.  For example, if the pipeline is to be used for
+both Loneos and SDSS image analysis and display, there could be two
+configuration files (eg, {\tt loneos.txt} and {\tt sdss.txt}), one for
+each data source.  Several important parameters would be different
+between these two, for example, the initial plate scale guess for the
+astrometry routine, or the parameters which define the rough chip
+orientation.  This scheme allows for analysis of different types of
+images, with a common destination photometry database, or for
+independent photometry databases.
+
+\begin{figure}
+\psfig{file=schematic.eps,width=9cm}
+\caption{\label{pipeline} 
+Schematic of the photometry pipeline.  Rectangles represent programs,
+while ovals represent data products.  Arrows show the direction of
+travel of information.  The flatten routine is a filter whose position
+may change as the pipeline matures.
+}
+\end{figure}
+
+Data from different sources can be processed by the pipeline and
+stored in the same photometry database, since all photometry is tagged
+with a source ID in the database (as are the images in the image
+database).  This allows us to include, for example, the USNO catalog
+magnitude measurements (or a subset) in the photometry database for a
+quick comparion.  Different sources may be considered different
+filters, so color-color and color-magnitude diagrams could be
+extracted by specifying choices for source catalog.  Currently each
+object has a single primary photometric system, and individual
+observations may be combined to determine that average (eg, if they
+are different photometry sources with roughly the filter bandpass) or
+they may be ignored when calculating relative magnitudes (eg, the USNO
+magnitudes would be ignored).  This may be expanded upon by defining
+multiple average magnitudes and allowing different measurements to
+contribute only to the appropriate average.  The determination of the
+photometry code for a particular image is currently not well defined.
+There are several points in the analysis where the user (or the
+controlling program) may specify the photometry source.  A table
+should be kept in the photometry catalog to define the various
+photometry codes.  
+
+\section{Image Analysis Pipeline}
+\label{parallel}
+\subsection{Photometry -- Dophot}
+
+Photometry is performed using a varient of {\tt Dophot}.  The version
+of dophot is based on Dophot 2.0, but it has been adapted to
+streamline processing of many files.  First, with this version of
+dophot, any FITS format data is safely read in.  Instead of compiling
+to a fixed maximum size, only the memory needed to contain the image
+matrix is allocated.  The image is also converted to REAL*32 from
+whatever BITPIX for processing.  Finally, only a single, complete
+parameter file is loaded by dophot.  There is no option for a modified
+and a default parameter file.  The parameter file to be used is
+defined, along with the input image and the output object list on the
+command line when the program is run: \\
+{\tt dophot image.fits image.obj parameter\_file} \\
+To achive this, the code from dophot was wrapped within a C program
+which interprets the command line arguments, allocates the necessary
+memory, and reads in the image.  The rest of the processing is
+performed by dophot in the standad manner.  Notice that we use a
+consistent naming convention through the pipeline reductions.  The
+image is called {\tt foo.fits}, while the resulting dophot-produced
+photometry list is called {\tt foo.obj}.  
+
+\subsection{Cleanup -- fstat}
+
+After an image is processed by dophot, the object file ({\tt foo.obj})
+is converted to a more-compact, more-complete file called a CMP file,
+with a name of the form ({\tt foo.cmp}).  This conversion is done with
+the program {\tt fstat}.  The CMP file consists of the FITS header
+from the original image ({\tt foo.fits}), with some additional
+keywords to be used at later stages in the analysis, followed by an
+ASCII list of the interesting data from ({\tt foo.obj}).  In this
+list, types 6 and 8 are excluded, and only the following values are
+kept:
+\begin{verbatim}
+X       Y     Mag   dMag t log(sky) 
+1342.0  106.1 14.166 000 4 3.2
+\end{verbatim}
+Objects with a signal-to-noise ratio lower than a specified cutoff
+({\tt MIN\_SN\_FSTAT}) are also excluded.  Some general information
+about the image is derived by {\tt fstat} (FWHM, saturation and
+completeness limits, number of each dophot type) and stored as
+keywords in the header.  The photometry source must be specified at
+this stage as one of the command line arguments, though the value used
+may be overridden in one of the stages belowe.  The resulting file can
+now stand on its own without reference to the original image.  The
+keywords used by {\tt fstat} include the minimum signal to noise, a
+rough guess at the zero point ({\tt ZERO\_PT}), and four numbers
+defining the format of the {\tt dophot} OBJ file.
+
+\subsection{Astrometry -- gastro}
+
+Astrometry is performed automatically by the program {\tt gastro}.
+{\tt gastro} loads a CMP file and determines an initial guess for the
+center coordinates (based on the RA and DEC header keywords).  The
+program also uses the configuration information about the plate scale
+and rough orientation of the image to get a close to the final
+solution.  Also, the true sky position of the telescope pole may be
+defined to allow astrometry on images taken close to the pole.  The
+comparison is made with the astrometric catalog, which may be the HST
+Guide Star Catalog, or it may be any source if the data is placed in
+the correct format.
+
+\section{The Photometry Database}
+
+\subsection{Photometry File Format}
+The photometry database consists of a large number of photometry files
+representing sections of the sky and a file containing information on
+the images incorporated in the database.  These files are called
+alternatively ``region files'' or CPT files (because they have the
+extension {\tt .cpt}).  The photometry files are sorted by Declination
+into different directories, each consisting of a band 7.5\degree\ 
+wide.  These directories have names like n0730, representing the band
+starting at a Declination of +07:30.  The image database (Images.dat)
+is stored in the upper level directory of this directory tree.  In
+fact, the locations of the Images.dat file, the photometry database,
+and such are all flexible and may be changed by altering the
+configuration file.
+
+The name and location of each sky region comes from the Hubble Space
+Telescope Guide Star Catalog.  There is a file, GSCregions.tbl, which
+can be used to find the region file appropriate for any location on
+the sky.  A number of routines exist to make such a query.  
+
+Each photometry file in the photometry database contains all
+observations and all average values for all stars observed within the
+appropriate region on the sky.  The identity of stars is essentially
+determined by the RA and DEC coordinates.  In very crowded regions,
+the end user may need to double check that a neighboring star is not
+contaminating individual detections (see the discusion on {\tt
+  addstar} below).
+
+The photometry files are stored in a binary format, both to reduce the
+volume and to speed access.  As a result, the interpretation of the
+data is machine dependent: little endian machines need to swap the
+data intelligently.  Fortunately, this operation is taken care of
+appropriately, if the programs are compiled with the BYTESWAP option
+set as needed, which is automatically set by the Makefile in the case
+of a Linux machine.  For reference, Suns, SGI, and HP are all big
+endian, while PCs and DECs are little endian.  The automatic
+conversion takes place by using the funcions {\tt Fread} and {\tt Fwrite}
+to substitute for the standard C library {\tt fread} and {\tt fwrite}
+functions.  {\tt Fread} and {\tt Fwrite} are told the datatype being read,
+and they know the layout of the bytes for a particular datatype.
+Anytime the definitions of the relevant structures (see below) are
+changed, {\tt Fread} and {\tt Fwrite} must be updated.  Fortunately, there
+is only one file ({\tt Fread.c}), and it has a single byteswapping
+section, making it easy to adjust the code appropriately.
+
+The format of a single photometry database file consists four
+sections:  
+\begin{itemize}
+\item {\bf header} -- this is a standard FITS header with room for comments
+  about the file or whatever.  Since the rest of the file is not a
+  standard FITS file, the SIMPLE keyword is set to False.  The three
+  necessary keywords are NSTARS, NMEAS, and NMISS, which define the
+  sizes of the next three sections.
+\item {\bf average} -- this section contains all average measurement
+  quantities for each star in the file.  There are NSTARS entries, and
+  each entry is the data from a structure of type Average (defined in
+  loneos.h, and discussed in more detail below).  Thus, the total size
+  in bytes of this section can be found by NSTARS*sizeof(Average).
+\item {\bf measure} -- this section contains the individual
+  measurements for each star in the database.  There are NMEAS
+  entries, and like the average section, each entry is a single
+  structure, in this case of type Measure (in loneos.h, see below).
+  All measurements of a single star are consecutive.  The number of
+  measurements for a single star is defined by average.Nm and the
+  starting entry for a single star is given by average.offset.
+  Therefore, the first measurement of a specific star average[500]
+  would be given by measure[average[500].offset], while the second is 
+  measure[average[500].offset + 1], and so forth.  
+\item {\bf missing} -- this section contains references to all missing
+  measurements of a star.  This means all of those occasions when an
+  image enclosed the location of a star in the database, but no star
+  was detected on the image.  Similar to the case of the measure
+  section, each star has a number of missing entries (which may be 0)
+  given by average.Nn, and the first missing entry is given by
+  average.missing.  Each missing entry value is again a structure of
+  type Missing.  Currently, the only data in the structure is the time
+  of the observation, which allows for an unambiguous recovery of the
+  image where the star was missed.
+\end{itemize}
+
+\subsubsection*{Average Structure defined in loneos.h}
+\begin{verbatim}
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm, Nn;  /* number of measurements, missing */
+  short int Xp, Xm;           /* log(chisq) values in tenths */
+  unsigned short int code;    /* an ID code (ie, star, ghost, satelite, etc) */
+  signed int offset;          /* offset to first measurement */
+  signed int missing;         /* offset to first missing obs */
+} Average; /* 28 bytes / Average */
+\end{verbatim}
+The structure above defines the average data stored in the photometry
+database for each star.  Most of the entries are self-explantory, but
+some need a bit of clarification.  The two $\chi^2$ entries ({\tt Xp}
+and {\tt Xm}) are the $\chi^2$ values of the average position and the
+average magnitude.  These are stored as logarthmic quantities because
+high dynamic range is not needed.  For the magnitude, the assumption
+is that the star brightness is constant and the $\chi^2$ incorporates
+the photometric errors on each measurement.  For the postion, the
+a default constant error is used \note{True?} and again the assumption
+is that the postion is constant.  As discussed above, the values of
+{\tt Nm} and {\tt Nn} give the number of measurements and missing
+observations for this star, while the entries {\tt offset} and {\tt
+  missing} point to the first {\bf measure} and {\bf missing} entry
+for this star.  The entry {\tt M} is the current best average
+magnitude solution for this star (see the section on Relative
+Photometry).  Finally, the entry {\tt code} is an ID code for each
+object, which may define a variety of things about the object.  For
+example, if the object is known to be variable, or if the object is
+associated with a USNO star, or if the object is a measurement of an
+asteroid.  See below for details of these definitions.
+
+\subsubsection*{Measure Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  short int dR, dD;           /* 1/100 of arcsec (-327.67 to +327.67 valid range) */
+  short int M;                /* thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mcal;             /* image cal mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 to 0.255 valid range) */
+  char dophot;                /* dophot type (1-9) */
+  unsigned short int source;  /* code to identify photometry source */
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+  unsigned int average;       /* reference to corresponding average entry */
+  /* upper byte of Measure.average stores flags:
+   limit of 16,777,215 stars (Naverage) in a file (=0xFFFFFF) 
+   flags: average & 0x1000000 */
+} Measure; /* 20 bytes / Measure */
+\end{verbatim}
+}
+The structure above defines the individual measurement data stored for
+each observation of each star.  The first two entries, dR and dD, are
+the difference between the average coordinates for this star and the
+coordinates determined for this observation.  Clearly, if this
+residual is too large, the individual measurement will not be
+successfully matched with the average star position.  {\tt M} and {\tt
+  dM} are the instrumental magnitude and error for this measurement,
+after correction for the exposure time and a zero point (defined in
+the configuration file as ZERO\_PT).  The entry {\tt t} determines the
+time of the individual observation.  This is important not only for
+timing purposes, but also to determine the source image for this
+observation.  The time and the entry {\tt source} uniquely determine
+the image in the image database that generated this measurement.
+Furthermore, this correspondence allows for determination of the pixel
+coordinates on the chip, by going throught the image astrometry stored
+in the Image database (see below).  The entry {\tt source} is a code which
+identifies the particular CCD/Telescope/Filter setup.  Each unique
+{\tt source} should be treated as an independent filter set for the
+purposes of accurate relative photometric comparisons.  This entry
+also allows external catalog data, such as the USNO or Sloan
+photometry, to be added to the database, as desired.  The entry {\tt
+  average} is a pointer back to the {\bf average} section to allow
+determination of the star from the measurements, in addition to the
+reverse.  The bits of the upper byte of this value are reserved for
+flags used to define particular situations for this measurement.
+Possible values are:
+\begin{itemize}
+\item 1 = BLEND\_IMAGE - the star on the image matched more than one
+  catalog star
+\item 2 = BLEND\_CATALOG - the star in the catalog matched more than
+  one image star
+\item 4 = UPPER\_LIMIT - \note{not really used?}
+\item 8 = CALIBRATED - relative photometry has been performed at least
+  once.
+\end{itemize}
+The entry {\tt dophot} stores the dophot type for this particular
+measurement (1-9: four extra bits in this field).   
+Finally, the value {\tt Mcal} determines the photometric calibration
+of this specific measurment.  This value is an offset appropriate to
+this image (and if needed, this point in time and this chip position)
+to bring the observations of the stars on multiple images to a common
+system (see the section on relative photometry).
+
+\subsection{Image Database}
+
+All images for which photometry has been included in the photometry
+database also have entries in an image database.  The image database
+is (currently) a single file in the upper directory of the photometry
+database.  The name of the file is determined by the IMAGE\_CATALOG
+entry in the configuration file, and is currently set to Images.dat.
+Like the photometry database files, the image database consists of a
+FITS header followed by binary data.  There is only one type of binary
+data: each image has an entry, which is the data from a structure of
+type Image (loneos.h).  The number of images in the file is determined
+by the {\tt NIMAGES} keyword.  If the number of images becomes too
+large, extrapolation of the system to a set of image database files
+with a reference list is quite straightforeward, and could be modeled
+on the organization of the region files (eg, one image database file
+for each Declination directory).
+
+\subsubsection*{Image Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  Coords         coords;            /* 120 bytes */
+  unsigned int   tzero;             /* readout time row 0 in sec (0 - 142 years valid range) */
+  unsigned int   nstar;             /* number of stars on image */
+  short int      secz;              /* thousanths of airmass (valid range -32.000 -- 32.000) */
+  short int      NX, NY;            /* dimensions of image */
+  short int      apmifit, dapmifit; /* aperture correction and error in thousandths of mag */
+  short int      source;            /* identifier for CCD (each ever used will have a unique letter) */
+  short int      Mcal;              /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      dMcal;             /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      Xm;                /* 10*log(image chi-square) */
+  char           name[32];          /* name of original image */
+  unsigned char  detection_limit;   /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  saturation_limit;  /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  cerror;            /* astrometric error: 1/50 of arcsec (0 -- 5.12 valid range) */
+  unsigned char  fwhm_x, fwhm_y;    /* PSF terms in 25*arcsec (valid range 0.0 -- 10.2" ") */
+  unsigned char  trate;             /* 10000 * scan rate in sec/pix (0 -- 0.0256 valid range, 
+                                       typically 0.0146. this is used only to determine the time
+                                       of the observation, not to find the coordinates.  1 byte
+                                       gives 0.11 sec accuracy */
+  char           code;              /* flag to mark an image as bad or whatever */
+  char           dummy[7];          /* extra space for the future?  (seems like a lot!) */
+  float          exptime;           /* exposure time, seconds */
+} Image;  /* 192 bytes / Image */
+\end{verbatim}}
+The structure above lists all of the data stored for each image.  A
+substantial amount of information is stored for each image.  First,
+the astrometric calibration information is stored in a {\tt Coords}
+structure (see coordinate systems, above).  The upper and lower limits
+of the photometry in the database (in instrumental magnitudes) is
+stored in {\tt detection\_limit} and {\tt saturation\_limit}.  These
+values are useful for comparison for those stars where observations
+are missing.  The relationship between time and pixel coordinates is
+given by {\tt tzero} and {\tt trate}.  Drift images will have a scan
+rate stored in {\tt trate}, while staring images will have a value of
+0.0 for this entry ({\tt tzero} then applies to the whole image).
+Other important parameters are kept: the astrometric error ({\tt
+  cerror}), the airmass ({\tt secz}), the exposure time ({\tt
+  exptime}), the number of stars detected ({\tt nstar}), the FWHM
+values ({\tt fwhm\_x, fwhm\_y}), the image name ({\tt name}), and the
+size of the image ({\tt NX, NY}).  The entry {\tt source} is used as
+above to define the CCD/Telescope/Filter used for this observation.
+The entry {\tt code} is used to flag images in various ways.
+Currently, only one bit is used, to define if the image has
+unacceptable photometric scatter.  Seven extra bytes are stored for
+future additions.
+
+\subsection{Data Incorporation -- {\tt addstar}}
+
+Images which are completely processed ({\tt dophot, fstat, gastro}) are
+then incorporated into the photometry database with the program {\tt 
+addstar}.  This program decides which region files are appropriate
+for this particular image, then one-by-one adds stars from the image
+to the appropriate region file.  Stars already in the catalog are
+matched with stars in the new image purely by a positional comparison.
+In order to avoid the difficulty of comparisons in the RA and DEC
+coordinate frame, a cartesian projection is performed.  The stars from
+the image being processed and the database stars in the same area are
+projected onto a tangent plane and positional comparisons made in this
+(locally cartesian) coordinate frame.  This avoids the dangerous
+singularities at the pole and also makes the RA 0,360\degree\ boundary
+a trivial problem.  
+
+Several choices must be made in the comparison process.  If a star in
+the catalog is matched with a star in the image, the new measurements
+of that star are added to the database.  If a star in the database
+lies in the field of the image, but is not detected, this information
+is added to the list of missing data.  The only data stored in this
+case is the time and source, which is sufficient to unambiguously
+identify the source image from the image database.  This allows later
+programs to find relevant statistics from the image database, if
+necessary.  If a star is detected in the image, but is not already in
+the database, a new entry is added to the database.  In addition, the
+same ``missing data'' from all previous observations images which have
+covered this location (ie, images already in the image database) are
+included.  This last step is necessary so that the image processing
+order is not important.  
+
+Stars also run the danger of being crowded together.  Since all
+comparisons are performed on the basis of position alone, crowded
+fields may make for ambiguous cross-identifications.  A pair of stars
+are matched if the difference in their positions is less than a
+specified search radius (usually dependent on the astrometric for the
+image).  If more than one catalog stars is correlated with a star in
+an image, the new measurement is added to {\em both} catalog stars,
+and a flag is set noting that this observation had a blended IMAGE.
+Conversely, if a single catalog star is matched with more than one
+image star, both new measurements are added to the one catalog star,
+and a different flat is set, noting that this observation had a
+blended CATALOG.   
+
+\section{Catalog Update and Cleaning}
+
+Occasionally, once a large number of images have been added to the
+photometry database, a set of programs should be run to clean and
+update the CPT files.  This may best be done on CPT files after a
+night's worth of data is incorporated.  These routines define bad
+data, identify the USNO catalog stars, and search for asteroids and
+other junk.  Most of the results from these routines are the addition
+of object flags to the Average data structures (Average.code).  Most
+of these routines process data within a single CPT file at a time.
+
+\subsection{Markstar}
+
+The first of the update programs, {\tt markstar}, identifies bad data
+and flags it.  It makes three types of identifications: bright stars,
+ghost stars, and trails.  In the first case, it searches the HST guide
+star catalog for bright stars within the field of the current CPT
+file.  Three types of pixels are flagged for bright stars.  Any
+measurements within a circular region centered on the star are suspect
+(the ``halo'' of the bright star).  Second, points along the X axis
+are likely to contain flux from the diffraction spikes.  Finally,
+points along the Y axis are likely to have bleeding in addition to the
+diffraction spikes.  Each of these three regions has a different size
+and range which must be defined in the configuration file.  The
+regions are represented by a representative magnitude and a scale
+parameter.  For example, the diameter $d$ of the halo for a star with
+magnitude $m$ is defined as 
+$d = \mbox{BRIGHT\_HALO\_SLOPE} (m - \mbox{BRIGHT\_HALO\_MAG})$.  The X and
+Y axis points are defined by the length of the diffraction spike, with
+an equivalent formula, and the width of the spike.  Since these are
+each independent, there are 8 parameters to define the exclusion
+regions of bright stars.  One of the current drawbacks of this system
+is the reliance on the HST Guide Star photometry.  In the HST Guide
+Star Catalog, only one photometry band is given, so no color
+information is available.  The parameters currently used were defined
+based on a large number of bright stars, with no adjustment for the
+different effective filter system of the Loneos telescope and the HST
+GSC.  Thus, occasionally very red stars will be several magnitudes
+brighter in the real data than reported in the catalog.  As a result,
+large numbers of bad data points in these halos and spikes may be
+missed.  
+
+The second type of bad data flagged by {\tt markstar} are the trails
+from satelite and other space junk.  This portion of the program
+searches for objects which land along a line and which have a high
+linear density.  Parameters may be adjusted to define the width and
+the necessary density or number of points in the line.  Objects in
+lines are also only identified if all observations come from a common
+image.  If an object only has one measurement and it is in a trail,
+the entire Average is flagged to be bad.  However, if an object has
+many measurements and only one is bad, the object is only flagged as
+having some bad data points.  
+
+The third type of bad dat are ghost star images.  The HST GSC is
+searched for stars projected across the telescope optical axis, which
+is defined by the user.  All objects within a region of fixed size is
+marked for ghost stars brighter than a specific cutoff magnitude.
+Similar to the trails, the average is marked as bad only if all
+detections of an object are ghost images.  Otherwise, it is noted that
+some data may be bad.
+
+\subsection{Addusno}
+
+The program {\tt addusno} makes two types of identifications of stars
+with the USNO catalog.  First, it searches for coincidences within a
+small, specified radius.  The choice of this radius is somewhat
+tricky: it is important to catch the association, but also to avoid
+making too many associations.  Unfortunately, astrometric errors in
+the USNO catalog make it necessary to choose a surprisingly large
+radius of 5\asec.  To avoid making double matches (matching the two
+USNO stars to the same photometry database object), only the USNO
+object closest to the object is associated.  There are also a
+substantial number of stars with significant proper motion between the
+USNO epochs and the current date.  It is not unusual to see 8-15\asec\ 
+discrepancy for specific stars.  To catch these objects, any objects
+which do not match the USNO database, but which have more than a
+minimum number of measurements (2 or 3?) are searched for more distant
+USNO companions.  A large, user-specified radius is used for this
+search.  Of course, only USNO stars which are not already matched to
+the database may be candidates for the proper motion match.  This
+stage is suceptible to errors in that a slow-moving solar-system
+object may be associated with a faint USNO star.  For this reason,
+objects flagged as high proper motion stars should be taken with some
+caution.  Of course, during the {\tt addusno} stage, no objects
+already flagged as bad by {\tt markstar} will be matched with USNO
+stars.  
+
+\subsection{Markrock}
+
+Once stars have been identified with the USNO database, it is possible
+to search for asteroid detections.  The program {\tt markrock}
+searches within a specific CPT file for objects which are moving along
+straight lines in (X,Y,t) space.  In order for an object to be found
+by {\tt markrock}, it must have three points, each with only single
+measurements.  The third point must land within a specified distance
+of the line projected from the first two data points.  These
+comparisons are made in the three dimensional space of image position
+and time.  Also, objects are only accepted if they have a speed less
+than a threshold.  If an object is moving too fast, it will make a
+streak on each individual image and will probably be missed anyway.
+Moving objects detected in this way are flagged in the photometry
+database and are also written to a Rock database.  Currently, the Rock
+database just contains ASCII lists of the RA, DEC, Mag, and time for
+each detection.  In fact, the data are stored in pairs of detections,
+with the middle detection saved twice.  This format makes it easy to
+plot lines connecting the points using the connect-the-dots plotting
+style of status/kapa (see below).
+
+One of the current drawbacks of {\tt markrock} is the insistence on
+three observations with only 1 measurement each.  If an object is
+moving too slowly, two of the dectections of the object may be merged
+together.  Enough data is stored in the database to extract these
+individual measurements, so a more sophisticated search is possible.
+It is also currently the case that USNO proper motion stars are
+ignored, but some of these will be asteroid detections which are
+simply too close to a faint USNO stars (it has to be faint because it
+would otherwise be associated with a star in the photometry
+database).  
+
+\begin{figure}
+\psfig{file=flags.eps,width=9cm}
+\caption{\label{flags} 
+Pictoral representation of the Average.code flags.  The lower byte
+value is used for specific definitions of object types.
+}
+\end{figure}
+
+\subsection{Data Flags}
+
+The identifications made by the above routines are noted as a set of
+flags in the Average.code structure entry.  Some of these flags are
+mutually exclusive, so a certain bit may have more than one meaning,
+depending on the value of other bits.  Figure~\ref{flags} shows a
+pictoral representation of the meaning of the different bit fields.
+The uppermost bit (bit 15) determines if the object may be considered
+a ``fixed'' star or something which has no fixed location.  If it is
+not fixed, and this bit is 1, then there are several options.  The
+second uppermost bit (bit 14) will be set if this object is one of the
+three types of bad data flagged by {\tt markstar}.  The lower byte of
+code is used to define the type of bad data: ghost, trail, or bleed.
+Thus, any datapoints determined to be a satelite trail will have a
+code value of 0xc002 (49154 decimal).  If an object is a moving
+object, but not a bad datapoint, it may be identified as a ``rock''
+(an asteroid) by the program {\tt markrock}.  In this case, the flag
+for an asteroid is turned on (bit 13).  Thus anything identified as a
+rock by {\tt markrock} will have a code value of 0xa000.  The lower
+byte of code is not yet defined for asteroids, but could be reserved
+for distinguishing different classes of asteroids (ie, on the basis of
+orbital speeds, and so forth).  Objects which are fixed may have a
+variety of possible flags.  First, an object may be identified with a
+USNO star (bit 14).  It may be found to exhibit variability (bit 13),
+implying that the relative photometry routine should ignore it.  If
+may be a transient object (bit 12).  Note that, while an object
+associated with a USNO object may not be transient, an object which is
+variable may also not be associated with a USNO object.  Thus, we need
+seperate bits for variable vs transient.  Different types of variable
+objects may be represented with different values of the lower byte.
+For example, a Cepheid may have a specific lower byte code of 0x01,
+which an RR Lyra may have a lower byte code of 0x02.  Thus a Cepheid
+associated with the USNO catalog would have a total code value of
+0x6001. Finally, any of these types of non-moving objects may have
+some bad individual measurements (bit 12) or may be found to have a
+significant proper motion (bit 11).
+
+\section{Holding it Together}
+
+The preceeding sections describe the step-by-step analysis and
+incorporation of the data from individual images.  However, the power
+of the Pipeline comes in apply it to large numbers of images.  At
+LONEOS, we are using four Pentinum II computers to analyse the roughly 200
+images that are observed each night.  
+
+It is best to think of the analysis of images occurring on groups of
+images from a given night.  Of the set of processes discussed above,
+those in section \ref{parallel} are performed on individual images
+essentially independently of the other images.  The rest of the steps,
+both the data incorporation ({\tt addstar} and the database cleaning
+routines occur on the entire batch, one image at a time.  Thus, the
+former routines can easily be run in parallel, but the latter routines
+are run in serial to avoid having two programs writing to same part of
+the database at the same time.  In this model, we would process all of
+the images from a night through the parallel stage of the analysis and
+then run the serial stage only after the entire night is finished in
+the parallel stage.  We thus have a natural division of the pipeline
+into two stages.  
+
+The implementation of the two stages involves several programs, some
+of which are specific to the LONEOS problem, and others which are more
+general.  There are two layers of programs which enable batch
+processing of many images and repeated batch processing over many
+nights.  At the highest level, are Perl scripts which decide on a new
+set of data.  At the next level down, these scripts call two main C
+programs which run the images of a given night through the pipeline.  
+A fixed set of files keeps a log of the nights and images that have
+been processed, so the programs may know if a given night has already
+been analysed. 
+
+\subsection{lastnight}
+
+The Perl script {\tt lastnight} looks at the disks used by the
+observers to write the images from a given night.  Images are written
+to a directory called /pallas/d[1-6]/NNNNNN where NNNNNN is an
+abbreviation for the current night's date in the form YYMMDD (ie,
+990223).  All of the images are stored in this directory with names
+yyyyMMDDxxxxb.fits where yyyy is the full year, MM is month, DD is
+date, and xxxx is a sequence number.  The 'b' refers to the 'b' CCD,
+and the .fits extension is required.  The script {\tt lastnight} is
+called by a cron job scheduled for 7am on {\tt hebe.lowell.edu}.  The
+script searches the disks /pallas/d[1-6] for a directory of the right
+form (basically any directory beginning with a number).  By default,
+the program demands that the directory have a name of today's date,
+but with the flag -any, it will accept any directory.  It then checks
+to see if this directory have been already included in the
+'processed.log' file.  If not, it lists all files with the right
+ending (*b.fits) and places these names in a file.  It also writes the
+name of the directory (along with some other data) in a file
+'extracted.log'.  When it has successfully ended and identified some
+data, it calls the next script, {\tt stage1} and then quits.  
+
+\subsection{slurp}
+
+An alternative to {\tt lastnight} is the Perl script {\tt slurp},
+which looks for data on the tape archive.  This script looks at the
+tape.log file and compares it to the file processed.log.  It tries to
+identify nights listed in the tape.log which have not been included in
+the processed.log.  If it finds any, it tries to download as much of
+the data as will fit on the disk /pallas/d1.  This script is called
+from within the {\tt stage1} script and is invoked if {\tt stage1} is
+run without any data already in extracted.log.  
+
+\subsection{stage1}
+
+The Perl script {\tt stage1} takes the image list produced by {\tt
+lastnight} or {\tt slurp} and passes the list to the controller
+program {\tt control1} which performs the parallel analysis.  The
+script has a few features to decide which files have been analysed
+through the pipeline and to what extent.  If {\tt stage1} is called,
+it should be able to figure out 1) if there is data ready to be
+analysed, 2) if the data has been partially analysed, 3) which data
+needs to be run through which part of the pipeline, and so forth.
+These features are most useful if the analysis crashes in the middle
+or needs to be restarted.  The {\tt stage1} script is meant to be run
+without any arguments and it will figure out what needs to be done.
+The one possible argument is the -once flag.  This flag tells {\tt
+stage1} to analyse the data it finds and quit when it finishes, and
+not call another instance of itself.  The script writes a log file
+called \$scriptdir/stage1.NN.log where NN is a number in sequence
+between all runs of {\tt stage1}.  A file stage1.count keeps track of
+which number NN we are on.  When {\tt stage1} has finished the
+analysis of a night's data, it writes the date in processed.log to
+keep {\tt slurp} and {\tt lastnight} from re-running a night.
+
+\subsection{stage2}
+The serial stage processes are run by the Perl scrip {\tt stage2}.
+Normally, this script is always running.  It waits for the name of a
+night to be added to the processed.log file.  Once if finds a new name
+in this file, it looks for the appropriate images in the file
+YYMMDD.addlist.  It then submits the list to the second controlling
+program {\tt control2}, which runs the images through {\tt addstar}.
+Images which are successfully run through addstar have their *bf.fits
+(flattened image) and *.obj (dophot output) files deleted.  When the
+entire night is done, the rest of the *.obj and *bf.fits images are
+deleted by {\tt stage2}, the directory with the *.cmp and *.log files
+is tared and gzipped into the file YYMMNN.tgz.  The directory is then
+deleted.  Finally, {\tt stage2} calls the script {\tt cleaning.pl}
+which runs the cleanup programs ({\tt markstar - nrphot}) on the
+database.  After a successful run, {\tt stage2} will automatically
+respawn a new copy that waits until more data arrives.
+
+\subsection{control1 / control2}
+These two C-programs perform the tasks of farming the images out to
+the different machines for analysis.  The two programs are essentially
+identical, but {\tt control1} is allowed to use all machines and {\tt
+control2} can only use one (hebe.lowell.edu, which has the database
+local to it, mostly).  The two programs also run a different set of
+program.  These controller programs start off by executing remote
+shells (using ssh) on a list of machines.  These shells are then used
+to execute the remote commands and are kept open the entire time the
+process runs.  They maintain a list of images in a set of queues.  A
+set of rules defines the order in which each image travels through the
+queues.  Each queue is associated with a single process (flatten,
+astrometry, etc).  Images which successfully run through a queue are
+sent on to the defined 'next' queue, while images which fail are
+instead sent to the defined 'fail' queue.  In most cases, the 'fail'
+queue is a process which marks the image as bad and write the name in
+a file, and then puts the image in the 'done' queue.  However, it is
+possible for the 'fail' queue to be another attempt, such as in the
+case of astrometry.  In this example, images which fail the default
+astrometry are run through a second queue which tries again with the
+-loneos flag set (this flag makes the assumption that the header
+information about the LONEOS region number for the image is correct,
+not the RA/DEC information).
+
+The connections on the remote machines are handled as child processes
+with communication through the stdin and stdout/stderr pipes.
+Messages can be sent back and forth though these pipes, and messages
+which are received from a process associated with an image are written
+to a log file with the name imagename.log (where imagename is the root
+name of the image).  The only required messages from the program are
+messages saying ``SUCCESS'' or ``ERROR''.  The programs therefore all
+end with either of these words.  The programs are started within the
+controller as a command to the shell followed by and echo ``PROCESS
+DONE''.  If the controller sees the message ``PROCESS DONE'' without
+either ``SUCCESS'' or ``FAILURE'' (after waiting an appropriately long
+time), it assumes the program crashed.  Currently, no timeout is
+available for the programs.  The flat-field process is run in mana and
+is a slightly special case.  We avoid re-loading the same flat many
+times by starting a mana process once and running the flatten
+procedures as mana function calls.  The images which are analysed
+(with an indicator of success or failure at each stage) are written to
+a file named YYMMDD.addlist by the {\tt control1} and YYMMDD.outlist
+by {\tt control2}.
+
+\section{Lock files}
+
+A variety of locking mechanisms are used to avoid overwriting the
+database or running more than one version of the controlling
+programs.  there is a perl program, locks, which allows the user to
+set or check the state of the different locks. 
+
+\section{File locations}
+
+\begin{verbatim}
+database: /hebe/d27/database (also in /metis/d27/database as linked directories).
+ lock files also go in this directory
+workspace: /irene/d11/workspace - temporary storage of result files
+dumpspace: /pallas/d1 - disk to store data dumped from the archive by slurp.
+scriptdir: /metis/d11/logs - all log files
+\end{verbatim}
+
+\section{Visualization -- Status}
+
+Visualization of the data in the photometry database can best be
+performed with the program {\tt status}.  This is a command-line
+driven program with a math and macro language which makes it easy to
+perform complex tasks.  
+
+First, a few notes about the user interface.  The interface has an
+interaction similar to {\tt tcsh}.  The arrows allow editing of
+previous commands.  You can also use emacs-like commands such as
+cntl-a to reach the beginning of the line and cntl-e to reach the end.
+There is command and file completion: if you type part of a command
+(as the first thing on a line) and then type tab, it will fill in as
+much as possible, until the word is not unique.  Typing tab twice at
+that point will list the possible endings.  For any but the first word
+on a line, the same thing will happen for the files in the current
+directory.  It is also possible to type just a fraction of a command,
+as long as it is unique.  An ambiguous command will list the possible
+alternatives.  For example:
+\begin{verbatim}
+status: c
+ambiguous command: c ( catalog cgrid clear create cursor )
+\end{verbatim}
+
+The shell is essentially an interpretive programming language.
+Variables are set as follows:
+\begin{verbatim}
+status: $fred = 10
+\end{verbatim}
+Any expression within curly brackets \{\} is assumed
+to be an arithmetical expression and is evaluated before the line is
+executed.  For example:
+\begin{verbatim}
+echo {$fred*dcos(45)}
+\end{verbatim}
+would give the response 7.07107.  There are math functions cos, sin,
+and tan, which operate on radian expressions, and also dcos, dsin,
+dtan, which operate on degree expressions.  There are also the
+equivalent inverse functions: eg., asin and dasin return radians and
+degrees, respectively.  The help section on Math defines all of the
+available math functions.  
+
+\subsection{Miscellaneous Commands}
+\begin{verbatim}
+!                         -- system call
+?                         -- list commands 
+??                        -- list variables 
+echo                      -- type this line 
+exec                      -- system call
+exit                      -- exit program 
+help                      -- get help on a function 
+output                    -- redirect output to file
+quit                      -- exit program 
+scan                      -- scan line from keyboard or file to variable 
+wait                      -- wait until return is typed
+which                     -- show command 
+\end{verbatim}
+Most of these are self-explanatory.  The command ?? prints the system
+variables.  The {\tt help} command will provide help on a single
+command or, without any arguments, will list all available help
+files (this includes general help not associated with a specific
+command).  
+
+\subsection{Shell Programing}
+\begin{verbatim}
+break                     -- escape from function 
+for                       -- loops 
+if                        -- logical cases 
+input                     -- read command lines from a file 
+macro                     -- deal with the macros 
+\end{verbatim}
+
+There are several options for programming in {\tt status}.  First, a
+file which contains a series of commands can be executed with {\tt
+  input (filename)}.  It is also possible to define macros which will
+behave much like regular commands.  A macro is defined by typing {\tt
+  macro name} or {\tt macro create name} followed by the commands.
+Arguments to the macro are assigned to the variables \$1 .. \$N and
+the number of arguments is given by \$0.  Macros may be defined in
+{\tt input} files, and in fact when {\tt status} is started, it loads
+the file {\tt \~/.statusrc} which may contain default macros.  Simple
+loops and if statements can be performed, and are quite useful for
+complex macros.  
+
+``If'' statements are similar in syntax to C if statements, but only
+the following logical operators are available: $>$, $<$, $=$, !, $|$,
+and \&.  Notice that (currently) there is no $>=$ or $<=$ symbol.  The
+operator ! means ``not equal to'', but cannot be used to negate a
+logical value.  The operators $|$ and \& have the meaning of ``or'' and
+``and'' respectively.  Math expresions in the if statement must be
+contained in curly braces, as elsewhere.  Variables with string values
+may use the logical $=$ operator to test if two strings are the same.
+``For'' loops are quite simplistic.  The form is:
+\begin{verbatim}
+for var first last delta
+ (commands)
+end
+\end{verbatim}
+The value of {\tt \$var} will start at the value {\tt first} and increment by
+{\tt delta} after each loop.  The loop will stop after {\tt \$var} is greater
+than {\tt stop}.  The value {\tt delta} is optional, with 1 assumed.
+The value of {\tt \$var} may be changed during the loop, and if set
+beyong the value of {\tt last} will end the loop early.  
+
+\subsection{Vector Plotting}
+
+\begin{verbatim}
+box                       -- draw a box on the plot
+clear                     -- erase plot
+create                    -- create a new vector
+cursor                    -- get coords from cursor
+grid                      -- plot cartesian grid
+hist                      -- create histogram from a vector
+labels                    -- define labels for plot
+limits                    -- define plot limits
+plot                      -- plot a pair of vectors
+print                     -- write vectors to file
+ps                        -- define labels for plot
+set                       -- vector math
+style                     -- set the style for graph plots
+vectors                   -- list vectors
+zplot                     -- plot scaled points 
+\end{verbatim}
+
+In addition to scalar variables, {\tt status} can manipulate and
+display 1-D vector variables.  Many of the commands which extract data
+from the photometry database place the data in vectors as well as
+plotting them.  A vector can also be created based on a number
+sequence with the command {\tt create name Nelements start delta}.
+The resulting vector has $Nelements$ entries, starting at a value of
+$start$ and running until $start + delta*Nelements$.  If $delta$ is
+0.0, all elements will have the value of $start$.  A histogram of a vector
+may be made with the command {\tt hist}, which creates a new vector
+containing the histogram of the first vector.  The data range and bin
+size of the histogram are defined in same way as with create.  This
+makes it easy to create the index vector that goes with a histogram
+vector:  
+\begin{verbatim}
+hist y Ny 1 100 0.1
+create dx 1 100 0.1
+\end{verbatim}
+The above will create a histogram of y in Ny and the index in dx.
+Plotting this with {\tt plot dx Ny} will show the histogram.
+
+Vector math is performed with a command of the form {\tt set new =
+  (expression)}.  The expression is some math function employing
+vectors and scalars.  A complete listing of the math operators
+available in {\tt set} can be found in the help for {\tt set}.
+
+Once vectors are defined, they may be plotted.  A pair of vectors can
+be plotted against each other if they have the same number of entries.
+The plotting is performed on the graphics window, Kapa.  There are
+actually several graphics windows available to {\tt status}, any of
+which may be used to plot at any time.  Some of the more complex
+operations default to either graphics window 0 or 1, depending on the
+context.  Except for those functions with a pre-defined window, all
+plotting functions apply to the current graphics window unless an
+option {\tt -n N} is given to specify a different window.  The
+plotting style is determined by the command {\tt style} which can set
+the line width, the line type (solid, dashed, dotted, etc), the point
+type (box, cross, etc), the point size, the color, and whether a pair
+of vectors is plotted as a sequence of points, a set of connected
+lines, or a histogram.  Some functions which make plots use their own
+styles, as discussed below.  The function {\tt limits} lets the user
+set the range of the plot axes, or check the current setting.  The
+command {\tt plot} will plot a pair of vectors on the current graphics
+window using the current plotting style for that window.  The command
+{\tt zplot} will plot a pair of vectors with the point size scaled by
+a third vector, with maximum and minimum point sizes representing
+specified values.  The {\tt cursor} command goes the other way: this
+command puts the Kapa window in cursor mode and waits for input from
+Kapa.  The user can then type any alphanumeric key on the graphics
+windows and will be told both the pointer location (in the graphics
+coordinates) and will have the coordinates stored in {\tt status}
+variables.  For example, by typing ``1'' in the sky display window,
+the RA and DEC of the pointer are stored in the variables {\tt \$R1}
+and {\tt \$D1}.  This command can be used to let the user define
+locations or regions of interest on the Kapa window. (Future addition:
+{\tt button}, which does the same with the mouse buttons).  
+
+\subsection{Database Functions}
+
+\begin{verbatim}
+gcat                        -- get catalog at location
+gimages                     -- get images at location
+gstar                       -- get star statistics
+extract                     -- extract average vectors from catalogs
+mextract                    -- extract measurement vectors from catalogs
+imstats                    -- plot image statistics
+imextract                   -- extract image vectors from database
+lcat                        -- list catalogs in display region
+cmatch                      -- match two catalogs
+\end{verbatim}
+
+There are a variety of other commands which directly refer to the
+photometry database.  Some of these functions extract data of various
+types from the database, others perform more complex plotting
+operations.  The commands listed above are those which simply extract
+data from the database.  The first three list information relevant to
+a specific RA, DEC location on the sky: {\tt gcat (RA) (DEC)} lists
+the catalog at the specified location and places the name in the
+variable {\tt \$CATNAME}, {\tt gimages (RA) (DEC)} lists all images
+which overlap the specified location, , {\tt gstars (RA) (DEC)
+  (RADIUS)} lists data about the stars within a specified radius of
+the specified location (all numbers above are given in decimal
+degrees).  Similarly, {\tt lcat} lists the catalogs in the region.
+Imstats lists statistics about each image
+
+The next three commands extract a specific piece of information from
+the photometry database and places it in a vector.  First, {\tt
+  extract} will extract average values for each star and place it in a
+vector.  Next, {\tt mextract} will extract measurement values for each
+star and place it in a vector: as a result a single star may have
+multiple entries in the measurement vectors.  Finally, {\tt imextract}
+will extract image statistics into vectors (not yet implemented).
+
+
+\begin{verbatim}
+catalog                    -- plot catalog stars
+cgrid                      -- plot sky coordinate grid
+cplot                      -- plot vectors in sky coordinates
+czplot                     -- plot scaled vectors in sky coordinates
+images                     -- plot image boxes
+imdense                    -- image density plot
+lcurve                     -- plot lightcurve for a star
+pcat                       -- plot catalog boundaries
+region                     -- define sky region for plot
+resid                      -- plot residuals
+simage                     -- plot stars in an image
+\end{verbatim}
+
+There are two types of database plotting functions: those that display
+or refer to the spatial charateristics of the data and those that
+refer to other types of charatersitics, such as the time domain.  The
+graphics window 0 is reserved for all plots of objects on the sky.
+The command {\tt region} defines the current sky coordinates for plots
+in graphic window 0.  The command {\tt pcat} plots the outline of all
+photometry database files which are within the currently defined
+region (and by default, only those with data).  {\tt images} plots the
+outline of the images in the image database, while {\tt imdense} shows
+the number of images at a location by randomly spacing dots within the
+boundary of the images.  The command {\tt cgrid}
+draws a grid in celestial coordinates on the for the current region.
+
+The most complex, but also one of the most useful command is {\tt
+  catalog}, which plots the positions of stars in the photometry
+database (and others) on the sky.  There are many options to this
+command.  One set allows the user to plot stars from the photometry
+database (the default), from the HST GSC, or from an ASCII text file
+with RA, DEC, and Mag in specified columns.  If the ASCII file has a
+fixed number of bytes per line, the data can be more quickly loaded.
+The size of the points may be scaled by the star magnitude, by the
+number of observations of the star, or by the number of missing
+datapoints for the star.  In addition, points may be plotted only if
+they land in specified magnitude ranges, or with specified numbers of
+measurements, or missed measurements.  Also, objects may be plotted
+only if they have a specified Average.code, so that only asteroids or
+only perfect stars may be plotted.  The plotted vectors may be saved,
+if desired, and the source catalog epoch may be specified as different
+from J2000 (only valid for ASCII data).
+
+Several other commands relate to non-spatial charateristics of images
+and stars.  {\tt lcurve} will plot a light curve for all stars within
+some radius of a point.  {\tt resid} plots the photometry residuals
+for a particular region file.  
+
+\section{Some Examples}
+
+\begin{figure}
+\psfig{file=allsky.ps,width=16cm}
+\caption{\label{allsky} 
+Map of the entire sky, and images added to database.
+}
+\end{figure}
+
+Fig.~\ref{allsky} shows a map of the entire sky, and the location
+of the images currently in the database.  This picture was made with
+the following commands: (output is not shown) \\
+\begin{verbatim}
+status: region 0 0 90 gls
+status: cgrid
+status: style -lw 2 -c red 
+status: images
+status: ps
+\end{verbatim}
+In this example, on the graphics window, the image boxes are shown in
+red.  The user now has the possiblitiy of using the cursor command to
+narrow in on a specific region, and so forth.  
+
+\begin{figure}
+\psfig{file=catalog.ps,width=9cm}
+\caption{\label{catalog} 
+Comparison between HST GSC and photometry database astrometry. 
+}
+\end{figure}
+
+Fig.~\ref{catalog} shows an example comparison of the photometry
+database star positions and the HST Guide Star Catalog star
+positions.  The crosses are from the photometry database while the
+boxes are from the HST GSC.  The size of both points is a function of
+brightness.  This plot was made with the following commands (starting
+from the previous image):
+\begin{verbatim}
+status: cursor  (typed 1 on region of interest)
+1 137.097858 22.698305
+q 137.097858 22.698305
+status: region $R1 $D1 0.5 TAN
+status: cgrid
+status: box
+status: style -pt 0 
+status: gcat $R1 $D1 
+  0 n2230/1951.cpt *
+status: catalog n2230/1951.cpt -m 12 18
+status: style -pt 2
+status: catalog n2230/1951.cpt -m 12 18 -g
+\end{verbatim}
+
+\begin{figure}
+\psfig{file=lightcurve.ps,width=9cm}
+\caption{\label{lightcurve} 
+Lightcurve for several image stars.
+}
+\end{figure}
+
+Fig.~\ref{lightcurve} shows an example lightcurve from three stars in
+the above field.  The x axis shows the time in seconds, which the y
+axis shows the star magnitudes.  This plot was made with the following commands (starting
+from the previous image):
+{\small
+\begin{verbatim}
+status: cursor
+1 137.062562 22.791860
+q 137.062562 22.791860
+status: lcurve $R1 $D1 0.01 -l
+status: box
+status: gstar $R1 $D1 0.01
+read 11318 stars from catalog file /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt (22462 total measurements)
+508 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.068619 22.785400 18.438000  1 (2)  1.000000 1.000000
+498 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.062820 22.792747 12.882000  3 (0)  1.000000 1.000000
+501 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.064499 22.800817 15.480000  3 (0)  1.000000 1.000000
+\end{verbatim}}
+The last lines show the database information on the three stars.  
+
+\section{Software Distribution}
+
+\section{Programming Details}
+
+\section {Comparison with USNO catalog}
+
+I have made several comparisons between the USNO catalog and results
+from running images from Loneos through the photometry pipeline.  In
+general, there is a good agreement between the astrometry of the two
+datasets.  There are specfic areas where the two disagree, however.
+First, as discussed above, the USNO star positions may be
+significantly different from the observed star positions simply
+because of proper motion.  The first picure in the ``Comparisons
+between Loneos + USNO'' pages shows several stars with significant
+proper motion.  These are currently being flagged in the photometry
+database as discussed.  Other differences evident in this first
+picture include the classification of bright stars and the splitting
+of faint and bright stars.  In the upper right of the image, two
+bright stars are visible, one of which is actually a double.  The USNO
+catalog does a good job of detecting both, but it also detects and
+includes as stars several diffraction spike points.  The HST GSC only
+detected a single point and did not split the star at all.  The Loneos
+data in our pipeline did not detect the star at all due to saturation.
+A star in the upper left corner shows the ability of {\tt dophot} in
+the Loneos pipeline to split double stars.  This star is, on close
+inspection, clearly a double.  The USNO catalog only detects one.  The
+Pipeline not only splits the two stars, but it also makes the correct
+cross-identification of the stars.  
+
+The second set of pictures shows the ability of the Loneos pipeline to
+deal with small galaxies.  There are two small galaxies in this field,
+both of which are broken into 4 or 5 objects by the USNO catalog, but
+maintained as single objects in the Loneos pipeline.  In another
+example (not shown) a bright star within the disk of a small galaxies
+was clearly split from the galaxy by the pipeline (and also by USNO).
+
+\appendix
+\section{Parameter file params.txt}
+\begin{verbatim}
+# Configuration file for Loneos analysis pipeline
+
+# important files and directories
+GSCFILE                 /host/pikake/d1/gene/gsc/GSCregions.tbl
+GSC_DIR                 /host/pikake/d1/gene/gsc
+CATDIR                  /host/radon/rad3/gene/photcat2
+IMAGE_CATALOG           /host/radon/rad3/gene/photcat2/Images.dat
+IMAGE_CATALOG_TEMPLATE  /host/radon/rad3/gene/photcat2/template.cat
+CATALOG_TEMPLATE        /host/radon/rad3/gene/photcat2/template.cat
+ROCK_CATALOG            /host/radon/rad3/gene/photcat2/Rocks.dat
+USNO_CDROM              /host/tycho/mnt/md0/kevin/zones
+LONEOS_REGIONS          /host/pikake/h1/gene/loneos3/regions.map
+
+# parameters for "fstat"
+# instrumental mag zero point
+ZERO_PT                 24.5
+DOPHOT_CHAR_LINE        129
+DOPHOT_TYPE_FIELD       5
+DOPHOT_AP_FIELD         91
+DOPHOT_PSF_FIELD        52
+MIN_SN_FSTAT            6.0
+
+# parameters for "gastro"
+DEFAULT_RADIUS   32.0
+MINIMUM_RADIUS   1.5
+MIN_ERROR        0.6
+MIN_PRECISE      0.12
+CCD_PC1_1        1
+CCD_PC2_2        -1    # for loneos
+CCD_PC1_2        0
+CCD_PC2_1        0
+ASEC_PIX         2.82
+NFIELD           3.0
+MMIN             6.0
+ROT_ZERO         0
+dROT             1.0
+NROT             2
+POLAR_AXIS_RA    -90.0
+POLAR_AXIS_DEC   89.88
+RA_OFFSET        -90.0
+DEC_OFFSET        0.0
+
+# parameters for "addstar"
+# airmass extinction coefficient (in mag / airmass)
+NSIGMA                  3.0
+ALPHA                   0.1
+XOVERSCAN               60
+YOVERSCAN               50
+
+# parameters for "controller"
+IN_DIR                  /host/pikake/h1/gene
+OUT_DIR                 /host/pikake/h1/gene/loneos4/
+DOPHOT_PARAMS           /host/pikake/h1/gene/src/ohana/config/default_parameters
+FLATTEN_SCRIPT          /host/pikake/h1/gene/src/ohana/config/test.pro
+NEW_IMAGES              images.dat
+USERNAME                gene
+PASSWORD                gene
+
+# here we list all available machines
+NMACHINES               2
+MACHINE0                pikake.astro.washington.edu
+MACHINE1                mildew.astro.washington.edu
+
+# here we define which machines which are always free
+fMACHINE0               1
+fMACHINE1               0
+
+# here we define the machine which runs the database 
+LOCAL_MACHINE           0
+
+# parameters for "status"
+TIME_REFERENCE          90/01/01 00:00:00
+
+# parameters for "nrphot"
+# make this one small to boost change of getting an early region 
+TAU                     3.0             
+SCATTER_LIM             15.0
+MAG_LIM                 17.0
+IMAGE_SCATTER           0.075
+NIMAGE_SCATTER          1.5
+STAR_SCATTER            0.05
+
+### parameters for "markstar"
+SEARCH_RADIUS           360   # region for initial trail hunt, in arcsec 
+TRAIL_WIDTH             5.0   # expected trail width, in arcsec
+NANGLE_BINS             180   # Number of angular bins in 180 degrees
+NPTSINLINE              5     # minimum points needed for trail
+MIN_DENSITY             0.025 # minimum linear density in star/arcsec
+SPACE_SIGMA             10.0  # how much denser than average for trail?
+# parameters defining bright star exclusion regions
+BRIGHT_XTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_XTRAIL_MAG         9.5 # faintest sat. star
+BRIGHT_XTRAIL_SLOPE     -80.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_YTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_YTRAIL_MAG        11.0 # faintest sat. star
+BRIGHT_YTRAIL_SLOPE    -400.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_HALO_MAG           8.5 # faintest sat. star
+BRIGHT_HALO_SLOPE       -28.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+# parameters which define the ghosts
+GHOST_MAG               7.5
+GHOST_RADIUS            200   # in arcsec
+OPTICAL_AXIS1           2154.0
+OPTICAL_AXIS2           2193.0
+
+# parameters for "addusno"
+USNO_RADIUS             5.0   # in arcsec
+USNO_PROPER             20.0   # in arcsec
+USNO_RED                1000  # code for USNO Red data
+USNO_BLUE               1001  # code for USNO Blue data
+# /mnt/cdrom
+
+# parameters for "markrock"
+ROCK_RADIUS             2.0   # in arcsec
+ROCK_MAX_RADIUS         20.0  # in arcsec
+ROCK_MAX_SPEED          0.1   # in arcsec / sec
+\end{verbatim}
+
+\end{document}
Index: /tags/start/Ohana/doc/pipeline/pipeline3.tex
===================================================================
--- /tags/start/Ohana/doc/pipeline/pipeline3.tex	(revision 12606)
+++ /tags/start/Ohana/doc/pipeline/pipeline3.tex	(revision 12606)
@@ -0,0 +1,1463 @@
+%\documentstyle[astro,psfig]{article}
+\documentclass{article}
+\usepackage{psfig}
+\usepackage{astro}
+\usepackage{times}
+\GoodMargins
+\newcommand{\note}[1]{({\bf #1})}
+\title{Variability Pipeline}
+\author{Eugene Magnier}
+\begin{document}
+\maketitle
+
+\section{Overview}
+
+The Loneos Pipeline provides automated reduction of images, including
+photometry and astrometry, with the final data stored in a photometry
+database organized by star position on the sky.
+
+Fig.~\ref{pipeline} shows a schematic of the analysis pipeline.
+Images are written to the disk from the camera by the software which
+runs it, {\tt astrocam}.  The resulting images are FITS files (which
+may be arbitrarily sized) and have header keyword parameters RA and
+DEC specifying rough celestial coordinates.  Images are first analyzed
+by {\tt dophot}, which produces instrumental photometry and pixel
+coordinate positions for stars and other objects in the images,
+writing files with a particular format, called OBJ files in this
+discussion.  The results from {\tt dophot} are cleaned up by a program
+called {\tt fstat} which merges the header information from the image
+with the most relevant parts of the OBJ file, creating a new file with
+the CMP format.  Astrometry is performed on the CMP file with the
+program {\tt gastro}.  {\tt Gastro} makes a comparison with an
+astrometric reference database and only changes CMP header keywords as
+a result.  Finally, the processed image CMP file is added to the
+photometry database with the program {\tt addstar}.  The photometry
+database is maintained in a large number of files (CPT files), each
+representing a small region of sky.  There is no relationship between
+the image locations and the boundaries of CPT file.  All of these
+processes occur on individual image, and would typically be performed
+while the observations are occuring, or during the day following, but
+may be performed at any time to add new or archived data to the
+database.
+
+Once large batches of images have been processed, a series of programs
+should be run to clean up the photometry database.  Typically, these
+routines would be run at the end of a night on all of the CPT files to
+which new data were added.  First, {\tt markstar} identifies bad data
+(the trails of satelites, the bleeding columns from stars, ghost
+images), and flags these data points appropriately.  Second, {\tt
+  addusno} matches the catalog stars with stars from the USNO database
+and adds the USNO magnitudes to the photometry database.  Next, {\tt
+  markrock} searches for likely asteroids in the CPT file, marks them,
+and writes the asteroid observations to an asteroid database.  It also
+notes measurements which are likely to be noise and cosmic rays.
+Finally, {\tt nrphot} determines relative photometric calibrations for
+observations in a set of CPT files.  
+
+With the exception of {\tt dophot}, all of the programs in the
+pipeline refer to a single configuration file to determine the large
+number of parameters necessary in the process.  The default parameter
+file is hardwired into the programs, but an alternate configuration
+file may be specified with the environment variable {\tt
+  PIPE\_CONFIG}.  This option makes independent processing of multiple
+data sources trivial.  For example, if the pipeline is to be used for
+both Loneos and SDSS image analysis and display, there could be two
+configuration files (eg, {\tt loneos.txt} and {\tt sdss.txt}), one for
+each data source.  Several important parameters would be different
+between these two, for example, the initial plate scale guess for the
+astrometry routine, or the parameters which define the rough chip
+orientation.  This scheme allows for analysis of different types of
+images, with a common destination photometry database, or for
+independent photometry databases.
+
+\begin{figure}
+\psfig{file=schematic.eps,width=9cm}
+\caption{\label{pipeline} 
+Schematic of the photometry pipeline.  Rectangles represent programs,
+while ovals represent data products.  Arrows show the direction of
+travel of information.  The flatten routine is a filter whose position
+may change as the pipeline matures.
+}
+\end{figure}
+
+Data from different sources can be processed by the pipeline and
+stored in the same photometry database, since all photometry is tagged
+with a source ID in the database (as are the images in the image
+database).  This allows us to include, for example, the USNO catalog
+magnitude measurements (or a subset) in the photometry database for a
+quick comparion.  Different sources may be considered different
+filters, so color-color and color-magnitude diagrams could be
+extracted by specifying choices for source catalog.  Currently each
+object has a single primary photometric system, and individual
+observations may be combined to determine that average (eg, if they
+are different photometry sources with roughly the filter bandpass) or
+they may be ignored when calculating relative magnitudes (eg, the USNO
+magnitudes would be ignored).  This may be expanded upon by defining
+multiple average magnitudes and allowing different measurements to
+contribute only to the appropriate average.  The determination of the
+photometry code for a particular image is currently not well defined.
+There are several points in the analysis where the user (or the
+controlling program) may specify the photometry source.  A table
+should be kept in the photometry catalog to define the various
+photometry codes.  
+
+\section{Image Analysis Pipeline}
+\label{parallel}
+\subsection{Photometry -- Dophot}
+
+Photometry is performed using a varient of {\tt Dophot}.  The version
+of dophot is based on Dophot 2.0, but it has been adapted to
+streamline processing of many files.  First, with this version of
+dophot, any FITS format data is safely read in.  Instead of compiling
+to a fixed maximum size, only the memory needed to contain the image
+matrix is allocated.  The image is also converted to REAL*32 from
+whatever BITPIX for processing.  Finally, only a single, complete
+parameter file is loaded by dophot.  There is no option for a modified
+and a default parameter file.  The parameter file to be used is
+defined, along with the input image and the output object list on the
+command line when the program is run: \\
+{\tt dophot image.fits image.obj parameter\_file} \\
+To achive this, the code from dophot was wrapped within a C program
+which interprets the command line arguments, allocates the necessary
+memory, and reads in the image.  The rest of the processing is
+performed by dophot in the standad manner.  Notice that we use a
+consistent naming convention through the pipeline reductions.  The
+image is called {\tt foo.fits}, while the resulting dophot-produced
+photometry list is called {\tt foo.obj}.  
+
+\subsection{Cleanup -- fstat}
+
+After an image is processed by dophot, the object file ({\tt foo.obj})
+is converted to a more-compact, more-complete file called a CMP file,
+with a name of the form ({\tt foo.cmp}).  This conversion is done with
+the program {\tt fstat}.  The CMP file consists of the FITS header
+from the original image ({\tt foo.fits}), with some additional
+keywords to be used at later stages in the analysis, followed by an
+ASCII list of the interesting data from ({\tt foo.obj}).  In this
+list, types 6 and 8 are excluded, and only the following values are
+kept:
+\begin{verbatim}
+X       Y     Mag   dMag t log(sky) 
+1342.0  106.1 14.166 000 4 3.2
+\end{verbatim}
+Objects with a signal-to-noise ratio lower than a specified cutoff
+({\tt MIN\_SN\_FSTAT}) are also excluded.  Some general information
+about the image is derived by {\tt fstat} (FWHM, saturation and
+completeness limits, number of each dophot type) and stored as
+keywords in the header.  The photometry source must be specified at
+this stage as one of the command line arguments, though the value used
+may be overridden in one of the stages belowe.  The resulting file can
+now stand on its own without reference to the original image.  The
+keywords used by {\tt fstat} include the minimum signal to noise, a
+rough guess at the zero point ({\tt ZERO\_PT}), and four numbers
+defining the format of the {\tt dophot} OBJ file.
+
+\subsection{Astrometry -- gastro}
+
+Astrometry is performed automatically by the program {\tt gastro}.
+{\tt gastro} loads a CMP file and determines an initial guess for the
+center coordinates (based on the RA and DEC header keywords).  The
+program also uses the configuration information about the plate scale
+and rough orientation of the image to get a close to the final
+solution.  Also, the true sky position of the telescope pole may be
+defined to allow astrometry on images taken close to the pole.  The
+comparison is made with the astrometric catalog, which may be the HST
+Guide Star Catalog, or it may be any source if the data is placed in
+the correct format.
+
+\section{The Photometry Database}
+
+\subsection{Photometry File Format}
+The photometry database consists of a large number of photometry files
+representing sections of the sky and a file containing information on
+the images incorporated in the database.  These files are called
+alternatively ``region files'' or CPT files (because they have the
+extension {\tt .cpt}).  The photometry files are sorted by Declination
+into different directories, each consisting of a band 7.5\degree\ 
+wide.  These directories have names like n0730, representing the band
+starting at a Declination of +07:30.  The image database (Images.dat)
+is stored in the upper level directory of this directory tree.  In
+fact, the locations of the Images.dat file, the photometry database,
+and such are all flexible and may be changed by altering the
+configuration file.
+
+The name and location of each sky region comes from the Hubble Space
+Telescope Guide Star Catalog.  There is a file, GSCregions.tbl, which
+can be used to find the region file appropriate for any location on
+the sky.  A number of routines exist to make such a query.  
+
+Each photometry file in the photometry database contains all
+observations and all average values for all stars observed within the
+appropriate region on the sky.  The identity of stars is essentially
+determined by the RA and DEC coordinates.  In very crowded regions,
+the end user may need to double check that a neighboring star is not
+contaminating individual detections (see the discusion on {\tt
+  addstar} below).
+
+The photometry files are stored in a binary format, both to reduce the
+volume and to speed access.  As a result, the interpretation of the
+data is machine dependent: little endian machines need to swap the
+data intelligently.  Fortunately, this operation is taken care of
+appropriately, if the programs are compiled with the BYTESWAP option
+set as needed, which is automatically set by the Makefile in the case
+of a Linux machine.  For reference, Suns, SGI, and HP are all big
+endian, while PCs and DECs are little endian.  The automatic
+conversion takes place by using the funcions {\tt Fread} and {\tt Fwrite}
+to substitute for the standard C library {\tt fread} and {\tt fwrite}
+functions.  {\tt Fread} and {\tt Fwrite} are told the datatype being read,
+and they know the layout of the bytes for a particular datatype.
+Anytime the definitions of the relevant structures (see below) are
+changed, {\tt Fread} and {\tt Fwrite} must be updated.  Fortunately, there
+is only one file ({\tt Fread.c}), and it has a single byteswapping
+section, making it easy to adjust the code appropriately.
+
+The format of a single photometry database file consists four
+sections:  
+\begin{itemize}
+\item {\bf header} -- this is a standard FITS header with room for comments
+  about the file or whatever.  Since the rest of the file is not a
+  standard FITS file, the SIMPLE keyword is set to False.  The three
+  necessary keywords are NSTARS, NMEAS, and NMISS, which define the
+  sizes of the next three sections.
+\item {\bf average} -- this section contains all average measurement
+  quantities for each star in the file.  There are NSTARS entries, and
+  each entry is the data from a structure of type Average (defined in
+  loneos.h, and discussed in more detail below).  Thus, the total size
+  in bytes of this section can be found by NSTARS*sizeof(Average).
+\item {\bf measure} -- this section contains the individual
+  measurements for each star in the database.  There are NMEAS
+  entries, and like the average section, each entry is a single
+  structure, in this case of type Measure (in loneos.h, see below).
+  All measurements of a single star are consecutive.  The number of
+  measurements for a single star is defined by average.Nm and the
+  starting entry for a single star is given by average.offset.
+  Therefore, the first measurement of a specific star average[500]
+  would be given by measure[average[500].offset], while the second is 
+  measure[average[500].offset + 1], and so forth.  
+\item {\bf missing} -- this section contains references to all missing
+  measurements of a star.  This means all of those occasions when an
+  image enclosed the location of a star in the database, but no star
+  was detected on the image.  Similar to the case of the measure
+  section, each star has a number of missing entries (which may be 0)
+  given by average.Nn, and the first missing entry is given by
+  average.missing.  Each missing entry value is again a structure of
+  type Missing.  Currently, the only data in the structure is the time
+  of the observation, which allows for an unambiguous recovery of the
+  image where the star was missed.
+\end{itemize}
+
+\subsubsection*{Average Structure defined in loneos.h}
+\begin{verbatim}
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm, Nn;  /* number of measurements, missing */
+  short int Xp;               /* scatter in 1/100 arcsec (-327.67 to +327.67 valid range) */
+  short int Xm;               /* 1000*log(chisq) for magnitude measurement */
+  unsigned short int code;    /* an ID code (ie, star, ghost, satelite, etc) */
+  signed int offset;          /* offset to first measurement */
+  signed int missing;         /* offset to first missing obs */
+} Average; /* 28 bytes / Average */
+\end{verbatim}
+The structure above defines the average data stored in the photometry
+database for each star.  Most of the entries are self-explantory, but
+some need a bit of clarification.  The two $\chi^2$ entries ({\tt Xp}
+and {\tt Xm}) are the $\chi^2$ values of the average position and the
+average magnitude.  These are stored as logarthmic quantities because
+high dynamic range is not needed.  For the magnitude, the assumption
+is that the star brightness is constant and the $\chi^2$ incorporates
+the photometric errors on each measurement.  For the postion, the
+a default constant error is used \note{True?} and again the assumption
+is that the postion is constant.  As discussed above, the values of
+{\tt Nm} and {\tt Nn} give the number of measurements and missing
+observations for this star, while the entries {\tt offset} and {\tt
+  missing} point to the first {\bf measure} and {\bf missing} entry
+for this star.  The entry {\tt M} is the current best average
+magnitude solution for this star (see the section on Relative
+Photometry).  Finally, the entry {\tt code} is an ID code for each
+object, which may define a variety of things about the object.  For
+example, if the object is known to be variable, or if the object is
+associated with a USNO star, or if the object is a measurement of an
+asteroid.  See below for details of these definitions.
+
+\subsubsection*{Measure Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  short int dR, dD;           /* 1/100 of arcsec (-327.67 to +327.67 valid range) */
+  short int M;                /* thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mcal;             /* image cal mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 to 0.255 valid range) */
+  char dophot;                /* dophot type (1-9) */
+  unsigned short int source;  /* code to identify photometry source */
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+  unsigned int average;       /* reference to corresponding average entry */
+  /* upper byte of Measure.average stores flags:
+   limit of 16,777,215 stars (Naverage) in a file (=0xFFFFFF) 
+   flags: average & 0x1000000 */
+} Measure; /* 20 bytes / Measure */
+\end{verbatim}
+}
+The structure above defines the individual measurement data stored for
+each observation of each star.  The first two entries, dR and dD, are
+the difference between the average coordinates for this star and the
+coordinates determined for this observation.  Clearly, if this
+residual is too large, the individual measurement will not be
+successfully matched with the average star position.  {\tt M} and {\tt
+  dM} are the instrumental magnitude and error for this measurement,
+after correction for the exposure time and a zero point (defined in
+the configuration file as ZERO\_PT).  The entry {\tt t} determines the
+time of the individual observation.  This is important not only for
+timing purposes, but also to determine the source image for this
+observation.  The time and the entry {\tt source} uniquely determine
+the image in the image database that generated this measurement.
+Furthermore, this correspondence allows for determination of the pixel
+coordinates on the chip, by going throught the image astrometry stored
+in the Image database (see below).  The entry {\tt source} is a code which
+identifies the particular CCD/Telescope/Filter setup.  Each unique
+{\tt source} should be treated as an independent filter set for the
+purposes of accurate relative photometric comparisons.  This entry
+also allows external catalog data, such as the USNO or Sloan
+photometry, to be added to the database, as desired.  The entry {\tt
+  average} is a pointer back to the {\bf average} section to allow
+determination of the star from the measurements, in addition to the
+reverse.  The bits of the upper byte of this value are reserved for
+flags used to define particular situations for this measurement.
+Possible values are:
+\begin{itemize}
+\item 1 = BLEND\_IMAGE - the star on the image matched more than one
+  catalog star
+\item 2 = BLEND\_CATALOG - the star in the catalog matched more than
+  one image star
+\item 4 = UPPER\_LIMIT - \note{not really used?}
+\item 8 = CALIBRATED - relative photometry has been performed at least
+  once.
+\end{itemize}
+The entry {\tt dophot} stores the dophot type for this particular
+measurement (1-9: four extra bits in this field).   
+Finally, the value {\tt Mcal} determines the photometric calibration
+of this specific measurment.  This value is an offset appropriate to
+this image (and if needed, this point in time and this chip position)
+to bring the observations of the stars on multiple images to a common
+system (see the section on relative photometry).
+
+\subsection{Image Database}
+
+All images for which photometry has been included in the photometry
+database also have entries in an image database.  The image database
+is (currently) a single file in the upper directory of the photometry
+database.  The name of the file is determined by the IMAGE\_CATALOG
+entry in the configuration file, and is currently set to Images.dat.
+Like the photometry database files, the image database consists of a
+FITS header followed by binary data.  There is only one type of binary
+data: each image has an entry, which is the data from a structure of
+type Image (loneos.h).  The number of images in the file is determined
+by the {\tt NIMAGES} keyword.  If the number of images becomes too
+large, extrapolation of the system to a set of image database files
+with a reference list is quite straightforeward, and could be modeled
+on the organization of the region files (eg, one image database file
+for each Declination directory).
+
+\subsubsection*{Image Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  Coords         coords;            /* 120 bytes */
+  unsigned int   tzero;             /* readout time row 0 in sec (0 - 142 years valid range) */
+  unsigned int   nstar;             /* number of stars on image */
+  short int      secz;              /* thousanths of airmass (valid range -32.000 -- 32.000) */
+  short int      NX, NY;            /* dimensions of image */
+  short int      apmifit, dapmifit; /* aperture correction and error in thousandths of mag */
+  short int      source;            /* identifier for CCD (each ever used will have a unique letter) */
+  short int      Mcal;              /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      dMcal;             /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      Xm;                /* 10*log(image chi-square) */
+  char           name[32];          /* name of original image */
+  unsigned char  detection_limit;   /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  saturation_limit;  /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  cerror;            /* astrometric error: 1/50 of arcsec (0 -- 5.12 valid range) */
+  unsigned char  fwhm_x, fwhm_y;    /* PSF terms in 25*arcsec (valid range 0.0 -- 10.2" ") */
+  unsigned char  trate;             /* 10000 * scan rate in sec/pix (0 -- 0.0256 valid range, 
+                                       typically 0.0146. this is used only to determine the time
+                                       of the observation, not to find the coordinates.  1 byte
+                                       gives 0.11 sec accuracy */
+  float          exptime;           /* exposure time, seconds */
+  char           code;              /* flag to mark an image as bad or whatever */
+  char           dummy[21];         /* extra space for the future */
+  short int      order;             /* number of terms used for Mrel */
+  short int      Mx, My;
+  short int      Mxx, Mxy, Myy;
+  short int      Mxxx, Mxxy, Mxyy, Myyy;
+  short int      Mxxxx, Mxxxy, Mxxyy, Mxyyy, Myyyy;
+} Image;  /* 240 bytes / Image */
+\end{verbatim}}
+The structure above lists all of the data stored for each image.  A
+substantial amount of information is stored for each image.  First,
+the astrometric calibration information is stored in a {\tt Coords}
+structure (see coordinate systems, above).  The upper and lower limits
+of the photometry in the database (in instrumental magnitudes) is
+stored in {\tt detection\_limit} and {\tt saturation\_limit}.  These
+values are useful for comparison for those stars where observations
+are missing.  The relationship between time and pixel coordinates is
+given by {\tt tzero} and {\tt trate}.  Drift images will have a scan
+rate stored in {\tt trate}, while staring images will have a value of
+0.0 for this entry ({\tt tzero} then applies to the whole image).
+Other important parameters are kept: the astrometric error ({\tt
+  cerror}), the airmass ({\tt secz}), the exposure time ({\tt
+  exptime}), the number of stars detected ({\tt nstar}), the FWHM
+values ({\tt fwhm\_x, fwhm\_y}), the image name ({\tt name}), and the
+size of the image ({\tt NX, NY}).  The entry {\tt source} is used as
+above to define the CCD/Telescope/Filter used for this observation.
+The entry {\tt code} is used to flag images in various ways.
+Currently, only one bit is used, to define if the image has
+unacceptable photometric scatter.  Seven extra bytes are stored for
+future additions.
+
+\subsection{Data Incorporation -- {\tt addstar}}
+
+Images which are completely processed ({\tt dophot, fstat, gastro}) are
+then incorporated into the photometry database with the program {\tt 
+addstar}.  This program decides which region files are appropriate
+for this particular image, then one-by-one adds stars from the image
+to the appropriate region file.  Stars already in the catalog are
+matched with stars in the new image purely by a positional comparison.
+In order to avoid the difficulty of comparisons in the RA and DEC
+coordinate frame, a cartesian projection is performed.  The stars from
+the image being processed and the database stars in the same area are
+projected onto a tangent plane and positional comparisons made in this
+(locally cartesian) coordinate frame.  This avoids the dangerous
+singularities at the pole and also makes the RA 0,360\degree\ boundary
+a trivial problem.  
+
+Several choices must be made in the comparison process.  If a star in
+the catalog is matched with a star in the image, the new measurements
+of that star are added to the database.  If a star in the database
+lies in the field of the image, but is not detected, this information
+is added to the list of missing data.  The only data stored in this
+case is the time and source, which is sufficient to unambiguously
+identify the source image from the image database.  This allows later
+programs to find relevant statistics from the image database, if
+necessary.  If a star is detected in the image, but is not already in
+the database, a new entry is added to the database.  In addition, the
+same ``missing data'' from all previous observations images which have
+covered this location (ie, images already in the image database) are
+included.  This last step is necessary so that the image processing
+order is not important.  
+
+Stars also run the danger of being crowded together.  Since all
+comparisons are performed on the basis of position alone, crowded
+fields may make for ambiguous cross-identifications.  A pair of stars
+are matched if the difference in their positions is less than a
+specified search radius (usually dependent on the astrometric for the
+image).  If more than one catalog stars is correlated with a star in
+an image, the new measurement is added to {\em both} catalog stars,
+and a flag is set noting that this observation had a blended IMAGE.
+Conversely, if a single catalog star is matched with more than one
+image star, both new measurements are added to the one catalog star,
+and a different flat is set, noting that this observation had a
+blended CATALOG.   
+
+\section{Catalog Update and Cleaning}
+
+Occasionally, once a large number of images have been added to the
+photometry database, a set of programs should be run to clean and
+update the CPT files.  This may best be done on CPT files after a
+night's worth of data is incorporated.  These routines define bad
+data, identify the USNO catalog stars, and search for asteroids and
+other junk.  Most of the results from these routines are the addition
+of object flags to the Average data structures (Average.code).  Most
+of these routines process data within a single CPT file at a time.
+
+\subsection{Markstar}
+
+The first of the update programs, {\tt markstar}, identifies bad data
+and flags it.  It makes three types of identifications: bright stars,
+ghost stars, and trails.  In the first case, it searches the HST guide
+star catalog for bright stars within the field of the current CPT
+file.  Three types of pixels are flagged for bright stars.  Any
+measurements within a circular region centered on the star are suspect
+(the ``halo'' of the bright star).  Second, points along the X axis
+are likely to contain flux from the diffraction spikes.  Finally,
+points along the Y axis are likely to have bleeding in addition to the
+diffraction spikes.  Each of these three regions has a different size
+and range which must be defined in the configuration file.  The
+regions are represented by a representative magnitude and a scale
+parameter.  For example, the diameter $d$ of the halo for a star with
+magnitude $m$ is defined as 
+$d = \mbox{BRIGHT\_HALO\_SLOPE} (m - \mbox{BRIGHT\_HALO\_MAG})$.  The X and
+Y axis points are defined by the length of the diffraction spike, with
+an equivalent formula, and the width of the spike.  Since these are
+each independent, there are 8 parameters to define the exclusion
+regions of bright stars.  One of the current drawbacks of this system
+is the reliance on the HST Guide Star photometry.  In the HST Guide
+Star Catalog, only one photometry band is given, so no color
+information is available.  The parameters currently used were defined
+based on a large number of bright stars, with no adjustment for the
+different effective filter system of the Loneos telescope and the HST
+GSC.  Thus, occasionally very red stars will be several magnitudes
+brighter in the real data than reported in the catalog.  As a result,
+large numbers of bad data points in these halos and spikes may be
+missed.  
+
+The second type of bad data flagged by {\tt markstar} are the trails
+from satelite and other space junk.  This portion of the program
+searches for objects which land along a line and which have a high
+linear density.  Parameters may be adjusted to define the width and
+the necessary density or number of points in the line.  Objects in
+lines are also only identified if all observations come from a common
+image.  If an object only has one measurement and it is in a trail,
+the entire Average is flagged to be bad.  However, if an object has
+many measurements and only one is bad, the object is only flagged as
+having some bad data points.  
+
+The third type of bad dat are ghost star images.  The HST GSC is
+searched for stars projected across the telescope optical axis, which
+is defined by the user.  All objects within a region of fixed size is
+marked for ghost stars brighter than a specific cutoff magnitude.
+Similar to the trails, the average is marked as bad only if all
+detections of an object are ghost images.  Otherwise, it is noted that
+some data may be bad.
+
+\subsection{Addusno}
+
+The program {\tt addusno} makes two types of identifications of stars
+with the USNO catalog.  First, it searches for coincidences within a
+small, specified radius.  The choice of this radius is somewhat
+tricky: it is important to catch the association, but also to avoid
+making too many associations.  Unfortunately, astrometric errors in
+the USNO catalog make it necessary to choose a surprisingly large
+radius of 5\asec.  To avoid making double matches (matching the two
+USNO stars to the same photometry database object), only the USNO
+object closest to the object is associated.  There are also a
+substantial number of stars with significant proper motion between the
+USNO epochs and the current date.  It is not unusual to see 8-15\asec\ 
+discrepancy for specific stars.  To catch these objects, any objects
+which do not match the USNO database, but which have more than a
+minimum number of measurements (2 or 3?) are searched for more distant
+USNO companions.  A large, user-specified radius is used for this
+search.  Of course, only USNO stars which are not already matched to
+the database may be candidates for the proper motion match.  This
+stage is suceptible to errors in that a slow-moving solar-system
+object may be associated with a faint USNO star.  For this reason,
+objects flagged as high proper motion stars should be taken with some
+caution.  Of course, during the {\tt addusno} stage, no objects
+already flagged as bad by {\tt markstar} will be matched with USNO
+stars.  
+
+\subsection{Markrock}
+
+Once stars have been identified with the USNO database, it is possible
+to search for asteroid detections.  The program {\tt markrock}
+searches within a specific CPT file for objects which are moving along
+straight lines in (X,Y,t) space.  In order for an object to be found
+by {\tt markrock}, it must have three points, each with only single
+measurements.  The third point must land within a specified distance
+of the line projected from the first two data points.  These
+comparisons are made in the three dimensional space of image position
+and time.  Also, objects are only accepted if they have a speed less
+than a threshold.  If an object is moving too fast, it will make a
+streak on each individual image and will probably be missed anyway.
+Moving objects detected in this way are flagged in the photometry
+database and are also written to a Rock database.  Currently, the Rock
+database just contains ASCII lists of the RA, DEC, Mag, and time for
+each detection.  In fact, the data are stored in pairs of detections,
+with the middle detection saved twice.  This format makes it easy to
+plot lines connecting the points using the connect-the-dots plotting
+style of status/kapa (see below).
+
+One of the current drawbacks of {\tt markrock} is the insistence on
+three observations with only 1 measurement each.  If an object is
+moving too slowly, two of the dectections of the object may be merged
+together.  Enough data is stored in the database to extract these
+individual measurements, so a more sophisticated search is possible.
+It is also currently the case that USNO proper motion stars are
+ignored, but some of these will be asteroid detections which are
+simply too close to a faint USNO stars (it has to be faint because it
+would otherwise be associated with a star in the photometry
+database).  
+
+\begin{figure}
+\psfig{file=flags.eps,width=9cm}
+\caption{\label{flags} 
+Pictoral representation of the Average.code flags.  The lower byte
+value is used for specific definitions of object types.
+}
+\end{figure}
+
+\subsection{Data Flags}
+
+The identifications made by the above routines are noted as a set of
+flags in the Average.code structure entry.  Some of these flags are
+mutually exclusive, so a certain bit may have more than one meaning,
+depending on the value of other bits.  Figure~\ref{flags} shows a
+pictoral representation of the meaning of the different bit fields.
+The uppermost bit (bit 15) determines if the object may be considered
+a ``fixed'' star or something which has no fixed location.  If it is
+not fixed, and this bit is 1, then there are several options.  The
+second uppermost bit (bit 14) will be set if this object is one of the
+three types of bad data flagged by {\tt markstar}.  The lower byte of
+code is used to define the type of bad data: ghost, trail, or bleed.
+Thus, any datapoints determined to be a satelite trail will have a
+code value of 0xc002 (49154 decimal).  If an object is a moving
+object, but not a bad datapoint, it may be identified as a ``rock''
+(an asteroid) by the program {\tt markrock}.  In this case, the flag
+for an asteroid is turned on (bit 13).  Thus anything identified as a
+rock by {\tt markrock} will have a code value of 0xa000.  The lower
+byte of code is not yet defined for asteroids, but could be reserved
+for distinguishing different classes of asteroids (ie, on the basis of
+orbital speeds, and so forth).  Objects which are fixed may have a
+variety of possible flags.  First, an object may be identified with a
+USNO star (bit 14).  It may be found to exhibit variability (bit 13),
+implying that the relative photometry routine should ignore it.  If
+may be a transient object (bit 12).  Note that, while an object
+associated with a USNO object may not be transient, an object which is
+variable may also not be associated with a USNO object.  Thus, we need
+seperate bits for variable vs transient.  Different types of variable
+objects may be represented with different values of the lower byte.
+For example, a Cepheid may have a specific lower byte code of 0x01,
+which an RR Lyra may have a lower byte code of 0x02.  Thus a Cepheid
+associated with the USNO catalog would have a total code value of
+0x6001. Finally, any of these types of non-moving objects may have
+some bad individual measurements (bit 12) or may be found to have a
+significant proper motion (bit 11).
+
+\section{Holding it Together}
+
+The preceeding sections describe the step-by-step analysis and
+incorporation of the data from individual images.  However, the power
+of the Pipeline comes in applying it to large numbers of images.  At
+LONEOS, we are using four Pentinum II computers to analyse the roughly 200
+images that are observed each night.  
+
+It is best to think of the analysis of images occurring on groups of
+images from a given night.  Of the set of processes discussed above,
+those in section \ref{parallel} are performed on individual images
+essentially independently of the other images.  The rest of the steps,
+both the data incorporation ({\tt addstar} and the database cleaning
+routines occur on the entire batch, one image at a time.  Thus, the
+former routines can easily be run in parallel, but the latter routines
+are run in serial to avoid having two programs writing to same part of
+the database at the same time.  In this model, we would process all of
+the images from a night through the parallel stage of the analysis and
+then run the serial stage only after the entire night is finished in
+the parallel stage.  We thus have a natural division of the pipeline
+into two stages.  
+
+The implementation of the two stages involves several programs, some
+of which are specific to the LONEOS situation, and others which are
+more general.  There are two layers of programs which enable batch
+processing of many images and repeated batch processing over many
+nights.  At the highest level, are Perl scripts which choose what data
+needs to be analysed and when.  These scripts tend to be more
+dependent on the details of the LONEOS implementation. At the next
+level down, these scripts call two main C programs which run the
+images of a given night through the pipeline.  These C programs are
+more general and do not depend on the details of the LONEOS
+implementation.  A defined set of files holds a log of the nights and
+images that have been processed, both for the information of people
+who might want to monitor the progress, but also used by the programs
+to guide decisions about what to analyse next.
+
+\subsection{data and file organization}
+
+There are a set of standard locations for all of the files used and
+created by the Pipeline.  These locations have both abstract names
+used by the pipeline programs and specific definitions used in the
+LONEOS implementation.  In general, the definitions of the files are
+given in the configuration file, 'config.txt' (currently located in a
+hard-wired location, but this may soon change to the mechanism used by
+the lastest version of spicam (3.0)).  The C programs all refer to the
+config file for the definitions, but the Perl scripts currently have
+the definitions hardwired as variable names defined in the beginning
+of each file.  This should be changed to a mechanism that looks in
+the config file, perhaps implemented by a standard Perl function.
+
+Here is a list of the main directories and their meanings:
+
+logdir:         /metis/d11/logs - all log files and the files used by
+the Perl scripts to control their actions (except locks) go here.
+
+workspace:      /irene/d11/workspace - the intermediate analysis
+stages go here, and the tar, gzipped directory files stay here.
+
+dumpspace:      /pallad/d1      - used by slurp to store images
+downloaded from the tape archive.
+
+database:       /hebe/d27/database      - the result database, as also
+the locks and the Rocks.dat file.
+
+references:     /metis/d11/references   - a variety of reference data,
+including the HST GSC, the USNO catalog, the config files, and so
+forth.
+
+source:         /metis/d11/src/ohana    - all of the programs source, 
+binaries, and scripts relevant to running the Pipeline are contained
+in these directories.  
+
+\begin{verbatim}
+database: /hebe/d27/database (also in /metis/d27/database as linked directories).
+ lock files also go in this directory
+workspace: /irene/d11/workspace - temporary storage of result files
+dumpspace: /pallas/d1 - disk to store data dumped from the archive by slurp.
+scriptdir: /metis/d11/logs - all log files
+\end{verbatim}
+
+\subsection{lastnight}
+
+The first step in the process is the Perl script {\tt lastnight},
+which is highly dependent on the specifics of the LONEOS setup.  It
+looks at the disks used by the observers to write the images from a
+given night.  Images are written to a directory called
+/pallas/d[1-6]/YYMMDD where 'YYMMDD' is an abbreviation for the current
+night's date (ie, 990223).  Many files use this naming scheme, so we
+will refer to such a name as 'YYMMDD'.  All of the images are stored
+in this directory with names yyyyMMDDxxxxb.fits where yyyy is the full
+year, MM is month, DD is date, and xxxx is a sequence number.  The 'b'
+refers to the 'b' CCD, and the .fits extension is required.  The
+script {\tt lastnight} is called by a cron job scheduled for 7am on
+{\tt hebe.lowell.edu} (note that the clock on hebe is set to PST, not
+local MST - fix this some day!).  The script searches the disks
+{\tt /pallas/d[1-6]} for a directory of the right form (basically any
+directory beginning with a number).  By default, the program demands
+that the directory have the name derived from today's date, but with
+the flag -any, it will accept any directory.  It then checks to see if
+this directory has been already been analysed (ie, it is included in
+the 'processed.log' file).  If not, it lists all files in that
+directory with the right ending (*b.fits) and places these names in a
+file, {\tt /metis/d11/logs/YYMMDD.inlist}.  It also writes the name of the
+directory (along with some other data) in a file 'extracted.log'.
+When it has successfully ended and identified some data, it calls the
+next script, {\tt stage1} and then quits.
+
+\subsection{slurp}
+
+An alternative to {\tt lastnight} is the Perl script {\tt slurp},
+which looks for data on the tape archive.  This script looks at the
+tape.log file and compares it to the file 'processed.log'.  It tries
+to identify nights listed in the file 'tape.log' which have not been
+included in the 'processed.log'.  If it finds any, it tries to
+download as much of the data as will fit on the disk {\tt /pallas/d1}.
+This script is called from within the {\tt stage1} script and is
+invoked if {\tt stage1} is run without any data already in
+the file 'extracted.log'.
+
+\subsection{stage1}
+
+The Perl script {\tt stage1} takes the image list produced by {\tt
+lastnight} or {\tt slurp} (YYMMDD.inlist) and passes the list to the
+controller program {\tt control1} which performs the parallel
+analysis.  The script has a few features to decide which files have
+been analysed through the pipeline and to what extent.  If {\tt
+stage1} is called, it should be able to figure out 1) if there is data
+ready to be analysed (ie, there is a new date reference in the file
+'extracted.log'), 2) if the data has been partially analysed (ie, the
+date reference in 'extracted.log' has not been put in 'processed.log',
+but there are entries in the file YYMMDD.outlist), and 3) which data
+needs to be run through which part of the pipeline (ie, it decides
+which of the images in YYMMDD.outlist have succeeded at which stages
+of the analysis, and starts them at the appropriate spot).  These
+features are most useful if the analysis crashes in the middle or
+needs to be restarted.  The {\tt stage1} script is meant to be run
+without any arguments and it will figure out what needs to be done.
+The one possible argument is the -once flag.  This flag tells {\tt
+stage1} to analyse the data it finds and quit when it finishes, and
+not call another instance of itself.  Otherwise, when it is done, it
+will restart itself, and since there is no new data in
+'extracted.log', it will start a slurp process to get data from the
+archive.  If there is no data in the archive either, this process will
+sleep for an hour and try again.  After a few attempts (2 days?), {\tt
+stage1} will give up and quit without restarting itself.  The script
+writes a log file called \$scriptdir/stage1.NN.log where NN is a
+number in sequence between all runs of {\tt stage1}.  A file
+stage1.count keeps track of which number NN we are on.  When {\tt
+stage1} has finished the analysis of a night's data, it writes the
+date in 'processed.log' to let other processes know what has been
+analysed.  The bulk of {\tt stage1} is not dependent on details of the
+LONEOS setup, but it does expect the files to have the naming scheme
+described above.
+
+\subsection{stage2}
+The serial stage processes are run by the Perl scrip {\tt stage2}.
+Normally, this script is always running.  It waits for the name of a
+night to be added to the 'processed.log file, presumably be {\tt
+stage1}.  Once if finds a new name in this file, it looks for the
+appropriate images in the file 'YYMMDD.addlist'.  It then submits the
+list to the second controlling program {\tt control2}, which runs the
+images through {\tt addstar}.  Images which are successfully run
+through addstar have their *bf.fits (flattened image) and *.obj
+(dophot output) files deleted.  When the entire night is done, the
+rest of the *.obj and *bf.fits images are deleted by {\tt stage2}, the
+directory with the *.cmp and *.log files is tared and gzipped into the
+file YYMMNN.tgz.  The directory is then deleted.  Finally, {\tt
+stage2} calls the scripts {\tt cleaning.pl} and {\tt run.phot} which
+runs the cleanup programs ({\tt markstar - nrphot}) on the database.
+After a successful run, {\tt stage2} will automatically respawn a new
+copy that waits until more data arrives.
+
+\subsection{control1 / control2}
+These two C-programs perform the tasks of farming the images out to
+the different machines for analysis.  The two programs are essentially
+identical, but {\tt control1} is allowed to use all machines and {\tt
+control2} can only use one (hebe.lowell.edu, which has the database
+local to it).  These controller programs start off by executing remote
+shells (using ssh) on a set of machines.  These shells are then used
+to execute the remote commands and are kept open the entire time the
+process runs.  
+
+Both control programs maintain a list of images in a set of queues.  A
+set of rules defines the order in which each image travels through the
+queues.  Each queue is associated with a single process (ie, flatten,
+astrometry, etc).  Images which successfully run through a queue are
+sent on to the defined 'next' queue, while images which fail are
+instead sent to the defined 'fail' queue.  In most cases, the 'fail'
+queue is a process which marks the image as bad and write the name in
+a file, and then puts the image in the 'done' queue.  However, it is
+possible for the 'fail' queue to be another attempt, such as in the
+case of astrometry.  In this example, images which fail the default
+astrometry are run through a second queue which tries again with the
+-loneos flag set (this flag makes the assumption that the header
+information about the LONEOS region number for the image is correct,
+not the RA/DEC information).
+
+The connections on the remote machines are handled as child processes
+with communication through the stdin and stdout/stderr pipes.
+Messages can be sent back and forth though these pipes, and messages
+which are received from a process associated with an image are written
+to a log file with the name imagename.log (where imagename is the root
+name of the image).  The only required messages from the program are
+messages saying ``SUCCESS'' or ``ERROR''.  The programs therefore all
+end with either of these words.  The programs are started within the
+controller as a command to the shell followed by and echo ``PROCESS
+DONE''.  If the controller sees the message ``PROCESS DONE'' without
+either ``SUCCESS'' or ``FAILURE'' (after waiting an appropriately long
+time), it assumes the program crashed.  Currently, no timeout is
+available for the programs.  The flat-field process is run in mana and
+is a slightly special case.  We avoid re-loading the same flat many
+times by starting a mana process once and running the flatten
+procedures as mana function calls.  The images which are analysed
+(with an indicator of success or failure at each stage) are written to
+a file named 'YYMMDD.addlist' by the {\tt control1} and 'YYMMDD.outlist'
+by {\tt control2}.
+
+\subsection{Lock files}
+
+A variety of locking mechanisms are used to avoid overwriting the
+database or running more than one version of the controlling
+programs.  There is a perl program, {\tt locks}, which allows the user to
+set or check the state of the different locks. All programs which
+write to the database check for the existence of a lock on the
+database and refuse to run if it exists.  The control1/2 programs and the
+stage1/2 programs check for their own lock files and only run if they
+don't exist.  Finally, the use can set the lock files 'kill' or 'halt'
+for either stage1 or stage2.  The first tells the process to stop
+immediately, taking care of bookkeeping first.  The second tells the
+process to finish the current set of images but not start a new
+version.  
+
+\subsection{Other Perl Scripts} 
+
+there are several other scripts which are either used to do some
+simple function or are used by the maintainer to check up / work on
+the pipeline.  The two programs 'checkoutlist' and 'checkaddlist' take
+a list of YYMMDD.outlist or YYMMDD.addlist files and list the number
+of images in the file and the number of successes at each analysis
+stage.  There programs 'cleaning.pl' and 'run.phot' deal with the
+cleanup programs and the running of nrphot.  the program
+'backup.stuff' take the first 4 characters of the year/month file
+names and backs up to the jukebox tape all tar files for the given
+month.
+
+\section{Operational Issues and Subtleties}
+
+The current LONEOS system runs principally on four Intel machines
+under linux.  The existing system has been generally quite stable over
+the past year of operation, but there are some subtleties.  One
+significant issue is the RAID disk attached to hebe.lowell.edu.  This
+device is a set of three 9 GB disks merged into one 27GB raid disk.
+The database is stored mostly on this dist and the RAID disk mounted
+on metis.  It is easy to split the database across multiple file
+systems by using links.  Within the database directory, there are
+directories for each of 24 Declination bands (7.5 degrees tall).  The
+easiest way of splitting up the data is to move some of these
+subdirectories to another device and creating links to them at the
+appropriate place.  This is currently done by having a directory
+/metis/d27/database with the remote directories.  
+
+The current problem with the /hebe/d27 RAID results from the poor way
+it was setup.  It was set up without much knowledge of the (at the
+time) rather rudimentary linux RAID system.  As a result, the
+implementation is such that the disk will not automatically be
+configured and mounted at boot time.  There is a script /root/mdstart
+which lists the step to setup the RAID correctly.  It would be helpful
+if the rc.local or rc.sysinit files were fixed to start, fsck and
+mount the RAID automatically at boot.  The setup on metis is
+substantially more mature and is correctly implemented.  It comes up
+when the machine boots.
+
+\section{Visualization -- Status}
+
+Visualization of the data in the photometry database can best be
+performed with the program {\tt status}.  This is a command-line
+driven program with a math and macro language which makes it easy to
+perform complex tasks.  
+
+First, a few notes about the user interface.  The interface has an
+interaction similar to {\tt tcsh}.  The arrows allow editing of
+previous commands.  You can also use emacs-like commands such as
+cntl-a to reach the beginning of the line and cntl-e to reach the end.
+There is command and file completion: if you type part of a command
+(as the first thing on a line) and then type tab, it will fill in as
+much as possible, until the word is not unique.  Typing tab twice at
+that point will list the possible endings.  For any but the first word
+on a line, the same thing will happen for the files in the current
+directory.  It is also possible to type just a fraction of a command,
+as long as it is unique.  An ambiguous command will list the possible
+alternatives.  For example:
+\begin{verbatim}
+status: c
+ambiguous command: c ( catalog cgrid clear create cursor )
+\end{verbatim}
+
+The shell is essentially an interpretive programming language.
+Variables are set as follows:
+\begin{verbatim}
+status: $fred = 10
+\end{verbatim}
+Any expression within curly brackets \{\} is assumed
+to be an arithmetical expression and is evaluated before the line is
+executed.  For example:
+\begin{verbatim}
+echo {$fred*dcos(45)}
+\end{verbatim}
+would give the response 7.07107.  There are math functions cos, sin,
+and tan, which operate on radian expressions, and also dcos, dsin,
+dtan, which operate on degree expressions.  There are also the
+equivalent inverse functions: eg., asin and dasin return radians and
+degrees, respectively.  The help section on Math defines all of the
+available math functions.  
+
+\subsection{Miscellaneous Commands}
+\begin{verbatim}
+!                         -- system call
+?                         -- list commands 
+??                        -- list variables 
+echo                      -- type this line 
+exec                      -- system call
+exit                      -- exit program 
+help                      -- get help on a function 
+output                    -- redirect output to file
+quit                      -- exit program 
+scan                      -- scan line from keyboard or file to variable 
+wait                      -- wait until return is typed
+which                     -- show command 
+\end{verbatim}
+Most of these are self-explanatory.  The command ?? prints the system
+variables.  The {\tt help} command will provide help on a single
+command or, without any arguments, will list all available help
+files (this includes general help not associated with a specific
+command).  
+
+\subsection{Shell Programing}
+\begin{verbatim}
+break                     -- escape from function 
+for                       -- loops 
+if                        -- logical cases 
+input                     -- read command lines from a file 
+macro                     -- deal with the macros 
+\end{verbatim}
+
+There are several options for programming in {\tt status}.  First, a
+file which contains a series of commands can be executed with {\tt
+  input (filename)}.  It is also possible to define macros which will
+behave much like regular commands.  A macro is defined by typing {\tt
+  macro name} or {\tt macro create name} followed by the commands.
+Arguments to the macro are assigned to the variables \$1 .. \$N and
+the number of arguments is given by \$0.  Macros may be defined in
+{\tt input} files, and in fact when {\tt status} is started, it loads
+the file {\tt \~/.statusrc} which may contain default macros.  Simple
+loops and if statements can be performed, and are quite useful for
+complex macros.  
+
+``If'' statements are similar in syntax to C if statements, but only
+the following logical operators are available: $>$, $<$, $=$, !, $|$,
+and \&.  Notice that (currently) there is no $>=$ or $<=$ symbol.  The
+operator ! means ``not equal to'', but cannot be used to negate a
+logical value.  The operators $|$ and \& have the meaning of ``or'' and
+``and'' respectively.  Math expresions in the if statement must be
+contained in curly braces, as elsewhere.  Variables with string values
+may use the logical $=$ operator to test if two strings are the same.
+``For'' loops are quite simplistic.  The form is:
+\begin{verbatim}
+for var first last delta
+ (commands)
+end
+\end{verbatim}
+The value of {\tt \$var} will start at the value {\tt first} and increment by
+{\tt delta} after each loop.  The loop will stop after {\tt \$var} is greater
+than {\tt stop}.  The value {\tt delta} is optional, with 1 assumed.
+The value of {\tt \$var} may be changed during the loop, and if set
+beyong the value of {\tt last} will end the loop early.  
+
+\subsection{Vector Plotting}
+
+\begin{verbatim}
+box                       -- draw a box on the plot
+clear                     -- erase plot
+create                    -- create a new vector
+cursor                    -- get coords from cursor
+grid                      -- plot cartesian grid
+hist                      -- create histogram from a vector
+labels                    -- define labels for plot
+limits                    -- define plot limits
+plot                      -- plot a pair of vectors
+print                     -- write vectors to file
+ps                        -- define labels for plot
+set                       -- vector math
+style                     -- set the style for graph plots
+vectors                   -- list vectors
+zplot                     -- plot scaled points 
+\end{verbatim}
+
+In addition to scalar variables, {\tt status} can manipulate and
+display 1-D vector variables.  Many of the commands which extract data
+from the photometry database place the data in vectors as well as
+plotting them.  A vector can also be created based on a number
+sequence with the command {\tt create name Nelements start delta}.
+The resulting vector has $Nelements$ entries, starting at a value of
+$start$ and running until $start + delta*Nelements$.  If $delta$ is
+0.0, all elements will have the value of $start$.  A histogram of a vector
+may be made with the command {\tt hist}, which creates a new vector
+containing the histogram of the first vector.  The data range and bin
+size of the histogram are defined in same way as with create.  This
+makes it easy to create the index vector that goes with a histogram
+vector:  
+\begin{verbatim}
+hist y Ny 1 100 0.1
+create dx 1 100 0.1
+\end{verbatim}
+The above will create a histogram of y in Ny and the index in dx.
+Plotting this with {\tt plot dx Ny} will show the histogram.
+
+Vector math is performed with a command of the form {\tt set new =
+  (expression)}.  The expression is some math function employing
+vectors and scalars.  A complete listing of the math operators
+available in {\tt set} can be found in the help for {\tt set}.
+
+Once vectors are defined, they may be plotted.  A pair of vectors can
+be plotted against each other if they have the same number of entries.
+The plotting is performed on the graphics window, Kapa.  There are
+actually several graphics windows available to {\tt status}, any of
+which may be used to plot at any time.  Some of the more complex
+operations default to either graphics window 0 or 1, depending on the
+context.  Except for those functions with a pre-defined window, all
+plotting functions apply to the current graphics window unless an
+option {\tt -n N} is given to specify a different window.  The
+plotting style is determined by the command {\tt style} which can set
+the line width, the line type (solid, dashed, dotted, etc), the point
+type (box, cross, etc), the point size, the color, and whether a pair
+of vectors is plotted as a sequence of points, a set of connected
+lines, or a histogram.  Some functions which make plots use their own
+styles, as discussed below.  The function {\tt limits} lets the user
+set the range of the plot axes, or check the current setting.  The
+command {\tt plot} will plot a pair of vectors on the current graphics
+window using the current plotting style for that window.  The command
+{\tt zplot} will plot a pair of vectors with the point size scaled by
+a third vector, with maximum and minimum point sizes representing
+specified values.  The {\tt cursor} command goes the other way: this
+command puts the Kapa window in cursor mode and waits for input from
+Kapa.  The user can then type any alphanumeric key on the graphics
+windows and will be told both the pointer location (in the graphics
+coordinates) and will have the coordinates stored in {\tt status}
+variables.  For example, by typing ``1'' in the sky display window,
+the RA and DEC of the pointer are stored in the variables {\tt \$R1}
+and {\tt \$D1}.  This command can be used to let the user define
+locations or regions of interest on the Kapa window. (Future addition:
+{\tt button}, which does the same with the mouse buttons).  
+
+\subsection{Database Functions}
+
+\begin{verbatim}
+gcat                        -- get catalog at location
+gimages                     -- get images at location
+gstar                       -- get star statistics
+extract                     -- extract average vectors from catalogs
+mextract                    -- extract measurement vectors from catalogs
+imstats                    -- plot image statistics
+imextract                   -- extract image vectors from database
+lcat                        -- list catalogs in display region
+cmatch                      -- match two catalogs
+\end{verbatim}
+
+There are a variety of other commands which directly refer to the
+photometry database.  Some of these functions extract data of various
+types from the database, others perform more complex plotting
+operations.  The commands listed above are those which simply extract
+data from the database.  The first three list information relevant to
+a specific RA, DEC location on the sky: {\tt gcat (RA) (DEC)} lists
+the catalog at the specified location and places the name in the
+variable {\tt \$CATNAME}, {\tt gimages (RA) (DEC)} lists all images
+which overlap the specified location, , {\tt gstars (RA) (DEC)
+  (RADIUS)} lists data about the stars within a specified radius of
+the specified location (all numbers above are given in decimal
+degrees).  Similarly, {\tt lcat} lists the catalogs in the region.
+Imstats lists statistics about each image
+
+The next three commands extract a specific piece of information from
+the photometry database and places it in a vector.  First, {\tt
+  extract} will extract average values for each star and place it in a
+vector.  Next, {\tt mextract} will extract measurement values for each
+star and place it in a vector: as a result a single star may have
+multiple entries in the measurement vectors.  Finally, {\tt imextract}
+will extract image statistics into vectors (not yet implemented).
+
+
+\begin{verbatim}
+catalog                    -- plot catalog stars
+cgrid                      -- plot sky coordinate grid
+cplot                      -- plot vectors in sky coordinates
+czplot                     -- plot scaled vectors in sky coordinates
+images                     -- plot image boxes
+imdense                    -- image density plot
+lcurve                     -- plot lightcurve for a star
+pcat                       -- plot catalog boundaries
+region                     -- define sky region for plot
+resid                      -- plot residuals
+simage                     -- plot stars in an image
+\end{verbatim}
+
+There are two types of database plotting functions: those that display
+or refer to the spatial charateristics of the data and those that
+refer to other types of charatersitics, such as the time domain.  The
+graphics window 0 is reserved for all plots of objects on the sky.
+The command {\tt region} defines the current sky coordinates for plots
+in graphic window 0.  The command {\tt pcat} plots the outline of all
+photometry database files which are within the currently defined
+region (and by default, only those with data).  {\tt images} plots the
+outline of the images in the image database, while {\tt imdense} shows
+the number of images at a location by randomly spacing dots within the
+boundary of the images.  The command {\tt cgrid}
+draws a grid in celestial coordinates on the for the current region.
+
+The most complex, but also one of the most useful command is {\tt
+  catalog}, which plots the positions of stars in the photometry
+database (and others) on the sky.  There are many options to this
+command.  One set allows the user to plot stars from the photometry
+database (the default), from the HST GSC, or from an ASCII text file
+with RA, DEC, and Mag in specified columns.  If the ASCII file has a
+fixed number of bytes per line, the data can be more quickly loaded.
+The size of the points may be scaled by the star magnitude, by the
+number of observations of the star, or by the number of missing
+datapoints for the star.  In addition, points may be plotted only if
+they land in specified magnitude ranges, or with specified numbers of
+measurements, or missed measurements.  Also, objects may be plotted
+only if they have a specified Average.code, so that only asteroids or
+only perfect stars may be plotted.  The plotted vectors may be saved,
+if desired, and the source catalog epoch may be specified as different
+from J2000 (only valid for ASCII data).
+
+Several other commands relate to non-spatial charateristics of images
+and stars.  {\tt lcurve} will plot a light curve for all stars within
+some radius of a point.  {\tt resid} plots the photometry residuals
+for a particular region file.  
+
+\section{Some Examples}
+
+\begin{figure}
+\psfig{file=allsky.ps,width=16cm}
+\caption{\label{allsky} 
+Map of the entire sky, and images added to database.
+}
+\end{figure}
+
+Fig.~\ref{allsky} shows a map of the entire sky, and the location
+of the images currently in the database.  This picture was made with
+the following commands: (output is not shown) \\
+\begin{verbatim}
+status: region 0 0 90 gls
+status: cgrid
+status: style -lw 2 -c red 
+status: images
+status: ps
+\end{verbatim}
+In this example, on the graphics window, the image boxes are shown in
+red.  The user now has the possiblitiy of using the cursor command to
+narrow in on a specific region, and so forth.  
+
+\begin{figure}
+\psfig{file=catalog.ps,width=9cm}
+\caption{\label{catalog} 
+Comparison between HST GSC and photometry database astrometry. 
+}
+\end{figure}
+
+Fig.~\ref{catalog} shows an example comparison of the photometry
+database star positions and the HST Guide Star Catalog star
+positions.  The crosses are from the photometry database while the
+boxes are from the HST GSC.  The size of both points is a function of
+brightness.  This plot was made with the following commands (starting
+from the previous image):
+\begin{verbatim}
+status: cursor  (typed 1 on region of interest)
+1 137.097858 22.698305
+q 137.097858 22.698305
+status: region $R1 $D1 0.5 TAN
+status: cgrid
+status: box
+status: style -pt 0 
+status: gcat $R1 $D1 
+  0 n2230/1951.cpt *
+status: catalog n2230/1951.cpt -m 12 18
+status: style -pt 2
+status: catalog n2230/1951.cpt -m 12 18 -g
+\end{verbatim}
+
+\begin{figure}
+\psfig{file=lightcurve.ps,width=9cm}
+\caption{\label{lightcurve} 
+Lightcurve for several image stars.
+}
+\end{figure}
+
+Fig.~\ref{lightcurve} shows an example lightcurve from three stars in
+the above field.  The x axis shows the time in seconds, which the y
+axis shows the star magnitudes.  This plot was made with the following commands (starting
+from the previous image):
+{\small
+\begin{verbatim}
+status: cursor
+1 137.062562 22.791860
+q 137.062562 22.791860
+status: lcurve $R1 $D1 0.01 -l
+status: box
+status: gstar $R1 $D1 0.01
+read 11318 stars from catalog file /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt (22462 total measurements)
+508 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.068619 22.785400 18.438000  1 (2)  1.000000 1.000000
+498 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.062820 22.792747 12.882000  3 (0)  1.000000 1.000000
+501 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.064499 22.800817 15.480000  3 (0)  1.000000 1.000000
+\end{verbatim}}
+The last lines show the database information on the three stars.  
+
+\section{Software Distribution}
+
+All of the code, binaries, and scripts for the Pipeline are stored in
+the ohana tree at /metis/d11/src/ohana.  The ohana directory contains
+subdirs of bin, lib, include, src, config, and doc.  There is a
+Makefile at the top level which calls lower-level Makefiles to build
+the programs desired.  One of the important concepts in the ohana
+distribution is the design of the directory layout to enable binary
+support for multiple architectures.  The Makefiles use the environment
+variable ARCH to determine the appropriate architecture.  The binary
+and library files are stored in subdirectories of the form bin/\$ARCH
+and lib/\$ARCH.  It is therefore necessary that users of the ohana
+system architecture define the ARCH variable correctly.  It is also
+necessary to include in the user's PATH the directory
+/metis/d11/ohana/bin/\$ARCH.  At LONEOS,
+with the solaris sparc station and the linux machines both in use,
+ARCH can take on the values of 'linux' and 'sol'.  The values 'sun4',
+'irix', and 'hp' have also been used at various sites.  A simple bit
+of csh script in the users .cshrc or equivalent can make this
+assignment transparently:
+
+\begin{verbatim}
+set sys=`uname -s` 
+switch ($sys)
+ case IRIX64:
+   setenv ARCH irix;
+   breaksw;
+ case SunOS:
+   set ver=`uname -r | awk '{print substr($1,1,1)}'`;
+   if ($ver == 5) then
+     setenv ARCH sol
+   else 
+     setenv ARCH sun4
+   endif
+   breaksw;
+ case Linux:
+   setenv ARCH linux;
+   breaksw;
+ default:
+   echo "unknown architecture";
+   setenv ARCH unknown;
+   breaksw;
+endsw
+\end{verbatim}
+
+The Makefiles use the ARCH variable not only for destination
+directories, but also for destination binary names.  All files of the
+form fred.c are compiled to fred.ARCH.o (instead of fred.o), 
+uninstalled libraries get the names libfred.ARCH.a (instead of
+libfred.a), while uninstalled programs are called fred.ARCH.  
+
+The perl scripts are kept in ohana/src/perl, with links to the
+appropriate bin directories.  All programs are stored in directories
+of the form ohana/src/program.  The exceptions are gastro (stored in
+ohana/src/astro), and control1/2 (stored in ohana/src/astro).  Also, a
+variety of simple, user-level functions are available in
+ohana/src/misc. 
+
+Most of the ohana package of programs use several common libraries.
+These include the readline library (except for dophot, this is the only
+part of ohana that is not written by Eugene Magnier), which is used
+for command-line interface systems.  Other important libraries are the
+fits library for implementing the FITS specifications in a convenient
+C-friendly environment, and the ohana library, consisting of basic
+string and other basic operations.  
+
+For more details on the programming aspects of parts of the pipeline,
+see the associated document, 'A Programmer's Guide to the Loneos
+Pipeline'
+
+\section {Comparison with USNO catalog}
+
+I have made several comparisons between the USNO catalog and results
+from running images from Loneos through the photometry pipeline.  In
+general, there is a good agreement between the astrometry of the two
+datasets.  There are specfic areas where the two disagree, however.
+First, as discussed above, the USNO star positions may be
+significantly different from the observed star positions simply
+because of proper motion.  The first picure in the ``Comparisons
+between Loneos + USNO'' pages shows several stars with significant
+proper motion.  These are currently being flagged in the photometry
+database as discussed.  Other differences evident in this first
+picture include the classification of bright stars and the splitting
+of faint and bright stars.  In the upper right of the image, two
+bright stars are visible, one of which is actually a double.  The USNO
+catalog does a good job of detecting both, but it also detects and
+includes as stars several diffraction spike points.  The HST GSC only
+detected a single point and did not split the star at all.  The Loneos
+data in our pipeline did not detect the star at all due to saturation.
+A star in the upper left corner shows the ability of {\tt dophot} in
+the Loneos pipeline to split double stars.  This star is, on close
+inspection, clearly a double.  The USNO catalog only detects one.  The
+Pipeline not only splits the two stars, but it also makes the correct
+cross-identification of the stars.  
+
+The second set of pictures shows the ability of the Loneos pipeline to
+deal with small galaxies.  There are two small galaxies in this field,
+both of which are broken into 4 or 5 objects by the USNO catalog, but
+maintained as single objects in the Loneos pipeline.  In another
+example (not shown) a bright star within the disk of a small galaxies
+was clearly split from the galaxy by the pipeline (and also by USNO).
+
+\appendix
+\section{Parameter file params.txt}
+\begin{verbatim}
+# Configuration file for Loneos analysis pipeline
+
+# important files and directories
+GSCFILE                 /host/pikake/d1/gene/gsc/GSCregions.tbl
+GSC_DIR                 /host/pikake/d1/gene/gsc
+CATDIR                  /host/radon/rad3/gene/photcat2
+IMAGE_CATALOG           /host/radon/rad3/gene/photcat2/Images.dat
+IMAGE_CATALOG_TEMPLATE  /host/radon/rad3/gene/photcat2/template.cat
+CATALOG_TEMPLATE        /host/radon/rad3/gene/photcat2/template.cat
+ROCK_CATALOG            /host/radon/rad3/gene/photcat2/Rocks.dat
+USNO_CDROM              /host/tycho/mnt/md0/kevin/zones
+LONEOS_REGIONS          /host/pikake/h1/gene/loneos3/regions.map
+
+# parameters for "fstat"
+# instrumental mag zero point
+ZERO_PT                 24.5
+DOPHOT_CHAR_LINE        129
+DOPHOT_TYPE_FIELD       5
+DOPHOT_AP_FIELD         91
+DOPHOT_PSF_FIELD        52
+MIN_SN_FSTAT            6.0
+
+# parameters for "gastro"
+DEFAULT_RADIUS   32.0
+MINIMUM_RADIUS   1.5
+MIN_ERROR        0.6
+MIN_PRECISE      0.12
+CCD_PC1_1        1
+CCD_PC2_2        -1    # for loneos
+CCD_PC1_2        0
+CCD_PC2_1        0
+ASEC_PIX         2.82
+NFIELD           3.0
+MMIN             6.0
+ROT_ZERO         0
+dROT             1.0
+NROT             2
+POLAR_AXIS_RA    -90.0
+POLAR_AXIS_DEC   89.88
+RA_OFFSET        -90.0
+DEC_OFFSET        0.0
+
+# parameters for "addstar"
+# airmass extinction coefficient (in mag / airmass)
+NSIGMA                  3.0
+ALPHA                   0.1
+XOVERSCAN               60
+YOVERSCAN               50
+
+# parameters for "controller"
+IN_DIR                  /host/pikake/h1/gene
+OUT_DIR                 /host/pikake/h1/gene/loneos4/
+DOPHOT_PARAMS           /host/pikake/h1/gene/src/ohana/config/default_parameters
+FLATTEN_SCRIPT          /host/pikake/h1/gene/src/ohana/config/test.pro
+NEW_IMAGES              images.dat
+USERNAME                gene
+PASSWORD                gene
+
+# here we list all available machines
+NMACHINES               2
+MACHINE0                pikake.astro.washington.edu
+MACHINE1                mildew.astro.washington.edu
+
+# here we define which machines which are always free
+fMACHINE0               1
+fMACHINE1               0
+
+# here we define the machine which runs the database 
+LOCAL_MACHINE           0
+
+# parameters for "status"
+TIME_REFERENCE          90/01/01 00:00:00
+
+# parameters for "nrphot"
+# make this one small to boost change of getting an early region 
+TAU                     3.0             
+SCATTER_LIM             15.0
+MAG_LIM                 17.0
+IMAGE_SCATTER           0.075
+NIMAGE_SCATTER          1.5
+STAR_SCATTER            0.05
+
+### parameters for "markstar"
+SEARCH_RADIUS           360   # region for initial trail hunt, in arcsec 
+TRAIL_WIDTH             5.0   # expected trail width, in arcsec
+NANGLE_BINS             180   # Number of angular bins in 180 degrees
+NPTSINLINE              5     # minimum points needed for trail
+MIN_DENSITY             0.025 # minimum linear density in star/arcsec
+SPACE_SIGMA             10.0  # how much denser than average for trail?
+# parameters defining bright star exclusion regions
+BRIGHT_XTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_XTRAIL_MAG         9.5 # faintest sat. star
+BRIGHT_XTRAIL_SLOPE     -80.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_YTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_YTRAIL_MAG        11.0 # faintest sat. star
+BRIGHT_YTRAIL_SLOPE    -400.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_HALO_MAG           8.5 # faintest sat. star
+BRIGHT_HALO_SLOPE       -28.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+# parameters which define the ghosts
+GHOST_MAG               7.5
+GHOST_RADIUS            200   # in arcsec
+OPTICAL_AXIS1           2154.0
+OPTICAL_AXIS2           2193.0
+
+# parameters for "addusno"
+USNO_RADIUS             5.0   # in arcsec
+USNO_PROPER             20.0   # in arcsec
+USNO_RED                1000  # code for USNO Red data
+USNO_BLUE               1001  # code for USNO Blue data
+# /mnt/cdrom
+
+# parameters for "markrock"
+ROCK_RADIUS             2.0   # in arcsec
+ROCK_MAX_RADIUS         20.0  # in arcsec
+ROCK_MAX_SPEED          0.1   # in arcsec / sec
+\end{verbatim}
+
+\end{document}
Index: /tags/start/Ohana/doc/pipeline/pipeline4.tex
===================================================================
--- /tags/start/Ohana/doc/pipeline/pipeline4.tex	(revision 12606)
+++ /tags/start/Ohana/doc/pipeline/pipeline4.tex	(revision 12606)
@@ -0,0 +1,1520 @@
+%\documentstyle[astro,psfig]{article}
+\documentclass{article}
+\usepackage{psfig}
+\usepackage{astro}
+\usepackage{times}
+\GoodMargins
+\newcommand{\note}[1]{({\bf #1})}
+\title{Variability Pipeline}
+\author{Eugene Magnier}
+\begin{document}
+\maketitle
+
+\section{Overview}
+
+The Loneos Pipeline provides automated reduction of images, including
+photometry and astrometry, with the final data stored in a photometry
+database organized by star position on the sky.
+
+Fig.~\ref{pipeline} shows a schematic of the analysis pipeline.
+Images are written to the disk from the camera by the software which
+runs it, {\tt astrocam}.  The resulting images are FITS files (which
+may be arbitrarily sized) and have header keyword parameters RA and
+DEC specifying rough celestial coordinates.  Images are first analyzed
+by {\tt dophot}, which produces instrumental photometry and pixel
+coordinate positions for stars and other objects in the images,
+writing files with a particular format, called OBJ files in this
+discussion.  The results from {\tt dophot} are cleaned up by a program
+called {\tt fstat} which merges the header information from the image
+with the most relevant parts of the OBJ file, creating a new file with
+the CMP format.  Astrometry is performed on the CMP file with the
+program {\tt gastro}.  {\tt Gastro} makes a comparison with an
+astrometric reference database and only changes CMP header keywords as
+a result.  Finally, the processed image CMP file is added to the
+photometry database with the program {\tt addstar}.  The photometry
+database is maintained in a large number of files (CPT files), each
+representing a small region of sky.  There is no relationship between
+the image locations and the boundaries of CPT file.  All of these
+processes occur on individual image, and would typically be performed
+while the observations are occuring, or during the day following, but
+may be performed at any time to add new or archived data to the
+database.
+
+Once large batches of images have been processed, a series of programs
+should be run to clean up the photometry database.  Typically, these
+routines would be run at the end of a night on all of the CPT files to
+which new data were added.  First, {\tt markstar} identifies bad data
+(the trails of satelites, the bleeding columns from stars, ghost
+images), and flags these data points appropriately.  Second, {\tt
+  addusno} matches the catalog stars with stars from the USNO database
+and adds the USNO magnitudes to the photometry database.  Next, {\tt
+  markrock} searches for likely asteroids in the CPT file, marks them,
+and writes the asteroid observations to an asteroid database.  It also
+notes measurements which are likely to be noise and cosmic rays.
+Finally, {\tt nrphot} determines relative photometric calibrations for
+observations in a set of CPT files.  
+
+With the exception of {\tt dophot}, all of the programs in the
+pipeline refer to a single configuration file to determine the large
+number of parameters necessary in the process.  The default parameter
+file is hardwired into the programs, but an alternate configuration
+file may be specified with the environment variable {\tt
+  PIPE\_CONFIG}.  This option makes independent processing of multiple
+data sources trivial.  For example, if the pipeline is to be used for
+both Loneos and SDSS image analysis and display, there could be two
+configuration files (eg, {\tt loneos.txt} and {\tt sdss.txt}), one for
+each data source.  Several important parameters would be different
+between these two, for example, the initial plate scale guess for the
+astrometry routine, or the parameters which define the rough chip
+orientation.  This scheme allows for analysis of different types of
+images, with a common destination photometry database, or for
+independent photometry databases.
+
+\begin{figure}
+\psfig{file=schematic.eps,width=9cm}
+\caption{\label{pipeline} 
+Schematic of the photometry pipeline.  Rectangles represent programs,
+while ovals represent data products.  Arrows show the direction of
+travel of information.  The flatten routine is a filter whose position
+may change as the pipeline matures.
+}
+\end{figure}
+
+Data from different sources can be processed by the pipeline and
+stored in the same photometry database, since all photometry is tagged
+with a source ID in the database (as are the images in the image
+database).  This allows us to include, for example, the USNO catalog
+magnitude measurements (or a subset) in the photometry database for a
+quick comparion.  Different sources may be considered different
+filters, so color-color and color-magnitude diagrams could be
+extracted by specifying choices for source catalog.  Currently each
+object has a single primary photometric system, and individual
+observations may be combined to determine that average (eg, if they
+are different photometry sources with roughly the filter bandpass) or
+they may be ignored when calculating relative magnitudes (eg, the USNO
+magnitudes would be ignored).  This may be expanded upon by defining
+multiple average magnitudes and allowing different measurements to
+contribute only to the appropriate average.  The determination of the
+photometry code for a particular image is currently not well defined.
+There are several points in the analysis where the user (or the
+controlling program) may specify the photometry source.  A table
+should be kept in the photometry catalog to define the various
+photometry codes.  
+
+\section{Image Analysis Pipeline}
+\label{parallel}
+\subsection{Flat Fielding -- Mana / Flatten}
+
+Flat fielding is performed on each image after it has been written to
+disk by the acquisition software.  The processing is performed with
+mana (see mana user's guide) using a script written to work with the
+analysis pipeline processing software.  There are several important
+aspects of the script which make it work with the containing programs.
+First, the script is contained within a file, flatten.pro, in the
+references directory.  the script is invoked by calling it on the
+command line wehn mana is started.  If mana is started with a file
+name on the command line, that file is loaded with in 'input'.  The
+file defines a macro 'flatten', and also loads the flat-field file.
+The flattening process is actually done by calling within mana the
+macro flatten, with the input and output file names as arguments.  By
+loading the flat-field at the start of mana, instead of on each
+execution of flatten, we save the load time of each flat-field image
+(which is 2x the size of the basic image, being 4byte floats per
+pixel).  The location of the flat field is currently hard-wired in the
+flatten script - this should probably be changed in the future.  One
+of the aspects of this is that the macro loads a flatfield with a
+specific name and location.  This file is actually a link; The
+higher-level controlling process (stage1) creates a link to the
+correct flatfield.  This allows the analysis process to use different
+flatfields for different situations.  At LONEOS, we currently use a
+flat field generated from a well-understood night.  This is probably
+not the best solution as the flatfield changes with time.  As
+discussed below, the photometry solution program, nrphot, fits a
+high-order polynomial to the relative photometry, allowing for
+differences from the correct flatfield.
+ 
+\subsection{Photometry -- Dophot}
+
+Photometry is performed using a varient of {\tt Dophot}.  The version
+of dophot is based on Dophot 2.0, but it has been adapted to
+streamline processing of many files.  First, with this version of
+dophot, any FITS format data is safely read in.  Instead of compiling
+to a fixed maximum size, only the memory needed to contain the image
+matrix is allocated.  The image is also converted to REAL*32 from
+whatever BITPIX for processing.  Finally, only a single, complete
+parameter file is loaded by dophot.  There is no option for a modified
+and a default parameter file.  The parameter file to be used is
+defined, along with the input image and the output object list on the
+command line when the program is run: \\
+{\tt dophot image.fits image.obj parameter\_file} \\
+To achive this, the code from dophot was wrapped within a C program
+which interprets the command line arguments, allocates the necessary
+memory, and reads in the image.  The rest of the processing is
+performed by dophot in the standad manner.  Notice that we use a
+consistent naming convention through the pipeline reductions.  The
+image is called {\tt foo.fits}, while the resulting dophot-produced
+photometry list is called {\tt foo.obj}.  
+
+\subsection{Cleanup -- fstat}
+
+After an image is processed by dophot, the object file ({\tt foo.obj})
+is converted to a more-compact, more-complete file called a CMP file,
+with a name of the form ({\tt foo.cmp}).  This conversion is done with
+the program {\tt fstat}.  The CMP file consists of the FITS header
+from the original image ({\tt foo.fits}), with some additional
+keywords to be used at later stages in the analysis, followed by an
+ASCII list of the interesting data from ({\tt foo.obj}).  In this
+list, types 6 and 8 are excluded, and only the following values are
+kept:
+\begin{verbatim}
+X       Y     Mag   dMag t log(sky) 
+1342.0  106.1 14.166 000 4 3.2
+\end{verbatim}
+Objects with a signal-to-noise ratio lower than a specified cutoff
+({\tt MIN\_SN\_FSTAT}) are also excluded.  Some general information
+about the image is derived by {\tt fstat} (FWHM, saturation and
+completeness limits, number of each dophot type) and stored as
+keywords in the header.  The photometry source must be specified at
+this stage as one of the command line arguments, though the value used
+may be overridden in one of the stages belowe.  The resulting file can
+now stand on its own without reference to the original image.  The
+keywords used by {\tt fstat} include the minimum signal to noise, a
+rough guess at the zero point ({\tt ZERO\_PT}), and four numbers
+defining the format of the {\tt dophot} OBJ file.
+
+\subsection{Astrometry -- gastro}
+
+Astrometry is performed automatically by the program {\tt gastro}.
+{\tt gastro} loads a CMP file and determines an initial guess for the
+center coordinates (based on the RA and DEC header keywords).  The
+program also uses the configuration information about the plate scale
+and rough orientation of the image to get a close to the final
+solution.  Also, the true sky position of the telescope pole may be
+defined to allow astrometry on images taken close to the pole.  The
+comparison is made with the astrometric catalog, which may be the HST
+Guide Star Catalog, or it may be any source if the data is placed in
+the correct format.
+
+\section{The Photometry Database}
+
+\subsection{Photometry File Format}
+The photometry database consists of a large number of photometry files
+representing sections of the sky and a file containing information on
+the images incorporated in the database.  These files are called
+alternatively ``region files'' or CPT files (because they have the
+extension {\tt .cpt}).  The photometry files are sorted by Declination
+into different directories, each consisting of a band 7.5\degree\ 
+wide.  These directories have names like n0730, representing the band
+starting at a Declination of +07:30.  The image database (Images.dat)
+is stored in the upper level directory of this directory tree.  In
+fact, the locations of the Images.dat file, the photometry database,
+and such are all flexible and may be changed by altering the
+configuration file.
+
+The name and location of each sky region comes from the Hubble Space
+Telescope Guide Star Catalog.  There is a file, GSCregions.tbl, which
+can be used to find the region file appropriate for any location on
+the sky.  A number of routines exist to make such a query.  
+
+Each photometry file in the photometry database contains all
+observations and all average values for all stars observed within the
+appropriate region on the sky.  The identity of stars is essentially
+determined by the RA and DEC coordinates.  In very crowded regions,
+the end user may need to double check that a neighboring star is not
+contaminating individual detections (see the discusion on {\tt
+  addstar} below).
+
+The photometry files are stored in a binary format, both to reduce the
+volume and to speed access.  As a result, the interpretation of the
+data is machine dependent: little endian machines need to swap the
+data intelligently.  Fortunately, this operation is taken care of
+appropriately, if the programs are compiled with the BYTESWAP option
+set as needed, which is automatically set by the Makefile in the case
+of a Linux machine.  For reference, Suns, SGI, and HP are all big
+endian, while PCs and DECs are little endian.  The automatic
+conversion takes place by using the funcions {\tt Fread} and {\tt Fwrite}
+to substitute for the standard C library {\tt fread} and {\tt fwrite}
+functions.  {\tt Fread} and {\tt Fwrite} are told the datatype being read,
+and they know the layout of the bytes for a particular datatype.
+Anytime the definitions of the relevant structures (see below) are
+changed, {\tt Fread} and {\tt Fwrite} must be updated.  Fortunately, there
+is only one file ({\tt Fread.c}), and it has a single byteswapping
+section, making it easy to adjust the code appropriately.
+
+The format of a single photometry database file consists four
+sections:  
+\begin{itemize}
+\item {\bf header} -- this is a standard FITS header with room for comments
+  about the file or whatever.  Since the rest of the file is not a
+  standard FITS file, the SIMPLE keyword is set to False.  The three
+  necessary keywords are NSTARS, NMEAS, and NMISS, which define the
+  sizes of the next three sections.
+\item {\bf average} -- this section contains all average measurement
+  quantities for each star in the file.  There are NSTARS entries, and
+  each entry is the data from a structure of type Average (defined in
+  loneos.h, and discussed in more detail below).  Thus, the total size
+  in bytes of this section can be found by NSTARS*sizeof(Average).
+\item {\bf measure} -- this section contains the individual
+  measurements for each star in the database.  There are NMEAS
+  entries, and like the average section, each entry is a single
+  structure, in this case of type Measure (in loneos.h, see below).
+  All measurements of a single star are consecutive.  The number of
+  measurements for a single star is defined by average.Nm and the
+  starting entry for a single star is given by average.offset.
+  Therefore, the first measurement of a specific star average[500]
+  would be given by measure[average[500].offset], while the second is 
+  measure[average[500].offset + 1], and so forth.  
+\item {\bf missing} -- this section contains references to all missing
+  measurements of a star.  This means all of those occasions when an
+  image enclosed the location of a star in the database, but no star
+  was detected on the image.  Similar to the case of the measure
+  section, each star has a number of missing entries (which may be 0)
+  given by average.Nn, and the first missing entry is given by
+  average.missing.  Each missing entry value is again a structure of
+  type Missing.  Currently, the only data in the structure is the time
+  of the observation, which allows for an unambiguous recovery of the
+  image where the star was missed.
+\end{itemize}
+
+\subsubsection*{Average Structure defined in loneos.h}
+{\footnotesize
+\begin{verbatim}
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm, Nn;  /* number of measurements, missing */
+  short int Xp;               /* scatter in 1/100 arcsec (-327.67 to +327.67 valid range) */
+  short int Xm;               /* 1000*log(chisq) for magnitude measurement */
+  unsigned short int code;    /* an ID code (ie, star, ghost, satelite, etc) */
+  signed int offset;          /* offset to first measurement */
+  signed int missing;         /* offset to first missing obs */
+} Average; /* 28 bytes / Average */
+\end{verbatim} }
+The structure above defines the average data stored in the photometry
+database for each star.  Most of the entries are self-explantory, but
+some need a bit of clarification.  The two $\chi^2$ entries ({\tt Xp}
+and {\tt Xm}) are the $\chi^2$ values of the average position and the
+average magnitude.  These are stored as logarthmic quantities because
+high dynamic range is not needed.  For the magnitude, the assumption
+is that the star brightness is constant and the $\chi^2$ incorporates
+the photometric errors on each measurement.  For the postion, the
+a default constant error is used \note{True?} and again the assumption
+is that the postion is constant.  As discussed above, the values of
+{\tt Nm} and {\tt Nn} give the number of measurements and missing
+observations for this star, while the entries {\tt offset} and {\tt
+  missing} point to the first {\bf measure} and {\bf missing} entry
+for this star.  The entry {\tt M} is the current best average
+magnitude solution for this star (see the section on Relative
+Photometry).  Finally, the entry {\tt code} is an ID code for each
+object, which may define a variety of things about the object.  For
+example, if the object is known to be variable, or if the object is
+associated with a USNO star, or if the object is a measurement of an
+asteroid.  See below for details of these definitions.
+
+\subsubsection*{Measure Structure defined in loneos.h}
+{\footnotesize
+\begin{verbatim}
+typedef struct {
+  short int dR, dD;           /* 1/100 of arcsec (-327.67 to +327.67 valid range) */
+  short int M;                /* thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mcal;             /* image cal mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 to 0.255 valid range) */
+  char dophot;                /* dophot type (1-9) */
+  unsigned short int source;  /* code to identify photometry source */
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+  unsigned int average;       /* reference to corresponding average entry */
+  /* upper byte of Measure.average stores flags:
+   limit of 16,777,215 stars (Naverage) in a file (=0xFFFFFF) 
+   flags: average & 0x1000000 */
+} Measure; /* 20 bytes / Measure */
+\end{verbatim} }
+The structure above defines the individual measurement data stored for
+each observation of each star.  The first two entries, dR and dD, are
+the difference between the average coordinates for this star and the
+coordinates determined for this observation.  Clearly, if this
+residual is too large, the individual measurement will not be
+successfully matched with the average star position.  {\tt M} and {\tt
+  dM} are the instrumental magnitude and error for this measurement,
+after correction for the exposure time and a zero point (defined in
+the configuration file as ZERO\_PT).  The entry {\tt t} determines the
+time of the individual observation.  This is important not only for
+timing purposes, but also to determine the source image for this
+observation.  The time and the entry {\tt source} uniquely determine
+the image in the image database that generated this measurement.
+Furthermore, this correspondence allows for determination of the pixel
+coordinates on the chip, by going throught the image astrometry stored
+in the Image database (see below).  The entry {\tt source} is a code which
+identifies the particular CCD/Telescope/Filter setup.  Each unique
+{\tt source} should be treated as an independent filter set for the
+purposes of accurate relative photometric comparisons.  This entry
+also allows external catalog data, such as the USNO or Sloan
+photometry, to be added to the database, as desired.  The entry {\tt
+  average} is a pointer back to the {\bf average} section to allow
+determination of the star from the measurements, in addition to the
+reverse.  The bits of the upper byte of this value are reserved for
+flags used to define particular situations for this measurement.
+Possible values are:
+\begin{itemize}
+\item 1 = BLEND\_IMAGE - the star on the image matched more than one
+  catalog star
+\item 2 = BLEND\_CATALOG - the star in the catalog matched more than
+  one image star
+\item 4 = UPPER\_LIMIT - \note{not really used?}
+\item 8 = CALIBRATED - relative photometry has been performed at least
+  once.
+\end{itemize}
+The entry {\tt dophot} stores the dophot type for this particular
+measurement (1-9: four extra bits in this field).   
+Finally, the value {\tt Mcal} determines the photometric calibration
+of this specific measurment.  This value is an offset appropriate to
+this image (and if needed, this point in time and this chip position)
+to bring the observations of the stars on multiple images to a common
+system (see the section on relative photometry).
+
+\subsection{Image Database}
+
+All images for which photometry has been included in the photometry
+database also have entries in an image database.  The image database
+is (currently) a single file in the upper directory of the photometry
+database.  The name of the file is determined by the IMAGE\_CATALOG
+entry in the configuration file, and is currently set to Images.dat.
+Like the photometry database files, the image database consists of a
+FITS header followed by binary data.  There is only one type of binary
+data: each image has an entry, which is the data from a structure of
+type Image (loneos.h).  The number of images in the file is determined
+by the {\tt NIMAGES} keyword.  If the number of images becomes too
+large, extrapolation of the system to a set of image database files
+with a reference list is quite straightforeward, and could be modeled
+on the organization of the region files (eg, one image database file
+for each Declination directory).
+
+\subsubsection*{Image Structure defined in loneos.h}
+{\footnotesize
+\begin{verbatim}
+typedef struct {
+  Coords         coords;            /* 120 bytes */
+  unsigned int   tzero;             /* readout time row 0 in sec (0 - 142 years valid range) */
+  unsigned int   nstar;             /* number of stars on image */
+  short int      secz;              /* thousanths of airmass (valid range -32.000 -- 32.000) */
+  short int      NX, NY;            /* dimensions of image */
+  short int      apmifit, dapmifit; /* aperture correction and error in thousandths of mag */
+  short int      source;            /* identifier for CCD (each ever used will have a unique letter) */
+  short int      Mcal;              /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      dMcal;             /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      Xm;                /* 10*log(image chi-square) */
+  char           name[32];          /* name of original image */
+  unsigned char  detection_limit;   /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  saturation_limit;  /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  cerror;            /* astrometric error: 1/50 of arcsec (0 -- 5.12 valid range) */
+  unsigned char  fwhm_x, fwhm_y;    /* PSF terms in 25*arcsec (valid range 0.0 -- 10.2" ") */
+  unsigned char  trate;             /* 10000 * scan rate in sec/pix (0 -- 0.0256 valid range, 
+                                       typically 0.0146. this is used only to determine the time
+                                       of the observation, not to find the coordinates.  1 byte
+                                       gives 0.11 sec accuracy */
+  float          exptime;           /* exposure time, seconds */
+  char           code;              /* flag to mark an image as bad or whatever */
+  char           dummy[21];         /* extra space for the future */
+  short int      order;             /* number of terms used for Mrel */
+  short int      Mx, My;
+  short int      Mxx, Mxy, Myy;
+  short int      Mxxx, Mxxy, Mxyy, Myyy;
+  short int      Mxxxx, Mxxxy, Mxxyy, Mxyyy, Myyyy;
+} Image;  /* 240 bytes / Image */
+\end{verbatim}}
+The structure above lists all of the data stored for each image.  A
+substantial amount of information is stored for each image.  First,
+the astrometric calibration information is stored in a {\tt Coords}
+structure (see coordinate systems, above).  The upper and lower limits
+of the photometry in the database (in instrumental magnitudes) is
+stored in {\tt detection\_limit} and {\tt saturation\_limit}.  These
+values are useful for comparison for those stars where observations
+are missing.  The relationship between time and pixel coordinates is
+given by {\tt tzero} and {\tt trate}.  Drift images will have a scan
+rate stored in {\tt trate}, while staring images will have a value of
+0.0 for this entry ({\tt tzero} then applies to the whole image).
+Other important parameters are kept: the astrometric error ({\tt
+  cerror}), the airmass ({\tt secz}), the exposure time ({\tt
+  exptime}), the number of stars detected ({\tt nstar}), the FWHM
+values ({\tt fwhm\_x, fwhm\_y}), the image name ({\tt name}), and the
+size of the image ({\tt NX, NY}).  The entry {\tt source} is used as
+above to define the CCD/Telescope/Filter used for this observation.
+The entry {\tt code} is used to flag images in various ways.
+Currently, only one bit is used, to define if the image has
+unacceptable photometric scatter.  Seven extra bytes are stored for
+future additions.
+
+\subsection{Data Incorporation -- {\tt addstar}}
+
+Images which are completely processed ({\tt dophot, fstat, gastro}) are
+then incorporated into the photometry database with the program {\tt 
+addstar}.  This program decides which region files are appropriate
+for this particular image, then one-by-one adds stars from the image
+to the appropriate region file.  Stars already in the catalog are
+matched with stars in the new image purely by a positional comparison.
+In order to avoid the difficulty of comparisons in the RA and DEC
+coordinate frame, a cartesian projection is performed.  The stars from
+the image being processed and the database stars in the same area are
+projected onto a tangent plane and positional comparisons made in this
+(locally cartesian) coordinate frame.  This avoids the dangerous
+singularities at the pole and also makes the RA 0,360\degree\ boundary
+a trivial problem.  
+
+Several choices must be made in the comparison process.  If a star in
+the catalog is matched with a star in the image, the new measurements
+of that star are added to the database.  If a star in the database
+lies in the field of the image, but is not detected, this information
+is added to the list of missing data.  The only data stored in this
+case is the time and source, which is sufficient to unambiguously
+identify the source image from the image database.  This allows later
+programs to find relevant statistics from the image database, if
+necessary.  If a star is detected in the image, but is not already in
+the database, a new entry is added to the database.  In addition, the
+same ``missing data'' from all previous observations images which have
+covered this location (ie, images already in the image database) are
+included.  This last step is necessary so that the image processing
+order is not important.  
+
+Stars also run the danger of being crowded together.  Since all
+comparisons are performed on the basis of position alone, crowded
+fields may make for ambiguous cross-identifications.  A pair of stars
+are matched if the difference in their positions is less than a
+specified search radius (usually dependent on the astrometric for the
+image).  If more than one catalog stars is correlated with a star in
+an image, the new measurement is added to {\em both} catalog stars,
+and a flag is set noting that this observation had a blended IMAGE.
+Conversely, if a single catalog star is matched with more than one
+image star, both new measurements are added to the one catalog star,
+and a different flat is set, noting that this observation had a
+blended CATALOG.   
+
+\section{Catalog Update and Cleaning}
+
+Occasionally, once a large number of images have been added to the
+photometry database, a set of programs should be run to clean and
+update the CPT files.  This may best be done on CPT files after a
+night's worth of data is incorporated.  These routines define bad
+data, identify the USNO catalog stars, and search for asteroids and
+other junk.  Most of the results from these routines are the addition
+of object flags to the Average data structures (Average.code).  Most
+of these routines process data within a single CPT file at a time.
+
+\subsection{Markstar}
+
+The first of the update programs, {\tt markstar}, identifies bad data
+and flags it.  It makes three types of identifications: bright stars,
+ghost stars, and trails.  In the first case, it searches the HST guide
+star catalog for bright stars within the field of the current CPT
+file.  Three types of pixels are flagged for bright stars.  Any
+measurements within a circular region centered on the star are suspect
+(the ``halo'' of the bright star).  Second, points along the X axis
+are likely to contain flux from the diffraction spikes.  Finally,
+points along the Y axis are likely to have bleeding in addition to the
+diffraction spikes.  Each of these three regions has a different size
+and range which must be defined in the configuration file.  The
+regions are represented by a representative magnitude and a scale
+parameter.  For example, the diameter $d$ of the halo for a star with
+magnitude $m$ is defined as 
+$d = \mbox{BRIGHT\_HALO\_SLOPE} (m - \mbox{BRIGHT\_HALO\_MAG})$.  The X and
+Y axis points are defined by the length of the diffraction spike, with
+an equivalent formula, and the width of the spike.  Since these are
+each independent, there are 8 parameters to define the exclusion
+regions of bright stars.  One of the current drawbacks of this system
+is the reliance on the HST Guide Star photometry.  In the HST Guide
+Star Catalog, only one photometry band is given, so no color
+information is available.  The parameters currently used were defined
+based on a large number of bright stars, with no adjustment for the
+different effective filter system of the Loneos telescope and the HST
+GSC.  Thus, occasionally very red stars will be several magnitudes
+brighter in the real data than reported in the catalog.  As a result,
+large numbers of bad data points in these halos and spikes may be
+missed.  
+
+The second type of bad data flagged by {\tt markstar} are the trails
+from satelite and other space junk.  This portion of the program
+searches for objects which land along a line and which have a high
+linear density.  Parameters may be adjusted to define the width and
+the necessary density or number of points in the line.  Objects in
+lines are also only identified if all observations come from a common
+image.  If an object only has one measurement and it is in a trail,
+the entire Average is flagged to be bad.  However, if an object has
+many measurements and only one is bad, the object is only flagged as
+having some bad data points.  
+
+The third type of bad dat are ghost star images.  The HST GSC is
+searched for stars projected across the telescope optical axis, which
+is defined by the user.  All objects within a region of fixed size is
+marked for ghost stars brighter than a specific cutoff magnitude.
+Similar to the trails, the average is marked as bad only if all
+detections of an object are ghost images.  Otherwise, it is noted that
+some data may be bad.
+
+\subsection{Addusno}
+
+The program {\tt addusno} makes two types of identifications of stars
+with the USNO catalog.  First, it searches for coincidences within a
+small, specified radius.  The choice of this radius is somewhat
+tricky: it is important to catch the association, but also to avoid
+making too many associations.  Unfortunately, astrometric errors in
+the USNO catalog make it necessary to choose a surprisingly large
+radius of 5\asec.  To avoid making double matches (matching the two
+USNO stars to the same photometry database object), only the USNO
+object closest to the object is associated.  There are also a
+substantial number of stars with significant proper motion between the
+USNO epochs and the current date.  It is not unusual to see 8-15\asec\ 
+discrepancy for specific stars.  To catch these objects, any objects
+which do not match the USNO database, but which have more than a
+minimum number of measurements (2 or 3?) are searched for more distant
+USNO companions.  A large, user-specified radius is used for this
+search.  Of course, only USNO stars which are not already matched to
+the database may be candidates for the proper motion match.  This
+stage is suceptible to errors in that a slow-moving solar-system
+object may be associated with a faint USNO star.  For this reason,
+objects flagged as high proper motion stars should be taken with some
+caution.  Of course, during the {\tt addusno} stage, no objects
+already flagged as bad by {\tt markstar} will be matched with USNO
+stars.  
+
+\subsection{Markrock}
+
+Once stars have been identified with the USNO database, it is possible
+to search for asteroid detections.  The program {\tt markrock}
+searches within a specific CPT file for objects which are moving along
+straight lines in (X,Y,t) space.  In order for an object to be found
+by {\tt markrock}, it must have three points, each with only single
+measurements.  The third point must land within a specified distance
+of the line projected from the first two data points.  These
+comparisons are made in the three dimensional space of image position
+and time.  Also, objects are only accepted if they have a speed less
+than a threshold.  If an object is moving too fast, it will make a
+streak on each individual image and will probably be missed anyway.
+Moving objects detected in this way are flagged in the photometry
+database and are also written to a Rock database.  Currently, the Rock
+database just contains ASCII lists of the RA, DEC, Mag, and time for
+each detection.  In fact, the data are stored in pairs of detections,
+with the middle detection saved twice.  This format makes it easy to
+plot lines connecting the points using the connect-the-dots plotting
+style of status/kapa (see below).
+
+One of the current drawbacks of {\tt markrock} is the insistence on
+three observations with only 1 measurement each.  If an object is
+moving too slowly, two of the dectections of the object may be merged
+together.  Enough data is stored in the database to extract these
+individual measurements, so a more sophisticated search is possible.
+It is also currently the case that USNO proper motion stars are
+ignored, but some of these will be asteroid detections which are
+simply too close to a faint USNO stars (it has to be faint because it
+would otherwise be associated with a star in the photometry
+database).  
+
+\section{Relative Photometry -- nrphot}
+
+Once the data has been incorporated in the photometry database and the
+data validation routines have been run, it is possible to determine
+photometric solutions for all of the images.  The program which does
+this is nrphot.  It tries to find a set of solutions for each image
+which reduce both the scatter per image and the scatter per star.  To
+see how this works, we start by defining a measurement of star $j$ on
+image $i$ as $m_{i,j}$.  Every star has an apparent magnitude of
+$M_j$.  Every image has a correction magnitude of $M_i$, defined as
+$m_{i,j}= M_i + M_j$.  (USE SOME OF THE TEXT FROM THE M31 paper).  
+
+The Pipeline implementation of relative photometry includes the
+possibility for up to third order polynomial terms across the field.
+This is needed to account for the different flat fields, particularly
+between images taken with and without the red-block filter.  
+
+\begin{figure}
+\psfig{file=flags.eps,width=9cm}
+\caption{\label{flags} 
+Pictoral representation of the Average.code flags.  The lower byte
+value is used for specific definitions of object types.
+}
+\end{figure}
+
+\subsection{Data Flags}
+
+The identifications made by the above routines are noted as a set of
+flags in the Average.code structure entry.  Some of these flags are
+mutually exclusive, so a certain bit may have more than one meaning,
+depending on the value of other bits.  Figure~\ref{flags} shows a
+pictoral representation of the meaning of the different bit fields.
+The uppermost bit (bit 15) determines if the object may be considered
+a ``fixed'' star or something which has no fixed location.  If it is
+not fixed, and this bit is 1, then there are several options.  The
+second uppermost bit (bit 14) will be set if this object is one of the
+three types of bad data flagged by {\tt markstar}.  The lower byte of
+code is used to define the type of bad data: ghost, trail, or bleed.
+Thus, any datapoints determined to be a satelite trail will have a
+code value of 0xc002 (49154 decimal).  If an object is a moving
+object, but not a bad datapoint, it may be identified as a ``rock''
+(an asteroid) by the program {\tt markrock}.  In this case, the flag
+for an asteroid is turned on (bit 13).  Thus anything identified as a
+rock by {\tt markrock} will have a code value of 0xa000.  The lower
+byte of code is not yet defined for asteroids, but could be reserved
+for distinguishing different classes of asteroids (ie, on the basis of
+orbital speeds, and so forth).  Objects which are fixed may have a
+variety of possible flags.  First, an object may be identified with a
+USNO star (bit 14).  It may be found to exhibit variability (bit 13),
+implying that the relative photometry routine should ignore it.  If
+may be a transient object (bit 12).  Note that, while an object
+associated with a USNO object may not be transient, an object which is
+variable may also not be associated with a USNO object.  Thus, we need
+seperate bits for variable vs transient.  Different types of variable
+objects may be represented with different values of the lower byte.
+For example, a Cepheid may have a specific lower byte code of 0x01,
+which an RR Lyra may have a lower byte code of 0x02.  Thus a Cepheid
+associated with the USNO catalog would have a total code value of
+0x6001. Finally, any of these types of non-moving objects may have
+some bad individual measurements (bit 12) or may be found to have a
+significant proper motion (bit 11).
+
+\section{Holding it Together}
+
+The preceeding sections describe the step-by-step analysis and
+incorporation of the data from individual images.  However, the power
+of the Pipeline comes in applying it to large numbers of images.  At
+LONEOS, we are using four Pentinum II computers to analyse the roughly 200
+images that are observed each night.  
+
+It is best to think of the analysis of images occurring on groups of
+images from a given night.  Of the set of processes discussed above,
+those in section \ref{parallel} are performed on individual images
+essentially independently of the other images.  The rest of the steps,
+both the data incorporation ({\tt addstar} and the database cleaning
+routines occur on the entire batch, one image at a time.  Thus, the
+former routines can easily be run in parallel, but the latter routines
+are run in serial to avoid having two programs writing to same part of
+the database at the same time.  In this model, we would process all of
+the images from a night through the parallel stage of the analysis and
+then run the serial stage only after the entire night is finished in
+the parallel stage.  We thus have a natural division of the pipeline
+into two stages.  
+
+The implementation of the two stages involves several programs, some
+of which are specific to the LONEOS situation, and others which are
+more general.  There are two layers of programs which enable batch
+processing of many images and repeated batch processing over many
+nights.  At the highest level, are Perl scripts which choose what data
+needs to be analysed and when.  These scripts tend to be more
+dependent on the details of the LONEOS implementation. At the next
+level down, these scripts call two main C programs which run the
+images of a given night through the pipeline.  These C programs are
+more general and do not depend on the details of the LONEOS
+implementation.  A defined set of files holds a log of the nights and
+images that have been processed, both for the information of people
+who might want to monitor the progress, but also used by the programs
+to guide decisions about what to analyse next.
+
+\subsection{data and file organization}
+
+There are a set of standard locations for all of the files used and
+created by the Pipeline.  These locations have both abstract names
+used by the pipeline programs and specific definitions used in the
+LONEOS implementation.  In general, the definitions of the files are
+given in the configuration file, 'config.txt' (currently located in a
+hard-wired location, but this may soon change to the mechanism used by
+the lastest version of spicam (3.0)).  The C programs all refer to the
+config file for the definitions, but the Perl scripts currently have
+the definitions hardwired as variable names defined in the beginning
+of each file.  This should be changed to a mechanism that looks in
+the config file, perhaps implemented by a standard Perl function.
+
+Here is a list of the main directories and their meanings:
+
+logdir:         /metis/d11/logs - all log files and the files used by
+the Perl scripts to control their actions (except locks) go here.
+
+workspace:      /irene/d11/workspace - the intermediate analysis
+stages go here, and the tar, gzipped directory files stay here.
+
+dumpspace:      /pallad/d1      - used by slurp to store images
+downloaded from the tape archive.
+
+database:       /hebe/d27/database      - the result database, as also
+the locks and the Rocks.dat file.
+
+references:     /metis/d11/references   - a variety of reference data,
+including the HST GSC, the USNO catalog, the config files, and so
+forth.
+
+source:         /metis/d11/src/ohana    - all of the programs source, 
+binaries, and scripts relevant to running the Pipeline are contained
+in these directories.  
+
+\begin{verbatim}
+database: /hebe/d27/database (also in /metis/d27/database as linked directories).
+ lock files also go in this directory
+workspace: /irene/d11/workspace - temporary storage of result files
+dumpspace: /pallas/d1 - disk to store data dumped from the archive by slurp.
+scriptdir: /metis/d11/logs - all log files
+\end{verbatim}
+
+\subsection{lastnight}
+
+The first step in the process is the Perl script {\tt lastnight},
+which is highly dependent on the specifics of the LONEOS setup.  It
+looks at the disks used by the observers to write the images from a
+given night.  Images are written to a directory called
+/pallas/d[1-6]/YYMMDD where 'YYMMDD' is an abbreviation for the current
+night's date (ie, 990223).  Many files use this naming scheme, so we
+will refer to such a name as 'YYMMDD'.  All of the images are stored
+in this directory with names yyyyMMDDxxxxb.fits where yyyy is the full
+year, MM is month, DD is date, and xxxx is a sequence number.  The 'b'
+refers to the 'b' CCD, and the .fits extension is required.  The
+script {\tt lastnight} is called by a cron job scheduled for 7am on
+{\tt hebe.lowell.edu} (note that the clock on hebe is set to PST, not
+local MST - fix this some day!).  The script searches the disks
+{\tt /pallas/d[1-6]} for a directory of the right form (basically any
+directory beginning with a number).  By default, the program demands
+that the directory have the name derived from today's date, but with
+the flag -any, it will accept any directory.  It then checks to see if
+this directory has been already been analysed (ie, it is included in
+the 'processed.log' file).  If not, it lists all files in that
+directory with the right ending (*b.fits) and places these names in a
+file, {\tt /metis/d11/logs/YYMMDD.inlist}.  It also writes the name of the
+directory (along with some other data) in a file 'extracted.log'.
+When it has successfully ended and identified some data, it calls the
+next script, {\tt stage1} and then quits.
+
+\subsection{slurp}
+
+An alternative to {\tt lastnight} is the Perl script {\tt slurp},
+which looks for data on the tape archive.  This script looks at the
+tape.log file and compares it to the file 'processed.log'.  It tries
+to identify nights listed in the file 'tape.log' which have not been
+included in the 'processed.log'.  If it finds any, it tries to
+download as much of the data as will fit on the disk {\tt /pallas/d1}.
+This script is called from within the {\tt stage1} script and is
+invoked if {\tt stage1} is run without any data already in
+the file 'extracted.log'.
+
+A related pair program is the load/unload C programs which are needed
+for loading and unloading the tape jukebox.  The first, load N, takes
+tape number N and loads it into the tape drive.  The second takes the
+tape a returns it to its slot.  It is important to check on the other
+users of the tape drive to be sure it is not occupied.  This is done
+with the llock, lunlock and llockstat programs.  llockstat lists the
+devices which have been allocated.  llock lets you lock a particular
+service, etc.
+
+\subsection{stage1}
+
+The Perl script {\tt stage1} takes the image list produced by {\tt
+lastnight} or {\tt slurp} (YYMMDD.inlist) and passes the list to the
+controller program {\tt control1} which performs the parallel
+analysis.  The script has a few features to decide which files have
+been analysed through the pipeline and to what extent.  If {\tt
+stage1} is called, it should be able to figure out 1) if there is data
+ready to be analysed (ie, there is a new date reference in the file
+'extracted.log'), 2) if the data has been partially analysed (ie, the
+date reference in 'extracted.log' has not been put in 'processed.log',
+but there are entries in the file YYMMDD.outlist), and 3) which data
+needs to be run through which part of the pipeline (ie, it decides
+which of the images in YYMMDD.outlist have succeeded at which stages
+of the analysis, and starts them at the appropriate spot).  These
+features are most useful if the analysis crashes in the middle or
+needs to be restarted.  The {\tt stage1} script is meant to be run
+without any arguments and it will figure out what needs to be done.
+The one possible argument is the -once flag.  This flag tells {\tt
+stage1} to analyse the data it finds and quit when it finishes, and
+not call another instance of itself.  Otherwise, when it is done, it
+will restart itself, and since there is no new data in
+'extracted.log', it will start a slurp process to get data from the
+archive.  If there is no data in the archive either, this process will
+sleep for an hour and try again.  After a few attempts (2 days?), {\tt
+stage1} will give up and quit without restarting itself.  The script
+writes a log file called \$scriptdir/stage1.NN.log where NN is a
+number in sequence between all runs of {\tt stage1}.  A file
+stage1.count keeps track of which number NN we are on.  When {\tt
+stage1} has finished the analysis of a night's data, it writes the
+date in 'processed.log' to let other processes know what has been
+analysed.  The bulk of {\tt stage1} is not dependent on details of the
+LONEOS setup, but it does expect the files to have the naming scheme
+described above.
+
+\subsection{stage2}
+The serial stage processes are run by the Perl scrip {\tt stage2}.
+Normally, this script is always running.  It waits for the name of a
+night to be added to the 'processed.log file, presumably be {\tt
+stage1}.  Once if finds a new name in this file, it looks for the
+appropriate images in the file 'YYMMDD.addlist'.  It then submits the
+list to the second controlling program {\tt control2}, which runs the
+images through {\tt addstar}.  Images which are successfully run
+through addstar have their *bf.fits (flattened image) and *.obj
+(dophot output) files deleted.  When the entire night is done, the
+rest of the *.obj and *bf.fits images are deleted by {\tt stage2}, the
+directory with the *.cmp and *.log files is tared and gzipped into the
+file YYMMNN.tgz.  The directory is then deleted.  Finally, {\tt
+stage2} calls the scripts {\tt cleaning.pl} and {\tt run.phot} which
+runs the cleanup programs ({\tt markstar - nrphot}) on the database.
+After a successful run, {\tt stage2} will automatically respawn a new
+copy that waits until more data arrives.
+
+\subsection{control1 / control2}
+These two C-programs perform the tasks of farming the images out to
+the different machines for analysis.  The two programs are essentially
+identical, but {\tt control1} is allowed to use all machines and {\tt
+control2} can only use one (hebe.lowell.edu, which has the database
+local to it).  These controller programs start off by executing remote
+shells (using ssh) on a set of machines.  These shells are then used
+to execute the remote commands and are kept open the entire time the
+process runs.  
+
+Both control programs maintain a list of images in a set of queues.  A
+set of rules defines the order in which each image travels through the
+queues.  Each queue is associated with a single process (ie, flatten,
+astrometry, etc).  Images which successfully run through a queue are
+sent on to the defined 'next' queue, while images which fail are
+instead sent to the defined 'fail' queue.  In most cases, the 'fail'
+queue is a process which marks the image as bad and write the name in
+a file, and then puts the image in the 'done' queue.  However, it is
+possible for the 'fail' queue to be another attempt, such as in the
+case of astrometry.  In this example, images which fail the default
+astrometry are run through a second queue which tries again with the
+-loneos flag set (this flag makes the assumption that the header
+information about the LONEOS region number for the image is correct,
+not the RA/DEC information).
+
+The connections on the remote machines are handled as child processes
+with communication through the stdin and stdout/stderr pipes.
+Messages can be sent back and forth though these pipes, and messages
+which are received from a process associated with an image are written
+to a log file with the name imagename.log (where imagename is the root
+name of the image).  The only required messages from the program are
+messages saying ``SUCCESS'' or ``ERROR''.  The programs therefore all
+end with either of these words.  The programs are started within the
+controller as a command to the shell followed by and echo ``PROCESS
+DONE''.  If the controller sees the message ``PROCESS DONE'' without
+either ``SUCCESS'' or ``FAILURE'' (after waiting an appropriately long
+time), it assumes the program crashed.  Currently, no timeout is
+available for the programs.  The flat-field process is run in mana and
+is a slightly special case.  We avoid re-loading the same flat many
+times by starting a mana process once and running the flatten
+procedures as mana function calls.  The images which are analysed
+(with an indicator of success or failure at each stage) are written to
+a file named 'YYMMDD.addlist' by the {\tt control1} and 'YYMMDD.outlist'
+by {\tt control2}.
+
+\subsection{Lock files}
+
+A variety of locking mechanisms are used to avoid overwriting the
+database or running more than one version of the controlling
+programs.  There is a perl program, {\tt locks}, which allows the user to
+set or check the state of the different locks. All programs which
+write to the database check for the existence of a lock on the
+database and refuse to run if it exists.  The control1/2 programs and the
+stage1/2 programs check for their own lock files and only run if they
+don't exist.  Finally, the use can set the lock files 'kill' or 'halt'
+for either stage1 or stage2.  The first tells the process to stop
+immediately, taking care of bookkeeping first.  The second tells the
+process to finish the current set of images but not start a new
+version.  
+
+\subsection{Other Perl Scripts} 
+
+there are several other scripts which are either used to do some
+simple function or are used by the maintainer to check up / work on
+the pipeline.  The two programs 'checkoutlist' and 'checkaddlist' take
+a list of YYMMDD.outlist or YYMMDD.addlist files and list the number
+of images in the file and the number of successes at each analysis
+stage.  There programs 'cleaning.pl' and 'run.phot' deal with the
+cleanup programs and the running of nrphot.  the program
+'backup.stuff' take the first 4 characters of the year/month file
+names and backs up to the jukebox tape all tar files for the given
+month.
+
+\section{Operational Issues and Subtleties}
+
+The current LONEOS system runs principally on four Intel machines
+under linux.  The existing system has been generally quite stable over
+the past year of operation, but there are some subtleties.  One
+significant issue is the RAID disk attached to hebe.lowell.edu.  This
+device is a set of three 9 GB disks merged into one 27GB raid disk.
+The database is stored mostly on this dist and the RAID disk mounted
+on metis.  It is easy to split the database across multiple file
+systems by using links.  Within the database directory, there are
+directories for each of 24 Declination bands (7.5 degrees tall).  The
+easiest way of splitting up the data is to move some of these
+subdirectories to another device and creating links to them at the
+appropriate place.  This is currently done by having a directory
+/metis/d27/database with the remote directories.  
+
+The current problem with the /hebe/d27 RAID results from the poor way
+it was setup.  It was set up without much knowledge of the (at the
+time) rather rudimentary linux RAID system.  As a result, the
+implementation is such that the disk will not automatically be
+configured and mounted at boot time.  There is a script /root/mdstart
+which lists the step to setup the RAID correctly.  It would be helpful
+if the rc.local or rc.sysinit files were fixed to start, fsck and
+mount the RAID automatically at boot.  The setup on metis is
+substantially more mature and is correctly implemented.  It comes up
+when the machine boots.
+
+\section{Visualization -- Status}
+
+Visualization of the data in the photometry database can best be
+performed with the program {\tt status}.  This is a command-line
+driven program with a math and macro language which makes it easy to
+perform complex tasks.  
+
+First, a few notes about the user interface.  The interface has an
+interaction similar to {\tt tcsh}.  The arrows allow editing of
+previous commands.  You can also use emacs-like commands such as
+cntl-a to reach the beginning of the line and cntl-e to reach the end.
+There is command and file completion: if you type part of a command
+(as the first thing on a line) and then type tab, it will fill in as
+much as possible, until the word is not unique.  Typing tab twice at
+that point will list the possible endings.  For any but the first word
+on a line, the same thing will happen for the files in the current
+directory.  It is also possible to type just a fraction of a command,
+as long as it is unique.  An ambiguous command will list the possible
+alternatives.  For example:
+\begin{verbatim}
+status: c
+ambiguous command: c ( catalog cgrid clear create cursor )
+\end{verbatim}
+
+The shell is essentially an interpretive programming language.
+Variables are set as follows:
+\begin{verbatim}
+status: $fred = 10
+\end{verbatim}
+Any expression within curly brackets \{\} is assumed
+to be an arithmetical expression and is evaluated before the line is
+executed.  For example:
+\begin{verbatim}
+echo {$fred*dcos(45)}
+\end{verbatim}
+would give the response 7.07107.  There are math functions cos, sin,
+and tan, which operate on radian expressions, and also dcos, dsin,
+dtan, which operate on degree expressions.  There are also the
+equivalent inverse functions: eg., asin and dasin return radians and
+degrees, respectively.  The help section on Math defines all of the
+available math functions.  
+
+\subsection{Miscellaneous Commands}
+\begin{verbatim}
+!                         -- system call
+?                         -- list commands 
+??                        -- list variables 
+echo                      -- type this line 
+exec                      -- system call
+exit                      -- exit program 
+help                      -- get help on a function 
+output                    -- redirect output to file
+quit                      -- exit program 
+scan                      -- scan line from keyboard or file to variable 
+wait                      -- wait until return is typed
+which                     -- show command 
+\end{verbatim}
+Most of these are self-explanatory.  The command ?? prints the system
+variables.  The {\tt help} command will provide help on a single
+command or, without any arguments, will list all available help
+files (this includes general help not associated with a specific
+command).  
+
+\subsection{Shell Programing}
+\begin{verbatim}
+break                     -- escape from function 
+for                       -- loops 
+if                        -- logical cases 
+input                     -- read command lines from a file 
+macro                     -- deal with the macros 
+\end{verbatim}
+
+There are several options for programming in {\tt status}.  First, a
+file which contains a series of commands can be executed with {\tt
+  input (filename)}.  It is also possible to define macros which will
+behave much like regular commands.  A macro is defined by typing {\tt
+  macro name} or {\tt macro create name} followed by the commands.
+Arguments to the macro are assigned to the variables \$1 .. \$N and
+the number of arguments is given by \$0.  Macros may be defined in
+{\tt input} files, and in fact when {\tt status} is started, it loads
+the file {\tt \~/.statusrc} which may contain default macros.  Simple
+loops and if statements can be performed, and are quite useful for
+complex macros.  
+
+``If'' statements are similar in syntax to C if statements, but only
+the following logical operators are available: $>$, $<$, $=$, !, $|$,
+and \&.  Notice that (currently) there is no $>=$ or $<=$ symbol.  The
+operator ! means ``not equal to'', but cannot be used to negate a
+logical value.  The operators $|$ and \& have the meaning of ``or'' and
+``and'' respectively.  Math expresions in the if statement must be
+contained in curly braces, as elsewhere.  Variables with string values
+may use the logical $=$ operator to test if two strings are the same.
+``For'' loops are quite simplistic.  The form is:
+\begin{verbatim}
+for var first last delta
+ (commands)
+end
+\end{verbatim}
+The value of {\tt \$var} will start at the value {\tt first} and increment by
+{\tt delta} after each loop.  The loop will stop after {\tt \$var} is greater
+than {\tt stop}.  The value {\tt delta} is optional, with 1 assumed.
+The value of {\tt \$var} may be changed during the loop, and if set
+beyong the value of {\tt last} will end the loop early.  
+
+\subsection{Vector Plotting}
+
+\begin{verbatim}
+box                       -- draw a box on the plot
+clear                     -- erase plot
+create                    -- create a new vector
+cursor                    -- get coords from cursor
+grid                      -- plot cartesian grid
+hist                      -- create histogram from a vector
+labels                    -- define labels for plot
+limits                    -- define plot limits
+plot                      -- plot a pair of vectors
+print                     -- write vectors to file
+ps                        -- define labels for plot
+set                       -- vector math
+style                     -- set the style for graph plots
+vectors                   -- list vectors
+zplot                     -- plot scaled points 
+\end{verbatim}
+
+In addition to scalar variables, {\tt status} can manipulate and
+display 1-D vector variables.  Many of the commands which extract data
+from the photometry database place the data in vectors as well as
+plotting them.  A vector can also be created based on a number
+sequence with the command {\tt create name Nelements start delta}.
+The resulting vector has $Nelements$ entries, starting at a value of
+$start$ and running until $start + delta*Nelements$.  If $delta$ is
+0.0, all elements will have the value of $start$.  A histogram of a vector
+may be made with the command {\tt hist}, which creates a new vector
+containing the histogram of the first vector.  The data range and bin
+size of the histogram are defined in same way as with create.  This
+makes it easy to create the index vector that goes with a histogram
+vector:  
+\begin{verbatim}
+hist y Ny 1 100 0.1
+create dx 1 100 0.1
+\end{verbatim}
+The above will create a histogram of y in Ny and the index in dx.
+Plotting this with {\tt plot dx Ny} will show the histogram.
+
+Vector math is performed with a command of the form {\tt set new =
+  (expression)}.  The expression is some math function employing
+vectors and scalars.  A complete listing of the math operators
+available in {\tt set} can be found in the help for {\tt set}.
+
+Once vectors are defined, they may be plotted.  A pair of vectors can
+be plotted against each other if they have the same number of entries.
+The plotting is performed on the graphics window, Kapa.  There are
+actually several graphics windows available to {\tt status}, any of
+which may be used to plot at any time.  Some of the more complex
+operations default to either graphics window 0 or 1, depending on the
+context.  Except for those functions with a pre-defined window, all
+plotting functions apply to the current graphics window unless an
+option {\tt -n N} is given to specify a different window.  The
+plotting style is determined by the command {\tt style} which can set
+the line width, the line type (solid, dashed, dotted, etc), the point
+type (box, cross, etc), the point size, the color, and whether a pair
+of vectors is plotted as a sequence of points, a set of connected
+lines, or a histogram.  Some functions which make plots use their own
+styles, as discussed below.  The function {\tt limits} lets the user
+set the range of the plot axes, or check the current setting.  The
+command {\tt plot} will plot a pair of vectors on the current graphics
+window using the current plotting style for that window.  The command
+{\tt zplot} will plot a pair of vectors with the point size scaled by
+a third vector, with maximum and minimum point sizes representing
+specified values.  The {\tt cursor} command goes the other way: this
+command puts the Kapa window in cursor mode and waits for input from
+Kapa.  The user can then type any alphanumeric key on the graphics
+windows and will be told both the pointer location (in the graphics
+coordinates) and will have the coordinates stored in {\tt status}
+variables.  For example, by typing ``1'' in the sky display window,
+the RA and DEC of the pointer are stored in the variables {\tt \$R1}
+and {\tt \$D1}.  This command can be used to let the user define
+locations or regions of interest on the Kapa window. (Future addition:
+{\tt button}, which does the same with the mouse buttons).  
+
+\subsection{Database Functions}
+
+\begin{verbatim}
+gcat                        -- get catalog at location
+gimages                     -- get images at location
+gstar                       -- get star statistics
+extract                     -- extract average vectors from catalogs
+mextract                    -- extract measurement vectors from catalogs
+imstats                    -- plot image statistics
+imextract                   -- extract image vectors from database
+lcat                        -- list catalogs in display region
+cmatch                      -- match two catalogs
+\end{verbatim}
+
+There are a variety of other commands which directly refer to the
+photometry database.  Some of these functions extract data of various
+types from the database, others perform more complex plotting
+operations.  The commands listed above are those which simply extract
+data from the database.  The first three list information relevant to
+a specific RA, DEC location on the sky: {\tt gcat (RA) (DEC)} lists
+the catalog at the specified location and places the name in the
+variable {\tt \$CATNAME}, {\tt gimages (RA) (DEC)} lists all images
+which overlap the specified location, , {\tt gstars (RA) (DEC)
+  (RADIUS)} lists data about the stars within a specified radius of
+the specified location (all numbers above are given in decimal
+degrees).  Similarly, {\tt lcat} lists the catalogs in the region.
+Imstats lists statistics about each image
+
+The next three commands extract a specific piece of information from
+the photometry database and places it in a vector.  First, {\tt
+  extract} will extract average values for each star and place it in a
+vector.  Next, {\tt mextract} will extract measurement values for each
+star and place it in a vector: as a result a single star may have
+multiple entries in the measurement vectors.  Finally, {\tt imextract}
+will extract image statistics into vectors (not yet implemented).
+
+
+\begin{verbatim}
+catalog                    -- plot catalog stars
+cgrid                      -- plot sky coordinate grid
+cplot                      -- plot vectors in sky coordinates
+czplot                     -- plot scaled vectors in sky coordinates
+images                     -- plot image boxes
+imdense                    -- image density plot
+lcurve                     -- plot lightcurve for a star
+pcat                       -- plot catalog boundaries
+region                     -- define sky region for plot
+resid                      -- plot residuals
+simage                     -- plot stars in an image
+\end{verbatim}
+
+There are two types of database plotting functions: those that display
+or refer to the spatial charateristics of the data and those that
+refer to other types of charatersitics, such as the time domain.  The
+graphics window 0 is reserved for all plots of objects on the sky.
+The command {\tt region} defines the current sky coordinates for plots
+in graphic window 0.  The command {\tt pcat} plots the outline of all
+photometry database files which are within the currently defined
+region (and by default, only those with data).  {\tt images} plots the
+outline of the images in the image database, while {\tt imdense} shows
+the number of images at a location by randomly spacing dots within the
+boundary of the images.  The command {\tt cgrid}
+draws a grid in celestial coordinates on the for the current region.
+
+The most complex, but also one of the most useful command is {\tt
+  catalog}, which plots the positions of stars in the photometry
+database (and others) on the sky.  There are many options to this
+command.  One set allows the user to plot stars from the photometry
+database (the default), from the HST GSC, or from an ASCII text file
+with RA, DEC, and Mag in specified columns.  If the ASCII file has a
+fixed number of bytes per line, the data can be more quickly loaded.
+The size of the points may be scaled by the star magnitude, by the
+number of observations of the star, or by the number of missing
+datapoints for the star.  In addition, points may be plotted only if
+they land in specified magnitude ranges, or with specified numbers of
+measurements, or missed measurements.  Also, objects may be plotted
+only if they have a specified Average.code, so that only asteroids or
+only perfect stars may be plotted.  The plotted vectors may be saved,
+if desired, and the source catalog epoch may be specified as different
+from J2000 (only valid for ASCII data).
+
+Several other commands relate to non-spatial charateristics of images
+and stars.  {\tt lcurve} will plot a light curve for all stars within
+some radius of a point.  {\tt resid} plots the photometry residuals
+for a particular region file.  
+
+\section{Some Examples}
+
+\begin{figure}
+\psfig{file=allsky.ps,width=16cm}
+\caption{\label{allsky} 
+Map of the entire sky, and images added to database.
+}
+\end{figure}
+
+Fig.~\ref{allsky} shows a map of the entire sky, and the location
+of the images currently in the database.  This picture was made with
+the following commands: (output is not shown) \\
+\begin{verbatim}
+status: region 0 0 90 gls
+status: cgrid
+status: style -lw 2 -c red 
+status: images
+status: ps
+\end{verbatim}
+In this example, on the graphics window, the image boxes are shown in
+red.  The user now has the possiblitiy of using the cursor command to
+narrow in on a specific region, and so forth.  
+
+\begin{figure}
+\psfig{file=catalog.ps,width=9cm}
+\caption{\label{catalog} 
+Comparison between HST GSC and photometry database astrometry. 
+}
+\end{figure}
+
+Fig.~\ref{catalog} shows an example comparison of the photometry
+database star positions and the HST Guide Star Catalog star
+positions.  The crosses are from the photometry database while the
+boxes are from the HST GSC.  The size of both points is a function of
+brightness.  This plot was made with the following commands (starting
+from the previous image):
+\begin{verbatim}
+status: cursor  (typed 1 on region of interest)
+1 137.097858 22.698305
+q 137.097858 22.698305
+status: region $R1 $D1 0.5 TAN
+status: cgrid
+status: box
+status: style -pt 0 
+status: gcat $R1 $D1 
+  0 n2230/1951.cpt *
+status: catalog n2230/1951.cpt -m 12 18
+status: style -pt 2
+status: catalog n2230/1951.cpt -m 12 18 -g
+\end{verbatim}
+
+\begin{figure}
+\psfig{file=lightcurve.ps,width=9cm}
+\caption{\label{lightcurve} 
+Lightcurve for several image stars.
+}
+\end{figure}
+
+Fig.~\ref{lightcurve} shows an example lightcurve from three stars in
+the above field.  The x axis shows the time in seconds, which the y
+axis shows the star magnitudes.  This plot was made with the following commands (starting
+from the previous image):
+{\footnotesize
+\begin{verbatim}
+status: cursor
+1 137.062562 22.791860
+q 137.062562 22.791860
+status: lcurve $R1 $D1 0.01 -l
+status: box
+status: gstar $R1 $D1 0.01
+read 11318 stars from catalog file /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt (22462 total measurements)
+508 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.068619 22.785400 18.438000  1 (2)  1.000000 1.000000
+498 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.062820 22.792747 12.882000  3 (0)  1.000000 1.000000
+501 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.064499 22.800817 15.480000  3 (0)  1.000000 1.000000
+\end{verbatim}}
+The last lines show the database information on the three stars.  
+
+\section{Software Distribution}
+
+All of the code, binaries, and scripts for the Pipeline are stored in
+the ohana tree at /metis/d11/src/ohana.  The ohana directory contains
+subdirs of bin, lib, include, src, config, and doc.  There is a
+Makefile at the top level which calls lower-level Makefiles to build
+the programs desired.  One of the important concepts in the ohana
+distribution is the design of the directory layout to enable binary
+support for multiple architectures.  The Makefiles use the environment
+variable ARCH to determine the appropriate architecture.  The binary
+and library files are stored in subdirectories of the form bin/\$ARCH
+and lib/\$ARCH.  It is therefore necessary that users of the ohana
+system architecture define the ARCH variable correctly.  It is also
+necessary to include in the user's PATH the directory
+/metis/d11/ohana/bin/\$ARCH.  At LONEOS,
+with the solaris sparc station and the linux machines both in use,
+ARCH can take on the values of 'linux' and 'sol'.  The values 'sun4',
+'irix', and 'hp' have also been used at various sites.  A simple bit
+of csh script in the users .cshrc or equivalent can make this
+assignment transparently:
+
+\begin{verbatim}
+set sys=`uname -s` 
+switch ($sys)
+ case IRIX64:
+   setenv ARCH irix;
+   breaksw;
+ case SunOS:
+   set ver=`uname -r | awk '{print substr($1,1,1)}'`;
+   if ($ver == 5) then
+     setenv ARCH sol
+   else 
+     setenv ARCH sun4
+   endif
+   breaksw;
+ case Linux:
+   setenv ARCH linux;
+   breaksw;
+ default:
+   echo "unknown architecture";
+   setenv ARCH unknown;
+   breaksw;
+endsw
+\end{verbatim}
+
+The Makefiles use the ARCH variable not only for destination
+directories, but also for destination binary names.  All files of the
+form fred.c are compiled to fred.ARCH.o (instead of fred.o), 
+uninstalled libraries get the names libfred.ARCH.a (instead of
+libfred.a), while uninstalled programs are called fred.ARCH.  
+
+The perl scripts are kept in ohana/src/perl, with links to the
+appropriate bin directories.  All programs are stored in directories
+of the form ohana/src/program.  The exceptions are gastro (stored in
+ohana/src/astro), and control1/2 (stored in ohana/src/astro).  Also, a
+variety of simple, user-level functions are available in
+ohana/src/misc. 
+
+Most of the ohana package of programs use several common libraries.
+These include the readline library (except for dophot, this is the only
+part of ohana that is not written by Eugene Magnier), which is used
+for command-line interface systems.  Other important libraries are the
+fits library for implementing the FITS specifications in a convenient
+C-friendly environment, and the ohana library, consisting of basic
+string and other basic operations.  
+
+For more details on the programming aspects of parts of the pipeline,
+see the associated document, 'A Programmer's Guide to the Loneos
+Pipeline'
+
+\section {Comparison with USNO catalog}
+
+I have made several comparisons between the USNO catalog and results
+from running images from Loneos through the photometry pipeline.  In
+general, there is a good agreement between the astrometry of the two
+datasets.  There are specfic areas where the two disagree, however.
+First, as discussed above, the USNO star positions may be
+significantly different from the observed star positions simply
+because of proper motion.  The first picure in the ``Comparisons
+between Loneos + USNO'' pages shows several stars with significant
+proper motion.  These are currently being flagged in the photometry
+database as discussed.  Other differences evident in this first
+picture include the classification of bright stars and the splitting
+of faint and bright stars.  In the upper right of the image, two
+bright stars are visible, one of which is actually a double.  The USNO
+catalog does a good job of detecting both, but it also detects and
+includes as stars several diffraction spike points.  The HST GSC only
+detected a single point and did not split the star at all.  The Loneos
+data in our pipeline did not detect the star at all due to saturation.
+A star in the upper left corner shows the ability of {\tt dophot} in
+the Loneos pipeline to split double stars.  This star is, on close
+inspection, clearly a double.  The USNO catalog only detects one.  The
+Pipeline not only splits the two stars, but it also makes the correct
+cross-identification of the stars.  
+
+The second set of pictures shows the ability of the Loneos pipeline to
+deal with small galaxies.  There are two small galaxies in this field,
+both of which are broken into 4 or 5 objects by the USNO catalog, but
+maintained as single objects in the Loneos pipeline.  In another
+example (not shown) a bright star within the disk of a small galaxies
+was clearly split from the galaxy by the pipeline (and also by USNO).
+
+\appendix
+\section{Parameter file params.txt}
+{\footnotesize
+\begin{verbatim}
+# Configuration file for Loneos analysis pipeline
+
+# important files and directories
+GSCFILE                 /host/pikake/d1/gene/gsc/GSCregions.tbl
+GSC_DIR                 /host/pikake/d1/gene/gsc
+CATDIR                  /host/radon/rad3/gene/photcat2
+IMAGE_CATALOG           /host/radon/rad3/gene/photcat2/Images.dat
+IMAGE_CATALOG_TEMPLATE  /host/radon/rad3/gene/photcat2/template.cat
+CATALOG_TEMPLATE        /host/radon/rad3/gene/photcat2/template.cat
+ROCK_CATALOG            /host/radon/rad3/gene/photcat2/Rocks.dat
+USNO_CDROM              /host/tycho/mnt/md0/kevin/zones
+LONEOS_REGIONS          /host/pikake/h1/gene/loneos3/regions.map
+
+# parameters for "fstat"
+# instrumental mag zero point
+ZERO_PT                 24.5
+DOPHOT_CHAR_LINE        129
+DOPHOT_TYPE_FIELD       5
+DOPHOT_AP_FIELD         91
+DOPHOT_PSF_FIELD        52
+MIN_SN_FSTAT            6.0
+
+# parameters for "gastro"
+DEFAULT_RADIUS   32.0
+MINIMUM_RADIUS   1.5
+MIN_ERROR        0.6
+MIN_PRECISE      0.12
+CCD_PC1_1        1
+CCD_PC2_2        -1    # for loneos
+CCD_PC1_2        0
+CCD_PC2_1        0
+ASEC_PIX         2.82
+NFIELD           3.0
+MMIN             6.0
+ROT_ZERO         0
+dROT             1.0
+NROT             2
+POLAR_AXIS_RA    -90.0
+POLAR_AXIS_DEC   89.88
+RA_OFFSET        -90.0
+DEC_OFFSET        0.0
+
+# parameters for "addstar"
+# airmass extinction coefficient (in mag / airmass)
+NSIGMA                  3.0
+ALPHA                   0.1
+XOVERSCAN               60
+YOVERSCAN               50
+
+# parameters for "controller"
+IN_DIR                  /host/pikake/h1/gene
+OUT_DIR                 /host/pikake/h1/gene/loneos4/
+DOPHOT_PARAMS           /host/pikake/h1/gene/src/ohana/config/default_parameters
+FLATTEN_SCRIPT          /host/pikake/h1/gene/src/ohana/config/test.pro
+NEW_IMAGES              images.dat
+USERNAME                gene
+PASSWORD                gene
+
+# here we list all available machines
+NMACHINES               2
+MACHINE0                pikake.astro.washington.edu
+MACHINE1                mildew.astro.washington.edu
+
+# here we define which machines which are always free
+fMACHINE0               1
+fMACHINE1               0
+
+# here we define the machine which runs the database 
+LOCAL_MACHINE           0
+
+# parameters for "status"
+TIME_REFERENCE          90/01/01 00:00:00
+
+# parameters for "nrphot"
+# make this one small to boost change of getting an early region 
+TAU                     3.0             
+SCATTER_LIM             15.0
+MAG_LIM                 17.0
+IMAGE_SCATTER           0.075
+NIMAGE_SCATTER          1.5
+STAR_SCATTER            0.05
+
+### parameters for "markstar"
+SEARCH_RADIUS           360   # region for initial trail hunt, in arcsec 
+TRAIL_WIDTH             5.0   # expected trail width, in arcsec
+NANGLE_BINS             180   # Number of angular bins in 180 degrees
+NPTSINLINE              5     # minimum points needed for trail
+MIN_DENSITY             0.025 # minimum linear density in star/arcsec
+SPACE_SIGMA             10.0  # how much denser than average for trail?
+# parameters defining bright star exclusion regions
+BRIGHT_XTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_XTRAIL_MAG         9.5 # faintest sat. star
+BRIGHT_XTRAIL_SLOPE     -80.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_YTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_YTRAIL_MAG        11.0 # faintest sat. star
+BRIGHT_YTRAIL_SLOPE    -400.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_HALO_MAG           8.5 # faintest sat. star
+BRIGHT_HALO_SLOPE       -28.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+# parameters which define the ghosts
+GHOST_MAG               7.5
+GHOST_RADIUS            200   # in arcsec
+OPTICAL_AXIS1           2154.0
+OPTICAL_AXIS2           2193.0
+
+# parameters for "addusno"
+USNO_RADIUS             5.0   # in arcsec
+USNO_PROPER             20.0   # in arcsec
+USNO_RED                1000  # code for USNO Red data
+USNO_BLUE               1001  # code for USNO Blue data
+# /mnt/cdrom
+
+# parameters for "markrock"
+ROCK_RADIUS             2.0   # in arcsec
+ROCK_MAX_RADIUS         20.0  # in arcsec
+ROCK_MAX_SPEED          0.1   # in arcsec / sec
+\end{verbatim}}
+
+\end{document}
Index: /tags/start/Ohana/doc/pipeline/pipeline5.tex
===================================================================
--- /tags/start/Ohana/doc/pipeline/pipeline5.tex	(revision 12606)
+++ /tags/start/Ohana/doc/pipeline/pipeline5.tex	(revision 12606)
@@ -0,0 +1,1990 @@
+%\documentstyle[astro,psfig]{article}
+\documentclass{article}
+\usepackage{psfig}
+\usepackage{astro}
+\usepackage{times}
+\GoodMargins
+\newcommand{\note}[1]{({\bf #1})}
+\title{Variability Pipeline}
+\author{Eugene Magnier}
+\begin{document}
+\maketitle
+
+\section{Overview}
+
+The Loneos Pipeline provides automated reduction of images, including
+photometry and astrometry, with the final data stored in a photometry
+database organized by star position on the sky.
+
+Fig.~\ref{pipeline} shows a schematic of the analysis pipeline.
+Images are written to the disk from the camera by the software which
+runs it, {\tt astrocam}.  The resulting images are FITS files (which
+may be arbitrarily sized) and have header keyword parameters RA and
+DEC specifying rough celestial coordinates.  Images are first analyzed
+by {\tt dophot}, which produces instrumental photometry and pixel
+coordinate positions for stars and other objects in the images,
+writing files with a particular format, called OBJ files in this
+discussion.  The results from {\tt dophot} are cleaned up by a program
+called {\tt fstat} which merges the header information from the image
+with the most relevant parts of the OBJ file, creating a new file with
+the CMP format.  Astrometry is performed on the CMP file with the
+program {\tt gastro}.  {\tt Gastro} makes a comparison with an
+astrometric reference database and only changes CMP header keywords as
+a result.  Finally, the processed image CMP file is added to the
+photometry database with the program {\tt addstar}.  The photometry
+database is maintained in a large number of files (CPT files), each
+representing a small region of sky.  There is no relationship between
+the image locations and the boundaries of CPT file.  All of these
+processes occur on individual images, and would typically be performed
+while the observations are occuring, or during the day following, but
+may be performed at any time to add new or archived data to the
+database.
+
+Once large batches of images have been processed, a series of programs
+should be run to clean up the photometry database.  Typically, these
+routines would be run at the end of a night on all of the CPT files to
+which new data were added.  First, {\tt markstar} identifies bad data
+(the trails of satelites, the bleeding columns from stars, ghost
+images), and flags these data points appropriately.  Second, {\tt
+  addusno} matches the catalog stars with stars from the USNO database
+and adds the USNO magnitudes to the photometry database.  Next, {\tt
+  markrock} searches for likely asteroids in the CPT file, marks them,
+and writes the asteroid observations to an asteroid database.  It also
+notes measurements which are likely to be noise and cosmic rays.
+Finally, {\tt nrphot} determines relative photometric calibrations for
+observations in a set of CPT files.  
+
+With the exception of {\tt dophot}, all of the programs in the
+pipeline refer to a single configuration file to determine the large
+number of parameters necessary in the process.  The default parameter
+file is hardwired into the programs, but an alternate configuration
+file may be specified with the environment variable {\tt
+  PIPE\_CONFIG}.  This option makes independent processing of multiple
+data sources trivial.  For example, if the pipeline is to be used for
+both Loneos and SDSS image analysis and display, there could be two
+configuration files (eg, {\tt loneos.txt} and {\tt sdss.txt}), one for
+each data source.  Several important parameters would be different
+between these two, for example, the initial plate scale guess for the
+astrometry routine, or the parameters which define the rough chip
+orientation.  This scheme allows for analysis of different types of
+images, with a common destination photometry database, or for
+independent photometry databases.
+
+\begin{figure}
+\psfig{file=schematic.eps,width=9cm}
+\caption{\label{pipeline} \small
+  Schematic of the photometry pipeline.  Rectangles represent
+  programs, while ovals represent data products.  Arrows show the
+  direction of travel of information.  The flatten routine is a filter
+  whose position may change as the pipeline matures.  }
+\end{figure}
+
+Data from different sources can be processed by the pipeline and
+stored in the same photometry database, since all photometry is tagged
+with a source ID in the database (as are the images in the image
+database).  This allows us to include, for example, the USNO catalog
+magnitude measurements (or a subset) in the photometry database for a
+quick comparion.  Different sources may be considered different
+filters, so color-color and color-magnitude diagrams could be
+extracted by specifying choices for source catalog.  Currently each
+object has a single primary photometric system, and individual
+observations may be combined to determine that average (eg, if they
+are different photometry sources with roughly the filter bandpass) or
+they may be ignored when calculating relative magnitudes (eg, the USNO
+magnitudes would be ignored).  This may be expanded upon by defining
+multiple average magnitudes and allowing different measurements to
+contribute only to the appropriate average.  The determination of the
+photometry code for a particular image is currently not well defined.
+There are several points in the analysis where the user (or the
+controlling program) may specify the photometry source.  A table
+should be kept in the photometry catalog to define the various
+photometry codes.  
+
+\section{Image Analysis Pipeline}
+\label{parallel}
+\subsection{Flat Fielding -- Mana / Flatten}
+
+Flat fielding is performed on each image after it has been written to
+disk by the acquisition software.  The processing is performed with
+mana (see mana user's guide) using a script written to work with the
+analysis pipeline processing software.  There are several important
+aspects of the script which make it work with the containing programs.
+First, the script is contained within a file, flatten.pro, in the
+references directory.  The script is invoked by calling it on the
+command line when mana is started.  If mana is started with a file
+name on the command line, that file is loaded with in 'input'.  The
+file defines a macro 'flatten', and also loads the flat-field file.
+The flattening process is actually done by calling within mana the
+macro flatten, with the input and output file names as arguments.  By
+loading the flat-field at the start of mana, instead of on each
+execution of flatten, we save the load time of each flat-field image
+(which is 2x the size of the basic image, being 4byte floats per
+pixel).  \note{The location of the flat field is currently hard-wired in the
+flatten script - this should probably be changed in the future.}  One
+of the aspects of this is that the macro loads a flatfield with a
+specific name and location.  This file is actually a link; The
+higher-level controlling process (stage1) creates a link to the
+correct flatfield.  This allows the analysis process to use different
+flatfields for different situations.  At LONEOS, we currently use a
+flat field generated from a well-understood night.  This is probably
+not the best solution as the flatfield changes with time.  As
+discussed below, the photometry solution program, nrphot, fits a
+high-order polynomial to the relative photometry, allowing for
+differences from the correct flatfield.
+ 
+\subsection{Photometry -- Dophot}
+
+Photometry is performed using a varient of {\tt Dophot}.  The version
+of dophot is based on Dophot 2.0, but it has been adapted to
+streamline processing of many files.  First, with this version of
+dophot, any FITS format data is safely read in.  Instead of compiling
+to a fixed maximum size, only the memory needed to contain the image
+matrix is allocated.  The image is also converted to REAL*32 from
+whatever BITPIX for processing.  Finally, only a single, complete
+parameter file is loaded by dophot.  There is no option for a modified
+and a default parameter file.  The parameter file to be used is
+defined, along with the input image and the output object list on the
+command line when the program is run: \\
+{\tt dophot image.fits image.obj parameter\_file} \\
+To achive this, the code from dophot was wrapped within a C program
+which interprets the command line arguments, allocates the necessary
+memory, and reads in the image.  The rest of the processing is
+performed by dophot in the standad manner.  Notice that we use a
+consistent naming convention through the pipeline reductions.  The
+image is called {\tt foo.fits}, while the resulting dophot-produced
+photometry list is called {\tt foo.obj}.  
+
+\subsection{Cleanup -- fstat}
+
+After an image is processed by dophot, the object file ({\tt foo.obj})
+is converted to a more-compact, more-complete file called a CMP file,
+with a name of the form ({\tt foo.cmp}).  This conversion is done with
+the program {\tt fstat}.  The CMP file consists of the FITS header
+from the original image ({\tt foo.fits}), with some additional
+keywords to be used at later stages in the analysis, followed by an
+ASCII list of the interesting data from ({\tt foo.obj}).  In this
+list, types 6 and 8 are excluded, and only the following values are
+kept:
+\begin{verbatim}
+X       Y     Mag   dMag t log(sky) 
+1342.0  106.1 14.166 000 4 3.2
+\end{verbatim}
+Objects with a signal-to-noise ratio lower than a specified cutoff
+({\tt MIN\_SN\_FSTAT}) are also excluded.  Some general information
+about the image is derived by {\tt fstat} (FWHM, saturation and
+completeness limits, number of each dophot type) and stored as
+keywords in the header.  The photometry source must be specified at
+this stage as one of the command line arguments, though the value used
+may be overridden in one of the stages belowe.  The resulting file can
+now stand on its own without reference to the original image.  The
+keywords used by {\tt fstat} include the minimum signal to noise, a
+rough guess at the zero point ({\tt ZERO\_PT}), and four numbers
+defining the format of the {\tt dophot} OBJ file.
+
+\subsection{Astrometry -- gastro}
+
+Astrometry is performed automatically by the program {\tt gastro}.
+{\tt gastro} loads a CMP file and determines an initial guess for the
+center coordinates (based on the RA and DEC header keywords).  The
+program also uses the configuration information about the plate scale
+and rough orientation of the image to get close to the final solution.
+Also, the true sky position of the telescope pole may be defined to
+allow astrometry on images taken close to the pole.  The comparison is
+made with the astrometric catalog, which may be the HST Guide Star
+Catalog, or it may be any source if the data is placed in the correct
+format.
+
+\section{The Photometry Database}
+
+\subsection{Photometry File Format}
+The photometry database consists of a large number of photometry files
+representing sections of the sky and a file containing information on
+the images incorporated in the database.  These files are called
+alternatively ``region files'' or CPT files (because they have the
+extension {\tt .cpt}).  The photometry files are sorted by Declination
+into different directories, each consisting of a band 7.5\degree\ 
+wide.  These directories have names like n0730, representing the band
+starting at a Declination of +07:30.  The image database (Images.dat)
+is stored in the upper level directory of this directory tree.  In
+fact, the locations of the Images.dat file, the photometry database,
+and such are all flexible and may be changed by altering the
+configuration file.
+
+The name and location of each sky region comes from the Hubble Space
+Telescope Guide Star Catalog.  There is a file, GSCregions.tbl, which
+can be used to find the region file appropriate for any location on
+the sky.  A number of routines exist to make such a query.  
+
+Each photometry file in the photometry database contains all
+observations and all average values for all stars observed within the
+appropriate region on the sky.  The identity of stars is essentially
+determined by the RA and DEC coordinates.  In very crowded regions,
+the end user may need to double check that a neighboring star is not
+contaminating individual detections (see the discusion on {\tt
+  addstar} below).
+
+The photometry files are stored in a binary format, both to reduce the
+volume and to speed access.  As a result, the interpretation of the
+data is machine dependent: little endian machines need to swap the
+data intelligently.  Fortunately, this operation is taken care of
+appropriately, if the programs are compiled with the BYTESWAP option
+set as needed, which is automatically set by the Makefile in the case
+of a Linux machine.  For reference, Suns, SGI, and HP are all big
+endian, while PCs and DECs are little endian.  The automatic
+conversion takes place by using the funcions {\tt Fread} and {\tt Fwrite}
+to substitute for the standard C library {\tt fread} and {\tt fwrite}
+functions.  {\tt Fread} and {\tt Fwrite} are told the datatype being read,
+and they know the layout of the bytes for a particular datatype.
+Anytime the definitions of the relevant structures (see below) are
+changed, {\tt Fread} and {\tt Fwrite} must be updated.  Fortunately, there
+is only one file ({\tt Fread.c}), and it has a single byteswapping
+section, making it easy to adjust the code appropriately.
+
+The format of a single photometry database file consists four
+sections:  
+\begin{itemize}
+\item {\bf header} -- this is a standard FITS header with room for comments
+  about the file or whatever.  Since the rest of the file is not a
+  standard FITS file, the SIMPLE keyword is set to False.  The three
+  necessary keywords are NSTARS, NMEAS, and NMISS, which define the
+  sizes of the next three sections.
+\item {\bf average} -- this section contains all average measurement
+  quantities for each star in the file.  There are NSTARS entries, and
+  each entry is the data from a structure of type Average (defined in
+  loneos.h, and discussed in more detail below).  Thus, the total size
+  in bytes of this section can be found by NSTARS*sizeof(Average).
+\item {\bf measure} -- this section contains the individual
+  measurements for each star in the database.  There are NMEAS
+  entries, and like the average section, each entry is a single
+  structure, in this case of type Measure (in loneos.h, see below).
+  All measurements of a single star are consecutive.  The number of
+  measurements for a single star is defined by average.Nm and the
+  starting entry for a single star is given by average.offset.
+  Therefore, the first measurement of a specific star average[500]
+  would be given by measure[average[500].offset], while the second is 
+  measure[average[500].offset + 1], and so forth.  
+\item {\bf missing} -- this section contains references to all missing
+  measurements of a star.  This means all of those occasions when an
+  image enclosed the location of a star in the database, but no star
+  was detected on the image.  Similar to the case of the measure
+  section, each star has a number of missing entries (which may be 0)
+  given by average.Nn, and the first missing entry is given by
+  average.missing.  Each missing entry value is again a structure of
+  type Missing.  Currently, the only data in the structure is the time
+  of the observation, which allows for an unambiguous recovery of the
+  image where the star was missed.
+\end{itemize}
+
+\subsubsection*{Average Structure defined in loneos.h}
+\begin{verbatim}
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm, Nn;  /* number of measurements, missing */
+  short int Xp;               /* scatter in 1/100 arcsec (-327.67 to +327.67 valid range) */
+  short int Xm;               /* 1000*log(chisq) for magnitude measurement */
+  unsigned short int code;    /* an ID code (ie, star, ghost, satelite, etc) */
+  signed int offset;          /* offset to first measurement */
+  signed int missing;         /* offset to first missing obs */
+} Average; /* 28 bytes / Average */
+\end{verbatim}
+The structure above defines the average data stored in the photometry
+database for each star.  Most of the entries are self-explantory, but
+some need a bit of clarification.  The entry {\tt Xm} is the magnitude
+$\chi^2$ value for the star, under the assumption that the star
+brightness is constant.  This $\chi^2$ incorporates the photometric
+errors on each measurement and is stored as 1000 times the logarithm
+of the $\chi^2$ because high dynamic range is not needed.  The entry
+{\tt Xp} is the scatter about the average postion, in 10
+milli-arcseconds.  As discussed above, the values of {\tt Nm} and {\tt
+  Nn} give the number of measurements and missing observations for
+this star, while the entries {\tt offset} and {\tt missing} point to
+the first {\bf measure} and {\bf missing} entry for this star.  The
+entry {\tt M} is the current best average magnitude solution for this
+star (see the section on Relative Photometry).  Finally, the entry
+{\tt code} is an ID code for each object, which may define a variety
+of things about the object.  For example, if the object is known to be
+variable, or if the object is associated with a USNO star, or if the
+object is a measurement of an asteroid.  See below for details of
+these definitions.
+
+\subsubsection*{Measure Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  short int dR, dD;           /* 1/100 of arcsec (-327.67 to +327.67 valid range) */
+  short int M;                /* thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mcal;             /* image cal mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 to 0.255 valid range) */
+  char dophot;                /* dophot type (1-9) */
+  unsigned short int source;  /* code to identify photometry source */
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+  unsigned int average;       /* reference to corresponding average entry */
+  /* upper byte of Measure.average stores flags:
+   limit of 16,777,215 stars (Naverage) in a file (=0xFFFFFF) 
+   flags: average & 0x1000000 */
+} Measure; /* 20 bytes / Measure */
+\end{verbatim}
+}
+The structure above defines the individual measurement data stored for
+each observation of each star.  The first two entries, dR and dD, are
+the difference between the average coordinates for this star and the
+coordinates determined for this observation.  Clearly, if this
+residual is too large, the individual measurement will not be
+successfully matched with the average star position.  {\tt M} and {\tt
+  dM} are the instrumental magnitude and error for this measurement,
+after correction for the exposure time and a zero point (defined in
+the configuration file as ZERO\_PT).  The entry {\tt t} determines the
+time of the individual observation.  This is important not only for
+timing purposes, but also to determine the source image for this
+observation.  The time and the entry {\tt source} uniquely determine
+the image in the image database that generated this measurement.
+Furthermore, this correspondence allows for determination of the pixel
+coordinates on the chip, by going throught the image astrometry stored
+in the Image database (see below).  The entry {\tt source} is a code which
+identifies the particular CCD/Telescope/Filter setup.  Each unique
+{\tt source} should be treated as an independent filter set for the
+purposes of accurate relative photometric comparisons.  This entry
+also allows external catalog data, such as the USNO or Sloan
+photometry, to be added to the database, as desired.  The entry {\tt
+  average} is a pointer back to the {\bf average} section to allow
+determination of the star from the measurements, in addition to the
+reverse.  The bits of the upper byte of this value are reserved for
+flags used to define particular situations for this measurement.
+Possible values are:
+\begin{itemize}
+\item 1 = BLEND\_IMAGE - the star on the image matched more than one
+  catalog star
+\item 2 = BLEND\_CATALOG - the star in the catalog matched more than
+  one image star
+\item 4 = UPPER\_LIMIT - \note{not really used?}
+\item 8 = CALIBRATED - relative photometry has been performed at least
+  once.
+\end{itemize}
+The entry {\tt dophot} stores the dophot type for this particular
+measurement (1-9: four extra bits in this field).   
+Finally, the value {\tt Mcal} determines the photometric calibration
+of this specific measurment.  This value is an offset appropriate to
+this image (and if needed, this point in time and this chip position)
+to bring the observations of the stars on multiple images to a common
+system (see the section on relative photometry).
+
+\subsection{Image Database}
+
+All images for which photometry has been included in the photometry
+database also have entries in an image database.  The image database
+is (currently) a single file in the upper directory of the photometry
+database.  The name of the file is determined by the IMAGE\_CATALOG
+entry in the configuration file, and is currently set to Images.dat.
+Like the photometry database files, the image database consists of a
+FITS header followed by binary data.  There is only one type of binary
+data: each image has an entry, which is the data from a structure of
+type Image (loneos.h).  The number of images in the file is determined
+by the {\tt NIMAGES} keyword.  If the number of images becomes too
+large, extrapolation of the system to a set of image database files
+with a reference list is quite straightforeward, and could be modeled
+on the organization of the region files (eg, one image database file
+for each Declination directory).
+
+\subsubsection*{Image Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  Coords         coords;            /* 120 bytes */
+  unsigned int   tzero;             /* readout time row 0 in sec (0 - 142 years valid range) */
+  unsigned int   nstar;             /* number of stars on image */
+  short int      secz;              /* thousanths of airmass (valid range -32.000 -- 32.000) */
+  short int      NX, NY;            /* dimensions of image */
+  short int      apmifit, dapmifit; /* aperture correction and error in thousandths of mag */
+  short int      source;            /* identifier for CCD (each ever used will have a unique letter) */
+  short int      Mcal;              /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      dMcal;             /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      Xm;                /* 10*log(image chi-square) */
+  char           name[32];          /* name of original image */
+  unsigned char  detection_limit;   /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  saturation_limit;  /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  cerror;            /* astrometric error: 1/50 of arcsec (0 -- 5.12 valid range) */
+  unsigned char  fwhm_x, fwhm_y;    /* PSF terms in 25*arcsec (valid range 0.0 -- 10.2" ") */
+  unsigned char  trate;             /* 10000 * scan rate in sec/pix (0 -- 0.0256 valid range, 
+                                       typically 0.0146. this is used only to determine the time
+                                       of the observation, not to find the coordinates.  1 byte
+                                       gives 0.11 sec accuracy */
+  float          exptime;           /* exposure time, seconds */
+  char           code;              /* flag to mark an image as bad or whatever */
+  char           dummy[21];         /* extra space for the future */
+  short int      order;             /* number of terms used for Mrel */
+  short int      Mx, My;
+  short int      Mxx, Mxy, Myy;
+  short int      Mxxx, Mxxy, Mxyy, Myyy;
+  short int      Mxxxx, Mxxxy, Mxxyy, Mxyyy, Myyyy;
+} Image;  /* 240 bytes / Image */
+\end{verbatim}}
+
+The structure above lists all of the data stored for each image.  A
+substantial amount of information is stored for each image.  First,
+the astrometric calibration information is stored in a {\tt Coords}
+structure (see coordinate systems, above).  The upper and lower limits
+of the photometry in the database (in instrumental magnitudes) is
+stored in {\tt detection\_limit} and {\tt saturation\_limit}.  These
+values are useful for comparison for those stars where observations
+are missing.  The relationship between time and pixel coordinates is
+given by {\tt tzero} and {\tt trate}.  Drift images will have a scan
+rate stored in {\tt trate}, while staring images will have a value of
+0.0 for this entry ({\tt tzero} then applies to the whole image).
+Other important parameters are kept: the astrometric error ({\tt
+  cerror}), the airmass ({\tt secz}), the exposure time ({\tt
+  exptime}), the number of stars detected ({\tt nstar}), the FWHM
+values ({\tt fwhm\_x, fwhm\_y}), the image name ({\tt name}), and the
+size of the image ({\tt NX, NY}).  The entry {\tt source} is used as
+above to define the CCD/Telescope/Filter used for this observation.
+The entry {\tt code} is used to flag images in various ways.
+Currently, only two bits are used, to define if the image has been
+photometrically calibrated and if the calibration is acceptable.
+There are 21 extra bytes are stored for future additions.
+
+\subsection{Data Incorporation -- {\tt addstar}}
+
+Images which are completely processed ({\tt dophot, fstat, gastro}) are
+then incorporated into the photometry database with the program {\tt 
+addstar}.  This program decides which region files are appropriate
+for this particular image, then one-by-one adds stars from the image
+to the appropriate region file.  Stars already in the catalog are
+matched with stars in the new image purely by a positional comparison.
+In order to avoid the difficulty of comparisons in the RA and DEC
+coordinate frame, a cartesian projection is performed.  The stars from
+the image being processed and the database stars in the same area are
+projected onto a tangent plane and positional comparisons made in this
+(locally cartesian) coordinate frame.  This avoids the dangerous
+singularities at the pole and also makes the RA 0,360\degree\ boundary
+a trivial problem.  
+
+Several choices must be made in the comparison process.  If a star in
+the catalog is matched with a star in the image, the new measurements
+of that star are added to the database.  If a star in the database
+lies in the field of the image, but is not detected, this information
+is added to the list of missing data.  The only data stored in this
+case is the time and source, which is sufficient to unambiguously
+identify the source image from the image database.  This allows later
+programs to find relevant statistics from the image database, if
+necessary.  If a star is detected in the image, but is not already in
+the database, a new entry is added to the database.  In addition, the
+same ``missing data'' from all previous observations images which have
+covered this location (ie, images already in the image database) are
+included.  This last step is necessary so that the image processing
+order is not important.  
+
+Stars also run the danger of being crowded together.  Since all
+comparisons are performed on the basis of position alone, crowded
+fields may make for ambiguous cross-identifications.  A pair of stars
+are matched if the difference in their positions is less than a
+specified search radius (dependent on the scatter in the astrometric
+solution for the image).  If more than one catalog stars are correlated
+with a star in an image, the new measurement is added to {\em both}
+catalog stars, and a flag is set noting that this observation had a
+blended IMAGE.  Conversely, if a single catalog star is matched with
+more than one image star, both new measurements are added to the one
+catalog star, and a different flat is set, noting that this
+observation had a blended CATALOG.
+
+\section{Catalog Update and Cleaning}
+
+Occasionally, once a large number of images have been added to the
+photometry database, a set of programs should be run to clean and
+update the CPT files.  This may best be done on CPT files after a
+night's worth of data is incorporated.  These routines define bad
+data, identify the USNO catalog stars, and search for asteroids and
+other junk.  Most of the results from these routines are the addition
+of object flags to the Average data structures (Average.code).  Most
+of these routines process data within a single CPT file at a time.
+
+\subsection{Markstar}
+
+The first of the update programs, {\tt markstar}, identifies bad data
+and flags it.  It makes three types of identifications: bright stars,
+ghost stars, and trails.  In the first case, it searches the HST guide
+star catalog for bright stars within the field of the current CPT
+file.  Three types of pixels are flagged for bright stars.  Any
+measurements within a circular region centered on the star are suspect
+(the ``halo'' of the bright star).  Second, points along the X axis
+are likely to contain flux from the diffraction spikes.  Finally,
+points along the Y axis are likely to have bleeding in addition to the
+diffraction spikes.  Each of these three regions has a different size
+and range which must be defined in the configuration file.  The
+regions are represented by a representative magnitude and a scale
+parameter.  For example, the diameter $d$ of the halo for a star with
+magnitude $m$ is defined as 
+$d = \mbox{BRIGHT\_HALO\_SLOPE} (m - \mbox{BRIGHT\_HALO\_MAG})$.  The X and
+Y axis points are defined by the length of the diffraction spike, with
+an equivalent formula, and the width of the spike.  Since these are
+each independent, there are 8 parameters to define the exclusion
+regions of bright stars.  One of the current drawbacks of this system
+is the reliance on the HST Guide Star photometry.  In the HST Guide
+Star Catalog, only one photometry band is given, so no color
+information is available.  The parameters currently used were defined
+based on a large number of bright stars, with no adjustment for the
+different effective filter system of the Loneos telescope and the HST
+GSC.  Thus, occasionally very red stars will be several magnitudes
+brighter in the real data than reported in the catalog.  As a result,
+large numbers of bad data points in these halos and spikes may be
+missed.  
+
+The second type of bad data flagged by {\tt markstar} are the trails
+from satelite and other space junk.  This portion of the program
+searches for objects which land along a line and which have a high
+linear density.  Parameters may be adjusted to define the width and
+the necessary density or number of points in the line.  Objects in
+lines are also only identified if all observations come from a common
+image.  If an object only has one measurement and it is in a trail,
+the entire Average is flagged to be bad.  However, if an object has
+many measurements and only one is bad, the object is only flagged as
+having some bad data points.  
+
+The third type of bad data are ghost star images.  The HST GSC is
+searched for stars projected across the telescope optical axis, which
+is defined by the user.  All objects within a region of fixed size are
+marked for ghost stars brighter than a specific cutoff magnitude.
+Similar to the trails, the average is marked as bad only if all
+detections of an object are ghost images.  Otherwise, it is noted that
+some data may be bad.
+
+To run 'markstar' by hand, the syntax is: {\tt markstar (file.cpt)}.
+There are several optional flags, which are listed if you type
+markstar by itself.
+
+\subsection{Addusno}
+
+The program {\tt addusno} makes two types of identifications of stars
+with the USNO catalog.  First, it searches for coincidences within a
+small, specified radius.  The choice of this radius is somewhat
+tricky: it is important to catch the association, but also to avoid
+making too many associations.  Unfortunately, astrometric errors in
+the USNO catalog make it necessary to choose a surprisingly large
+radius of 5\asec.  To avoid making double matches (matching the two
+USNO stars to the same photometry database object), only the USNO
+object closest to the object is associated.  There are also a
+substantial number of stars with significant proper motion between the
+USNO epochs and the current date.  It is not unusual to see 8-15\asec\ 
+discrepancy for specific stars.  To catch these objects, any objects
+which do not match the USNO database, but which have more than a
+minimum number of measurements (2 or 3?) are searched for more distant
+USNO companions.  A large, user-specified radius is used for this
+search.  Of course, only USNO stars which are not already matched to
+the database may be candidates for the proper motion match.  This
+stage is susceptible to errors in that a slow-moving solar-system
+object may be associated with a faint USNO star.  For this reason,
+objects flagged as high proper motion stars should be taken with some
+caution.  Of course, during the {\tt addusno} stage, no objects
+already flagged as bad by {\tt markstar} will be matched with USNO
+stars.  
+
+To run 'addusno' by hand, the syntax is: {\tt addusno (file.cpt)}.
+There are several optional flags, which are listed if you type
+addusno by itself.
+
+\subsection{Markrock}
+
+Once stars have been identified with the USNO database, it is possible
+to search for asteroid detections.  The program {\tt markrock}
+searches within a specific CPT file for objects which are moving along
+straight lines in (X,Y,t) space.  In order for an object to be found
+by {\tt markrock}, it must have three points, each with only single
+measurements.  The third point must land within a specified distance
+of the line projected from the first two data points.  These
+comparisons are made in the three dimensional space of image position
+and time.  Also, objects are only accepted if they have a speed less
+than a threshold.  If an object is moving too fast, it will make a
+streak on each individual image and will probably be missed anyway.
+Moving objects detected in this way are flagged in the photometry
+database and are also written to a Rock database.  Currently, the Rock
+database just contains ASCII lists of the RA, DEC, Mag, and time for
+each detection.  In fact, the data are stored in pairs of detections,
+with the middle detection saved twice.  This format makes it easy to
+plot lines connecting the points using the connect-the-dots plotting
+style of status/kapa (see below).
+
+One of the current drawbacks of {\tt markrock} is the insistence on
+three observations with only 1 measurement each.  If an object is
+moving too slowly, two of the dectections of the object may be merged
+together.  Enough data is stored in the database to extract these
+individual measurements, so a more sophisticated search is possible.
+It is also currently the case that USNO proper motion stars are
+ignored, but some of these will be asteroid detections which are
+simply too close to a faint USNO stars (it has to be faint because it
+would otherwise be associated with a star in the photometry
+database).  
+
+To run 'markrock' by hand, the syntax is: {\tt markrock (file.cpt)}.
+There are several optional flags, which are listed if you type
+markrock by itself.
+
+\section{Relative Photometry -- nrphot}
+
+Once the data has been incorporated in the photometry database and the
+data validation routines have been run, it is possible to determine
+photometric solutions for all of the images.  The program which does
+this is nrphot.  It tries to find a set of solutions for each image
+which reduce both the scatter per image and the scatter per star.
+\note{the following section is quoted verbatim from the M31 paper
+  Magnier et al 1992, A\&A Supp 96, 379.  It could use a little
+  editing to fit the reality of the LONEOS implementation.}
+
+In order to convert from instrumental magnitudes reported by DOPHOT
+to a standard photometric system, relative photometry was used, and
+all values converted to one internal magnitude system for the entire
+set of data taken with each filter.  Note that this is not {\em
+  differential}\ photometry on a single image, but rather {\em
+  relative}\ photometry between many images.  This method was
+advantageous for several reasons.  First, since many of our nights
+were not photometric, relative photometry allowed us to use all of our
+data, even that obtained on the cloudy nights.  Second, it allowed us
+to use photometry from several of the recent CCD photometric studies
+(Massey \etal\ 1986; Hodge \& Lee 1988; Freedman 1989; Richer \etal\ 
+1990) in small fields of M31 to calibrate our data to a standard
+system.  Third, relative photometry allowed us to check the agreement
+of the photometry of the calibration data.
+
+        In order to perform relative photometry, we used multiple
+measurements of individual stars on overlapping images to connect
+neighboring images.  A standard method of converting between
+instrumental magnitudes and a standard photometric system is to use a
+photometry equation of the form:
+\begin{equation}        
+M_{app} = c_{\lambda} + m + a_{\lambda}*\zeta + \gamma_{color}*(color) \\
+\label{M_mag}
+\end{equation}
+where $m$ is the instrumental magnitude,
+\begin{equation}        
+m = -2.5\log(N_{el}) + 2.5\log(t). \\
+\label{inst_mag}
+\end{equation}
+$N_{el}$ is the number of electrons measured in a single star, $t$ is
+the exposure time for the image, $M_{app}$ is the apparent magnitude
+of the star in the standard system, $\zeta$ is the airmass of the
+image, and $color$ is the value of a color index (\ie\ \B\ - \V\ or
+\V\ - \R) for the particular star.  The subscript $\lambda$ refers to
+the filter and the subscript $color$ refers to the color index.  For a
+given filter, several possible color indices could be used (\ie\, for
+calibration of \V\ data, both \B\ - \V\ and \V\ - \R\ could be used to
+measure the response of the detector with the color of the star);
+however the colors of stars are highly correlated, so only one color
+index need be used at a time.  $c_{\lambda}$, $a_{\lambda}$, and
+$\gamma_{color}$ are calibration coefficients dependent on the
+instruments and the site.  $c_{\lambda}$ is a factor to scale the
+response of the detector.  In fact, the value determined for
+$c_{\lambda}$ depends on what color index is used in the calibration,
+so one might in fact write $c_{\lambda}$ as $c_{\lambda, color}$.
+However, for the sake of readability, this second subscript will be
+dropped.  The terms $\gamma_{color}$ and $a_{\lambda}$ give the
+variation of the sensitivity with the color of the star and the
+airmass.  For a detailed discussion of photometric calibrations, see
+Hardie (1962).  Equation (\ref{M_mag}) is only valid for photometric
+conditions.  Under non-photometric conditions, we need to add another
+term to account for clouds:
+\begin{equation}        
+M_{app} = c_{\lambda} + m + a_{\lambda}*\zeta + \gamma_{color}*(color) + clouds \\
+\label{M_cloud}
+\end{equation}
+Now, we can regroup the terms in (\ref{M_cloud}) as follows:
+\begin{equation}        
+m = [M_{app} - \gamma_{color}*(color)] - [c_{\lambda} + a_{\lambda}*\zeta + clouds]
+\label{M_sep}
+\end{equation}
+Of the two terms on the right side of equation (\ref{M_sep}), the variables
+in the first pair of brackets are dependent on the properties of the
+star, those in the second pair of brackets are dependent on the image parameters,
+except for $c_{\lambda}$ which is independent of both image and star.
+We can now define the ``relative magnitude'' and the ``calibration
+magnitude'' from (\ref{M_sep}) as follows:
+\begin{eqnarray}
+        m       & = & M_{rel} + M_{cal} \label{rel_phot1}\\
+        M_{rel} & = & [M_{app} - \gamma_{color}*(color) + \Delta] \label{color}\\
+        M_{cal} & = & - [c_{\lambda} + a_{\lambda}*\zeta + clouds + \Delta] \label{M_cal}
+\end{eqnarray}
+where $M_{rel}$ is the relative photometric magnitude of the star in
+the internal system and $M_{cal}$ is a correction factor to convert
+instrumental magnitudes to relative magnitudes.  The terms $\Delta$
+are included in eqs. (\ref{color}) and (\ref{M_cal}) to make explicit
+the fact that an arbitrary constant can be added to $M_{rel}$ and
+subtracted from $M_{cal}$, as this fact will be important (see below).
+The goal of relative photometry is to determine $M_{cal}$ for each
+image, then use this $M_{cal}$ to find $M_{rel}$ for all stars from
+eq. (\ref{rel_phot1}).  Once one has $M_{rel}$ for each star, one can
+then convert them to a standard system ($M_{app}$) using equation
+(\ref{color}).
+
+        An equation of the form (\ref{rel_phot1}) exists for each star
+detected on each image.  As described, the value $m$ depends on both
+the particular image and the particular star, the value of $M_{cal}$
+only depends on the image, and the value of $M_{rel}$ only depends on
+the particular star.  Let us label the images with the subscript $i$
+and the stars with the subscript $j$.  Equation (\ref{rel_phot1}) can
+then be written in the form:
+\begin{equation}
+m_{i,j} = M_{rel,j} + M_{cal,i} \label{rel_phot}
+\end{equation}
+Of course, $m_{i,j}$ only exists for certain combinations of images
+and stars: not all stars appear on all images.  In the entire system
+of equations, only one value of $\Delta$ (from eqs. \ref{color} and
+\ref{M_cal}) can be used, but, as noted above, the {\em value}\ of
+$\Delta$ is arbitrary.
+
+        In equation (\ref{rel_phot}), both $M_{rel,j}$ and $M_{cal,i}$
+are unknown quantities.  We can use a method of least squares to find
+these values for the entire set of data.  We try to minimize the chi
+square, defined as:
+\begin{equation}
+\chisq = \sum_{i,j}(m_{i,j} - M_{rel,j} - M_{cal,i})^2 / \sigma_{i,j}^2 \label{chisquare}
+\end{equation}
+where $\sigma_{i,j}$ is the error in the measurement $m_{i,j}$, and
+the index $i$ runs over all images, while the index $j$ runs over all
+stars which are multiply measured, \ie\ those stars which appear on more
+than one image.
+
+        We attempt to minimize \chisq\ analytically by finding the
+derivatives of \chisq\ with respect to $M_{rel,j}$ and $M_{cal,i}$
+and setting them equal to zero:
+\begin{eqnarray}
+\frac{\partial\chisq}{\partial M_{rel,j}} = \sum_{i}-2(m_{i,j} -
+M_{rel,j} - M_{cal,i}) / \sigma_{i,j}^2 = 0  \nonumber \\
+\frac{\partial\chisq}{\partial M_{cal,i}} = \sum_{j}-2(m_{i,j} -
+M_{rel,j} - M_{cal,i}) / \sigma_{i,j}^2 = 0
+\end{eqnarray}
+In these summations, the index $i$ runs over all images in which star
+$j$ appears, and the index $j$ runs over all stars which appear on
+image $i$ which are multiply measured.  Solving the equality leads to
+the following system of equations:
+\begin{eqnarray}
+R_{j}M_{rel,j} = \sum_{i}(m_{i,j} - M_{cal,i}) / \sigma_{i,j}^2 \label{system1} \\
+R_{i}M_{cal,i} = \sum_{j}(m_{i,j} - M_{rel,j}) / \sigma_{i,j}^2 \label{system2}
+\end{eqnarray}
+where 
+\begin{eqnarray}
+R_{i} = \sum_{j}\frac{1}{\sigma_{i,j}^2} \nonumber \\
+R_{j} = \sum_{i}\frac{1}{\sigma_{i,j}^2} 
+\end{eqnarray}
+Again, the index $i$ runs over all images in which star $j$ appears,
+and the index $j$ runs over all stars which appear on image $i$, with
+the restriction of multiple measurements.  The term $\Delta$ from
+eqs. (\ref{color}) and (\ref{M_cal}) acts as an arbitrary zero point
+between the relative and apparent photometric systems.
+
+        Equations (\ref{system1}) and (\ref{system2}) are a set of
+$N_{images} + N_{stars}$ linear equations with $N_{images} +
+N_{stars}$ unknowns.  The unknown parameters are the terms $M_{rel,j}$
+and $M_{cal,i}$.  Unfortunately, $N_{images} + N_{stars}$ is a number
+on the order of 5000 - 10000, thus an analytical solution is
+impractical and an iteration method must be used.  A simple iteration
+method is as follows:
+
+%\SingleSpace
+\begin{enumerate}
+\setlength{\parskip}{-0.05in}
+\item Guess at values for each $M_{cal,i}$.
+\item Use equation (\ref{system1}) to find values for $M_{rel,j}$.  
+\item Substitute these $M_{rel,j}$ values into (\ref{system2}) to get a new
+set of $M_{cal,i}$ values.  
+\item Return to step 1.
+\end{enumerate}
+%\DoubleSpace
+This process is repeated until some criterion is reached, such as the
+\chisq\ no longer changes or reaches a desired minimum.  Although a
+minimum can be found, error propagation causes severe problems
+since images are only connected to neighboring images.  The end point
+images are connected by \approx 50 intermediate images, and errors
+propagating over such a long distance can cause severe errors.  Also,
+$M_{rel,j}$ and $M_{cal,i}$ are not uniquely defined, because of the
+term $\Delta$.  Therefore, during the iteration process, the values of
+$M_{rel,j}$ and $M_{cal,i}$ tend to wander and do not tend to converge
+($M_{cal,i}$ may be incorrect by typically 0.5 mag).  These problems
+can be overcome if some of the values $M_{cal,i}$ or $M_{rel,j}$ are
+known.  In this situation, the known values can be held fixed,
+providing a reference point for the remaining values.  If enough
+values are known across a large enough portion of the data, no image
+is separated from the fixed values by many images, and errors will not
+build up.
+
+        Although many values $M_{rel,j}$ were known from other CCD
+photometry studies, we chose not to use them.  The reason for this
+decision was threefold: 1) By not using them, we are able to check the
+effectiveness of our method.  2) We are able to check the accuracy of
+the reference data.  3) The known $M_{rel,j}$ values were in a very
+small number of highly concentrated regions (the locations of the CCD
+photometry studies).  This was particularly a problem in \R\ and \I,
+where we only had one or two reference fields.  We therefore chose to
+fix certain values of $M_{cal,i}$
+
+        Images taken under photometric conditions provide a set of
+known $M_{cal,i}$ which can be held fixed.  This is true since, if the
+image is taken under photometric conditions, the term $clouds$ in eq.
+(\ref{M_cal}) is by definition 0.  The other terms in this equation
+are either known ($a_{\lambda}*\zeta$) or are constant for all images
+($c_{\lambda}$) and can thus be assigned to a set value, which can
+later be removed with the zero point calibration.  We used the values
+of $a_{\lambda}$ reported by Pilachowski \etal\ (1991): $a_B$, $a_V$,
+$a_R$, $a_I$ = (0.24, 0.15, 0.11, 0.07).  We used the long-term
+average coefficients, not those measured in October 1991, since the
+observations were performed before the eruption of Mount Pinatubo.
+The task that remains is to determine which images were photometric.
+
+        Since the conditions during observations varied greatly from
+night to night, we decided to determine which images were photometric
+from the images themselves.  To do this, we used a variation on the
+iteration method described above.  Before starting the iterations, we
+assume a value for $c_{\lambda}$.  We can choose this arbitrarily, and
+correct for our choice in the correction to an absolute photometric
+system.  Now, we perform the following iteration:
+
+%\SingleSpace
+\begin{enumerate}
+\setlength{\parskip}{-0.05in}
+\item Assume that all images are photometric and determine $M_{cal,i}$.
+\item Find the corresponding values of $M_{rel,j}$ from equation (\ref{system1}).
+\item Use these $M_{rel,j}$ values to find new values for $M_{cal,i}$.
+\item Find the values of $clouds$ for each image from these $M_{cal,i}$
+\item Assume that any image with a value $clouds$ more than 1 standard
+deviation from the mean value (over images) has a substantial cloud
+layer.  
+\item Return to step 1, but use the iterated $M_{cal,i}$ values for those
+images with substantial clouds.
+\end{enumerate}
+%\DoubleSpace
+This process is continued until \chisq (eq. \ref{chisquare}) does not
+change substantially.  Figure (\ref{fig:Mrel}) shows a histogram of
+the occurrences of different $clouds$ values.  There are a few
+important points to make about this figure.  First, there is a
+concentrated peak at 0.  All of these images have essentially zero
+cloud level.  As one would expect, there are a large number of images
+to the right of this peak.  These are the images which were taken
+through some amount of clouds.  Since the exposures were stopped if
+the clouds got too thick, it is not surprising that these images taper
+off at higher cloud levels.  The most curious and telling part of the
+plot is the area below the 0-cloud peak.  There are many images on the
+``negative cloud'' side of the peak.  Because ``negative clouds'' are
+unphysical, there must be a simple explanation for this.  In fact, 112
+of the 122 images more than 0.02 mag below the peak had exposure times
+of less than 20 seconds.  Since the shutter at MDM is accurate to only
+1 - 2 seconds, it is likely that these images had an exposure time
+which was longer than reported, and therefore have artificially
+enhanced values of $M_{cal,i}$.
+
+        We calculate the error on the relative calibration of each
+image by finding the scatter of the $M_{cal,i}$ values for each image
+and dividing by $\sqrt{N stars}$.  A histogram of this error for all
+images is shown in Figure (\ref{fig:dMrel}).  We also show the
+variation of the formal photometric error reported by \dophot\ with
+magnitude for each filter in Figure (\ref{fig:dm}).  Now that we have
+the values $M_{cal,i}$, we can calculate the values $M_{rel,j}$ for
+every star on every image.
+
+The Pipeline implementation of relative photometry includes the
+possibility for up to third order polynomial terms across the field.
+This is needed to account for the different flat fields, particularly
+between images taken with and without the red-block filter.  
+
+\begin{figure}
+\psfig{file=flags.eps,width=9cm}
+\caption{\label{flags} \small
+  Pictoral representation of the Average.code flags.  The lower byte
+  value is used for specific definitions of object types.  }
+\end{figure}
+
+To run 'nrphot' by hand, the syntax is: {\tt nrphot (file.cpt)}.
+There are several optional flags, which are listed if you type
+nrphot by itself.
+
+\subsection{Data Flags}
+
+The identifications made by the above routines are noted as a set of
+flags in the Average.code structure entry.  Some of these flags are
+mutually exclusive, so a certain bit may have more than one meaning,
+depending on the value of other bits.  Figure~\ref{flags} shows a
+pictoral representation of the meaning of the different bit fields.
+The uppermost bit (bit 15) determines if the object may be considered
+a ``fixed'' star or something which has no fixed location.  If it is
+not fixed, and this bit is 1, then there are several options.  The
+second uppermost bit (bit 14) will be set if this object is one of the
+three types of bad data flagged by {\tt markstar}.  The lower byte of
+code is used to define the type of bad data: ghost, trail, or bleed.
+Thus, any datapoints determined to be a satelite trail will have a
+code value of 0xc002 (49154 decimal).  If an object is a moving
+object, but not a bad datapoint, it may be identified as a ``rock''
+(an asteroid) by the program {\tt markrock}.  In this case, the flag
+for an asteroid is turned on (bit 13).  Thus anything identified as a
+rock by {\tt markrock} will have a code value of 0xa000.  The lower
+byte of code is not yet defined for asteroids, but could be reserved
+for distinguishing different classes of asteroids (ie, on the basis of
+orbital speeds, and so forth).  Objects which are fixed may have a
+variety of possible flags.  First, an object may be identified with a
+USNO star (bit 14).  It may be found to exhibit variability (bit 13),
+implying that the relative photometry routine should ignore it.  If
+may be a transient object (bit 12).  Note that, while an object
+associated with a USNO object may not be transient, an object which is
+variable may also not be associated with a USNO object.  Thus, we need
+seperate bits for variable vs transient.  Different types of variable
+objects may be represented with different values of the lower byte.
+For example, a Cepheid may have a specific lower byte code of 0x01,
+which an RR Lyrae may have a lower byte code of 0x02.  Thus a Cepheid
+associated with the USNO catalog would have a total code value of
+0x6001. Finally, any of these types of non-moving objects may have
+some bad individual measurements (bit 12) or may be found to have a
+significant proper motion (bit 11).  It should be noted that the above
+guidelines for variable stars are suggestions only, and to date (July
+7, 1999), no programs currently assign or define these variability flags. 
+
+\section{Holding it Together}
+
+The preceeding sections describe the step-by-step analysis and
+incorporation of the data from individual images.  However, the power
+of the Pipeline comes in applying it to large numbers of images.  At
+LONEOS, we are using four Pentinum II computers to analyse the roughly 200
+images that are observed each night.  
+
+It is best to think of the analysis of images occurring on groups of
+images from a given night.  Of the set of processes discussed above,
+those in section \ref{parallel} are performed on individual images
+essentially independently of the other images.  The rest of the steps,
+both the data incorporation ({\tt addstar} and the database cleaning
+routines occur on the entire batch, one image at a time.  Thus, the
+former routines can easily be run in parallel, but the latter routines
+are run in serial to avoid having two programs writing to same part of
+the database at the same time.  In this model, we would process all of
+the images from a night through the parallel stage of the analysis and
+then run the serial stage only after the entire night is finished in
+the parallel stage.  We thus have a natural division of the pipeline
+into two stages.  
+
+The implementation of the two stages involves several programs, some
+of which are specific to the LONEOS situation, and others which are
+more general.  There are two layers of programs which enable batch
+processing of many images and repeated batch processing over many
+nights.  At the highest level, are Perl scripts which choose what data
+needs to be analysed and when.  These scripts tend to be more
+dependent on the details of the LONEOS implementation. At the next
+level down, these scripts call two main C programs which run the
+images of a given night through the pipeline.  These C programs are
+more general and do not depend on the details of the LONEOS
+implementation.  A defined set of files holds a log of the nights and
+images that have been processed, both for the information of people
+who might want to monitor the progress, but also used by the programs
+to guide decisions about what to analyse next.
+
+\subsection{data and file organization}
+
+There are a set of standard locations for all of the files used and
+created by the Pipeline.  These locations have both abstract names
+used by the pipeline programs and specific definitions used in the
+LONEOS implementation.  In general, the definitions of the files are
+given in the configuration file, 'config.txt' (currently located in a
+hard-wired location, but this may soon change to the mechanism used by
+the lastest version of spicam (3.0)).  The C programs all refer to the
+config file for the definitions, but the Perl scripts currently have
+the definitions hardwired as variable names defined in the beginning
+of each file.  This should be changed to a mechanism that looks in
+the config file, perhaps implemented by a standard Perl function.
+
+Here is a list of the main directories and their meanings:
+
+logdir:         /metis/d11/logs - all log files and the files used by
+the Perl scripts to control their actions (except locks) go here.
+
+workspace:      /irene/d11/workspace - the intermediate analysis
+stages go here, and the tar, gzipped directory files stay here.
+
+dumpspace:      /pallad/d1      - used by slurp to store images
+downloaded from the tape archive.
+
+database:       /hebe/d27/database      - the result database, as also
+the locks and the Rocks.dat file.
+
+references:     /metis/d11/references   - a variety of reference data,
+including the HST GSC, the USNO catalog, the config files, and so
+forth.
+
+source:         /metis/d11/src/ohana    - all of the programs source, 
+binaries, and scripts relevant to running the Pipeline are contained
+in these directories.  
+
+\begin{verbatim}
+database: /hebe/d27/database (also in /metis/d27/database as linked directories).
+ lock files also go in this directory
+workspace: /irene/d11/workspace - temporary storage of result files
+dumpspace: /pallas/d1 - disk to store data dumped from the archive by slurp.
+scriptdir: /metis/d11/logs - all log files
+\end{verbatim}
+
+\subsection{lastnight}
+
+The first step in the process is the Perl script {\tt lastnight},
+which is highly dependent on the specifics of the LONEOS setup.  It
+looks at the disks used by the observers to write the images from a
+given night.  Images are written to a directory called
+/pallas/d[1-6]/YYMMDD where 'YYMMDD' is an abbreviation for the current
+night's date (ie, 990223).  Many files use this naming scheme, so we
+will refer to such a name as 'YYMMDD'.  All of the images are stored
+in this directory with names yyyyMMDDxxxxb.fits where yyyy is the full
+year, MM is month, DD is date, and xxxx is a sequence number.  The 'b'
+refers to the 'b' CCD, and the .fits extension is required.  The
+script {\tt lastnight} is called by a cron job scheduled for 7am on
+{\tt hebe.lowell.edu} (note that the clock on hebe is set to PST, not
+local MST - fix this some day!).  The script searches the disks
+{\tt /pallas/d[1-6]} for a directory of the right form (basically any
+directory beginning with a number).  By default, the program demands
+that the directory have the name derived from today's date, but with
+the flag -any, it will accept any directory.  It then checks to see if
+this directory has been already been analysed (ie, it is included in
+the 'processed.log' file).  If not, it lists all files in that
+directory with the right ending (*b.fits) and places these names in a
+file, {\tt /metis/d11/logs/YYMMDD.inlist}.  It also writes the name of the
+directory (along with some other data) in a file 'extracted.log'.
+When it has successfully ended and identified some data, it calls the
+next script, {\tt stage1} and then quits.
+
+\subsection{slurp}
+
+An alternative to {\tt lastnight} is the Perl script {\tt slurp},
+which looks for data on the tape archive.  This script looks at the
+tape.log file and compares it to the file 'processed.log'.  It tries
+to identify nights listed in the file 'tape.log' which have not been
+included in the 'processed.log'.  If it finds any, it tries to
+download as much of the data as will fit on the disk {\tt /pallas/d1}.
+This script is called from within the {\tt stage1} script and is
+invoked if {\tt stage1} is run without any data already in
+the file 'extracted.log'.
+
+A related pair program is the load/unload C programs which are needed
+for loading and unloading the tape jukebox.  The first, load N, takes
+tape number N and loads it into the tape drive.  The second takes the
+tape a returns it to its slot.  It is important to check on the other
+users of the tape drive to be sure it is not occupied.  This is done
+with the llock, lunlock and llockstat programs.  llockstat lists the
+devices which have been allocated.  llock lets you lock a particular
+service, etc.
+
+\subsection{stage1}
+
+The Perl script {\tt stage1} takes the image list produced by {\tt
+lastnight} or {\tt slurp} (YYMMDD.inlist) and passes the list to the
+controller program {\tt control1} which performs the parallel
+analysis.  The script has a few features to decide which files have
+been analysed through the pipeline and to what extent.  If {\tt
+stage1} is called, it should be able to figure out 1) if there is data
+ready to be analysed (ie, there is a new date reference in the file
+'extracted.log'), 2) if the data has been partially analysed (ie, the
+date reference in 'extracted.log' has not been put in 'processed.log',
+but there are entries in the file YYMMDD.outlist), and 3) which data
+needs to be run through which part of the pipeline (ie, it decides
+which of the images in YYMMDD.outlist have succeeded at which stages
+of the analysis, and starts them at the appropriate spot).  These
+features are most useful if the analysis crashes in the middle or
+needs to be restarted.  The {\tt stage1} script is meant to be run
+without any arguments and it will figure out what needs to be done.
+The one possible argument is the -once flag.  This flag tells {\tt
+stage1} to analyse the data it finds and quit when it finishes, and
+not call another instance of itself.  Otherwise, when it is done, it
+will restart itself, and since there is no new data in
+'extracted.log', it will start a slurp process to get data from the
+archive.  If there is no data in the archive either, this process will
+sleep for an hour and try again.  After a few attempts (2 days?), {\tt
+stage1} will give up and quit without restarting itself.  The script
+writes a log file called \$scriptdir/stage1.NN.log where NN is a
+number in sequence between all runs of {\tt stage1}.  A file
+stage1.count keeps track of which number NN we are on.  When {\tt
+stage1} has finished the analysis of a night's data, it writes the
+date in 'processed.log' to let other processes know what has been
+analysed.  The bulk of {\tt stage1} is not dependent on details of the
+LONEOS setup, but it does expect the files to have the naming scheme
+described above.
+
+\subsection{stage2}
+The serial stage processes are run by the Perl scrip {\tt stage2}.
+Normally, this script is always running.  It waits for the name of a
+night to be added to the 'processed.log file, presumably by {\tt
+stage1}.  Once it finds a new name in this file, it looks for the
+appropriate images in the file 'YYMMDD.addlist'.  It then submits the
+list to the second controlling program {\tt control2}, which runs the
+images through {\tt addstar}.  Images which are successfully run
+through addstar have their *bf.fits (flattened image) and *.obj
+(dophot output) files deleted.  When the entire night is done, the
+rest of the *.obj and *bf.fits images are deleted by {\tt stage2}, the
+directory with the *.cmp and *.log files is tared and gzipped into the
+file YYMMNN.tgz.  The directory is then deleted.  Finally, {\tt
+stage2} calls the scripts {\tt cleaning.pl} and {\tt run.phot} which
+runs the cleanup programs ({\tt markstar - nrphot}) on the database.
+After a successful run, {\tt stage2} will automatically respawn a new
+copy that waits until more data arrives.
+
+\subsection{control1 / control2}
+These two C-programs perform the tasks of farming the images out to
+the different machines for analysis.  The two programs are essentially
+identical, but {\tt control1} is allowed to use all machines and {\tt
+control2} can only use one (hebe.lowell.edu, which has the database
+local to it).  These controller programs start off by executing remote
+shells (using ssh) on a set of machines.  These shells are then used
+to execute the remote commands and are kept open the entire time the
+process runs.  
+
+Both control programs maintain a list of images in a set of queues.  A
+set of rules defines the order in which each image travels through the
+queues.  Each queue is associated with a single process (ie, flatten,
+astrometry, etc).  Images which successfully run through a queue are
+sent on to the defined 'next' queue, while images which fail are
+instead sent to the defined 'fail' queue.  In most cases, the 'fail'
+queue is a process which marks the image as bad and write the name in
+a file, and then puts the image in the 'done' queue.  However, it is
+possible for the 'fail' queue to be another attempt, such as in the
+case of astrometry.  In this example, images which fail the default
+astrometry are run through a second queue which tries again with the
+-loneos flag set (this flag makes the assumption that the header
+information about the LONEOS region number for the image is correct,
+not the RA/DEC information).
+
+The connections on the remote machines are handled as child processes
+with communication through the stdin and stdout/stderr pipes.
+Messages can be sent back and forth though these pipes, and messages
+which are received from a process associated with an image are written
+to a log file with the name imagename.log (where imagename is the root
+name of the image).  The only required messages from the program are
+messages saying ``SUCCESS'' or ``ERROR''.  The programs therefore all
+end with either of these words.  The programs are started within the
+controller as a command to the shell followed by and echo ``PROCESS
+DONE''.  If the controller sees the message ``PROCESS DONE'' without
+either ``SUCCESS'' or ``FAILURE'' (after waiting an appropriately long
+time), it assumes the program crashed.  Currently, no timeout is
+available for the programs.  The flat-field process is run in mana and
+is a slightly special case.  We avoid re-loading the same flat many
+times by starting a mana process once and running the flatten
+procedures as mana function calls.  The images which are analysed
+(with an indicator of success or failure at each stage) are written to
+a file named 'YYMMDD.addlist' by the {\tt control1} and 'YYMMDD.outlist'
+by {\tt control2}.
+
+\subsection{Lock files}
+
+A variety of locking mechanisms are used to avoid overwriting the
+database or running more than one version of the controlling
+programs.  There is a perl program, {\tt locks}, which allows the user to
+set or check the state of the different locks. All programs which
+write to the database check for the existence of a lock on the
+database and refuse to run if it exists.  The control1/2 programs and the
+stage1/2 programs check for their own lock files and only run if they
+don't exist.  Finally, the use can set the lock files 'kill' or 'halt'
+for either stage1 or stage2.  The first tells the process to stop
+immediately, taking care of bookkeeping first.  The second tells the
+process to finish the current set of images but not start a new
+version.  
+
+\subsection{Other Perl Scripts} 
+
+there are several other scripts which are either used to do some
+simple function or are used by the maintainer to check up or work on
+the pipeline.  The two programs 'checkoutlist' and 'checkaddlist' take
+a list of YYMMDD.outlist or YYMMDD.addlist files and list the number
+of images in the file and the number of successes at each analysis
+stage.  There programs 'cleaning.pl' and 'run.phot' deal with the
+cleanup programs and the running of nrphot.  the program
+'backup.stuff' takes the first 4 characters of the year/month file
+names and backs up to the jukebox tape all tar files for the given
+month.
+
+\section{Operational Issues and Subtleties}
+
+The current LONEOS system runs principally on four Intel machines
+under linux.  The existing system has been generally quite stable over
+the past year of operation, but there are some subtleties.  One
+significant issue is the RAID disk attached to hebe.lowell.edu.  This
+device is a set of three 9 GB disks merged into one 27GB raid disk.
+The database is stored mostly on this disk and the RAID disk mounted
+on metis.  It is easy to split the database across multiple file
+systems by using links.  Within the database directory, there are
+directories for each of 24 Declination bands (7.5 degrees tall).  The
+easiest way of splitting up the data is to move some of these
+subdirectories to another device and creating links to them at the
+appropriate place.  This is currently done by having a directory
+/metis/d27/database with the remote directories.  
+
+The current problem with the /hebe/d27 RAID results from the poor way
+it was setup.  It was set up without much knowledge of the (at the
+time) rather rudimentary linux RAID system.  As a result, the
+implementation is such that the disk will not automatically be
+configured and mounted at boot time.  There is a script /root/mdstart
+which lists the step to setup the RAID correctly.  It would be helpful
+if the rc.local or rc.sysinit files were fixed to start, fsck and
+mount the RAID automatically at boot.  The setup on metis is
+substantially more mature and is correctly implemented.  It comes up
+when the machine boots.
+
+\section{Visualization -- Status}
+
+Visualization of the data in the photometry database can best be
+performed with the program {\tt status}.  This is a command-line
+driven program with a math and macro language which makes it easy to
+perform complex tasks.  
+
+First, a few notes about the user interface.  The interface has an
+interaction similar to {\tt tcsh}.  The arrows allow editing of
+previous commands.  You can also use emacs-like commands such as
+cntl-a to reach the beginning of the line and cntl-e to reach the end.
+There is command and file completion: if you type part of a command
+(as the first thing on a line) and then type tab, it will fill in as
+much as possible, until the word is not unique.  Typing tab twice at
+that point will list the possible endings.  For any but the first word
+on a line, the same thing will happen for the files in the current
+directory.  It is also possible to type just a fraction of a command,
+as long as it is unique.  An ambiguous command will list the possible
+alternatives.  For example:
+\begin{verbatim}
+status: c
+ambiguous command: c ( catalog cgrid clear create cursor )
+\end{verbatim}
+
+The shell is essentially an interpretive programming language.
+Variables are set as follows:
+\begin{verbatim}
+status: $fred = 10
+\end{verbatim}
+Any expression within curly brackets \{\} is assumed
+to be an arithmetical expression and is evaluated before the line is
+executed.  For example:
+\begin{verbatim}
+echo {$fred*dcos(45)}
+\end{verbatim}
+would give the response 7.07107.  There are math functions cos, sin,
+and tan, which operate on radian expressions, and also dcos, dsin,
+dtan, which operate on degree expressions.  There are also the
+equivalent inverse functions: eg., asin and dasin return radians and
+degrees, respectively.  The help section on Math defines all of the
+available math functions.  
+
+\subsection{Miscellaneous Commands}
+\begin{verbatim}
+!                         -- system call
+?                         -- list commands 
+??                        -- list variables 
+echo                      -- type this line 
+exec                      -- system call
+exit                      -- exit program 
+help                      -- get help on a function 
+output                    -- redirect output to file
+quit                      -- exit program 
+scan                      -- scan line from keyboard or file to variable 
+wait                      -- wait until return is typed
+which                     -- show command 
+\end{verbatim}
+Most of these are self-explanatory.  The command ?? prints the system
+variables.  The {\tt help} command will provide help on a single
+command or, without any arguments, will list all available help
+files (this includes general help not associated with a specific
+command).  
+
+\subsection{Shell Programing}
+\begin{verbatim}
+break                     -- escape from function 
+for                       -- loops 
+if                        -- logical cases 
+input                     -- read command lines from a file 
+macro                     -- deal with the macros 
+\end{verbatim}
+
+There are several options for programming in {\tt status}.  First, a
+file which contains a series of commands can be executed with {\tt
+  input (filename)}.  It is also possible to define macros which will
+behave much like regular commands.  A macro is defined by typing {\tt
+  macro name} or {\tt macro create name} followed by the commands.
+Arguments to the macro are assigned to the variables \$1 .. \$N and
+the number of arguments is given by \$0.  Macros may be defined in
+{\tt input} files, and in fact when {\tt status} is started, it loads
+the file {\tt \~/.statusrc} which may contain default macros.  Simple
+loops and if statements can be performed, and are quite useful for
+complex macros.  
+
+``If'' statements are similar in syntax to C if statements, but only
+the following logical operators are available: $>$, $<$, $=$, !, $|$,
+and \&.  Notice that (currently) there is no $>=$ or $<=$ symbol.  The
+operator ! means ``not equal to'', but cannot be used to negate a
+logical value.  The operators $|$ and \& have the meaning of ``or'' and
+``and'' respectively.  Math expresions in the if statement must be
+contained in curly braces, as elsewhere.  Variables with string values
+may use the logical $=$ operator to test if two strings are the same.
+``For'' loops are quite simplistic.  The form is:
+\begin{verbatim}
+for var first last delta
+ (commands)
+end
+\end{verbatim}
+The value of {\tt \$var} will start at the value {\tt first} and increment by
+{\tt delta} after each loop.  The loop will stop after {\tt \$var} is greater
+than {\tt stop}.  The value {\tt delta} is optional, with 1 assumed.
+The value of {\tt \$var} may be changed during the loop, and if set
+beyong the value of {\tt last} will end the loop early.  
+
+\subsection{Vector Plotting}
+
+\begin{verbatim}
+box                       -- draw a box on the plot
+clear                     -- erase plot
+create                    -- create a new vector
+cursor                    -- get coords from cursor
+grid                      -- plot cartesian grid
+hist                      -- create histogram from a vector
+labels                    -- define labels for plot
+limits                    -- define plot limits
+plot                      -- plot a pair of vectors
+print                     -- write vectors to file
+ps                        -- define labels for plot
+set                       -- vector math
+style                     -- set the style for graph plots
+vectors                   -- list vectors
+zplot                     -- plot scaled points 
+\end{verbatim}
+
+In addition to scalar variables, {\tt status} can manipulate and
+display 1-D vector variables.  Many of the commands which extract data
+from the photometry database place the data in vectors as well as
+plotting them.  A vector can also be created based on a number
+sequence with the command {\tt create name Nelements start delta}.
+The resulting vector has $Nelements$ entries, starting at a value of
+$start$ and running until $start + delta*Nelements$.  If $delta$ is
+0.0, all elements will have the value of $start$.  A histogram of a vector
+may be made with the command {\tt hist}, which creates a new vector
+containing the histogram of the first vector.  The data range and bin
+size of the histogram are defined in same way as with create.  This
+makes it easy to create the index vector that goes with a histogram
+vector:  
+\begin{verbatim}
+hist y Ny 1 100 0.1
+create dx 1 100 0.1
+\end{verbatim}
+The above will create a histogram of y in Ny and the index in dx.
+Plotting this with {\tt plot dx Ny} will show the histogram.
+
+Vector math is performed with a command of the form {\tt set new =
+  (expression)}.  The expression is some math function employing
+vectors and scalars.  A complete listing of the math operators
+available in {\tt set} can be found in the help for {\tt set}.
+
+Once vectors are defined, they may be plotted.  A pair of vectors can
+be plotted against each other if they have the same number of entries.
+The plotting is performed on the graphics window, Kapa.  There are
+actually several graphics windows available to {\tt status}, any of
+which may be used to plot at any time.  Some of the more complex
+operations default to either graphics window 0 or 1, depending on the
+context.  Except for those functions with a pre-defined window, all
+plotting functions apply to the current graphics window unless an
+option {\tt -n N} is given to specify a different window.  The
+plotting style is determined by the command {\tt style} which can set
+the line width, the line type (solid, dashed, dotted, etc), the point
+type (box, cross, etc), the point size, the color, and whether a pair
+of vectors is plotted as a sequence of points, a set of connected
+lines, or a histogram.  Some functions which make plots use their own
+styles, as discussed below.  The function {\tt limits} lets the user
+set the range of the plot axes, or check the current setting.  The
+command {\tt plot} will plot a pair of vectors on the current graphics
+window using the current plotting style for that window.  The command
+{\tt zplot} will plot a pair of vectors with the point size scaled by
+a third vector, with maximum and minimum point sizes representing
+specified values.  The {\tt cursor} command goes the other way: this
+command puts the Kapa window in cursor mode and waits for input from
+Kapa.  The user can then type any alphanumeric key on the graphics
+windows and will be told both the pointer location (in the graphics
+coordinates) and will have the coordinates stored in {\tt status}
+variables.  For example, by typing ``1'' in the sky display window,
+the RA and DEC of the pointer are stored in the variables {\tt \$R1}
+and {\tt \$D1}.  This command can be used to let the user define
+locations or regions of interest on the Kapa window. (Future addition:
+{\tt button}, which does the same with the mouse buttons).  
+
+\subsection{Database Functions}
+
+\begin{verbatim}
+gcat                        -- get catalog at location
+gimages                     -- get images at location
+gstar                       -- get star statistics
+extract                     -- extract average vectors from catalogs
+mextract                    -- extract measurement vectors from catalogs
+imstats                    -- plot image statistics
+imextract                   -- extract image vectors from database
+lcat                        -- list catalogs in display region
+cmatch                      -- match two catalogs
+\end{verbatim}
+
+There are a variety of other commands which directly refer to the
+photometry database.  Some of these functions extract data of various
+types from the database, others perform more complex plotting
+operations.  The commands listed above are those which simply extract
+data from the database.  The first three list information relevant to
+a specific RA, DEC location on the sky: {\tt gcat (RA) (DEC)} lists
+the catalog at the specified location and places the name in the
+variable {\tt \$CATNAME}, {\tt gimages (RA) (DEC)} lists all images
+which overlap the specified location, {\tt gstars (RA) (DEC) (RADIUS)}
+lists data about the stars within a specified radius of the specified
+location (all numbers above are given in decimal degrees).  Similarly,
+{\tt lcat} lists the catalogs in the region.  Imstats lists statistics
+about each image
+
+The next three commands extract a specific piece of information from
+the photometry database and places it in a vector.  First, {\tt
+  extract} will extract average values for each star and place it in a
+vector.  Next, {\tt mextract} will extract measurement values for each
+star and place it in a vector: as a result a single star may have
+multiple entries in the measurement vectors.  Finally, {\tt imextract}
+will extract image statistics into vectors (not yet implemented).
+
+
+\begin{verbatim}
+catalog                    -- plot catalog stars
+cgrid                      -- plot sky coordinate grid
+cplot                      -- plot vectors in sky coordinates
+czplot                     -- plot scaled vectors in sky coordinates
+images                     -- plot image boxes
+imdense                    -- image density plot
+lcurve                     -- plot lightcurve for a star
+pcat                       -- plot catalog boundaries
+region                     -- define sky region for plot
+resid                      -- plot residuals
+simage                     -- plot stars in an image
+\end{verbatim}
+
+There are two types of database plotting functions: those that display
+or refer to the spatial charateristics of the data and those that
+refer to other types of charatersitics, such as the time domain.  The
+graphics window 0 is reserved for all plots of objects on the sky.
+The command {\tt region} defines the current sky coordinates for plots
+in graphic window 0.  The command {\tt pcat} plots the outline of all
+photometry database files which are within the currently defined
+region (and by default, only those with data).  {\tt images} plots the
+outline of the images in the image database, while {\tt imdense} shows
+the number of images at a location by randomly spacing dots within the
+boundary of the images.  The command {\tt cgrid}
+draws a grid in celestial coordinates on the for the current region.
+
+The most complex, but also one of the most useful command is {\tt
+  catalog}, which plots the positions of stars in the photometry
+database (and others) on the sky.  There are many options to this
+command.  One set allows the user to plot stars from the photometry
+database (the default), from the HST GSC, or from an ASCII text file
+with RA, DEC, and Mag in specified columns.  If the ASCII file has a
+fixed number of bytes per line, the data can be more quickly loaded.
+The size of the points may be scaled by the star magnitude, by the
+number of observations of the star, or by the number of missing
+datapoints for the star.  In addition, points may be plotted only if
+they land in specified magnitude ranges, or with specified numbers of
+measurements, or missed measurements.  Also, objects may be plotted
+only if they have a specified Average.code, so that only asteroids or
+only perfect stars may be plotted.  The plotted vectors may be saved,
+if desired, and the source catalog epoch may be specified as different
+from J2000 (only valid for ASCII data).
+
+Several other commands relate to non-spatial charateristics of images
+and stars.  {\tt lcurve} will plot a light curve for all stars within
+some radius of a point.  {\tt resid} plots the photometry residuals
+for a particular region file.  
+
+\section{Some Examples}
+
+\begin{figure}
+\psfig{file=allsky.ps,width=16cm}
+\caption{\label{allsky} \small
+  Map of the entire sky, and images added to database.  }
+\end{figure}
+
+Fig.~\ref{allsky} shows a map of the entire sky, and the location
+of the images currently in the database.  This picture was made with
+the following commands: (output is not shown) \\
+\begin{verbatim}
+status: region 0 0 90 gls
+status: cgrid
+status: style -lw 2 -c red 
+status: images
+status: ps
+\end{verbatim}
+In this example, on the graphics window, the image boxes are shown in
+red.  The user now has the possiblitiy of using the cursor command to
+narrow in on a specific region, and so forth.  
+
+\begin{figure}
+\psfig{file=catalog.ps,width=9cm}
+\caption{\label{catalog} \small
+  Comparison between HST GSC and photometry database astrometry.  }
+\end{figure}
+
+Fig.~\ref{catalog} shows an example comparison of the photometry
+database star positions and the HST Guide Star Catalog star
+positions.  The crosses are from the photometry database while the
+boxes are from the HST GSC.  The size of both points is a function of
+brightness.  This plot was made with the following commands (starting
+from the previous image):
+\begin{verbatim}
+status: cursor  (typed 1 on region of interest)
+1 137.097858 22.698305
+q 137.097858 22.698305
+status: region $R1 $D1 0.5 TAN
+status: cgrid
+status: box
+status: style -pt 0 
+status: gcat $R1 $D1 
+  0 n2230/1951.cpt *
+status: catalog n2230/1951.cpt -m 12 18
+status: style -pt 2
+status: catalog n2230/1951.cpt -m 12 18 -g
+\end{verbatim}
+
+\begin{figure}
+\psfig{file=lightcurve.ps,width=9cm}
+\caption{\label{lightcurve} \small
+  Lightcurve for several image stars.  }
+\end{figure}
+
+Fig.~\ref{lightcurve} shows an example lightcurve from three stars in
+the above field.  The x axis shows the time in seconds, which the y
+axis shows the star magnitudes.  This plot was made with the following
+commands (starting from the previous image): {\small
+\begin{verbatim}
+status: cursor
+1 137.062562 22.791860
+q 137.062562 22.791860
+status: lcurve $R1 $D1 0.01 -l
+status: box
+status: gstar $R1 $D1 0.01
+read 11318 stars from catalog file /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt (22462 total measurements)
+508 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.068619 22.785400 18.438000  1 (2)  1.000000 1.000000
+498 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.062820 22.792747 12.882000  3 (0)  1.000000 1.000000
+501 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.064499 22.800817 15.480000  3 (0)  1.000000 1.000000
+\end{verbatim}}
+The last lines show the database information on the three stars.  
+
+\section{Software Distribution}
+
+All of the code, binaries, and scripts for the Pipeline are stored in
+the ohana tree at /metis/d11/src/ohana.  The ohana directory contains
+subdirs of bin, lib, include, src, config, and doc.  There is a
+Makefile at the top level which calls lower-level Makefiles to build
+the programs desired.  One of the important concepts in the ohana
+distribution is the design of the directory layout to enable binary
+support for multiple architectures.  The Makefiles use the environment
+variable ARCH to determine the appropriate architecture.  The binary
+and library files are stored in subdirectories of the form bin/\$ARCH
+and lib/\$ARCH.  It is therefore necessary that users of the ohana
+system architecture define the ARCH variable correctly.  It is also
+necessary to include in the user's PATH the directory
+/metis/d11/ohana/bin/\$ARCH.  At LONEOS,
+with the solaris sparc station and the linux machines both in use,
+ARCH can take on the values of 'linux' and 'sol'.  The values 'sun4',
+'irix', and 'hp' have also been used at various sites.  A simple bit
+of csh script in the users .cshrc or equivalent can make this
+assignment transparently:
+
+\begin{verbatim}
+set sys=`uname -s` 
+switch ($sys)
+ case IRIX64:
+   setenv ARCH irix;
+   breaksw;
+ case SunOS:
+   set ver=`uname -r | awk '{print substr($1,1,1)}'`;
+   if ($ver == 5) then
+     setenv ARCH sol
+   else 
+     setenv ARCH sun4
+   endif
+   breaksw;
+ case Linux:
+   setenv ARCH linux;
+   breaksw;
+ default:
+   echo "unknown architecture";
+   setenv ARCH unknown;
+   breaksw;
+endsw
+\end{verbatim}
+
+The Makefiles use the ARCH variable not only for destination
+directories, but also for destination binary names.  All files of the
+form fred.c are compiled to fred.ARCH.o (instead of fred.o), 
+uninstalled libraries get the names libfred.ARCH.a (instead of
+libfred.a), while uninstalled programs are called fred.ARCH.  
+
+The perl scripts are kept in ohana/src/perl, with links to the
+appropriate bin directories.  All programs are stored in directories
+of the form ohana/src/program.  The exceptions are gastro (stored in
+ohana/src/astro), and control1/2 (stored in ohana/src/astro).  Also, a
+variety of simple, user-level functions are available in
+ohana/src/misc. 
+
+Most of the ohana package of programs use several common libraries.
+These include the readline library (except for dophot, this is the only
+part of ohana that is not written by Eugene Magnier), which is used
+for command-line interface systems.  Other important libraries are the
+fits library for implementing the FITS specifications in a convenient
+C-friendly environment, and the ohana library, consisting of basic
+string and other basic operations.  
+
+For more details on the programming aspects of parts of the pipeline,
+see the associated document, 'A Programmer's Guide to the Loneos
+Pipeline'
+
+\section {Comparison with USNO catalog}
+
+I have made several comparisons between the USNO catalog and results
+from running images from Loneos through the photometry pipeline.  In
+general, there is a good agreement between the astrometry of the two
+datasets.  There are specfic areas where the two disagree, however.
+First, as discussed above, the USNO star positions may be
+significantly different from the observed star positions simply
+because of proper motion.  The first picure in the ``Comparisons
+between Loneos + USNO'' pages shows several stars with significant
+proper motion.  These are currently being flagged in the photometry
+database as discussed.  Other differences evident in this first
+picture include the classification of bright stars and the splitting
+of faint and bright stars.  In the upper right of the image, two
+bright stars are visible, one of which is actually a double.  The USNO
+catalog does a good job of detecting both, but it also detects and
+includes as stars several diffraction spike points.  The HST GSC only
+detected a single point and did not split the star at all.  The Loneos
+data in our pipeline did not detect the star at all due to saturation.
+A star in the upper left corner shows the ability of {\tt dophot} in
+the Loneos pipeline to split double stars.  This star is, on close
+inspection, clearly a double.  The USNO catalog only detects one.  The
+Pipeline not only splits the two stars, but it also makes the correct
+cross-identification of the stars.  
+
+The second set of pictures shows the ability of the Loneos pipeline to
+deal with small galaxies.  There are two small galaxies in this field,
+both of which are broken into 4 or 5 objects by the USNO catalog, but
+maintained as single objects in the Loneos pipeline.  In another
+example (not shown) a bright star within the disk of a small galaxies
+was clearly split from the galaxy by the pipeline (and also by USNO).
+
+\appendix
+\section{Parameter file params.txt}
+\begin{verbatim}
+# Configuration file for Loneos analysis pipeline 
+
+# important files and directories
+IN_DIR                  /pallas
+OUT_DIR                 /irene/d11/workspace
+#
+CATDIR                  /hebe/d27/database
+IMAGE_CATALOG           /hebe/d27/database/Images.dat
+IMAGE_CATALOG_TEMPLATE  /hebe/d27/database/template.cat
+CATALOG_TEMPLATE        /hebe/d27/database/template.cat
+ROCK_CATALOG            /hebe/d27/database/Rocks.dat
+#
+GSCFILE                 /metis/d11/references/GSC/GSCregions.tbl
+GSC_DIR                 /metis/d11/references/GSC
+USNO_CDROM              /metis/d11/references/USNO
+DOPHOT_PARAMS           /metis/d11/references/config/default_parameters
+FLATTEN_SCRIPT          /metis/d11/references/config/flatten.pro
+LONEOS_REGIONS          /metis/d11/references/config/regions.map
+
+# parameters for "fstat"
+# instrumental mag zero point
+ZERO_PT                 24.5
+DOPHOT_CHAR_LINE        129
+DOPHOT_TYPE_FIELD       5
+DOPHOT_AP_FIELD         91
+DOPHOT_PSF_FIELD        52
+MIN_SN_FSTAT            6.0
+
+# parameters for "gastro"
+DEFAULT_RADIUS   32.0
+MINIMUM_RADIUS   1.5
+MIN_ERROR        0.6
+MIN_PRECISE      0.12
+CCD_PC1_1        1
+CCD_PC2_2        -1    # for loneos
+CCD_PC1_2        0
+CCD_PC2_1        0
+ASEC_PIX         2.82
+NFIELD           3.0
+MMIN             6.0
+ROT_ZERO         0
+dROT             1.0
+NROT             2
+POLAR_AXIS_RA    -90.0
+POLAR_AXIS_DEC   89.88
+RA_OFFSET        -90.0
+DEC_OFFSET        0.0
+
+# parameters for "addstar"
+# airmass extinction coefficient (in mag / airmass)
+NSIGMA                  3.0
+ALPHA                   0.03
+XOVERSCAN               60
+YOVERSCAN               50
+
+# parameters for "controller"
+NEW_IMAGES              images.dat
+USERNAME                gene
+PASSWORD                gene
+
+# here we list all available machines
+NMACHINES               6
+MACHINE0                metis
+MACHINE1                hebe
+MACHINE2                iris
+MACHINE3                irene
+#MACHINE4               juno
+MACHINE4                ceres
+MACHINE5                vesta
+
+# here we define which machines which are always free
+fMACHINE0               1
+fMACHINE1               1
+fMACHINE2               1
+fMACHINE3               1
+fMACHINE4               0
+fMACHINE5               0
+fMACHINE6               0
+
+LOCAL_MACHINE           1  # machine with catalog on local disk
+
+# parameters for "status"
+TIME_REFERENCE          90/01/01 00:00:00
+
+# parameters for "nrphot"
+# make this one small to boost change of getting an early region 
+TAU                     3.0             
+SCATTER_LIM             15.0
+MAG_LIM                 17.0
+IMAGE_SCATTER           0.075
+NIMAGE_SCATTER          1.5
+STAR_SCATTER            0.05
+
+### parameters for "markstar"
+SEARCH_RADIUS           360   # region for initial trail hunt, in arcsec 
+TRAIL_WIDTH             5.0   # expected trail width, in arcsec
+NANGLE_BINS             180   # Number of angular bins in 180 degrees
+NPTSINLINE              5     # minimum points needed for trail
+MIN_DENSITY             0.025 # minimum linear density in star/arcsec
+SPACE_SIGMA             10.0  # how much denser than average for trail?
+# parameters defining bright star exclusion regions
+BRIGHT_XTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_XTRAIL_MAG         9.5 # faintest sat. star
+BRIGHT_XTRAIL_SLOPE     -80.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_YTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_YTRAIL_MAG        11.0 # faintest sat. star
+BRIGHT_YTRAIL_SLOPE    -400.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_HALO_MAG           8.5 # faintest sat. star
+BRIGHT_HALO_SLOPE       -28.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+# parameters which define the ghosts
+GHOST_MAG               7.5
+GHOST_RADIUS            200   # in arcsec
+OPTICAL_AXIS1           2154.0
+OPTICAL_AXIS2           2193.0
+
+# parameters for "addusno"
+USNO_RADIUS             5.0   # in arcsec
+USNO_PROPER             20.0   # in arcsec
+USNO_RED                1000  # code for USNO Red data
+USNO_BLUE               1001  # code for USNO Blue data
+
+# parameters for "markrock"
+ROCK_RADIUS             2.0   # in arcsec
+ROCK_MAX_RADIUS         20.0  # in arcsec
+ROCK_MAX_SPEED          0.1   # in arcsec / sec
+\end{verbatim}
+
+\section{Creating New Flats}
+
+The LONEOS implementation of the analysis pipeline has a limited
+ability to choose a flatfield image.  There is a mechanism in the
+stage1 script to select a flatfield on the basis of the photcode
+entry.  It works like this:  there is a fixed directory for all
+flatfield files, currently /metis/d11/reference/.  This directory is
+written in the file flatten.pro, and also in the script stage1.  Each
+flatfield has a name like flatcodeN.fits, where N is the relevant
+photcode.  The mana macro 'flatten' in flatten.pro loads the file
+\$flatdir/flatfield.fits (OR SOMETHING LIKE THAT), which is a link to
+the correct flat.  The script stage1 has the job of deciding which is
+the correct photcode and setting the link appropriately.
+
+This then begs the question of how this flatfield file should be
+created and assigned a new photcode.  The flatfield is NOT made
+nightly from the entire set of data, as one might expect.  This is not
+done because of the problems of scattered light in the telescope.  The
+widefield of the LONEOS telescope makes it somewhat succeptible to
+light at relatively large incident angles.  As a result, a median
+image made from images of the night sky will have different amounts of
+scattered light depending on the overall sky brightness.  In our
+experience, the presence of light clouds and just a small moon (as
+little as a quarter) make the resulting median image a very poor
+representation of the chip response.  Our solution to this problem is
+to choose a good night, in which the sky is very dark, and make a
+flatfield from that collection of images.  As a result, there is too
+much decision-making involved to allow the pipeline to make this
+decision.  Instead, we have chosen to only infrequently make a new
+flat from the data, choosing those nights that we are confident will
+not introduce excess scattered light.  
+
+There are a set of scripts and programs to make the flatfield image.
+The process involves first removing the bias and dark from the image,
+by subtracting a dark image, then medianing the resulting images.
+The mana script FRED performs the dark-subtraction and then
+medianfilter performs the medianing.  In fact, instead of medianing,
+medianfilter returns the average of the fraction of pixels with values
+between f1 and f2 percent of the total range of the pixel data. 
+
+\section{Daily Monitoring of the Pipeline}
+
+On a daily basis, the pipeline generally runs by itself without any
+intervention.  There are a few checks that can be made to be sure the
+process is running OK.
+
+First, it is good to see if the disk space is sufficient.  There is a
+component to stage1 which will keep it from running the analysis if
+there is less space on the destination disk (/irene/d11/workspace)
+than 1.1 times the amount of space in the source directory
+(/pallas/d?/YYMMDD).
+
+Second, it is a good idea to see if the nightly cron job is checking
+for new data and if the data is getting analysed.  If data was created
+lastnight, there should be a set of files in the log directory
+(/metis/d11/logs) of the form YYMMDD.inlist, YYMMDD.addlist, and
+YYMMDD.outlist.  If these files do not exist, it may just mean that no
+data was created last night.  In that case, the tail of the file
+/metis/d11/logs/lastnight should say something like 'there is no new
+data to analyse'.
+
+If data was created, and these files exist, it is a good idea then to
+check that the analysis of the images was reasonable and didn't fail
+on most of the images.  There are two Perl scripts to check on this.
+First, 'checkaddlist [filenames]' will take a list of *.addlist files
+and, for each file, list the total number of images, then the number
+that failed for each of the four stage1 processes, flatten, dophot,
+fstat, and gastro.  A typical run might look like this:
+
+\begin{verbatim}
+hebe: checkaddlist 9907??.addlist
+990701: 206 0 0 0 0
+990703: 199 5 0 0 0
+990705: 150 10 1 0 1
+\end{verbatim}
+
+It is actually unusual for any except the flatten process to fail, but
+it might be typical for 1 or 2 to fail, since they will represent
+aborted images or images which failed to write everything to disk.
+The second Perl script is 'checkoutlist' which works just the same
+with the YYMMDD.outlist files, but only give statistics on the
+'addstar' process.  Here, it is more common for several images to fail
+'addstar'.  At the current time, 'gastro' does not return a fail
+status if it finds a bogus solution.   Images which fail 'gastro' are
+mostly those which were taken when the sky was too bright and all that
+is seen is the sky itself, or the focus frames, or the very short
+images taken of bright stars to check the coords.  If the images fail
+'gastro', they are rejected by 'addstar'.  
+
+\section{Restarting the Pipeline}
+
+It is difficult to predict the future, so it is hard to give guidance
+on solving future problems.  Some of the things which might happen
+would include having one of the machines which serve a disk go down or
+having the disks fill up.  If this happens, it is possible that the
+run of a given night will have failed completely, or mostly.  There
+are a variety of things to do to recover from these situations.
+
+\subsection{Deleting data from the archive}
+
+The program 'delstar' lets the user delete a set of data from the
+database.  There are several options for this.  The first example is:
+{\tt delstar 199902040015b.cmp}.  In this form, delstar uses the
+astrometry information in the image header to find the measurements
+and delete them from the database, along with the image from the image
+database.  This form requires the datafile *.cmp to exist in the local
+directory.  The second form, {\tt delstar 911012323 1}, uses the given
+time in standard FORM (NEED TO DISCUSS TIME FORMATS AND GIVE THEM
+NAMES) to identify the image in the image database and delete both the
+image and the measurements.  It is easy to associate time with image
+with the status function 'findimages' or 'gimage' which list images
+covering a specific location.
+
+The third form of delstar is used to clean up the database if an image
+is deleted but not all measurements from that image are removed.  The
+routine 'addstar' uses the astrometric information for an image and
+the X,Y coordinates of each object in the image to locate the object
+in the database.  Several other routines which do the reverse process of
+finding location of objects within the images.  The function which
+performs this association needs to find all database *.cpt files which
+are covered by the image.  The existing implemenation is relatively
+quick, but not the most general possible.  If an image has extreme
+astrometric problems, yet somehow makes it through the pipeline, it
+will introduce stars which are not easily found by the inversion
+process.  This may be because the image has astrometric parameters
+which make it extremely non-rectilinear.  If such an image is deleted,
+which will probably be desired, some of the stars from that image may
+get left behind.  These orphaned stars can be deleted with the command
+{\tt delstar -orphan STUFF}.
+
+\subsection{Deleting a night from the pipeline}
+
+If the analysis for a specific night fails miserably, it is probably
+necessary to delete the entire night and then encourage the system to
+redo that night.  It is easy to delete an entire night with delstar by
+giving a time interval which includes the night in question.  It is
+also easy to find the value of the time in seconds with the status
+function 'ctimes'.  (At some point, delstar should incorporate the
+code from status which does the time format conversion automatically).
+This process will remove the night in question from the database.  But
+before the pipeline can be re-run, the pipeline needs to be forget
+that it ran that night before.  Every night which has been analysed
+gets included in the log files 'processed.log' and 'addstared.log'.
+The appropriate entry from these files needs to be deleted.  It is
+also necessary to delete the files 'YYMMDD.addlist' and
+'YYMMDD.outlist' from the log directory.  If the 'extracted.log' file
+exists, it should be deleted as well.  All of this is predicated on
+the assumption that the user has halted all processing by the pipeline
+before trying to fix anything.  At this point, it is possible to
+restart the database.  This can be done in several possible ways.  If
+the night in question has already been put on tape, it has to be
+extracted.  The program 'slurp' will automatically find data which has
+not been extracted from the tape, download it, and set up the
+appropriate files.  Unfortunately, 'slurp' uses the file 'tape.log'
+which is not automatically generated.  It is therefore necessary to
+add a line to 'tape.log' (in /metis/d11/logs) for the night in
+question.  Instead of actually running 'slurp', however, the user
+should just run 'stage1 -once' which will perform one run of stage1
+and then end.  If there is no pending data (nothing in 'extracted.log'
+that has not been analysed), then stage1 will automatically call
+'slurp' in the correct fashion (ie, on pallas), run through the
+analysis, and then exit without restarting.
+
+If the night's data has not been deleted yet, then it is not necessary
+to run 'slurp' as the script 'lastnight' will do the job.  The
+cronscript for 'lastnight' uses the -today option so that the
+automatic analysis will not reattempt any nights still on pallas.
+Instead, it will be necessary for the user to run 'lastnight' with the
+-any flag, which will also take care of running 'stage1'. This should
+be safe at anytime, as the lock functions keep multiple instances of
+the programs from running, but it is better to do this with enough
+time to allow the process to finish before the next night's data is
+ready for processing.
+
+If the pipeline has been interrupted, it will probably be necessary to
+restart 'stage2' as well.  Since 'stage2' always restarts itself on
+exit, there is no cron job for it to make the initial start.  (This
+probably should be introduced into the /etc/rc.local file, or some
+cron implementation for stage2 worked out).  Note that both 'stage1'
+and 'stage2' take no arguments except the -once flag.  They make their
+own decisions about the correct log file number and so forth.
+
+If the 'lastnight' cron job gets lost, there is a copy of the
+necessary cron script /metis/d11/src/ohana/src/perl/lastnight.cron.
+This can be submitted with 'crontab lastnight.cron'.  
+
+\section{Data backup}
+
+Backups are the still rather primitive in implementation for the
+LONEOS system.  There are two things which should be backed up, but
+only one currently has a good scheme.  The database itself does not
+have a backup process at the moment.  This is a bad situation, but not
+an easy one to solve.  The database is very large, over 30 GB, which
+is larger than the space on a single AIC tape.  At the moment, we are
+satisfied with simply saving the intermediate results directories, all
+of the YYMMDD.tgz files.  If the entire database is destroyed, these
+files can be used to rebuild the database in a relatively short time
+(currently, about a week).  The script 'backup.stuff' will backup a
+group of files.  A good method is to backup a month at a time.  These
+will become a single tar file on the AIC tape, and a month's worth of
+data is a reasonable amount of disk space for future downloads.
+
+\end{document}
Index: /tags/start/Ohana/doc/pipeline/pipeline6.tex
===================================================================
--- /tags/start/Ohana/doc/pipeline/pipeline6.tex	(revision 12606)
+++ /tags/start/Ohana/doc/pipeline/pipeline6.tex	(revision 12606)
@@ -0,0 +1,2047 @@
+%\documentstyle[astro,psfig]{article}
+\documentclass{article}
+\usepackage{psfig}
+\usepackage{astro}
+\usepackage{times}
+\GoodMargins
+\newcommand{\note}[1]{({\bf #1})}
+\newcommand\pr{\em}                   % font for program names
+\newcommand\ff{\bf}                   % font for file names
+\newcommand\cc{\tt}                   % font for program code
+\newcommand\ty{\sc}                   % font for file types
+
+\title{Variability Pipeline}
+\author{Eugene Magnier}
+
+\begin{document}
+\maketitle
+
+\section{Overview}
+
+Ptolemy is a collection of programs which act together to provide
+automated reduction of images, including photometry and astrometry,
+data validation, and incorporation of the resulting measurements in a
+photometry database organized by star position on the sky.  Ptolemy
+was designed to deal with images produced by LONEOS, the Lowell
+Observatory Near Earth Object Search, to study the data stream with
+astronomical goals in mind beyond just the Near-Earth Objects.  The
+document deals with both the generalities of Ptolemy and also the
+specifics of the LONEOS implementation.  Why Ptolemy?  Two reasons:
+First, Ptolemy, the Roman Astronomery (AD 100-170) was the the first
+to make a systematic map of the entire sky visible from Greece, much
+like LONEOS is doing.  Second, Ptolemy I (367-283 BC), as the founder
+of the Library of Alexandria, represents the ideals of collection and
+organization of large quantities of knowledge).
+
+Fig.~\ref{pipeline} shows a schematic of the {\pr Ptolemy} program
+organzation.  Images to be analysed may be provided to Ptolemy either
+from the telescope or from a tape archive.  Images are first analyzed
+by {\pr dophot}, which produces instrumental photometry and pixel
+coordinate positions for stars and other objects in the images,
+writing files with a particular format, called {\ty obj} files in this
+discussion.  The results from {\pr dophot} are cleaned up by a program
+called {\pr fstat} which merges the header information from the image
+with the most relevant parts of the {\ty obj} file, creating a new
+file with the {\ty cmp} format.  Astrometry is performed on the {\ty
+cmp} file with the program {\pr gastro}.  The program {\pr gastro}
+makes a comparison with an astrometric reference database and only
+changes {\ty cmp} header keywords as a result.  Finally, the processed
+image {\ty cmp} file is added to the photometry database with the
+program {\pr addstar}.  The photometry database is maintained in a
+large number of files ({\ty cpt} files), each representing a small
+region of sky.  There is no relationship between the image locations
+and the boundaries of {\ty cpt} file.  All of the preceeding processes
+occur on individual images, and would typically be performed while the
+observations are occuring, or during the day following, but may be
+performed at any time to add new or archived data to the database.
+
+\begin{figure}
+\psfig{file=schematic.eps,width=9cm}
+\caption{\label{pipeline} \small
+  Schematic of the photometry pipeline.  Rectangles represent
+  programs, while ovals represent data products.  Arrows show the
+  direction of travel of information.  The flatten routine is a filter
+  whose position may change as the pipeline matures.  }
+\end{figure}
+
+Once large batches of images have been processed, a series of programs
+should be run to clean up the photometry database.  First, {\pr
+markstar} identifies bad data (the trails of satelites, the bleeding
+columns from stars, ghost images), and flags these data points
+appropriately.  Second, {\pr addusno} matches the catalog stars with
+stars from the USNO database and adds the USNO magnitudes to the
+photometry database.  Next, {\pr markrock} searches for likely
+asteroids in the {\ty cpt} file, marks them, and writes the asteroid
+observations to an asteroid database.  It also notes measurements
+which are likely to be noise and cosmic rays.  Finally, {\pr nrphot}
+determines relative photometric calibrations for observations in a set
+of {\ty cpt} files.
+
+\section{Image Analysis Pipeline}
+\label{parallel}
+
+\subsection{Configuration and Generalization}
+With the exception of {\pr dophot}, all of the Ptolemy programs refer
+to a single configuration file to determine the large number of
+parameters necessary in the process.  The default parameter file is
+hardwired into the programs, but an alternate configuration file may
+be specified with the environment variable {\ff PIPE\_CONFIG}.  This
+option makes independent processing of multiple data sources trivial.
+For example, if the pipeline is to be used for both Loneos and SDSS
+image analysis and display, there could be two configuration files
+(eg, {\ff loneos.txt} and {\ff sdss.txt}), one for each data source.
+Several important parameters would be different between these two, for
+example, the initial plate scale guess for the astrometry routine, or
+the parameters which define the rough chip orientation.  This scheme
+allows for analysis of different types of images, with a common
+destination photometry database, or for independent photometry
+databases.
+
+Data from different sources can be processed by the pipeline and
+stored in the same photometry database, since all photometry is tagged
+with a source ID in the database (as are the images in the image
+database).  This allows us to include, for example, the USNO catalog
+magnitude measurements (or a subset) in the photometry database for a
+quick comparion.  Different sources may be considered different
+filters, so color-color and color-magnitude diagrams could be
+extracted by specifying choices for source catalog.  Currently each
+object has a single primary photometric system, and individual
+observations may be combined to determine that average (eg, if they
+are different photometry sources with roughly the filter bandpass) or
+they may be ignored when calculating relative magnitudes (eg, the USNO
+magnitudes would be ignored).  This may be expanded upon by defining
+multiple average magnitudes and allowing different measurements to
+contribute only to the appropriate average.  The determination of the
+photometry code for a particular image is currently not well defined.
+There are several points in the analysis where the user (or the
+controlling program) may specify the photometry source.  A table
+should be kept in the photometry catalog to define the various
+photometry codes.  
+
+file names: Notice that we use a consistent naming convention through
+the pipeline reductions.  The image is called {\tt foo.fits}, while
+the resulting dophot-produced photometry list is called {\tt foo.obj}.
+
+\subsection{Time representations in Ptolemy}
+
+Every measurement in the Ptolemy database has a time stamp associated
+with it, as do all of the images.  Throughout the software, the time
+is represented consistently using the standard UNIX representation of
+time, which consists of an unsigned integer representing the number of
+seconds since 1970 Jan 01, midnight.  The time used roughly represents
+UT time, though there is some subtlety here.  In reality, the time
+reported at LONEOS is reported by a GPS clock, and therefore uses the
+GPS zero point.  There are small, well defined differences between UT,
+GPS, and WHAT IS THE THIRD ONE?  GPS - UT is a constant NN seconds,
+while UT - OTHER is a function of time, as leap seconds are
+accumulated in one and not the other.  While the programs all refer to
+this seconds representation of GPS time, the user of the programs
+usually has a few more choices.  In {\pr status}, all(?) functions
+which require a time argument expect to see one of three formats. If
+there is a number of the form NNNNNNNNNs, this is assumed to be the
+UNIX seconds form.  If there is a number of the form NNNNNNj, this is
+assumed to be a Julian date.  If there is a number of the form
+YY:MM:DD,hh:mm:ss, this is assumed to be a UT date string.  Note that
+the difference is in the presence of either 's', 'j', or something
+else at the end of the string.  In the case of a date, it is
+acceptable for the separators to be any non-numerical character, and
+there may even be a trailing separator, as long as it is neither 's'
+nor 'j'.  Command arguments which expect a time range may provide one
+of the following units: 's' (seconds), 'm' (minutes), 'h' (hours), 'd'
+(days).  Also, it is only necessary to provide as many significant
+places in the date as desired.  So, if you are interested in the
+images taken on UT 1999 March 03, you could run {\pr images -im
+99:03:03 1d}.  
+
+The validity range of the UNIX seconds representation of time is 143
+years, so this measurement representation will become ambiguous in the
+year 2113.  Note that the Y2K problem is dealt in the date string by
+assuming any date with year smaller that 70 means 21st century, and
+others are 19th century.  Of course, the user may explicitly type the
+full 4 digit year to ensure an unambiguous answer.  Finally, the user
+may refer to the current time as NOW and the current date as TODAY.
+
+\subsection{Flat Fielding -- Mana / Flatten}
+
+Flat fielding is performed on each image with {\pr mana} (see {\pr
+mana} user's guide) using a script which interacts with the Ptolemy
+controlling software.  The script is contained within a file, {\ff
+flatten.pro}, in the references directory.  The script is invoked by
+calling it on the command line when {\pr mana} is started.  If {\pr
+mana} is started with a file name on the command line, that file is
+loaded with in 'input'.  The file defines a macro '{\pr flatten}', and
+also loads the flat-field file.  The flattening process is actually
+done by calling within {\pr mana} the macro {\pr flatten}, with the
+input and output file names as arguments.  By loading the flat-field
+at the start of {\pr mana}, instead of on each execution of {\pr
+flatten}, we save the load time of each flat-field image (which is 2x
+the size of the basic image, being 4byte floats per pixel).  \note{The
+location of the flat field is currently hard-wired in the {\pr
+flatten} script - this should probably be changed in the future.}  The
+macro loads a flatfield with a specific name and location, which is
+actually a link; The higher-level controlling process ({\pr stage1})
+creates a link to the correct flatfield.  This allows the analysis
+process to use different flatfields for different situations.  At
+LONEOS, we currently use a flat field generated from a well-understood
+night.  This is probably not the best solution as the flatfield
+changes with time.  As discussed below, the photometry solution
+program, nrphot, fits a high-order polynomial to the relative
+photometry, allowing for differences from the correct flatfield.
+ 
+\subsection{Photometry -- Dophot}
+
+Photometry is performed using a varient of {\pr dophot}, based on {\pr
+Dophot 2.0} and adapted to streamline processing of many files.  With
+this version of {\pr dophot}, any FITS format data is safely read in.
+Instead of using staticly defined memory blocks for the images, the
+necessary memory is allocated dynamically.  The image is also
+converted to REAL*32 from the given BITPIX for processing.  Finally,
+only a single, complete parameter file is loaded by dophot.  There is
+no option for a modified and a default parameter file.  The parameter
+file to be used is given, along with the input image and the output
+object list on the command line when the program is run: {\cc dophot
+image.fits image.obj parameter\_file}. To achive these changes, the
+code from {\pr dophot} was wrapped within a C program which interprets
+the command line arguments, allocates the necessary memory, and reads
+in the image.  The rest of the processing is performed by {\pr dophot} in
+the standard manner.  
+
+\subsection{Cleanup -- fstat}
+
+After an image is processed by {\pr dophot}, the object file ({\ff
+foo.obj}) is converted to a more-compact, more-complete file called a
+{\ty cmp} file, with a name of the form ({\ff foo.cmp}).  This
+conversion is done with the program {\pr fstat}.  The {\ty cmp} file
+consists of the FITS header from the original image ({\ff foo.fits}),
+with some additional keywords to be used at later stages in the
+analysis, followed by an ASCII list of the interesting data from ({\ff
+foo.obj}).  In this list, types 6 and 8 are excluded, and only the
+following values are kept:
+\begin{verbatim}
+X       Y     Mag   dMag t log(sky) 
+1342.0  106.1 14.166 000 4 3.2
+\end{verbatim}
+Objects with a signal-to-noise ratio lower than a specified cutoff
+({\cc MIN\_SN\_FSTAT}) are also excluded.  Some general information
+about the image is derived by {\pr fstat} (FWHM, saturation and
+completeness limits, number of each dophot type) and stored as
+keywords in the header.  The photometry source must be specified at
+this stage as one of the command line arguments, though the value used
+may be overridden in one of the stages belowe.  The resulting file can
+now stand on its own without reference to the original image.  The
+keywords used by {\pr fstat} include the minimum signal to noise, a
+rough guess at the zero point ({\cc ZERO\_PT}), and four numbers
+defining the format of the {\pr dophot} {\ty obj} file.
+
+\subsection{Astrometry -- gastro}
+
+Astrometry is performed automatically by the program {\pr gastro}.
+{\pr gastro} loads a {\ty cmp} file and determines an initial guess
+for the center coordinates (based on the RA and DEC header keywords).
+The program also uses the configuration information about the plate
+scale and rough orientation of the image to get close to the final
+solution.  Also, the true sky position of the telescope pole may be
+defined to allow astrometry on images taken close to the pole.  The
+comparison is made with the astrometric catalog, which may be the HST
+Guide Star Catalog, or it may be any source if the data is placed in
+the correct format.  \note{the astrometric reference catalog
+is currently stored in an ASCII format with very limited efficiency.
+It would be nice to make a standard format that has a bit of meta-data
+documentation and probably a binary format to save space.}
+
+\section{The Photometry Database}
+
+\subsection{Photometry File Format}
+The photometry database consists of a large number of photometry files
+representing sections of the sky and a file containing information on
+the images incorporated in the database.  These files are called
+alternatively ``region files'' or {\ty cpt} files (because they have
+the extension {\cc .cpt}).  The photometry files are sorted by
+Declination into different directories, each consisting of a band
+7.5\degree\ wide.  These directories have names like n0730,
+representing the band starting at a Declination of +07:30.  The image
+database ({\ff Images.dat}) is stored in the upper level directory of
+this directory tree.  In fact, the locations of the {\ff Images.dat}
+file, the photometry database, and such are all flexible and may be
+changed by altering the configuration file.  
+
+At LONEOS, the database is stored mostly on a RAID disk on {\ff hebe}
+and a RAID disk mounted on {\ff metis}.  It is easy to split the
+database across multiple file systems by using links.  Within the
+database directory, there are directories for each of 24 Declination
+bands (7.5 degrees tall).  The easiest way of splitting up the data is
+to move some of these subdirectories to another device and creating
+links to them at the appropriate place.  This is currently done by
+having a directory{\ff /metis/d27/database} with the remote
+directories.
+
+The name and location of each sky region comes from the Hubble Space
+Telescope Guide Star Catalog.  There is a file, {\ff GSCregions.tbl},
+which can be used to find the region file appropriate for any location
+on the sky.  A number of routines exist to make such a query.
+
+Each photometry file in the photometry database contains all
+observations and all average values for all stars observed within the
+appropriate region on the sky.  The identity of stars is essentially
+determined by their RA and DEC coordinates.  In very crowded regions,
+the end user may need to double check that a neighboring star is not
+contaminating individual detections (see the discusion on {\pr
+addstar} below).
+
+The photometry files are stored in a binary format, both to reduce the
+volume and to speed access.  As a result, the interpretation of the
+data is machine dependent: little endian machines need to swap the
+data intelligently.  Fortunately, this operation is taken care of
+appropriately, if the programs are compiled with the BYTESWAP option
+set as needed, which is automatically set by the Makefile in the case
+of a Linux machine.  For reference, Suns, SGI, and HP are all big
+endian, while PCs and DECs are little endian.  The automatic
+conversion takes place by using the funcions {\tt Fread} and {\tt Fwrite}
+to substitute for the standard C library {\tt fread} and {\tt fwrite}
+functions.  {\tt Fread} and {\tt Fwrite} are told the datatype being read,
+and they know the layout of the bytes for a particular datatype.
+Anytime the definitions of the relevant structures (see below) are
+changed, {\tt Fread} and {\tt Fwrite} must be updated.  Fortunately, there
+is only one file ({\tt Fread.c}), and it has a single byteswapping
+section, making it easy to adjust the code appropriately.
+
+The format of a single photometry database file consists four
+sections:  
+\begin{itemize}
+\item {\bf header} -- this is a standard FITS header with room for comments
+  about the file or whatever.  Since the rest of the file is not a
+  standard FITS file, the SIMPLE keyword is set to False.  The three
+  necessary keywords are NSTARS, NMEAS, and NMISS, which define the
+  sizes of the next three sections.
+\item {\bf average} -- this section contains all average measurement
+  quantities for each star in the file.  There are NSTARS entries, and
+  each entry is the data from a structure of type Average (defined in
+  loneos.h, and discussed in more detail below).  Thus, the total size
+  in bytes of this section can be found by NSTARS*sizeof(Average).
+\item {\bf measure} -- this section contains the individual
+  measurements for each star in the database.  There are NMEAS
+  entries, and like the average section, each entry is a single
+  structure, in this case of type Measure (in loneos.h, see below).
+  All measurements of a single star are consecutive.  The number of
+  measurements for a single star is defined by average.Nm and the
+  starting entry for a single star is given by average.offset.
+  Therefore, the first measurement of a specific star average[500]
+  would be given by measure[average[500].offset], while the second is 
+  measure[average[500].offset + 1], and so forth.  
+\item {\bf missing} -- this section contains references to all missing
+  measurements of a star.  This means all of those occasions when an
+  image enclosed the location of a star in the database, but no star
+  was detected on the image.  Similar to the case of the measure
+  section, each star has a number of missing entries (which may be 0)
+  given by average.Nn, and the first missing entry is given by
+  average.missing.  Each missing entry value is again a structure of
+  type Missing.  Currently, the only data in the structure is the time
+  of the observation, which allows for an unambiguous recovery of the
+  image where the star was missed.
+\end{itemize}
+
+\subsubsection*{Average Structure defined in loneos.h}
+\begin{verbatim}
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm, Nn;  /* number of measurements, missing */
+  short int Xp;               /* scatter in 1/100 arcsec (-327.67 to +327.67 valid range) */
+  short int Xm;               /* 1000*log(chisq) for magnitude measurement */
+  unsigned short int code;    /* an ID code (ie, star, ghost, satelite, etc) */
+  signed int offset;          /* offset to first measurement */
+  signed int missing;         /* offset to first missing obs */
+} Average; /* 28 bytes / Average */
+\end{verbatim}
+The structure above defines the average data stored in the photometry
+database for each star.  Most of the entries are self-explantory, but
+some need a bit of clarification.  The entry {\tt Xm} is the magnitude
+$\chi^2$ value for the star, under the assumption that the star
+brightness is constant.  This $\chi^2$ incorporates the photometric
+errors on each measurement and is stored as 1000 times the logarithm
+of the $\chi^2$ because high dynamic range is not needed.  The entry
+{\tt Xp} is the scatter about the average postion, in 10
+milli-arcseconds.  As discussed above, the values of {\tt Nm} and {\tt
+  Nn} give the number of measurements and missing observations for
+this star, while the entries {\tt offset} and {\tt missing} point to
+the first {\bf measure} and {\bf missing} entry for this star.  The
+entry {\tt M} is the current best average magnitude solution for this
+star (see the section on Relative Photometry).  Finally, the entry
+{\tt code} is an ID code for each object, which may define a variety
+of things about the object.  For example, if the object is known to be
+variable, or if the object is associated with a USNO star, or if the
+object is a measurement of an asteroid.  See below for details of
+these definitions.
+
+\subsubsection*{Measure Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  short int dR, dD;           /* 1/100 of arcsec (-327.67 to +327.67 valid range) */
+  short int M;                /* thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mcal;             /* image cal mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 to 0.255 valid range) */
+  char dophot;                /* dophot type (1-9) */
+  unsigned short int source;  /* code to identify photometry source */
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+  unsigned int average;       /* reference to corresponding average entry */
+  /* upper byte of Measure.average stores flags:
+   limit of 16,777,215 stars (Naverage) in a file (=0xFFFFFF) 
+   flags: average & 0x1000000 */
+} Measure; /* 20 bytes / Measure */
+\end{verbatim}
+}
+The structure above defines the individual measurement data stored for
+each observation of each star.  The first two entries, dR and dD, are
+the difference between the average coordinates for this star and the
+coordinates determined for this observation.  Clearly, if this
+residual is too large, the individual measurement will not be
+successfully matched with the average star position.  {\tt M} and {\tt
+  dM} are the instrumental magnitude and error for this measurement,
+after correction for the exposure time and a zero point (defined in
+the configuration file as ZERO\_PT).  The entry {\tt t} determines the
+time of the individual observation.  This is important not only for
+timing purposes, but also to determine the source image for this
+observation.  The time and the entry {\tt source} uniquely determine
+the image in the image database that generated this measurement.
+Furthermore, this correspondence allows for determination of the pixel
+coordinates on the chip, by going throught the image astrometry stored
+in the Image database (see below).  The entry {\tt source} is a code which
+identifies the particular CCD/Telescope/Filter setup.  Each unique
+{\tt source} should be treated as an independent filter set for the
+purposes of accurate relative photometric comparisons.  This entry
+also allows external catalog data, such as the USNO or Sloan
+photometry, to be added to the database, as desired.  The entry {\tt
+  average} is a pointer back to the {\bf average} section to allow
+determination of the star from the measurements, in addition to the
+reverse.  The bits of the upper byte of this value are reserved for
+flags used to define particular situations for this measurement.
+Possible values are:
+\begin{itemize}
+\item 1 = BLEND\_IMAGE - the star on the image matched more than one
+  catalog star
+\item 2 = BLEND\_CATALOG - the star in the catalog matched more than
+  one image star
+\item 4 = UPPER\_LIMIT - \note{not really used?}
+\item 8 = CALIBRATED - relative photometry has been performed at least
+  once.
+\end{itemize}
+The entry {\tt dophot} stores the dophot type for this particular
+measurement (1-9: four extra bits in this field).   
+Finally, the value {\tt Mcal} determines the photometric calibration
+of this specific measurment.  This value is an offset appropriate to
+this image (and if needed, this point in time and this chip position)
+to bring the observations of the stars on multiple images to a common
+system (see the section on relative photometry).
+
+\subsection{Image Database}
+
+All images for which photometry has been included in the photometry
+database also have entries in an image database.  The image database
+is (currently) a single file in the upper directory of the photometry
+database.  The name of the file is determined by the IMAGE\_CATALOG
+entry in the configuration file, and is currently set to Images.dat.
+Like the photometry database files, the image database consists of a
+FITS header followed by binary data.  There is only one type of binary
+data: each image has an entry, which is the data from a structure of
+type Image (loneos.h).  The number of images in the file is determined
+by the {\tt NIMAGES} keyword.  If the number of images becomes too
+large, extrapolation of the system to a set of image database files
+with a reference list is quite straightforeward, and could be modeled
+on the organization of the region files (eg, one image database file
+for each Declination directory).
+
+\subsubsection*{Image Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  Coords         coords;            /* 120 bytes */
+  unsigned int   tzero;             /* readout time row 0 in sec (0 - 142 years valid range) */
+  unsigned int   nstar;             /* number of stars on image */
+  short int      secz;              /* thousanths of airmass (valid range -32.000 -- 32.000) */
+  short int      NX, NY;            /* dimensions of image */
+  short int      apmifit, dapmifit; /* aperture correction and error in thousandths of mag */
+  short int      source;            /* identifier for CCD (each ever used will have a unique letter) */
+  short int      Mcal;              /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      dMcal;             /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      Xm;                /* 10*log(image chi-square) */
+  char           name[32];          /* name of original image */
+  unsigned char  detection_limit;   /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  saturation_limit;  /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  cerror;            /* astrometric error: 1/50 of arcsec (0 -- 5.12 valid range) */
+  unsigned char  fwhm_x, fwhm_y;    /* PSF terms in 25*arcsec (valid range 0.0 -- 10.2" ") */
+  unsigned char  trate;             /* 10000 * scan rate in sec/pix (0 -- 0.0256 valid range, 
+                                       typically 0.0146. this is used only to determine the time
+                                       of the observation, not to find the coordinates.  1 byte
+                                       gives 0.11 sec accuracy */
+  float          exptime;           /* exposure time, seconds */
+  char           code;              /* flag to mark an image as bad or whatever */
+  char           dummy[21];         /* extra space for the future */
+  short int      order;             /* number of terms used for Mrel */
+  short int      Mx, My;
+  short int      Mxx, Mxy, Myy;
+  short int      Mxxx, Mxxy, Mxyy, Myyy;
+  short int      Mxxxx, Mxxxy, Mxxyy, Mxyyy, Myyyy;
+} Image;  /* 240 bytes / Image */
+\end{verbatim}}
+
+The structure above lists all of the data stored for each image.  A
+substantial amount of information is stored for each image.  First,
+the astrometric calibration information is stored in a {\tt Coords}
+structure (see coordinate systems, above).  The upper and lower limits
+of the photometry in the database (in instrumental magnitudes) is
+stored in {\tt detection\_limit} and {\tt saturation\_limit}.  These
+values are useful for comparison for those stars where observations
+are missing.  The relationship between time and pixel coordinates is
+given by {\tt tzero} and {\tt trate}.  Drift images will have a scan
+rate stored in {\tt trate}, while staring images will have a value of
+0.0 for this entry ({\tt tzero} then applies to the whole image).
+Other important parameters are kept: the astrometric error ({\tt
+  cerror}), the airmass ({\tt secz}), the exposure time ({\tt
+  exptime}), the number of stars detected ({\tt nstar}), the FWHM
+values ({\tt fwhm\_x, fwhm\_y}), the image name ({\tt name}), and the
+size of the image ({\tt NX, NY}).  The entry {\tt source} is used as
+above to define the CCD/Telescope/Filter used for this observation.
+The entry {\tt code} is used to flag images in various ways.
+Currently, only two bits are used, to define if the image has been
+photometrically calibrated and if the calibration is acceptable.
+There are 21 extra bytes are stored for future additions.
+
+\subsection{Data Incorporation -- {\pr addstar}}
+
+Images which are completely processed ({\pr dophot, fstat, gastro}) are
+then incorporated into the photometry database with the program {\pr 
+addstar}.  This program decides which region files are appropriate
+for this particular image, then one-by-one adds stars from the image
+to the appropriate region file.  Stars already in the catalog are
+matched with stars in the new image purely by a positional comparison.
+In order to avoid the difficulty of comparisons in the RA and DEC
+coordinate frame, a cartesian projection is performed.  The stars from
+the image being processed and the database stars in the same area are
+projected onto a tangent plane and positional comparisons made in this
+(locally cartesian) coordinate frame.  This avoids the dangerous
+singularities at the pole and also makes the RA 0,360\degree\ boundary
+a trivial problem.  
+
+Several choices must be made in the comparison process.  If a star in
+the catalog is matched with a star in the image, the new measurements
+of that star are added to the database.  If a star in the database
+lies in the field of the image, but is not detected, this information
+is added to the list of missing data.  The only data stored in this
+case is the time and source, which is sufficient to unambiguously
+identify the source image from the image database.  This allows later
+programs to find relevant statistics from the image database, if
+necessary.  If a star is detected in the image, but is not already in
+the database, a new entry is added to the database.  In addition, the
+same ``missing data'' from all previous observations images which have
+covered this location (ie, images already in the image database) are
+included.  This last step is necessary so that the image processing
+order is not important.  
+
+Stars also run the danger of being crowded together.  Since all
+comparisons are performed on the basis of position alone, crowded
+fields may make for ambiguous cross-identifications.  A pair of stars
+are matched if the difference in their positions is less than a
+specified search radius (dependent on the scatter in the astrometric
+solution for the image).  If more than one catalog stars are correlated
+with a star in an image, the new measurement is added to {\em both}
+catalog stars, and a flag is set noting that this observation had a
+blended IMAGE.  Conversely, if a single catalog star is matched with
+more than one image star, both new measurements are added to the one
+catalog star, and a different flat is set, noting that this
+observation had a blended CATALOG.
+
+\section{Catalog Update and Cleaning}
+
+Occasionally, once a large number of images have been added to the
+photometry database, a set of programs should be run to clean and
+update the {\ty cpt} files.  This may best be done on {\ty cpt} files after a
+night's worth of data is incorporated.  These routines define bad
+data, identify the USNO catalog stars, and search for asteroids and
+other junk.  Most of the results from these routines are the addition
+of object flags to the Average data structures (Average.code).  Most
+of these routines process data within a single {\ty cpt} file at a time.
+
+\subsection{Markstar}
+
+The first of the update programs, {\pr markstar}, identifies bad data
+and flags it.  It makes three types of identifications: bright stars,
+ghost stars, and trails.  In the first case, it searches the HST guide
+star catalog for bright stars within the field of the current {\ty cpt}
+file.  Three types of pixels are flagged for bright stars.  Any
+measurements within a circular region centered on the star are suspect
+(the ``halo'' of the bright star).  Second, points along the X axis
+are likely to contain flux from the diffraction spikes.  Finally,
+points along the Y axis are likely to have bleeding in addition to the
+diffraction spikes.  Each of these three regions has a different size
+and range which must be defined in the configuration file.  The
+regions are represented by a representative magnitude and a scale
+parameter.  For example, the diameter $d$ of the halo for a star with
+magnitude $m$ is defined as 
+$d = \mbox{BRIGHT\_HALO\_SLOPE} (m - \mbox{BRIGHT\_HALO\_MAG})$.  The X and
+Y axis points are defined by the length of the diffraction spike, with
+an equivalent formula, and the width of the spike.  Since these are
+each independent, there are 8 parameters to define the exclusion
+regions of bright stars.  One of the current drawbacks of this system
+is the reliance on the HST Guide Star photometry.  In the HST Guide
+Star Catalog, only one photometry band is given, so no color
+information is available.  The parameters currently used were defined
+based on a large number of bright stars, with no adjustment for the
+different effective filter system of the Loneos telescope and the HST
+GSC.  Thus, occasionally very red stars will be several magnitudes
+brighter in the real data than reported in the catalog.  As a result,
+large numbers of bad data points in these halos and spikes may be
+missed.  
+
+The second type of bad data flagged by {\pr markstar} are the trails
+from satelite and other space junk.  This portion of the program
+searches for objects which land along a line and which have a high
+linear density.  Parameters may be adjusted to define the width and
+the necessary density or number of points in the line.  Objects in
+lines are also only identified if all observations come from a common
+image.  If an object only has one measurement and it is in a trail,
+the entire Average is flagged to be bad.  However, if an object has
+many measurements and only one is bad, the object is only flagged as
+having some bad data points.  
+
+The third type of bad data are ghost star images.  The HST GSC is
+searched for stars projected across the telescope optical axis, which
+is defined by the user.  All objects within a region of fixed size are
+marked for ghost stars brighter than a specific cutoff magnitude.
+Similar to the trails, the average is marked as bad only if all
+detections of an object are ghost images.  Otherwise, it is noted that
+some data may be bad.
+
+To run 'markstar' by hand, the syntax is: {\pr markstar (file.cpt)}.
+There are several optional flags, which are listed if you type
+markstar by itself.
+
+\subsection{Addusno}
+
+The program {\pr addusno} makes two types of identifications of stars
+with the USNO catalog.  First, it searches for coincidences within a
+small, specified radius.  The choice of this radius is somewhat
+tricky: it is important to catch the association, but also to avoid
+making too many associations.  Unfortunately, astrometric errors in
+the USNO catalog make it necessary to choose a surprisingly large
+radius of 5\asec.  To avoid making double matches (matching the two
+USNO stars to the same photometry database object), only the USNO
+object closest to the object is associated.  There are also a
+substantial number of stars with significant proper motion between the
+USNO epochs and the current date.  It is not unusual to see 8-15\asec\ 
+discrepancy for specific stars.  To catch these objects, any objects
+which do not match the USNO database, but which have more than a
+minimum number of measurements (2 or 3?) are searched for more distant
+USNO companions.  A large, user-specified radius is used for this
+search.  Of course, only USNO stars which are not already matched to
+the database may be candidates for the proper motion match.  This
+stage is susceptible to errors in that a slow-moving solar-system
+object may be associated with a faint USNO star.  For this reason,
+objects flagged as high proper motion stars should be taken with some
+caution.  Of course, during the {\pr addusno} stage, no objects
+already flagged as bad by {\pr markstar} will be matched with USNO
+stars.  
+
+To run 'addusno' by hand, the syntax is: {\pr addusno (file.cpt)}.
+There are several optional flags, which are listed if you type
+addusno by itself.
+
+\subsection{Markrock}
+
+Once stars have been identified with the USNO database, it is possible
+to search for asteroid detections.  The program {\pr markrock}
+searches within a specific {\ty cpt} file for objects which are moving along
+straight lines in (X,Y,t) space.  In order for an object to be found
+by {\pr markrock}, it must have three points, each with only single
+measurements.  The third point must land within a specified distance
+of the line projected from the first two data points.  These
+comparisons are made in the three dimensional space of image position
+and time.  Also, objects are only accepted if they have a speed less
+than a threshold.  If an object is moving too fast, it will make a
+streak on each individual image and will probably be missed anyway.
+Moving objects detected in this way are flagged in the photometry
+database and are also written to a Rock database.  Currently, the Rock
+database just contains ASCII lists of the RA, DEC, Mag, and time for
+each detection.  In fact, the data are stored in pairs of detections,
+with the middle detection saved twice.  This format makes it easy to
+plot lines connecting the points using the connect-the-dots plotting
+style of status/kapa (see below).
+
+One of the current drawbacks of {\pr markrock} is the insistence on
+three observations with only 1 measurement each.  If an object is
+moving too slowly, two of the dectections of the object may be merged
+together.  Enough data is stored in the database to extract these
+individual measurements, so a more sophisticated search is possible.
+It is also currently the case that USNO proper motion stars are
+ignored, but some of these will be asteroid detections which are
+simply too close to a faint USNO stars (it has to be faint because it
+would otherwise be associated with a star in the photometry
+database).  
+
+To run 'markrock' by hand, the syntax is: {\pr markrock (file.cpt)}.
+There are several optional flags, which are listed if you type
+markrock by itself.
+
+\section{Relative Photometry -- nrphot}
+
+Once the data has been incorporated in the photometry database and the
+data validation routines have been run, it is possible to determine
+photometric solutions for all of the images.  The program which does
+this is nrphot.  It tries to find a set of solutions for each image
+which reduce both the scatter per image and the scatter per star.
+\note{the following section is taken from Magnier et al
+1992, A\&A Supp 96, 379.  It could use a little editing to fit the
+reality of the LONEOS implementation.}
+
+In order bring the different measurements to a common photometric
+system, relative photometry was performed to determine calibrations
+for each image.  We used multiple measurements of individual stars on
+overlapping images to connect neighboring images.  It is useful to
+discuss some of the details of this process.  
+
+A typical photometry equation can be written in a form such as:
+\begin{equation}        
+M_{app} = c_{\lambda} + m + a_{\lambda}*\zeta + \gamma_{\Delta\lambda}*(\Delta\lambda) \\
+\label{M_mag}
+\end{equation}
+where $m$ is the instrumental magnitude,
+\begin{equation}        
+m = -2.5\log(N_{e}) + 2.5\log(t). \\
+\label{inst_mag}
+\end{equation}
+$N_{e}$ is the number of electrons measured in a single star, $t$ is
+the exposure time for the image, $M_{app}$ is the apparent magnitude
+of the star in the standard system, $\zeta$ is the airmass of the
+image, and $\Delta\lambda$ is the value of a color index (\ie\ $B-V$
+or $V-I$) for the particular star.  The subscript $\lambda$ refers to
+the filter and the subscript $\Delta\lambda$ refers to the color
+index.  Notice that we are ignoring the second-order color-airmass
+crossterm, and any higher order terms in $\Delta\lambda$ or $\zeta$.
+In all situations, $c_{\lambda}$, $a_{\lambda}$, and
+$\gamma_{\Delta\lambda}$ are calibration coefficients dependent on the
+instruments and the site.  The term $c_{\lambda}$ is a factor to scale
+the response of the detector.  The terms $\gamma_{\Delta\lambda}$ and
+$a_{\lambda}$ give the variation of the sensitivity with the color of
+the star and the airmass.  Also, Eqn. (\ref{M_mag}) is only valid for
+photometric conditions.  Under non-photometric conditions, we need to
+add another term to account for clouds:
+\begin{equation}        
+M_{app} = c_{\lambda} + m + a_{\lambda}*\zeta + \gamma_{\Delta\lambda}*(\Delta\lambda) + clouds \\
+\label{M_cloud}
+\end{equation}
+Now, we can regroup the terms in (\ref{M_cloud}) as follows:
+\begin{equation}        
+m = [M_{app} - \gamma_{\Delta\lambda}*(\Delta\lambda)] - [c_{\lambda} + a_{\lambda}*\zeta + clouds]
+\label{M_sep}
+\end{equation}
+Of the two terms on the right side of equation (\ref{M_sep}), the variables
+in the first pair of brackets are dependent on the properties of the
+star, those in the second pair of brackets are dependent on the image parameters,
+except for $c_{\lambda}$ which is independent of both image and star.
+We can now define the ``relative magnitude'' and the ``calibration
+magnitude'' from (\ref{M_sep}) as follows:
+\begin{eqnarray}
+        m       & = & M_{rel} + M_{cal} \label{rel_phot1}\\
+        M_{rel} & = & [M_{app} - \gamma_{\Delta\lambda}*(\Delta\lambda) + \Delta] \label{color}\\
+        M_{cal} & = & - [c_{\lambda} + a_{\lambda}*\zeta + clouds + \Delta] \label{M_cal}
+\end{eqnarray}
+where $M_{rel}$ is the relative photometric magnitude of the star in
+the internal system and $M_{cal}$ is a correction factor to convert
+instrumental magnitudes to relative magnitudes.  The terms $\Delta$
+are included in eqs. (\ref{color}) and (\ref{M_cal}) to make explicit
+the fact that an arbitrary constant can be added to $M_{rel}$ and
+subtracted from $M_{cal}$.  The goal of relative photometry is to
+determine $M_{cal}$ for each image, then use this $M_{cal}$ to find
+$M_{rel}$ for all stars from eq. (\ref{rel_phot1}).  Once one has
+$M_{rel}$ for each star, one can then convert them to a standard
+system ($M_{app}$) using an equation of the form of
+Eqn. (\ref{color}).  In the case of the LONEOS photometry, the absence
+of a filter makes an effective bandpass which is so wide that it may
+be meaningless to force it to a specific, standard filter.  For the
+sake of variability measurements, it is probably more sensible simply
+to refer to the LONEOS system magnitudes and present a set of color
+terms which give the rough relationship between stars of various
+colors and the LONEOS system. 
+
+In fact, the discussion above make a significant simplification which
+assumes that all images will have a single calibration magnitude
+$M_{cal}$.  In fact, it is the case in the LONEOS system that a
+variety of effects introduce systematic variations across the images.
+For this reason, in practice we extrapolate the above discussion to a
+situation where the value of $M_{cal}$ is allowed to be a function of
+position, and is fit with a 2-D polynomial of some degree.  With the
+LONEOS system, we allow the fit to take polynomials of up to 4th
+order, but only accept the minimum order which significantly reduces
+the scatter for the particular image.
+
+        An equation of the form (\ref{rel_phot1}) exists for each star
+detected on each image.  As described, the value $m$ depends on both
+the particular image and the particular star, the value of $M_{cal}$
+only depends on the image, and the value of $M_{rel}$ only depends on
+the particular star.  Let us label the images with the subscript $i$
+and the stars with the subscript $j$.  Equation (\ref{rel_phot1}) can
+then be written in the form:
+\begin{equation}
+m_{i,j} = M_{rel,j} + M_{cal,i} \label{rel_phot}
+\end{equation}
+Of course, $m_{i,j}$ only exists for certain combinations of images
+and stars: not all stars appear on all images.  In the entire system
+of equations, only one value of $\Delta$ (from eqs. \ref{color} and
+\ref{M_cal}) can be used, but, as noted above, the {\em value}\ of
+$\Delta$ is arbitrary.
+
+        In equation (\ref{rel_phot}), both $M_{rel,j}$ and $M_{cal,i}$
+are unknown quantities.  We can use a method of least squares to find
+these values for the entire set of data.  We try to minimize the chi
+square, defined as:
+\begin{equation}
+\chisq = \sum_{i,j}(m_{i,j} - M_{rel,j} - M_{cal,i})^2 / \sigma_{i,j}^2 \label{chisquare}
+\end{equation}
+where $\sigma_{i,j}$ is the error in the measurement $m_{i,j}$, and
+the index $i$ runs over all images, while the index $j$ runs over all
+stars which are multiply measured, \ie\ those stars which appear on more
+than one image.
+
+        We attempt to minimize \chisq\ analytically by finding the
+derivatives of \chisq\ with respect to $M_{rel,j}$ and $M_{cal,i}$
+and setting them equal to zero:
+\begin{eqnarray}
+\frac{\partial\chisq}{\partial M_{rel,j}} = \sum_{i}-2(m_{i,j} -
+M_{rel,j} - M_{cal,i}) / \sigma_{i,j}^2 = 0  \nonumber \\
+\frac{\partial\chisq}{\partial M_{cal,i}} = \sum_{j}-2(m_{i,j} -
+M_{rel,j} - M_{cal,i}) / \sigma_{i,j}^2 = 0
+\end{eqnarray}
+In these summations, the index $i$ runs over all images in which star
+$j$ appears, and the index $j$ runs over all stars which appear on
+image $i$ which are multiply measured.  Solving the equality leads to
+the following system of equations:
+\begin{eqnarray}
+R_{j}M_{rel,j} = \sum_{i}(m_{i,j} - M_{cal,i}) / \sigma_{i,j}^2 \label{system1} \\
+R_{i}M_{cal,i} = \sum_{j}(m_{i,j} - M_{rel,j}) / \sigma_{i,j}^2 \label{system2}
+\end{eqnarray}
+where 
+\begin{eqnarray}
+R_{i} = \sum_{j}\frac{1}{\sigma_{i,j}^2} \nonumber \\
+R_{j} = \sum_{i}\frac{1}{\sigma_{i,j}^2} 
+\end{eqnarray}
+Again, the index $i$ runs over all images in which star $j$ appears,
+and the index $j$ runs over all stars which appear on image $i$, with
+the restriction of multiple measurements.  The term $\Delta$ from
+eqs. (\ref{color}) and (\ref{M_cal}) acts as an arbitrary zero point
+between the relative and apparent photometric systems.
+
+        Equations (\ref{system1}) and (\ref{system2}) are a set of
+$N_{images} + N_{stars}$ linear equations with $N_{images} +
+N_{stars}$ unknowns.  The unknown parameters are the terms $M_{rel,j}$
+and $M_{cal,i}$.  Unfortunately, $N_{images} + N_{stars}$ is a number
+on the order of 5000 - 10000, thus an analytical solution is
+impractical and an iteration method must be used.  A simple iteration
+method is as follows:
+
+%\SingleSpace
+\begin{enumerate}
+\setlength{\parskip}{-0.05in}
+\item Guess at values for each $M_{cal,i}$.
+\item Use equation (\ref{system1}) to find values for $M_{rel,j}$.  
+\item Substitute these $M_{rel,j}$ values into (\ref{system2}) to get a new
+set of $M_{cal,i}$ values.  
+\item Return to step 1.
+\end{enumerate}
+%\DoubleSpace
+This process is repeated until some criterion is reached, such as the
+\chisq\ no longer changes or reaches a desired minimum.  Although a
+minimum can be found, error propagation causes severe problems
+since images are only connected to neighboring images.  The end point
+images are connected by \approx 50 intermediate images, and errors
+propagating over such a long distance can cause severe errors.  Also,
+$M_{rel,j}$ and $M_{cal,i}$ are not uniquely defined, because of the
+term $\Delta$.  Therefore, during the iteration process, the values of
+$M_{rel,j}$ and $M_{cal,i}$ tend to wander and do not tend to converge
+($M_{cal,i}$ may be incorrect by typically 0.5 mag).  These problems
+can be overcome if some of the values $M_{cal,i}$ or $M_{rel,j}$ are
+known.  In this situation, the known values can be held fixed,
+providing a reference point for the remaining values.  If enough
+values are known across a large enough portion of the data, no image
+is separated from the fixed values by many images, and errors will not
+build up.
+
+        Images taken under photometric conditions provide a set of
+known $M_{cal,i}$ which can be held fixed.  This is true since, if the
+image is taken under photometric conditions, the term $clouds$ in eq.
+(\ref{M_cal}) is by definition 0.  The other terms in this equation
+are either known ($a_{\lambda}*\zeta$) or are constant for all images
+($c_{\lambda}$) and can thus be assigned to a set value, which can
+later be removed with the zero point calibration.  We make an initial
+assumption of the value of $a_\lambda$, but use the data themselves to
+determine a best fit choice for $a_\lambda$.  The task that remains is
+to determine which images were photometric.
+
+        Since the conditions during observations varied greatly from
+night to night, we decided to determine which images were photometric
+from the images themselves.  To do this, we used a variation on the
+iteration method described above.  Before starting the iterations, we
+assume a value for $c_{\lambda}$.  We can choose this arbitrarily, and
+correct for our choice in the correction to an absolute photometric
+system.  Now, we perform the following iteration:
+
+%\SingleSpace
+\begin{enumerate}
+\setlength{\parskip}{-0.05in}
+\item Assume that all images are photometric and determine $M_{cal,i}$.
+\item Find the corresponding values of $M_{rel,j}$ from equation (\ref{system1}).
+\item Use these $M_{rel,j}$ values to find new values for $M_{cal,i}$.
+\item Find the values of $clouds$ for each image from these $M_{cal,i}$
+\item Assume that any image with a value $clouds$ more than 1 standard
+deviation from the mean value (over images) has a substantial cloud
+layer.  
+\item Return to step 1, but use the iterated $M_{cal,i}$ values for those
+images with substantial clouds.
+\end{enumerate}
+%\DoubleSpace
+This process is continued until \chisq (eq. \ref{chisquare}) does not
+change substantially.  Figure (\ref{fig:Mrel}) shows a histogram of
+the occurrences of different $clouds$ values.  There are a few
+important points to make about this figure.  First, there is a
+concentrated peak at 0.  All of these images have essentially zero
+cloud level.  As one would expect, there are a large number of images
+to the right of this peak.  These are the images which were taken
+through some amount of clouds.  Since the exposures were stopped if
+the clouds got too thick, it is not surprising that these images taper
+off at higher cloud levels.  The most curious and telling part of the
+plot is the area below the 0-cloud peak.  There are many images on the
+``negative cloud'' side of the peak.  Because ``negative clouds'' are
+unphysical, there must be a simple explanation for this.
+
+        We calculate the error on the relative calibration of each
+image by finding the scatter of the $M_{cal,i}$ values for each image
+and dividing by $\sqrt{N stars}$.  A histogram of this error for all
+images is shown in Figure (\ref{fig:dMrel}).  We also show the
+variation of the formal photometric error reported by \dophot\ with
+magnitude for each filter in Figure (\ref{fig:dm}).  Now that we have
+the values $M_{cal,i}$, we can calculate the values $M_{rel,j}$ for
+every star on every image.
+
+To run 'nrphot' by hand, the syntax is: {\pr nrphot (file.cpt)}.
+There are several optional flags, which are listed if you type nrphot
+by itself.  \note{discuss the optional flags in some detail}
+
+\begin{figure}
+\psfig{file=flags.eps,width=9cm}
+\caption{\label{flags} \small
+  Pictoral representation of the Average.code flags.  The lower byte
+  value is used for specific definitions of object types.  }
+\end{figure}
+
+\subsection{Data Flags}
+
+The identifications made by the above routines are noted as a set of
+flags in the Average.code structure entry.  Some of these flags are
+mutually exclusive, so a certain bit may have more than one meaning,
+depending on the value of other bits.  Figure~\ref{flags} shows a
+pictoral representation of the meaning of the different bit fields.
+The uppermost bit (bit 15) determines if the object may be considered
+a ``fixed'' star or something which has no fixed location.  If it is
+not fixed, and this bit is 1, then there are several options.  The
+second uppermost bit (bit 14) will be set if this object is one of the
+three types of bad data flagged by {\pr markstar}.  The lower byte of
+code is used to define the type of bad data: ghost, trail, or bleed.
+Thus, any datapoints determined to be a satelite trail will have a
+code value of 0xc002 (49154 decimal).  If an object is a moving
+object, but not a bad datapoint, it may be identified as a ``rock''
+(an asteroid) by the program {\pr markrock}.  In this case, the flag
+for an asteroid is turned on (bit 13).  Thus anything identified as a
+rock by {\pr markrock} will have a code value of 0xa000.  The lower
+byte of code is not yet defined for asteroids, but could be reserved
+for distinguishing different classes of asteroids (ie, on the basis of
+orbital speeds, and so forth).  Objects which are fixed may have a
+variety of possible flags.  First, an object may be identified with a
+USNO star (bit 14).  It may be found to exhibit variability (bit 13),
+implying that the relative photometry routine should ignore it.  If
+may be a transient object (bit 12).  Note that, while an object
+associated with a USNO object may not be transient, an object which is
+variable may also not be associated with a USNO object.  Thus, we need
+seperate bits for variable vs transient.  Different types of variable
+objects may be represented with different values of the lower byte.
+For example, a Cepheid may have a specific lower byte code of 0x01,
+which an RR Lyrae may have a lower byte code of 0x02.  Thus a Cepheid
+associated with the USNO catalog would have a total code value of
+0x6001. Finally, any of these types of non-moving objects may have
+some bad individual measurements (bit 12) or may be found to have a
+significant proper motion (bit 11).  It should be noted that the above
+guidelines for variable stars are suggestions only, and to date (July
+7, 1999), no programs currently assign or define these variability flags. 
+
+\section{Holding it Together}
+
+The preceeding sections describe the step-by-step analysis and
+incorporation of the data from individual images.  However, the power
+of the Pipeline comes in applying it to large numbers of images.  At
+LONEOS, we are using four Pentinum II computers to analyse the roughly 200
+images that are observed each night.  
+
+It is best to think of the analysis of images occurring on groups of
+images from a given night.  Of the set of processes discussed above,
+those in section \ref{parallel} are performed on individual images
+essentially independently of the other images.  The rest of the steps,
+both the data incorporation ({\pr addstar}) and the database cleaning
+routines occur on the entire batch, one image at a time.  Thus, the
+former routines can easily be run in parallel, but the latter routines
+are run in serial to avoid having two programs writing to same part of
+the database at the same time.  In this model, we would process all of
+the images from a night through the parallel stage of the analysis and
+then run the serial stage only after the entire night is finished in
+the parallel stage.  We thus have a natural division of the pipeline
+into two stages.  
+
+The implementation of the two stages involves several programs, some
+of which are specific to the LONEOS situation, and others which are
+more general.  There are two layers of programs which enable batch
+processing of many images and repeated batch processing over many
+nights.  At the highest level, are Perl scripts which choose what data
+needs to be analysed and when.  These scripts tend to be more
+dependent on the details of the LONEOS implementation. At the next
+level down, these scripts principally call two C programs which run
+the images of a given night through the pipeline.  These C programs
+are more general and do not depend on the details of the LONEOS
+implementation.  A defined set of files holds a log of the nights and
+images that have been processed, both for the information of people
+who might want to monitor the progress, but also used by the programs
+to guide decisions about what to analyse next.
+
+\subsection{Data and File Organization}
+
+There are a set of standard locations for all of the files used and
+created by Ptolemy.  These locations have both abstract names used by
+the pipeline programs and specific definitions used in the LONEOS
+implementation.  In general, the definitions of the files are given in
+the configuration file, 'config.txt' (currently located in a
+hard-wired location, but this may soon change to the mechanism used by
+the lastest version of {\pr spicam} (3.0)).  The C programs all refer
+to the config file for the definitions, but the Perl scripts currently
+have the definitions hardwired as variable names defined in the
+beginning of each file.  This should be changed to a mechanism that
+looks in the config file, perhaps implemented by a standard Perl
+function.
+
+Here is a list of the main directories and their meanings:
+
+{\bf logdir: {\ff /metis/d11/logs} - all log files and the files used
+by the Perl scripts to control their actions (except locks) go here.
+
+{\bf workspace}: {\ff /irene/d11/workspace} - the intermediate
+analysis stages go here, and the tarred, gzipped directory files stay
+here.
+
+{\bf dumpspace}: {\ff /pallas/d1} - used by slurp to store images
+downloaded from the tape archive.
+
+{\bf database}: {\ff /hebe/d27/database} - the result database, and
+also the locks and the {\ff Rocks.dat} file.
+
+{\bf references}: {\ff /metis/d11/references} - a variety of reference
+data, including the HST GSC, the USNO catalog, the config files, and
+so forth.
+
+{\bf source}: {\ff /metis/d11/src/ohana} - all of the programs source,
+binaries, and scripts relevant to running the Pipeline are contained
+in these directories.
+
+\subsection{lastnight}
+
+The first step in the process is the Perl script {\pr lastnight},
+which is highly dependent on the specifics of the LONEOS setup.  It
+looks at the disks used by the observers to write the images from a
+given night.  Images are written to a directory called {\ff
+/pallas/d[1-6]/YYMMDD} where {\ff YYMMDD} is an abbreviation for the
+current night's date (ie, 990223).  Many files use this naming scheme,
+so we will refer to such a name as {\ff YYMMDD}.  All of the images
+are stored in this directory with names {\ff yyyyMMDDxxxxb.fits} where
+{\ff yyyy} is the full year, {\ff MM} is month, {\ff DD} is date, and
+{\ff xxxx} is a sequence number.  The 'b' refers to the 'b' CCD, and
+the '.fits' extension is required.  The script {\pr lastnight} is
+called by a cron job scheduled for 7am on {\ff hebe.lowell.edu} (note
+that the clock on hebe is set to PST, not local MST - fix this some
+day!  see also man crontab for details on setting up a cron job).  The
+script searches the disks {\ff /pallas/d[1-6]} for a directory of the
+right form (basically any directory beginning with a number).  By
+default, the program demands that the directory have the name derived
+from today's date, but with the flag {\pr -any}, it will accept any
+directory.  It then checks to see if this directory has been already
+been analysed (ie, it is included in the {\ff processed.log} file).
+If not, it lists all files in that directory with the right ending
+(\ff b.fits}) and places these names in a file, {\ff
+/metis/d11/logs/YYMMDD.inlist}.  It also writes the name of the
+directory (along with some other data) in a file {\ff extracted.log}.
+When it has successfully ended and identified some data, it calls the
+next script, {\pr stage1} and then quits.
+
+\subsection{slurp}
+
+An alternative to {\pr lastnight} is the Perl script {\pr slurp},
+which looks for data on the tape archive.  This script looks at the
+{\ff tape.log} file and compares it to the file {\ff processed.log}|.
+It tries to identify nights listed in the file {\ff tape.log} which
+have not been included in the {\ff processed.log}.  If it finds any,
+it tries to download as much of the data as will fit on the disk {\ff
+/pallas/d1}.  This script is called from within the {\pr stage1}
+script and is invoked if {\pr stage1} is run without any data already
+in the file {\ff extracted.log.
+
+A related pair program are the {\pr load} \& {\pr unload} C programs
+which are needed for loading and unloading the tape jukebox.  The
+first is called with, {\pr load N}, which takes tape number N and
+loads it into the tape drive.  The second version, called with {\pr
+unload N} takes the tape and returns it to its slot.  Note that the
+jukebox does not know by itself what number tape is in the drive, so
+{\pr unload} needs to be told the correct one.  If it is mis-led, it
+will complain and refuse to return the tape.  It is important to check
+on the other users of the tape drive to be sure it is not occupied.
+This is done with the {\pr llock}, {\pr lunlock} and {\pr llockstat}
+programs.  The first, {\pr llock} lets you lock a particular service,
+etc, while the last {\pr llockstat} lists the devices which have been
+allocated.
+
+\subsection{stage1}
+
+The Perl script {\pr stage1} takes the image list produced by {\pr
+lastnight} or {\pr slurp} ({\ff YYMMDD.inlist}) and passes the list to
+the controller program {\pr control1} which performs the parallel
+analysis.  The script has a few features to decide which files have
+been analysed through the pipeline and to what extent.  If {\pr
+stage1} is called, it should be able to figure out 1) if there is data
+ready to be analysed (ie, there is a new date reference in the file
+{\ff extracted.log}), 2) if the data has been partially analysed (ie,
+the date reference in {\ff extracted.log} has not been put in {\ff
+processed.log}, but there are entries in the file {\ff
+YYMMDD.outlist}), and 3) which data needs to be run through which part
+of the pipeline (ie, it decides which of the images in {\ff
+YYMMDD.outlist} have succeeded at which stages of the analysis, and
+starts them at the appropriate spot).  These features are most useful
+if the analysis crashes in the middle or needs to be restarted.  The
+{\pr stage1} script is meant to be run without any arguments and it
+will figure out what needs to be done.  The only possible argument is
+the -once flag.  This flag tells {\pr stage1} to analyse the data it
+finds and quit when it finishes, and not call another instance of
+itself.  Otherwise, when it is done, it will restart itself, and since
+there is no new data in {\ff extracted.log}, it will start a {\pr
+slurp} process to get data from the archive.  If there is no data in
+the archive either, this process will sleep for an hour and try again.
+After a few attempts (2 days?), {\pr stage1} will give up and quit
+without restarting itself.  The script writes a log file called {\ff
+\$scriptdir/stage1.NN.log} where NN is a number in sequence between
+all runs of {\pr stage1}.  A file {\ff stage1.count} keeps track of
+which number NN we are on.  When {\pr stage1} has finished the
+analysis of a night's data, it writes the date in {\ff processed.log}
+to let other processes know what has been analysed.  The bulk of {\pr
+stage1} is not dependent on details of the LONEOS setup, but it does
+expect the files to have the naming scheme described above.
+
+\subsection{stage2}
+The serial stage processes are run by the Perl scrip {\pr stage2}.
+Normally, this script is always running.  It waits for the name of a
+night to be added to the {\ff processed.log} file, presumably by {\pr
+stage1}.  Once it finds a new name in this file, it looks for the
+appropriate images in the file {\ff YYMMDD.addlist}.  It then submits
+the list to the second controlling program {\pr control2}, which runs
+the images through {\pr addstar}.  Images which are successfully run
+through addstar have their {\ff *bf.fits} (flattened image) and {\ff
+*.obj} (dophot output) files deleted.  When the entire night is done,
+the rest of the {\ff *.obj} and {\ff *bf.fits} images are deleted by
+{\pr stage2}, the directory with the {\ff *.cmp} and {\ff *.log} files
+is tared and gzipped into the file {\ff YYMMNN.tgz}.  The directory is
+then deleted.  Finally, {\pr stage2} calls the scripts {\pr
+cleaning.pl} and {\pr run.phot} which runs the cleanup programs ({\pr
+markstar - nrphot}) on the database.  After a successful run, {\pr
+stage2} will automatically respawn a new copy that waits until more
+data arrives.
+
+\subsection{control1 / control2}
+These two C-programs perform the tasks of farming the images out to
+the different machines for analysis.  The two programs are essentially
+identical, but {\pr control1} is allowed to use all machines and {\pr
+control2} can only use one ({\ff hebe.lowell.edu}, which has the database
+local to it).  These controller programs start off by executing remote
+shells (using {\pr ssh}) on a set of machines.  These shells are then used
+to execute the remote commands and are kept open the entire time the
+process runs.  
+
+Both control programs maintain a list of images in a set of queues.  A
+set of rules defines the order in which each image travels through the
+queues.  Each queue is associated with a single process (ie, {\pr
+flatten}, astrometry, etc).  Images which successfully run through a
+queue are sent on to the defined 'next' queue, while images which fail
+are instead sent to the defined 'fail' queue.  In most cases, the
+'fail' queue is a process which marks the image as bad and write the
+name in a file, and then puts the image in the 'done' queue.  However,
+it is possible for the 'fail' queue to be another attempt, such as in
+the case of astrometry.  In this example, images which fail the
+default astrometry are run through a second queue which tries again
+with the {\pr -loneos} flag set (this flag makes the assumption that
+the header information about the LONEOS region number for the image is
+correct, not the RA/DEC information).
+
+The {\pr ssh} connections on the remote machines are handled as child
+processes with communication through the {\ff stdin} and {\ff
+stdout/stderr} pipes.  Messages can be sent back and forth though
+these pipes, and messages which are received from a process associated
+with an image are written to a log file with the name {\ff
+imagename.log} (where imagename is the root name of the image).  The
+only required messages from the program are messages saying
+``SUCCESS'' or ``ERROR''.  The programs therefore all end with either
+of these words.  The programs are started within the controller as a
+command to the shell followed by an echo of ``PROCESS DONE''.  If the
+controller sees the message ``PROCESS DONE'' without either
+``SUCCESS'' or ``FAILURE'' (after waiting an appropriately long time),
+it assumes the program crashed.  Currently, no timeout is available
+for the programs.  The flat-field process is run in {\pr mana} and is
+a slightly special case.  We avoid re-loading the same flat many times
+by starting a {\pr mana} process once and running the flatten
+procedures as {\pr mana} function calls.  The images which are
+analysed (with an indicator of success or failure at each stage) are
+written to a file named {\ff YYMMDD.addlist} by the {\pr control1} and
+\ff YYMMDD.outlist} by {\pr control2}.
+
+\subsection{Lock files}
+
+A variety of locking mechanisms are used to avoid overwriting the
+database or running more than one version of the controlling programs.
+There is a Perl program, {\pr locks}, which allows the user to set or
+check the state of the different locks. All programs which write to
+the database check for the existence of a lock on the database and
+refuse to run if it exists.  The {\pr control1/2} programs and the
+{\pr stage1/2} programs check for their own lock files and only run if
+they don't exist.  Finally, the user can set the locks 'kill' or
+'halt' for either {\pr stage1} or {\pr stage2}.  The first tells the
+process to stop immediately, taking care of bookkeeping first.  The
+second tells the process to finish the current set of images but not
+start a new version.
+
+\subsection{Other Perl Scripts} 
+
+there are several other scripts which are either used to do some
+simple function or may be used by the maintainer to check on the
+status of the Ptolemy exectution.  The two programs {\pr checkoutlist}
+and {\pr checkaddlist} take a list of {\ff YYMMDD.outlist} or {\ff
+YYMMDD.addlist} files and list the number of images in the file and
+the number of successes at each analysis stage.  There programs {\pr
+cleaning.pl} and {\pr run.phot} deal with the cleanup programs and the
+running of {\pr nrphot}.  The program {\pr backup.stuff} takes the
+first 4 characters of the year/month file names and backs up to the
+jukebox tape all tar files for the given month.
+
+\section{Operational Issues and Subtleties}
+
+The current LONEOS system runs principally on four Intel machines
+under Linux.  The existing system has been generally quite stable over
+the past year of operation, but there are some subtleties.  One
+significant issue is the RAID disk attached to {\ff hebe.lowell.edu}.
+This device is a set of three 9 GB disks merged into one 27GB RAID
+disk.  The current problem with the /hebe/d27 RAID results from the
+poor way it was setup.  It was set up without much knowledge of the
+(at the time) rather rudimentary linux RAID system.  As a result, the
+implementation is such that the disk will not automatically be
+configured and mounted at boot time.  There is a script {\ff
+/root/mdstart} which lists the step to setup the RAID correctly.  It
+would be helpful if the {\ff rc.local} or {\ff rc.sysinit} files were
+fixed to start, fsck and mount the RAID automatically at boot.  The
+setup on {\ff metis} is substantially more mature and is correctly
+implemented.  It comes up when the machine boots.
+
+\section{Visualization -- Status}
+
+Visualization of the data in the photometry database can best be
+performed with the program {\pr status}.  This is a command-line
+driven program with a math and macro language which makes it easy to
+perform complex tasks.  
+
+First, a few notes about the user interface.  The interface has an
+interaction similar to {\pr tcsh}.  The arrows allow editing of
+previous commands.  You can also use emacs-like commands such as
+cntl-a to reach the beginning of the line and cntl-e to reach the end.
+There is command and file completion: if you type part of a command
+(as the first thing on a line) and then type tab, it will fill in as
+much as possible, until the word is not unique.  Typing tab twice at
+that point will list the possible endings.  For any but the first word
+on a line, the same thing will happen for the files in the current
+directory.  It is also possible to type just a fraction of a command,
+as long as it is unique.  An ambiguous command will list the possible
+alternatives.  For example:
+\begin{verbatim}
+status: c
+ambiguous command: c ( catalog cgrid clear create cursor )
+\end{verbatim}
+
+The shell is essentially an interpretive programming language.
+Variables are set as follows:
+\begin{verbatim}
+status: $fred = 10
+\end{verbatim}
+Any expression within curly brackets \{\} is assumed
+to be an arithmetical expression and is evaluated before the line is
+executed.  For example:
+\begin{verbatim}
+echo {$fred*dcos(45)}
+\end{verbatim}
+would give the response 7.07107.  There are math functions cos, sin,
+and tan, which operate on radian expressions, and also dcos, dsin,
+dtan, which operate on degree expressions.  There are also the
+equivalent inverse functions: eg., asin and dasin return radians and
+degrees, respectively.  The help section on Math defines all of the
+available math functions.  
+
+\subsection{Miscellaneous Commands}
+\begin{verbatim}
+!                         -- system call
+?                         -- list commands 
+??                        -- list variables 
+echo                      -- type this line 
+exec                      -- system call
+exit                      -- exit program 
+help                      -- get help on a function 
+output                    -- redirect output to file
+quit                      -- exit program 
+scan                      -- scan line from keyboard or file to variable 
+wait                      -- wait until return is typed
+which                     -- show command 
+\end{verbatim}
+Most of these are self-explanatory.  The command ?? prints the system
+variables.  The {\tt help} command will provide help on a single
+command or, without any arguments, will list all available help
+files (this includes general help not associated with a specific
+command).  
+
+\subsection{Shell Programing}
+\begin{verbatim}
+break                     -- escape from function 
+for                       -- loops 
+if                        -- logical cases 
+input                     -- read command lines from a file 
+macro                     -- deal with the macros 
+\end{verbatim}
+
+There are several options for programming in {\pr status}.  First, a
+file which contains a series of commands can be executed with {\tt
+  input (filename)}.  It is also possible to define macros which will
+behave much like regular commands.  A macro is defined by typing {\tt
+  macro name} or {\tt macro create name} followed by the commands.
+Arguments to the macro are assigned to the variables \$1 .. \$N and
+the number of arguments is given by \$0.  Macros may be defined in
+{\tt input} files, and in fact when {\tt status} is started, it loads
+the file {\tt \~/.statusrc} which may contain default macros.  Simple
+loops and if statements can be performed, and are quite useful for
+complex macros.  
+
+``If'' statements are similar in syntax to C if statements, but only
+the following logical operators are available: $>$, $<$, $=$, !, $|$,
+and \&.  Notice that (currently) there is no $>=$ or $<=$ symbol.  The
+operator ! means ``not equal to'', but cannot be used to negate a
+logical value.  The operators $|$ and \& have the meaning of ``or'' and
+``and'' respectively.  Math expresions in the if statement must be
+contained in curly braces, as elsewhere.  Variables with string values
+may use the logical $=$ operator to test if two strings are the same.
+``For'' loops are quite simplistic.  The form is:
+\begin{verbatim}
+for var first last delta
+ (commands)
+end
+\end{verbatim}
+The value of {\tt \$var} will start at the value {\tt first} and increment by
+{\tt delta} after each loop.  The loop will stop after {\tt \$var} is greater
+than {\tt stop}.  The value {\tt delta} is optional, with 1 assumed.
+The value of {\tt \$var} may be changed during the loop, and if set
+beyong the value of {\tt last} will end the loop early.  
+
+\subsection{Vector Plotting}
+
+\begin{verbatim}
+box                       -- draw a box on the plot
+clear                     -- erase plot
+create                    -- create a new vector
+cursor                    -- get coords from cursor
+grid                      -- plot cartesian grid
+hist                      -- create histogram from a vector
+labels                    -- define labels for plot
+limits                    -- define plot limits
+plot                      -- plot a pair of vectors
+print                     -- write vectors to file
+ps                        -- define labels for plot
+set                       -- vector math
+style                     -- set the style for graph plots
+vectors                   -- list vectors
+zplot                     -- plot scaled points 
+\end{verbatim}
+
+In addition to scalar variables, {\tt status} can manipulate and
+display 1-D vector variables.  Many of the commands which extract data
+from the photometry database place the data in vectors as well as
+plotting them.  A vector can also be created based on a number
+sequence with the command {\tt create name Nelements start delta}.
+The resulting vector has $Nelements$ entries, starting at a value of
+$start$ and running until $start + delta*Nelements$.  If $delta$ is
+0.0, all elements will have the value of $start$.  A histogram of a vector
+may be made with the command {\tt hist}, which creates a new vector
+containing the histogram of the first vector.  The data range and bin
+size of the histogram are defined in same way as with create.  This
+makes it easy to create the index vector that goes with a histogram
+vector:  
+\begin{verbatim}
+hist y Ny 1 100 0.1
+create dx 1 100 0.1
+\end{verbatim}
+The above will create a histogram of y in Ny and the index in dx.
+Plotting this with {\tt plot dx Ny} will show the histogram.
+
+Vector math is performed with a command of the form {\tt set new =
+  (expression)}.  The expression is some math function employing
+vectors and scalars.  A complete listing of the math operators
+available in {\tt set} can be found in the help for {\tt set}.
+
+Once vectors are defined, they may be plotted.  A pair of vectors can
+be plotted against each other if they have the same number of entries.
+The plotting is performed on the graphics window, Kapa.  There are
+actually several graphics windows available to {\tt status}, any of
+which may be used to plot at any time.  Some of the more complex
+operations default to either graphics window 0 or 1, depending on the
+context.  Except for those functions with a pre-defined window, all
+plotting functions apply to the current graphics window unless an
+option {\tt -n N} is given to specify a different window.  The
+plotting style is determined by the command {\tt style} which can set
+the line width, the line type (solid, dashed, dotted, etc), the point
+type (box, cross, etc), the point size, the color, and whether a pair
+of vectors is plotted as a sequence of points, a set of connected
+lines, or a histogram.  Some functions which make plots use their own
+styles, as discussed below.  The function {\tt limits} lets the user
+set the range of the plot axes, or check the current setting.  The
+command {\tt plot} will plot a pair of vectors on the current graphics
+window using the current plotting style for that window.  The command
+{\tt zplot} will plot a pair of vectors with the point size scaled by
+a third vector, with maximum and minimum point sizes representing
+specified values.  The {\tt cursor} command goes the other way: this
+command puts the Kapa window in cursor mode and waits for input from
+Kapa.  The user can then type any alphanumeric key on the graphics
+windows and will be told both the pointer location (in the graphics
+coordinates) and will have the coordinates stored in {\tt status}
+variables.  For example, by typing ``1'' in the sky display window,
+the RA and DEC of the pointer are stored in the variables {\tt \$R1}
+and {\tt \$D1}.  This command can be used to let the user define
+locations or regions of interest on the Kapa window. (Future addition:
+{\tt button}, which does the same with the mouse buttons).  
+
+\subsection{Database Functions}
+
+\begin{verbatim}
+gcat                        -- get catalog at location
+gimages                     -- get images at location
+gstar                       -- get star statistics
+extract                     -- extract average vectors from catalogs
+mextract                    -- extract measurement vectors from catalogs
+imstats                    -- plot image statistics
+imextract                   -- extract image vectors from database
+lcat                        -- list catalogs in display region
+cmatch                      -- match two catalogs
+\end{verbatim}
+
+There are a variety of other commands which directly refer to the
+photometry database.  Some of these functions extract data of various
+types from the database, others perform more complex plotting
+operations.  The commands listed above are those which simply extract
+data from the database.  The first three list information relevant to
+a specific RA, DEC location on the sky: {\tt gcat (RA) (DEC)} lists
+the catalog at the specified location and places the name in the
+variable {\tt \$CATNAME}, {\tt gimages (RA) (DEC)} lists all images
+which overlap the specified location, {\tt gstars (RA) (DEC) (RADIUS)}
+lists data about the stars within a specified radius of the specified
+location (all numbers above are given in decimal degrees).  Similarly,
+{\tt lcat} lists the catalogs in the region.  Imstats lists statistics
+about each image
+
+The next three commands extract a specific piece of information from
+the photometry database and places it in a vector.  First, {\tt
+  extract} will extract average values for each star and place it in a
+vector.  Next, {\tt mextract} will extract measurement values for each
+star and place it in a vector: as a result a single star may have
+multiple entries in the measurement vectors.  Finally, {\tt imextract}
+will extract image statistics into vectors (not yet implemented).
+
+
+\begin{verbatim}
+catalog                    -- plot catalog stars
+cgrid                      -- plot sky coordinate grid
+cplot                      -- plot vectors in sky coordinates
+czplot                     -- plot scaled vectors in sky coordinates
+images                     -- plot image boxes
+imdense                    -- image density plot
+lcurve                     -- plot lightcurve for a star
+pcat                       -- plot catalog boundaries
+region                     -- define sky region for plot
+resid                      -- plot residuals
+simage                     -- plot stars in an image
+\end{verbatim}
+
+There are two types of database plotting functions: those that display
+or refer to the spatial charateristics of the data and those that
+refer to other types of charatersitics, such as the time domain.  The
+graphics window 0 is reserved for all plots of objects on the sky.
+The command {\tt region} defines the current sky coordinates for plots
+in graphic window 0.  The command {\tt pcat} plots the outline of all
+photometry database files which are within the currently defined
+region (and by default, only those with data).  {\tt images} plots the
+outline of the images in the image database, while {\tt imdense} shows
+the number of images at a location by randomly spacing dots within the
+boundary of the images.  The command {\tt cgrid}
+draws a grid in celestial coordinates on the for the current region.
+
+The most complex, but also one of the most useful command is {\tt
+  catalog}, which plots the positions of stars in the photometry
+database (and others) on the sky.  There are many options to this
+command.  One set allows the user to plot stars from the photometry
+database (the default), from the HST GSC, or from an ASCII text file
+with RA, DEC, and Mag in specified columns.  If the ASCII file has a
+fixed number of bytes per line, the data can be more quickly loaded.
+The size of the points may be scaled by the star magnitude, by the
+number of observations of the star, or by the number of missing
+datapoints for the star.  In addition, points may be plotted only if
+they land in specified magnitude ranges, or with specified numbers of
+measurements, or missed measurements.  Also, objects may be plotted
+only if they have a specified Average.code, so that only asteroids or
+only perfect stars may be plotted.  The plotted vectors may be saved,
+if desired, and the source catalog epoch may be specified as different
+from J2000 (only valid for ASCII data).
+
+Several other commands relate to non-spatial charateristics of images
+and stars.  {\tt lcurve} will plot a light curve for all stars within
+some radius of a point.  {\tt resid} plots the photometry residuals
+for a particular region file.  
+
+\section{Some Examples}
+
+\note{we need some better and more relevant examples}
+
+\begin{figure}
+\psfig{file=fullsky.ps,width=16cm}
+\caption{\label{allsky} \small
+  Map of the entire sky, and images added to database.  }
+\end{figure}
+
+Fig.~\ref{allsky} shows a map of the entire sky, and the location
+of the images currently in the database.  This picture was made with
+the following commands: (output is not shown) \\
+\begin{verbatim}
+status: region 0 0 90 gls
+status: cgrid
+status: style -lw 2 -c red 
+status: images
+status: ps
+\end{verbatim}
+In this example, on the graphics window, the image boxes are shown in
+red.  The user now has the possiblitiy of using the cursor command to
+narrow in on a specific region, and so forth.  
+
+\begin{figure}
+\psfig{file=polar.ps,width=16cm}
+\caption{\label{polar} \small
+  Map of the sky in polar project, and images added to database.  }
+\end{figure}
+
+Fig.~\ref{allsky} shows a map of the entire sky, and the location of
+the images currently in the database from a polar project.  This
+picture was made with the following commands: (output is not shown) \\ 
+\begin{verbatim}
+status: region 0 0 90 zea
+status: cgrid
+status: style -lw 2 -c red 
+status: images
+status: ps
+\end{verbatim}
+In this example, on the graphics window, the image boxes are shown in
+red.  The user now has the possiblitiy of using the cursor command to
+narrow in on a specific region, and so forth.  
+
+\begin{figure}
+\psfig{file=catalog.ps,width=9cm}
+\caption{\label{catalog} \small
+  Comparison between HST GSC and photometry database astrometry.  }
+\end{figure}
+
+Fig.~\ref{catalog} shows an example comparison of the photometry
+database star positions and the HST Guide Star Catalog star positions.
+The crosses are all objects in the photometry database, while the
+boxes are only the stars identified as USNO stars.  The circles are
+the stars from the HST GSC.  The size of both points is a function of
+brightness.  This plot was made with the following commands (starting
+from the previous image):
+\begin{verbatim}
+status: cursor  (typed 1 on region of interest)
+1 137.097858 22.698305
+q 137.097858 22.698305
+status: region $R1 $D1 0.2 TAN
+status: cgrid
+status: box
+status: style -pt 0 
+status: gcat $R1 $D1 
+  0 n2230/1951.cpt *
+status: style -pt 2; cat -all -m 12 18
+status: style -pt 1; cat -all -m 12 18 -ID $USNO
+status: style -pt 7; cat -all -m 12 18 -g
+\end{verbatim}
+
+\section{Software Distribution}
+
+All of the code, binaries, and scripts for the Pipeline are stored in
+the ohana tree at {\ff /metis/d11/src/ohana}.  The ohana directory contains
+subdirs of bin, lib, include, src, config, and doc.  There is a
+Makefile at the top level which calls lower-level Makefiles to build
+the programs desired.  One of the important concepts in the ohana
+distribution is the design of the directory layout to enable binary
+support for multiple architectures.  The Makefiles use the environment
+variable ARCH to determine the appropriate architecture.  The binary
+and library files are stored in subdirectories of the form {\ff bin/\$ARCH}
+and {\ff lib/\$ARCH}.  It is therefore necessary that users of the ohana
+system architecture define the ARCH variable correctly.  It is also
+necessary to include in the user's PATH the directory
+{\ff /metis/d11/ohana/bin/\$ARCH}.  At LONEOS,
+with the solaris sparc station and the linux machines both in use,
+ARCH can take on the values of 'linux' and 'sol'.  The values 'sun4',
+'irix', and 'hp' have also been used at various sites.  A simple bit
+of csh script in the users .cshrc or equivalent can make this
+assignment transparently:
+
+\begin{verbatim}
+set sys=`uname -s` 
+switch ($sys)
+ case IRIX64:
+   setenv ARCH irix;
+   breaksw;
+ case SunOS:
+   set ver=`uname -r | awk '{print substr($1,1,1)}'`;
+   if ($ver == 5) then
+     setenv ARCH sol
+   else 
+     setenv ARCH sun4
+   endif
+   breaksw;
+ case Linux:
+   setenv ARCH linux;
+   breaksw;
+ default:
+   echo "unknown architecture";
+   setenv ARCH unknown;
+   breaksw;
+endsw
+\end{verbatim}
+
+The Makefiles use the ARCH variable not only for destination
+directories, but also for destination binary names.  All files of the
+form fred.c are compiled to fred.ARCH.o (instead of fred.o), 
+uninstalled libraries get the names libfred.ARCH.a (instead of
+libfred.a), while uninstalled programs are called fred.ARCH.  
+
+The perl scripts are kept in {\ff ohana/src/perl}, with links to the
+appropriate bin directories.  All programs are stored in directories
+of the form {\ff ohana/src/program}.  The exceptions are {\pr gastro}
+(stored in {\ff ohana/src/astro}), and {\pr control1/2} (stored in
+{\ff ohana/src/astro}).  Also, a variety of simple, user-level
+functions are available in {\ff ohana/src/misc}.
+
+Most of the ohana package of programs use several common libraries.
+These include the {\pr readline} library (except for {\pr dophot},
+this is the only part of ohana that is not written by Eugene Magnier),
+which is used for command-line interface systems.  Other important
+libraries are the {\pr fits} library for implementing the FITS
+specifications in a convenient C-friendly environment, and the {\pr
+ohana} library, consisting of basic string and other basic operations.
+
+\section {Comparison with USNO catalog}
+
+I have made several comparisons between the USNO catalog and results
+from running images from Loneos through the photometry pipeline.  In
+general, there is a good agreement between the astrometry of the two
+datasets.  There are specfic areas where the two disagree, however.
+First, as discussed above, the USNO star positions may be
+significantly different from the observed star positions simply
+because of proper motion.  The first picure in the ``Comparisons
+between Loneos + USNO'' pages shows several stars with significant
+proper motion.  These are currently being flagged in the photometry
+database as discussed.  Other differences evident in this first
+picture include the classification of bright stars and the splitting
+of faint and bright stars.  In the upper right of the image, two
+bright stars are visible, one of which is actually a double.  The USNO
+catalog does a good job of detecting both, but it also detects and
+includes as stars several diffraction spike points.  The HST GSC only
+detected a single point and did not split the star at all.  The Loneos
+data in our pipeline did not detect the star at all due to saturation.
+A star in the upper left corner shows the ability of {\pr dophot} in
+the Loneos pipeline to split double stars.  This star is, on close
+inspection, clearly a double.  The USNO catalog only detects one.  The
+Pipeline not only splits the two stars, but it also makes the correct
+cross-identification of the stars.  
+
+The second set of pictures shows the ability of the Loneos pipeline to
+deal with small galaxies.  There are two small galaxies in this field,
+both of which are broken into 4 or 5 objects by the USNO catalog, but
+maintained as single objects in the Loneos pipeline.  In another
+example (not shown) a bright star within the disk of a small galaxies
+was clearly split from the galaxy by the pipeline (and also by USNO).
+
+\appendix
+\section{Parameter file params.txt}
+\note{replace with up-to-date version from Lowell}
+\begin{verbatim}
+# Configuration file for Loneos analysis pipeline 
+
+# important files and directories
+IN_DIR                  /pallas
+OUT_DIR                 /irene/d11/workspace
+#
+CATDIR                  /hebe/d27/database
+IMAGE_CATALOG           /hebe/d27/database/Images.dat
+IMAGE_CATALOG_TEMPLATE  /hebe/d27/database/template.cat
+CATALOG_TEMPLATE        /hebe/d27/database/template.cat
+ROCK_CATALOG            /hebe/d27/database/Rocks.dat
+#
+GSCFILE                 /metis/d11/references/GSC/GSCregions.tbl
+GSC_DIR                 /metis/d11/references/GSC
+USNO_CDROM              /metis/d11/references/USNO
+DOPHOT_PARAMS           /metis/d11/references/config/default_parameters
+FLATTEN_SCRIPT          /metis/d11/references/config/flatten.pro
+LONEOS_REGIONS          /metis/d11/references/config/regions.map
+
+# parameters for "fstat"
+# instrumental mag zero point
+ZERO_PT                 24.5
+DOPHOT_CHAR_LINE        129
+DOPHOT_TYPE_FIELD       5
+DOPHOT_AP_FIELD         91
+DOPHOT_PSF_FIELD        52
+MIN_SN_FSTAT            6.0
+
+# parameters for "gastro"
+DEFAULT_RADIUS   32.0
+MINIMUM_RADIUS   1.5
+MIN_ERROR        0.6
+MIN_PRECISE      0.12
+CCD_PC1_1        1
+CCD_PC2_2        -1    # for loneos
+CCD_PC1_2        0
+CCD_PC2_1        0
+ASEC_PIX         2.82
+NFIELD           3.0
+MMIN             6.0
+ROT_ZERO         0
+dROT             1.0
+NROT             2
+POLAR_AXIS_RA    -90.0
+POLAR_AXIS_DEC   89.88
+RA_OFFSET        -90.0
+DEC_OFFSET        0.0
+
+# parameters for "addstar"
+# airmass extinction coefficient (in mag / airmass)
+NSIGMA                  3.0
+ALPHA                   0.03
+XOVERSCAN               60
+YOVERSCAN               50
+
+# parameters for "controller"
+NEW_IMAGES              images.dat
+USERNAME                gene
+PASSWORD                gene
+
+# here we list all available machines
+NMACHINES               6
+MACHINE0                metis
+MACHINE1                hebe
+MACHINE2                iris
+MACHINE3                irene
+#MACHINE4               juno
+MACHINE4                ceres
+MACHINE5                vesta
+
+# here we define which machines which are always free
+fMACHINE0               1
+fMACHINE1               1
+fMACHINE2               1
+fMACHINE3               1
+fMACHINE4               0
+fMACHINE5               0
+fMACHINE6               0
+
+LOCAL_MACHINE           1  # machine with catalog on local disk
+
+# parameters for "status"
+TIME_REFERENCE          90/01/01 00:00:00
+
+# parameters for "nrphot"
+# make this one small to boost change of getting an early region 
+TAU                     3.0             
+SCATTER_LIM             15.0
+MAG_LIM                 17.0
+IMAGE_SCATTER           0.075
+NIMAGE_SCATTER          1.5
+STAR_SCATTER            0.05
+
+### parameters for "markstar"
+SEARCH_RADIUS           360   # region for initial trail hunt, in arcsec 
+TRAIL_WIDTH             5.0   # expected trail width, in arcsec
+NANGLE_BINS             180   # Number of angular bins in 180 degrees
+NPTSINLINE              5     # minimum points needed for trail
+MIN_DENSITY             0.025 # minimum linear density in star/arcsec
+SPACE_SIGMA             10.0  # how much denser than average for trail?
+# parameters defining bright star exclusion regions
+BRIGHT_XTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_XTRAIL_MAG         9.5 # faintest sat. star
+BRIGHT_XTRAIL_SLOPE     -80.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_YTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_YTRAIL_MAG        11.0 # faintest sat. star
+BRIGHT_YTRAIL_SLOPE    -400.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_HALO_MAG           8.5 # faintest sat. star
+BRIGHT_HALO_SLOPE       -28.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+# parameters which define the ghosts
+GHOST_MAG               7.5
+GHOST_RADIUS            200   # in arcsec
+OPTICAL_AXIS1           2154.0
+OPTICAL_AXIS2           2193.0
+
+# parameters for "addusno"
+USNO_RADIUS             5.0   # in arcsec
+USNO_PROPER             20.0   # in arcsec
+USNO_RED                1000  # code for USNO Red data
+USNO_BLUE               1001  # code for USNO Blue data
+
+# parameters for "markrock"
+ROCK_RADIUS             2.0   # in arcsec
+ROCK_MAX_RADIUS         20.0  # in arcsec
+ROCK_MAX_SPEED          0.1   # in arcsec / sec
+\end{verbatim}
+
+\section{Creating New Flats}
+
+The LONEOS implementation of the analysis pipeline has a limited
+ability to choose a flatfield image.  There is a mechanism in the
+stage1 script to select a flatfield on the basis of the photcode
+entry.  It works like this: there is a fixed directory for all
+flatfield files, currently {\ff /metis/d11/reference}.  This directory
+is written in the file {\ff flatten.pro}, and also in the script {\pr
+stage1}.  Each flatfield has a name like {\ff flatcodeN.fits}, where N
+is the relevant photcode.  The {\pr mana} macro '{\pr flatten}' in
+{\ff flatten.pro} loads the file {\ff \$flatdir/flatfield.fits} (OR
+SOMETHING LIKE THAT), which is a link to the correct flat.  The script
+{\pr stage1} has the job of deciding which is the correct photcode and
+setting the link appropriately.
+
+This then begs the question of how this flatfield file should be
+created and assigned a new photcode.  The flatfield is NOT made
+nightly from the entire set of data, as one might expect.  This is not
+done because of the problems of scattered light in the telescope.  The
+widefield of the LONEOS telescope makes it somewhat succeptible to
+light at relatively large incident angles.  As a result, a median
+image made from images of the night sky will have different amounts of
+scattered light depending on the overall sky brightness.  In our
+experience, the presence of light clouds and just a small moon (as
+little as a quarter) make the resulting median image a very poor
+representation of the chip response.  Our solution to this problem is
+to choose a good night, in which the sky is very dark, and make a
+flatfield from that collection of images.  As a result, there is too
+much decision-making involved to allow the pipeline to make this
+decision.  Instead, we have chosen to only infrequently make a new
+flat from the data, choosing those nights that we are confident will
+not introduce excess scattered light.  
+
+There are a set of scripts and programs to make the flatfield image.
+The process involves first removing the bias and dark from the image,
+by subtracting a dark image, then medianing the resulting images.
+\note{find these scripts...}  In fact, instead of medianing,
+medianfilter returns the average of the fraction of pixels with values
+between f1 and f2 percent of the total range of the pixel data.
+
+\section{Daily Monitoring of the Pipeline}
+
+On a daily basis, the pipeline generally runs by itself without any
+intervention.  There are a few checks that can be made to be sure the
+process is running OK.
+
+First, it is good to see if the disk space is sufficient.  There is a
+component to stage1 which will keep it from running the analysis if
+there is less space on the destination disk ({\ff /irene/d11/workspace})
+than 1.1 times the amount of space in the source directory
+({\ff /pallas/d?/YYMMDD}).
+
+Second, it is a good idea to see if the nightly cron job is checking
+for new data and if the data is getting analysed.  If data was created
+last night, there should be a set of files in the log directory ({\ff
+/metis/d11/logs}) of the form {\ff YYMMDD.inlist}, {\ff
+YYMMDD.addlist}, and {\ff YYMMDD.outlist}.  If these files do not
+exist, it may just mean that no data was created last night.  In that
+case, the tail of the file {\ff /metis/d11/logs/lastnight} should say
+something like 'there is no new data to analyse'.  \note{It would be
+nice to include some notification scripts at the end of {\pr
+lastnight}, {\pr stage1} and {\pr stage2} which sent some mail
+describing what had been accomplished the previous night}.
+
+If data was created, and these files exist, it is a good idea then to
+check that the analysis of the images was reasonable and didn't fail
+on most of the images.  There are two Perl scripts to check on this.
+First, {\pr checkaddlist [filenames]} will take a list of {\ff
+*.addlist} files and, for each file, list the total number of images,
+then the number that failed for each of the four {\pr stage1}
+processes, {\pr flatten}, {\pr dophot}, {\pr fstat}, and {\pr gastro}.
+A typical run might look like this:
+
+\begin{verbatim}
+hebe: checkaddlist 9907??.addlist
+990701: 206 0 0 0 0
+990703: 199 5 0 0 0
+990705: 150 10 1 0 1
+\end{verbatim}
+
+It is actually unusual for any except the {\pr flatten} process to
+fail, and it might be typical for 1 or 2 of those to fail, since they
+will represent aborted images or images which failed to write
+everything to disk.  The second Perl script is {\pr checkoutlist}
+which works just the same with the {\ff YYMMDD.outlist} files, but
+only give statistics on the {\pr addstar} process.  Here, it is more
+common for several images to fail {\pr addstar}.  At the current time,
+{\pr gastro} does not always return a fail status if it finds a bogus
+solution (recent work in late July may have fixed all of those fail
+status messages).  Images which fail {\pr gastro} are mostly those
+which were taken when the sky was too bright and all that is seen is
+the sky itself, or the focus frames, or the very short images taken of
+bright stars to check the coords.  If the images fail {\pr gastro} but
+do not get rejected with an error status, they are rejected by {\pr
+addstar} on the basis of header keywords which will say 0 stars used
+astrometry.  It is also the case that {\pr gastro} should return a
+failure status if the astrometric solution is sufficiently far from
+Cartesian.  In general, the astrometry does not fail with a solution
+close to the correct solution.  I have found several examples of
+images with extremely wrong astrometric solutions, with very large
+non-Cartesian images on the sky.  There are also a number of failures
+near the pole with signficantly off astrometry, but close to an
+accurate solution.  The should now be rejected by {\pr gastro}.
+
+\section{Restarting the Pipeline}
+
+It is difficult to predict the future, so it is hard to give guidance
+on solving future problems.  Some of the things which might happen
+would include having one of the machines which serve a disk go down or
+having the disks fill up.  If this happens, it is possible that the
+run of a given night will have failed completely, or mostly.  There
+are a variety of things to do to recover from these situations.
+
+\subsection{Deleting data from the archive}
+
+The program {\pr delstar} lets the user delete a set of data from the
+database.  There are several options for this.  The first example is:
+{\pr delstar 199902040015b.cmp}.  In this form, delstar uses the
+astrometry information in the image header to find the measurements
+and delete them from the database, along with the image from the image
+database.  This form requires the datafile *.cmp to exist in the local
+directory.  The second form, {\pr delstar 911012323 1}, uses the given
+time in standard UNIX seconds form to identify the image in the image
+database and delete both the image and the measurements.  \note{does
+delstar expect a UNIX seconds date, or can it take any of the
+variations available in 'status'?}  It is easy to associate time with
+image with the status function {\pr findimages} or {\pr gimage} which
+list images covering a specific location.
+
+The third form of {\pr delstar} is used to clean up the database if an
+image is deleted but not all measurements from that image are removed.
+The routine {\pr addstar} uses the astrometric information for an
+image and the X,Y coordinates of each object in the image to locate
+the object in the database.  Several other routines do the reverse
+process of finding the location of objects within the images.  The
+function which performs this association needs to find all database
+*.cpt files which are covered by the image.  The existing
+implemenation is relatively quick, but not the most general possible.
+In some rare cases, parts of an image will not be found.  This is
+normally not an issue since few functions need to find all stars in a
+given image from scratch.  However, if such an image is deleted, some
+of the stars from that image may get left behind.  These orphaned
+stars can be deleted with the command {\pr delstar region.cpt -orphan
+STUFF??}.
+
+\subsection{Deleting a night from the pipeline}
+
+If the analysis for a specific night fails miserably, it is probably
+necessary to delete the entire night and then encourage the system to
+redo that night.  It is easy to delete an entire night with {\pr
+delstar} by giving a time interval which includes (only) the night in
+question.  It is also easy to find the value of the time in seconds
+with the {\pr status} function {\pr ctimes}.  (At some point, {\pr
+delstar} should incorporate the code from {\pr status} which does the
+time format conversion automatically).  This process will remove the
+night in question from the database.  But before the analysis can be
+re-run, Ptolemy needs to forget that it already ran that night before.
+Every night which has been analysed gets included in the log files
+{\ff processed.log} and {\pr addstared.log}.  The appropriate entry
+from these files needs to be deleted.  It is also necessary to delete
+the files {\ff YYMMDD.addlist} and {\ff YYMMDD.outlist} from the log
+directory.  If the {\ff extracted.log} file exists, it should be
+deleted as well.  All of this is predicated on the assumption that the
+user has halted all processing by Ptolemy before trying to fix
+anything.  At this point, it is possible to restart the analysis.
+This can be done in several possible ways.  If the night in question
+has already been put on tape, it has to be extracted.  The program
+{\pr slurp} will automatically find data which has not been extracted
+from the tape, download it, and set up the appropriate files.
+Unfortunately, {\pr slurp} uses the file {\ff tape.log} which is not
+automatically generated.  It is therefore necessary to add a line to
+{\ff tape.log} (in {\ff /metis/d11/logs}) for the night in question,
+which should look just like the entry in the directory {\ff
+pallas:/root/tape.log}.  Instead of actually running {\pr slurp},
+however, the user should just run {\pr stage1 -once} which will
+perform one run of {\pr stage1} and then end.  If there is no pending
+data (nothing in {\ff extracted.log} that has not been analysed), then
+{\pr stage1} will automatically call {\pr slurp} in the correct
+fashion (ie, on {\ff pallas}), run through the analysis, and then exit
+without restarting.
+
+If the night's data has not been deleted yet, then it is not necessary
+to run {\pr slurp} as the script {\pr lastnight} will do the job.  The
+cronscript for {\pr lastnight} uses the -today option so that the
+automatic analysis will not reattempt any nights still on pallas.
+Instead, it will be necessary for the user to run {\pr lastnight
+-any}, which will also take care of running {\pr stage1}. This should be
+safe at anytime, as the lock functions keep multiple instances of the
+programs from running, but it is better to do this with enough time to
+allow the process to finish before the next night's data is ready for
+processing.
+
+If the pipeline has been interrupted, it will probably be necessary to
+restart {\pr stage2} as well.  Since {\pr stage2} always restarts
+itself on exit, there is no cron job for it to make the initial start.
+(This probably should be introduced into the /etc/rc.local file, or
+some cron implementation for {\pr stage2} worked out).  Note that both
+{\pr stage1} and {\pr stage2} take no arguments except the optional
+{\pr -once} flag.  They make their own decisions about the correct log
+file number and so forth.
+
+If the {\pr lastnight} cron job gets lost, there is a copy of the
+necessary cron script {\ff
+/metis/d11/src/ohana/src/perl/lastnight.cron}.  This can be submitted
+with {\pr crontab lastnight.cron}.
+
+\section{Data backup}
+
+Backups are the still rather primitive in implementation for the
+LONEOS system.  There are two things which should be backed up, but
+only one currently has a good scheme.  The database itself does not
+have a backup process at the moment.  This is a bad situation, but not
+an easy one to solve.  The database is very large, over 30 GB, which
+is comparable to the space on a single AIC tape.  At the moment, we
+are satisfied with simply saving the intermediate results directories,
+all of the {\ff YYMMDD.tgz} files.  If the entire database is
+destroyed, these files can be used to rebuild the database in a
+relatively short time (currently, about a week).  The script {\pr
+backup.stuff} will backup a group of files.  A good method is to
+backup a month at a time.  These will become a single tar file on the
+AIC tape, and a month's worth of data is a reasonable amount of disk
+space for future downloads.
+
+\end{document}
+
+At LONEOS, the images are
+written to the disk from the camera by {\pr astrocam}, the camera
+controller user interface.  The resulting images are FITS files (which
+may be arbitrarily sized) and have header keyword parameters RA and
+DEC specifying rough celestial coordinates.  
Index: /tags/start/Ohana/doc/pipeline/schematic.fig
===================================================================
--- /tags/start/Ohana/doc/pipeline/schematic.fig	(revision 12606)
+++ /tags/start/Ohana/doc/pipeline/schematic.fig	(revision 12606)
@@ -0,0 +1,214 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter  
+100.00
+Single
+-2
+1200 2
+6 2400 375 3600 825
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 2400 375 3600 375 3600 825 2400 825 2400 375
+4 0 0 0 0 0 18 0.0000 4 150 975 2550 750 astrocam\001
+-6
+6 2400 2250 3600 2700
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 2400 2250 3600 2250 3600 2700 2400 2700 2400 2250
+4 0 0 0 0 0 18 0.0000 4 240 750 2550 2625 dophot\001
+-6
+6 2400 1125 3600 1875
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 3000 1500 600 375 3000 1500 3600 1875
+4 0 0 0 0 0 18 0.0000 4 180 540 2625 1575 *.fits\001
+-6
+6 2475 2925 3675 3675
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 3075 3300 600 375 3075 3300 3675 3675
+4 0 0 0 0 0 18 0.0000 4 240 540 2700 3375 *.obj\001
+-6
+6 2475 4650 3675 5400
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 3075 5025 600 375 3075 5025 3675 5400
+4 0 0 0 0 0 18 0.0000 4 240 660 2700 5100 *.cmp\001
+-6
+6 600 4800 1800 5250
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 600 4800 1800 4800 1800 5250 600 5250 600 4800
+4 0 0 0 0 0 18 0.0000 4 210 660 750 5175 gastro\001
+-6
+6 4425 4800 5625 5250
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 4425 4800 5625 4800 5625 5250 4425 5250 4425 4800
+4 0 0 0 0 0 18 0.0000 4 180 780 4575 5175 addstar\001
+-6
+6 8775 4425 9975 4875
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 8775 4425 9975 4425 9975 4875 8775 4875 8775 4425
+4 0 0 0 0 0 18 0.0000 4 150 615 8925 4800 status\001
+-6
+6 525 2850 1875 4050
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 1200 3450 675 600 1200 3450 1875 4050
+4 0 0 0 0 0 18 0.0000 4 210 975 750 3525 Astro dB\001
+4 0 0 0 0 0 18 0.0000 4 225 690 825 3825 (HST)\001
+-6
+6 8475 1725 10125 2925
+1 1 0 1 0 7 0 0 -1 4.000 1 0.0000 9300 2325 825 600 9300 2325 10125 2925
+4 0 0 0 0 0 18 0.0000 4 240 855 8850 2565 pictures\001
+4 0 0 0 0 0 18 0.0000 4 210 765 8850 2250 results,\001
+-6
+6 6300 1725 7950 2925
+1 1 0 1 0 7 0 0 -1 4.000 1 0.0000 7125 2325 825 600 7125 2325 7950 2925
+4 0 0 0 0 0 18 0.0000 4 180 480 6900 2250 alert\001
+-6
+6 4200 750 5850 1950
+1 1 0 1 0 7 0 0 -1 4.000 1 0.0000 5025 1350 825 600 5025 1350 5850 1950
+4 0 0 0 0 0 18 0.0000 4 210 885 4575 1275 postage \001
+4 0 0 0 0 0 18 0.0000 4 210 750 4575 1590 stamps\001
+-6
+6 750 1275 1725 1650
+2 2 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 750 1275 1725 1275 1725 1650 750 1650 750 1275
+4 0 0 0 0 0 18 0.0000 4 180 690 825 1575 flatten\001
+-6
+6 2475 3900 3675 4350
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 2475 3900 3675 3900 3675 4350 2475 4350 2475 3900
+4 0 0 0 0 0 18 0.0000 4 180 465 2625 4275 fstat\001
+-6
+6 4425 6225 5625 6675
+6 4575 6375 5475 6600
+4 0 0 0 0 0 18 0.0000 4 180 900 4575 6600 addusno\001
+-6
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 4425 6225 5625 6225 5625 6675 4425 6675 4425 6225
+-6
+6 4425 5550 5625 6000
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 4425 5550 5625 5550 5625 6000 4425 6000 4425 5550
+4 0 0 0 0 0 18 0.0000 4 180 945 4575 5925 markstar\001
+-6
+6 4425 6900 5625 7350
+6 4425 6900 5625 7350
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 4425 6900 5625 6900 5625 7350 4425 7350 4425 6900
+-6
+4 0 0 0 0 0 18 0.0000 4 180 1035 4575 7275 markrock\001
+-6
+6 4425 7575 5625 8025
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 4425 7575 5625 7575 5625 8025 4425 8025 4425 7575
+4 0 0 0 0 0 18 0.0000 4 240 705 4575 7950 nrphot\001
+-6
+6 6225 4425 8025 7725
+6 6450 5925 7800 7125
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 7125 6525 675 600 7125 6525 7800 7125
+4 0 0 0 0 0 18 0.0000 4 210 810 6675 6600 Star dB\001
+-6
+6 6450 4650 7800 5850
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 7125 5250 675 600 7125 5250 7800 5850
+4 0 0 0 0 0 18 0.0000 4 240 1050 6675 5325 Image dB\001
+-6
+2 4 1 1 0 7 0 0 -1 4.000 0 0 7 0 0 5
+	 8025 7725 8025 4425 6225 4425 6225 7725 8025 7725
+4 0 0 0 0 0 18 0.0000 4 210 1395 6375 7575    Photom dB\001
+-6
+6 1500 5700 2850 6900
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 2175 6300 675 600 2175 6300 2850 6900
+4 0 0 0 0 0 18 0.0000 4 210 1110 1650 6375 USNO dB\001
+-6
+6 1500 7200 2850 8400
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 2175 7800 675 600 2175 7800 2850 8400
+4 0 0 0 0 0 18 0.0000 4 210 945 1725 7875 Rock dB\001
+-6
+2 2 1 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 2775 975 3150 975 3150 1050 2775 1050 2775 975
+2 2 1 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 2775 2025 3225 2025 3225 2100 2775 2100 2775 2025
+2 1 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 2
+	 3075 3675 3075 3900
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 3075 4350 3075 4650
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 3000 2700 3000 2925
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 3000 1875 3000 2250
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 3000 825 3000 1125
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 2475 5025 1800 5025
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 3675 5025 4425 5025
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 5625 5025 6225 5025
+2 1 3 1 0 7 0 0 -1 4.000 0 0 -1 0 1 3
+	0 0 1.00 60.00 120.00
+	 2775 975 1350 975 1350 1275
+2 1 3 1 0 7 0 0 -1 4.000 0 0 -1 0 1 4
+	0 0 1.00 60.00 120.00
+	 2775 2025 1425 2025 1350 2025 1350 1650
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 6450 3525 7650 3525 7650 3975 6450 3975 6450 3525
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 5625 5775 6225 5775
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 7050 3975 7050 4425
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 3600 4875 4575 3150
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 3600 1575 4575 2850
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 4575 2775 5775 2775 5775 3225 4575 3225 4575 2775
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 4950 3225 4950 4800
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 7050 3525 7050 2925
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 4950 2775 4950 1950
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 0 1 2
+	0 0 1.00 60.00 120.00
+	 8775 4650 8025 4650
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 1
+	 9375 4425
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 9300 4425 9300 2925
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 5625 6450 6225 6450
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 5625 7125 6225 7125
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 5625 7800 6225 7575
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 2850 7800 4425 7125
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 2850 6300 4425 6450
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 1200 4050 1200 4800
+4 0 0 0 0 0 18 0.0000 4 180 465 6900 2625 files\001
+4 0 0 0 0 0 18 0.0000 4 225 810 6675 3825 (filters)\001
+4 0 0 0 0 0 18 0.0000 4 180 675 4800 3075 imdiff\001
Index: /tags/start/Ohana/doc/pipeline/survey.fig
===================================================================
--- /tags/start/Ohana/doc/pipeline/survey.fig	(revision 12606)
+++ /tags/start/Ohana/doc/pipeline/survey.fig	(revision 12606)
@@ -0,0 +1,16 @@
+#FIG 3.2
+Portrait
+Center
+Inches
+Letter 
+100.00
+Single
+-2
+1200 2
+2 5 0 1 0 -1 0 0 -1 0.000 0 0 -1 0 0 5
+	0 polar.ps
+	 975 823 9127 823 9127 9375 975 9375 975 823
+2 5 0 1 0 -1 0 0 -1 0.000 0 0 -1 0 0 5
+	0 fullsky.ps
+	 975 8273 9127 8273 9127 12225 975 12225 975 8273
+4 0 0 0 0 0 36 0.0000 4 375 6030 2250 1125 LONEOS SURVEY MAPS\001
Index: /tags/start/Ohana/doc/projection.txt
===================================================================
--- /tags/start/Ohana/doc/projection.txt	(revision 12606)
+++ /tags/start/Ohana/doc/projection.txt	(revision 12606)
@@ -0,0 +1,51 @@
+
+/* 
+here is some C code to project from R,D to x,y (all in decimal
+degrees) in a SIN projection, with Ro, Do as projection center:
+*/
+
+# define DEG_RAD 57.295779513082322
+# define RAD_DEG  0.017453292519943
+
+project (double *x, double *y, double R, double D, double Ro, double Do) {
+
+  double sdp, cdp, salp, calp, sdel, cdel, stht, sphi, cphi;
+		 
+  sdp  = sin(RAD_DEG*Do);
+  cdp  = cos(RAD_DEG*Do);
+  salp = sin(RAD_DEG*(ra - Ro));
+  calp = cos(RAD_DEG*(ra - Ro));
+  sdel = sin(RAD_DEG*dec);
+  cdel = cos(RAD_DEG*dec);
+  
+  stht = sdel*sdp + cdel*cdp*calp;    /* sin(theta) */
+  sphi = cdel*salp;                   /* = cos(theta)*sin(phi) */
+  cphi = cdel*sdp*calp - sdel*cdp;    /* = cos(theta)*cos(phi) */
+  if (stht < 0) { return 0; /* projection from the wrong side of the sphere */ }
+  
+  X =  DEG_RAD * sphi;
+  Y = -DEG_RAD * cphi;
+  
+# if (0) 
+  
+  /* 
+     these lines allow for a rotation / distortion 2x2 matrix (pci_j),
+     a (two direction) plate-scale shift (cdelt1, cdelt2), 
+     and a reference center offset of Xo, Yo, if desired. 
+  */
+
+  tmp_d = 1.0 / (pc_1_1*pc_2_2 - pc_1_2*pc_2_1); 
+  *x = tmp_d * (pc_2_2*X - pc_1_2*Y) / cdelt1 + Xo;
+  *y = tmp_d * (pc_1_1*Y - pc_2_1*X) / cdelt2 + Yo;
+
+# else
+
+  *x = X;
+  *y = Y;
+  
+# endif
+
+
+  return (1);
+
+}
Index: /tags/start/Ohana/doc/status.txt
===================================================================
--- /tags/start/Ohana/doc/status.txt	(revision 12606)
+++ /tags/start/Ohana/doc/status.txt	(revision 12606)
@@ -0,0 +1,72 @@
+
+hi christian,
+
+The path you need depends on the machine type, either:
+
+/h/eugene/src/ohana/bin/linux  or  /h/eugene/src/ohana/bin/sol
+
+(the linux version is usually a little more up to date, but both
+should work just fine for you). 
+
+you also need to copy the following files to you home directory:
+
+ ~dougados/.ptolemyrc
+ ~eugene/.statusrc
+
+The configuration scheme is much too complex to go into here, but
+basically, the first defines the location of certain data, and in this
+case, by choosing Catherine's .ptolemyrc file, you'll be looking at
+the Taurus data by default, instead of the archive analysis I've been
+running.  
+
+The second file defines various macros for you, in particular
+'ecliptic' and 'galactic', which draw the ecliptic and galactic
+planes.  
+
+start the program by running 'status'.  It is command-line driven, and
+has some limited help files.  type '?' to see a list of commands and
+'help' to get a list of help files.  
+
+I think most things you'd want to do, you can do.  In some cases the
+syntax can be a little cumbersome.  To get you started, here is a
+macro to generate a box from (10,20) to (15,25), with an offset.
+this could be more easily done by loading the reference coordinates
+from a file with the 'data (filename)' and 'read' commands.  I'll try
+to help you figure things out when you have had a chance to play with
+it a bit.
+
+gene
+
+the syntax for somr
+macro skybox
+ create ra 0 2
+ set ra = ra * 0
+ set dec = ra * 0
+ concat {10+$1} ra 
+ concat {15+$1} ra 
+	      
+ concat {15+$1} ra 
+ concat {15+$1} ra 
+	      
+ concat {15+$1} ra 
+ concat {10+$1} ra 
+	      
+ concat {10+$1} ra 
+ concat {10+$1} ra 
+
+ concat {20+$2}  dec
+ concat {20+$2}  dec
+       	       
+ concat {20+$2}  dec
+ concat {25+$2}  dec
+       	       
+ concat {25+$2}  dec
+ concat {25+$2}  dec
+       	       
+ concat {25+$2}  dec
+ concat {20+$2}  dec
+
+ style -x 2 -c red -lw 3 -pt 100
+ cplot ra dec
+end
+
Index: /tags/start/Ohana/doc/systest.c
===================================================================
--- /tags/start/Ohana/doc/systest.c	(revision 12606)
+++ /tags/start/Ohana/doc/systest.c	(revision 12606)
@@ -0,0 +1,98 @@
+# include <stdio.h>
+
+main (argc, argv) 
+int argc;
+char **argv;
+{
+
+  int i;
+  FILE *f;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: %s testfile \n", argv[0]);
+    exit (0);
+  }
+
+  fprintf (stderr, "char:   %d bytes\n", sizeof (char));
+  fprintf (stderr, "short:  %d bytes\n", sizeof (short));
+  fprintf (stderr, "int:    %d bytes\n", sizeof (int));
+  fprintf (stderr, "long:   %d bytes\n", sizeof (long)); 
+  fprintf (stderr, "float:  %d bytes\n", sizeof (float));
+  fprintf (stderr, "double: %d bytes\n", sizeof (double));
+
+  f = fopen (argv[1], "w");
+  
+# define TYPE char
+  { 
+    TYPE I[20];
+    
+    I[0] = 1;
+    for (i = 1; i < 20; i++) {
+      I[i] = I[i-1] * 2;
+    }
+    fprintf (f, "20 of type TYPE, %d bytes each\n", sizeof(TYPE));
+    fwrite (I, sizeof(TYPE), 20, f);
+  }
+
+# define TYPE short
+  { 
+    TYPE I[20];
+    
+    I[0] = 1;
+    for (i = 1; i < 20; i++) {
+      I[i] = I[i-1] * 2;
+    }
+    fprintf (f, "20 of type TYPE, %d bytes each\n", sizeof(TYPE));
+    fwrite (I, sizeof(TYPE), 20, f);
+  }
+
+# define TYPE int
+  { 
+    TYPE I[20];
+    
+    I[0] = 1;
+    for (i = 1; i < 20; i++) {
+      I[i] = I[i-1] * 2;
+    }
+    fprintf (f, "20 of type TYPE, %d bytes each\n", sizeof(TYPE));
+    fwrite (I, sizeof(TYPE), 20, f);
+  }
+
+# define TYPE long
+  { 
+    TYPE I[20];
+    
+    I[0] = 1;
+    for (i = 1; i < 20; i++) {
+      I[i] = I[i-1] * 2;
+    }
+    fprintf (f, "20 of type TYPE, %d bytes each\n", sizeof(TYPE));
+    fwrite (I, sizeof(TYPE), 20, f);
+  }
+
+# define TYPE float
+  { 
+    TYPE I[20];
+    
+    I[0] = 1;
+    for (i = 1; i < 20; i++) {
+      I[i] = I[i-1] * 2;
+    }
+    fprintf (f, "20 of type TYPE, %d bytes each\n", sizeof(TYPE));
+    fwrite (I, sizeof(TYPE), 20, f);
+  }
+
+# define TYPE double
+  { 
+    TYPE I[20];
+    
+    I[0] = 1;
+    for (i = 1; i < 20; i++) {
+      I[i] = I[i-1] * 2;
+    }
+    fprintf (f, "20 of type TYPE, %d bytes each\n", sizeof(TYPE));
+    fwrite (I, sizeof(TYPE), 20, f);
+  }
+
+
+}
Index: /tags/start/Ohana/doc/thread.c
===================================================================
--- /tags/start/Ohana/doc/thread.c	(revision 12606)
+++ /tags/start/Ohana/doc/thread.c	(revision 12606)
@@ -0,0 +1,36 @@
+# include <stdio.h>
+# include <pthread.h>
+
+static int loop1, loop2;
+
+void *subloop (void *arg) {
+  
+  char *input;
+  
+  input = (char *) arg;
+  fprintf (stderr, "starting thread %s\n", input);
+
+  while (loop1) {
+    fprintf (stderr, "loop2: %d\n", loop2);
+    usleep (300000);
+  }
+  pthread_exit (0);
+}
+
+main () {
+
+  int var;
+  pthread_t thread1;
+  pthread_attr_t thread_attr;
+
+  loop1 = 1;
+  loop2 = 10;
+  pthread_create (&thread1, NULL, subloop, "test");
+
+  while (fscanf (stdin, "%d", &var) != EOF) {
+    loop2 = var;
+    if (loop2 == 0) loop1 = 0;
+  }
+}
+
+// a comment
Index: /tags/start/Ohana/doc/wcs.txt
===================================================================
--- /tags/start/Ohana/doc/wcs.txt	(revision 12606)
+++ /tags/start/Ohana/doc/wcs.txt	(revision 12606)
@@ -0,0 +1,54 @@
+
+DETSEC - It looks like it is defining the real pixel coordinates of
+each chip relative to the mosaic, including the gaps.  This means it
+is not affected by binning.  For now, let's leave it off from
+subrastering until we can calculate the correct coornates in that
+case.
+
+CRPIX1,2 - these need to be adjusted to the effective coordinate of
+the same pixel in the new coordinate frame:
+
+if you read a subraster (x1 - x2, y1 - y2) [unbinned pixels] with
+binning dx, 
+
+CRPIX1 = (CRPIX1' - x1) / dx
+CRPIX2 = (CRPIX2' - y1) / dy
+
+CD1_1, CD1_2, CD2_1, CD2_2 just need to be rescaled:
+
+CD1_1' = CD1_1 / dx
+CD2_1' = CD2_1 / dx
+
+CD1_2' = CD1_2 / dy
+CD2_2' = CD2_2 / dy
+
+GAIN stays fixed (we are providing the sum of the binned pixels, not
+the average). 
+
+what about the terms PIXSIZEn, PIXSCALn (I don't know whether these
+refer to physical pixels or image pixels.  in the former case, they
+stay constant, in the later case, they get scaled by dx, dy).
+
+As for the issue of the number of valid pixels...  Well, I can see
+arguments both ways.  Perhaps we *should* stick with the old
+definition of the valid data area.  In that case, make it:
+
+X1 = 6
+X2 = (Nx + 1) / dx
+Y1 = 5
+Y2 = (Ny + 4) / dy
+
+for DATASEC, which seems to match what we use now.
+
+you are right about the BIASSEC, we want the vertical region, not the corner.
+
+X1 = Nx / dx + 2
+X2 = Nx / dx + Sx
+Y1 = 5
+Y2 = (Ny + 4) / dy
+
+(currently we don't use the full Y-direction overscan -- BIASSEC is
+[6:2049,5:4100]).
+
+gene
+
Index: /tags/start/Ohana/src/addrefs/Makefile
===================================================================
--- /tags/start/Ohana/src/addrefs/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/Makefile	(revision 12606)
@@ -0,0 +1,61 @@
+include ../../Configure
+HOME 	=	$(ROOT)/src/addrefs
+CONFIG  =	$(ROOT)/config
+PROGRAM =       addrefs
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#  
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lFITS -lohana -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS)
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+ADDSTAR = \
+$(SRC)/addrefs.$(ARCH).o 	$(SRC)/gcatalog.$(ARCH).o     \
+$(SRC)/gregion.$(ARCH).o 	$(SRC)/gimages.$(ARCH).o      \
+$(SRC)/wimage.$(ARCH).o   	$(SRC)/gstars.$(ARCH).o       \
+$(SRC)/find_matches.$(ARCH).o 	$(SRC)/wcatalog.$(ARCH).o     \
+$(SRC)/find_subset.$(ARCH).o 	$(SRC)/args.$(ARCH).o         \
+$(SRC)/sort_lists.$(ARCH).o 	$(SRC)/ConfigInit.$(ARCH).o   \
+$(SRC)/aregion.$(ARCH).o	$(SRC)/conversions.$(ARCH).o  \
+$(SRC)/mkcatalog.$(ARCH).o      $(SRC)/check_permissions.$(ARCH).o
+
+OBJ = $(ADDSTAR)
+
+default: $(PROGRAM)
+
+$(ADDSTAR): $(INC)/addstar.h
+
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:	
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
+
+
Index: /tags/start/Ohana/src/addrefs/doc/database.txt
===================================================================
--- /tags/start/Ohana/src/addrefs/doc/database.txt	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/doc/database.txt	(revision 12606)
@@ -0,0 +1,91 @@
+
+\begin{verbatim}
+
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm;      /* number of measurements */
+  unsigned short int Xp, Xm;  /* chisq values in tenths */
+  unsigned int offset;        /* offset to first Measure-ment */
+} Average;                    /* = 20 bytes / average */
+
+typedef struct {
+  char dR, dD;                /* tenths of arcsec (-12.7 to +12.7 valid range) */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 -- 0.255 valid range) */
+  float t;                    /* time in seconds (what is reference?) */
+  unsigned int average;       /* reference to corresponding Average entry, 
+				 upper byte of value contains flags.
+				 limit of 16,777,215 stars (Naverage) 
+				 in a file (=0xFFFFFF).
+				 flags = average & 0x1000000 */
+} Measure;                    /* = 13 bytes / measure */
+
+# define BLEND_IMAGE   0X01000000
+# define BLEND_CATALOG 0X02000000
+# define UPPER_LIMIT   0X04000000
+# define CALIBRATED    0X08000000
+
+\end{verbatim}
+
+The above two structures define the entries in the photometry
+database.  The database consists of a large number of files
+representing a small patch on the sky (roughly 1.5 degree$^2$ in most
+places).  These files are organized into directories representing
+bands of Declination.  A reference file determines the coordinate
+boundaries for each of the files so that a given point on the sky can
+unambiguously be associated with a specific file in a specific
+directory.  The sky coordinates for each file is the same as those
+used by the HST Guide Star catalog, except for the region around the
+North celestial pole, for which all stars are included in a single
+file.  
+
+Within a given file, the data are stored in a binary format, with an
+ASCII FITS-like header.  The header is examply in the format of a
+normal FITS header, but with the exception that all files have a fixed
+number of header blocks (for now 3 blocks = 8640 bytes).  This is done
+to speed loading the header and finding the beginning of the binary
+data.  The number of 3 blocks seems quite generous, as currently only
+a few FITS keywords have been defined for each file, basically
+keywords to define the number of stars and the total number of
+measurements stored in the file, as well as values to define the RA
+and DEC range of the file.  
+
+The first section of data following the header blocks consists of
+average measurements for each uniquely observed star.  Each star
+occupies 20 bytes, the size of the Average structure defined above.
+The Average structure contains the average Ra, Dec, and Magnitude for
+the star, as well as the number of measurements, and \chisq\ values
+for the magnitude and position.  Finally, there is a 32 bit integer
+which defines the offset to the first measurement for this star.  This
+offset is defined as the number of Measure records from the start of
+the Measure structure.
+
+The second section of data, following the Average data contains all
+measurements for each star listed in Average.  Each measurement
+occupies 13 bytes, the size of the Measure structure.  This structure
+contains the difference of this position from the average RA and DEC,
+and the instrumental magnitude of this measurement (in the units
+defined by the fstat program, which give m = -2.5*log(cts) + Mo, where
+Mo is currently 24.5 [10/15]).  There is also the magnitude error for
+this measurement, the time of the measurement (in seconds relative to
+a to-be-determined zero point), and a reference to the entry in the
+Average structure so we can relate a given measurement with a given star.
+This last entry also includes a byte of flags, of which only 4 have
+currently been defined.  This means the Average offset can only be as
+large as  16,777,215 (0xffffff), limiting the possible number of stars
+allowed in a given file.  This does not seem like a long term problem,
+though:  aside from the fact that this number is very large and we
+only expect in the vicinity of 20,000 stars per file, the file can
+easily be divided into pieces at a later date if needed.  this last
+step is trivial, consisting of splitting the data up into smaller
+RA,DEC regions, and updating the reference catalog.  With the above
+definitions for the Average and Measure structures, we will typically
+expect 20,000 * 15 measurements per year and 20,000 average entries in
+a given file.  This implies a file size of about 4.3 MB at the end of
+a year.  It is also possible that we will choose to split the files up
+in the future if the number of measurements makes their size
+unweildy.  4.3 MB is sufficiently small that this is not a problem,
+but after only 5 years, the files will be over 21 MB each, getting to
+be fairly significant.  
Index: /tags/start/Ohana/src/addrefs/doc/description.txt
===================================================================
--- /tags/start/Ohana/src/addrefs/doc/description.txt	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/doc/description.txt	(revision 12606)
@@ -0,0 +1,94 @@
+
+ADDSTAR:
+
+This program takes a photometry file, with astrometry, provided by
+earlier routines and incorporates the stellar measurements into the
+photometry database.  This routine does NOT try to calibrate or check
+the photometry, nor does it try to improve the coordinate
+determinations or calculate chisquares for position or photometry -
+those tasks are performed by other routines.
+
+Addstar starts by loading in the photometry file and converting the
+pixel coordinates to sky coordinates using the astrometry information
+in the header of the file.  It also gets the detection limits and
+stores the image astrometry information.
+
+Next, addstar determines which of all the previous images overlaps
+with this image and also which of the catalog regions overlaps with
+this image.
+
+Addstar considers each catalog region in turn, and compares the
+positions of stars in the catalog with stars in the image.  If a
+catalog star is detected, a new measurement is added to the catalog.
+If a catalog star is not detected, but is in the field of view of this
+image, the detection limit for this image is added to the list of
+measurements as an upper limit.  If the image contains a star which is
+not already included in the catalog, the star is added to the catalog,
+and all previous images are checked to see if they included this
+location.  If so, upper limits are added to the list of measurements.
+
+To deal with blended images, we have taken the philosophy that all
+measurements compatible with the coordinates of a given star should be
+included in the list of measurements.  This assumes that programs or people
+downstream will figure out which is the "correct" measurement.  To
+this end, if a catalog star is consistent with multiple measurements,
+they are all added to the catalog measurement and the measurements are
+given a flag to say that there was blending in the catalog (ie, it is
+probably the catalog star which is a blend).  If multiple catalog
+stars are consistent with the same image star, that measurement is
+added to each catalog star, and given a flag to say that there was
+blending on the image.
+
+After all catalogs have been checked, updated, and written to disk,
+the image is added to the database of images.
+
+The format for a catalog region file is as follows:
+
+-- 
+Header
+--
+Averages
+--
+Measurements
+--
+
+The Header follows the format of a FITS header but always stored with
+3 blocks to speed up read time: 2880 x 3 bytes.  Two important
+keywords in the header: NSTARS & NMEAS
+
+All average values are stored consecutively in a single block.  They
+are written as an array with NSTARS elements of the Average structure
+defined below.  The individual measurements follow the averages as a
+block.  To find a measurement for a given star, you need to get the
+value of the offset for the star.  this is the element number for the
+first measurement of this star, and are followed by next measurements
+for this star, until the value Nm is reached.
+
+Here are the structures being used for the average and measurement
+values:
+
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm;      /* number of measurements */
+  unsigned short int Xp, Xm;  /* chisq values in tenths */
+  unsigned int offset;        /* offset to first measurement */
+} Average;                    /* = 20 bytes / average */
+
+typedef struct {
+  char dR, dD;                /* tenths of arcsec (-12.7 to +12.7 valid range) */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 -- 0.255 valid range) */
+  float t;                    /* time in seconds (what is reference?) */
+  unsigned int average;       
+  /* reference to corresponding average entry, upper byte stores flags:
+   limit of 16,777,215 stars (Naverage) in a file (=0xFFFFFF) 
+   flags: average & 0x1000000 */
+} Measure;                    /* = 13 bytes / measure */
+
+/* flags for measurements: */
+# define BLEND_IMAGE   0X01000000
+# define BLEND_CATALOG 0X02000000
+# define UPPER_LIMIT   0X04000000
+# define CALIBRATED    0X08000000
Index: /tags/start/Ohana/src/addrefs/etc/phottemp.cat
===================================================================
--- /tags/start/Ohana/src/addrefs/etc/phottemp.cat	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/etc/phottemp.cat	(revision 12606)
@@ -0,0 +1,296 @@
+SIMPLE  =                    F  / ASTROCAM PHOTOMETRY FILE                    \
+BITPIX  =                   16 /                                              \
+NAXIS   =                    2  / NUMBER OF AXES                              \
+NAXIS1  =                 1106  / NUMBER OF COLUMNS                           \
+NAXIS2  =                 1024  / NUMBER OF ROWS                              \
+BSCALE  =             1.000000 /                                              \
+BZERO   =             0.000000 /                                              \
+DATE    = '19/12/94'            / UT Date of file creation (DD/MM/YY)         \
+ORIGIN  = 'MDM Observatory'     / Michigan-Dartmouth-MIT                      \
+LATITUDE=              31.9500  / Latitude (degrees N)                        \
+LONGITUD=            -111.6150  / Longitude (degrees E)                       \
+OBSERVER= 'Metzger '            / Name of observer                            \
+TELESCOP= '1.3m McGraw-Hill'    / Telescope used for observation              \
+INSTRUME= 'Charlotte Direct'    / Instrument used for observation             \
+DETECTOR= 'Charlotte/Tek 1024^2 CCD'  / Detector used for observation         \
+FRAME   =                   32  / Frame number of observation                 \
+CCDPICNO=                   32  / Frame number of observation                 \
+OBJECT  = 'ocl0327 '            / Name of object                              \
+IMAGETYP= 'OBJECT  '            / Type of observation                         \
+EXPTIME =              250.000  / Integration time (seconds)                  \
+DARKTIME=              250.067  / Dark current time (seconds)                 \
+DATE-OBS= '19/12/94'            / UT Date of observation (DD/MM/YY)           \
+UT      = ' 05:25:44.00'        / Universal time (UTC) at exposure start      \
+JD      =       2449705.726204                                                \
+RA      =           50.700      / Right Ascension                             \
+DEC     =           89.000      / Declination                                 \
+DIRECTN =                 -1    / Moving South                                \
+EQUINOX =             1950.000  / Equinox of RA and DEC                       \
+HA      = ' 02:14:06.72'        / Hour angle at start                         \
+ST      = ' 03:49:36.85'        / Sidereal time at start                      \
+ZD      = ' 36:26:07.17'        / Zenith distance (degrees)                   \
+AIRMASS =                1.243  / Airmass at start                            \
+FILTER  = 'I KP    '            / Filter description                          \
+GAIN    =                3.350  / Nominal gain (e-/ADU)                       \
+SECPIX1 =                0.508  / Arcseconds per pixel in fast dir            \
+SECPIX2 =                0.508  / Arcseconds per pixel in slow dir            \
+CCDBIN1 =                    1  / On-chip column binning (fast dir)           \
+CCDBIN2 =                    1  / On-chip row binning (slow dir)              \
+GPROBE  = '  5000.00   7000.00'  / Guide probe X Y                            \
+DATASEC = '[51:1074,1:1024]'    / Image area of frame                         \
+CCDSEC  = '[1:1074,1:1024]'     / Image area relative to full chip            \
+BIASSEC = '[1080:1106,1:1023]'  / Overscan area of frame                      \
+UNSIGN  =                    T /                                              \
+NSTARS  =                    0  / NUMBER OF stars                             \
+CTYPE1  = 'RA---SIN          ' /                                               
+CTYPE2  = 'DEC--SIN          ' /                                               
+CDELT1  =             0.000733 /                                               
+CDELT2  =             0.000733 /                                               
+CRVAL1  =            50.191418 /                                               
+CRVAL2  =            88.998663 /                                               
+CRPIX1  =          1028.644173 /                                               
+CRPIX2  =           503.129830 /                                               
+PC001001=             0.999906 /                                               
+PC001002=             0.012081 /                                               
+PC002001=            -0.011936 /                                               
+PC002002=             0.999950 /                                               
+END                                                                           \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+ 246.5  352.1 13.000 020 1 3.2
+ 246.5  352.1 14.100 020 1 3.2
+ 279.4  328.9 13.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 436.6  413.5 14.300 020 1 3.2
+   9.3  856.5 13.000 020 1 3.2
+   9.3  856.2 13.600 020 1 3.2
+ 319.7  697.9 12.000 020 1 3.2
+ 319.7  697.7 12.100 020 1 3.2
+ 244.3    9.5 14.100 020 1 3.2
+ 284.7  334.4 14.000 020 1 3.2
+ 127.1  122.8 14.200 020 1 3.2
+ 140.2  791.1 13.700 020 1 3.2
+ 140.2  790.8 14.400 020 1 3.2
+ 131.7  636.3 13.800 020 1 3.2
+ 423.8  700.6 13.800 020 1 3.2
+ 423.7  700.7 12.500 020 1 3.2
+ 266.2  290.7 13.800 020 1 3.2
+ 266.0  290.7 13.100 020 1 3.2
+ 570.7  721.6 13.600 020 1 3.2
+ 570.7  721.6 13.100 020 1 3.2
+ 548.7  673.0 13.700 020 1 3.2
+ 264.2  219.7 12.800 020 1 3.2
+ 264.0  219.7 12.100 020 1 3.2
+ 161.9  797.4 11.900 020 1 3.2
+ 162.0  797.2 12.200 020 1 3.2
+ 505.8  851.8 13.700 020 1 3.2
+  88.2  419.0 11.400 020 1 3.2
+  88.2  419.0 11.800 020 1 3.2
+ 426.9  613.2  9.400 020 1 3.2
+ 427.4  613.5  7.600 020 1 3.2
+ 326.1  595.2 12.100 020 1 3.2
+ 326.2  595.1 12.600 020 1 3.2
+ 444.4  845.2 14.200 020 1 3.2
+ 254.1  916.8 14.500 020 1 3.2
+ 502.6  882.4 14.200 020 1 3.2
+ 128.3  275.7 12.300 020 1 3.2
+ 128.3  275.7 12.900 020 1 3.2
+ 230.9  554.8 13.300 020 1 3.2
+ 230.9  554.7 14.200 020 1 3.2
+  47.5  685.2 13.500 020 1 3.2
+  47.5  684.9 14.200 020 1 3.2
+ 382.6  658.7 14.000 020 1 3.2
+ 182.2  330.3 14.200 020 1 3.2
+ 245.1  548.3 12.600 020 1 3.2
+ 245.3  548.0 13.200 020 1 3.2
+  50.3  849.0 13.700 020 1 3.2
+  50.5  848.8 14.300 020 1 3.2
+  17.9  772.7 14.200 020 1 3.2
+ 499.8  712.8 13.500 020 1 3.2
+ 499.8  712.6 14.400 020 1 3.2
+ 294.5  349.4 14.000 020 1 3.2
+ 497.7  747.8 11.000 020 1 3.2
+ 497.5  747.8 10.900 020 1 3.2
+ 109.7  323.5 14.000 020 1 3.2
+  59.5  917.6 14.300 020 1 3.2
+  59.4  917.8 13.700 020 1 3.2
+  82.2  880.5 13.800 020 1 3.2
+ 145.1  341.2 14.500 020 1 3.2
+ 452.7  592.4 14.400 020 1 3.2
+ 623.4  820.0 13.700 020 1 3.2
+ 609.7  829.3 13.500 020 1 3.2
+ 481.8  938.3 14.400 020 1 3.2
+ 617.0  792.7 13.500 020 1 3.2
+ 183.2  539.7 14.400 020 1 3.2
+ 133.9  679.6 14.400 020 1 3.2
+ 423.7  667.8  6.500 020 1 3.2
+ 434.7  111.9 13.200 020 1 3.2
+ 434.5  111.9 13.200 020 1 3.2
+ 434.6  111.9 14.200 020 1 3.2
+1222.3  684.2 13.900 020 1 3.2
+1077.6  282.5 14.000 020 1 3.2
+1077.8  282.5 13.400 020 1 3.2
+ 720.8  562.1 14.100 020 1 3.2
+ 721.1  561.9 14.400 020 1 3.2
+1182.1  944.4 12.100 020 1 3.2
+1181.9  944.4 11.800 020 1 3.2
+1181.9  944.4 12.300 020 1 3.2
+ 761.2  423.1 14.300 020 1 3.2
+ 761.0  423.1 14.100 020 1 3.2
+ 926.7  436.8 13.400 020 1 3.2
+ 926.6  436.8 14.200 020 1 3.2
+1209.1   45.0 13.200 020 1 3.2
+1209.2   43.6 12.800 020 1 3.2
+1135.2  653.1  8.100 020 1 3.2
+1135.6  653.4  8.200 020 1 3.2
+1123.5  735.8 12.000 020 1 3.2
+1123.6  735.8 11.800 020 1 3.2
+1123.7  735.7 11.600 020 1 3.2
+ 730.7   28.6 12.100 020 1 3.2
+ 730.7   28.6 12.200 020 1 3.2
+ 783.1  267.5 14.200 020 1 3.2
+ 783.2  267.5 13.400 020 1 3.2
+ 876.2  462.7 13.800 020 1 3.2
+ 876.4  462.7 14.200 020 1 3.2
+ 917.2  399.9 13.700 020 1 3.2
+ 917.3  399.9 13.200 020 1 3.2
+1227.5  218.4 10.400 020 1 3.2
+1227.7  218.4 10.500 020 1 3.2
+1022.7  146.0 13.300 020 1 3.2
+1022.5  146.0 14.100 020 1 3.2
+1324.7   72.3 12.900 020 1 3.2
+1324.6   72.3 13.200 020 1 3.2
+ 743.2  379.4 14.300 020 1 3.2
+ 742.9  379.4 13.900 020 1 3.2
+1255.9  544.0 12.600 020 1 3.2
+1256.0  543.9 12.300 020 1 3.2
+ 848.9  251.1 13.200 020 1 3.2
+ 849.0  251.1 12.700 020 1 3.2
+ 495.6  147.4 11.400 020 1 3.2
+ 495.6  147.4 11.300 020 1 3.2
+ 495.5  147.4 11.000 020 1 3.2
+1016.4  735.5 14.200 020 1 3.2
+1016.3  735.7 13.900 020 1 3.2
+ 795.2  675.9 14.400 020 1 3.2
+ 887.2  968.8 10.800 020 1 3.2
+ 626.8  726.9 14.400 020 1 3.2
+ 718.6  800.1  9.700 020 1 3.2
+ 675.4  301.6 14.400 020 1 3.2
+ 801.6  436.8 14.200 020 1 3.2
+1066.4  870.0 13.700 020 1 3.2
+1066.5  869.9 13.800 020 1 3.2
+ 644.5  662.9  9.900 020 1 3.2
+ 639.1  760.4 13.000 020 1 3.2
+ 822.7  663.1 12.800 020 1 3.2
+ 822.7  663.1 13.100 020 1 3.2
+ 677.2  716.2 12.900 020 1 3.2
+ 765.6  641.5 13.200 020 1 3.2
+ 765.7  641.4 13.500 020 1 3.2
+ 998.3  425.8 14.400 020 1 3.2
+ 713.7  716.2 13.800 020 1 3.2
+ 814.7  887.6  2.000 020 1 3.2
+ 808.7  884.1  8.200 020 1 3.2
+1812.3  259.3 14.500 020 1 3.2
+1655.9  655.4 12.200 020 1 3.2
+1655.9  655.4 12.100 020 1 3.2
+1577.2  839.6 11.500 020 1 3.2
+1577.2  839.6 11.400 020 1 3.2
+1643.7  597.0 14.100 020 1 3.2
+1552.8  251.1 10.100 020 1 3.2
+1552.8  251.1 10.300 020 1 3.2
+1410.0  999.9 13.900 020 1 3.2
+1335.6  687.0 13.000 020 1 3.2
+1335.8  686.8 12.700 020 1 3.2
+1471.4  262.0 14.200 020 1 3.2
+1479.6  608.3 14.200 020 1 3.2
+1478.1  211.5 12.000 020 1 3.2
+1478.3  211.5 12.000 020 1 3.2
+1552.5   46.4 14.500 020 1 3.2
+2042.4  548.3 10.800 020 1 3.2
+2042.6  548.3 11.000 020 1 3.2
+1448.0  915.7 14.100 020 1 3.2
+1462.3  989.2 13.000 020 1 3.2
+1462.3  989.0 12.700 020 1 3.2
+1316.9  787.3 14.100 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1677.2  106.4 13.100 020 1 3.2
+1677.0  106.4 13.300 020 1 3.2
+1324.2  429.9  9.200 020 1 3.2
+1324.2  429.9  9.000 020 1 3.2
+1462.8  214.3 13.700 020 1 3.2
+1462.8  214.3 14.200 020 1 3.2
+1405.4   95.5 11.700 020 1 3.2
+1405.2   95.5 11.600 020 1 3.2
+1604.8   90.0 11.200 020 1 3.2
+1604.8   90.0 11.300 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1459.8  473.6 13.400 020 1 3.2
+1459.7  473.6 13.800 020 1 3.2
+1438.7   77.8 12.200 020 1 3.2
+1438.6   77.8 12.200 020 1 3.2
+1355.0  114.6 13.000 020 1 3.2
+1354.9  114.6 13.200 020 1 3.2
+1941.4  940.7 13.000 020 1 3.2
+1941.6  940.7 12.900 020 1 3.2
+1994.0  800.8 13.900 020 1 3.2
+1993.8  800.8 14.000 020 1 3.2
+2024.4  907.0 13.700 020 1 3.2
+2024.4  907.0 13.800 020 1 3.2
+2035.7  881.6 13.900 020 1 3.2
+2035.9  881.6 13.800 020 1 3.2
+1994.0  924.2 12.100 020 1 3.2
+1994.0  924.2 12.000 020 1 3.2
Index: /tags/start/Ohana/src/addrefs/etc/template.cat
===================================================================
--- /tags/start/Ohana/src/addrefs/etc/template.cat	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/etc/template.cat	(revision 12606)
@@ -0,0 +1,296 @@
+SIMPLE  =                    F  / ASTROCAM PHOTOMETRY FILE                    \
+BITPIX  =                   16 /                                              \
+NAXIS   =                    2  / NUMBER OF AXES                              \
+NAXIS1  =                 1106  / NUMBER OF COLUMNS                           \
+NAXIS2  =                 1024  / NUMBER OF ROWS                              \
+BSCALE  =             1.000000 /                                              \
+BZERO   =             0.000000 /                                              \
+DATE    = '19/12/94'            / UT Date of file creation (DD/MM/YY)         \
+ORIGIN  = 'MDM Observatory'     / Michigan-Dartmouth-MIT                      \
+LATITUDE=              31.9500  / Latitude (degrees N)                        \
+LONGITUD=            -111.6150  / Longitude (degrees E)                       \
+OBSERVER= 'Metzger '            / Name of observer                            \
+TELESCOP= '1.3m McGraw-Hill'    / Telescope used for observation              \
+INSTRUME= 'Charlotte Direct'    / Instrument used for observation             \
+DETECTOR= 'Charlotte/Tek 1024^2 CCD'  / Detector used for observation         \
+FRAME   =                   32  / Frame number of observation                 \
+CCDPICNO=                   32  / Frame number of observation                 \
+OBJECT  = 'ocl0327 '            / Name of object                              \
+IMAGETYP= 'OBJECT  '            / Type of observation                         \
+EXPTIME =              250.000  / Integration time (seconds)                  \
+DARKTIME=              250.067  / Dark current time (seconds)                 \
+DATE-OBS= '19/12/94'            / UT Date of observation (DD/MM/YY)           \
+UT      = ' 05:25:44.00'        / Universal time (UTC) at exposure start      \
+JD      =       2449705.726204                                                \
+RA      =           50.700      / Right Ascension                             \
+DEC     =           89.000      / Declination                                 \
+DIRECTN =                 -1    / Moving South                                \
+EQUINOX =             1950.000  / Equinox of RA and DEC                       \
+HA      = ' 02:14:06.72'        / Hour angle at start                         \
+ST      = ' 03:49:36.85'        / Sidereal time at start                      \
+ZD      = ' 36:26:07.17'        / Zenith distance (degrees)                   \
+AIRMASS =                1.243  / Airmass at start                            \
+FILTER  = 'I KP    '            / Filter description                          \
+GAIN    =                3.350  / Nominal gain (e-/ADU)                       \
+SECPIX1 =                0.508  / Arcseconds per pixel in fast dir            \
+SECPIX2 =                0.508  / Arcseconds per pixel in slow dir            \
+CCDBIN1 =                    1  / On-chip column binning (fast dir)           \
+CCDBIN2 =                    1  / On-chip row binning (slow dir)              \
+GPROBE  = '  5000.00   7000.00'  / Guide probe X Y                            \
+DATASEC = '[51:1074,1:1024]'    / Image area of frame                         \
+CCDSEC  = '[1:1074,1:1024]'     / Image area relative to full chip            \
+BIASSEC = '[1080:1106,1:1023]'  / Overscan area of frame                      \
+UNSIGN  =                    T /                                              \
+NSTARS  =                    0  / NUMBER OF stars                             \
+CTYPE1  = 'RA---SIN          ' /                                               
+CTYPE2  = 'DEC--SIN          ' /                                               
+CDELT1  =             0.000733 /                                               
+CDELT2  =             0.000733 /                                               
+CRVAL1  =            50.191418 /                                               
+CRVAL2  =            88.998663 /                                               
+CRPIX1  =          1028.644173 /                                               
+CRPIX2  =           503.129830 /                                               
+PC001001=             0.999906 /                                               
+PC001002=             0.012081 /                                               
+PC002001=            -0.011936 /                                               
+PC002002=             0.999950 /                                               
+END                                                                           \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+ 246.5  352.1 13.000 020 1 3.2
+ 246.5  352.1 14.100 020 1 3.2
+ 279.4  328.9 13.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 436.6  413.5 14.300 020 1 3.2
+   9.3  856.5 13.000 020 1 3.2
+   9.3  856.2 13.600 020 1 3.2
+ 319.7  697.9 12.000 020 1 3.2
+ 319.7  697.7 12.100 020 1 3.2
+ 244.3    9.5 14.100 020 1 3.2
+ 284.7  334.4 14.000 020 1 3.2
+ 127.1  122.8 14.200 020 1 3.2
+ 140.2  791.1 13.700 020 1 3.2
+ 140.2  790.8 14.400 020 1 3.2
+ 131.7  636.3 13.800 020 1 3.2
+ 423.8  700.6 13.800 020 1 3.2
+ 423.7  700.7 12.500 020 1 3.2
+ 266.2  290.7 13.800 020 1 3.2
+ 266.0  290.7 13.100 020 1 3.2
+ 570.7  721.6 13.600 020 1 3.2
+ 570.7  721.6 13.100 020 1 3.2
+ 548.7  673.0 13.700 020 1 3.2
+ 264.2  219.7 12.800 020 1 3.2
+ 264.0  219.7 12.100 020 1 3.2
+ 161.9  797.4 11.900 020 1 3.2
+ 162.0  797.2 12.200 020 1 3.2
+ 505.8  851.8 13.700 020 1 3.2
+  88.2  419.0 11.400 020 1 3.2
+  88.2  419.0 11.800 020 1 3.2
+ 426.9  613.2  9.400 020 1 3.2
+ 427.4  613.5  7.600 020 1 3.2
+ 326.1  595.2 12.100 020 1 3.2
+ 326.2  595.1 12.600 020 1 3.2
+ 444.4  845.2 14.200 020 1 3.2
+ 254.1  916.8 14.500 020 1 3.2
+ 502.6  882.4 14.200 020 1 3.2
+ 128.3  275.7 12.300 020 1 3.2
+ 128.3  275.7 12.900 020 1 3.2
+ 230.9  554.8 13.300 020 1 3.2
+ 230.9  554.7 14.200 020 1 3.2
+  47.5  685.2 13.500 020 1 3.2
+  47.5  684.9 14.200 020 1 3.2
+ 382.6  658.7 14.000 020 1 3.2
+ 182.2  330.3 14.200 020 1 3.2
+ 245.1  548.3 12.600 020 1 3.2
+ 245.3  548.0 13.200 020 1 3.2
+  50.3  849.0 13.700 020 1 3.2
+  50.5  848.8 14.300 020 1 3.2
+  17.9  772.7 14.200 020 1 3.2
+ 499.8  712.8 13.500 020 1 3.2
+ 499.8  712.6 14.400 020 1 3.2
+ 294.5  349.4 14.000 020 1 3.2
+ 497.7  747.8 11.000 020 1 3.2
+ 497.5  747.8 10.900 020 1 3.2
+ 109.7  323.5 14.000 020 1 3.2
+  59.5  917.6 14.300 020 1 3.2
+  59.4  917.8 13.700 020 1 3.2
+  82.2  880.5 13.800 020 1 3.2
+ 145.1  341.2 14.500 020 1 3.2
+ 452.7  592.4 14.400 020 1 3.2
+ 623.4  820.0 13.700 020 1 3.2
+ 609.7  829.3 13.500 020 1 3.2
+ 481.8  938.3 14.400 020 1 3.2
+ 617.0  792.7 13.500 020 1 3.2
+ 183.2  539.7 14.400 020 1 3.2
+ 133.9  679.6 14.400 020 1 3.2
+ 423.7  667.8  6.500 020 1 3.2
+ 434.7  111.9 13.200 020 1 3.2
+ 434.5  111.9 13.200 020 1 3.2
+ 434.6  111.9 14.200 020 1 3.2
+1222.3  684.2 13.900 020 1 3.2
+1077.6  282.5 14.000 020 1 3.2
+1077.8  282.5 13.400 020 1 3.2
+ 720.8  562.1 14.100 020 1 3.2
+ 721.1  561.9 14.400 020 1 3.2
+1182.1  944.4 12.100 020 1 3.2
+1181.9  944.4 11.800 020 1 3.2
+1181.9  944.4 12.300 020 1 3.2
+ 761.2  423.1 14.300 020 1 3.2
+ 761.0  423.1 14.100 020 1 3.2
+ 926.7  436.8 13.400 020 1 3.2
+ 926.6  436.8 14.200 020 1 3.2
+1209.1   45.0 13.200 020 1 3.2
+1209.2   43.6 12.800 020 1 3.2
+1135.2  653.1  8.100 020 1 3.2
+1135.6  653.4  8.200 020 1 3.2
+1123.5  735.8 12.000 020 1 3.2
+1123.6  735.8 11.800 020 1 3.2
+1123.7  735.7 11.600 020 1 3.2
+ 730.7   28.6 12.100 020 1 3.2
+ 730.7   28.6 12.200 020 1 3.2
+ 783.1  267.5 14.200 020 1 3.2
+ 783.2  267.5 13.400 020 1 3.2
+ 876.2  462.7 13.800 020 1 3.2
+ 876.4  462.7 14.200 020 1 3.2
+ 917.2  399.9 13.700 020 1 3.2
+ 917.3  399.9 13.200 020 1 3.2
+1227.5  218.4 10.400 020 1 3.2
+1227.7  218.4 10.500 020 1 3.2
+1022.7  146.0 13.300 020 1 3.2
+1022.5  146.0 14.100 020 1 3.2
+1324.7   72.3 12.900 020 1 3.2
+1324.6   72.3 13.200 020 1 3.2
+ 743.2  379.4 14.300 020 1 3.2
+ 742.9  379.4 13.900 020 1 3.2
+1255.9  544.0 12.600 020 1 3.2
+1256.0  543.9 12.300 020 1 3.2
+ 848.9  251.1 13.200 020 1 3.2
+ 849.0  251.1 12.700 020 1 3.2
+ 495.6  147.4 11.400 020 1 3.2
+ 495.6  147.4 11.300 020 1 3.2
+ 495.5  147.4 11.000 020 1 3.2
+1016.4  735.5 14.200 020 1 3.2
+1016.3  735.7 13.900 020 1 3.2
+ 795.2  675.9 14.400 020 1 3.2
+ 887.2  968.8 10.800 020 1 3.2
+ 626.8  726.9 14.400 020 1 3.2
+ 718.6  800.1  9.700 020 1 3.2
+ 675.4  301.6 14.400 020 1 3.2
+ 801.6  436.8 14.200 020 1 3.2
+1066.4  870.0 13.700 020 1 3.2
+1066.5  869.9 13.800 020 1 3.2
+ 644.5  662.9  9.900 020 1 3.2
+ 639.1  760.4 13.000 020 1 3.2
+ 822.7  663.1 12.800 020 1 3.2
+ 822.7  663.1 13.100 020 1 3.2
+ 677.2  716.2 12.900 020 1 3.2
+ 765.6  641.5 13.200 020 1 3.2
+ 765.7  641.4 13.500 020 1 3.2
+ 998.3  425.8 14.400 020 1 3.2
+ 713.7  716.2 13.800 020 1 3.2
+ 814.7  887.6  2.000 020 1 3.2
+ 808.7  884.1  8.200 020 1 3.2
+1812.3  259.3 14.500 020 1 3.2
+1655.9  655.4 12.200 020 1 3.2
+1655.9  655.4 12.100 020 1 3.2
+1577.2  839.6 11.500 020 1 3.2
+1577.2  839.6 11.400 020 1 3.2
+1643.7  597.0 14.100 020 1 3.2
+1552.8  251.1 10.100 020 1 3.2
+1552.8  251.1 10.300 020 1 3.2
+1410.0  999.9 13.900 020 1 3.2
+1335.6  687.0 13.000 020 1 3.2
+1335.8  686.8 12.700 020 1 3.2
+1471.4  262.0 14.200 020 1 3.2
+1479.6  608.3 14.200 020 1 3.2
+1478.1  211.5 12.000 020 1 3.2
+1478.3  211.5 12.000 020 1 3.2
+1552.5   46.4 14.500 020 1 3.2
+2042.4  548.3 10.800 020 1 3.2
+2042.6  548.3 11.000 020 1 3.2
+1448.0  915.7 14.100 020 1 3.2
+1462.3  989.2 13.000 020 1 3.2
+1462.3  989.0 12.700 020 1 3.2
+1316.9  787.3 14.100 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1677.2  106.4 13.100 020 1 3.2
+1677.0  106.4 13.300 020 1 3.2
+1324.2  429.9  9.200 020 1 3.2
+1324.2  429.9  9.000 020 1 3.2
+1462.8  214.3 13.700 020 1 3.2
+1462.8  214.3 14.200 020 1 3.2
+1405.4   95.5 11.700 020 1 3.2
+1405.2   95.5 11.600 020 1 3.2
+1604.8   90.0 11.200 020 1 3.2
+1604.8   90.0 11.300 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1459.8  473.6 13.400 020 1 3.2
+1459.7  473.6 13.800 020 1 3.2
+1438.7   77.8 12.200 020 1 3.2
+1438.6   77.8 12.200 020 1 3.2
+1355.0  114.6 13.000 020 1 3.2
+1354.9  114.6 13.200 020 1 3.2
+1941.4  940.7 13.000 020 1 3.2
+1941.6  940.7 12.900 020 1 3.2
+1994.0  800.8 13.900 020 1 3.2
+1993.8  800.8 14.000 020 1 3.2
+2024.4  907.0 13.700 020 1 3.2
+2024.4  907.0 13.800 020 1 3.2
+2035.7  881.6 13.900 020 1 3.2
+2035.9  881.6 13.800 020 1 3.2
+1994.0  924.2 12.100 020 1 3.2
+1994.0  924.2 12.000 020 1 3.2
Index: /tags/start/Ohana/src/addrefs/include/addstar.h
===================================================================
--- /tags/start/Ohana/src/addrefs/include/addstar.h	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/include/addstar.h	(revision 12606)
@@ -0,0 +1,76 @@
+# include <ohana.h>
+# include <loneos.h>
+# include <signal.h>
+
+typedef struct {
+  double X;
+  double Y;
+  double R;
+  double D;
+  double M, dM;
+  char   dophot;
+  double sky;
+  double fx, fy, df;
+  double Mgal, Map;
+  int found;
+} Stars;
+
+/* global variables set in parameter file */
+char   ImageCat[256];
+char   ImageTemplate[256];
+char   CatTemplate[256];
+char   GSCFILE[256];
+char   CATDIR[256];
+double NSIGMA, SNLIMIT, DEFAULT_RADIUS;
+double ALPHA;
+int    VERBOSE;
+int    XOVERSCAN, YOVERSCAN;
+char   DBServer[1024];
+PhotCode *thiscode;
+
+int REMOTE;
+int ONLY_MATCH;
+int REPLACE;
+
+unsigned int TIMEREF;
+
+Stars *find_subset (GSCRegion *region, Stars *stars, int Nstars, int **Subref, int *NSTARS);
+Image *gimages (Image *image, int *Npimage);
+GSCRegion *gregions (Image *image, int *Nregions);
+Stars *gstars (char *file, int *Nstars);
+char *sec_to_date (unsigned long second);
+void ConfigInit (int *argc, char **argv);
+void FindCalibration (Image *image);
+void InitCalibration ();
+void SaveCalibration (float M, float dM, float Mr, float Mc, float A, int N, float ra, float dec, float x, float y);
+int SetSignals ();
+int Shutdown ();
+void TrapSignal (int sig);
+void aregion (GSCRegion *region, FILE *f, double ra, double dec);
+int args (int argc, char **argv);
+void check_permissions (char *basefile);
+int chk_time (char *line);
+int dms_to_ddd (double *Value, char *string);
+int edge_check (double *x1, double *y1, double *x2, double *y2);
+void find_matches (GSCRegion *region, Stars *stars, int Nstars, Catalog *catalog);
+void fsort (float *X, int N);
+int gcatalog (Catalog *catalog);
+void gregion (Stars *star, GSCRegion *region);
+void help ();
+int hms_to_deg (double *h0, double *h1, double *d0, double *d1, char *string);
+int in_image (double r, double d, Image *image);
+unsigned long jd_to_sec (double jd);
+unsigned long date_to_sec (char *date);
+int main (int argc, char **argv);
+void make_backup (char *filename);
+void mkcatalog (GSCRegion *region, Catalog *catalog);
+double opening_angle (double x1, double y1, double x2, double y2, double x3, double y3);
+int parse_time (Header *header);
+double sec_to_jd (unsigned long second);
+void sort_lists (float *X, float *Y, int *S, int N);
+int str_to_dtime (char *line, double *second);
+int str_to_radec (double *ra, double *dec, char *str1, char *str2);
+int str_to_time (char *line, unsigned int *second);
+void uppercase (char *string);
+void wcatalog (Catalog *catalog);
+void wimage (char *filename, Image *image, int Nstars);
Index: /tags/start/Ohana/src/addrefs/src/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/addrefs/src/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/src/ConfigInit.c	(revision 12606)
@@ -0,0 +1,50 @@
+# include "addstar.h"
+
+void ConfigInit (int *argc, char **argv) {
+
+  char *config, *file;
+  char RadiusWord[80];
+  char PhotCodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (1);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  ScanConfig (config, "RADIUS",                 "%s", 0,  RadiusWord);
+  if (!strcasecmp (RadiusWord, "header")) {
+    DEFAULT_RADIUS = 0;
+  } else {
+    DEFAULT_RADIUS = atof (RadiusWord);
+  }
+
+  ScanConfig (config, "NSIGMA",                 "%lf", 0, &NSIGMA);
+  ScanConfig (config, "ALPHA",                  "%lf", 0, &ALPHA);
+  ScanConfig (config, "XOVERSCAN",              "%d",  0, &XOVERSCAN);
+  ScanConfig (config, "YOVERSCAN",              "%d",  0, &YOVERSCAN);
+  ScanConfig (config, "IMAGE_CATALOG",          "%s",  0, ImageCat);
+  ScanConfig (config, "IMAGE_CATALOG_TEMPLATE", "%s",  0, ImageTemplate);
+  ScanConfig (config, "CATALOG_TEMPLATE",       "%s",  0, CatTemplate);
+  ScanConfig (config, "GSCFILE",                "%s",  0, GSCFILE);
+  ScanConfig (config, "CATDIR",                 "%s",  0, CATDIR);
+  ScanConfig (config, "MIN_SN_FSTAT",           "%lf", 0, &SNLIMIT);
+  ScanConfig (config, "PHOTCODE_FILE",          "%s",  0, PhotCodeFile);
+  ScanConfig (config, "DB_SERVER",              "%s",  0, DBServer);
+
+  free (config);
+  free (file);
+
+  if (!LoadPhotcodes (PhotCodeFile)) {
+    fprintf (stderr, "error loading photcodes\n");
+    exit (1);
+  }
+
+}
+
+
+/* choose the last, not the first entry! */
Index: /tags/start/Ohana/src/addrefs/src/addrefs.c
===================================================================
--- /tags/start/Ohana/src/addrefs/src/addrefs.c	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/src/addrefs.c	(revision 12606)
@@ -0,0 +1,144 @@
+# include "addstar.h"
+
+/* these variables are needed by Shutdown */
+static FILE *f = (FILE *) NULL;
+static int Protect = FALSE;
+static int Trapped = FALSE;
+
+/* clean up open / locked files before shutting down */
+int Shutdown () {  
+  int dbstate;
+
+  Protect = TRUE;
+  fclearlockfile (ImageCat, f, LCK_HARD, &dbstate);
+  fprintf (stderr, "ERROR: addrefs halted\n");
+  exit (1);
+}
+
+void TrapSignal (int sig) {
+    fprintf (stderr, "trapped signal %d, exiting gracefully\n", sig);
+    if (sig == 11) {
+      fprintf (stderr, "seg fault\n");
+      exit (1);
+    }
+    if (Protect) {
+      Trapped = TRUE;
+      fprintf (stderr, "blocking until protected sections are clear\n");
+      return;
+    }
+    Shutdown ();
+}    
+
+int main (int argc, char **argv) {
+
+  int Nm, Nf, dbstate;
+  int i, j, Nstars, Nmissed, Nsubset, *subref;
+  Stars *stars, *subset, *gstars(), *find_subset();
+  GSCRegion region;
+  Catalog catalog;
+
+  SetSignals ();
+  args (argc, argv);
+
+  /* load data from file */
+  stars = gstars (argv[1], &Nstars);
+  if (Nstars == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in data file, skipping\n");
+    fprintf (stderr, "SUCCESS\n");
+    exit (0);
+  }
+
+  check_permissions (ImageCat);
+  f = fsetlockfile (ImageCat, 3600.0, LCK_HARD, &dbstate);
+  if (f == (FILE *) NULL) { /* don't add to empty catalog */
+    fprintf (stderr, "ERROR: can't lock image catalog\n");
+    exit (1);
+  }
+  
+  /* put stars in the appropriate db file */
+  for (i = 0; i < Nstars; i++) {
+    if (stars[i].found != -1) continue;
+    gregion (&stars[i], &region);
+    check_permissions (region.filename);
+    make_backup (region.filename);
+
+    catalog.filename = region.filename;  /* don't free region before catalog! */
+    fprintf (stderr, "adding to %s [star %d]\n", region.filename, i);
+    
+    switch (lock_catalog (&catalog, LCK_XCLD)) {
+    case 0:
+      fprintf (stderr, "ERROR: can't lock file %s\n", catalog.filename);
+      exit (1);
+    case 1:
+      gcatalog (&catalog); /* load from disk */
+      break;
+    case 2:
+      mkcatalog (&region, &catalog); /* fills in new header info */
+      break;
+    }
+    subset = find_subset (&region, stars, Nstars, &subref, &Nsubset);
+    if (VERBOSE) fprintf (stderr, "%d stars in subset for %s\n", Nsubset, region.filename);
+    find_matches (&region, subset, Nsubset, &catalog);
+
+    /* protect wcatalog from interrupt signals */
+    Protect = TRUE;
+    wcatalog (&catalog);
+    if (Trapped) Shutdown ();
+    Protect = FALSE;
+    unlock_catalog (&catalog);
+
+    Nm = 0; Nf = 0;
+    for (j = 0; j < Nsubset; j++) {
+      stars[subref[j]].found = subset[j].found;
+      if (subset[j].found == -2) Nm ++;
+      if (subset[j].found >=  0) Nf ++;
+    }
+    /* found:
+       -1 - not yet tried
+       -2 - found on previous catalog
+       -3 - not found on previous catalog
+       +N - found elsewhere
+    */
+    if (VERBOSE) fprintf (stderr, "found %d stars, skipped %d stars\n", Nf, Nm);
+    free (subset);
+    free (subref);
+  }
+  
+  for (Nmissed = i = 0; i < Nstars; i++) {
+    if (stars[i].found == -1) {
+      fprintf (stderr, "%d %f %f %f %f\n", i, stars[i].R, stars[i].D, stars[i].M, stars[i].dM);
+      Nmissed ++;
+    }
+  }
+  if (Nmissed) fprintf (stderr, "WARNING: %d stars in image were missed!\n", Nmissed);
+
+  fclearlockfile (ImageCat, f, LCK_HARD, &dbstate);
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
+
+int SetSignals () {
+
+  int i;
+
+  /* disable almost all signal interrupts */
+  for (i = 0; i < 36; i++) {
+    switch (i) {
+      /* can't redirect this signals */
+    case SIGKILL:    /* kill -9: cannot be caught or ignored */
+    case SIGSTOP:    /* SIGSTOP: cannot be caught or ignored */
+      /* ignore these signals */
+    case SIGCHLD:    /* child halted: ignore */
+    case SIGPWR:     /* power failure - why ignore this? */
+    case SIGWINCH:   /* window resized */
+    case SIGCONT:    /* continue - maintain this action */
+    case SIGTSTP:    /* stop signal sent from tty - why ignore? */
+    case SIGURG:     /* socket signal, ignore this */
+      break;
+      
+    default:
+      signal (i, TrapSignal);
+    }
+  }
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/addrefs/src/aregion.c
===================================================================
--- /tags/start/Ohana/src/addrefs/src/aregion.c	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/src/aregion.c	(revision 12606)
@@ -0,0 +1,171 @@
+# include "addstar.h"
+
+double BigDecBounds[] = {0.0, 7.5, 15.0, 22.5, 30.0, 37.5, 45.0, 
+			 52.5, 60.0, 67.5, 75.0, 82.5, 90.0,
+			 0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, 
+			 -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+char *DecSections[] = {"N0000", "N0730", "N1500", "N2230", "N3000", "N3730", "N4500", 
+		       "N5230", "N6000", "N6730", "N7500", "N8230", "weirdness", 
+		       "S0000", "S0730", "S1500", "S2230", "S3000", "S3730", "S4500", 
+		       "S5230", "S6000", "S6730", "S7500", "S8230", "weirdness"};
+
+char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			"n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			"s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			"s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+char *disk[] = {"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", 
+		"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "weirdness", 
+		"disk 1", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", 
+		"disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "weirdness"};
+
+int NBigRASections [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3, 48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3};
+
+int NDecLines[] = {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 24, 
+                   0, 597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48};
+
+# define DEBUG 1
+
+/* find region file which contains ra, dec */
+void aregion (GSCRegion *region, FILE *f, double ra, double dec) {
+  
+  char buffer[28800], temp[50], file[256];
+  double RA0, RA1, DEC0, DEC1;
+  int i, NBigDec, NLINES, done;
+  
+  while (ra < 0) { ra += 360.0; }
+  while (ra >= 360.0) { ra -= 360.0; }
+
+  if (dec >= 86.25) {
+    sprintf (file, "%s/n8230/pole.cpt", CATDIR);
+    region[0].DEC[0] = 86.25;
+    region[0].DEC[1] = 93.75;
+    region[0].RA[0] =  0.0;
+    region[0].RA[1] =  360.0;
+    strcpy (region[0].filename, file);
+    return;
+  }
+    
+  NBigDec = -1;
+  for (i = 0; i < 12; i++) {
+    if ((dec >= BigDecBounds[i]) && (dec < BigDecBounds[i+1])) {
+      NBigDec = i;
+      break;
+    }
+  }
+  if (NBigDec < 0) {
+    for (i = 13; i < 25; i++) {
+      if ((dec < BigDecBounds[i]) && (dec >= BigDecBounds[i+1])) {
+	NBigDec = i;
+	break;
+      }
+    }
+  }
+  if (NBigDec < 0) {
+    fprintf (stderr, "dec out of range: %f\n", dec);
+  }
+    
+  NLINES = 0;
+  for (i = 0; i < NBigDec; i++) {
+    NLINES += NDecLines[i];
+  }
+  fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+      
+  done = FALSE;
+  Fread (buffer, 1, 48*NDecLines[NBigDec], f, "char");
+  for (i = 0; !done && (i < NDecLines[NBigDec]); i++) {
+    strncpy (temp, &buffer[i*48], 48);
+    temp[49] = 0;
+    hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+    if (RA1 < RA0) RA1 += 360.0;
+    if ((dec >= 0) && (dec >= DEC0) && (dec < DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+    if ((dec < 0) && (dec < DEC0) && (dec >= DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+  }
+
+  if (!done) {
+    fprintf (stderr, "ERROR: in search: %f %f\n", ra, dec);
+    exit (1);
+  }
+  temp[5] = 0;
+  sprintf (file, "%s/%s/%s.cpt", CATDIR, Dec2Sections[NBigDec],&temp[1]);
+  if (DEC0 < DEC1) {
+    region[0].DEC[0] = DEC0;
+    region[0].DEC[1] = DEC1;
+  } else {
+    region[0].DEC[0] = DEC1;
+    region[0].DEC[1] = DEC0;
+  }     
+  region[0].RA[0] = RA0;
+  region[0].RA[1] = RA1;
+  strcpy (region[0].filename, file);
+  return;
+}
+
+
+/**********/
+int hms_to_deg (double *h0, double *h1, double *d0, double *d1, char *string) {
+  
+  int flag_d0, flag_d1, flag_h0, flag_h1;
+  double tmp;
+  
+  *d0 = *h0 = *d1 = *h1 = 0;
+
+  flag_h0 = dparse (h0, 1, string);
+  flag_h1 = dparse (h1, 4, string);
+  flag_d0 = dparse (d0, 7, string);
+  flag_d1 = dparse (d1, 9, string);
+  *h0 *= flag_h0;
+  *h1 *= flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  dparse (&tmp, 2, string);
+  *h0 += tmp/60.0;
+  dparse (&tmp, 3, string);
+  *h0 += tmp/3600.0;
+  
+  dparse (&tmp, 5, string);
+  *h1 += tmp/60.0;
+  dparse (&tmp, 6, string);
+  *h1 += tmp/3600.0;
+  
+  dparse (&tmp, 8, string);
+  *d0 += tmp/60.0;
+
+  dparse (&tmp, 10, string);
+  *d1 += tmp/60.0;
+
+  *h0 *= 15*flag_h0;
+  *h1 *= 15*flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  return (TRUE);
+}
+
+
+/*
+      if (buffer[i*48 + 19] == ' ') continue;
+      strncpy (temp, &buffer[i*48 + 19], 20);       temp[20] = 0;
+      hms_to_deg (&RA,  &DEC, temp, ' ', 3);
+
+
+  dBigRA = 360.0 / (int)(0.5 + 48*cos(3.1415927*0.5*(BigDecBounds[NBigDec] + BigDecBounds[NBigDec + 1])/180.0));
+
+  NBigRA = ra / dBigRA;
+
+  NBig = NBigRA;
+  for (i = 0; (i < 12) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+  for (i = 13; (i < 24) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+
+
+  fprintf (stderr, "%d %d %d %d %f %f -> %f %f %f\n", NBigDec, NBigRA, NBigRASections[NBigDec], NBig, ra, dec, BigDecBounds[NBigDec], BigDecBounds[NBigDec + 1], dBigRA);
+*/
Index: /tags/start/Ohana/src/addrefs/src/args.c
===================================================================
--- /tags/start/Ohana/src/addrefs/src/args.c	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/src/args.c	(revision 12606)
@@ -0,0 +1,58 @@
+# include "addstar.h"
+# define NARGS 3  /* minimum is: addstar (filename) */
+
+void help () {
+
+  fprintf (stderr, "USAGE: addrefs (filename) (photcode)\n");
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -v (verbose mode)\n");
+  fprintf (stderr, "\n"); 
+  exit (2);
+
+}
+
+int args (int argc, char **argv) {
+  
+  int i;
+
+  if (get_argument (argc, argv, "-help") ||
+      get_argument (argc, argv, "-h")) {
+    help ();
+  }
+
+  ConfigInit (&argc, argv);
+
+  VERBOSE = FALSE;
+  if ((i = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  REPLACE = FALSE;
+  if ((i = get_argument (argc, argv, "-replace"))) {
+    REPLACE = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  ONLY_MATCH = FALSE;
+  if ((i = get_argument (argc, argv, "-only-match"))) {
+    ONLY_MATCH = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  TIMEREF = 0; 
+  if ((i = get_argument (argc, argv, "-time"))) {
+    remove_argument (i, &argc, argv);
+    if (!str_to_time (argv[i], &TIMEREF)) { 
+      fprintf (stderr, "syntax error in time\n");
+      exit (1);
+    }
+    remove_argument (i, &argc, argv);
+  }
+
+  if (argc != NARGS) help ();
+
+  /* get photcode, check for type == PHOT_REF? */
+  if ((thiscode = GetPhotcodebyName (argv[2])) == NULL) {
+    fprintf (stderr, "ERROR: photcode %s not found in photcode table\n", argv[2]);
+    exit (1);
+  }
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/addrefs/src/check_permissions.c
===================================================================
--- /tags/start/Ohana/src/addrefs/src/check_permissions.c	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/src/check_permissions.c	(revision 12606)
@@ -0,0 +1,90 @@
+# include "addstar.h"
+
+void check_permissions (char *basefile) {
+  
+  char *c, dir[256], filename[256];
+  struct stat filestat;
+  uid_t uid;
+  gid_t gid;
+  int status, cmode;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to write to directory */
+  sprintf (filename, "%s", basefile);
+  c = strrchr (filename, '/');
+  if (c == (char *) NULL) {
+    strcpy (dir, ".");
+  } else {
+    *c = 0;
+    strcpy (dir, filename);
+  }
+  status = stat (dir, &filestat);
+  if (status == -1) {
+    fprintf (stderr, "directory %s does not exist, creating...\n", dir);
+    cmode = S_IRWXU | S_IRWXG | S_IRWXO;
+    status = mkdir (dir, cmode);
+    if (status == -1) {
+      fprintf (stderr, "ERROR: can't create %s\n", dir);
+      exit (1);
+    }
+  } 
+  status = stat (dir, &filestat);
+  if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRWXU)) ||
+      ((gid == filestat.st_gid) && (filestat.st_mode & S_IRWXG)) || 
+      (filestat.st_mode & S_IRWXO)) {
+  } else {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (1);
+  }
+  
+  /* check permission to write to file */
+  sprintf (filename, "%s", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (1);
+    }
+  }
+  
+  /* check permission to write to backup file */
+  sprintf (filename, "%s~", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (1);
+    }
+  }
+  
+}
+
+/* uses cp only */
+void make_backup (char *filename) {
+
+  int status, cmode;
+  struct stat filestat;
+  char line [256];
+
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, make backup copy */
+    sprintf (line, "cp %s %s~", filename, filename);
+    status = system (line);
+    if (status) {
+      fprintf (stderr, "ERROR: unable to create %s~, exiting\n", filename);
+      exit (1);
+    }
+    cmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    sprintf (line, "%s~", filename);
+    chmod (line, cmode);
+  }
+  
+}
Index: /tags/start/Ohana/src/addrefs/src/conversions.c
===================================================================
--- /tags/start/Ohana/src/addrefs/src/conversions.c	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/src/conversions.c	(revision 12606)
@@ -0,0 +1,301 @@
+# include "addstar.h"
+enum {TIME_NONE, TIME_DATE, TIME_HOURS, TIME_DAYS, TIME_JD, TIME_MJD, TIME_SEC};
+
+/***** convert [-]00:00:00 to 0.0000 ****/
+int dms_to_ddd (double *Value, char *string) {
+  
+  int valid, neg, status;
+  double tmp, value;
+  char *p1, *p2, *px;
+
+  valid = FALSE; 
+  neg = FALSE;
+  stripwhite (string);
+  p1 = string;
+  px = string + strlen(string);
+
+  if (string[0] == '-') { 
+    valid = TRUE; 
+    neg = TRUE;
+    p1 = &string[1];
+  }
+  if (string[0] == '+') { 
+    valid = TRUE; 
+    neg = FALSE;
+    p1 = &string[1];
+  }
+  if (isdigit(string[0])) { 
+    valid = TRUE;
+    p1 = &string[0];
+  }
+  if (!valid) { return (FALSE); }
+
+  status = 1;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) return (FALSE); /* entry not a number: +fred */
+  value = tmp;
+  if (p2 == px) goto escape;    /* entry only number: +1.0 */ 
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:fred */
+  status = 2;
+  value += tmp / 60.0;
+  if (p2 == px) goto escape;    /* entry only number: +1:1 */
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:1:fred */
+  value += tmp / 3600.0;
+
+ escape:
+  if (neg) {
+    value *= -1;
+  }
+  *Value = value;
+
+  return (status);
+}
+
+/**********/
+int str_to_radec (double *ra, double *dec, char *str1, char *str2) {
+
+  double Ra, Dec;
+
+  *ra = *dec = 0;
+  switch (dms_to_ddd (&Ra, str1)) {
+  case 0:
+    fprintf (stderr, "syntax error in RA\n");
+    return (FALSE);
+  case 1:
+    break;
+  case 2:
+    Ra = Ra * 15;
+    break;
+  }
+  switch (dms_to_ddd (&Dec, str2)) {
+  case 0:
+    fprintf (stderr, "syntax error in DEC\n");
+    return (FALSE);
+  case 1:
+  case 2:
+    break;
+  }
+  *ra = Ra;
+  *dec = Dec;
+  return (TRUE);
+}
+
+# define FORMAT_DAYS    1
+# define FORMAT_HOURS   2
+# define FORMAT_MINUTES 3
+# define FORMAT_SECONDS 4
+# define FORMAT_JD      5
+# define FORMAT_DATE    6
+
+/**********/
+int chk_time (char *line) {
+
+  char *p1, *p2;
+  double tmp;
+  int mode;
+
+  p1 = line;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1 + strlen (p1) - 1) {
+    if (*p2 == 'd') {
+      mode = FORMAT_DAYS;
+    }
+    if (*p2 == 'h') {
+      mode = FORMAT_HOURS;
+    }
+    if (*p2 == 'm') {
+      mode = FORMAT_MINUTES;
+    }
+    if (*p2 == 's') {
+      mode = FORMAT_SECONDS;
+    }
+    if (*p2 == 'j') {
+      mode = FORMAT_JD;
+    }
+  } else { 
+    mode = FORMAT_DATE;
+  }
+  return (mode);
+}
+
+/**********/
+int str_to_time (char *line, unsigned int *second) {
+  
+  char *tmpline;
+  struct tm *gmt;
+  struct timeval now;
+  double jd;
+  unsigned long tsec;
+
+  if (!strcasecmp (line, "NOW")) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    *second = now.tv_sec;
+    return (TRUE);
+  }
+    
+  if (!strncasecmp (line, "TODAY", 5)) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    if (line[5]) { /* line has extra data (ie, hh:mm:ss) */
+      tsec = now.tv_sec;
+      ALLOCATE (tmpline, char, 64);
+      gmt   = gmtime (&tsec);
+      sprintf (tmpline, "%04d/%02d/%02d,%s", 
+	       1900 + gmt[0].tm_year, gmt[0].tm_mon+1, gmt[0].tm_mday, &line[6]);
+      *second = date_to_sec (tmpline);
+      free (tmpline);
+      return (TRUE);
+    } else {
+      *second = 86400 * ((int)(now.tv_sec / 86400));
+      return (TRUE); 
+    }
+  }
+    
+  switch (chk_time (line)) {
+  case 0:
+    return (FALSE);
+  case FORMAT_DAYS:
+    *second = strtod (line, 0) * 86400.0;
+    return (TRUE);
+  case FORMAT_HOURS:
+    *second = strtod (line, 0) * 3600.0;
+    return (TRUE);
+  case FORMAT_MINUTES:
+    *second = strtod (line, 0) * 60.0;
+    return (TRUE);
+  case FORMAT_SECONDS:
+    *second = strtod (line, 0);
+    return (TRUE);
+  case FORMAT_JD:
+    jd = strtod (line, 0);
+    *second = jd_to_sec (jd);
+    return (TRUE);
+  case FORMAT_DATE:
+    *second = date_to_sec (line);
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+
+/**********/
+int str_to_dtime (char *line, double *second) {
+  
+  switch (chk_time (line)) {
+  case 0:
+  case FORMAT_JD:
+  case FORMAT_DATE:
+    return (FALSE);
+  case FORMAT_DAYS:
+    *second = strtod (line, 0) * 86400.0;
+    return (TRUE);
+  case FORMAT_HOURS:
+    *second = strtod (line, 0) * 3600.0;
+    return (TRUE);
+  case FORMAT_MINUTES:
+    *second = strtod (line, 0) * 60.0;
+    return (TRUE);
+  case FORMAT_SECONDS:
+    *second = strtod (line, 0);
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+/**********/
+double sec_to_jd (unsigned long second) {
+
+  double jd;
+  
+  jd = second/86400.0 + 2440587.5;
+  return (jd);
+}
+
+/**********/
+unsigned long jd_to_sec (double jd) {
+
+  unsigned long second;
+
+  second = (jd - 2440587.5)*86400;
+  return (second);
+}
+
+/**********/
+char *sec_to_date (unsigned long second) {
+  
+  struct tm *gmt;
+  char *line;
+  
+  ALLOCATE (line, char, 64);
+  gmt   = gmtime (&second);
+  sprintf (line, "%04d/%02d/%02d,%02d:%02d:%02d", 
+	   1900 + gmt[0].tm_year, gmt[0].tm_mon+1, gmt[0].tm_mday, 
+	   gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+  return (line);
+
+}
+
+/***** date in format yyyy/mm/dd,hh:mm:ss *****/
+unsigned long date_to_sec (char *date) {
+  
+  unsigned long second;
+  double tmp, jd;
+  struct tm now;
+  char *p1, *p2, *px;
+  
+  p1 = date;
+  px = date + strlen(date);
+  bzero (&now, sizeof(now));
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_year = tmp;
+  if (now.tm_year > 1000) now.tm_year -= 1900;
+  if (now.tm_year <   50) now.tm_year += 100;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mon = tmp - 1; /* mon runs from 0 - 11 */
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mday = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  p1 = p2 + 1;
+  now.tm_hour = tmp;
+  if (p2 == px) goto escape;  
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_min = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_sec = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+ escape:
+  jd = now.tm_mday - 32075 + (int)(1461*(1900 + now.tm_year + 4800 + (int)(((now.tm_mon+1)-14)/12))/4)
+    + (int)(367*((now.tm_mon+1) - 2 - (int)(((now.tm_mon+1) - 14)/12)*12)/12)
+    - (int)(3*(int)((1900 + now.tm_year + 4900 + (int)(((now.tm_mon+1) - 14)/12))/100)/4) - 0.5;
+  
+  second = (jd - 2440587.5)*86400 + 3600.0*now.tm_hour + now.tm_min*60.0 + now.tm_sec;
+
+  return (second);
+}
Index: /tags/start/Ohana/src/addrefs/src/find_matches.c
===================================================================
--- /tags/start/Ohana/src/addrefs/src/find_matches.c	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/src/find_matches.c	(revision 12606)
@@ -0,0 +1,385 @@
+# include "addstar.h"
+
+void find_matches (GSCRegion *region, Stars *stars, int Nstars, Catalog *catalog) {
+
+  int i, j, k, n, m, N, first_j;
+  double RADIUS, RADIUS2;
+  float *X1, *Y1, *X2, *Y2;
+  float dX, dY, dR;
+  int *N1, *N2,  *next, *next_miss, last, last_miss;
+  int Nave, NAVE, Nmeas, NMEAS, Nmiss, NMISS, Nmatch;
+  Measure *tmpmeasure;
+  Missing *tmpmissing;
+  Coords tcoords;
+  int Nsecfilt, Nsec;
+
+  /** allocate local arrays **/
+  ALLOCATE (X1, float, Nstars);
+  ALLOCATE (Y1, float, Nstars);
+  ALLOCATE (N1, int, Nstars);
+
+  Nsecfilt = GetPhotcodeNsecfilt ();
+  Nsec     = GetPhotcodeNsec (thiscode[0].code);
+
+  Nave = catalog[0].Naverage;
+  NAVE = Nave + 1000;
+  ALLOCATE (X2, float, NAVE);
+  ALLOCATE (Y2, float, NAVE);
+  ALLOCATE (N2, int, NAVE);
+  ALLOCATE (catalog[0].found, int, NAVE);
+  REALLOCATE (catalog[0].average, Average, NAVE);
+  REALLOCATE (catalog[0].secfilt, SecFilt, NAVE*catalog[0].Nsecfilt);
+  /* for secfilt j and star i, secfilt[i*Nsecfilt+j] */
+
+  Nmatch = 0;
+  Nmeas = catalog[0].Nmeasure;
+  NMEAS = Nmeas + 1000;
+  ALLOCATE (next, int, NMEAS);
+  REALLOCATE (catalog[0].measure, Measure, NMEAS);
+  
+  Nmiss = catalog[0].Nmissing;
+  NMISS = Nmiss + 1000;
+  ALLOCATE (next_miss, int, NMISS);
+  REALLOCATE (catalog[0].missing, Missing, NMISS);
+  
+  /* project onto rectilinear grid with 1 arcsec pixels, sort by X */
+  /* reference for coords is catalog center */
+  tcoords.crval1 = 0.5*(region[0].RA[0] + region[0].RA[1]);
+  tcoords.crval2 = 0.5*(region[0].DEC[0] + region[0].DEC[1]);
+  tcoords.crpix1 = tcoords.crpix2 = 0.0;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1 = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2 = tcoords.pc2_1 = 0.0;
+  strcpy (tcoords.ctype, "RA---TAN");
+  tcoords.Npolyterms = 0;
+  
+  for (i = 0; i < Nstars; i++) {
+    fRD_to_XY (&X1[i], &Y1[i], stars[i].R, stars[i].D, &tcoords);
+    N1[i] = i;
+  }
+  if (Nstars > 1) sort_lists (X1, Y1, N1, Nstars);
+  
+  for (i = 0; i < Nave; i++) {
+    fRD_to_XY (&X2[i], &Y2[i], catalog[0].average[i].R, catalog[0].average[i].D, &tcoords);
+    N2[i] = i;
+    catalog[0].found[N2[i]] = -1;
+  }
+  if (Nave > 1) sort_lists (X2, Y2, N2, Nave);
+
+  /* set up pointers for linked list of measurements */
+  for (i = 0; i < Nmeas - 1; i++) {
+    next[i] = i+1;
+  }
+  next[i] = -1;
+  last = i;
+
+  for (i = 0; i < Nmiss - 1; i++) {
+    next_miss[i] = i+1;
+  }
+  next_miss[i] = -1;
+  last_miss = i;
+
+  /* choose a radius for matches */
+  /* 0.02 corrects cerror to arcsec from storage units */
+  if (DEFAULT_RADIUS == 0) {
+    RADIUS = 2.0;
+  } else {
+    RADIUS = DEFAULT_RADIUS;
+  }
+  RADIUS2 = RADIUS*RADIUS;
+
+  /** find matched stars **/
+  for (i = j = 0; (i < Nstars) && (j < Nave); ) {
+    
+    dX = X1[i] - X2[j];
+    /* fprintf (stderr, "%f   %f %f  %f %f    %f %f  %f %f\n", dX, X1[i], Y1[i], X2[j], Y2[j], stars[i].R, stars[i].D, catalog[0].average[j].R, catalog[0].average[j].D); */
+
+    if (dX <= -2*RADIUS) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*RADIUS) {
+      j++;
+      continue;
+    }
+
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    for (; (dX > -2*RADIUS) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < RADIUS2) {  /* new measurement of this star */
+	Nmatch ++;
+	n = N2[j];
+	N = N1[i];
+
+	/** in replace mode, search for entry and replace values M, dM, R, D */
+	if (REPLACE) {
+	  int found;
+	  found = FALSE;
+	  m = catalog[0].average[n].offset;  
+	  for (k = 0; !found && (k < catalog[0].average[n].Nm); k++) {
+	    if (catalog[0].measure[m+k].source == thiscode[0].code) {
+	      catalog[0].measure[m+k].dR       = 360000.0*(catalog[0].average[n].R - stars[N].R);
+	      catalog[0].measure[m+k].dD       = 360000.0*(catalog[0].average[n].D - stars[N].D);
+	      catalog[0].measure[m+k].M        = 1000.0*stars[N].M;
+	      catalog[0].measure[m+k].dM       = 1000.0*MIN (255, stars[N].dM);  /* error in input files stored in thousandths of mag */
+	      found = TRUE;
+	      stars[N].found = m+k;  /* save first match, in case coincidences are found */
+	    }
+	  }
+	  if (found) continue;
+	}
+
+	/** insert star in measurement list */
+	/* find last measurement of this star */
+	m = catalog[0].average[n].offset;  
+	for (k = 0; k < catalog[0].average[n].Nm - 1; k++) m = next[m];
+	/* set up references */
+	next[Nmeas] = next[m];
+	next[m] = Nmeas;
+	/* last just was moved */
+	if (next[Nmeas] == -1) last = Nmeas;
+	
+	/** add measurements for this star **/
+	catalog[0].measure[Nmeas].dR       = 360000.0*(catalog[0].average[n].R - stars[N].R);
+	catalog[0].measure[Nmeas].dD       = 360000.0*(catalog[0].average[n].D - stars[N].D);
+	catalog[0].measure[Nmeas].M        = 1000.0*stars[N].M;
+	catalog[0].measure[Nmeas].Mcal     = 0;
+	catalog[0].measure[Nmeas].dM       = 1000.0*MIN (255, stars[N].dM);  /* error in input files stored in thousandths of mag */
+	catalog[0].measure[Nmeas].t        = TIMEREF;
+	catalog[0].measure[Nmeas].averef   = n;
+	catalog[0].measure[Nmeas].source   = thiscode[0].code;
+	catalog[0].measure[Nmeas].dophot   = stars[N].dophot;  /* error in input files stored in thousandths of mag */
+	catalog[0].measure[Nmeas].flags    = 0;
+	catalog[0].measure[Nmeas].dt       = 0xffff;
+
+	catalog[0].measure[Nmeas].Mgal     = NO_MAG;
+	catalog[0].measure[Nmeas].airmass  = 0;
+	catalog[0].measure[Nmeas].FWx      = NO_MAG;
+	catalog[0].measure[Nmeas].fwy      = 0xff;
+	catalog[0].measure[Nmeas].theta    = 0xff;
+	
+	/* check for entries in the secfilt lists */
+	if ((thiscode[0].type == PHOT_PRI) && (catalog[0].average[n].M == NO_MAG)) {
+	  catalog[0].average[n].M = 1000.0*stars[N].M;
+	}
+	if ((thiscode[0].type == PHOT_SEC) && (catalog[0].secfilt[n*Nsecfilt+Nsec].M == NO_MAG)) {
+	  catalog[0].secfilt[n*Nsecfilt+Nsec].M = 1000.0*stars[N].M;
+	}
+
+	/*** handle multiple stars */
+	/* this image star matches more than one catalog star */
+	if (stars[N].found > -1) {
+	  catalog[0].measure[stars[N].found].flags |= BLEND_IMAGE;
+	  catalog[0].measure[Nmeas].flags |= BLEND_IMAGE;
+	} 
+	if (stars[N].found == -2) { /* this image star matches a catalog star on a neighboring catalog */
+	  catalog[0].measure[Nmeas].flags |= BLEND_IMAGE_NEIGHBOR;
+	} 
+	if (stars[N].found == -1) { /* this image star matches only this catalog star */
+	  stars[N].found = Nmeas;  /* save first match, in case coincidences are found */
+	}
+	/* this catalog star matches more than one image star */
+	if (catalog[0].found[n] > -1) {
+	  catalog[0].measure[catalog[0].found[n]].flags |= BLEND_CATALOG;
+	  catalog[0].measure[Nmeas].flags |= BLEND_CATALOG;
+	} else {
+	  catalog[0].found[n] = Nmeas;
+	}
+
+	catalog[0].average[n].Nm ++;
+	Nmeas ++;
+	if (Nmeas == NMEAS) {
+	  NMEAS = Nmeas + 1000;
+	  REALLOCATE (next, int, NMEAS);
+	  REALLOCATE (catalog[0].measure, Measure, NMEAS);
+	}
+
+	/* update values of Ro, Do */
+	if (catalog[0].average[n].Nm > 2) {
+	  double R, D, r, d, r2, d2, Npt;
+	  Npt = r = d = r2 = d2 = 0;
+	  m = catalog[0].average[n].offset;  /* first measurement of this star */
+	  for (k = 0; k < catalog[0].average[n].Nm; k++) {
+	    if (catalog[0].measure[m].t == 0) {
+	      m = next[m];
+	      continue;
+	    }
+	    R = catalog[0].measure[m].dR;
+	    D = catalog[0].measure[m].dD;
+	    r += R;
+	    d += D;
+	    r2 += R*R;
+	    d2 += D*D;
+	    m = next[m];
+	    Npt += 1.0;
+	  }
+	  if (Npt > 2) {
+	    r = r / Npt;  /* these are corrections in 1/100 arcsec to RA and DEC */
+	    d = d / Npt;
+	    R = r2 / Npt - r*r;
+	    D = d2 / Npt - d*d;
+	    /* Xp is scatter in position in hundredths of arcsec */
+	    catalog[0].average[n].Xp = sqrt (D + R / SQ(cos(catalog[0].average[n].D*RAD_DEG)));
+	    m = catalog[0].average[n].offset;  /* first measurement of this star */
+	    for (k = 0; k < catalog[0].average[n].Nm; k++) {
+	      catalog[0].measure[m].dR = catalog[0].measure[m].dR - r;
+	      catalog[0].measure[m].dD = catalog[0].measure[m].dD - d;
+	      m = next[m];
+	    }
+	    catalog[0].average[n].R = catalog[0].average[n].R - r / 360000.0;
+	    catalog[0].average[n].D = catalog[0].average[n].D - d / 360000.0;
+	  }
+	}
+      }
+    }
+    j = first_j;
+    i++;
+  }
+
+  /* incorporate unmatched image stars, if this star is in field of this catalog */
+  /* skip if we want to force matches - combined with -replace, this lets us keep 
+     the reference up-to-date with known stars only */
+  for (i = 0; (i < Nstars) && !ONLY_MATCH; i++) {
+    N = N1[i];
+    if (stars[N].found < 0) {
+      catalog[0].average[Nave].R = stars[N].R;
+      catalog[0].average[Nave].D = stars[N].D;
+      catalog[0].average[Nave].M = NO_MAG;
+      for (j = 0; j < Nsecfilt; j++) {
+	catalog[0].secfilt[Nave*Nsecfilt+j].M  = NO_MAG;
+	catalog[0].secfilt[Nave*Nsecfilt+j].Xm = NO_MAG;
+      }
+
+      if (thiscode[0].type == PHOT_PRI) {
+	catalog[0].average[Nave].M = 1000.0*stars[N].M;
+      }
+      if (thiscode[0].type == PHOT_SEC) {
+	catalog[0].secfilt[Nave*Nsecfilt+Nsec].M = 1000.0*stars[N].M;
+      }
+      catalog[0].average[Nave].Nm        = 1;
+      catalog[0].average[Nave].Nn        = 0;
+      catalog[0].average[Nave].Xp        = NO_MAG;
+      catalog[0].average[Nave].Xm        = NO_MAG;
+      catalog[0].average[Nave].dM        = NO_MAG;
+      catalog[0].average[Nave].offset    = Nmeas;
+      catalog[0].average[Nave].missing   = -1;
+      catalog[0].average[Nave].code      = 0;
+
+      catalog[0].measure[Nmeas].dR       = 0.0;
+      catalog[0].measure[Nmeas].dD       = 0.0;
+      catalog[0].measure[Nmeas].M        = 1000.0*stars[N].M;
+      catalog[0].measure[Nmeas].Mcal     = 0;
+      catalog[0].measure[Nmeas].dM       = MIN (255, stars[N].dM);
+      catalog[0].measure[Nmeas].t        = 0;
+      catalog[0].measure[Nmeas].averef   = Nave;
+      catalog[0].measure[Nmeas].source   = thiscode[0].code;
+      catalog[0].measure[Nmeas].dophot   = stars[N].dophot;  /* error in input files stored in thousandths of mag */
+      catalog[0].measure[Nmeas].flags    = 0;
+      catalog[0].measure[Nmeas].dt       = 0xffff;
+
+      catalog[0].measure[Nmeas].Mgal     = NO_MAG;
+      catalog[0].measure[Nmeas].airmass  = 0;
+      catalog[0].measure[Nmeas].FWx      = NO_MAG;
+      catalog[0].measure[Nmeas].fwy      = 0xff;
+      catalog[0].measure[Nmeas].theta    = 0xff;
+
+      stars[N].found = Nmeas;
+      next[last] = Nmeas;
+      next[Nmeas] = -1;
+      last = Nmeas;
+      Nmeas ++;
+      if (Nmeas == NMEAS) {
+	NMEAS = Nmeas + 1000;
+	REALLOCATE (next, int, NMEAS);
+	REALLOCATE (catalog[0].measure, Measure, NMEAS);
+      }
+      Nave ++;
+      if (Nave == NAVE) {
+	NAVE = Nave + 1000;
+	REALLOCATE (catalog[0].average, Average, NAVE);
+	REALLOCATE (catalog[0].secfilt, SecFilt, NAVE*catalog[0].Nsecfilt);
+      }
+    }
+  }
+      
+  free (catalog[0].found);
+  REALLOCATE (catalog[0].average, Average, Nave);
+  REALLOCATE (catalog[0].measure, Measure, Nmeas);
+
+  /* fix order of Measure (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmeasure, Measure, Nmeas);
+  for (i = 0; i < Nave; i++) {
+    n = catalog[0].average[i].offset;
+    catalog[0].average[i].offset = N;
+    for (k = 0; k < catalog[0].average[i].Nm; k++, N++) {
+      tmpmeasure[N] = catalog[0].measure[n]; 
+      tmpmeasure[N].averef = i;
+      n = next[n];
+    }
+  }
+  free (catalog[0].measure);
+  catalog[0].measure = tmpmeasure;
+    
+  /* fix order of Missing (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmissing, Missing, Nmiss);
+  for (i = 0; i < Nave; i++) {
+    if (catalog[0].average[i].Nn > 0) {
+      n = catalog[0].average[i].missing;
+      catalog[0].average[i].missing = N;
+      for (k = 0; k < catalog[0].average[i].Nn; k++, N++) {
+	tmpmissing[N] = catalog[0].missing[n]; 
+	n = next_miss[n];
+      }
+    }
+  }
+  free (catalog[0].missing);
+  catalog[0].missing = tmpmissing;
+
+  /* note stars which have been found in this catalog */
+  for (i = 0; i < Nstars; i++) {
+    if (stars[i].found > -1) {
+      stars[i].found = -2;
+    } else {
+      stars[i].found = -3;
+    }
+  }
+
+  catalog[0].Naverage = Nave;
+  catalog[0].Nmeasure = Nmeas;
+  catalog[0].Nmissing = Nmiss;
+  if (VERBOSE) fprintf (stderr, "Nstars, Nave, Nmeas, Nmiss: %d %d %d %d, (%d matches)\n", Nstars, Nave, Nmeas, Nmiss, Nmatch);
+}
+
+
+# if (0)
+      /* this is a bit of an issue.  i don't want to include missing obs if the
+	 ref star has not been previously detected (why?), but if i do this, it won't 
+	 get all missed entries if ref star is detected in the future... */
+      /** now add references from all previous non-detection observations of this spot on the sky */
+      for (j = 0; j < Nimage; j++) {
+	if (in_image (catalog[0].average[Nave].R, catalog[0].average[Nave].D, &pimage[j])) {
+	  if (catalog[0].average[Nave].Nn < 1) {
+	    catalog[0].average[Nave].missing = Nmiss;
+	  }
+	  next_miss[last_miss] = Nmiss;
+	  next_miss[Nmiss] = -1;
+	  last_miss = Nmiss;
+	  /* this can now be done exactly */
+	  RD_to_XY (&X, &Y, catalog[0].average[Nave].R, catalog[0].average[Nave].D, &pimage[j].coords);	  
+	  catalog[0].missing[Nmiss].t  = pimage[j].tzero + 1e-4*Y*pimage[j].trate;  /* rough guess at time */
+	  catalog[0].average[Nave].Nn ++;
+	  Nmiss ++;
+	  if (Nmiss == NMISS) {
+	    NMISS = Nmiss + 1000;
+	    REALLOCATE (next_miss, int, NMISS);
+	    REALLOCATE (catalog[0].missing, Missing, NMISS);
+	  }
+  
+	}
+      }
+# endif
Index: /tags/start/Ohana/src/addrefs/src/find_subset.c
===================================================================
--- /tags/start/Ohana/src/addrefs/src/find_subset.c	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/src/find_subset.c	(revision 12606)
@@ -0,0 +1,37 @@
+# include "addstar.h"
+
+Stars *find_subset (GSCRegion *region, Stars *stars, int Nstars, int **Subref, int *NSTARS) {
+
+  int i, N, NSUBSET, *subref;
+  Stars *subset;
+  double RA0, RA1, DEC0, DEC1;
+
+  NSUBSET = 100;
+  ALLOCATE (subset, Stars, NSUBSET);
+  ALLOCATE (subref, int, NSUBSET);
+
+  RA0 = region[0].RA[0];
+  RA1 = region[0].RA[1];
+  DEC0 = region[0].DEC[0];
+  DEC1 = region[0].DEC[1];
+
+  if (VERBOSE) fprintf (stderr, "subset for %f - %f, %f - %f\n", RA0, RA1, DEC0, DEC1);
+  /* read in stars line-by-line */
+  for (i = N = 0; i < Nstars; i++) {
+    if ((stars[i].R >= RA0)  && (stars[i].R < RA1) &&
+	(stars[i].D >= DEC0) && (stars[i].D < DEC1)) {
+      subset[N] = stars[i];
+      subref[N] = i;
+      N++;
+      if (N == NSUBSET - 1) {
+	NSUBSET += 100;
+	REALLOCATE (subset, Stars, NSUBSET);
+	REALLOCATE (subref, int, NSUBSET);
+      }
+    }
+  }
+  *NSTARS = N;
+  *Subref = subref;
+  return (subset);
+}
+
Index: /tags/start/Ohana/src/addrefs/src/gcatalog.c
===================================================================
--- /tags/start/Ohana/src/addrefs/src/gcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/src/gcatalog.c	(revision 12606)
@@ -0,0 +1,46 @@
+# include "addstar.h"
+
+int gcatalog (Catalog *catalog) {
+  
+  int Nsecfilt;
+  char mode;
+
+  /* read catalog header */
+  mode = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+  if (!load_catalog (catalog, mode, VERBOSE)) {
+    fprintf (stderr, "ERROR: failure loading catalog\n");
+    exit (1);
+  }
+
+  /* check Nsecfile value, update if needed */
+  Nsecfilt = GetPhotcodeNsecfilt ();
+  if (catalog[0].Nsecfilt < Nsecfilt) {
+
+    int i, j, Nextra, in, out;
+    SecFilt *insec, *outsec;
+
+    Nextra = Nsecfilt - catalog[0].Nsecfilt;
+    insec = catalog[0].secfilt;
+    ALLOCATE (outsec, SecFilt, catalog[0].Naverage * Nsecfilt);
+    for (in = out = i = 0; i < catalog[0].Naverage; i++) {
+      for (j = 0; j < catalog[0].Nsecfilt; j++, in++, out++) {
+	outsec[out].M = insec[in].M;
+	outsec[out].Xm = insec[in].Xm;
+      }
+      for (j = 0; j < Nextra; j++, out++) {
+	outsec[out].M = NO_MAG;
+	outsec[out].Xm = NO_MAG;
+      }
+    }
+    free (catalog[0].secfilt);
+    catalog[0].secfilt = outsec;
+    catalog[0].Nsecfilt = Nsecfilt;
+  }
+
+  if (catalog[0].Nsecfilt > Nsecfilt) {
+    fprintf (stderr, "ERROR: can't reduce number of secondary filters\n");
+    exit (1);
+  }
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/addrefs/src/gimages.c
===================================================================
--- /tags/start/Ohana/src/addrefs/src/gimages.c	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/src/gimages.c	(revision 12606)
@@ -0,0 +1,158 @@
+# include "addstar.h"
+
+Image *gimages (Image *image, int *Npimage) {
+  
+  int i, j, k, Nimage, addtolist;
+  int NTIMAGE, Ntimage, ntimage;
+  int NPIMAGE, npimage;
+  FILE *f;
+  Image *timage, *pimage;
+  Coords tcoords;
+  Header header;
+  double r, d;
+  double Xi[5], Yi[5], Xo[5], Yo[5];  /* image and original corners */
+
+  /* check if image datafile exists, get header */
+  if (!fits_read_header (ImageCat, &header)) {
+    if (VERBOSE) fprintf (stderr, "New image catalog %s (1)\n", ImageCat);
+    *Npimage = 0;
+    return ((Image *) NULL);
+  }
+
+  /* project onto rectilinear grid with 1 arcsec pixels */
+  /* we keep the original crpix1,2 and crref1,2 */
+  tcoords = image[0].coords;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1 = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2 = tcoords.pc2_1 = 0.0;
+  strcpy (tcoords.ctype, "RA---TAN");
+
+  /* define original corners */
+  Xo[0] = 0;           Yo[0] = 0;
+  Xo[1] = image[0].NX; Yo[1] = 0;
+  Xo[2] = image[0].NX; Yo[2] = image[0].NY;
+  Xo[3] = 0;           Yo[3] = image[0].NY;
+  Xo[4] = 0;           Yo[4] = 0;  /* so we can make a loop easily */
+  for (j = 0; j < 5; j++) {
+    XY_to_RD (&r, &d, Xo[j], Yo[j], &image[0].coords);
+    RD_to_XY (&Xo[j], &Yo[j], r, d, &tcoords);
+  }
+  
+  /* get ready to read data on images */ 
+  f = fopen (ImageCat, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "New image catalog: %s (2)\n", ImageCat);
+    free (header.buffer);
+    *Npimage = 0;
+    return ((Image *) NULL);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  Nimage = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+
+  NTIMAGE = 100;
+  ALLOCATE (timage, Image, NTIMAGE);
+
+  npimage = 0;
+  NPIMAGE = 20;
+  ALLOCATE (pimage, Image, NPIMAGE);
+
+  for (Ntimage = 0; Ntimage < Nimage; Ntimage += ntimage) {
+    ntimage = Fread (timage, sizeof(Image), NTIMAGE, f, "image");
+    for (i = 0; i < ntimage; i++) {
+      addtolist = FALSE;
+      /* define image corners */
+      Xi[0] = 0;            Yi[0] = 0;
+      Xi[1] = timage[i].NX; Yi[1] = 0;
+      Xi[2] = timage[i].NX; Yi[2] = timage[i].NY;
+      Xi[3] = 0;            Yi[3] = timage[i].NY;
+      Xi[4] = 0;            Yi[4] = 0;  /* so we can make a loop easily */
+      /* transform to tcoords */
+      for (j = 0; j < 5; j++) {
+	XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+	RD_to_XY (&Xi[j], &Yi[j], r, d, &tcoords);
+      }
+      /* check if any edges cross */
+      for (j = 0; (j < 4) && !addtolist; j++) {
+	for (k = 0; (k < 4) && !addtolist; k++) {
+	  addtolist |= edge_check (&Xi[j], &Yi[j], &Xo[k], &Yo[k]);
+	}
+      }
+      if (addtolist) {
+	pimage[npimage] = timage[i];
+	npimage ++;
+	if (npimage == NPIMAGE) {
+	  NPIMAGE += 20;
+	  REALLOCATE (pimage, Image, NPIMAGE);
+	}
+      }
+    }
+
+    if (ntimage == 0) {
+      fprintf (stderr, "ERROR: expected %d images, only found %d\n", Nimage, Ntimage);
+      exit (1);
+    }
+  }
+
+  if (VERBOSE) fprintf (stderr, "found %d overlapping images\n", npimage);
+
+  fclose (f);
+  *Npimage = npimage;
+  return (pimage);
+
+}
+  
+int edge_check (double *x1, double *y1, double *x2, double *y2) {
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+double opening_angle (double x1, double y1, double x2, double y2, double x3, double y3) {
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
+
Index: /tags/start/Ohana/src/addrefs/src/gregion.c
===================================================================
--- /tags/start/Ohana/src/addrefs/src/gregion.c	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/src/gregion.c	(revision 12606)
@@ -0,0 +1,19 @@
+# include "addstar.h"
+
+void gregion (Stars *star, GSCRegion *region) {
+  
+  FILE *f;
+  
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find GSC region file %s\n", GSCFILE);
+    exit (1);
+  }
+  
+  aregion (region, f, star[0].R, star[0].D);
+
+  fprintf (stderr, " loading %s\n",  region[0].filename);
+  
+  fclose (f);
+  
+}
Index: /tags/start/Ohana/src/addrefs/src/gstars.c
===================================================================
--- /tags/start/Ohana/src/addrefs/src/gstars.c	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/src/gstars.c	(revision 12606)
@@ -0,0 +1,43 @@
+# include "addstar.h"
+#include <sys/time.h>
+#include <time.h>
+
+Stars *gstars (char *file, int *Nstars) {
+
+  FILE *f;
+  int N, NSTARS;
+  Stars *stars;
+  char line[256];
+
+  /* open file */
+  f = fopen (file, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't read data from %s\n", file);
+    Shutdown ();
+  }
+
+  NSTARS = 100;
+  ALLOCATE (stars, Stars, NSTARS);
+
+  /* read in stars line-by-line */
+  for (N = 0; scan_line (f, line) != EOF; N++) {
+    stripwhite (line);
+    if (line[0] == 0) continue;
+    if (line[0] == '#') continue;
+    dparse (&stars[N].R,  1, line);
+    dparse (&stars[N].D,  2, line);
+    dparse (&stars[N].M,  3, line);
+    dparse (&stars[N].dM, 4, line);
+    while (stars[N].R < 0.0) stars[N].R += 360.0;
+    while (stars[N].R >= 360.0) stars[N].R -= 360.0;
+    stars[N].dophot = 0;
+    stars[N].found = -1;
+    if (N == NSTARS - 1) {
+      NSTARS += 100;
+      REALLOCATE (stars, Stars, NSTARS);
+    }
+  }
+  *Nstars = N;
+  return (stars);
+}
+
Index: /tags/start/Ohana/src/addrefs/src/mkcatalog.c
===================================================================
--- /tags/start/Ohana/src/addrefs/src/mkcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/src/mkcatalog.c	(revision 12606)
@@ -0,0 +1,38 @@
+# include "addstar.h"
+# include <time.h>
+
+void mkcatalog (GSCRegion *region, Catalog *catalog) {
+  
+  char filename[64], line[64];
+  struct tm *local;
+  struct timeval now;
+
+  if (VERBOSE) fprintf (stderr, "new catalog file: %s\n", region[0].filename);
+  if (!fits_read_header (CatTemplate, &catalog[0].header)) {
+    fprintf (stderr, "ERROR: can't find template header %s\n", CatTemplate);
+    exit (1);
+  }
+  
+  /* assign header values for RA, DEC, DATE, etc */
+  fits_modify (&catalog[0].header, "RA0", "%lf", 1, region[0].RA[0]);
+  fits_modify (&catalog[0].header, "DEC0", "%lf", 1, region[0].DEC[0]);
+  fits_modify (&catalog[0].header, "RA1", "%lf", 1, region[0].RA[1]);
+  fits_modify (&catalog[0].header, "DEC1", "%lf", 1, region[0].DEC[1]);
+  gettimeofday (&now, NULL);
+  local = localtime (&now.tv_sec);
+  /* sprintf (line, "%02d/%02d/%02d\0", local[0].tm_year, local[0].tm_mon + 1, local[0].tm_mday);  */
+  fits_modify (&catalog[0].header, "DATE", "%s", 1, line);
+  strcpy (filename, CatTemplate);
+  ALLOCATE (catalog[0].average, Average, 1);
+  ALLOCATE (catalog[0].measure, Measure, 1);
+  ALLOCATE (catalog[0].missing, Missing, 1);
+  catalog[0].Naverage = catalog[0].Nmeasure = catalog[0].Nmissing = 0;
+
+  /* setup secondary filters to match photcodes */
+  ALLOCATE (catalog[0].secfilt, SecFilt, 1);
+  catalog[0].Nsecfilt = GetPhotcodeNsecfilt ();
+
+  /* Nsecfilt is number of filters.  Number of entries in array is
+     Nsecfilt * Naverage.  At this point, N entries == 0 */
+
+}
Index: /tags/start/Ohana/src/addrefs/src/sort_lists.c
===================================================================
--- /tags/start/Ohana/src/addrefs/src/sort_lists.c	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/src/sort_lists.c	(revision 12606)
@@ -0,0 +1,46 @@
+
+void sort_lists (float *X, float *Y, int *S, int N) {
+
+  int l,j,ir,i;
+  double tX, tY, tS;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    S[i] = tS;
+  }
+}
Index: /tags/start/Ohana/src/addrefs/src/wcatalog.c
===================================================================
--- /tags/start/Ohana/src/addrefs/src/wcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/src/wcatalog.c	(revision 12606)
@@ -0,0 +1,35 @@
+# include "addstar.h"
+
+void wcatalog (Catalog *catalog) {
+  
+  /* we'll leave these for now, but they are LONEOS specific */
+  fits_modify (&catalog[0].header, "MARKSTAR", "%t", 1, FALSE);
+  fits_modify (&catalog[0].header, "ADDUSNO", "%t", 1, FALSE);
+  fits_modify (&catalog[0].header, "MARKROCK", "%t", 1, FALSE);
+
+  if (!save_catalog (catalog, VERBOSE)) {
+    fprintf (stderr, "ERROR: failure saving catalog\n");
+    exit (1);
+  }
+
+  /* free, initialize data structures */
+
+  if (catalog[0].Naverage) {
+    free (catalog[0].average); 
+    catalog[0].Naverage = 0;
+  }
+  if (catalog[0].Nmeasure) {
+    free (catalog[0].measure); 
+    catalog[0].Nmeasure = 0;
+  }
+  if (catalog[0].Nmissing) {
+    free (catalog[0].missing); 
+    catalog[0].Nmissing = 0;
+  }
+  if (catalog[0].Nsecfilt) {
+    free (catalog[0].secfilt); 
+    catalog[0].Nsecfilt = 0;
+  }
+  fits_free_header (&catalog[0].header);
+}
+
Index: /tags/start/Ohana/src/addrefs/src/wimage.c
===================================================================
--- /tags/start/Ohana/src/addrefs/src/wimage.c	(revision 12606)
+++ /tags/start/Ohana/src/addrefs/src/wimage.c	(revision 12606)
@@ -0,0 +1,60 @@
+# include "addstar.h"
+
+void wimage (char *filename, Image *image, int Nstars) {
+  
+  int Nimages, status, mode;
+  FILE *f;
+  Header header;
+
+  if (!fits_read_header (ImageCat, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't find %s, creating a new one\n", ImageCat);
+    if (!fits_read_header (ImageTemplate, &header)) {
+      fprintf (stderr, "ERROR: can't find template header %s\n", ImageTemplate);
+      exit (1);
+    }
+    f = fopen (ImageCat, "w");
+    if (f == NULL) {
+      fprintf (stderr, "ERROR: can't create/open image catalog file: %s\n", ImageCat);
+      exit (1);
+    }
+  }
+  
+  Nimages = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimages);
+  Nimages ++;
+  fits_modify (&header, "NIMAGES", "%d", 1, Nimages);
+
+  f = fopen (ImageCat, "r+");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't create/open image catalog file: %s\n", ImageCat);
+    exit (1);
+  }
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  chmod (ImageCat, mode);
+
+  /* position to begining of file to write header */
+  fseek (f, 0, SEEK_SET);
+  status = Fwrite (header.buffer, 1, header.size, f, "char");
+  if (status != header.size) {
+    fprintf (stderr, "ERROR: failed writing data to image header\n");
+    exit (1);
+  }
+
+  fseek (f, 0, SEEK_END);
+  fprintf (stderr, "Image: %d\n", sizeof(Image));
+  status = Fwrite (image, sizeof(Image), 1, f, "image");
+  if (status != 1) {
+    fprintf (stderr, "ERROR: failed writing data to image catalog\n");
+    exit (1);
+  }
+
+  fclose (f);
+  
+
+}
+
+/* the image we add in this routine is always a new image.  
+   We only need to do two things:
+     1) append the data for the image to the end of the file
+     2) update the NIMAGES field in the header (which means, read in header, re-write)
+ */
Index: /tags/start/Ohana/src/addspphot/Makefile
===================================================================
--- /tags/start/Ohana/src/addspphot/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/Makefile	(revision 12606)
@@ -0,0 +1,61 @@
+include ../../Configure
+HOME 	=	$(ROOT)/src/addspphot
+PROGRAM =       addspphot
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#  
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lFITS -lohana -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS)
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+ADDSPPHOT = \
+$(SRC)/addspphot.$(ARCH).o 	$(SRC)/gcatalog.$(ARCH).o   \
+$(SRC)/gregions.$(ARCH).o 	$(SRC)/gimages.$(ARCH).o    \
+$(SRC)/wimage.$(ARCH).o   	$(SRC)/gstars.$(ARCH).o     \
+$(SRC)/find_matches.$(ARCH).o 	$(SRC)/wcatalog.$(ARCH).o   \
+$(SRC)/sort_lists.$(ARCH).o 	$(SRC)/ConfigInit.$(ARCH).o 	\
+$(SRC)/aregion.$(ARCH).o	$(SRC)/load_subpix.$(ARCH).o\
+$(SRC)/check_permissions.$(ARCH).o $(SRC)/calibrate.$(ARCH).o \
+$(SRC)/args.$(ARCH).o		$(SRC)/parse_time.$(ARCH).o \
+$(SRC)/mkcatalog.$(ARCH).o	$(SRC)/airmass.$(ARCH).o
+
+OBJ = $(ADDSPPHOT)
+
+default: $(PROGRAM)
+
+$(ADDSPPHOT): $(INC)/addstar.h
+
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:	
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
+
+
Index: /tags/start/Ohana/src/addspphot/doc/database.txt
===================================================================
--- /tags/start/Ohana/src/addspphot/doc/database.txt	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/doc/database.txt	(revision 12606)
@@ -0,0 +1,91 @@
+
+\begin{verbatim}
+
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm;      /* number of measurements */
+  unsigned short int Xp, Xm;  /* chisq values in tenths */
+  unsigned int offset;        /* offset to first Measure-ment */
+} Average;                    /* = 20 bytes / average */
+
+typedef struct {
+  char dR, dD;                /* tenths of arcsec (-12.7 to +12.7 valid range) */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 -- 0.255 valid range) */
+  float t;                    /* time in seconds (what is reference?) */
+  unsigned int average;       /* reference to corresponding Average entry, 
+				 upper byte of value contains flags.
+				 limit of 16,777,215 stars (Naverage) 
+				 in a file (=0xFFFFFF).
+				 flags = average & 0x1000000 */
+} Measure;                    /* = 13 bytes / measure */
+
+# define BLEND_IMAGE   0X01000000
+# define BLEND_CATALOG 0X02000000
+# define UPPER_LIMIT   0X04000000
+# define CALIBRATED    0X08000000
+
+\end{verbatim}
+
+The above two structures define the entries in the photometry
+database.  The database consists of a large number of files
+representing a small patch on the sky (roughly 1.5 degree$^2$ in most
+places).  These files are organized into directories representing
+bands of Declination.  A reference file determines the coordinate
+boundaries for each of the files so that a given point on the sky can
+unambiguously be associated with a specific file in a specific
+directory.  The sky coordinates for each file is the same as those
+used by the HST Guide Star catalog, except for the region around the
+North celestial pole, for which all stars are included in a single
+file.  
+
+Within a given file, the data are stored in a binary format, with an
+ASCII FITS-like header.  The header is examply in the format of a
+normal FITS header, but with the exception that all files have a fixed
+number of header blocks (for now 3 blocks = 8640 bytes).  This is done
+to speed loading the header and finding the beginning of the binary
+data.  The number of 3 blocks seems quite generous, as currently only
+a few FITS keywords have been defined for each file, basically
+keywords to define the number of stars and the total number of
+measurements stored in the file, as well as values to define the RA
+and DEC range of the file.  
+
+The first section of data following the header blocks consists of
+average measurements for each uniquely observed star.  Each star
+occupies 20 bytes, the size of the Average structure defined above.
+The Average structure contains the average Ra, Dec, and Magnitude for
+the star, as well as the number of measurements, and \chisq\ values
+for the magnitude and position.  Finally, there is a 32 bit integer
+which defines the offset to the first measurement for this star.  This
+offset is defined as the number of Measure records from the start of
+the Measure structure.
+
+The second section of data, following the Average data contains all
+measurements for each star listed in Average.  Each measurement
+occupies 13 bytes, the size of the Measure structure.  This structure
+contains the difference of this position from the average RA and DEC,
+and the instrumental magnitude of this measurement (in the units
+defined by the fstat program, which give m = -2.5*log(cts) + Mo, where
+Mo is currently 24.5 [10/15]).  There is also the magnitude error for
+this measurement, the time of the measurement (in seconds relative to
+a to-be-determined zero point), and a reference to the entry in the
+Average structure so we can relate a given measurement with a given star.
+This last entry also includes a byte of flags, of which only 4 have
+currently been defined.  This means the Average offset can only be as
+large as  16,777,215 (0xffffff), limiting the possible number of stars
+allowed in a given file.  This does not seem like a long term problem,
+though:  aside from the fact that this number is very large and we
+only expect in the vicinity of 20,000 stars per file, the file can
+easily be divided into pieces at a later date if needed.  this last
+step is trivial, consisting of splitting the data up into smaller
+RA,DEC regions, and updating the reference catalog.  With the above
+definitions for the Average and Measure structures, we will typically
+expect 20,000 * 15 measurements per year and 20,000 average entries in
+a given file.  This implies a file size of about 4.3 MB at the end of
+a year.  It is also possible that we will choose to split the files up
+in the future if the number of measurements makes their size
+unweildy.  4.3 MB is sufficiently small that this is not a problem,
+but after only 5 years, the files will be over 21 MB each, getting to
+be fairly significant.  
Index: /tags/start/Ohana/src/addspphot/doc/description.txt
===================================================================
--- /tags/start/Ohana/src/addspphot/doc/description.txt	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/doc/description.txt	(revision 12606)
@@ -0,0 +1,94 @@
+
+ADDSTAR:
+
+This program takes a photometry file, with astrometry, provided by
+earlier routines and incorporates the stellar measurements into the
+photometry database.  This routine does NOT try to calibrate or check
+the photometry, nor does it try to improve the coordinate
+determinations or calculate chisquares for position or photometry -
+those tasks are performed by other routines.
+
+Addstar starts by loading in the photometry file and converting the
+pixel coordinates to sky coordinates using the astrometry information
+in the header of the file.  It also gets the detection limits and
+stores the image astrometry information.
+
+Next, addstar determines which of all the previous images overlaps
+with this image and also which of the catalog regions overlaps with
+this image.
+
+Addstar considers each catalog region in turn, and compares the
+positions of stars in the catalog with stars in the image.  If a
+catalog star is detected, a new measurement is added to the catalog.
+If a catalog star is not detected, but is in the field of view of this
+image, the detection limit for this image is added to the list of
+measurements as an upper limit.  If the image contains a star which is
+not already included in the catalog, the star is added to the catalog,
+and all previous images are checked to see if they included this
+location.  If so, upper limits are added to the list of measurements.
+
+To deal with blended images, we have taken the philosophy that all
+measurements compatible with the coordinates of a given star should be
+included in the list of measurements.  This assumes that programs or people
+downstream will figure out which is the "correct" measurement.  To
+this end, if a catalog star is consistent with multiple measurements,
+they are all added to the catalog measurement and the measurements are
+given a flag to say that there was blending in the catalog (ie, it is
+probably the catalog star which is a blend).  If multiple catalog
+stars are consistent with the same image star, that measurement is
+added to each catalog star, and given a flag to say that there was
+blending on the image.
+
+After all catalogs have been checked, updated, and written to disk,
+the image is added to the database of images.
+
+The format for a catalog region file is as follows:
+
+-- 
+Header
+--
+Averages
+--
+Measurements
+--
+
+The Header follows the format of a FITS header but always stored with
+3 blocks to speed up read time: 2880 x 3 bytes.  Two important
+keywords in the header: NSTARS & NMEAS
+
+All average values are stored consecutively in a single block.  They
+are written as an array with NSTARS elements of the Average structure
+defined below.  The individual measurements follow the averages as a
+block.  To find a measurement for a given star, you need to get the
+value of the offset for the star.  this is the element number for the
+first measurement of this star, and are followed by next measurements
+for this star, until the value Nm is reached.
+
+Here are the structures being used for the average and measurement
+values:
+
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm;      /* number of measurements */
+  unsigned short int Xp, Xm;  /* chisq values in tenths */
+  unsigned int offset;        /* offset to first measurement */
+} Average;                    /* = 20 bytes / average */
+
+typedef struct {
+  char dR, dD;                /* tenths of arcsec (-12.7 to +12.7 valid range) */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 -- 0.255 valid range) */
+  float t;                    /* time in seconds (what is reference?) */
+  unsigned int average;       
+  /* reference to corresponding average entry, upper byte stores flags:
+   limit of 16,777,215 stars (Naverage) in a file (=0xFFFFFF) 
+   flags: average & 0x1000000 */
+} Measure;                    /* = 13 bytes / measure */
+
+/* flags for measurements: */
+# define BLEND_IMAGE   0X01000000
+# define BLEND_CATALOG 0X02000000
+# define UPPER_LIMIT   0X04000000
+# define CALIBRATED    0X08000000
Index: /tags/start/Ohana/src/addspphot/etc/phottemp.cat
===================================================================
--- /tags/start/Ohana/src/addspphot/etc/phottemp.cat	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/etc/phottemp.cat	(revision 12606)
@@ -0,0 +1,296 @@
+SIMPLE  =                    F  / ASTROCAM PHOTOMETRY FILE                    \
+BITPIX  =                   16 /                                              \
+NAXIS   =                    2  / NUMBER OF AXES                              \
+NAXIS1  =                 1106  / NUMBER OF COLUMNS                           \
+NAXIS2  =                 1024  / NUMBER OF ROWS                              \
+BSCALE  =             1.000000 /                                              \
+BZERO   =             0.000000 /                                              \
+DATE    = '19/12/94'            / UT Date of file creation (DD/MM/YY)         \
+ORIGIN  = 'MDM Observatory'     / Michigan-Dartmouth-MIT                      \
+LATITUDE=              31.9500  / Latitude (degrees N)                        \
+LONGITUD=            -111.6150  / Longitude (degrees E)                       \
+OBSERVER= 'Metzger '            / Name of observer                            \
+TELESCOP= '1.3m McGraw-Hill'    / Telescope used for observation              \
+INSTRUME= 'Charlotte Direct'    / Instrument used for observation             \
+DETECTOR= 'Charlotte/Tek 1024^2 CCD'  / Detector used for observation         \
+FRAME   =                   32  / Frame number of observation                 \
+CCDPICNO=                   32  / Frame number of observation                 \
+OBJECT  = 'ocl0327 '            / Name of object                              \
+IMAGETYP= 'OBJECT  '            / Type of observation                         \
+EXPTIME =              250.000  / Integration time (seconds)                  \
+DARKTIME=              250.067  / Dark current time (seconds)                 \
+DATE-OBS= '19/12/94'            / UT Date of observation (DD/MM/YY)           \
+UT      = ' 05:25:44.00'        / Universal time (UTC) at exposure start      \
+JD      =       2449705.726204                                                \
+RA      =           50.700      / Right Ascension                             \
+DEC     =           89.000      / Declination                                 \
+DIRECTN =                 -1    / Moving South                                \
+EQUINOX =             1950.000  / Equinox of RA and DEC                       \
+HA      = ' 02:14:06.72'        / Hour angle at start                         \
+ST      = ' 03:49:36.85'        / Sidereal time at start                      \
+ZD      = ' 36:26:07.17'        / Zenith distance (degrees)                   \
+AIRMASS =                1.243  / Airmass at start                            \
+FILTER  = 'I KP    '            / Filter description                          \
+GAIN    =                3.350  / Nominal gain (e-/ADU)                       \
+SECPIX1 =                0.508  / Arcseconds per pixel in fast dir            \
+SECPIX2 =                0.508  / Arcseconds per pixel in slow dir            \
+CCDBIN1 =                    1  / On-chip column binning (fast dir)           \
+CCDBIN2 =                    1  / On-chip row binning (slow dir)              \
+GPROBE  = '  5000.00   7000.00'  / Guide probe X Y                            \
+DATASEC = '[51:1074,1:1024]'    / Image area of frame                         \
+CCDSEC  = '[1:1074,1:1024]'     / Image area relative to full chip            \
+BIASSEC = '[1080:1106,1:1023]'  / Overscan area of frame                      \
+UNSIGN  =                    T /                                              \
+NSTARS  =                    0  / NUMBER OF stars                             \
+CTYPE1  = 'RA---SIN          ' /                                               
+CTYPE2  = 'DEC--SIN          ' /                                               
+CDELT1  =             0.000733 /                                               
+CDELT2  =             0.000733 /                                               
+CRVAL1  =            50.191418 /                                               
+CRVAL2  =            88.998663 /                                               
+CRPIX1  =          1028.644173 /                                               
+CRPIX2  =           503.129830 /                                               
+PC001001=             0.999906 /                                               
+PC001002=             0.012081 /                                               
+PC002001=            -0.011936 /                                               
+PC002002=             0.999950 /                                               
+END                                                                           \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+ 246.5  352.1 13.000 020 1 3.2
+ 246.5  352.1 14.100 020 1 3.2
+ 279.4  328.9 13.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 436.6  413.5 14.300 020 1 3.2
+   9.3  856.5 13.000 020 1 3.2
+   9.3  856.2 13.600 020 1 3.2
+ 319.7  697.9 12.000 020 1 3.2
+ 319.7  697.7 12.100 020 1 3.2
+ 244.3    9.5 14.100 020 1 3.2
+ 284.7  334.4 14.000 020 1 3.2
+ 127.1  122.8 14.200 020 1 3.2
+ 140.2  791.1 13.700 020 1 3.2
+ 140.2  790.8 14.400 020 1 3.2
+ 131.7  636.3 13.800 020 1 3.2
+ 423.8  700.6 13.800 020 1 3.2
+ 423.7  700.7 12.500 020 1 3.2
+ 266.2  290.7 13.800 020 1 3.2
+ 266.0  290.7 13.100 020 1 3.2
+ 570.7  721.6 13.600 020 1 3.2
+ 570.7  721.6 13.100 020 1 3.2
+ 548.7  673.0 13.700 020 1 3.2
+ 264.2  219.7 12.800 020 1 3.2
+ 264.0  219.7 12.100 020 1 3.2
+ 161.9  797.4 11.900 020 1 3.2
+ 162.0  797.2 12.200 020 1 3.2
+ 505.8  851.8 13.700 020 1 3.2
+  88.2  419.0 11.400 020 1 3.2
+  88.2  419.0 11.800 020 1 3.2
+ 426.9  613.2  9.400 020 1 3.2
+ 427.4  613.5  7.600 020 1 3.2
+ 326.1  595.2 12.100 020 1 3.2
+ 326.2  595.1 12.600 020 1 3.2
+ 444.4  845.2 14.200 020 1 3.2
+ 254.1  916.8 14.500 020 1 3.2
+ 502.6  882.4 14.200 020 1 3.2
+ 128.3  275.7 12.300 020 1 3.2
+ 128.3  275.7 12.900 020 1 3.2
+ 230.9  554.8 13.300 020 1 3.2
+ 230.9  554.7 14.200 020 1 3.2
+  47.5  685.2 13.500 020 1 3.2
+  47.5  684.9 14.200 020 1 3.2
+ 382.6  658.7 14.000 020 1 3.2
+ 182.2  330.3 14.200 020 1 3.2
+ 245.1  548.3 12.600 020 1 3.2
+ 245.3  548.0 13.200 020 1 3.2
+  50.3  849.0 13.700 020 1 3.2
+  50.5  848.8 14.300 020 1 3.2
+  17.9  772.7 14.200 020 1 3.2
+ 499.8  712.8 13.500 020 1 3.2
+ 499.8  712.6 14.400 020 1 3.2
+ 294.5  349.4 14.000 020 1 3.2
+ 497.7  747.8 11.000 020 1 3.2
+ 497.5  747.8 10.900 020 1 3.2
+ 109.7  323.5 14.000 020 1 3.2
+  59.5  917.6 14.300 020 1 3.2
+  59.4  917.8 13.700 020 1 3.2
+  82.2  880.5 13.800 020 1 3.2
+ 145.1  341.2 14.500 020 1 3.2
+ 452.7  592.4 14.400 020 1 3.2
+ 623.4  820.0 13.700 020 1 3.2
+ 609.7  829.3 13.500 020 1 3.2
+ 481.8  938.3 14.400 020 1 3.2
+ 617.0  792.7 13.500 020 1 3.2
+ 183.2  539.7 14.400 020 1 3.2
+ 133.9  679.6 14.400 020 1 3.2
+ 423.7  667.8  6.500 020 1 3.2
+ 434.7  111.9 13.200 020 1 3.2
+ 434.5  111.9 13.200 020 1 3.2
+ 434.6  111.9 14.200 020 1 3.2
+1222.3  684.2 13.900 020 1 3.2
+1077.6  282.5 14.000 020 1 3.2
+1077.8  282.5 13.400 020 1 3.2
+ 720.8  562.1 14.100 020 1 3.2
+ 721.1  561.9 14.400 020 1 3.2
+1182.1  944.4 12.100 020 1 3.2
+1181.9  944.4 11.800 020 1 3.2
+1181.9  944.4 12.300 020 1 3.2
+ 761.2  423.1 14.300 020 1 3.2
+ 761.0  423.1 14.100 020 1 3.2
+ 926.7  436.8 13.400 020 1 3.2
+ 926.6  436.8 14.200 020 1 3.2
+1209.1   45.0 13.200 020 1 3.2
+1209.2   43.6 12.800 020 1 3.2
+1135.2  653.1  8.100 020 1 3.2
+1135.6  653.4  8.200 020 1 3.2
+1123.5  735.8 12.000 020 1 3.2
+1123.6  735.8 11.800 020 1 3.2
+1123.7  735.7 11.600 020 1 3.2
+ 730.7   28.6 12.100 020 1 3.2
+ 730.7   28.6 12.200 020 1 3.2
+ 783.1  267.5 14.200 020 1 3.2
+ 783.2  267.5 13.400 020 1 3.2
+ 876.2  462.7 13.800 020 1 3.2
+ 876.4  462.7 14.200 020 1 3.2
+ 917.2  399.9 13.700 020 1 3.2
+ 917.3  399.9 13.200 020 1 3.2
+1227.5  218.4 10.400 020 1 3.2
+1227.7  218.4 10.500 020 1 3.2
+1022.7  146.0 13.300 020 1 3.2
+1022.5  146.0 14.100 020 1 3.2
+1324.7   72.3 12.900 020 1 3.2
+1324.6   72.3 13.200 020 1 3.2
+ 743.2  379.4 14.300 020 1 3.2
+ 742.9  379.4 13.900 020 1 3.2
+1255.9  544.0 12.600 020 1 3.2
+1256.0  543.9 12.300 020 1 3.2
+ 848.9  251.1 13.200 020 1 3.2
+ 849.0  251.1 12.700 020 1 3.2
+ 495.6  147.4 11.400 020 1 3.2
+ 495.6  147.4 11.300 020 1 3.2
+ 495.5  147.4 11.000 020 1 3.2
+1016.4  735.5 14.200 020 1 3.2
+1016.3  735.7 13.900 020 1 3.2
+ 795.2  675.9 14.400 020 1 3.2
+ 887.2  968.8 10.800 020 1 3.2
+ 626.8  726.9 14.400 020 1 3.2
+ 718.6  800.1  9.700 020 1 3.2
+ 675.4  301.6 14.400 020 1 3.2
+ 801.6  436.8 14.200 020 1 3.2
+1066.4  870.0 13.700 020 1 3.2
+1066.5  869.9 13.800 020 1 3.2
+ 644.5  662.9  9.900 020 1 3.2
+ 639.1  760.4 13.000 020 1 3.2
+ 822.7  663.1 12.800 020 1 3.2
+ 822.7  663.1 13.100 020 1 3.2
+ 677.2  716.2 12.900 020 1 3.2
+ 765.6  641.5 13.200 020 1 3.2
+ 765.7  641.4 13.500 020 1 3.2
+ 998.3  425.8 14.400 020 1 3.2
+ 713.7  716.2 13.800 020 1 3.2
+ 814.7  887.6  2.000 020 1 3.2
+ 808.7  884.1  8.200 020 1 3.2
+1812.3  259.3 14.500 020 1 3.2
+1655.9  655.4 12.200 020 1 3.2
+1655.9  655.4 12.100 020 1 3.2
+1577.2  839.6 11.500 020 1 3.2
+1577.2  839.6 11.400 020 1 3.2
+1643.7  597.0 14.100 020 1 3.2
+1552.8  251.1 10.100 020 1 3.2
+1552.8  251.1 10.300 020 1 3.2
+1410.0  999.9 13.900 020 1 3.2
+1335.6  687.0 13.000 020 1 3.2
+1335.8  686.8 12.700 020 1 3.2
+1471.4  262.0 14.200 020 1 3.2
+1479.6  608.3 14.200 020 1 3.2
+1478.1  211.5 12.000 020 1 3.2
+1478.3  211.5 12.000 020 1 3.2
+1552.5   46.4 14.500 020 1 3.2
+2042.4  548.3 10.800 020 1 3.2
+2042.6  548.3 11.000 020 1 3.2
+1448.0  915.7 14.100 020 1 3.2
+1462.3  989.2 13.000 020 1 3.2
+1462.3  989.0 12.700 020 1 3.2
+1316.9  787.3 14.100 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1677.2  106.4 13.100 020 1 3.2
+1677.0  106.4 13.300 020 1 3.2
+1324.2  429.9  9.200 020 1 3.2
+1324.2  429.9  9.000 020 1 3.2
+1462.8  214.3 13.700 020 1 3.2
+1462.8  214.3 14.200 020 1 3.2
+1405.4   95.5 11.700 020 1 3.2
+1405.2   95.5 11.600 020 1 3.2
+1604.8   90.0 11.200 020 1 3.2
+1604.8   90.0 11.300 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1459.8  473.6 13.400 020 1 3.2
+1459.7  473.6 13.800 020 1 3.2
+1438.7   77.8 12.200 020 1 3.2
+1438.6   77.8 12.200 020 1 3.2
+1355.0  114.6 13.000 020 1 3.2
+1354.9  114.6 13.200 020 1 3.2
+1941.4  940.7 13.000 020 1 3.2
+1941.6  940.7 12.900 020 1 3.2
+1994.0  800.8 13.900 020 1 3.2
+1993.8  800.8 14.000 020 1 3.2
+2024.4  907.0 13.700 020 1 3.2
+2024.4  907.0 13.800 020 1 3.2
+2035.7  881.6 13.900 020 1 3.2
+2035.9  881.6 13.800 020 1 3.2
+1994.0  924.2 12.100 020 1 3.2
+1994.0  924.2 12.000 020 1 3.2
Index: /tags/start/Ohana/src/addspphot/etc/template.cat
===================================================================
--- /tags/start/Ohana/src/addspphot/etc/template.cat	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/etc/template.cat	(revision 12606)
@@ -0,0 +1,296 @@
+SIMPLE  =                    F  / ASTROCAM PHOTOMETRY FILE                    \
+BITPIX  =                   16 /                                              \
+NAXIS   =                    2  / NUMBER OF AXES                              \
+NAXIS1  =                 1106  / NUMBER OF COLUMNS                           \
+NAXIS2  =                 1024  / NUMBER OF ROWS                              \
+BSCALE  =             1.000000 /                                              \
+BZERO   =             0.000000 /                                              \
+DATE    = '19/12/94'            / UT Date of file creation (DD/MM/YY)         \
+ORIGIN  = 'MDM Observatory'     / Michigan-Dartmouth-MIT                      \
+LATITUDE=              31.9500  / Latitude (degrees N)                        \
+LONGITUD=            -111.6150  / Longitude (degrees E)                       \
+OBSERVER= 'Metzger '            / Name of observer                            \
+TELESCOP= '1.3m McGraw-Hill'    / Telescope used for observation              \
+INSTRUME= 'Charlotte Direct'    / Instrument used for observation             \
+DETECTOR= 'Charlotte/Tek 1024^2 CCD'  / Detector used for observation         \
+FRAME   =                   32  / Frame number of observation                 \
+CCDPICNO=                   32  / Frame number of observation                 \
+OBJECT  = 'ocl0327 '            / Name of object                              \
+IMAGETYP= 'OBJECT  '            / Type of observation                         \
+EXPTIME =              250.000  / Integration time (seconds)                  \
+DARKTIME=              250.067  / Dark current time (seconds)                 \
+DATE-OBS= '19/12/94'            / UT Date of observation (DD/MM/YY)           \
+UT      = ' 05:25:44.00'        / Universal time (UTC) at exposure start      \
+JD      =       2449705.726204                                                \
+RA      =           50.700      / Right Ascension                             \
+DEC     =           89.000      / Declination                                 \
+DIRECTN =                 -1    / Moving South                                \
+EQUINOX =             1950.000  / Equinox of RA and DEC                       \
+HA      = ' 02:14:06.72'        / Hour angle at start                         \
+ST      = ' 03:49:36.85'        / Sidereal time at start                      \
+ZD      = ' 36:26:07.17'        / Zenith distance (degrees)                   \
+AIRMASS =                1.243  / Airmass at start                            \
+FILTER  = 'I KP    '            / Filter description                          \
+GAIN    =                3.350  / Nominal gain (e-/ADU)                       \
+SECPIX1 =                0.508  / Arcseconds per pixel in fast dir            \
+SECPIX2 =                0.508  / Arcseconds per pixel in slow dir            \
+CCDBIN1 =                    1  / On-chip column binning (fast dir)           \
+CCDBIN2 =                    1  / On-chip row binning (slow dir)              \
+GPROBE  = '  5000.00   7000.00'  / Guide probe X Y                            \
+DATASEC = '[51:1074,1:1024]'    / Image area of frame                         \
+CCDSEC  = '[1:1074,1:1024]'     / Image area relative to full chip            \
+BIASSEC = '[1080:1106,1:1023]'  / Overscan area of frame                      \
+UNSIGN  =                    T /                                              \
+NSTARS  =                    0  / NUMBER OF stars                             \
+CTYPE1  = 'RA---SIN          ' /                                               
+CTYPE2  = 'DEC--SIN          ' /                                               
+CDELT1  =             0.000733 /                                               
+CDELT2  =             0.000733 /                                               
+CRVAL1  =            50.191418 /                                               
+CRVAL2  =            88.998663 /                                               
+CRPIX1  =          1028.644173 /                                               
+CRPIX2  =           503.129830 /                                               
+PC001001=             0.999906 /                                               
+PC001002=             0.012081 /                                               
+PC002001=            -0.011936 /                                               
+PC002002=             0.999950 /                                               
+END                                                                           \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+ 246.5  352.1 13.000 020 1 3.2
+ 246.5  352.1 14.100 020 1 3.2
+ 279.4  328.9 13.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 436.6  413.5 14.300 020 1 3.2
+   9.3  856.5 13.000 020 1 3.2
+   9.3  856.2 13.600 020 1 3.2
+ 319.7  697.9 12.000 020 1 3.2
+ 319.7  697.7 12.100 020 1 3.2
+ 244.3    9.5 14.100 020 1 3.2
+ 284.7  334.4 14.000 020 1 3.2
+ 127.1  122.8 14.200 020 1 3.2
+ 140.2  791.1 13.700 020 1 3.2
+ 140.2  790.8 14.400 020 1 3.2
+ 131.7  636.3 13.800 020 1 3.2
+ 423.8  700.6 13.800 020 1 3.2
+ 423.7  700.7 12.500 020 1 3.2
+ 266.2  290.7 13.800 020 1 3.2
+ 266.0  290.7 13.100 020 1 3.2
+ 570.7  721.6 13.600 020 1 3.2
+ 570.7  721.6 13.100 020 1 3.2
+ 548.7  673.0 13.700 020 1 3.2
+ 264.2  219.7 12.800 020 1 3.2
+ 264.0  219.7 12.100 020 1 3.2
+ 161.9  797.4 11.900 020 1 3.2
+ 162.0  797.2 12.200 020 1 3.2
+ 505.8  851.8 13.700 020 1 3.2
+  88.2  419.0 11.400 020 1 3.2
+  88.2  419.0 11.800 020 1 3.2
+ 426.9  613.2  9.400 020 1 3.2
+ 427.4  613.5  7.600 020 1 3.2
+ 326.1  595.2 12.100 020 1 3.2
+ 326.2  595.1 12.600 020 1 3.2
+ 444.4  845.2 14.200 020 1 3.2
+ 254.1  916.8 14.500 020 1 3.2
+ 502.6  882.4 14.200 020 1 3.2
+ 128.3  275.7 12.300 020 1 3.2
+ 128.3  275.7 12.900 020 1 3.2
+ 230.9  554.8 13.300 020 1 3.2
+ 230.9  554.7 14.200 020 1 3.2
+  47.5  685.2 13.500 020 1 3.2
+  47.5  684.9 14.200 020 1 3.2
+ 382.6  658.7 14.000 020 1 3.2
+ 182.2  330.3 14.200 020 1 3.2
+ 245.1  548.3 12.600 020 1 3.2
+ 245.3  548.0 13.200 020 1 3.2
+  50.3  849.0 13.700 020 1 3.2
+  50.5  848.8 14.300 020 1 3.2
+  17.9  772.7 14.200 020 1 3.2
+ 499.8  712.8 13.500 020 1 3.2
+ 499.8  712.6 14.400 020 1 3.2
+ 294.5  349.4 14.000 020 1 3.2
+ 497.7  747.8 11.000 020 1 3.2
+ 497.5  747.8 10.900 020 1 3.2
+ 109.7  323.5 14.000 020 1 3.2
+  59.5  917.6 14.300 020 1 3.2
+  59.4  917.8 13.700 020 1 3.2
+  82.2  880.5 13.800 020 1 3.2
+ 145.1  341.2 14.500 020 1 3.2
+ 452.7  592.4 14.400 020 1 3.2
+ 623.4  820.0 13.700 020 1 3.2
+ 609.7  829.3 13.500 020 1 3.2
+ 481.8  938.3 14.400 020 1 3.2
+ 617.0  792.7 13.500 020 1 3.2
+ 183.2  539.7 14.400 020 1 3.2
+ 133.9  679.6 14.400 020 1 3.2
+ 423.7  667.8  6.500 020 1 3.2
+ 434.7  111.9 13.200 020 1 3.2
+ 434.5  111.9 13.200 020 1 3.2
+ 434.6  111.9 14.200 020 1 3.2
+1222.3  684.2 13.900 020 1 3.2
+1077.6  282.5 14.000 020 1 3.2
+1077.8  282.5 13.400 020 1 3.2
+ 720.8  562.1 14.100 020 1 3.2
+ 721.1  561.9 14.400 020 1 3.2
+1182.1  944.4 12.100 020 1 3.2
+1181.9  944.4 11.800 020 1 3.2
+1181.9  944.4 12.300 020 1 3.2
+ 761.2  423.1 14.300 020 1 3.2
+ 761.0  423.1 14.100 020 1 3.2
+ 926.7  436.8 13.400 020 1 3.2
+ 926.6  436.8 14.200 020 1 3.2
+1209.1   45.0 13.200 020 1 3.2
+1209.2   43.6 12.800 020 1 3.2
+1135.2  653.1  8.100 020 1 3.2
+1135.6  653.4  8.200 020 1 3.2
+1123.5  735.8 12.000 020 1 3.2
+1123.6  735.8 11.800 020 1 3.2
+1123.7  735.7 11.600 020 1 3.2
+ 730.7   28.6 12.100 020 1 3.2
+ 730.7   28.6 12.200 020 1 3.2
+ 783.1  267.5 14.200 020 1 3.2
+ 783.2  267.5 13.400 020 1 3.2
+ 876.2  462.7 13.800 020 1 3.2
+ 876.4  462.7 14.200 020 1 3.2
+ 917.2  399.9 13.700 020 1 3.2
+ 917.3  399.9 13.200 020 1 3.2
+1227.5  218.4 10.400 020 1 3.2
+1227.7  218.4 10.500 020 1 3.2
+1022.7  146.0 13.300 020 1 3.2
+1022.5  146.0 14.100 020 1 3.2
+1324.7   72.3 12.900 020 1 3.2
+1324.6   72.3 13.200 020 1 3.2
+ 743.2  379.4 14.300 020 1 3.2
+ 742.9  379.4 13.900 020 1 3.2
+1255.9  544.0 12.600 020 1 3.2
+1256.0  543.9 12.300 020 1 3.2
+ 848.9  251.1 13.200 020 1 3.2
+ 849.0  251.1 12.700 020 1 3.2
+ 495.6  147.4 11.400 020 1 3.2
+ 495.6  147.4 11.300 020 1 3.2
+ 495.5  147.4 11.000 020 1 3.2
+1016.4  735.5 14.200 020 1 3.2
+1016.3  735.7 13.900 020 1 3.2
+ 795.2  675.9 14.400 020 1 3.2
+ 887.2  968.8 10.800 020 1 3.2
+ 626.8  726.9 14.400 020 1 3.2
+ 718.6  800.1  9.700 020 1 3.2
+ 675.4  301.6 14.400 020 1 3.2
+ 801.6  436.8 14.200 020 1 3.2
+1066.4  870.0 13.700 020 1 3.2
+1066.5  869.9 13.800 020 1 3.2
+ 644.5  662.9  9.900 020 1 3.2
+ 639.1  760.4 13.000 020 1 3.2
+ 822.7  663.1 12.800 020 1 3.2
+ 822.7  663.1 13.100 020 1 3.2
+ 677.2  716.2 12.900 020 1 3.2
+ 765.6  641.5 13.200 020 1 3.2
+ 765.7  641.4 13.500 020 1 3.2
+ 998.3  425.8 14.400 020 1 3.2
+ 713.7  716.2 13.800 020 1 3.2
+ 814.7  887.6  2.000 020 1 3.2
+ 808.7  884.1  8.200 020 1 3.2
+1812.3  259.3 14.500 020 1 3.2
+1655.9  655.4 12.200 020 1 3.2
+1655.9  655.4 12.100 020 1 3.2
+1577.2  839.6 11.500 020 1 3.2
+1577.2  839.6 11.400 020 1 3.2
+1643.7  597.0 14.100 020 1 3.2
+1552.8  251.1 10.100 020 1 3.2
+1552.8  251.1 10.300 020 1 3.2
+1410.0  999.9 13.900 020 1 3.2
+1335.6  687.0 13.000 020 1 3.2
+1335.8  686.8 12.700 020 1 3.2
+1471.4  262.0 14.200 020 1 3.2
+1479.6  608.3 14.200 020 1 3.2
+1478.1  211.5 12.000 020 1 3.2
+1478.3  211.5 12.000 020 1 3.2
+1552.5   46.4 14.500 020 1 3.2
+2042.4  548.3 10.800 020 1 3.2
+2042.6  548.3 11.000 020 1 3.2
+1448.0  915.7 14.100 020 1 3.2
+1462.3  989.2 13.000 020 1 3.2
+1462.3  989.0 12.700 020 1 3.2
+1316.9  787.3 14.100 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1677.2  106.4 13.100 020 1 3.2
+1677.0  106.4 13.300 020 1 3.2
+1324.2  429.9  9.200 020 1 3.2
+1324.2  429.9  9.000 020 1 3.2
+1462.8  214.3 13.700 020 1 3.2
+1462.8  214.3 14.200 020 1 3.2
+1405.4   95.5 11.700 020 1 3.2
+1405.2   95.5 11.600 020 1 3.2
+1604.8   90.0 11.200 020 1 3.2
+1604.8   90.0 11.300 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1459.8  473.6 13.400 020 1 3.2
+1459.7  473.6 13.800 020 1 3.2
+1438.7   77.8 12.200 020 1 3.2
+1438.6   77.8 12.200 020 1 3.2
+1355.0  114.6 13.000 020 1 3.2
+1354.9  114.6 13.200 020 1 3.2
+1941.4  940.7 13.000 020 1 3.2
+1941.6  940.7 12.900 020 1 3.2
+1994.0  800.8 13.900 020 1 3.2
+1993.8  800.8 14.000 020 1 3.2
+2024.4  907.0 13.700 020 1 3.2
+2024.4  907.0 13.800 020 1 3.2
+2035.7  881.6 13.900 020 1 3.2
+2035.9  881.6 13.800 020 1 3.2
+1994.0  924.2 12.100 020 1 3.2
+1994.0  924.2 12.000 020 1 3.2
Index: /tags/start/Ohana/src/addspphot/include/addstar.h
===================================================================
--- /tags/start/Ohana/src/addspphot/include/addstar.h	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/include/addstar.h	(revision 12606)
@@ -0,0 +1,87 @@
+# include <ohana.h>
+# include <loneos.h>
+# include <signal.h>
+
+typedef struct {
+  double X;
+  double Y;
+  double R;
+  double D;
+  double M, dM;
+  char   dophot;
+  double sky;
+  double fx, fy, df;
+  double Mgal, Map;
+  int found;
+} Stars;
+
+/* global variables set in parameter file */
+char   ImageCat[256];
+char   ImageTemplate[256];
+char   CatTemplate[256];
+char   GSCFILE[256];
+char   CATDIR[256];
+double DEFAULT_RADIUS, NSIGMA, SNLIMIT;
+double ALPHA, ZeroPt;
+double Latitude, SiderealTime;
+int    VERBOSE, FORCE;
+int    XOVERSCAN, YOVERSCAN;
+int    ACCEPT_ASTROM;
+
+PhotCode *thiscode;
+
+char DateKeyword[64];
+char DateMode[64];
+char UTKeyword[64];
+char MJDKeyword[64];
+char JDKeyword[64];
+char ExptimeKeyword[64];
+char AirmassKeyword[64];
+char CCDNumKeyword[64];
+char STKeyword[64];
+char SubpixDatafile[256];
+
+int CalReference;
+int CalColor;
+int CALIBRATE;
+int DUMP_MATCHES;
+int ONLY_IMAGES;
+int SKIP_MISSED;
+
+double get_subpix (double x, double y);
+void load_subpix ();
+double scat_subpix (double x, double y);
+
+int Shutdown ();  
+void TrapSignal (int sig);
+int main (int argc, char **argv);
+int SetSignals ();
+int gcatalog (Catalog *catalog);
+GSCRegion *gregions (Image *image, int *Nregions);
+Image *gimages (FILE *f, Image *image, int *Npimage);
+int edge_check (double *x1, double *y1, double *x2, double *y2);
+double opening_angle (double x1, double y1, double x2, double y2, double x3, double y3);
+void wimage (FILE *f, int dbstate, Image *image, int Nstars);
+Stars *gstars (char *file, int *NSTARS, Image *image);
+void find_matches (GSCRegion *region, Stars *stars, int Nstars, Catalog *catalog, Image *image, Image *pimage, int Nimage);
+int in_image (double r, double d, Image *image);
+void wcatalog (Catalog *catalog);
+void ConfigInit (int *argc, char **argv);
+int hms_to_deg (double *h0, double *h1, double *d0, double *d1, char *string);
+void aregion (GSCRegion *region, FILE *f, double ra, double dec);
+void wimage (FILE *f, int dbstate, Image *image, int Nstars);
+void check_permissions (char *basefile);
+void make_backup (char *filename);
+void help ();
+int args (int argc, char **argv);
+int parse_time (Header *header);
+void uppercase (char *string);
+void mkcatalog (GSCRegion *region, Catalog *catalog);
+double airmass (double ra, double dec, double st, double latitude);
+
+void SaveCalibration (float M, float dM, float Mr, float dMr, float Mc, float A, int N, float ra, float dec, float x, float y);
+void InitCalibration ();
+void FindCalibration (Image *image);
+void fsort (float *X, int N);
+void sort_lists (float *X, float *Y, int *S, int N);
+void fsort2 (float *X, float *Y, int N);
Index: /tags/start/Ohana/src/addspphot/src/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/addspphot/src/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/src/ConfigInit.c	(revision 12606)
@@ -0,0 +1,59 @@
+# include "addstar.h"
+
+void ConfigInit (int *argc, char **argv) {
+
+  char *config, *file;
+  char RadiusWord[80];
+  char PhotCodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (1);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  ScanConfig (config, "RADIUS",                 "%s", 0,  RadiusWord);
+  if (!strcasecmp (RadiusWord, "header")) {
+    DEFAULT_RADIUS = 0;
+  } else {
+    DEFAULT_RADIUS = atof (RadiusWord);
+  }
+  ScanConfig (config, "NSIGMA",                 "%lf", 0, &NSIGMA);
+  ScanConfig (config, "ALPHA",                  "%lf", 0, &ALPHA);
+  ScanConfig (config, "XOVERSCAN",              "%d",  0, &XOVERSCAN);
+  ScanConfig (config, "YOVERSCAN",              "%d",  0, &YOVERSCAN);
+  ScanConfig (config, "IMAGE_CATALOG",          "%s",  0, ImageCat);
+  ScanConfig (config, "IMAGE_CATALOG_TEMPLATE", "%s",  0, ImageTemplate);
+  ScanConfig (config, "CATALOG_TEMPLATE",       "%s",  0, CatTemplate);
+  ScanConfig (config, "GSCFILE",                "%s",  0, GSCFILE);
+  ScanConfig (config, "CATDIR",                 "%s",  0, CATDIR);
+  ScanConfig (config, "MIN_SN_FSTAT",           "%lf", 0, &SNLIMIT);
+  ScanConfig (config, "PHOTCODE_FILE",          "%s",  0, PhotCodeFile);
+
+  ScanConfig (config, "DATE-KEYWORD",           "%s",  0, DateKeyword);
+  ScanConfig (config, "DATE-MODE",              "%s",  0, DateMode);
+  ScanConfig (config, "UT-KEYWORD",             "%s",  0, UTKeyword);
+  ScanConfig (config, "MJD-KEYWORD",            "%s",  0, MJDKeyword);
+  ScanConfig (config, "JD-KEYWORD",             "%s",  0, JDKeyword);
+
+  ScanConfig (config, "EXPTIME-KEYWORD",        "%s",  0, ExptimeKeyword);
+  ScanConfig (config, "AIRMASS-KEYWORD",        "%s",  0, AirmassKeyword);
+  ScanConfig (config, "CCDNUM-KEYWORD",         "%s",  0, CCDNumKeyword);
+
+  ScanConfig (config, "ST-KEYWORD",             "%s",  0, STKeyword);
+  ScanConfig (config, "OBSERVATORY-LATITUDE",   "%lf", 0, &Latitude);
+  ScanConfig (config, "SUBPIX_DATAFILE",        "%s",  0, SubpixDatafile);
+
+  if (!LoadPhotcodes (PhotCodeFile)) {
+    fprintf (stderr, "error loading photcodes\n");
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+
+}
Index: /tags/start/Ohana/src/addspphot/src/addspphot.c
===================================================================
--- /tags/start/Ohana/src/addspphot/src/addspphot.c	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/src/addspphot.c	(revision 12606)
@@ -0,0 +1,222 @@
+# include "addstar.h"
+
+/* these variables are needed by Shutdown */
+static FILE *f = (FILE *) NULL;
+static int Protect = FALSE;
+static int Trapped = FALSE;
+
+/* clean up open / locked files before shutting down */
+int Shutdown () {  
+  int dbstate;
+
+  Protect = TRUE;
+  fclearlockfile (ImageCat, f, LCK_HARD, &dbstate);
+  fprintf (stderr, "ERROR: addstar halted\n");
+  exit (1);
+}
+
+void TrapSignal (int sig) {
+    fprintf (stderr, "trapped signal %d, exiting gracefully\n", sig);
+    if (sig == 11) {
+      fprintf (stderr, "seg fault\n");
+      exit (1);
+    }
+    if (Protect) {
+      Trapped = TRUE;
+      fprintf (stderr, "blocking until protected sections are clear\n");
+      return;
+    }
+    Shutdown ();
+}    
+
+int main (int argc, char **argv) {
+
+  int i, mode, dbstate;
+  int Nstars, Nimage, Nregions, Nmissed;
+  Stars *stars, *gstars();
+  Image image, *pimage, *gimages();
+  GSCRegion *region, *gregions();
+  Catalog catalog;
+  
+  SetSignals ();
+  args (argc, argv);
+
+  load_subpix ();
+
+  stars = gstars (argv[1], &Nstars, &image);
+  if (Nstars == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in data file, skipping\n");
+    fprintf (stderr, "SUCCESS\n");
+    exit (0);
+  }
+
+  /* lock the image catalog */
+  check_permissions (ImageCat);
+  f = fsetlockfile (ImageCat, 3600.0, LCK_HARD, &dbstate);
+  if ((f == (FILE *) NULL) && (dbstate != LCK_EMPTY)) {
+    fprintf (stderr, "ERROR: can't lock image catalog\n");
+    exit (1);
+  }
+  fseek (f, 0, SEEK_SET);
+
+  /* load images */
+  if (dbstate == LCK_EMPTY) {
+    Nimage = 0;
+  } else {
+    pimage = gimages (f, &image, &Nimage);
+  }
+  region = gregions (&image, &Nregions);
+  fprintf (stderr, "region %f %f %f %f\n", region[0].RA[0], region[0].RA[1], region[0].DEC[0], region[0].DEC[1]);
+
+  for (i = 0; i < Nregions; i++) {
+    check_permissions (region[i].filename);
+  }
+
+  if (CALIBRATE) { InitCalibration (); }
+
+  for (i = 0; i < Nregions; i++) {
+    catalog.filename = region[i].filename;  /* don't free region before catalog! */
+    fprintf (stderr, "adding to %s\n", region[i].filename);
+    
+    switch (lock_catalog (&catalog, LCK_XCLD)) {
+    case 0:
+      fprintf (stderr, "ERROR: can't lock file %s\n", catalog.filename);
+      exit (1);
+    case 1:
+      gcatalog (&catalog); /* load from disk */
+      break;
+    case 2:
+      mkcatalog (&region[i], &catalog); /* fills in new header info */
+      break;
+    }
+    find_matches (&region[i], stars, Nstars, &catalog, &image, pimage, Nimage);
+
+    /* protect wcatalog from interrupt signals */
+    Protect = TRUE;
+    if (!DUMP_MATCHES && !ONLY_IMAGES) wcatalog (&catalog);
+    if (Trapped) Shutdown ();
+    Protect = FALSE;
+    unlock_catalog (&catalog);
+  }
+
+  if (CALIBRATE) { FindCalibration (&image); }
+  if (DUMP_MATCHES) Shutdown ();
+
+  for (Nmissed = i = 0; i < Nstars; i++) {
+    if (stars[i].found == -1) {
+      fprintf (stderr, "%d %f %f %f %f\n", i, stars[i].R, stars[i].D, stars[i].M, stars[i].dM);
+      Nmissed ++;
+    }
+  }
+  if (Nmissed) fprintf (stderr, "WARNING: %d stars in image were missed!\n", Nmissed);
+
+  /* protect wimage from interrupt signals */
+  Protect = TRUE;
+  wimage (f, dbstate, &image, Nstars); 
+  if (Trapped) Shutdown ();
+  Protect = FALSE;
+
+  fclearlockfile (ImageCat, f, LCK_HARD, &dbstate);
+
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  chmod (ImageCat, mode);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+
+}
+
+int SetSignals () {
+
+  int i;
+
+  /* disable almost all signal interrupts */
+  for (i = 0; i < 36; i++) {
+    switch (i) {
+      /* can't redirect this signals */
+    case SIGKILL:    /* kill -9: cannot be caught or ignored */
+    case SIGSTOP:    /* SIGSTOP: cannot be caught or ignored */
+      /* ignore these signals */
+    case SIGCHLD:    /* child halted: ignore */
+    case SIGPWR:     /* power failure - why ignore this? */
+    case SIGWINCH:   /* window resized */
+    case SIGCONT:    /* continue - maintain this action */
+    case SIGTSTP:    /* stop signal sent from tty - why ignore? */
+    case SIGURG:     /* socket signal, ignore this */
+      break;
+      
+    default:
+      signal (i, TrapSignal);
+    }
+  }
+  return (TRUE);
+}
+/*
+
+       Signal     Value     Action   Comment
+       -------------------------------------------------------------------------
+       SIGHUP        1        A      Hangup detected on controlling terminal
+                                     or death of controlling process
+       SIGINT        2        A      Interrupt from keyboard
+       SIGQUIT       3        A      Quit from keyboard
+       SIGILL        4        A      Illegal Instruction
+       SIGABRT       6        C      Abort signal from abort(3)
+       SIGFPE        8        C      Floating point exception
+       SIGKILL       9       AEF     Kill signal
+       SIGSEGV      11        C      Invalid memory reference
+       SIGPIPE      13        A      Broken pipe: write to pipe with no readers
+       SIGALRM      14        A      Timer signal from alarm(2)
+       SIGTERM      15        A      Termination signal
+       SIGUSR1   30,10,16     A      User-defined signal 1
+       SIGUSR2   31,12,17     A      User-defined signal 2
+       SIGCHLD   20,17,18     B      Child stopped or terminated
+       SIGCONT   19,18,25            Continue if stopped
+       SIGSTOP   17,19,23    DEF     Stop process
+       SIGTSTP   18,20,24     D      Stop typed at tty
+       SIGTTIN   21,21,26     D      tty input for background process
+       SIGTTOU   22,22,27     D      tty output for background process
+
+       Next various other signals.
+
+       Signal       Value     Action   Comment
+       ---------------------------------------------------------------------
+       SIGTRAP        5         CG     Trace/breakpoint trap
+       SIGIOT         6         CG     IOT trap. A synonym for SIGABRT
+       SIGEMT       7,-,7       G
+       SIGBUS      10,7,10      AG     Bus error
+       SIGSYS      12,-,12      G      Bad argument to routine (SVID)
+       SIGSTKFLT    -,16,-      AG     Stack fault on coprocessor
+       SIGURG      16,23,21     BG     Urgent condition on socket (4.2 BSD)
+       SIGIO       23,29,22     AG     I/O now possible (4.2 BSD)
+       SIGPOLL                  AG     A synonym for SIGIO (System V)
+       SIGCLD       -,-,18      G      A synonym for SIGCHLD
+       SIGXCPU     24,24,30     AG     CPU time limit exceeded (4.2 BSD)
+       SIGXFSZ     25,25,31     AG     File size limit exceeded (4.2 BSD)
+       SIGVTALRM   26,26,28     AG     Virtual alarm clock (4.2 BSD)
+       SIGPROF     27,27,29     AG     Profile alarm clock
+       SIGPWR      29,30,19     AG     Power failure (System V)
+       SIGINFO      29,-,-      G      A synonym for SIGPWR
+       SIGLOST      -,-,-       AG     File lock lost
+       SIGWINCH    28,28,20     BG     Window resize signal (4.3 BSD, Sun)
+       SIGUNUSED    -,31,-      AG     Unused signal
+       (Here - denotes that a signal is absent; there where three values are given, the first one is usually  valid  for  alpha  and
+       sparc,  the  middle  one  for i386 and ppc, the last one for mips. Signal 29 is SIGINFO / SIGPWR on an alpha but SIGLOST on a
+       sparc.)
+
+       The letters in the "Action" column have the following meanings:
+
+       A      Default action is to terminate the process.
+
+       B      Default action is to ignore the signal.
+
+       C      Default action is to dump core.
+
+       D      Default action is to stop the process.
+
+       E      Signal cannot be caught.
+
+       F      Signal cannot be ignored.
+
+       G      Not a POSIX.1 conformant signal.
+
+*/
Index: /tags/start/Ohana/src/addspphot/src/airmass.c
===================================================================
--- /tags/start/Ohana/src/addspphot/src/airmass.c	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/src/airmass.c	(revision 12606)
@@ -0,0 +1,17 @@
+# include "addstar.h"
+
+double airmass (double ra, double dec, double st, double latitude) {
+
+  double hour, cosz, secz;
+
+  /* ra, dec, latitude in dec deg; st in dec hours */
+
+  /* hour : hour angle in degrees */
+  hour = 15.0*st - ra;
+  cosz = sin (RAD_DEG*dec) * sin (RAD_DEG*latitude) + cos (RAD_DEG*dec) * cos (RAD_DEG*hour) * cos (RAD_DEG*latitude);
+  
+  secz = 1.0 / cosz;
+
+  return (secz);
+
+}
Index: /tags/start/Ohana/src/addspphot/src/aregion.c
===================================================================
--- /tags/start/Ohana/src/addspphot/src/aregion.c	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/src/aregion.c	(revision 12606)
@@ -0,0 +1,174 @@
+# include "addstar.h"
+
+double BigDecBounds[] = {0.0, 7.5, 15.0, 22.5, 30.0, 37.5, 45.0, 
+			 52.5, 60.0, 67.5, 75.0, 82.5, 90.0,
+			 0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, 
+			 -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+char *DecSections[] = {"N0000", "N0730", "N1500", "N2230", "N3000", "N3730", "N4500", 
+		       "N5230", "N6000", "N6730", "N7500", "N8230", "weirdness", 
+		       "S0000", "S0730", "S1500", "S2230", "S3000", "S3730", "S4500", 
+		       "S5230", "S6000", "S6730", "S7500", "S8230", "weirdness"};
+
+char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			"n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			"s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			"s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+char *disk[] = {"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", 
+		"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "weirdness", 
+		"disk 1", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", 
+		"disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "weirdness"};
+
+int NBigRASections [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3, 48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3};
+
+int NDecLines[] = {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 24, 
+                   0, 597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48};
+
+# define DEBUG 1
+
+/* find region file which contains ra, dec */
+void aregion (GSCRegion *region, FILE *f, double ra, double dec) {
+  
+  char buffer[28800], temp[50], file[256];
+  double RA0, RA1, DEC0, DEC1;
+  int i, NBigDec, NLINES, done;
+  
+  while (ra < 0) { ra += 360.0; }
+  while (ra >= 360.0) { ra -= 360.0; }
+
+  if (dec >= 86.25) {
+    sprintf (file, "%s/n8230/pole.cpt", CATDIR);
+    region[0].DEC[0] = 86.25;
+    region[0].DEC[1] = 93.75;
+    region[0].RA[0] =  0.0;
+    region[0].RA[1] =  360.0;
+    strcpy (region[0].filename, file);
+    return;
+  }
+    
+  NBigDec = -1;
+  for (i = 0; i < 12; i++) {
+    if ((dec >= BigDecBounds[i]) && (dec < BigDecBounds[i+1])) {
+      NBigDec = i;
+      break;
+    }
+  }
+  if (NBigDec < 0) {
+    for (i = 13; i < 24; i++) {
+      if ((dec < BigDecBounds[i]) && (dec >= BigDecBounds[i+1])) {
+	NBigDec = i;
+	break;
+      }
+    }
+  }
+  if (NBigDec < 0) {
+    fprintf (stderr, "dec out of range: %f\n", dec);
+  }
+    
+  NLINES = 0;
+  for (i = 0; i < NBigDec; i++) {
+    NLINES += NDecLines[i];
+  }
+  fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+      
+  done = FALSE;
+  Fread (buffer, 1, 48*NDecLines[NBigDec], f, "char");
+  for (i = 0; !done && (i < NDecLines[NBigDec]); i++) {
+    strncpy (temp, &buffer[i*48], 48);
+    temp[49] = 0;
+    hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+    if (RA1 < RA0) RA1 += 360.0;
+    if ((dec >= 0) && (dec >= DEC0) && (dec < DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+    if ((dec < 0) && (dec < DEC0) && (dec >= DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+  }
+
+  if (!done) {
+    fprintf (stderr, "ERROR in search: %f %f\n", ra, dec);
+    exit (1);
+  }
+  temp[5] = 0;
+  sprintf (file, "%s/%s/%s.cpt", CATDIR, Dec2Sections[NBigDec], &temp[1]);
+  if (DEC0 < DEC1) {
+    region[0].DEC[0] = DEC0;
+    region[0].DEC[1] = DEC1;
+  } else {
+    region[0].DEC[0] = DEC1;
+    region[0].DEC[1] = DEC0;
+  }     
+  region[0].RA[0] = RA0;
+  region[0].RA[1] = RA1;
+  strcpy (region[0].filename, file);
+  return;
+}
+
+
+/**********/
+int hms_to_deg (h0, h1, d0, d1, string) 
+     char *string;
+     double *h0, *h1, *d0, *d1;
+{
+  
+  int flag_d0, flag_d1, flag_h0, flag_h1;
+  double tmp;
+  
+  *d0 = *h0 = *d1 = *h1 = 0;
+
+  flag_h0 = dparse (h0, 1, string);
+  flag_h1 = dparse (h1, 4, string);
+  flag_d0 = dparse (d0, 7, string);
+  flag_d1 = dparse (d1, 9, string);
+  *h0 *= flag_h0;
+  *h1 *= flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  dparse (&tmp, 2, string);
+  *h0 += tmp/60.0;
+  dparse (&tmp, 3, string);
+  *h0 += tmp/3600.0;
+  
+  dparse (&tmp, 5, string);
+  *h1 += tmp/60.0;
+  dparse (&tmp, 6, string);
+  *h1 += tmp/3600.0;
+  
+  dparse (&tmp, 8, string);
+  *d0 += tmp/60.0;
+
+  dparse (&tmp, 10, string);
+  *d1 += tmp/60.0;
+
+  *h0 *= 15*flag_h0;
+  *h1 *= 15*flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  return (TRUE);
+}
+
+
+/*
+      if (buffer[i*48 + 19] == ' ') continue;
+      strncpy (temp, &buffer[i*48 + 19], 20);       temp[20] = 0;
+      hms_to_deg (&RA,  &DEC, temp, ' ', 3);
+
+
+  dBigRA = 360.0 / (int)(0.5 + 48*cos(3.1415927*0.5*(BigDecBounds[NBigDec] + BigDecBounds[NBigDec + 1])/180.0));
+
+  NBigRA = ra / dBigRA;
+
+  NBig = NBigRA;
+  for (i = 0; (i < 12) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+  for (i = 13; (i < 24) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+
+
+  fprintf (stderr, "%d %d %d %d %f %f -> %f %f %f\n", NBigDec, NBigRA, NBigRASections[NBigDec], NBig, ra, dec, BigDecBounds[NBigDec], BigDecBounds[NBigDec + 1], dBigRA);
+*/
Index: /tags/start/Ohana/src/addspphot/src/args.c
===================================================================
--- /tags/start/Ohana/src/addspphot/src/args.c	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/src/args.c	(revision 12606)
@@ -0,0 +1,113 @@
+# include "addstar.h"
+# define NARGS 2  /* minimum is: addstar (filename) */
+
+void help () {
+
+  fprintf (stderr, "USAGE: addstar (filename)\n");
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -v (verbose mode)\n");
+  fprintf (stderr, "  -p (photcode) - define the photcode\n");
+  fprintf (stderr, "\n"); 
+  exit (2);
+
+}
+
+int args (int argc, char **argv) {
+  
+  int N;
+
+  /* check for help request */
+  if (get_argument (argc, argv, "-help") ||
+      get_argument (argc, argv, "-h")) {
+    help ();
+  }
+
+  /* configuration info */
+  ConfigInit (&argc, argv);
+
+  /* check for command line options */
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  FORCE = FALSE;
+  if ((N = get_argument (argc, argv, "-force"))) {
+    FORCE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  ACCEPT_ASTROM = FALSE;
+  if ((N = get_argument (argc, argv, "-accept"))) {
+    ACCEPT_ASTROM = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  thiscode = NULL;
+  if ((N = get_argument (argc, argv, "-p"))) {
+    remove_argument (N, &argc, argv);
+    thiscode = GetPhotcodebyName (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  ONLY_IMAGES = FALSE;
+  if ((N = get_argument (argc, argv, "-image"))) {
+    ONLY_IMAGES = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  DUMP_MATCHES = FALSE;
+  if ((N = get_argument (argc, argv, "-dump"))) {
+    DUMP_MATCHES = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  SKIP_MISSED = FALSE;
+  if ((N = get_argument (argc, argv, "-missed"))) {
+    SKIP_MISSED = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  CALIBRATE = FALSE;
+  if ((N = get_argument (argc, argv, "-cal"))) {
+    CALIBRATE = TRUE;
+    remove_argument (N, &argc, argv);
+    CalReference = GetPhotcodeCodebyName (argv[N]);
+    if (!CalReference) {
+      fprintf (stderr, "ERROR: photcode %s not found in photcode table\n", argv[N]);
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    CalColor = GetPhotcodeCodebyName (argv[N]);
+    if (!CalColor) {
+      fprintf (stderr, "ERROR: photcode %s not found in photcode table\n", argv[N]);
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+  }
+  if (DUMP_MATCHES && !CALIBRATE) {
+    fprintf (stderr, "-dump only valid -with -cal\n");
+    exit (1);
+  }
+
+  /*
+  Subpix.C0 = 0.06;
+  Subpix.C1 = -0.00015;
+  Subpix.P0 = 0.55;
+  if ((N = get_argument (argc, argv, "-subpix"))) {
+    remove_argument (N, &argc, argv);
+    Subpix.C0 = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    Subpix.C1 = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    Subpix.P0 = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  */
+  return (TRUE);
+}
+
+
+/***
+
+ it is silly to define CalReference and CalColor on the command line
+ these are *already* define in the photcode table.  
+ CalColor1 = thiscode[0].c1
+ CalColor2 = thiscode[0].c2
+ CalReference = thiscode[0].equiv
+
+***/
Index: /tags/start/Ohana/src/addspphot/src/calibrate.c
===================================================================
--- /tags/start/Ohana/src/addspphot/src/calibrate.c	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/src/calibrate.c	(revision 12606)
@@ -0,0 +1,166 @@
+# include "addstar.h"
+
+static int Ncal, NCAL;
+static float *Mobs, *dMobs, *Mref, *dMref, *Cref, *Airm;
+static float *RA, *DEC, *X, *Y;
+int *Nstar;
+
+void InitCalibration () {
+
+    fprintf (stderr, "calibrating the image...  %d\n", CalReference);
+    Ncal = 0;
+    NCAL = 1000;
+    ALLOCATE (Mobs,  float,  NCAL);
+    ALLOCATE (dMobs, float, NCAL);
+    ALLOCATE (Mref,  float,  NCAL);
+    ALLOCATE (dMref,  float,  NCAL);
+    ALLOCATE (Cref,  float,  NCAL);
+    ALLOCATE (Airm,  float,  NCAL);
+    ALLOCATE (Nstar, int, NCAL);
+    ALLOCATE (RA, float, NCAL);
+    ALLOCATE (DEC, float, NCAL);
+    ALLOCATE (X, float, NCAL);
+    ALLOCATE (Y, float, NCAL);
+}
+  
+void SaveCalibration (float M, float dM, float Mr, float dMr, float Mc, float A, int N, float ra, float dec, float x, float y) {
+
+  Mobs[Ncal] = M;
+  dMobs[Ncal] = dM;
+  Mref[Ncal] = Mr;
+  dMref[Ncal] = dMr;
+  Cref[Ncal] = Mc;
+  Airm[Ncal] = A;
+  Nstar[Ncal] = N;
+
+  RA[Ncal] = ra;
+  DEC[Ncal] = dec;
+  X[Ncal] = x;
+  Y[Ncal] = y;
+  Ncal ++;
+
+  if (Ncal == NCAL) {
+    NCAL += 1000;
+    REALLOCATE (dMobs, float, NCAL);
+    REALLOCATE (Mobs,  float, NCAL);
+    REALLOCATE (Mref,  float, NCAL);
+    REALLOCATE (dMref,  float, NCAL);
+    REALLOCATE (Cref,  float, NCAL);
+    REALLOCATE (Airm,  float, NCAL);
+    REALLOCATE (Nstar, int,   NCAL);
+    REALLOCATE (RA, float, NCAL);
+    REALLOCATE (DEC, float, NCAL);
+    REALLOCATE (X, float, NCAL);
+    REALLOCATE (Y, float, NCAL);
+  }
+}
+
+void FindCalibration (Image *image) {
+
+  int i, MaxN, *Nlist, Nkeep;
+  float N, M1, M2, Klam, Clam, Xlam, Mabs, *Dmag, *dDmag;
+  float dMo, dMr, Mw, Dmed, W1, W2, NSigma;
+  
+  /* reject multiple matched-stars */
+  /* find maximum value of Nstar[] */
+  MaxN = -1;
+  for (i = 0; i < Ncal; i++) {
+    MaxN = MAX (Nstar[i], MaxN);
+  }
+  if (MaxN == -1) {
+    fprintf (stderr, "no clean stars\n");
+    image[0].Mcal = 10000;
+    image[0].dMcal = 10000;
+    return;
+  }
+  /* create a hash array from Nstar[] entries */
+  ALLOCATE (Nlist, int, MAX (1, MaxN + 1));
+  bzero (Nlist, MAX (0, MaxN*sizeof(int)));
+  for (i = 0; i < Ncal; i++) {
+    Nlist[Nstar[i]] ++;
+  }
+  
+  /* accumulate delta mags */
+  ALLOCATE (Dmag, float, Ncal);
+  ALLOCATE (dDmag, float, Ncal);
+  Nkeep = 0;
+  Klam = thiscode[0].K;
+  Clam = thiscode[0].C;
+  Xlam = thiscode[0].X[0];
+  for (i = 0; i < Ncal; i++) {
+    /* if this entry has too many (or two few?) matches, skip it */
+    if (Nlist[Nstar[i]] != 1) continue;
+    Mabs = 0.001*(Mobs[i] + Klam*(Airm[i] - 1000) + Clam + Xlam*(Mref[i] - Cref[i])) - ZeroPt;
+
+    /* note: subpix correction is applied in gstars */
+
+    if (DUMP_MATCHES) 
+      fprintf (stdout, "%d  %6.3f %6.3f %6.3f  %10.6f %10.6f  %7.2f %7.2f  %7.2f  %7.2f\n", 
+	       i, Mabs, 0.001*Mref[i], 0.001*Cref[i], RA[i], DEC[i], X[i], Y[i], Airm[i], 0.001*dMobs[i]);
+
+    /* skip stars brighter than 8.0 */
+    if (Mabs > 9.0) continue;
+    if (Mabs < 5.0) continue;
+    
+    dMr = MAX (0.005, 0.001*dMref[i]);
+    dMo = MAX (0.005, 0.001*dMobs[i]);
+      
+    Dmag[Nkeep]  = (Mabs - 0.001*Mref[i]);
+    dDmag[Nkeep] = (dMr*dMr + dMo*dMo);
+    Nkeep ++;
+  }
+
+  if (Nkeep < 5) {
+    fprintf (stderr, "too few stars\n");
+    image[0].Mcal = 10000;
+    image[0].dMcal = 10000;
+    return;
+  }
+  fsort2 (Dmag, dDmag, Nkeep);
+
+  /* take sort list of Dmag, find median */
+  Dmed = Dmag[(int)(0.5*Nkeep)];
+
+  /* exclude points with abs(Dmag - Dmed) / dDmag > 2.5 */
+
+  /* find lo (Dmed - 0.1) + hi (Dmed + 0.1) 
+  lo = -1; hi = -1;
+  for (i = 0; (lo == -1) && (i < Nkeep); i++) { if (Dmed - Dmag[i] < 0.1) lo = i; }
+  for (i = Nkeep - 1; (hi == -1) && (i >= 0); i--) { if (Dmag[i] - Dmed < 0.1) hi = i; }
+  if (lo == -1) lo = 0;
+  if (hi == -1) hi = Nkeep - 1;
+  */
+
+  /* accumulate delta mags (25% - 75% of clipped range) */
+  W1 = 0.0;
+  W2 = 0.0;
+  M1 = 0.0;
+  M2 = 0.0;
+  N  = 0.0;
+  for (i = 0; i < Nkeep; i++) {
+    NSigma = fabs (Dmag[i] - Dmed) / sqrt (dDmag[i]);
+    if (NSigma > 2.5) continue;
+    W1 += Dmag[i] / dDmag[i];
+    W2 += 1 / dDmag[i];
+    M1 += Dmag[i];
+    M2 += SQ (Dmag[i]);
+    N  += 1.0; 
+  }
+
+  if (N > 1) {
+    M1 = M1 / N;
+    M2 = sqrt (fabs(M2/N - M1*M1));
+    Mw = W1 / W2;
+    fprintf (stderr, "N: %.0f, mean: %f, wt mean: %f, stdev: %f, precision: %f\n", N, M1, Mw, M2, M2 / sqrt (N));
+    image[0].Mcal = 1000 * M1;
+    image[0].dMcal = 1000 * M2 / sqrt (N);
+    image[0].Mxxxx = N;
+  } else {
+    fprintf (stderr, "too few stars\n");
+    image[0].Mcal = 10000;
+    image[0].dMcal = 10000;
+    image[0].Mxxxx = 0;
+  }
+}
+
+
Index: /tags/start/Ohana/src/addspphot/src/check_permissions.c
===================================================================
--- /tags/start/Ohana/src/addspphot/src/check_permissions.c	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/src/check_permissions.c	(revision 12606)
@@ -0,0 +1,90 @@
+# include "addstar.h"
+
+void check_permissions (char *basefile) {
+  
+  char *c, dir[256], filename[256];
+  struct stat filestat;
+  uid_t uid;
+  gid_t gid;
+  int status, cmode;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to write to directory */
+  sprintf (filename, "%s", basefile);
+  c = strrchr (filename, '/');
+  if (c == (char *) NULL) {
+    strcpy (dir, ".");
+  } else {
+    *c = 0;
+    strcpy (dir, filename);
+  }
+  status = stat (dir, &filestat);
+  if (status == -1) {
+    fprintf (stderr, "directory %s does not exist, creating...\n", dir);
+    cmode = S_IRWXU | S_IRWXG | S_IRWXO;
+    status = mkdir (dir, cmode);
+    if (status == -1) {
+      fprintf (stderr, "ERROR: can't create %s\n", dir);
+      exit (1);
+    }
+  } 
+  status = stat (dir, &filestat);
+  if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRWXU)) ||
+      ((gid == filestat.st_gid) && (filestat.st_mode & S_IRWXG)) || 
+      (filestat.st_mode & S_IRWXO)) {
+  } else {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (1);
+  }
+  
+  /* check permission to write to file */
+  sprintf (filename, "%s", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (1);
+    }
+  }
+  
+  /* check permission to write to backup file */
+  sprintf (filename, "%s~", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (1);
+    }
+  }
+  
+}
+
+/* uses cp only */
+void make_backup (char *filename) {
+
+  int status, cmode;
+  struct stat filestat;
+  char line [256];
+
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, make backup copy */
+    sprintf (line, "cp %s %s~", filename, filename);
+    status = system (line);
+    if (status) {
+      fprintf (stderr, "ERROR: unable to create %s~, exiting\n", filename);
+      exit (1);
+    }
+    cmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    sprintf (line, "%s~", filename);
+    chmod (line, cmode);
+  }
+  
+}
Index: /tags/start/Ohana/src/addspphot/src/find_matches.c
===================================================================
--- /tags/start/Ohana/src/addspphot/src/find_matches.c	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/src/find_matches.c	(revision 12606)
@@ -0,0 +1,519 @@
+# include "addstar.h"
+
+# define IN_CATALOG(R,D) ( \
+((D) >= region[0].DEC[0]) && ((D) < region[0].DEC[1]) && \
+((R) >= region[0].RA[0])  && ((R) < region[0].RA[1]))
+
+void find_matches (GSCRegion *region, Stars *stars, int Nstars, Catalog *catalog, Image *image, Image *pimage, int Nimage) {
+
+  double secz;
+  int i, j, k, n, m, N, first_j, found, found0, found1;
+  double X, Y, RADIUS, RADIUS2;
+  float *X1, *Y1, *X2, *Y2, CalM, CalC, dCalM, *Xs, *Ys;
+  float dX, dY, dR;
+  int *N1, *N2,  *next, *next_miss, last, last_miss;
+  int Nave, NAVE, Nmeas, NMEAS, Nmiss, NMISS, Nmatch;
+  Measure *tmpmeasure;
+  Missing *tmpmissing;
+  Coords tcoords;
+  int Nsecfilt, Nsec, MTIME;
+  short int Mrel, *Mval;
+
+  /** allocate local arrays **/
+  ALLOCATE (X1, float, Nstars);
+  ALLOCATE (Y1, float, Nstars);
+  ALLOCATE (N1, int, Nstars);
+
+  /** allocate local arrays **/
+
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  Nave = catalog[0].Naverage;
+  NAVE = Nave + 1000;
+  ALLOCATE (X2, float, NAVE);
+  ALLOCATE (Y2, float, NAVE);
+  ALLOCATE (N2, int, NAVE);
+  ALLOCATE (Xs, float, NAVE);
+  ALLOCATE (Ys, float, NAVE);
+  ALLOCATE (catalog[0].found, int, NAVE);
+  REALLOCATE (catalog[0].average, Average, NAVE);
+  REALLOCATE (catalog[0].secfilt, SecFilt, NAVE*catalog[0].Nsecfilt);
+  /* for secfilt j and star i, secfilt[i*Nsecfilt+j] */
+
+  Nmatch = 0;
+  Nmeas = catalog[0].Nmeasure;
+  NMEAS = Nmeas + 1000;
+  ALLOCATE (next, int, NMEAS);
+  REALLOCATE (catalog[0].measure, Measure, NMEAS);
+  
+  Nmiss = catalog[0].Nmissing;
+  NMISS = Nmiss + 1000;
+  ALLOCATE (next_miss, int, NMISS);
+  REALLOCATE (catalog[0].missing, Missing, NMISS);
+  
+  /* check on photcode */
+  Nsec = GetPhotcodeNsec (thiscode[0].code);
+
+  /* project onto rectilinear grid with 1 arcsec pixels, sort by X */
+  /* reference for coords is this image */
+  tcoords = image[0].coords;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1 = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2 = tcoords.pc2_1 = 0.0;
+  strcpy (tcoords.ctype, "RA---TAN");
+  
+  for (i = 0; i < Nstars; i++) {
+    fRD_to_XY (&X1[i], &Y1[i], stars[i].R, stars[i].D, &tcoords);
+    N1[i] = i;
+  }
+  if (Nstars > 1) sort_lists (X1, Y1, N1, Nstars);
+  
+  for (i = 0; i < Nave; i++) {
+    fRD_to_XY (&Xs[i], &Ys[i], catalog[0].average[i].R, catalog[0].average[i].D, &image[0].coords);
+    fRD_to_XY (&X2[i], &Y2[i], catalog[0].average[i].R, catalog[0].average[i].D, &tcoords);
+    N2[i] = i;
+    catalog[0].found[N2[i]] = -1;
+  }
+  if (Nave > 1) sort_lists (X2, Y2, N2, Nave);
+
+  /* set up pointers for linked list of measurements */
+  for (i = 0; i < Nmeas - 1; i++) {
+    next[i] = i+1;
+  }
+  next[i] = -1;
+  last = i;
+
+  for (i = 0; i < Nmiss - 1; i++) {
+    next_miss[i] = i+1;
+  }
+  next_miss[i] = -1;
+  last_miss = i;
+
+  /* choose a radius for matches */
+  /* 0.02 corrects cerror to arcsec from storage units */
+  if (DEFAULT_RADIUS == 0) {
+    RADIUS = NSIGMA * 0.02 * image[0].cerror;
+  } else {
+    RADIUS = DEFAULT_RADIUS;
+  }
+  RADIUS2 = RADIUS*RADIUS;
+  /* correct instrumental mags for exposure time */
+  if (image[0].exptime > 0) {
+    MTIME = 2500*log10(image[0].exptime);
+  } else {
+    MTIME = 0;
+  }
+
+  /** find matched stars **/
+  for (i = j = 0; (i < Nstars) && (j < Nave); ) {
+    
+    dX = X1[i] - X2[j];
+    /* fprintf (stderr, "%f   %f %f  %f %f    %f %f  %f %f\n", dX, X1[i], Y1[i], X2[j], Y2[j], stars[i].R, stars[i].D, catalog[0].average[j].R, catalog[0].average[j].D); */
+
+    if (dX <= -2*RADIUS) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*RADIUS) {
+      j++;
+      continue;
+    }
+
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    for (; (dX > -2*RADIUS) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < RADIUS2) {  /* new measurement of this star */
+	Nmatch ++;
+	/** insert star in measurement list */
+	n = N2[j];
+	N = N1[i];
+	m = catalog[0].average[n].offset;  /* first measurement of this star */
+	for (k = 0; k < catalog[0].average[n].Nm - 1; k++)
+	  m = next[m];
+	next[Nmeas] = next[m];
+	next[m] = Nmeas;
+	if (next[Nmeas] == -1) { /* last just was moved */
+	  last = Nmeas;
+	}
+	
+	/* calculate accurate per-star airmass */
+	secz = 1000 * airmass (stars[N].R, stars[N].D, SiderealTime, Latitude);
+	if (CALIBRATE) {
+	  found = FALSE;
+	  found0 = FALSE;
+	  found1 = FALSE;
+	  m = catalog[0].average[n].offset;  /* first measurement of this star */
+	  for (k = 0; !found && (k < catalog[0].average[n].Nm); k++) {
+	    if (catalog[0].measure[m+k].source == CalReference) { found0 = TRUE; CalM = catalog[0].measure[m+k].M; dCalM = catalog[0].measure[m+k].dM; }
+	    if (catalog[0].measure[m+k].source == CalColor)     { found1 = TRUE; CalC = catalog[0].measure[m+k].M; }
+	    if (found0 && found1) {
+	      found = TRUE;
+	      SaveCalibration (MIN (NO_MAG, 1000*stars[N].M + MTIME), 
+			       MIN (255, stars[N].dM),
+			       CalM, dCalM, CalC,
+			       secz, N, stars[N].R, stars[N].D, Xs[n], Ys[n]);
+	    }
+	  }
+	}
+	      
+	/** add measurements for this star **/
+	catalog[0].measure[Nmeas].dR     = 360000.0*(catalog[0].average[n].R - stars[N].R);
+	catalog[0].measure[Nmeas].dD     = 360000.0*(catalog[0].average[n].D - stars[N].D);
+	catalog[0].measure[Nmeas].M      = MIN (NO_MAG, 1000*stars[N].M + MTIME);
+	catalog[0].measure[Nmeas].Mcal   = image[0].Mcal;
+	catalog[0].measure[Nmeas].dM     = MIN (255, stars[N].dM);  /* error in input files stored in thousandths of mag */
+	catalog[0].measure[Nmeas].t      = image[0].tzero + 1e-4*stars[N].Y*image[0].trate;  /* trate is in 0.1 msec / row */
+	catalog[0].measure[Nmeas].averef = n;
+	catalog[0].measure[Nmeas].source = image[0].source;  /* photometry source */
+	catalog[0].measure[Nmeas].dophot = stars[N].dophot;  
+	catalog[0].measure[Nmeas].flags  = 0;
+	catalog[0].measure[Nmeas].dt     = MTIME;
+
+	catalog[0].measure[Nmeas].Mgal     = MIN (NO_MAG, 1000*stars[N].Mgal + MTIME);
+	catalog[0].measure[Nmeas].airmass  = secz;
+	catalog[0].measure[Nmeas].FWx      = MIN (NO_MAG, 100*stars[N].fx);
+	catalog[0].measure[Nmeas].fwy      = MIN (255, 100*(stars[N].fy / stars[N].fx));
+	catalog[0].measure[Nmeas].theta    = MIN (255, (255/360)*stars[N].df);
+	/* refers to same number as first measurement */
+	
+	/* check for entries in the secfilt lists */
+	Mrel = catalog[0].measure[Nmeas].M + catalog[0].measure[Nmeas].airmass * thiscode[0].K;
+	Mval = (Nsec == -1) ? &catalog[0].average[n].M : &catalog[0].secfilt[n*Nsecfilt+Nsec].M;
+	if (*Mval == NO_MAG) *Mval = Mrel;
+
+	/*** handle multiple stars */
+	/* this image star matches more than one catalog star */
+	if (stars[N].found > -1) {
+	  catalog[0].measure[stars[N].found].flags |= BLEND_IMAGE;
+	  catalog[0].measure[Nmeas].flags |= BLEND_IMAGE;
+	} 
+	if (stars[N].found == -2) { /* this image star matches a catalog star on a neighboring catalog */
+	  catalog[0].measure[Nmeas].flags |= BLEND_IMAGE_NEIGHBOR;
+	} 
+	if (stars[N].found == -1) { /* this image star matches only this catalog star */
+	  stars[N].found = Nmeas;  /* save first match, in case coincidences are found */
+	}
+	/* this catalog star matches more than one image star */
+	if (catalog[0].found[n] > -1) {
+	  catalog[0].measure[catalog[0].found[n]].flags |= BLEND_CATALOG;
+	  catalog[0].measure[Nmeas].flags |= BLEND_CATALOG;
+	} else {
+	  catalog[0].found[n] = Nmeas;
+	}
+
+	catalog[0].average[n].Nm ++;
+	Nmeas ++;
+	if (Nmeas == NMEAS) {
+	  NMEAS = Nmeas + 1000;
+	  REALLOCATE (next, int, NMEAS);
+	  REALLOCATE (catalog[0].measure, Measure, NMEAS);
+	}
+
+	/* update values of Ro, Do */
+	if (catalog[0].average[n].Nm > 2) {
+	  double R, D, r, d, r2, d2, Npt;
+	  Npt = r = d = r2 = d2 = 0;
+	  m = catalog[0].average[n].offset;  /* first measurement of this star */
+	  for (k = 0; k < catalog[0].average[n].Nm; k++) {
+	    if (catalog[0].measure[m].t == 0) {
+	      m = next[m];
+	      continue;
+	    }
+	    R = catalog[0].measure[m].dR;
+	    D = catalog[0].measure[m].dD;
+	    r += R;
+	    d += D;
+	    r2 += R*R;
+	    d2 += D*D;
+	    m = next[m];
+	    Npt += 1.0;
+	  }
+	  if (Npt > 2) {
+	    r = r / Npt;  /* these are corrections in 1/100 arcsec to RA and DEC */
+	    d = d / Npt;
+	    R = r2 / Npt - r*r;
+	    D = d2 / Npt - d*d;
+	    /* Xp is scatter in position in hundredths of arcsec */
+	    catalog[0].average[n].Xp = sqrt (D + R / SQ(cos(catalog[0].average[n].D*RAD_DEG)));
+	    m = catalog[0].average[n].offset;  /* first measurement of this star */
+	    for (k = 0; k < catalog[0].average[n].Nm; k++) {
+	      catalog[0].measure[m].dR = catalog[0].measure[m].dR - r;
+	      catalog[0].measure[m].dD = catalog[0].measure[m].dD - d;
+	      m = next[m];
+	    }
+	    catalog[0].average[n].R = catalog[0].average[n].R - r / 360000.0;
+	    catalog[0].average[n].D = catalog[0].average[n].D - d / 360000.0;
+	  }
+	}
+      }
+    }
+    j = first_j;
+    i++;
+  }
+
+  /* add reference for undetected catalog stars */
+  for (j = 0; (j < Nave) && !SKIP_MISSED; j++) {
+    n = N2[j];
+    if (catalog[0].found[n] < 0) { 
+      /* should the catalog star be on this image? project into image coords */
+      if (in_image (catalog[0].average[n].R, catalog[0].average[n].D, image)) {
+	/* find last missing meas */
+	if (catalog[0].average[n].Nn < 1) { /* no previous missing obs */
+	  catalog[0].average[n].missing = Nmiss;
+	  next_miss[last_miss] = Nmiss;
+	  next_miss[Nmiss] = -1;
+	  last_miss = Nmiss;
+	} else {
+	  m = catalog[0].average[n].missing;
+	  for (k = 0; k < catalog[0].average[n].Nn - 1; k++)
+	    m = next_miss[m];
+	  next_miss[Nmiss] = next_miss[m];
+	  next_miss[m] = Nmiss;
+	  if (next_miss[Nmiss] == -1) { /* last just was moved */
+	    last_miss = Nmiss;
+	  }
+	}
+	RD_to_XY (&X, &Y, catalog[0].average[n].R, catalog[0].average[n].D, &image[0].coords);	  
+	catalog[0].missing[Nmiss].t  = image[0].tzero + 1e-4*Y*image[0].trate;  /* trate is in 0.1 msec / row */
+	catalog[0].average[n].Nn ++;
+	Nmiss ++;
+	if (Nmiss == NMISS) {
+	  NMISS = Nmiss + 1000;
+	  REALLOCATE (next_miss, int, NMISS);
+	  REALLOCATE (catalog[0].missing, Missing, NMISS);
+	}
+      }
+    }
+  }
+
+  /* incorporate unmatched image stars, if this star is in field of this catalog */
+  for (i = 0; i < Nstars; i++) {
+    N = N1[i];
+    if ((stars[N].found < 0) && IN_CATALOG (stars[N].R, stars[N].D)) {
+      catalog[0].average[Nave].R = stars[N].R;
+      catalog[0].average[Nave].D = stars[N].D;
+      catalog[0].average[Nave].M = NO_MAG;
+      for (j = 0; j < Nsecfilt; j++) {
+	catalog[0].secfilt[Nave*Nsecfilt+j].M  = NO_MAG;
+	catalog[0].secfilt[Nave*Nsecfilt+j].Xm = NO_MAG;
+      }
+      
+      secz = 1000 * airmass (stars[N].R, stars[N].D, SiderealTime, Latitude);
+
+      catalog[0].average[Nave].Nm        = 1;
+      catalog[0].average[Nave].Nn        = 0;
+      catalog[0].average[Nave].Xp        = NO_MAG;
+      catalog[0].average[Nave].Xm        = NO_MAG;
+      catalog[0].average[Nave].dM        = NO_MAG;
+      catalog[0].average[Nave].offset    = Nmeas;
+      catalog[0].average[Nave].missing   = -1;
+      catalog[0].average[Nave].code      = 0;
+
+      catalog[0].measure[Nmeas].dR       = 0.0;
+      catalog[0].measure[Nmeas].dD       = 0.0;
+      catalog[0].measure[Nmeas].M        = MIN (NO_MAG, 1000.0*stars[N].M + MTIME);
+      catalog[0].measure[Nmeas].Mcal     = image[0].Mcal;
+      catalog[0].measure[Nmeas].dM       = MIN (255, stars[N].dM);
+      catalog[0].measure[Nmeas].t        = image[0].tzero + 1e-4*stars[N].Y*image[0].trate; /* trate is in 0.1 msec / row */
+      catalog[0].measure[Nmeas].averef   = Nave;
+      catalog[0].measure[Nmeas].source   = image[0].source;  /* photometry source */
+      catalog[0].measure[Nmeas].dophot   = stars[N].dophot;  
+      catalog[0].measure[Nmeas].flags    = 0;
+      catalog[0].measure[Nmeas].dt       = MTIME;
+
+      catalog[0].measure[Nmeas].Mgal     = MIN (NO_MAG, 1000.0*stars[N].Mgal + MTIME);
+      catalog[0].measure[Nmeas].airmass  = secz;
+      catalog[0].measure[Nmeas].FWx      = MIN (0x7fff, 100*stars[N].fx);
+      catalog[0].measure[Nmeas].fwy      = MIN (255, 100*(stars[N].fy / stars[N].fx));
+      catalog[0].measure[Nmeas].theta    = MIN (255, (255/360)*stars[N].df);
+
+      Mrel = catalog[0].measure[Nmeas].M + catalog[0].measure[Nmeas].airmass * thiscode[0].K;
+      Mval = (Nsec == -1) ? &catalog[0].average[Nave].M : &catalog[0].secfilt[Nave*Nsecfilt+Nsec].M;
+      if (*Mval == NO_MAG) *Mval = Mrel;
+
+      stars[N].found = Nmeas;
+      next[last] = Nmeas;
+      next[Nmeas] = -1;
+      last = Nmeas;
+      Nmeas ++;
+      if (Nmeas == NMEAS) {
+	NMEAS = Nmeas + 1000;
+	REALLOCATE (next, int, NMEAS);
+	REALLOCATE (catalog[0].measure, Measure, NMEAS);
+      }
+
+      /** now add references from all previous non-detection observations of this spot on the sky */
+      for (j = 0; (j < Nimage) && !SKIP_MISSED; j++) {
+	if (in_image (catalog[0].average[Nave].R, catalog[0].average[Nave].D, &pimage[j])) {
+	  if (catalog[0].average[Nave].Nn < 1) {
+	    catalog[0].average[Nave].missing = Nmiss;
+	  }
+	  next_miss[last_miss] = Nmiss;
+	  next_miss[Nmiss] = -1;
+	  last_miss = Nmiss;
+	  /* this can now be done exactly */
+	  RD_to_XY (&X, &Y, catalog[0].average[Nave].R, catalog[0].average[Nave].D, &pimage[j].coords);	  
+	  catalog[0].missing[Nmiss].t  = pimage[j].tzero + 1e-4*Y*pimage[j].trate;  /* rough guess at time */
+	  catalog[0].average[Nave].Nn ++;
+	  Nmiss ++;
+	  if (Nmiss == NMISS) {
+	    NMISS = Nmiss + 1000;
+	    REALLOCATE (next_miss, int, NMISS);
+	    REALLOCATE (catalog[0].missing, Missing, NMISS);
+	  }
+  
+	}
+      }
+      Nave ++;
+      if (Nave == NAVE) {
+	NAVE = Nave + 1000;
+	REALLOCATE (catalog[0].average, Average, NAVE);
+	REALLOCATE (catalog[0].secfilt, SecFilt, NAVE*catalog[0].Nsecfilt);
+      }
+    }
+  }
+      
+  free (catalog[0].found);
+  REALLOCATE (catalog[0].average, Average, Nave);
+  REALLOCATE (catalog[0].measure, Measure, Nmeas);
+
+  /* fix order of Measure (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmeasure, Measure, Nmeas);
+  for (i = 0; i < Nave; i++) {
+    n = catalog[0].average[i].offset;
+    catalog[0].average[i].offset = N;
+    for (k = 0; k < catalog[0].average[i].Nm; k++, N++) {
+      tmpmeasure[N] = catalog[0].measure[n]; 
+      tmpmeasure[N].averef = i;
+      n = next[n];
+    }
+  }
+  free (catalog[0].measure);
+  catalog[0].measure = tmpmeasure;
+    
+  /* fix order of Missing (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmissing, Missing, Nmiss);
+  for (i = 0; i < Nave; i++) {
+    if (catalog[0].average[i].Nn > 0) {
+      n = catalog[0].average[i].missing;
+      catalog[0].average[i].missing = N;
+      for (k = 0; k < catalog[0].average[i].Nn; k++, N++) {
+	tmpmissing[N] = catalog[0].missing[n]; 
+	n = next_miss[n];
+      }
+    }
+  }
+  free (catalog[0].missing);
+  catalog[0].missing = tmpmissing;
+
+  /* note stars which have been found in this catalog */
+  for (i = 0; i < Nstars; i++) {
+    if (stars[i].found > -1) {
+      stars[i].found = -2;
+    }
+  }
+
+  catalog[0].Naverage = Nave;
+  catalog[0].Nmeasure = Nmeas;
+  catalog[0].Nmissing = Nmiss;
+  if (VERBOSE) fprintf (stderr, "Nstars, Nave, Nmeas, Nmiss: %d %d %d %d, (%d matches)\n", Nstars, Nave, Nmeas, Nmiss, Nmatch);
+}
+
+int in_image (double r, double d, Image *image) {
+
+  double X, Y;
+
+  RD_to_XY (&X, &Y, r, d, &image[0].coords);
+  if (((X) >= 0) && ((X) < image[0].NX) && ((Y) >= 0) && ((Y) < image[0].NY))
+    return (TRUE);
+  else 
+    return (FALSE);
+
+}
+
+/* 
+   notes:
+
+     for finding if a catalog star is in an image or an image star is in the catalog:
+       
+       catalogs have boundaries defined by RA and DEC, but they may curve in projection
+       images have boundaries which are lines in pixels coords, but curve in RA and DEC
+
+       catalog[0].found[Ncat] but stars[Nstar].found
+
+       */
+
+     
+# ifdef OLDJUNKHERE
+
+ 
+  /* fix measurement list order */
+  for (i = 0; i < Nmeas - 1; i++) {
+    if (next[i] != i + 1) {
+      n0 = next[i];
+      n1 = next[i+1];
+      n2 = next[n0];
+      t = i;
+      while ((t != -1) && (next[t] != i+1))
+	t = next[t];
+      if ((t == -1) || (n2 == i+1)) {
+	t = n2;
+      }
+      next[i] = i+1;
+      next[i+1] = n2;
+      next[n0] = n1;
+      next[t] = n0;
+      tmpmeasure = catalog[0].measure[n0];
+      catalog[0].measure[n0] = catalog[0].measure[i+1];
+      catalog[0].measure[i+1] = tmpmeasure;
+    }
+  }
+ 
+  /* fix offset references */
+  n = (0x00ffffff & catalog[0].measure[0].average);
+  catalog[0].average[n].offset = 0;
+  for (i = 1; i < Nmeas; i++) {
+    if (n != (0x00ffffff & catalog[0].measure[i].average)) {
+      n = (0x00ffffff & catalog[0].measure[i].average);
+      catalog[0].average[n].offset = i;
+    }
+  }
+
+  /* fix missing list order */
+  for (i = 0; i < Nmiss - 1; i++) {
+    if (next_miss[i] != i + 1) {
+      n0 = next_miss[i];
+      n1 = next_miss[i+1];
+      n2 = next_miss[n0];
+      t = i;
+      while ((t != -1) && (next_miss[t] != i+1))
+	t = next_miss[t];
+      if ((t == -1) || (n2 == i+1)) {
+	t = n2;
+      }
+      next_miss[i] = i+1;
+      next_miss[i+1] = n2;
+      next_miss[n0] = n1;
+      next_miss[t] = n0;
+      tmpmissing = catalog[0].missing[n0];
+      catalog[0].missing[n0] = catalog[0].missing[i+1];
+      catalog[0].missing[i+1] = tmpmissing;
+    }
+  }
+ 
+  /* fix offset references */
+  n = (0x00ffffff & catalog[0].measure[0].average);
+  catalog[0].average[n].offset = 0;
+  for (i = 1; i < Nmeas; i++) {
+    if (n != (0x00ffffff & catalog[0].measure[i].average)) {
+      n = (0x00ffffff & catalog[0].measure[i].average);
+      catalog[0].average[n].offset = i;
+    }
+  }
+
+# endif
Index: /tags/start/Ohana/src/addspphot/src/gcatalog.c
===================================================================
--- /tags/start/Ohana/src/addspphot/src/gcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/src/gcatalog.c	(revision 12606)
@@ -0,0 +1,45 @@
+# include "addstar.h"
+
+int gcatalog (Catalog *catalog) {
+  
+  int Nsecfilt;
+  char mode;
+
+  /* read catalog header */
+  mode = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+  if (!load_catalog (catalog, mode, VERBOSE)) {
+    fprintf (stderr, "ERROR: failure loading catalog\n");
+    exit (1);
+  }
+
+  /* check Nsecfile value, update if needed */
+  Nsecfilt = GetPhotcodeNsecfilt ();
+  if (catalog[0].Nsecfilt < Nsecfilt) {
+
+    int i, j, Nextra, in, out;
+    SecFilt *insec, *outsec;
+
+    Nextra = Nsecfilt - catalog[0].Nsecfilt;
+    insec = catalog[0].secfilt;
+    ALLOCATE (outsec, SecFilt, catalog[0].Naverage * Nsecfilt);
+    for (in = out = i = 0; i < catalog[0].Naverage; i++) {
+      for (j = 0; j < catalog[0].Nsecfilt; j++, in++, out++) {
+	outsec[out].M = insec[in].M;
+	outsec[out].Xm = insec[in].Xm;
+      }
+      for (j = 0; j < Nextra; j++, out++) {
+	outsec[out].M = NO_MAG;
+	outsec[out].Xm = NO_MAG;
+      }
+    }
+    free (catalog[0].secfilt);
+    catalog[0].secfilt = outsec;
+    catalog[0].Nsecfilt = Nsecfilt;
+  }
+
+  if (catalog[0].Nsecfilt > Nsecfilt) {
+    fprintf (stderr, "ERROR: can't reduce number of secondary filters\n");
+    exit (1);
+  }
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/addspphot/src/gimages.c
===================================================================
--- /tags/start/Ohana/src/addspphot/src/gimages.c	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/src/gimages.c	(revision 12606)
@@ -0,0 +1,180 @@
+# include "addstar.h"
+
+Image *gimages (FILE *f, Image *image, int *Npimage) {
+  
+  int i, j, k, Nimage, addtolist, size;
+  int NTIMAGE, Ntimage, ntimage;
+  int NPIMAGE, npimage;
+  Image *timage, *pimage;
+  Coords tcoords;
+  Header header;
+  double r, d;
+  double Xi[5], Yi[5], Xo[5], Yo[5];  /* image and original corners */
+  double zeropt;
+  struct stat filestatus;
+  
+  fseek (f, 0, SEEK_SET);
+
+  /* read header */
+  if (!fits_load_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read image catalog %s\n", ImageCat);
+    Shutdown ();
+  }
+
+  fits_scan (&header, "ZERO_PT", "%lf", 1, &zeropt);
+  if (fabs (ZeroPt - zeropt) > 1e-4) {
+    fprintf (stderr, "zero point in image (%f:%s) inconsistent with zero point in catalog (%f)\n",
+	     ZeroPt, image[0].name, zeropt);
+    Shutdown ();
+  }
+
+  /* project onto rectilinear grid with 1 arcsec pixels */
+  /* we keep the original crpix1,2 and crref1,2 */
+  tcoords = image[0].coords;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1 = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2 = tcoords.pc2_1 = 0.0;
+  strcpy (tcoords.ctype, "RA---TAN");
+
+  /* define original corners */
+  Xo[0] = 0;           Yo[0] = 0;
+  Xo[1] = image[0].NX; Yo[1] = 0;
+  Xo[2] = image[0].NX; Yo[2] = image[0].NY;
+  Xo[3] = 0;           Yo[3] = image[0].NY;
+  Xo[4] = 0;           Yo[4] = 0;  /* so we can make a loop easily */
+  for (j = 0; j < 5; j++) {
+    XY_to_RD (&r, &d, Xo[j], Yo[j], &image[0].coords);
+    RD_to_XY (&Xo[j], &Yo[j], r, d, &tcoords);
+  }
+  
+  /* advance to data segment */ 
+  fseek (f, header.size, SEEK_SET); 
+
+  Nimage = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+  /* check that file size makes sense */
+  if (stat (ImageCat, &filestatus) == -1) {
+    fprintf (stderr, "failed to get status of image catalog\n");
+    Shutdown ();
+  }
+  size = Nimage*sizeof(Image) + header.size;
+  if (size != filestatus.st_size) {
+    int Ndata;
+
+    Ndata = (filestatus.st_size - header.size) / sizeof (Image);
+    fprintf (stderr, "image catalog has inconsistent size\n");
+    fprintf (stderr, "header: %d images, data: %d images\n", Nimage, Ndata);
+    if (!FORCE) Shutdown ();
+    
+    Nimage = MIN (Nimage, Ndata);
+    fprintf (stderr, "using %d images\n", Nimage);
+  } 
+
+  NTIMAGE = 100;
+  ALLOCATE (timage, Image, NTIMAGE);
+
+  npimage = 0;
+  NPIMAGE = 20;
+  ALLOCATE (pimage, Image, NPIMAGE);
+
+  for (Ntimage = 0; Ntimage < Nimage; Ntimage += ntimage) {
+    ntimage = Fread (timage, sizeof(Image), NTIMAGE, f, "image");
+    for (i = 0; i < ntimage; i++) {
+      addtolist = FALSE;
+      /* define image corners */
+      Xi[0] = 0;            Yi[0] = 0;
+      Xi[1] = timage[i].NX; Yi[1] = 0;
+      Xi[2] = timage[i].NX; Yi[2] = timage[i].NY;
+      Xi[3] = 0;            Yi[3] = timage[i].NY;
+      Xi[4] = 0;            Yi[4] = 0;  /* so we can make a loop easily */
+      /* transform to tcoords */
+      for (j = 0; j < 5; j++) {
+	XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+	RD_to_XY (&Xi[j], &Yi[j], r, d, &tcoords);
+      }
+      /* check if any edges cross */
+      for (j = 0; (j < 4) && !addtolist; j++) {
+	for (k = 0; (k < 4) && !addtolist; k++) {
+	  addtolist |= edge_check (&Xi[j], &Yi[j], &Xo[k], &Yo[k]);
+	}
+      }
+      if (addtolist) {
+	pimage[npimage] = timage[i];
+	npimage ++;
+	if (npimage == NPIMAGE) {
+	  NPIMAGE += 20;
+	  REALLOCATE (pimage, Image, NPIMAGE);
+	}
+      }
+    }
+
+    if (ntimage == 0) {
+      fprintf (stderr, "ERROR: expected %d images, only found %d\n", Nimage, Ntimage);
+      Shutdown ();
+    }
+  }
+
+  if (VERBOSE) fprintf (stderr, "found %d overlapping images\n", npimage);
+
+  *Npimage = npimage;
+  return (pimage);
+
+}
+  
+int edge_check (x1, y1, x2, y2)
+double *x1, *y1, *x2, *y2;
+{
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+double opening_angle (x1, y1, x2, y2, x3, y3)
+double x1, y1, x2, y2, x3, y3;
+{
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
+
Index: /tags/start/Ohana/src/addspphot/src/gregions.c
===================================================================
--- /tags/start/Ohana/src/addspphot/src/gregions.c	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/src/gregions.c	(revision 12606)
@@ -0,0 +1,56 @@
+# include "addstar.h"
+
+GSCRegion *gregions (image, Nregions)
+Image *image;
+int *Nregions;
+{
+  
+  GSCRegion *region;
+  FILE *f;
+  double x, y;
+  double dec, ra;
+  int i, j, done, nregion, NREGION;
+  
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find GSC region file %s\n", GSCFILE);
+    exit (1);
+  }
+  
+  /* find regions at image corners */
+  NREGION = 10;
+  ALLOCATE (region, GSCRegion, NREGION);
+  nregion = 0;
+
+  /* look for new regions on grid across image */ 
+  for (x = 0.0; x <= 1.0; x+=0.1) {
+    for (y = 0.0; y <= 1.0; y+=0.1) {
+      XY_to_RD (&ra, &dec, image[0].NX*(1.1*x - 0.05), image[0].NY*(1.1*y - 0.05), &image[0].coords);
+      aregion (&region[nregion], f, ra, dec);
+      done = FALSE;
+      for (j = 0; (j < nregion) && !done; j++) {
+	if (!strcmp (region[nregion].filename, region[j].filename)) {
+	  nregion --;
+	  done = TRUE;
+	}
+      }
+      nregion ++;
+      if (nregion == NREGION) {
+	NREGION += 10;
+	REALLOCATE (region, GSCRegion, NREGION);
+      }
+    }
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "found %d region files:\n", nregion);
+    for (i = 0; i < nregion; i++) {
+      fprintf (stderr, "  %d %s\n", i, region[i].filename);
+    }
+  }
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (region);
+  
+}
Index: /tags/start/Ohana/src/addspphot/src/gstars.c
===================================================================
--- /tags/start/Ohana/src/addspphot/src/gstars.c	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/src/gstars.c	(revision 12606)
@@ -0,0 +1,295 @@
+# include "addstar.h"
+# define D_NSTARS 1000
+# define BYTES_STAR 66
+# define BLOCK 1000
+#include <sys/time.h>
+#include <time.h>
+
+Stars *gstars (char *file, int *NSTARS, Image *image) {
+
+  FILE *f;
+  Header header;
+  int j, N, Ninstar;
+  int nbytes, Nbytes;
+  Stars *stars;
+  char *buffer, *c, *c2, photcode[64];
+  double tmp, dMs;
+  int done, doneread, Nskip, Nextra, itmp;
+  int hour, min;
+  double sec;
+  char line[80];
+
+  if (!fits_read_header (file, &header)) {
+    fprintf (stderr, "ERROR: can't read header for %s\n", file);
+    exit (1);
+  }
+
+  /* open file */
+  f = fopen (file, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't read data from %s\n", file);
+    exit (1);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* find image rootname */
+  c = strrchr (file, 0x2f);
+  if (c == (char *) NULL) {
+    strcpy (image[0].name, file);
+  } else { 
+    strcpy (image[0].name, (c+1));
+  }
+
+  /* get astrometry information */
+  if (!GetCoords (&image[0].coords, &header)) {
+    fprintf (stderr, "ERROR: no astrometric solution in header\n");
+    exit (1);
+  }
+  while (image[0].coords.crval1 < 0) image[0].coords.crval1 += 360.0;
+  while (image[0].coords.crval1 > 360.0) image[0].coords.crval1 -= 360.0;
+  itmp = 0;
+  fits_scan (&header, "NASTRO",   "%d", 1, &itmp);
+  if ((itmp == 0) && !ACCEPT_ASTROM) {
+    fprintf (stderr, "ERROR: bad astrometric solution in header\n");
+    exit (1);
+  }
+
+  /* get ST */
+  fits_scan (&header, STKeyword, "%s", 1, line);
+  /* remove ':' characters */
+  for (c = strchr (line, ':'); c != (char *) NULL; c = strchr (line, ':')) { *c = ' '; }
+  sscanf (line, "%d %d %lf", &hour, &min, &sec);
+  SiderealTime = hour + min/60.0 + sec/3600.0;
+
+  /* CERROR in data file is in arcsec */
+  if (!fits_scan (&header, "CERROR",   "%lf", 1, &tmp)) tmp = 1.0;
+  image[0].cerror = tmp * 50.0;
+  fits_scan (&header, "NAXIS1",   "%hd", 1, &image[0].NX); 
+  fits_scan (&header, "NAXIS2",   "%hd", 1, &image[0].NY);
+ 
+  /* get photcode from header */
+  if (thiscode == NULL) {
+    fits_scan (&header, "PHOTCODE", "%s", 1, photcode);
+    thiscode = GetPhotcodebyName (photcode);
+  }
+  if (thiscode == NULL) {
+    fprintf (stderr, "ERROR: photcode %s not found in photcode table\n", photcode);
+    exit (1);
+  }
+  image[0].source = thiscode[0].code;
+
+  image[0].NX -= XOVERSCAN;
+  image[0].NY -= YOVERSCAN;
+  fits_scan (&header, ExptimeKeyword,  "%lf", 1, &tmp);
+  image[0].exptime = tmp;
+  
+  tmp = 0;
+  /* fits_scan (&header, "APMIFIT",  "%lf", 1, &tmp); */
+  image[0].apmifit = tmp * 1000.0;
+
+  tmp = 0;
+  /* fits_scan (&header, "dAPMIFIT", "%lf", 1, &tmp); */
+  image[0].dapmifit = tmp * 1000.0;
+
+  tmp = 0;
+  fits_scan (&header, "FLIMIT",   "%lf", 1, &tmp);
+  image[0].detection_limit = tmp * 10.0;
+
+  tmp = 0;
+  fits_scan (&header, "FSATUR",   "%lf", 1, &tmp);
+  image[0].saturation_limit = tmp * 10.0;
+
+  tmp = 0;
+  fits_scan (&header, "FWHM_X",   "%lf", 1, &tmp);
+  image[0].fwhm_x = tmp * 25.0 * image[0].coords.cdelt1 * 3600.0;
+
+  tmp = 0;
+  fits_scan (&header, "FWHM_Y",   "%lf", 1, &tmp);
+  image[0].fwhm_y = tmp * 25.0 * image[0].coords.cdelt1 * 3600.0;
+
+  if (!fits_scan (&header, "TZERO",   "%d",  1, &image[0].tzero)) {
+    image[0].tzero = parse_time (&header);
+  }
+
+  tmp = 0;
+  fits_scan (&header, "TRATE",   "%lf", 1, &tmp);
+  image[0].trate = 10000 * tmp;
+
+  tmp = 0;
+  fits_scan (&header, AirmassKeyword, "%lf", 1, &tmp);
+  image[0].secz = MIN (NO_MAG, 1000*tmp);
+
+  if (!fits_scan (&header, CCDNumKeyword, "%d", 1, &itmp)) {
+    image[0].ccdnum = 0xff;
+  } else {
+    image[0].ccdnum = itmp;
+  }
+
+  fits_scan (&header, "ZERO_PT", "%lf", 1, &ZeroPt);
+
+  /* secz is in units milli-airmass */
+  image[0].Mcal = 0.0;
+  image[0].Xm   = NO_MAG;
+  image[0].code = 0;
+  bzero (image[0].dummy, sizeof(image[0].dummy));
+
+  /* find expected number of stars */
+  fits_scan (&header, "NSTARS", "%d", 1, &image[0].nstar);
+  if (image[0].nstar == 0) {
+    fprintf (stderr, "ERROR: can't get NSTARS from header\n");
+    exit (1);
+  }
+  ALLOCATE (stars, Stars, image[0].nstar);
+
+  /* temporary:  get sky background from Flips data */
+  {
+    char *p;
+    int sky;
+    
+    fits_scan (&header, "HISTORY", "%S", 10, line);
+    p = strstr (line, "|I=");
+    if (p != (char *) NULL) {
+      p += 3;
+      sky = atoi (p);
+    }
+    image[0].Myyyy = MIN (sky - 0x8000, 0xffff);
+  }
+
+  /* load in stars by blocks of 1000 */
+  N = 0;
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR) + 1);
+  buffer[BLOCK*BYTES_STAR] = 0;
+  Nextra = 0;
+  doneread = FALSE;
+  while (!doneread) {
+    Nbytes = BYTES_STAR * BLOCK - Nextra;
+    nbytes = Fread (&buffer[Nextra], 1, Nbytes, f, "char");
+    if (nbytes == 0) {
+      doneread = TRUE;
+      continue;
+    }
+    nbytes += Nextra;
+    /* check line-by-line integrity */
+    c = buffer;
+    done = FALSE;
+    while ((c < buffer + nbytes) && (!done)) { 
+      for (c2 = c; *c2 == '\n'; c2++);
+      if (c2 > c) { /* extra return chars */
+	memmove (c, c2, (int)(buffer + nbytes - c2));
+	Nskip = c2 - c;
+	nbytes -= Nskip;
+	bzero (buffer + nbytes, Nskip);
+	if (VERBOSE) fprintf (stderr, "deleted %d extra return chars\n", Nskip);
+      }
+      c2 = strchr (c, '\n');
+      if (c2 == (char *) NULL) {
+	done = TRUE;	
+	continue;
+      }
+      c2++;
+      if ((c2 - c) != BYTES_STAR) { /* bad line, delete it */
+	memmove (c, c2, (int)(buffer + nbytes - c2));
+	Nskip = c2 - c;
+	nbytes -= Nskip;
+	bzero (buffer + nbytes, Nskip);
+	if (VERBOSE) fprintf (stderr, "deleted line, %d extra chars\n", Nskip);
+      } else {
+	c = c2;
+      }
+    }
+    Ninstar = nbytes / BYTES_STAR;
+    Nextra = nbytes % BYTES_STAR;
+    for (j = 0; j < Ninstar; j++, N++) {
+      dparse (&stars[N].X,  1, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].Y,  2, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].M,  3, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].dM, 4, &buffer[j*BYTES_STAR]);
+      dparse (&tmp,         5, &buffer[j*BYTES_STAR]);
+      stars[N].dophot = tmp;
+      dparse (&stars[N].Mgal, 7, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].Map,  8, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].fx,   9, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].fy,  10, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].df,  11, &buffer[j*BYTES_STAR]);
+
+      XY_to_RD (&stars[N].R, &stars[N].D, stars[N].X, stars[N].Y, &image[0].coords);
+      while (stars[N].R < 0.0) stars[N].R += 360.0;
+      while (stars[N].R >= 360.0) stars[N].R -= 360.0;
+      stars[N].found = -1;
+
+      dMs = get_subpix (stars[N].X, stars[N].Y);
+      stars[N].M    -= dMs;
+      stars[N].Mgal -= dMs;
+      stars[N].Map  -= dMs;
+      dMs = 1000.0*scat_subpix (stars[N].X, stars[N].Y);
+      stars[N].dM = hypot (stars[N].dM, dMs);
+    }
+  }
+
+  image[0].nstar = N;
+  REALLOCATE (stars, Stars, image[0].nstar);
+  if (VERBOSE) fprintf (stderr, "read %d stars from target file\n", image[0].nstar);
+  *NSTARS = image[0].nstar;
+
+  return (stars);
+}
+
+
+
+
+# if (0)
+  /* left over fraction of a block */
+  nbytes = Fread (buffer, 1, (Nbytes % (BLOCK*BYTES_STAR)), f, "char");
+  if (nbytes != (Nbytes % (BLOCK*BYTES_STAR))) {
+    fprintf (stderr, "ERROR: failed to read in stars (2)\n");
+    exit (1);
+  }
+  /* check line-by-line integrity */
+  Nnew = 0;
+  c = buffer;
+  done = FALSE;
+  while ((c < buffer + nbytes) && (!done)) { 
+    for (c2 = c; *c2 == '\n'; c2++);
+    if (c2 > c) { /* extra return chars */
+      memmove (c, c2, (int)(buffer + nbytes - c2));
+      Nnew += c2 - c;
+      fprintf (stderr, "deleting %d extra return chars\n", (int)(c2-c));
+    }
+    c2 = strchr (c, '\n');
+    if (c2 == (char *) NULL) {
+      if (Nnew > 0) {
+	nnew = Fread (&buffer[nbytes-Nnew], 1, Nnew, f, "char");
+	if (nnew != Nnew) {
+	  fprintf (stderr, "ERROR: failed to read in stars (1)\n");
+	  exit (1);
+	}
+      } else {
+	done = TRUE;	
+      }
+      continue;
+    }
+    c2++;
+    if ((c2 - c) != BYTES_STAR) {
+      /* this is a bad line, delete it, adjust data in buffer, 
+	 and be ready to read the rest of the last line */
+      memmove (c, c2, (int)(buffer + nbytes - c2));
+      Nnew += c2 - c;
+      fprintf (stderr, "deleting bad line with %d chars\n", (int)(c2-c));
+    } else {
+      c = c2;
+    }
+  }
+  for (j = 0; j < nbytes / BYTES_STAR; j++, nstar++, N++) {
+    dparse (&stars[N].X, 1, &buffer[j*BYTES_STAR]);
+    dparse (&stars[N].Y, 2, &buffer[j*BYTES_STAR]);
+    dparse (&stars[N].M, 3, &buffer[j*BYTES_STAR]);
+    dparse (&stars[N].dM, 4, &buffer[j*BYTES_STAR]);
+    XY_to_RD (&stars[N].R, &stars[N].D, stars[N].X, stars[N].Y, &image[0].coords);
+    while (stars[N].R < 0.0) stars[N].R += 360.0;
+    while (stars[N].R >= 360.0) stars[N].R -= 360.0;
+    dparse (&tmp, 5, &buffer[j*BYTES_STAR]);
+    stars[N].dophot = tmp;
+    stars[N].found = -1;
+  }
+
+# endif
Index: /tags/start/Ohana/src/addspphot/src/load_subpix.c
===================================================================
--- /tags/start/Ohana/src/addspphot/src/load_subpix.c	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/src/load_subpix.c	(revision 12606)
@@ -0,0 +1,53 @@
+# include "addstar.h"
+
+typedef struct {
+  double Amp;
+  double Phase;
+  double dM;
+} SubPixFix;
+
+static int Nsubpix;
+static SubPixFix *Subpix;
+
+void load_subpix () {
+
+  int i;
+  FILE *f;
+
+  Nsubpix = 40;
+  ALLOCATE (Subpix, SubPixFix, Nsubpix);
+
+  f = fopen (SubpixDatafile, "r");
+  if (f == (FILE *) NULL) { 
+    fprintf (stderr, "can't load subpix datafile %s\n", SubpixDatafile);
+    Shutdown ();
+  }
+  for (i = 0; i < Nsubpix; i++) {
+    fscanf (f, "%*s %*s %lf %lf %lf %*s\n", 
+	    &Subpix[i].Amp, &Subpix[i].Phase, &Subpix[i].dM);
+  }
+  fclose (f);
+
+}
+
+double get_subpix (double x, double y) {
+
+  int bin;
+  double dy, dM;
+
+  dy = y - (int)(y);
+  bin = 5 * (int)(x/100) + (int)(y/100);
+  dM = Subpix[bin].Amp*sin(2*3.14159*dy + Subpix[bin].Phase);
+  return (dM);
+}
+
+double scat_subpix (double x, double y) {
+
+  int bin;
+  double dy, dM;
+
+  dy = y - (int)(y);
+  bin = 5 * (int)(x/100) + (int)(y/100);
+  dM = Subpix[bin].dM;
+  return (dM);
+}
Index: /tags/start/Ohana/src/addspphot/src/mkcatalog.c
===================================================================
--- /tags/start/Ohana/src/addspphot/src/mkcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/src/mkcatalog.c	(revision 12606)
@@ -0,0 +1,38 @@
+# include "addstar.h"
+# include <time.h>
+
+void mkcatalog (GSCRegion *region, Catalog *catalog) {
+  
+  char filename[64], line[64];
+  struct tm *local;
+  struct timeval now;
+
+  if (VERBOSE) fprintf (stderr, "new catalog file: %s\n", region[0].filename);
+  if (!fits_read_header (CatTemplate, &catalog[0].header)) {
+    fprintf (stderr, "ERROR: can't find template header %s\n", CatTemplate);
+    exit (1);
+  }
+  
+  /* assign header values for RA, DEC, DATE, etc */
+  fits_modify (&catalog[0].header, "RA0", "%lf", 1, region[0].RA[0]);
+  fits_modify (&catalog[0].header, "DEC0", "%lf", 1, region[0].DEC[0]);
+  fits_modify (&catalog[0].header, "RA1", "%lf", 1, region[0].RA[1]);
+  fits_modify (&catalog[0].header, "DEC1", "%lf", 1, region[0].DEC[1]);
+  gettimeofday (&now, NULL);
+  local = localtime (&now.tv_sec);
+  sprintf (line, "%02d/%02d/%02d", local[0].tm_year, local[0].tm_mon + 1, local[0].tm_mday); 
+  fits_modify (&catalog[0].header, "DATE", "%s", 1, line);
+  strcpy (filename, CatTemplate);
+  ALLOCATE (catalog[0].average, Average, 1);
+  ALLOCATE (catalog[0].measure, Measure, 1);
+  ALLOCATE (catalog[0].missing, Missing, 1);
+  catalog[0].Naverage = catalog[0].Nmeasure = catalog[0].Nmissing = 0;
+
+  /* setup secondary filters to match photcodes */
+  ALLOCATE (catalog[0].secfilt, SecFilt, 1);
+  catalog[0].Nsecfilt = GetPhotcodeNsecfilt ();
+
+  /* Nsecfilt is number of filters.  Number of entries in array is
+     Nsecfilt * Naverage.  At this point, N entries == 0 */
+
+}
Index: /tags/start/Ohana/src/addspphot/src/parse_time.c
===================================================================
--- /tags/start/Ohana/src/addspphot/src/parse_time.c	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/src/parse_time.c	(revision 12606)
@@ -0,0 +1,126 @@
+# include "addstar.h"
+
+int parse_time (Header *header) {
+
+  double jd;
+  int Ny, Nf, mode;
+  int Nsec, hour, min, sec, year, month, day;
+  char *py, *pm, *pd, *c;
+  char line[256];
+
+  /* we want to find JD or MJD to get Nsec (seconds since 01/01/1970) */
+
+  /* try JD first */
+  if (strcasecmp (JDKeyword, "NONE")) {
+    uppercase (JDKeyword);
+    fits_scan (header, JDKeyword, "%lf", 1, &jd);
+    Nsec = (jd - 2440587.5)*86400;
+    return (Nsec);
+  }
+
+  /* try MJD next */
+  if (strcasecmp (MJDKeyword, "NONE")) {
+    uppercase (MJDKeyword);
+    fits_scan (header, MJDKeyword, "%lf", 1, &jd);
+    Nsec = (jd - 40587.0)*86400;
+    return (Nsec);
+  }
+    
+  /* get UT and DATE */
+  uppercase (UTKeyword);
+  fits_scan (header, UTKeyword, "%s", 1, line);
+  /* remove ':' characters */
+  for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
+  sscanf (line, "%d %d %d", &hour, &min, &sec);
+
+  /* parse mode line */
+  uppercase (DateMode);
+  for (Ny = 0, c = strchr (DateMode, 'Y'); c != (char ) NULL; c = strchr (c + 1, 'Y'), Ny++);
+  if ((Ny != 2) && (Ny != 4)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  py = strchr (DateMode, 'Y');
+  pm = strchr (DateMode, 'M');
+  pd = strchr (DateMode, 'D');
+  if ((py == (char *) NULL) || (pm == (char *) NULL) || (pd == (char *) NULL)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  if ((py > pm) && (py < pd)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  if ((py > pd) && (py < pm)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  mode = 0;
+  if ((py < pm) && (pm < pd)) { mode = 1; }  /* yyyy-mm-dd */
+  if ((py < pm) && (pm > pd)) { mode = 2; }  /* yyyy-dd-mm */
+  if ((py > pm) && (pm < pd)) { mode = 3; }  /* mm-dd-yyyy */
+  if ((py > pm) && (pm > pd)) { mode = 4; }  /* dd-mm-yyyy */
+  if (!mode) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+
+  /* parse date entry */
+  uppercase (DateKeyword);
+  fits_scan (header, DateKeyword, "%s",  1, line);
+  /* remove possible separators: ':', '/' '.', '-' */
+  for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
+  for (c = strchr (line, 0x2f); c != (char *) NULL; c = strchr (line, 0x2f)) { *c = ' '; }
+  for (c = strchr (line, 0x2e); c != (char *) NULL; c = strchr (line, 0x2e)) { *c = ' '; }
+  for (c = strchr (line, 0x2d); c != (char *) NULL; c = strchr (line, 0x2d)) { *c = ' '; }
+
+  switch (mode) {
+  case 1:
+    Nf = sscanf (line, "%d %d %d", &year, &month, &day);
+    break;
+  case 2:
+    Nf = sscanf (line, "%d %d %d", &year, &day, &month);
+    break;
+  case 3:
+    Nf = sscanf (line, "%d %d %d", &month, &day, &year);
+    break;
+  case 4:
+    Nf = sscanf (line, "%d %d %d", &day, &month, &year);
+    break;
+  }
+  if (Nf != 3) {
+    fprintf (stderr, "error in date entry (%s) or DATE-MODE format (%s)\n", line, DateMode);
+    exit (1);
+  }
+
+  if (year > 1000) {
+    if (Ny == 2) {
+      fprintf (stderr, "warning: mode line claims 2 digit year, but 4 digit year found\n");
+    }
+  } else {
+    if (Ny == 4) {
+      fprintf (stderr, "warning: mode line claims 4 digit year, but 2 digit year found\n");
+    }
+    if (year < 50) year += 100;
+    year += 1900;
+  }    
+
+  /* convert yy.mm.dd hh.mm.ss to Nsec since 1970 (jd = 2440587.5) */
+  /* note that in this section, tm_mon has range 1-12, unlike for gmtime () */
+  jd = day - 32075 + (int)(1461*(year + 4800 + (int)(((month)-14)/12))/4)
+    + (int)(367*((month) - 2 - (int)(((month) - 14)/12)*12)/12)
+    - (int)(3*(int)((year + 4900 + (int)(((month) - 14)/12))/100)/4) - 0.5;
+  /* jd is the julian day of the whole day only not the time */
+  Nsec = (jd - 2440587.5)*86400 + 3600.0*hour + min*60.0 + sec;
+  
+  return (Nsec);
+
+}
+
+void uppercase (char *string) {
+
+  int i;
+    
+  for (i = 0; i < strlen (string); i++) string[i] = toupper (string[i]);
+
+}
Index: /tags/start/Ohana/src/addspphot/src/sort_lists.c
===================================================================
--- /tags/start/Ohana/src/addspphot/src/sort_lists.c	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/src/sort_lists.c	(revision 12606)
@@ -0,0 +1,120 @@
+
+void sort_lists (float *X, float *Y, int *S, int N) {
+
+  int l,j,ir,i;
+  double tX, tY, tS;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    S[i] = tS;
+  }
+}
+
+void fsort (float *X, int N) {
+
+  int l,j,ir,i;
+  float tX;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+  }
+}
+
+void fsort2 (float *X, float *Y, int N) {
+
+  int l,j,ir,i;
+  float tX, tY;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+    }
+    else {
+      tX = X[ir];
+      tY = Y[ir];
+      X[ir] = X[0];
+      Y[ir] = Y[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+  }
+}
Index: /tags/start/Ohana/src/addspphot/src/wcatalog.c
===================================================================
--- /tags/start/Ohana/src/addspphot/src/wcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/src/wcatalog.c	(revision 12606)
@@ -0,0 +1,35 @@
+# include "addstar.h"
+
+void wcatalog (Catalog *catalog) {
+  
+  /* we'll leave these for now, but they are LONEOS specific */
+  fits_modify (&catalog[0].header, "MARKSTAR", "%t", 1, FALSE);
+  fits_modify (&catalog[0].header, "ADDUSNO", "%t", 1, FALSE);
+  fits_modify (&catalog[0].header, "MARKROCK", "%t", 1, FALSE);
+
+  if (!save_catalog (catalog, VERBOSE)) {
+    fprintf (stderr, "ERROR: failure saving catalog\n");
+    exit (1);
+  }
+
+  /* free, initialize data structures */
+
+  if (catalog[0].Naverage) {
+    free (catalog[0].average); 
+    catalog[0].Naverage = 0;
+  }
+  if (catalog[0].Nmeasure) {
+    free (catalog[0].measure); 
+    catalog[0].Nmeasure = 0;
+  }
+  if (catalog[0].Nmissing) {
+    free (catalog[0].missing); 
+    catalog[0].Nmissing = 0;
+  }
+  if (catalog[0].Nsecfilt) {
+    free (catalog[0].secfilt); 
+    catalog[0].Nsecfilt = 0;
+  }
+  fits_free_header (&catalog[0].header);
+}
+
Index: /tags/start/Ohana/src/addspphot/src/wimage.c
===================================================================
--- /tags/start/Ohana/src/addspphot/src/wimage.c	(revision 12606)
+++ /tags/start/Ohana/src/addspphot/src/wimage.c	(revision 12606)
@@ -0,0 +1,54 @@
+# include "addstar.h"
+
+void wimage (FILE *f, int dbstate, Image *image, int Nstars) {
+  
+  int Nimages, status, offset;
+  Header header;
+
+  /* place file pointer at beginning of file */
+  fseek (f, 0, SEEK_SET);
+
+  if (dbstate == LCK_EMPTY) {
+    if (VERBOSE) fprintf (stderr, "can't find %s, creating a new one\n", ImageCat);
+    if (!fits_read_header (ImageTemplate, &header)) {
+      fprintf (stderr, "ERROR: can't find template header %s\n", ImageTemplate);
+      exit (1);
+    }
+    /* assign Zero Point provided by first image in dB */
+    fits_modify (&header, "ZERO_PT", "%lf", 1, ZeroPt);
+  } else {
+    if (!fits_load_header (f, &header)) {
+      fprintf (stderr, "ERROR: can't read image header %s\n", ImageCat);
+      exit (1);
+    }
+  }
+  
+  Nimages = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimages);
+  Nimages ++;
+  fits_modify (&header, "NIMAGES", "%d", 1, Nimages);
+
+  /* position to begining of file to write header */
+  fseek (f, 0, SEEK_SET);
+  status = Fwrite (header.buffer, 1, header.size, f, "char");
+  if (status != header.size) {
+    fprintf (stderr, "ERROR: failed writing data to image header\n");
+    exit (1);
+  }
+
+  /* position to end of data array */
+  offset = (Nimages - 1)*sizeof(Image) + header.size;
+  fseek (f, offset, SEEK_SET);
+
+  status = Fwrite (image, sizeof(Image), 1, f, "image");
+  if (status != 1) {
+    fprintf (stderr, "ERROR: failed writing data to image catalog\n");
+    exit (1);
+  }
+}
+
+/* the image we add in this routine is always a new image.  
+   We only need to do two things:
+     1) append the data for the image to the end of the file
+     2) update the NIMAGES field in the header (which means, read in header, re-write)
+ */
Index: /tags/start/Ohana/src/addstar/Makefile
===================================================================
--- /tags/start/Ohana/src/addstar/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/addstar/Makefile	(revision 12606)
@@ -0,0 +1,61 @@
+include ../../Configure
+HOME 	=	$(ROOT)/src/addstar
+PROGRAM =       addstar
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#  
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lFITS -lohana -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS)
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+ADDSTAR = \
+$(SRC)/addstar.$(ARCH).o 	$(SRC)/gcatalog.$(ARCH).o   \
+$(SRC)/gregions.$(ARCH).o 	$(SRC)/gimages.$(ARCH).o    \
+$(SRC)/wimage.$(ARCH).o   	$(SRC)/gstars.$(ARCH).o     \
+$(SRC)/find_matches.$(ARCH).o 	$(SRC)/wcatalog.$(ARCH).o   \
+$(SRC)/sort_lists.$(ARCH).o 	$(SRC)/ConfigInit.$(ARCH).o 	\
+$(SRC)/aregion.$(ARCH).o	\
+$(SRC)/check_permissions.$(ARCH).o $(SRC)/calibrate.$(ARCH).o \
+$(SRC)/args.$(ARCH).o		$(SRC)/parse_time.$(ARCH).o \
+$(SRC)/mkcatalog.$(ARCH).o
+
+OBJ = $(ADDSTAR)
+
+default: $(PROGRAM)
+
+$(ADDSTAR): $(INC)/addstar.h
+
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:	
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
+
+
Index: /tags/start/Ohana/src/addstar/doc/database.txt
===================================================================
--- /tags/start/Ohana/src/addstar/doc/database.txt	(revision 12606)
+++ /tags/start/Ohana/src/addstar/doc/database.txt	(revision 12606)
@@ -0,0 +1,91 @@
+
+\begin{verbatim}
+
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm;      /* number of measurements */
+  unsigned short int Xp, Xm;  /* chisq values in tenths */
+  unsigned int offset;        /* offset to first Measure-ment */
+} Average;                    /* = 20 bytes / average */
+
+typedef struct {
+  char dR, dD;                /* tenths of arcsec (-12.7 to +12.7 valid range) */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 -- 0.255 valid range) */
+  float t;                    /* time in seconds (what is reference?) */
+  unsigned int average;       /* reference to corresponding Average entry, 
+				 upper byte of value contains flags.
+				 limit of 16,777,215 stars (Naverage) 
+				 in a file (=0xFFFFFF).
+				 flags = average & 0x1000000 */
+} Measure;                    /* = 13 bytes / measure */
+
+# define BLEND_IMAGE   0X01000000
+# define BLEND_CATALOG 0X02000000
+# define UPPER_LIMIT   0X04000000
+# define CALIBRATED    0X08000000
+
+\end{verbatim}
+
+The above two structures define the entries in the photometry
+database.  The database consists of a large number of files
+representing a small patch on the sky (roughly 1.5 degree$^2$ in most
+places).  These files are organized into directories representing
+bands of Declination.  A reference file determines the coordinate
+boundaries for each of the files so that a given point on the sky can
+unambiguously be associated with a specific file in a specific
+directory.  The sky coordinates for each file is the same as those
+used by the HST Guide Star catalog, except for the region around the
+North celestial pole, for which all stars are included in a single
+file.  
+
+Within a given file, the data are stored in a binary format, with an
+ASCII FITS-like header.  The header is examply in the format of a
+normal FITS header, but with the exception that all files have a fixed
+number of header blocks (for now 3 blocks = 8640 bytes).  This is done
+to speed loading the header and finding the beginning of the binary
+data.  The number of 3 blocks seems quite generous, as currently only
+a few FITS keywords have been defined for each file, basically
+keywords to define the number of stars and the total number of
+measurements stored in the file, as well as values to define the RA
+and DEC range of the file.  
+
+The first section of data following the header blocks consists of
+average measurements for each uniquely observed star.  Each star
+occupies 20 bytes, the size of the Average structure defined above.
+The Average structure contains the average Ra, Dec, and Magnitude for
+the star, as well as the number of measurements, and \chisq\ values
+for the magnitude and position.  Finally, there is a 32 bit integer
+which defines the offset to the first measurement for this star.  This
+offset is defined as the number of Measure records from the start of
+the Measure structure.
+
+The second section of data, following the Average data contains all
+measurements for each star listed in Average.  Each measurement
+occupies 13 bytes, the size of the Measure structure.  This structure
+contains the difference of this position from the average RA and DEC,
+and the instrumental magnitude of this measurement (in the units
+defined by the fstat program, which give m = -2.5*log(cts) + Mo, where
+Mo is currently 24.5 [10/15]).  There is also the magnitude error for
+this measurement, the time of the measurement (in seconds relative to
+a to-be-determined zero point), and a reference to the entry in the
+Average structure so we can relate a given measurement with a given star.
+This last entry also includes a byte of flags, of which only 4 have
+currently been defined.  This means the Average offset can only be as
+large as  16,777,215 (0xffffff), limiting the possible number of stars
+allowed in a given file.  This does not seem like a long term problem,
+though:  aside from the fact that this number is very large and we
+only expect in the vicinity of 20,000 stars per file, the file can
+easily be divided into pieces at a later date if needed.  this last
+step is trivial, consisting of splitting the data up into smaller
+RA,DEC regions, and updating the reference catalog.  With the above
+definitions for the Average and Measure structures, we will typically
+expect 20,000 * 15 measurements per year and 20,000 average entries in
+a given file.  This implies a file size of about 4.3 MB at the end of
+a year.  It is also possible that we will choose to split the files up
+in the future if the number of measurements makes their size
+unweildy.  4.3 MB is sufficiently small that this is not a problem,
+but after only 5 years, the files will be over 21 MB each, getting to
+be fairly significant.  
Index: /tags/start/Ohana/src/addstar/doc/description.txt
===================================================================
--- /tags/start/Ohana/src/addstar/doc/description.txt	(revision 12606)
+++ /tags/start/Ohana/src/addstar/doc/description.txt	(revision 12606)
@@ -0,0 +1,94 @@
+
+ADDSTAR:
+
+This program takes a photometry file, with astrometry, provided by
+earlier routines and incorporates the stellar measurements into the
+photometry database.  This routine does NOT try to calibrate or check
+the photometry, nor does it try to improve the coordinate
+determinations or calculate chisquares for position or photometry -
+those tasks are performed by other routines.
+
+Addstar starts by loading in the photometry file and converting the
+pixel coordinates to sky coordinates using the astrometry information
+in the header of the file.  It also gets the detection limits and
+stores the image astrometry information.
+
+Next, addstar determines which of all the previous images overlaps
+with this image and also which of the catalog regions overlaps with
+this image.
+
+Addstar considers each catalog region in turn, and compares the
+positions of stars in the catalog with stars in the image.  If a
+catalog star is detected, a new measurement is added to the catalog.
+If a catalog star is not detected, but is in the field of view of this
+image, the detection limit for this image is added to the list of
+measurements as an upper limit.  If the image contains a star which is
+not already included in the catalog, the star is added to the catalog,
+and all previous images are checked to see if they included this
+location.  If so, upper limits are added to the list of measurements.
+
+To deal with blended images, we have taken the philosophy that all
+measurements compatible with the coordinates of a given star should be
+included in the list of measurements.  This assumes that programs or people
+downstream will figure out which is the "correct" measurement.  To
+this end, if a catalog star is consistent with multiple measurements,
+they are all added to the catalog measurement and the measurements are
+given a flag to say that there was blending in the catalog (ie, it is
+probably the catalog star which is a blend).  If multiple catalog
+stars are consistent with the same image star, that measurement is
+added to each catalog star, and given a flag to say that there was
+blending on the image.
+
+After all catalogs have been checked, updated, and written to disk,
+the image is added to the database of images.
+
+The format for a catalog region file is as follows:
+
+-- 
+Header
+--
+Averages
+--
+Measurements
+--
+
+The Header follows the format of a FITS header but always stored with
+3 blocks to speed up read time: 2880 x 3 bytes.  Two important
+keywords in the header: NSTARS & NMEAS
+
+All average values are stored consecutively in a single block.  They
+are written as an array with NSTARS elements of the Average structure
+defined below.  The individual measurements follow the averages as a
+block.  To find a measurement for a given star, you need to get the
+value of the offset for the star.  this is the element number for the
+first measurement of this star, and are followed by next measurements
+for this star, until the value Nm is reached.
+
+Here are the structures being used for the average and measurement
+values:
+
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm;      /* number of measurements */
+  unsigned short int Xp, Xm;  /* chisq values in tenths */
+  unsigned int offset;        /* offset to first measurement */
+} Average;                    /* = 20 bytes / average */
+
+typedef struct {
+  char dR, dD;                /* tenths of arcsec (-12.7 to +12.7 valid range) */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 -- 0.255 valid range) */
+  float t;                    /* time in seconds (what is reference?) */
+  unsigned int average;       
+  /* reference to corresponding average entry, upper byte stores flags:
+   limit of 16,777,215 stars (Naverage) in a file (=0xFFFFFF) 
+   flags: average & 0x1000000 */
+} Measure;                    /* = 13 bytes / measure */
+
+/* flags for measurements: */
+# define BLEND_IMAGE   0X01000000
+# define BLEND_CATALOG 0X02000000
+# define UPPER_LIMIT   0X04000000
+# define CALIBRATED    0X08000000
Index: /tags/start/Ohana/src/addstar/etc/phottemp.cat
===================================================================
--- /tags/start/Ohana/src/addstar/etc/phottemp.cat	(revision 12606)
+++ /tags/start/Ohana/src/addstar/etc/phottemp.cat	(revision 12606)
@@ -0,0 +1,296 @@
+SIMPLE  =                    F  / ASTROCAM PHOTOMETRY FILE                    \
+BITPIX  =                   16 /                                              \
+NAXIS   =                    2  / NUMBER OF AXES                              \
+NAXIS1  =                 1106  / NUMBER OF COLUMNS                           \
+NAXIS2  =                 1024  / NUMBER OF ROWS                              \
+BSCALE  =             1.000000 /                                              \
+BZERO   =             0.000000 /                                              \
+DATE    = '19/12/94'            / UT Date of file creation (DD/MM/YY)         \
+ORIGIN  = 'MDM Observatory'     / Michigan-Dartmouth-MIT                      \
+LATITUDE=              31.9500  / Latitude (degrees N)                        \
+LONGITUD=            -111.6150  / Longitude (degrees E)                       \
+OBSERVER= 'Metzger '            / Name of observer                            \
+TELESCOP= '1.3m McGraw-Hill'    / Telescope used for observation              \
+INSTRUME= 'Charlotte Direct'    / Instrument used for observation             \
+DETECTOR= 'Charlotte/Tek 1024^2 CCD'  / Detector used for observation         \
+FRAME   =                   32  / Frame number of observation                 \
+CCDPICNO=                   32  / Frame number of observation                 \
+OBJECT  = 'ocl0327 '            / Name of object                              \
+IMAGETYP= 'OBJECT  '            / Type of observation                         \
+EXPTIME =              250.000  / Integration time (seconds)                  \
+DARKTIME=              250.067  / Dark current time (seconds)                 \
+DATE-OBS= '19/12/94'            / UT Date of observation (DD/MM/YY)           \
+UT      = ' 05:25:44.00'        / Universal time (UTC) at exposure start      \
+JD      =       2449705.726204                                                \
+RA      =           50.700      / Right Ascension                             \
+DEC     =           89.000      / Declination                                 \
+DIRECTN =                 -1    / Moving South                                \
+EQUINOX =             1950.000  / Equinox of RA and DEC                       \
+HA      = ' 02:14:06.72'        / Hour angle at start                         \
+ST      = ' 03:49:36.85'        / Sidereal time at start                      \
+ZD      = ' 36:26:07.17'        / Zenith distance (degrees)                   \
+AIRMASS =                1.243  / Airmass at start                            \
+FILTER  = 'I KP    '            / Filter description                          \
+GAIN    =                3.350  / Nominal gain (e-/ADU)                       \
+SECPIX1 =                0.508  / Arcseconds per pixel in fast dir            \
+SECPIX2 =                0.508  / Arcseconds per pixel in slow dir            \
+CCDBIN1 =                    1  / On-chip column binning (fast dir)           \
+CCDBIN2 =                    1  / On-chip row binning (slow dir)              \
+GPROBE  = '  5000.00   7000.00'  / Guide probe X Y                            \
+DATASEC = '[51:1074,1:1024]'    / Image area of frame                         \
+CCDSEC  = '[1:1074,1:1024]'     / Image area relative to full chip            \
+BIASSEC = '[1080:1106,1:1023]'  / Overscan area of frame                      \
+UNSIGN  =                    T /                                              \
+NSTARS  =                    0  / NUMBER OF stars                             \
+CTYPE1  = 'RA---SIN          ' /                                               
+CTYPE2  = 'DEC--SIN          ' /                                               
+CDELT1  =             0.000733 /                                               
+CDELT2  =             0.000733 /                                               
+CRVAL1  =            50.191418 /                                               
+CRVAL2  =            88.998663 /                                               
+CRPIX1  =          1028.644173 /                                               
+CRPIX2  =           503.129830 /                                               
+PC001001=             0.999906 /                                               
+PC001002=             0.012081 /                                               
+PC002001=            -0.011936 /                                               
+PC002002=             0.999950 /                                               
+END                                                                           \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+ 246.5  352.1 13.000 020 1 3.2
+ 246.5  352.1 14.100 020 1 3.2
+ 279.4  328.9 13.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 436.6  413.5 14.300 020 1 3.2
+   9.3  856.5 13.000 020 1 3.2
+   9.3  856.2 13.600 020 1 3.2
+ 319.7  697.9 12.000 020 1 3.2
+ 319.7  697.7 12.100 020 1 3.2
+ 244.3    9.5 14.100 020 1 3.2
+ 284.7  334.4 14.000 020 1 3.2
+ 127.1  122.8 14.200 020 1 3.2
+ 140.2  791.1 13.700 020 1 3.2
+ 140.2  790.8 14.400 020 1 3.2
+ 131.7  636.3 13.800 020 1 3.2
+ 423.8  700.6 13.800 020 1 3.2
+ 423.7  700.7 12.500 020 1 3.2
+ 266.2  290.7 13.800 020 1 3.2
+ 266.0  290.7 13.100 020 1 3.2
+ 570.7  721.6 13.600 020 1 3.2
+ 570.7  721.6 13.100 020 1 3.2
+ 548.7  673.0 13.700 020 1 3.2
+ 264.2  219.7 12.800 020 1 3.2
+ 264.0  219.7 12.100 020 1 3.2
+ 161.9  797.4 11.900 020 1 3.2
+ 162.0  797.2 12.200 020 1 3.2
+ 505.8  851.8 13.700 020 1 3.2
+  88.2  419.0 11.400 020 1 3.2
+  88.2  419.0 11.800 020 1 3.2
+ 426.9  613.2  9.400 020 1 3.2
+ 427.4  613.5  7.600 020 1 3.2
+ 326.1  595.2 12.100 020 1 3.2
+ 326.2  595.1 12.600 020 1 3.2
+ 444.4  845.2 14.200 020 1 3.2
+ 254.1  916.8 14.500 020 1 3.2
+ 502.6  882.4 14.200 020 1 3.2
+ 128.3  275.7 12.300 020 1 3.2
+ 128.3  275.7 12.900 020 1 3.2
+ 230.9  554.8 13.300 020 1 3.2
+ 230.9  554.7 14.200 020 1 3.2
+  47.5  685.2 13.500 020 1 3.2
+  47.5  684.9 14.200 020 1 3.2
+ 382.6  658.7 14.000 020 1 3.2
+ 182.2  330.3 14.200 020 1 3.2
+ 245.1  548.3 12.600 020 1 3.2
+ 245.3  548.0 13.200 020 1 3.2
+  50.3  849.0 13.700 020 1 3.2
+  50.5  848.8 14.300 020 1 3.2
+  17.9  772.7 14.200 020 1 3.2
+ 499.8  712.8 13.500 020 1 3.2
+ 499.8  712.6 14.400 020 1 3.2
+ 294.5  349.4 14.000 020 1 3.2
+ 497.7  747.8 11.000 020 1 3.2
+ 497.5  747.8 10.900 020 1 3.2
+ 109.7  323.5 14.000 020 1 3.2
+  59.5  917.6 14.300 020 1 3.2
+  59.4  917.8 13.700 020 1 3.2
+  82.2  880.5 13.800 020 1 3.2
+ 145.1  341.2 14.500 020 1 3.2
+ 452.7  592.4 14.400 020 1 3.2
+ 623.4  820.0 13.700 020 1 3.2
+ 609.7  829.3 13.500 020 1 3.2
+ 481.8  938.3 14.400 020 1 3.2
+ 617.0  792.7 13.500 020 1 3.2
+ 183.2  539.7 14.400 020 1 3.2
+ 133.9  679.6 14.400 020 1 3.2
+ 423.7  667.8  6.500 020 1 3.2
+ 434.7  111.9 13.200 020 1 3.2
+ 434.5  111.9 13.200 020 1 3.2
+ 434.6  111.9 14.200 020 1 3.2
+1222.3  684.2 13.900 020 1 3.2
+1077.6  282.5 14.000 020 1 3.2
+1077.8  282.5 13.400 020 1 3.2
+ 720.8  562.1 14.100 020 1 3.2
+ 721.1  561.9 14.400 020 1 3.2
+1182.1  944.4 12.100 020 1 3.2
+1181.9  944.4 11.800 020 1 3.2
+1181.9  944.4 12.300 020 1 3.2
+ 761.2  423.1 14.300 020 1 3.2
+ 761.0  423.1 14.100 020 1 3.2
+ 926.7  436.8 13.400 020 1 3.2
+ 926.6  436.8 14.200 020 1 3.2
+1209.1   45.0 13.200 020 1 3.2
+1209.2   43.6 12.800 020 1 3.2
+1135.2  653.1  8.100 020 1 3.2
+1135.6  653.4  8.200 020 1 3.2
+1123.5  735.8 12.000 020 1 3.2
+1123.6  735.8 11.800 020 1 3.2
+1123.7  735.7 11.600 020 1 3.2
+ 730.7   28.6 12.100 020 1 3.2
+ 730.7   28.6 12.200 020 1 3.2
+ 783.1  267.5 14.200 020 1 3.2
+ 783.2  267.5 13.400 020 1 3.2
+ 876.2  462.7 13.800 020 1 3.2
+ 876.4  462.7 14.200 020 1 3.2
+ 917.2  399.9 13.700 020 1 3.2
+ 917.3  399.9 13.200 020 1 3.2
+1227.5  218.4 10.400 020 1 3.2
+1227.7  218.4 10.500 020 1 3.2
+1022.7  146.0 13.300 020 1 3.2
+1022.5  146.0 14.100 020 1 3.2
+1324.7   72.3 12.900 020 1 3.2
+1324.6   72.3 13.200 020 1 3.2
+ 743.2  379.4 14.300 020 1 3.2
+ 742.9  379.4 13.900 020 1 3.2
+1255.9  544.0 12.600 020 1 3.2
+1256.0  543.9 12.300 020 1 3.2
+ 848.9  251.1 13.200 020 1 3.2
+ 849.0  251.1 12.700 020 1 3.2
+ 495.6  147.4 11.400 020 1 3.2
+ 495.6  147.4 11.300 020 1 3.2
+ 495.5  147.4 11.000 020 1 3.2
+1016.4  735.5 14.200 020 1 3.2
+1016.3  735.7 13.900 020 1 3.2
+ 795.2  675.9 14.400 020 1 3.2
+ 887.2  968.8 10.800 020 1 3.2
+ 626.8  726.9 14.400 020 1 3.2
+ 718.6  800.1  9.700 020 1 3.2
+ 675.4  301.6 14.400 020 1 3.2
+ 801.6  436.8 14.200 020 1 3.2
+1066.4  870.0 13.700 020 1 3.2
+1066.5  869.9 13.800 020 1 3.2
+ 644.5  662.9  9.900 020 1 3.2
+ 639.1  760.4 13.000 020 1 3.2
+ 822.7  663.1 12.800 020 1 3.2
+ 822.7  663.1 13.100 020 1 3.2
+ 677.2  716.2 12.900 020 1 3.2
+ 765.6  641.5 13.200 020 1 3.2
+ 765.7  641.4 13.500 020 1 3.2
+ 998.3  425.8 14.400 020 1 3.2
+ 713.7  716.2 13.800 020 1 3.2
+ 814.7  887.6  2.000 020 1 3.2
+ 808.7  884.1  8.200 020 1 3.2
+1812.3  259.3 14.500 020 1 3.2
+1655.9  655.4 12.200 020 1 3.2
+1655.9  655.4 12.100 020 1 3.2
+1577.2  839.6 11.500 020 1 3.2
+1577.2  839.6 11.400 020 1 3.2
+1643.7  597.0 14.100 020 1 3.2
+1552.8  251.1 10.100 020 1 3.2
+1552.8  251.1 10.300 020 1 3.2
+1410.0  999.9 13.900 020 1 3.2
+1335.6  687.0 13.000 020 1 3.2
+1335.8  686.8 12.700 020 1 3.2
+1471.4  262.0 14.200 020 1 3.2
+1479.6  608.3 14.200 020 1 3.2
+1478.1  211.5 12.000 020 1 3.2
+1478.3  211.5 12.000 020 1 3.2
+1552.5   46.4 14.500 020 1 3.2
+2042.4  548.3 10.800 020 1 3.2
+2042.6  548.3 11.000 020 1 3.2
+1448.0  915.7 14.100 020 1 3.2
+1462.3  989.2 13.000 020 1 3.2
+1462.3  989.0 12.700 020 1 3.2
+1316.9  787.3 14.100 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1677.2  106.4 13.100 020 1 3.2
+1677.0  106.4 13.300 020 1 3.2
+1324.2  429.9  9.200 020 1 3.2
+1324.2  429.9  9.000 020 1 3.2
+1462.8  214.3 13.700 020 1 3.2
+1462.8  214.3 14.200 020 1 3.2
+1405.4   95.5 11.700 020 1 3.2
+1405.2   95.5 11.600 020 1 3.2
+1604.8   90.0 11.200 020 1 3.2
+1604.8   90.0 11.300 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1459.8  473.6 13.400 020 1 3.2
+1459.7  473.6 13.800 020 1 3.2
+1438.7   77.8 12.200 020 1 3.2
+1438.6   77.8 12.200 020 1 3.2
+1355.0  114.6 13.000 020 1 3.2
+1354.9  114.6 13.200 020 1 3.2
+1941.4  940.7 13.000 020 1 3.2
+1941.6  940.7 12.900 020 1 3.2
+1994.0  800.8 13.900 020 1 3.2
+1993.8  800.8 14.000 020 1 3.2
+2024.4  907.0 13.700 020 1 3.2
+2024.4  907.0 13.800 020 1 3.2
+2035.7  881.6 13.900 020 1 3.2
+2035.9  881.6 13.800 020 1 3.2
+1994.0  924.2 12.100 020 1 3.2
+1994.0  924.2 12.000 020 1 3.2
Index: /tags/start/Ohana/src/addstar/etc/template.cat
===================================================================
--- /tags/start/Ohana/src/addstar/etc/template.cat	(revision 12606)
+++ /tags/start/Ohana/src/addstar/etc/template.cat	(revision 12606)
@@ -0,0 +1,296 @@
+SIMPLE  =                    F  / ASTROCAM PHOTOMETRY FILE                    \
+BITPIX  =                   16 /                                              \
+NAXIS   =                    2  / NUMBER OF AXES                              \
+NAXIS1  =                 1106  / NUMBER OF COLUMNS                           \
+NAXIS2  =                 1024  / NUMBER OF ROWS                              \
+BSCALE  =             1.000000 /                                              \
+BZERO   =             0.000000 /                                              \
+DATE    = '19/12/94'            / UT Date of file creation (DD/MM/YY)         \
+ORIGIN  = 'MDM Observatory'     / Michigan-Dartmouth-MIT                      \
+LATITUDE=              31.9500  / Latitude (degrees N)                        \
+LONGITUD=            -111.6150  / Longitude (degrees E)                       \
+OBSERVER= 'Metzger '            / Name of observer                            \
+TELESCOP= '1.3m McGraw-Hill'    / Telescope used for observation              \
+INSTRUME= 'Charlotte Direct'    / Instrument used for observation             \
+DETECTOR= 'Charlotte/Tek 1024^2 CCD'  / Detector used for observation         \
+FRAME   =                   32  / Frame number of observation                 \
+CCDPICNO=                   32  / Frame number of observation                 \
+OBJECT  = 'ocl0327 '            / Name of object                              \
+IMAGETYP= 'OBJECT  '            / Type of observation                         \
+EXPTIME =              250.000  / Integration time (seconds)                  \
+DARKTIME=              250.067  / Dark current time (seconds)                 \
+DATE-OBS= '19/12/94'            / UT Date of observation (DD/MM/YY)           \
+UT      = ' 05:25:44.00'        / Universal time (UTC) at exposure start      \
+JD      =       2449705.726204                                                \
+RA      =           50.700      / Right Ascension                             \
+DEC     =           89.000      / Declination                                 \
+DIRECTN =                 -1    / Moving South                                \
+EQUINOX =             1950.000  / Equinox of RA and DEC                       \
+HA      = ' 02:14:06.72'        / Hour angle at start                         \
+ST      = ' 03:49:36.85'        / Sidereal time at start                      \
+ZD      = ' 36:26:07.17'        / Zenith distance (degrees)                   \
+AIRMASS =                1.243  / Airmass at start                            \
+FILTER  = 'I KP    '            / Filter description                          \
+GAIN    =                3.350  / Nominal gain (e-/ADU)                       \
+SECPIX1 =                0.508  / Arcseconds per pixel in fast dir            \
+SECPIX2 =                0.508  / Arcseconds per pixel in slow dir            \
+CCDBIN1 =                    1  / On-chip column binning (fast dir)           \
+CCDBIN2 =                    1  / On-chip row binning (slow dir)              \
+GPROBE  = '  5000.00   7000.00'  / Guide probe X Y                            \
+DATASEC = '[51:1074,1:1024]'    / Image area of frame                         \
+CCDSEC  = '[1:1074,1:1024]'     / Image area relative to full chip            \
+BIASSEC = '[1080:1106,1:1023]'  / Overscan area of frame                      \
+UNSIGN  =                    T /                                              \
+NSTARS  =                    0  / NUMBER OF stars                             \
+CTYPE1  = 'RA---SIN          ' /                                               
+CTYPE2  = 'DEC--SIN          ' /                                               
+CDELT1  =             0.000733 /                                               
+CDELT2  =             0.000733 /                                               
+CRVAL1  =            50.191418 /                                               
+CRVAL2  =            88.998663 /                                               
+CRPIX1  =          1028.644173 /                                               
+CRPIX2  =           503.129830 /                                               
+PC001001=             0.999906 /                                               
+PC001002=             0.012081 /                                               
+PC002001=            -0.011936 /                                               
+PC002002=             0.999950 /                                               
+END                                                                           \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+ 246.5  352.1 13.000 020 1 3.2
+ 246.5  352.1 14.100 020 1 3.2
+ 279.4  328.9 13.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 436.6  413.5 14.300 020 1 3.2
+   9.3  856.5 13.000 020 1 3.2
+   9.3  856.2 13.600 020 1 3.2
+ 319.7  697.9 12.000 020 1 3.2
+ 319.7  697.7 12.100 020 1 3.2
+ 244.3    9.5 14.100 020 1 3.2
+ 284.7  334.4 14.000 020 1 3.2
+ 127.1  122.8 14.200 020 1 3.2
+ 140.2  791.1 13.700 020 1 3.2
+ 140.2  790.8 14.400 020 1 3.2
+ 131.7  636.3 13.800 020 1 3.2
+ 423.8  700.6 13.800 020 1 3.2
+ 423.7  700.7 12.500 020 1 3.2
+ 266.2  290.7 13.800 020 1 3.2
+ 266.0  290.7 13.100 020 1 3.2
+ 570.7  721.6 13.600 020 1 3.2
+ 570.7  721.6 13.100 020 1 3.2
+ 548.7  673.0 13.700 020 1 3.2
+ 264.2  219.7 12.800 020 1 3.2
+ 264.0  219.7 12.100 020 1 3.2
+ 161.9  797.4 11.900 020 1 3.2
+ 162.0  797.2 12.200 020 1 3.2
+ 505.8  851.8 13.700 020 1 3.2
+  88.2  419.0 11.400 020 1 3.2
+  88.2  419.0 11.800 020 1 3.2
+ 426.9  613.2  9.400 020 1 3.2
+ 427.4  613.5  7.600 020 1 3.2
+ 326.1  595.2 12.100 020 1 3.2
+ 326.2  595.1 12.600 020 1 3.2
+ 444.4  845.2 14.200 020 1 3.2
+ 254.1  916.8 14.500 020 1 3.2
+ 502.6  882.4 14.200 020 1 3.2
+ 128.3  275.7 12.300 020 1 3.2
+ 128.3  275.7 12.900 020 1 3.2
+ 230.9  554.8 13.300 020 1 3.2
+ 230.9  554.7 14.200 020 1 3.2
+  47.5  685.2 13.500 020 1 3.2
+  47.5  684.9 14.200 020 1 3.2
+ 382.6  658.7 14.000 020 1 3.2
+ 182.2  330.3 14.200 020 1 3.2
+ 245.1  548.3 12.600 020 1 3.2
+ 245.3  548.0 13.200 020 1 3.2
+  50.3  849.0 13.700 020 1 3.2
+  50.5  848.8 14.300 020 1 3.2
+  17.9  772.7 14.200 020 1 3.2
+ 499.8  712.8 13.500 020 1 3.2
+ 499.8  712.6 14.400 020 1 3.2
+ 294.5  349.4 14.000 020 1 3.2
+ 497.7  747.8 11.000 020 1 3.2
+ 497.5  747.8 10.900 020 1 3.2
+ 109.7  323.5 14.000 020 1 3.2
+  59.5  917.6 14.300 020 1 3.2
+  59.4  917.8 13.700 020 1 3.2
+  82.2  880.5 13.800 020 1 3.2
+ 145.1  341.2 14.500 020 1 3.2
+ 452.7  592.4 14.400 020 1 3.2
+ 623.4  820.0 13.700 020 1 3.2
+ 609.7  829.3 13.500 020 1 3.2
+ 481.8  938.3 14.400 020 1 3.2
+ 617.0  792.7 13.500 020 1 3.2
+ 183.2  539.7 14.400 020 1 3.2
+ 133.9  679.6 14.400 020 1 3.2
+ 423.7  667.8  6.500 020 1 3.2
+ 434.7  111.9 13.200 020 1 3.2
+ 434.5  111.9 13.200 020 1 3.2
+ 434.6  111.9 14.200 020 1 3.2
+1222.3  684.2 13.900 020 1 3.2
+1077.6  282.5 14.000 020 1 3.2
+1077.8  282.5 13.400 020 1 3.2
+ 720.8  562.1 14.100 020 1 3.2
+ 721.1  561.9 14.400 020 1 3.2
+1182.1  944.4 12.100 020 1 3.2
+1181.9  944.4 11.800 020 1 3.2
+1181.9  944.4 12.300 020 1 3.2
+ 761.2  423.1 14.300 020 1 3.2
+ 761.0  423.1 14.100 020 1 3.2
+ 926.7  436.8 13.400 020 1 3.2
+ 926.6  436.8 14.200 020 1 3.2
+1209.1   45.0 13.200 020 1 3.2
+1209.2   43.6 12.800 020 1 3.2
+1135.2  653.1  8.100 020 1 3.2
+1135.6  653.4  8.200 020 1 3.2
+1123.5  735.8 12.000 020 1 3.2
+1123.6  735.8 11.800 020 1 3.2
+1123.7  735.7 11.600 020 1 3.2
+ 730.7   28.6 12.100 020 1 3.2
+ 730.7   28.6 12.200 020 1 3.2
+ 783.1  267.5 14.200 020 1 3.2
+ 783.2  267.5 13.400 020 1 3.2
+ 876.2  462.7 13.800 020 1 3.2
+ 876.4  462.7 14.200 020 1 3.2
+ 917.2  399.9 13.700 020 1 3.2
+ 917.3  399.9 13.200 020 1 3.2
+1227.5  218.4 10.400 020 1 3.2
+1227.7  218.4 10.500 020 1 3.2
+1022.7  146.0 13.300 020 1 3.2
+1022.5  146.0 14.100 020 1 3.2
+1324.7   72.3 12.900 020 1 3.2
+1324.6   72.3 13.200 020 1 3.2
+ 743.2  379.4 14.300 020 1 3.2
+ 742.9  379.4 13.900 020 1 3.2
+1255.9  544.0 12.600 020 1 3.2
+1256.0  543.9 12.300 020 1 3.2
+ 848.9  251.1 13.200 020 1 3.2
+ 849.0  251.1 12.700 020 1 3.2
+ 495.6  147.4 11.400 020 1 3.2
+ 495.6  147.4 11.300 020 1 3.2
+ 495.5  147.4 11.000 020 1 3.2
+1016.4  735.5 14.200 020 1 3.2
+1016.3  735.7 13.900 020 1 3.2
+ 795.2  675.9 14.400 020 1 3.2
+ 887.2  968.8 10.800 020 1 3.2
+ 626.8  726.9 14.400 020 1 3.2
+ 718.6  800.1  9.700 020 1 3.2
+ 675.4  301.6 14.400 020 1 3.2
+ 801.6  436.8 14.200 020 1 3.2
+1066.4  870.0 13.700 020 1 3.2
+1066.5  869.9 13.800 020 1 3.2
+ 644.5  662.9  9.900 020 1 3.2
+ 639.1  760.4 13.000 020 1 3.2
+ 822.7  663.1 12.800 020 1 3.2
+ 822.7  663.1 13.100 020 1 3.2
+ 677.2  716.2 12.900 020 1 3.2
+ 765.6  641.5 13.200 020 1 3.2
+ 765.7  641.4 13.500 020 1 3.2
+ 998.3  425.8 14.400 020 1 3.2
+ 713.7  716.2 13.800 020 1 3.2
+ 814.7  887.6  2.000 020 1 3.2
+ 808.7  884.1  8.200 020 1 3.2
+1812.3  259.3 14.500 020 1 3.2
+1655.9  655.4 12.200 020 1 3.2
+1655.9  655.4 12.100 020 1 3.2
+1577.2  839.6 11.500 020 1 3.2
+1577.2  839.6 11.400 020 1 3.2
+1643.7  597.0 14.100 020 1 3.2
+1552.8  251.1 10.100 020 1 3.2
+1552.8  251.1 10.300 020 1 3.2
+1410.0  999.9 13.900 020 1 3.2
+1335.6  687.0 13.000 020 1 3.2
+1335.8  686.8 12.700 020 1 3.2
+1471.4  262.0 14.200 020 1 3.2
+1479.6  608.3 14.200 020 1 3.2
+1478.1  211.5 12.000 020 1 3.2
+1478.3  211.5 12.000 020 1 3.2
+1552.5   46.4 14.500 020 1 3.2
+2042.4  548.3 10.800 020 1 3.2
+2042.6  548.3 11.000 020 1 3.2
+1448.0  915.7 14.100 020 1 3.2
+1462.3  989.2 13.000 020 1 3.2
+1462.3  989.0 12.700 020 1 3.2
+1316.9  787.3 14.100 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1677.2  106.4 13.100 020 1 3.2
+1677.0  106.4 13.300 020 1 3.2
+1324.2  429.9  9.200 020 1 3.2
+1324.2  429.9  9.000 020 1 3.2
+1462.8  214.3 13.700 020 1 3.2
+1462.8  214.3 14.200 020 1 3.2
+1405.4   95.5 11.700 020 1 3.2
+1405.2   95.5 11.600 020 1 3.2
+1604.8   90.0 11.200 020 1 3.2
+1604.8   90.0 11.300 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1459.8  473.6 13.400 020 1 3.2
+1459.7  473.6 13.800 020 1 3.2
+1438.7   77.8 12.200 020 1 3.2
+1438.6   77.8 12.200 020 1 3.2
+1355.0  114.6 13.000 020 1 3.2
+1354.9  114.6 13.200 020 1 3.2
+1941.4  940.7 13.000 020 1 3.2
+1941.6  940.7 12.900 020 1 3.2
+1994.0  800.8 13.900 020 1 3.2
+1993.8  800.8 14.000 020 1 3.2
+2024.4  907.0 13.700 020 1 3.2
+2024.4  907.0 13.800 020 1 3.2
+2035.7  881.6 13.900 020 1 3.2
+2035.9  881.6 13.800 020 1 3.2
+1994.0  924.2 12.100 020 1 3.2
+1994.0  924.2 12.000 020 1 3.2
Index: /tags/start/Ohana/src/addstar/include/addstar.h
===================================================================
--- /tags/start/Ohana/src/addstar/include/addstar.h	(revision 12606)
+++ /tags/start/Ohana/src/addstar/include/addstar.h	(revision 12606)
@@ -0,0 +1,79 @@
+# include <ohana.h>
+# include <loneos.h>
+# include <signal.h>
+
+typedef struct {
+  double X;
+  double Y;
+  double R;
+  double D;
+  double M, dM;
+  char   dophot;
+  double sky;
+  double fx, fy, df;
+  double Mgal, Map;
+  int found;
+} Stars;
+
+/* global variables set in parameter file */
+char   ImageCat[256];
+char   ImageTemplate[256];
+char   CatTemplate[256];
+char   GSCFILE[256];
+char   CATDIR[256];
+double DEFAULT_RADIUS, NSIGMA, SNLIMIT;
+double ZeroPt;
+int    VERBOSE;
+int    SKIP_MISSED;
+int    XOVERSCAN, YOVERSCAN;
+int    XMIN, XMAX, YMIN, YMAX;
+int    ACCEPT_ASTROM;
+
+PhotCode *thiscode;
+
+char DateKeyword[64];
+char DateMode[64];
+char UTKeyword[64];
+char MJDKeyword[64];
+char JDKeyword[64];
+char ExptimeKeyword[64];
+char AirmassKeyword[64];
+char CCDNumKeyword[64];
+
+int CalReference;
+int CalColor;
+int CALIBRATE;
+int DUMP_MATCHES;
+int ONLY_IMAGES;
+int FORCE_READ;
+
+int Shutdown ();  
+void TrapSignal (int sig);
+int main (int argc, char **argv);
+int SetSignals ();
+int gcatalog (Catalog *catalog);
+GSCRegion *gregions (Image *image, int *Nregions);
+Image *gimages (FILE *f, Image *image, int *Npimage);
+int edge_check (double *x1, double *y1, double *x2, double *y2);
+double opening_angle (double x1, double y1, double x2, double y2, double x3, double y3);
+void wimage (FILE *f, int dbstate, Image *image, int Nstars);
+Stars *gstars (char *file, int *NSTARS, Image *image);
+void find_matches (GSCRegion *region, Stars *stars, int Nstars, Catalog *catalog, Image *image, Image *pimage, int Nimage);
+int in_image (double r, double d, Image *image);
+void wcatalog (Catalog *catalog);
+void sort_lists (float *X, float *Y, int *S, int N);
+void fsort (float *X, int N);
+void ConfigInit (int *argc, char **argv);
+int hms_to_deg (double *h0, double *h1, double *d0, double *d1, char *string);
+void aregion (GSCRegion *region, FILE *f, double ra, double dec);
+void wimage (FILE *f, int dbstate, Image *image, int Nstars);
+void check_permissions (char *basefile);
+void make_backup (char *filename);
+void InitCalibration ();
+void SaveCalibration (float M, float dM, float Mr, float Mc, float A, int N, float ra, float dec, float x, float y);
+void FindCalibration (Image *image);
+void help ();
+int args (int argc, char **argv);
+int parse_time (Header *header);
+void uppercase (char *string);
+void mkcatalog (GSCRegion *region, Catalog *catalog);
Index: /tags/start/Ohana/src/addstar/src/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/addstar/src/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/addstar/src/ConfigInit.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include "addstar.h"
+
+void ConfigInit (int *argc, char **argv) {
+
+  char *config, *file;
+  char RadiusWord[80];
+  char PhotCodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (1);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  ScanConfig (config, "RADIUS",                 "%s", 0,  RadiusWord);
+  if (!strcasecmp (RadiusWord, "header")) {
+    DEFAULT_RADIUS = 0;
+  } else {
+    DEFAULT_RADIUS = atof (RadiusWord);
+  }
+
+  XMIN = XMAX = YMIN = YMAX = 0;
+  ScanConfig (config, "NSIGMA",                 "%lf", 0, &NSIGMA);
+  ScanConfig (config, "XOVERSCAN",              "%d", 0, &XOVERSCAN);
+  ScanConfig (config, "YOVERSCAN",              "%d", 0, &YOVERSCAN);
+  ScanConfig (config, "ADDSTAR_XMIN",           "%d", 0, &XMIN);
+  ScanConfig (config, "ADDSTAR_XMAX",           "%d", 0, &XMAX);
+  ScanConfig (config, "ADDSTAR_YMIN",           "%d", 0, &YMIN);
+  ScanConfig (config, "ADDSTAR_YMAX",           "%d", 0, &YMAX);
+
+  ScanConfig (config, "IMAGE_CATALOG",          "%s", 0, ImageCat);
+  ScanConfig (config, "IMAGE_CATALOG_TEMPLATE", "%s", 0, ImageTemplate);
+  ScanConfig (config, "CATALOG_TEMPLATE",       "%s", 0, CatTemplate);
+  ScanConfig (config, "GSCFILE",                "%s", 0, GSCFILE);
+  ScanConfig (config, "CATDIR",                 "%s", 0, CATDIR);
+  ScanConfig (config, "MIN_SN_FSTAT",           "%lf", 0, &SNLIMIT);
+  ScanConfig (config, "PHOTCODE_FILE",          "%s", 0, PhotCodeFile);
+
+  ScanConfig (config, "DATE-KEYWORD",           "%s", 0, DateKeyword);
+  ScanConfig (config, "DATE-MODE",              "%s", 0, DateMode);
+  ScanConfig (config, "UT-KEYWORD",             "%s", 0, UTKeyword);
+  ScanConfig (config, "MJD-KEYWORD",            "%s", 0, MJDKeyword);
+  ScanConfig (config, "JD-KEYWORD",             "%s", 0, JDKeyword);
+
+  ScanConfig (config, "EXPTIME-KEYWORD",        "%s", 0, ExptimeKeyword);
+  ScanConfig (config, "AIRMASS-KEYWORD",        "%s", 0, AirmassKeyword);
+  ScanConfig (config, "CCDNUM-KEYWORD",         "%s", 0, CCDNumKeyword);
+
+  if (!LoadPhotcodes (PhotCodeFile)) {
+    fprintf (stderr, "error loading photcodes\n");
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+
+}
Index: /tags/start/Ohana/src/addstar/src/addstar.c
===================================================================
--- /tags/start/Ohana/src/addstar/src/addstar.c	(revision 12606)
+++ /tags/start/Ohana/src/addstar/src/addstar.c	(revision 12606)
@@ -0,0 +1,222 @@
+# include "addstar.h"
+
+/* these variables are needed by Shutdown */
+static FILE *f = (FILE *) NULL;
+static int Protect = FALSE;
+static int Trapped = FALSE;
+
+/* clean up open / locked ImageCat before shutting down */
+int Shutdown () {  
+  int dbstate;
+
+  Protect = TRUE;
+  fclearlockfile (ImageCat, f, LCK_HARD, &dbstate);
+  fprintf (stderr, "ERROR: addstar halted\n");
+  exit (1);
+}
+
+void TrapSignal (int sig) {
+    fprintf (stderr, "trapped signal %d, exiting gracefully\n", sig);
+    if (sig == 11) {
+      fprintf (stderr, "seg fault\n");
+      exit (1);
+    }
+    if (Protect) {
+      Trapped = TRUE;
+      fprintf (stderr, "blocking until protected sections are clear\n");
+      return;
+    }
+    Shutdown ();
+}    
+
+int main (int argc, char **argv) {
+
+  int i, mode, dbstate;
+  int Nstars, Nimage, Nregions, Nmissed;
+  Stars *stars, *gstars();
+  Image image, *pimage, *gimages();
+  GSCRegion *region, *gregions();
+  Catalog catalog;
+  
+  SetSignals ();
+  args (argc, argv);
+
+  /* load the input datafile */
+  stars = gstars (argv[1], &Nstars, &image);
+  if (Nstars == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in data file, skipping\n");
+    fprintf (stderr, "SUCCESS\n");
+    exit (0);
+  }
+
+  /* lock the image catalog */
+  check_permissions (ImageCat);
+  f = fsetlockfile (ImageCat, 3600.0, LCK_HARD, &dbstate);
+  if ((f == (FILE *) NULL) && (dbstate != LCK_EMPTY)) {
+    fprintf (stderr, "ERROR: can't lock image catalog\n");
+    exit (1);
+  }
+  fseek (f, 0, SEEK_SET);
+
+  /* load images */
+  if (dbstate == LCK_EMPTY) {
+    Nimage = 0;
+  } else {
+    pimage = gimages (f, &image, &Nimage);
+  }
+  region = gregions (&image, &Nregions);
+  fprintf (stderr, "region %f %f %f %f\n", region[0].RA[0], region[0].RA[1], region[0].DEC[0], region[0].DEC[1]);
+
+  for (i = 0; i < Nregions; i++) {
+    check_permissions (region[i].filename);
+  }
+
+  if (CALIBRATE) { InitCalibration (); }
+
+  for (i = 0; i < Nregions; i++) {
+    catalog.filename = region[i].filename;  /* don't free region before catalog! */
+    fprintf (stderr, "adding to %s\n", region[i].filename);
+    
+    switch (lock_catalog (&catalog, LCK_XCLD)) {
+    case 0:
+      /* this is a serious error because ImageCat was NOT locked */
+      fprintf (stderr, "ERROR: can't lock file %s\n", catalog.filename);
+      exit (1);
+    case 1:
+      gcatalog (&catalog); /* load from disk */
+      break;
+    case 2:
+      mkcatalog (&region[i], &catalog); /* fills in new header info */
+      break;
+    }
+    find_matches (&region[i], stars, Nstars, &catalog, &image, pimage, Nimage);
+
+    /* protect wcatalog from interrupt signals */
+    Protect = TRUE;
+    if (!DUMP_MATCHES && !ONLY_IMAGES) wcatalog (&catalog);
+    if (Trapped) Shutdown ();
+    Protect = FALSE;
+    unlock_catalog (&catalog);
+  }
+
+  if (CALIBRATE) { FindCalibration (&image); }
+  if (DUMP_MATCHES) Shutdown ();
+
+  for (Nmissed = i = 0; i < Nstars; i++) {
+    if (stars[i].found == -1) {
+      fprintf (stderr, "%d %f %f %f %f\n", i, stars[i].R, stars[i].D, stars[i].M, stars[i].dM);
+      Nmissed ++;
+    }
+  }
+  if (Nmissed) fprintf (stderr, "WARNING: %d stars in image were missed!\n", Nmissed);
+
+  /* protect wimage from interrupt signals */
+  Protect = TRUE;
+  wimage (f, dbstate, &image, Nstars); 
+  if (Trapped) Shutdown ();
+  Protect = FALSE;
+
+  fclearlockfile (ImageCat, f, LCK_HARD, &dbstate);
+
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  chmod (ImageCat, mode);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+
+}
+
+int SetSignals () {
+
+  int i;
+
+  /* disable almost all signal interrupts */
+  for (i = 0; i < 36; i++) {
+    switch (i) {
+      /* can't redirect this signals */
+    case SIGKILL:    /* kill -9: cannot be caught or ignored */
+    case SIGSTOP:    /* SIGSTOP: cannot be caught or ignored */
+      /* ignore these signals */
+    case SIGCHLD:    /* child halted: ignore */
+    case SIGPWR:     /* power failure - why ignore this? */
+    case SIGWINCH:   /* window resized */
+    case SIGCONT:    /* continue - maintain this action */
+    case SIGTSTP:    /* stop signal sent from tty - why ignore? */
+    case SIGURG:     /* socket signal, ignore this */
+      break;
+      
+    default:
+      signal (i, TrapSignal);
+    }
+  }
+  return (TRUE);
+}
+/*
+
+       Signal     Value     Action   Comment
+       -------------------------------------------------------------------------
+       SIGHUP        1        A      Hangup detected on controlling terminal
+                                     or death of controlling process
+       SIGINT        2        A      Interrupt from keyboard
+       SIGQUIT       3        A      Quit from keyboard
+       SIGILL        4        A      Illegal Instruction
+       SIGABRT       6        C      Abort signal from abort(3)
+       SIGFPE        8        C      Floating point exception
+       SIGKILL       9       AEF     Kill signal
+       SIGSEGV      11        C      Invalid memory reference
+       SIGPIPE      13        A      Broken pipe: write to pipe with no readers
+       SIGALRM      14        A      Timer signal from alarm(2)
+       SIGTERM      15        A      Termination signal
+       SIGUSR1   30,10,16     A      User-defined signal 1
+       SIGUSR2   31,12,17     A      User-defined signal 2
+       SIGCHLD   20,17,18     B      Child stopped or terminated
+       SIGCONT   19,18,25            Continue if stopped
+       SIGSTOP   17,19,23    DEF     Stop process
+       SIGTSTP   18,20,24     D      Stop typed at tty
+       SIGTTIN   21,21,26     D      tty input for background process
+       SIGTTOU   22,22,27     D      tty output for background process
+
+       Next various other signals.
+
+       Signal       Value     Action   Comment
+       ---------------------------------------------------------------------
+       SIGTRAP        5         CG     Trace/breakpoint trap
+       SIGIOT         6         CG     IOT trap. A synonym for SIGABRT
+       SIGEMT       7,-,7       G
+       SIGBUS      10,7,10      AG     Bus error
+       SIGSYS      12,-,12      G      Bad argument to routine (SVID)
+       SIGSTKFLT    -,16,-      AG     Stack fault on coprocessor
+       SIGURG      16,23,21     BG     Urgent condition on socket (4.2 BSD)
+       SIGIO       23,29,22     AG     I/O now possible (4.2 BSD)
+       SIGPOLL                  AG     A synonym for SIGIO (System V)
+       SIGCLD       -,-,18      G      A synonym for SIGCHLD
+       SIGXCPU     24,24,30     AG     CPU time limit exceeded (4.2 BSD)
+       SIGXFSZ     25,25,31     AG     File size limit exceeded (4.2 BSD)
+       SIGVTALRM   26,26,28     AG     Virtual alarm clock (4.2 BSD)
+       SIGPROF     27,27,29     AG     Profile alarm clock
+       SIGPWR      29,30,19     AG     Power failure (System V)
+       SIGINFO      29,-,-      G      A synonym for SIGPWR
+       SIGLOST      -,-,-       AG     File lock lost
+       SIGWINCH    28,28,20     BG     Window resize signal (4.3 BSD, Sun)
+       SIGUNUSED    -,31,-      AG     Unused signal
+       (Here - denotes that a signal is absent; there where three values are given, the first one is usually  valid  for  alpha  and
+       sparc,  the  middle  one  for i386 and ppc, the last one for mips. Signal 29 is SIGINFO / SIGPWR on an alpha but SIGLOST on a
+       sparc.)
+
+       The letters in the "Action" column have the following meanings:
+
+       A      Default action is to terminate the process.
+
+       B      Default action is to ignore the signal.
+
+       C      Default action is to dump core.
+
+       D      Default action is to stop the process.
+
+       E      Signal cannot be caught.
+
+       F      Signal cannot be ignored.
+
+       G      Not a POSIX.1 conformant signal.
+
+*/
Index: /tags/start/Ohana/src/addstar/src/aregion.c
===================================================================
--- /tags/start/Ohana/src/addstar/src/aregion.c	(revision 12606)
+++ /tags/start/Ohana/src/addstar/src/aregion.c	(revision 12606)
@@ -0,0 +1,171 @@
+# include "addstar.h"
+
+double BigDecBounds[] = {0.0, 7.5, 15.0, 22.5, 30.0, 37.5, 45.0, 
+			 52.5, 60.0, 67.5, 75.0, 82.5, 90.0,
+			 0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, 
+			 -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+char *DecSections[] = {"N0000", "N0730", "N1500", "N2230", "N3000", "N3730", "N4500", 
+		       "N5230", "N6000", "N6730", "N7500", "N8230", "weirdness", 
+		       "S0000", "S0730", "S1500", "S2230", "S3000", "S3730", "S4500", 
+		       "S5230", "S6000", "S6730", "S7500", "S8230", "weirdness"};
+
+char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			"n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			"s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			"s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+char *disk[] = {"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", 
+		"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "weirdness", 
+		"disk 1", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", 
+		"disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "weirdness"};
+
+int NBigRASections [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3, 48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3};
+
+int NDecLines[] = {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 24, 
+                   0, 597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48};
+
+# define DEBUG 1
+
+/* find region file which contains ra, dec */
+void aregion (GSCRegion *region, FILE *f, double ra, double dec) {
+  
+  char buffer[28800], temp[50], file[256];
+  double RA0, RA1, DEC0, DEC1;
+  int i, NBigDec, NLINES, done;
+  
+  while (ra < 0) { ra += 360.0; }
+  while (ra >= 360.0) { ra -= 360.0; }
+
+  if (dec >= 86.25) {
+    sprintf (file, "%s/n8230/pole.cpt", CATDIR);
+    region[0].DEC[0] = 86.25;
+    region[0].DEC[1] = 93.75;
+    region[0].RA[0] =  0.0;
+    region[0].RA[1] =  360.0;
+    strcpy (region[0].filename, file);
+    return;
+  }
+    
+  NBigDec = -1;
+  for (i = 0; i < 12; i++) {
+    if ((dec >= BigDecBounds[i]) && (dec < BigDecBounds[i+1])) {
+      NBigDec = i;
+      break;
+    }
+  }
+  if (NBigDec < 0) {
+    for (i = 13; i < 24; i++) {
+      if ((dec < BigDecBounds[i]) && (dec >= BigDecBounds[i+1])) {
+	NBigDec = i;
+	break;
+      }
+    }
+  }
+  if (NBigDec < 0) {
+    fprintf (stderr, "dec out of range: %f\n", dec);
+  }
+    
+  NLINES = 0;
+  for (i = 0; i < NBigDec; i++) {
+    NLINES += NDecLines[i];
+  }
+  fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+      
+  done = FALSE;
+  Fread (buffer, 1, 48*NDecLines[NBigDec], f, "char");
+  for (i = 0; !done && (i < NDecLines[NBigDec]); i++) {
+    strncpy (temp, &buffer[i*48], 48);
+    temp[49] = 0;
+    hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+    if (RA1 < RA0) RA1 += 360.0;
+    if ((dec >= 0) && (dec >= DEC0) && (dec < DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+    if ((dec < 0) && (dec < DEC0) && (dec >= DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+  }
+
+  if (!done) {
+    fprintf (stderr, "error in search: %f %f\n", ra, dec);
+    exit (1);
+  }
+  temp[5] = 0;
+  sprintf (file, "%s/%s/%s.cpt", CATDIR, Dec2Sections[NBigDec], &temp[1]);
+  if (DEC0 < DEC1) {
+    region[0].DEC[0] = DEC0;
+    region[0].DEC[1] = DEC1;
+  } else {
+    region[0].DEC[0] = DEC1;
+    region[0].DEC[1] = DEC0;
+  }     
+  region[0].RA[0] = RA0;
+  region[0].RA[1] = RA1;
+  strcpy (region[0].filename, file);
+  return;
+}
+
+
+/**********/
+int hms_to_deg (double *h0, double *h1, double *d0, double *d1, char *string) {
+  
+  int flag_d0, flag_d1, flag_h0, flag_h1;
+  double tmp;
+  
+  *d0 = *h0 = *d1 = *h1 = 0;
+
+  flag_h0 = dparse (h0, 1, string);
+  flag_h1 = dparse (h1, 4, string);
+  flag_d0 = dparse (d0, 7, string);
+  flag_d1 = dparse (d1, 9, string);
+  *h0 *= flag_h0;
+  *h1 *= flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  dparse (&tmp, 2, string);
+  *h0 += tmp/60.0;
+  dparse (&tmp, 3, string);
+  *h0 += tmp/3600.0;
+  
+  dparse (&tmp, 5, string);
+  *h1 += tmp/60.0;
+  dparse (&tmp, 6, string);
+  *h1 += tmp/3600.0;
+  
+  dparse (&tmp, 8, string);
+  *d0 += tmp/60.0;
+
+  dparse (&tmp, 10, string);
+  *d1 += tmp/60.0;
+
+  *h0 *= 15*flag_h0;
+  *h1 *= 15*flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  return (TRUE);
+}
+
+
+/*
+      if (buffer[i*48 + 19] == ' ') continue;
+      strncpy (temp, &buffer[i*48 + 19], 20);       temp[20] = 0;
+      hms_to_deg (&RA,  &DEC, temp, ' ', 3);
+
+
+  dBigRA = 360.0 / (int)(0.5 + 48*cos(3.1415927*0.5*(BigDecBounds[NBigDec] + BigDecBounds[NBigDec + 1])/180.0));
+
+  NBigRA = ra / dBigRA;
+
+  NBig = NBigRA;
+  for (i = 0; (i < 12) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+  for (i = 13; (i < 24) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+
+
+  fprintf (stderr, "%d %d %d %d %f %f -> %f %f %f\n", NBigDec, NBigRA, NBigRASections[NBigDec], NBig, ra, dec, BigDecBounds[NBigDec], BigDecBounds[NBigDec + 1], dBigRA);
+*/
Index: /tags/start/Ohana/src/addstar/src/args.c
===================================================================
--- /tags/start/Ohana/src/addstar/src/args.c	(revision 12606)
+++ /tags/start/Ohana/src/addstar/src/args.c	(revision 12606)
@@ -0,0 +1,93 @@
+# include "addstar.h"
+# define NARGS 2  /* minimum is: addstar (filename) */
+
+void help () {
+
+  fprintf (stderr, "USAGE: addstar (filename)\n");
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -v (verbose mode)\n");
+  fprintf (stderr, "  -p (photcode) - define the photcode\n");
+  fprintf (stderr, "\n"); 
+  exit (2);
+
+}
+
+int args (int argc, char **argv) {
+  
+  int N;
+
+  /* check for help request */
+  if (get_argument (argc, argv, "-help") ||
+      get_argument (argc, argv, "-h")) {
+    help ();
+  }
+
+  /* configuration info */
+  ConfigInit (&argc, argv);
+
+  /* check for command line options */
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  ACCEPT_ASTROM = FALSE;
+  if ((N = get_argument (argc, argv, "-accept"))) {
+    ACCEPT_ASTROM = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  thiscode = NULL;
+  if ((N = get_argument (argc, argv, "-p"))) {
+    remove_argument (N, &argc, argv);
+    thiscode = GetPhotcodebyName (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  DUMP_MATCHES = FALSE;
+  if ((N = get_argument (argc, argv, "-dump"))) {
+    DUMP_MATCHES = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  FORCE_READ = FALSE;
+  if ((N = get_argument (argc, argv, "-force"))) {
+    remove_argument (N, &argc, argv);
+    FORCE_READ = TRUE;
+  }
+  SKIP_MISSED = FALSE;
+  if ((N = get_argument (argc, argv, "-missed"))) {
+    SKIP_MISSED = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  ONLY_IMAGES = FALSE;
+  if ((N = get_argument (argc, argv, "-image"))) {
+    ONLY_IMAGES = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  CALIBRATE = FALSE;
+  if ((N = get_argument (argc, argv, "-cal"))) {
+    CALIBRATE = TRUE;
+    remove_argument (N, &argc, argv);
+    CalReference = GetPhotcodeCodebyName (argv[N]);
+    if (!CalReference) {
+      fprintf (stderr, "ERROR: photcode %s not found in photcode table\n", argv[N]);
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    CalColor = GetPhotcodeCodebyName (argv[N]);
+    if (!CalColor) {
+      fprintf (stderr, "ERROR: photcode color %s not found in photcode table\n", argv[N]);
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+  }
+  if (DUMP_MATCHES && !CALIBRATE) {
+    fprintf (stderr, "-dump only valid -with -cal\n");
+    exit (1);
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: addstar (filename) [-dump] [-image] [-v] [-p photcode] [-accept] [-cal code1 code2]\n");
+    exit (2);
+  }
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/addstar/src/calibrate.c
===================================================================
--- /tags/start/Ohana/src/addstar/src/calibrate.c	(revision 12606)
+++ /tags/start/Ohana/src/addstar/src/calibrate.c	(revision 12606)
@@ -0,0 +1,143 @@
+# include "addstar.h"
+
+static int Ncal, NCAL;
+static float *Mobs, *dMobs, *Mref, *Cref, *Airm;
+static float *RA, *DEC, *X, *Y;
+int *Nstar;
+
+void InitCalibration () {
+
+    fprintf (stderr, "calibrating the image...  %d\n", CalReference);
+    Ncal = 0;
+    NCAL = 1000;
+    ALLOCATE (Mobs,  float,  NCAL);
+    ALLOCATE (dMobs, float, NCAL);
+    ALLOCATE (Mref,  float,  NCAL);
+    ALLOCATE (Cref,  float,  NCAL);
+    ALLOCATE (Airm,  float,  NCAL);
+    ALLOCATE (Nstar, int, NCAL);
+    ALLOCATE (RA, float, NCAL);
+    ALLOCATE (DEC, float, NCAL);
+    ALLOCATE (X, float, NCAL);
+    ALLOCATE (Y, float, NCAL);
+}
+  
+void SaveCalibration (float M, float dM, float Mr, float Mc, float A, int N, float ra, float dec, float x, float y) {
+
+  Mobs[Ncal] = M;
+  dMobs[Ncal] = dM;
+  Mref[Ncal] = Mr;
+  Cref[Ncal] = Mc;
+  Airm[Ncal] = A;
+  Nstar[Ncal] = N;
+
+  RA[Ncal] = ra;
+  DEC[Ncal] = dec;
+  X[Ncal] = x;
+  Y[Ncal] = y;
+  Ncal ++;
+
+  if (Ncal == NCAL) {
+    NCAL += 1000;
+    REALLOCATE (dMobs, float, NCAL);
+    REALLOCATE (Mobs,  float, NCAL);
+    REALLOCATE (Mref,  float, NCAL);
+    REALLOCATE (Cref,  float, NCAL);
+    REALLOCATE (Airm,  float, NCAL);
+    REALLOCATE (Nstar, int,   NCAL);
+    REALLOCATE (RA, float, NCAL);
+    REALLOCATE (DEC, float, NCAL);
+    REALLOCATE (X, float, NCAL);
+    REALLOCATE (Y, float, NCAL);
+  }
+}
+
+void FindCalibration (Image *image) {
+
+  int i, MaxN, *Nlist, Nkeep;
+  float N, M1, M2, Klam, Clam, Xlam, Mabs, *Dmag;
+  float dAs, dMs, dYs;
+  
+  /* reject multiple matched-stars */
+  /* find maximum value of Nstar[] */
+  MaxN = -1;
+  for (i = 0; i < Ncal; i++) {
+    MaxN = MAX (Nstar[i], MaxN);
+  }
+  if (MaxN == -1) {
+    fprintf (stderr, "no clean stars\n");
+    image[0].Mcal = 10000;
+    image[0].dMcal = 10000;
+    return;
+  }
+  /* create a hash array from Nstar[] entries */
+  ALLOCATE (Nlist, int, MAX (1, MaxN + 1));
+  bzero (Nlist, MAX (0, MaxN*sizeof(int)));
+  for (i = 0; i < Ncal; i++) {
+    Nlist[Nstar[i]] ++;
+  }
+  
+  /* accumulate delta mags */
+  ALLOCATE (Dmag, float, Ncal);
+  Nkeep = 0;
+  Klam = thiscode[0].K;
+  Clam = thiscode[0].C;
+  Xlam = thiscode[0].X[0];
+  for (i = 0; i < Ncal; i++) {
+    /* if this entry has too many (or two few?) matches, skip it */
+    if (Nlist[Nstar[i]] != 1) continue;
+    Mabs = 0.001*(Mobs[i] + Klam*(Airm[i] - 1000) + Clam + Xlam*(Mref[i] - Cref[i])) - ZeroPt;
+
+    /* subpix correction : make parameters global! */
+    dAs = 0;
+    if (Y[i] < 400) dAs = 0.06 - 0.00015*Y[i];
+    dYs = Y[i] - (int) (Y[i]) + 0.55;
+    dMs = dAs * sin (6.28*dYs);
+    /* Mabs -= dMs; */
+
+    if (DUMP_MATCHES) 
+      fprintf (stdout, "%d  %6.3f %6.3f %6.3f  %10.6f %10.6f  %7.2f %7.2f\n", 
+	       i, Mabs, 0.001*Mref[i], 0.001*Cref[i], RA[i], DEC[i], X[i], Y[i]);
+
+    /* skip stars brighter than 8.0 */
+    /* if (Mabs < 8.0) continue; */
+    
+    Dmag[Nkeep] = (Mabs - 0.001*Mref[i]);
+    Nkeep ++;
+  }
+
+  if (Nkeep < 3) {
+    fprintf (stderr, "too few stars\n");
+    image[0].Mcal = 10000;
+    image[0].dMcal = 10000;
+    return;
+  }
+  fsort (Dmag, Nkeep);
+
+  /* accumulate delta mags (25% - 75% of list) */
+  M1 = 0.0;
+  M2 = 0.0;
+  N  = 0.0;
+  for (i = 0.25*Nkeep; i <= 0.75*Nkeep; i++) {
+
+    /* a straight mean works better, given the bad photometry of skyprobe */
+    M1 += Dmag[i];
+    M2 += SQ (Dmag[i]);
+    N  += 1.0; 
+
+  }
+
+  if (N > 1) {
+    M1 = M1 / N;
+    M2 = sqrt (fabs(M2/N - M1*M1));
+    fprintf (stderr, "N: %.0f, mean: %f, stdev: %f, precision: %f\n", N, M1, M2, M2 / sqrt (N));
+    image[0].Mcal = 1000 * M1;
+    image[0].dMcal = 1000 * M2 / sqrt (N);
+  } else {
+    fprintf (stderr, "too few stars\n");
+    image[0].Mcal = 10000;
+    image[0].dMcal = 10000;
+  }
+}
+
+
Index: /tags/start/Ohana/src/addstar/src/check_permissions.c
===================================================================
--- /tags/start/Ohana/src/addstar/src/check_permissions.c	(revision 12606)
+++ /tags/start/Ohana/src/addstar/src/check_permissions.c	(revision 12606)
@@ -0,0 +1,90 @@
+# include "addstar.h"
+
+void check_permissions (char *basefile) {
+  
+  char *c, dir[256], filename[256];
+  struct stat filestat;
+  uid_t uid;
+  gid_t gid;
+  int status, cmode;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to write to directory */
+  sprintf (filename, "%s", basefile);
+  c = strrchr (filename, '/');
+  if (c == (char *) NULL) {
+    strcpy (dir, ".");
+  } else {
+    *c = 0;
+    strcpy (dir, filename);
+  }
+  status = stat (dir, &filestat);
+  if (status == -1) {
+    fprintf (stderr, "directory %s does not exist, creating...\n", dir);
+    cmode = S_IRWXU | S_IRWXG | S_IRWXO;
+    status = mkdir (dir, cmode);
+    if (status == -1) {
+      fprintf (stderr, "ERROR: can't create %s\n", dir);
+      exit (1);
+    }
+  } 
+  status = stat (dir, &filestat);
+  if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRWXU)) ||
+      ((gid == filestat.st_gid) && (filestat.st_mode & S_IRWXG)) || 
+      (filestat.st_mode & S_IRWXO)) {
+  } else {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (1);
+  }
+  
+  /* check permission to write to file */
+  sprintf (filename, "%s", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (1);
+    }
+  }
+  
+  /* check permission to write to backup file */
+  sprintf (filename, "%s~", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (1);
+    }
+  }
+  
+}
+
+/* uses cp only */
+void make_backup (char *filename) {
+
+  int status, cmode;
+  struct stat filestat;
+  char line [256];
+
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, make backup copy */
+    sprintf (line, "cp %s %s~", filename, filename);
+    status = system (line);
+    if (status) {
+      fprintf (stderr, "ERROR: unable to create %s~, exiting\n", filename);
+      exit (1);
+    }
+    cmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    sprintf (line, "%s~", filename);
+    chmod (line, cmode);
+  }
+  
+}
Index: /tags/start/Ohana/src/addstar/src/find_matches.c
===================================================================
--- /tags/start/Ohana/src/addstar/src/find_matches.c	(revision 12606)
+++ /tags/start/Ohana/src/addstar/src/find_matches.c	(revision 12606)
@@ -0,0 +1,513 @@
+# include "addstar.h"
+
+# define IN_CATALOG(R,D) ( \
+((D) >= region[0].DEC[0]) && ((D) < region[0].DEC[1]) && \
+((R) >= region[0].RA[0])  && ((R) < region[0].RA[1]))
+
+void find_matches (GSCRegion *region, Stars *stars, int Nstars, Catalog *catalog, Image *image, Image *pimage, int Nimage) {
+
+  int i, j, k, n, m, N, first_j, found, found0, found1;
+  double X, Y, RADIUS, RADIUS2;
+  float *X1, *Y1, *X2, *Y2, CalM, CalC, *Xs, *Ys;
+  float dX, dY, dR;
+  int *N1, *N2,  *next, *next_miss, last, last_miss;
+  int Nave, NAVE, Nmeas, NMEAS, Nmiss, NMISS, Nmatch;
+  Measure *tmpmeasure;
+  Missing *tmpmissing;
+  Coords tcoords;
+  int Nsecfilt, Nsec, MTIME;
+  short int Mrel, *Mval;
+
+  /** allocate local arrays **/
+  ALLOCATE (X1, float, Nstars);
+  ALLOCATE (Y1, float, Nstars);
+  ALLOCATE (N1, int, Nstars);
+
+  /** allocate local arrays **/
+
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  Nave = catalog[0].Naverage;
+  NAVE = Nave + 1000;
+  ALLOCATE (X2, float, NAVE);
+  ALLOCATE (Y2, float, NAVE);
+  ALLOCATE (N2, int, NAVE);
+  ALLOCATE (Xs, float, NAVE);
+  ALLOCATE (Ys, float, NAVE);
+  ALLOCATE (catalog[0].found, int, NAVE);
+  REALLOCATE (catalog[0].average, Average, NAVE);
+  REALLOCATE (catalog[0].secfilt, SecFilt, NAVE*catalog[0].Nsecfilt);
+  /* for secfilt j and star i, secfilt[i*Nsecfilt+j] */
+
+  Nmatch = 0;
+  Nmeas = catalog[0].Nmeasure;
+  NMEAS = Nmeas + 1000;
+  ALLOCATE (next, int, NMEAS);
+  REALLOCATE (catalog[0].measure, Measure, NMEAS);
+  
+  Nmiss = catalog[0].Nmissing;
+  NMISS = Nmiss + 1000;
+  ALLOCATE (next_miss, int, NMISS);
+  REALLOCATE (catalog[0].missing, Missing, NMISS);
+  
+  /* check on photcode */
+  Nsec = GetPhotcodeNsec (thiscode[0].code);
+
+  /* project onto rectilinear grid with 1 arcsec pixels, sort by X */
+  /* reference for coords is this image */
+  tcoords = image[0].coords;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1 = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2 = tcoords.pc2_1 = 0.0;
+  strcpy (tcoords.ctype, "RA---TAN");
+  
+  for (i = 0; i < Nstars; i++) {
+    fRD_to_XY (&X1[i], &Y1[i], stars[i].R, stars[i].D, &tcoords);
+    N1[i] = i;
+  }
+  if (Nstars > 1) sort_lists (X1, Y1, N1, Nstars);
+  
+  for (i = 0; i < Nave; i++) {
+    fRD_to_XY (&Xs[i], &Ys[i], catalog[0].average[i].R, catalog[0].average[i].D, &image[0].coords);
+    fRD_to_XY (&X2[i], &Y2[i], catalog[0].average[i].R, catalog[0].average[i].D, &tcoords);
+    N2[i] = i;
+    catalog[0].found[N2[i]] = -1;
+  }
+  if (Nave > 1) sort_lists (X2, Y2, N2, Nave);
+
+  /* set up pointers for linked list of measurements */
+  for (i = 0; i < Nmeas - 1; i++) {
+    next[i] = i+1;
+  }
+  next[i] = -1;
+  last = i;
+
+  for (i = 0; i < Nmiss - 1; i++) {
+    next_miss[i] = i+1;
+  }
+  next_miss[i] = -1;
+  last_miss = i;
+
+  /* choose a radius for matches */
+  /* 0.02 corrects cerror to arcsec from storage units */
+  if (DEFAULT_RADIUS == 0) {
+    RADIUS = NSIGMA * 0.02 * image[0].cerror;
+  } else {
+    RADIUS = DEFAULT_RADIUS;
+  }
+  RADIUS2 = RADIUS*RADIUS;
+  /* correct instrumental mags for exposure time */
+  if (image[0].exptime > 0) {
+    MTIME = 2500*log10(image[0].exptime);
+  } else {
+    MTIME = 0;
+  }
+
+  /** find matched stars **/
+  for (i = j = 0; (i < Nstars) && (j < Nave); ) {
+    
+    dX = X1[i] - X2[j];
+    /* fprintf (stderr, "%f   %f %f  %f %f    %f %f  %f %f\n", dX, X1[i], Y1[i], X2[j], Y2[j], stars[i].R, stars[i].D, catalog[0].average[j].R, catalog[0].average[j].D); */
+
+    if (dX <= -2*RADIUS) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*RADIUS) {
+      j++;
+      continue;
+    }
+
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    for (; (dX > -2*RADIUS) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < RADIUS2) {  /* new measurement of this star */
+	Nmatch ++;
+	/** insert star in measurement list */
+	n = N2[j];
+	N = N1[i];
+	m = catalog[0].average[n].offset;  /* first measurement of this star */
+	for (k = 0; k < catalog[0].average[n].Nm - 1; k++)
+	  m = next[m];
+	next[Nmeas] = next[m];
+	next[m] = Nmeas;
+	if (next[Nmeas] == -1) { /* last just was moved */
+	  last = Nmeas;
+	}
+	
+	if (CALIBRATE) {
+	  found = FALSE;
+	  found0 = FALSE;
+	  found1 = FALSE;
+	  m = catalog[0].average[n].offset;  /* first measurement of this star */
+	  for (k = 0; !found && (k < catalog[0].average[n].Nm); k++) {
+	    if (catalog[0].measure[m+k].source == CalReference) { found0 = TRUE; CalM = catalog[0].measure[m+k].M; }
+	    if (catalog[0].measure[m+k].source == CalColor)     { found1 = TRUE; CalC = catalog[0].measure[m+k].M; }
+	    if (found0 && found1) {
+	      found = TRUE;
+	      SaveCalibration (MIN (NO_MAG, 1000*stars[N].M + MTIME), 
+			       MIN (255, stars[N].dM),
+			       CalM, CalC,
+			       image[0].secz, N,
+			       stars[N].R, stars[N].D, Xs[n], Ys[n]);
+	    }
+	  }
+	}
+	      
+	/** add measurements for this star **/
+	catalog[0].measure[Nmeas].dR     = 360000.0*(catalog[0].average[n].R - stars[N].R);
+	catalog[0].measure[Nmeas].dD     = 360000.0*(catalog[0].average[n].D - stars[N].D);
+	catalog[0].measure[Nmeas].M      = MIN (NO_MAG, 1000*stars[N].M + MTIME);
+	catalog[0].measure[Nmeas].Mcal   = image[0].Mcal;
+	catalog[0].measure[Nmeas].dM     = MIN (255, stars[N].dM);  /* error in input files stored in thousandths of mag */
+	catalog[0].measure[Nmeas].t      = image[0].tzero + 1e-4*stars[N].Y*image[0].trate;  /* trate is in 0.1 msec / row */
+	catalog[0].measure[Nmeas].averef = n;
+	catalog[0].measure[Nmeas].source = image[0].source;  /* photometry source */
+	catalog[0].measure[Nmeas].dophot = stars[N].dophot;  
+	catalog[0].measure[Nmeas].flags  = 0;
+	catalog[0].measure[Nmeas].dt     = MTIME;
+
+	catalog[0].measure[Nmeas].Mgal     = MIN (NO_MAG, 1000*stars[N].Mgal + MTIME);
+	catalog[0].measure[Nmeas].airmass  = image[0].secz;
+	catalog[0].measure[Nmeas].FWx      = MIN (NO_MAG, 100*stars[N].fx);
+	catalog[0].measure[Nmeas].fwy      = MIN (255, 100*(stars[N].fy / stars[N].fx));
+	catalog[0].measure[Nmeas].theta    = MIN (255, (255/360)*stars[N].df);
+	/* refers to same number as first measurement */
+	
+	/* check for entries in the secfilt lists */
+	Mrel = catalog[0].measure[Nmeas].M + catalog[0].measure[Nmeas].airmass * thiscode[0].K;
+	Mval = (Nsec == -1) ? &catalog[0].average[n].M : &catalog[0].secfilt[n*Nsecfilt+Nsec].M;
+	if (*Mval == NO_MAG) *Mval = Mrel;
+
+	/*** handle multiple stars */
+	/* this image star matches more than one catalog star */
+	if (stars[N].found > -1) {
+	  catalog[0].measure[stars[N].found].flags |= BLEND_IMAGE;
+	  catalog[0].measure[Nmeas].flags |= BLEND_IMAGE;
+	} 
+	if (stars[N].found == -2) { /* this image star matches a catalog star on a neighboring catalog */
+	  catalog[0].measure[Nmeas].flags |= BLEND_IMAGE_NEIGHBOR;
+	} 
+	if (stars[N].found == -1) { /* this image star matches only this catalog star */
+	  stars[N].found = Nmeas;  /* save first match, in case coincidences are found */
+	}
+	/* this catalog star matches more than one image star */
+	if (catalog[0].found[n] > -1) {
+	  catalog[0].measure[catalog[0].found[n]].flags |= BLEND_CATALOG;
+	  catalog[0].measure[Nmeas].flags |= BLEND_CATALOG;
+	} else {
+	  catalog[0].found[n] = Nmeas;
+	}
+
+	catalog[0].average[n].Nm ++;
+	Nmeas ++;
+	if (Nmeas == NMEAS) {
+	  NMEAS = Nmeas + 1000;
+	  REALLOCATE (next, int, NMEAS);
+	  REALLOCATE (catalog[0].measure, Measure, NMEAS);
+	}
+
+	/* update values of Ro, Do */
+	if (catalog[0].average[n].Nm > 2) {
+	  double R, D, r, d, r2, d2, Npt;
+	  Npt = r = d = r2 = d2 = 0;
+	  m = catalog[0].average[n].offset;  /* first measurement of this star */
+	  for (k = 0; k < catalog[0].average[n].Nm; k++) {
+	    if (catalog[0].measure[m].t == 0) {
+	      m = next[m];
+	      continue;
+	    }
+	    R = catalog[0].measure[m].dR;
+	    D = catalog[0].measure[m].dD;
+	    r += R;
+	    d += D;
+	    r2 += R*R;
+	    d2 += D*D;
+	    m = next[m];
+	    Npt += 1.0;
+	  }
+	  if (Npt > 2) {
+	    r = r / Npt;  /* these are corrections in 1/100 arcsec to RA and DEC */
+	    d = d / Npt;
+	    R = r2 / Npt - r*r;
+	    D = d2 / Npt - d*d;
+	    /* Xp is scatter in position in hundredths of arcsec */
+	    catalog[0].average[n].Xp = sqrt (D + R / SQ(cos(catalog[0].average[n].D*RAD_DEG)));
+	    m = catalog[0].average[n].offset;  /* first measurement of this star */
+	    for (k = 0; k < catalog[0].average[n].Nm; k++) {
+	      catalog[0].measure[m].dR = catalog[0].measure[m].dR - r;
+	      catalog[0].measure[m].dD = catalog[0].measure[m].dD - d;
+	      m = next[m];
+	    }
+	    catalog[0].average[n].R = catalog[0].average[n].R - r / 360000.0;
+	    catalog[0].average[n].D = catalog[0].average[n].D - d / 360000.0;
+	  }
+	}
+      }
+    }
+    j = first_j;
+    i++;
+  }
+
+  /* add reference for undetected catalog stars */
+  for (j = 0; (j < Nave) && !SKIP_MISSED; j++) {
+    n = N2[j];
+    if (catalog[0].found[n] < 0) { 
+      /* should the catalog star be on this image? project into image coords */
+      if (in_image (catalog[0].average[n].R, catalog[0].average[n].D, image)) {
+	/* find last missing meas */
+	if (catalog[0].average[n].Nn < 1) { /* no previous missing obs */
+	  catalog[0].average[n].missing = Nmiss;
+	  next_miss[last_miss] = Nmiss;
+	  next_miss[Nmiss] = -1;
+	  last_miss = Nmiss;
+	} else {
+	  m = catalog[0].average[n].missing;
+	  for (k = 0; k < catalog[0].average[n].Nn - 1; k++)
+	    m = next_miss[m];
+	  next_miss[Nmiss] = next_miss[m];
+	  next_miss[m] = Nmiss;
+	  if (next_miss[Nmiss] == -1) { /* last just was moved */
+	    last_miss = Nmiss;
+	  }
+	}
+	RD_to_XY (&X, &Y, catalog[0].average[n].R, catalog[0].average[n].D, &image[0].coords);	  
+	catalog[0].missing[Nmiss].t  = image[0].tzero + 1e-4*Y*image[0].trate;  /* trate is in 0.1 msec / row */
+	catalog[0].average[n].Nn ++;
+	Nmiss ++;
+	if (Nmiss == NMISS) {
+	  NMISS = Nmiss + 1000;
+	  REALLOCATE (next_miss, int, NMISS);
+	  REALLOCATE (catalog[0].missing, Missing, NMISS);
+	}
+      }
+    }
+  }
+
+  /* incorporate unmatched image stars, if this star is in field of this catalog */
+  for (i = 0; i < Nstars; i++) {
+    N = N1[i];
+    if ((stars[N].found < 0) && IN_CATALOG (stars[N].R, stars[N].D)) {
+      catalog[0].average[Nave].R = stars[N].R;
+      catalog[0].average[Nave].D = stars[N].D;
+      catalog[0].average[Nave].M = NO_MAG;
+      for (j = 0; j < Nsecfilt; j++) {
+	catalog[0].secfilt[Nave*Nsecfilt+j].M  = NO_MAG;
+	catalog[0].secfilt[Nave*Nsecfilt+j].Xm = NO_MAG;
+      }
+      
+      Mrel = catalog[0].measure[Nmeas].M + catalog[0].measure[Nmeas].airmass * thiscode[0].K;
+      Mval = (Nsec == -1) ? &catalog[0].average[Nave].M : &catalog[0].secfilt[Nave*Nsecfilt+Nsec].M;
+      if (*Mval == NO_MAG) *Mval = Mrel;
+
+      catalog[0].average[Nave].Nm        = 1;
+      catalog[0].average[Nave].Nn        = 0;
+      catalog[0].average[Nave].Xp        = NO_MAG;
+      catalog[0].average[Nave].Xm        = NO_MAG;
+      catalog[0].average[Nave].dM        = NO_MAG;
+      catalog[0].average[Nave].offset    = Nmeas;
+      catalog[0].average[Nave].missing   = -1;
+      catalog[0].average[Nave].code      = 0;
+
+      catalog[0].measure[Nmeas].dR       = 0.0;
+      catalog[0].measure[Nmeas].dD       = 0.0;
+      catalog[0].measure[Nmeas].M        = MIN (NO_MAG, 1000.0*stars[N].M + MTIME);
+      catalog[0].measure[Nmeas].Mcal     = image[0].Mcal;
+      catalog[0].measure[Nmeas].dM       = MIN (255, stars[N].dM);
+      catalog[0].measure[Nmeas].t        = image[0].tzero + 1e-4*stars[N].Y*image[0].trate; /* trate is in 0.1 msec / row */
+      catalog[0].measure[Nmeas].averef   = Nave;
+      catalog[0].measure[Nmeas].source   = image[0].source;  /* photometry source */
+      catalog[0].measure[Nmeas].dophot   = stars[N].dophot;  
+      catalog[0].measure[Nmeas].flags    = 0;
+      catalog[0].measure[Nmeas].dt       = MTIME;
+
+      catalog[0].measure[Nmeas].Mgal     = MIN (NO_MAG, 1000.0*stars[N].Mgal + MTIME);
+      catalog[0].measure[Nmeas].airmass  = image[0].secz;
+      catalog[0].measure[Nmeas].FWx      = MIN (0x7fff, 100*stars[N].fx);
+      catalog[0].measure[Nmeas].fwy      = MIN (255, 100*(stars[N].fy / stars[N].fx));
+      catalog[0].measure[Nmeas].theta    = MIN (255, (255/360)*stars[N].df);
+      stars[N].found = Nmeas;
+      next[last] = Nmeas;
+      next[Nmeas] = -1;
+      last = Nmeas;
+      Nmeas ++;
+      if (Nmeas == NMEAS) {
+	NMEAS = Nmeas + 1000;
+	REALLOCATE (next, int, NMEAS);
+	REALLOCATE (catalog[0].measure, Measure, NMEAS);
+      }
+      /** now add references from all previous non-detection observations of this spot on the sky */
+      for (j = 0; (j < Nimage) && !SKIP_MISSED; j++) {
+	if (in_image (catalog[0].average[Nave].R, catalog[0].average[Nave].D, &pimage[j])) {
+	  if (catalog[0].average[Nave].Nn < 1) {
+	    catalog[0].average[Nave].missing = Nmiss;
+	  }
+	  next_miss[last_miss] = Nmiss;
+	  next_miss[Nmiss] = -1;
+	  last_miss = Nmiss;
+	  /* this can now be done exactly */
+	  RD_to_XY (&X, &Y, catalog[0].average[Nave].R, catalog[0].average[Nave].D, &pimage[j].coords);	  
+	  catalog[0].missing[Nmiss].t  = pimage[j].tzero + 1e-4*Y*pimage[j].trate;  /* rough guess at time */
+	  catalog[0].average[Nave].Nn ++;
+	  Nmiss ++;
+	  if (Nmiss == NMISS) {
+	    NMISS = Nmiss + 1000;
+	    REALLOCATE (next_miss, int, NMISS);
+	    REALLOCATE (catalog[0].missing, Missing, NMISS);
+	  }
+  
+	}
+      }
+      Nave ++;
+      if (Nave == NAVE) {
+	NAVE = Nave + 1000;
+	REALLOCATE (catalog[0].average, Average, NAVE);
+	REALLOCATE (catalog[0].secfilt, SecFilt, NAVE*catalog[0].Nsecfilt);
+      }
+    }
+  }
+      
+  free (catalog[0].found);
+  REALLOCATE (catalog[0].average, Average, Nave);
+  REALLOCATE (catalog[0].measure, Measure, Nmeas);
+
+  /* fix order of Measure (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmeasure, Measure, Nmeas);
+  for (i = 0; i < Nave; i++) {
+    n = catalog[0].average[i].offset;
+    catalog[0].average[i].offset = N;
+    for (k = 0; k < catalog[0].average[i].Nm; k++, N++) {
+      tmpmeasure[N] = catalog[0].measure[n]; 
+      tmpmeasure[N].averef = i;
+      n = next[n];
+    }
+  }
+  free (catalog[0].measure);
+  catalog[0].measure = tmpmeasure;
+    
+  /* fix order of Missing (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmissing, Missing, Nmiss);
+  for (i = 0; i < Nave; i++) {
+    if (catalog[0].average[i].Nn > 0) {
+      n = catalog[0].average[i].missing;
+      catalog[0].average[i].missing = N;
+      for (k = 0; k < catalog[0].average[i].Nn; k++, N++) {
+	tmpmissing[N] = catalog[0].missing[n]; 
+	n = next_miss[n];
+      }
+    }
+  }
+  free (catalog[0].missing);
+  catalog[0].missing = tmpmissing;
+
+  /* note stars which have been found in this catalog */
+  for (i = 0; i < Nstars; i++) {
+    if (stars[i].found > -1) {
+      stars[i].found = -2;
+    }
+  }
+
+  catalog[0].Naverage = Nave;
+  catalog[0].Nmeasure = Nmeas;
+  catalog[0].Nmissing = Nmiss;
+  if (VERBOSE) fprintf (stderr, "Nstars, Nave, Nmeas, Nmiss: %d %d %d %d, (%d matches)\n", Nstars, Nave, Nmeas, Nmiss, Nmatch);
+}
+
+int in_image (double r, double d, Image *image) {
+
+  double X, Y;
+
+  RD_to_XY (&X, &Y, r, d, &image[0].coords);
+  if (((X) >= 0) && ((X) < image[0].NX) && ((Y) >= 0) && ((Y) < image[0].NY))
+    return (TRUE);
+  else 
+    return (FALSE);
+
+}
+
+/* 
+   notes:
+
+     for finding if a catalog star is in an image or an image star is in the catalog:
+       
+       catalogs have boundaries defined by RA and DEC, but they may curve in projection
+       images have boundaries which are lines in pixels coords, but curve in RA and DEC
+
+       catalog[0].found[Ncat] but stars[Nstar].found
+
+       */
+
+     
+# ifdef OLDJUNKHERE
+
+ 
+  /* fix measurement list order */
+  for (i = 0; i < Nmeas - 1; i++) {
+    if (next[i] != i + 1) {
+      n0 = next[i];
+      n1 = next[i+1];
+      n2 = next[n0];
+      t = i;
+      while ((t != -1) && (next[t] != i+1))
+	t = next[t];
+      if ((t == -1) || (n2 == i+1)) {
+	t = n2;
+      }
+      next[i] = i+1;
+      next[i+1] = n2;
+      next[n0] = n1;
+      next[t] = n0;
+      tmpmeasure = catalog[0].measure[n0];
+      catalog[0].measure[n0] = catalog[0].measure[i+1];
+      catalog[0].measure[i+1] = tmpmeasure;
+    }
+  }
+ 
+  /* fix offset references */
+  n = (0x00ffffff & catalog[0].measure[0].average);
+  catalog[0].average[n].offset = 0;
+  for (i = 1; i < Nmeas; i++) {
+    if (n != (0x00ffffff & catalog[0].measure[i].average)) {
+      n = (0x00ffffff & catalog[0].measure[i].average);
+      catalog[0].average[n].offset = i;
+    }
+  }
+
+  /* fix missing list order */
+  for (i = 0; i < Nmiss - 1; i++) {
+    if (next_miss[i] != i + 1) {
+      n0 = next_miss[i];
+      n1 = next_miss[i+1];
+      n2 = next_miss[n0];
+      t = i;
+      while ((t != -1) && (next_miss[t] != i+1))
+	t = next_miss[t];
+      if ((t == -1) || (n2 == i+1)) {
+	t = n2;
+      }
+      next_miss[i] = i+1;
+      next_miss[i+1] = n2;
+      next_miss[n0] = n1;
+      next_miss[t] = n0;
+      tmpmissing = catalog[0].missing[n0];
+      catalog[0].missing[n0] = catalog[0].missing[i+1];
+      catalog[0].missing[i+1] = tmpmissing;
+    }
+  }
+ 
+  /* fix offset references */
+  n = (0x00ffffff & catalog[0].measure[0].average);
+  catalog[0].average[n].offset = 0;
+  for (i = 1; i < Nmeas; i++) {
+    if (n != (0x00ffffff & catalog[0].measure[i].average)) {
+      n = (0x00ffffff & catalog[0].measure[i].average);
+      catalog[0].average[n].offset = i;
+    }
+  }
+
+# endif
Index: /tags/start/Ohana/src/addstar/src/gcatalog.c
===================================================================
--- /tags/start/Ohana/src/addstar/src/gcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/addstar/src/gcatalog.c	(revision 12606)
@@ -0,0 +1,45 @@
+# include "addstar.h"
+
+int gcatalog (Catalog *catalog) {
+  
+  int Nsecfilt;
+  char mode;
+
+  /* read catalog header */
+  mode = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+  if (!load_catalog (catalog, mode, VERBOSE)) {
+    fprintf (stderr, "ERROR: failure loading catalog\n");
+    exit (1);
+  }
+
+  /* check Nsecfile value, update if needed */
+  Nsecfilt = GetPhotcodeNsecfilt ();
+  if (catalog[0].Nsecfilt < Nsecfilt) {
+
+    int i, j, Nextra, in, out;
+    SecFilt *insec, *outsec;
+
+    Nextra = Nsecfilt - catalog[0].Nsecfilt;
+    insec = catalog[0].secfilt;
+    ALLOCATE (outsec, SecFilt, catalog[0].Naverage * Nsecfilt);
+    for (in = out = i = 0; i < catalog[0].Naverage; i++) {
+      for (j = 0; j < catalog[0].Nsecfilt; j++, in++, out++) {
+	outsec[out].M = insec[in].M;
+	outsec[out].Xm = insec[in].Xm;
+      }
+      for (j = 0; j < Nextra; j++, out++) {
+	outsec[out].M = NO_MAG;
+	outsec[out].Xm = NO_MAG;
+      }
+    }
+    free (catalog[0].secfilt);
+    catalog[0].secfilt = outsec;
+    catalog[0].Nsecfilt = Nsecfilt;
+  }
+
+  if (catalog[0].Nsecfilt > Nsecfilt) {
+    fprintf (stderr, "ERROR: can't reduce number of secondary filters\n");
+    exit (1);
+  }
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/addstar/src/gimages.c
===================================================================
--- /tags/start/Ohana/src/addstar/src/gimages.c	(revision 12606)
+++ /tags/start/Ohana/src/addstar/src/gimages.c	(revision 12606)
@@ -0,0 +1,174 @@
+# include "addstar.h"
+double opening_angle ();
+
+Image *gimages (FILE *f, Image *image, int *Npimage) {
+  
+  int i, j, k, Nimage, addtolist, size;
+  int NTIMAGE, Ntimage, ntimage;
+  int NPIMAGE, npimage;
+  Image *timage, *pimage;
+  Coords tcoords;
+  Header header;
+  double r, d;
+  double Xi[5], Yi[5], Xo[5], Yo[5];  /* image and original corners */
+  double zeropt;
+  struct stat filestatus;
+  
+  fseek (f, 0, SEEK_SET);
+
+  /* read header */
+  if (!fits_load_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "ERROR: can't read image catalog %s\n", ImageCat);
+    exit (1);
+  }
+
+  fits_scan (&header, "ZERO_PT", "%lf", 1, &zeropt);
+  if (fabs (ZeroPt - zeropt) > 1e-4) {
+    fprintf (stderr, "ERROR: zero point in image (%f:%s) inconsistent with zero point in catalog (%f)\n",
+	     ZeroPt, image[0].name, zeropt);
+    exit (1);
+  }
+
+  /* project onto rectilinear grid with 1 arcsec pixels */
+  /* we keep the original crpix1,2 and crref1,2 */
+  tcoords = image[0].coords;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1 = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2 = tcoords.pc2_1 = 0.0;
+  strcpy (tcoords.ctype, "RA---TAN");
+
+  /* define original corners */
+  Xo[0] = 0;           Yo[0] = 0;
+  Xo[1] = image[0].NX; Yo[1] = 0;
+  Xo[2] = image[0].NX; Yo[2] = image[0].NY;
+  Xo[3] = 0;           Yo[3] = image[0].NY;
+  Xo[4] = 0;           Yo[4] = 0;  /* so we can make a loop easily */
+  for (j = 0; j < 5; j++) {
+    XY_to_RD (&r, &d, Xo[j], Yo[j], &image[0].coords);
+    RD_to_XY (&Xo[j], &Yo[j], r, d, &tcoords);
+  }
+  
+  /* advance to data segment */ 
+  fseek (f, header.size, SEEK_SET); 
+
+  Nimage = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+  /* check that file size makes sense */
+  if (stat (ImageCat, &filestatus) == -1) {
+    fprintf (stderr, "ERROR: failed to get status of image catalog\n");
+    exit (1);
+  }
+  size = Nimage*sizeof(Image) + header.size;
+  if (size != filestatus.st_size) {
+    int Ndata;
+    Ndata = (filestatus.st_size - header.size) / sizeof (Image);
+    fprintf (stderr, "ERROR: image catalog has inconsistent size\n");
+    fprintf (stderr, "header: %d, data: %d\n", Nimage, Ndata);
+    if (!FORCE_READ) Shutdown ();
+    Nimage = Ndata;
+  } 
+
+  NTIMAGE = 100;
+  ALLOCATE (timage, Image, NTIMAGE);
+
+  npimage = 0;
+  NPIMAGE = 20;
+  ALLOCATE (pimage, Image, NPIMAGE);
+
+  for (Ntimage = 0; Ntimage < Nimage; Ntimage += ntimage) {
+    ntimage = Fread (timage, sizeof(Image), NTIMAGE, f, "image");
+    for (i = 0; i < ntimage; i++) {
+      addtolist = FALSE;
+      /* define image corners */
+      Xi[0] = 0;            Yi[0] = 0;
+      Xi[1] = timage[i].NX; Yi[1] = 0;
+      Xi[2] = timage[i].NX; Yi[2] = timage[i].NY;
+      Xi[3] = 0;            Yi[3] = timage[i].NY;
+      Xi[4] = 0;            Yi[4] = 0;  /* so we can make a loop easily */
+      /* transform to tcoords */
+      for (j = 0; j < 5; j++) {
+	XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+	RD_to_XY (&Xi[j], &Yi[j], r, d, &tcoords);
+      }
+      /* check if any edges cross */
+      for (j = 0; (j < 4) && !addtolist; j++) {
+	for (k = 0; (k < 4) && !addtolist; k++) {
+	  addtolist |= edge_check (&Xi[j], &Yi[j], &Xo[k], &Yo[k]);
+	}
+      }
+      if (addtolist) {
+	pimage[npimage] = timage[i];
+	npimage ++;
+	if (npimage == NPIMAGE) {
+	  NPIMAGE += 20;
+	  REALLOCATE (pimage, Image, NPIMAGE);
+	}
+      }
+    }
+
+    if (ntimage == 0) {
+      fprintf (stderr, "ERROR: expected %d images, only found %d\n", Nimage, Ntimage);
+      exit (1);
+    }
+  }
+
+  if (VERBOSE) fprintf (stderr, "found %d overlapping images\n", npimage);
+
+  *Npimage = npimage;
+  return (pimage);
+
+}
+  
+int edge_check (double *x1, double *y1, double *x2, double *y2) {
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+double opening_angle (double x1, double y1, double x2, double y2, double x3, double y3) {
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
+
Index: /tags/start/Ohana/src/addstar/src/gregions.c
===================================================================
--- /tags/start/Ohana/src/addstar/src/gregions.c	(revision 12606)
+++ /tags/start/Ohana/src/addstar/src/gregions.c	(revision 12606)
@@ -0,0 +1,53 @@
+# include "addstar.h"
+
+GSCRegion *gregions (Image *image, int *Nregions) {
+  
+  GSCRegion *region;
+  FILE *f;
+  double x, y;
+  double dec, ra;
+  int i, j, done, nregion, NREGION;
+  
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find GSC region file %s\n", GSCFILE);
+    exit (1);
+  }
+  
+  /* find regions at image corners */
+  NREGION = 10;
+  ALLOCATE (region, GSCRegion, NREGION);
+  nregion = 0;
+
+  /* look for new regions on grid across image */ 
+  for (x = 0.0; x <= 1.0; x+=0.25) {
+    for (y = 0.0; y <= 1.0; y+=0.25) {
+      XY_to_RD (&ra, &dec, image[0].NX*(1.1*x - 0.05), image[0].NY*(1.1*y - 0.05), &image[0].coords);
+      aregion (&region[nregion], f, ra, dec);
+      done = FALSE;
+      for (j = 0; (j < nregion) && !done; j++) {
+	if (!strcmp (region[nregion].filename, region[j].filename)) {
+	  nregion --;
+	  done = TRUE;
+	}
+      }
+      nregion ++;
+      if (nregion == NREGION) {
+	NREGION += 10;
+	REALLOCATE (region, GSCRegion, NREGION);
+      }
+    }
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "found %d region files:\n", nregion);
+    for (i = 0; i < nregion; i++) {
+      fprintf (stderr, "  %d %s\n", i, region[i].filename);
+    }
+  }
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (region);
+  
+}
Index: /tags/start/Ohana/src/addstar/src/gstars.c
===================================================================
--- /tags/start/Ohana/src/addstar/src/gstars.c	(revision 12606)
+++ /tags/start/Ohana/src/addstar/src/gstars.c	(revision 12606)
@@ -0,0 +1,271 @@
+# include "addstar.h"
+# define D_NSTARS 1000
+# define BYTES_STAR 66
+# define BLOCK 1000
+#include <sys/time.h>
+#include <time.h>
+
+Stars *gstars (char *file, int *NSTARS, Image *image) {
+
+  FILE *f;
+  Header header;
+  int j, N, Ninstar;
+  int nbytes, Nbytes;
+  Stars *stars;
+  char *buffer, *c, *c2, photcode[64];
+  double tmp;
+  int done, doneread, Nskip, Nextra, itmp;
+
+  if (!fits_read_header (file, &header)) {
+    fprintf (stderr, "ERROR: can't read header for %s\n", file);
+    exit (1);
+  }
+
+  /* open file */
+  f = fopen (file, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't read data from %s\n", file);
+    exit (1);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* find image rootname */
+  c = strrchr (file, 0x2f);
+  if (c == (char *) NULL) {
+    strcpy (image[0].name, file);
+  } else { 
+    strcpy (image[0].name, (c+1));
+  }
+
+  /* get astrometry information */
+  if (!GetCoords (&image[0].coords, &header)) {
+    fprintf (stderr, "ERROR: no astrometric solution in header\n");
+    exit (1);
+  }
+  while (image[0].coords.crval1 < 0) image[0].coords.crval1 += 360.0;
+  while (image[0].coords.crval1 > 360.0) image[0].coords.crval1 -= 360.0;
+  itmp = 0;
+  fits_scan (&header, "NASTRO",   "%d", 1, &itmp);
+  if ((itmp == 0) && !ACCEPT_ASTROM) {
+    fprintf (stderr, "ERROR: bad astrometric solution in header\n");
+    exit (1);
+  }
+    
+  /* CERROR in data file is in arcsec */
+  if (!fits_scan (&header, "CERROR",   "%lf", 1, &tmp)) tmp = 1.0;
+  image[0].cerror = tmp * 50.0;
+  fits_scan (&header, "NAXIS1",   "%hd", 1, &image[0].NX); 
+  fits_scan (&header, "NAXIS2",   "%hd", 1, &image[0].NY);
+ 
+  /* get photcode from header */
+  if (thiscode == NULL) {
+    fits_scan (&header, "PHOTCODE", "%s", 1, photcode);
+    thiscode = GetPhotcodebyName (photcode);
+  }
+  if (thiscode == NULL) {
+    fprintf (stderr, "ERROR: photcode %s not found in photcode table\n", photcode);
+    exit (1);
+  }
+  image[0].source = thiscode[0].code;
+
+  image[0].NX -= XOVERSCAN;
+  image[0].NY -= YOVERSCAN;
+  fits_scan (&header, ExptimeKeyword,  "%lf", 1, &tmp);
+  image[0].exptime = tmp;
+  
+  tmp = 0;
+  /* fits_scan (&header, "APMIFIT",  "%lf", 1, &tmp); */
+  image[0].apmifit = tmp * 1000.0;
+
+  tmp = 0;
+  /* fits_scan (&header, "dAPMIFIT", "%lf", 1, &tmp); */
+  image[0].dapmifit = tmp * 1000.0;
+
+  tmp = 0;
+  fits_scan (&header, "FLIMIT",   "%lf", 1, &tmp);
+  image[0].detection_limit = tmp * 10.0;
+
+  tmp = 0;
+  fits_scan (&header, "FSATUR",   "%lf", 1, &tmp);
+  image[0].saturation_limit = tmp * 10.0;
+
+  tmp = 0;
+  fits_scan (&header, "FWHM_X",   "%lf", 1, &tmp);
+  image[0].fwhm_x = tmp * 25.0 * image[0].coords.cdelt1 * 3600.0;
+
+  tmp = 0;
+  fits_scan (&header, "FWHM_Y",   "%lf", 1, &tmp);
+  image[0].fwhm_y = tmp * 25.0 * image[0].coords.cdelt1 * 3600.0;
+
+  if (!fits_scan (&header, "TZERO",   "%d",  1, &image[0].tzero)) {
+    image[0].tzero = parse_time (&header);
+  }
+
+  tmp = 0;
+  fits_scan (&header, "TRATE",   "%lf", 1, &tmp);
+  image[0].trate = 10000 * tmp;
+
+  tmp = 0;
+  fits_scan (&header, AirmassKeyword, "%lf", 1, &tmp);
+  image[0].secz = MIN (NO_MAG, 1000*tmp);
+
+  if (!fits_scan (&header, CCDNumKeyword, "%d", 1, &itmp)) {
+    image[0].ccdnum = 0xff;
+  } else {
+    image[0].ccdnum = itmp;
+  }
+
+  fits_scan (&header, "ZERO_PT", "%lf", 1, &ZeroPt);
+
+  /* secz is in units milli-airmass */
+  image[0].Mcal = 0.0;
+  image[0].code = 0;
+  image[0].Xm   = NO_MAG;
+  bzero (image[0].dummy, sizeof(image[0].dummy));
+
+  /* find expected number of stars */
+  fits_scan (&header, "NSTARS", "%d", 1, &image[0].nstar);
+  if (image[0].nstar == 0) {
+    fprintf (stderr, "ERROR: can't get NSTARS from header\n");
+    exit (1);
+  }
+  ALLOCATE (stars, Stars, image[0].nstar);
+
+  /* load in stars by blocks of 1000 */
+  N = 0;
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR) + 1);
+  buffer[BLOCK*BYTES_STAR] = 0;
+  Nextra = 0;
+  doneread = FALSE;
+  while (!doneread) {
+    Nbytes = BYTES_STAR * BLOCK - Nextra;
+    nbytes = Fread (&buffer[Nextra], 1, Nbytes, f, "char");
+    if (nbytes == 0) {
+      doneread = TRUE;
+      continue;
+    }
+    nbytes += Nextra;
+    /* check line-by-line integrity */
+    c = buffer;
+    done = FALSE;
+    while ((c < buffer + nbytes) && (!done)) { 
+      for (c2 = c; *c2 == '\n'; c2++);
+      if (c2 > c) { /* extra return chars */
+	memmove (c, c2, (int)(buffer + nbytes - c2));
+	Nskip = c2 - c;
+	nbytes -= Nskip;
+	bzero (buffer + nbytes, Nskip);
+	if (VERBOSE) fprintf (stderr, "deleted %d extra return chars\n", Nskip);
+      }
+      c2 = strchr (c, '\n');
+      if (c2 == (char *) NULL) {
+	done = TRUE;	
+	continue;
+      }
+      c2++;
+      if ((c2 - c) != BYTES_STAR) { /* bad line, delete it */
+	memmove (c, c2, (int)(buffer + nbytes - c2));
+	Nskip = c2 - c;
+	nbytes -= Nskip;
+	bzero (buffer + nbytes, Nskip);
+	if (VERBOSE) fprintf (stderr, "deleted line, %d extra chars\n", Nskip);
+      } else {
+	c = c2;
+      }
+    }
+    Ninstar = nbytes / BYTES_STAR;
+    Nextra = nbytes % BYTES_STAR;
+    for (j = 0; j < Ninstar; j++, N++) {
+      dparse (&stars[N].X,  1, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].Y,  2, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].M,  3, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].dM, 4, &buffer[j*BYTES_STAR]);
+      /* allow for some dynamic filtering of star list */
+      if (stars[N].dM > 1000.0 / SNLIMIT) { N--; continue; }
+      if (XMAX && (stars[N].X > XMAX))    { N--; continue; }
+      if (XMIN && (stars[N].X < XMIN))    { N--; continue; }
+      if (YMAX && (stars[N].Y > YMAX))    { N--; continue; }
+      if (YMIN && (stars[N].Y < YMIN))    { N--; continue; }
+
+      dparse (&tmp,         5, &buffer[j*BYTES_STAR]);
+      stars[N].dophot = tmp;
+      dparse (&stars[N].Mgal, 7, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].Map,  8, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].fx,   9, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].fy,  10, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].df,  11, &buffer[j*BYTES_STAR]);
+
+      XY_to_RD (&stars[N].R, &stars[N].D, stars[N].X, stars[N].Y, &image[0].coords);
+      while (stars[N].R < 0.0) stars[N].R += 360.0;
+      while (stars[N].R >= 360.0) stars[N].R -= 360.0;
+      stars[N].found = -1;
+    }
+  }
+
+  image[0].nstar = N;
+  REALLOCATE (stars, Stars, image[0].nstar);
+  if (VERBOSE) fprintf (stderr, "read %d stars from target file\n", image[0].nstar);
+  *NSTARS = image[0].nstar;
+
+  return (stars);
+}
+
+
+
+
+# if (0)
+  /* left over fraction of a block */
+  nbytes = Fread (buffer, 1, (Nbytes % (BLOCK*BYTES_STAR)), f, "char");
+  if (nbytes != (Nbytes % (BLOCK*BYTES_STAR))) {
+    fprintf (stderr, "ERROR: failed to read in stars (2)\n");
+    exit (1);
+  }
+  /* check line-by-line integrity */
+  Nnew = 0;
+  c = buffer;
+  done = FALSE;
+  while ((c < buffer + nbytes) && (!done)) { 
+    for (c2 = c; *c2 == '\n'; c2++);
+    if (c2 > c) { /* extra return chars */
+      memmove (c, c2, (int)(buffer + nbytes - c2));
+      Nnew += c2 - c;
+      fprintf (stderr, "deleting %d extra return chars\n", (int)(c2-c));
+    }
+    c2 = strchr (c, '\n');
+    if (c2 == (char *) NULL) {
+      if (Nnew > 0) {
+	nnew = Fread (&buffer[nbytes-Nnew], 1, Nnew, f, "char");
+	if (nnew != Nnew) {
+	  fprintf (stderr, "ERROR: failed to read in stars (1)\n");
+	  exit (1);
+	}
+      } else {
+	done = TRUE;	
+      }
+      continue;
+    }
+    c2++;
+    if ((c2 - c) != BYTES_STAR) {
+      /* this is a bad line, delete it, adjust data in buffer, 
+	 and be ready to read the rest of the last line */
+      memmove (c, c2, (int)(buffer + nbytes - c2));
+      Nnew += c2 - c;
+      fprintf (stderr, "deleting bad line with %d chars\n", (int)(c2-c));
+    } else {
+      c = c2;
+    }
+  }
+  for (j = 0; j < nbytes / BYTES_STAR; j++, nstar++, N++) {
+    dparse (&stars[N].X, 1, &buffer[j*BYTES_STAR]);
+    dparse (&stars[N].Y, 2, &buffer[j*BYTES_STAR]);
+    dparse (&stars[N].M, 3, &buffer[j*BYTES_STAR]);
+    dparse (&stars[N].dM, 4, &buffer[j*BYTES_STAR]);
+    XY_to_RD (&stars[N].R, &stars[N].D, stars[N].X, stars[N].Y, &image[0].coords);
+    while (stars[N].R < 0.0) stars[N].R += 360.0;
+    while (stars[N].R >= 360.0) stars[N].R -= 360.0;
+    dparse (&tmp, 5, &buffer[j*BYTES_STAR]);
+    stars[N].dophot = tmp;
+    stars[N].found = -1;
+  }
+
+# endif
Index: /tags/start/Ohana/src/addstar/src/mkcatalog.c
===================================================================
--- /tags/start/Ohana/src/addstar/src/mkcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/addstar/src/mkcatalog.c	(revision 12606)
@@ -0,0 +1,38 @@
+# include "addstar.h"
+# include <time.h>
+
+void mkcatalog (GSCRegion *region, Catalog *catalog) {
+  
+  char filename[64], line[64];
+  struct tm *local;
+  struct timeval now;
+
+  if (VERBOSE) fprintf (stderr, "new catalog file: %s\n", region[0].filename);
+  if (!fits_read_header (CatTemplate, &catalog[0].header)) {
+    fprintf (stderr, "ERROR: can't find template header %s\n", CatTemplate);
+    exit (1);
+  }
+  
+  /* assign header values for RA, DEC, DATE, etc */
+  fits_modify (&catalog[0].header, "RA0", "%lf", 1, region[0].RA[0]);
+  fits_modify (&catalog[0].header, "DEC0", "%lf", 1, region[0].DEC[0]);
+  fits_modify (&catalog[0].header, "RA1", "%lf", 1, region[0].RA[1]);
+  fits_modify (&catalog[0].header, "DEC1", "%lf", 1, region[0].DEC[1]);
+  gettimeofday (&now, NULL);
+  local = localtime (&now.tv_sec);
+  sprintf (line, "%02d/%02d/%02d", local[0].tm_year, local[0].tm_mon + 1, local[0].tm_mday); 
+  fits_modify (&catalog[0].header, "DATE", "%s", 1, line);
+  strcpy (filename, CatTemplate);
+  ALLOCATE (catalog[0].average, Average, 1);
+  ALLOCATE (catalog[0].measure, Measure, 1);
+  ALLOCATE (catalog[0].missing, Missing, 1);
+  catalog[0].Naverage = catalog[0].Nmeasure = catalog[0].Nmissing = 0;
+
+  /* setup secondary filters to match photcodes */
+  ALLOCATE (catalog[0].secfilt, SecFilt, 1);
+  catalog[0].Nsecfilt = GetPhotcodeNsecfilt ();
+
+  /* Nsecfilt is number of filters.  Number of entries in array is
+     Nsecfilt * Naverage.  At this point, N entries == 0 */
+
+}
Index: /tags/start/Ohana/src/addstar/src/parse_time.c
===================================================================
--- /tags/start/Ohana/src/addstar/src/parse_time.c	(revision 12606)
+++ /tags/start/Ohana/src/addstar/src/parse_time.c	(revision 12606)
@@ -0,0 +1,126 @@
+# include "addstar.h"
+
+int parse_time (Header *header) {
+
+  double jd;
+  int Ny, Nf, mode;
+  int Nsec, hour, min, sec, year, month, day;
+  char *py, *pm, *pd, *c;
+  char line[256];
+
+  /* we want to find JD or MJD to get Nsec (seconds since 01/01/1970) */
+
+  /* try JD first */
+  if (strcasecmp (JDKeyword, "NONE")) {
+    uppercase (JDKeyword);
+    fits_scan (header, JDKeyword, "%lf", 1, &jd);
+    Nsec = (jd - 2440587.5)*86400;
+    return (Nsec);
+  }
+
+  /* try MJD next */
+  if (strcasecmp (MJDKeyword, "NONE")) {
+    uppercase (MJDKeyword);
+    fits_scan (header, MJDKeyword, "%lf", 1, &jd);
+    Nsec = (jd - 40587.0)*86400;
+    return (Nsec);
+  }
+    
+  /* get UT and DATE */
+  uppercase (UTKeyword);
+  fits_scan (header, UTKeyword, "%s", 1, line);
+  /* remove ':' characters */
+  for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
+  sscanf (line, "%d %d %d", &hour, &min, &sec);
+
+  /* parse mode line */
+  uppercase (DateMode);
+  for (Ny = 0, c = strchr (DateMode, 'Y'); c != (char ) NULL; c = strchr (c + 1, 'Y'), Ny++);
+  if ((Ny != 2) && (Ny != 4)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  py = strchr (DateMode, 'Y');
+  pm = strchr (DateMode, 'M');
+  pd = strchr (DateMode, 'D');
+  if ((py == (char *) NULL) || (pm == (char *) NULL) || (pd == (char *) NULL)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  if ((py > pm) && (py < pd)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  if ((py > pd) && (py < pm)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  mode = 0;
+  if ((py < pm) && (pm < pd)) { mode = 1; }  /* yyyy-mm-dd */
+  if ((py < pm) && (pm > pd)) { mode = 2; }  /* yyyy-dd-mm */
+  if ((py > pm) && (pm < pd)) { mode = 3; }  /* mm-dd-yyyy */
+  if ((py > pm) && (pm > pd)) { mode = 4; }  /* dd-mm-yyyy */
+  if (!mode) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+
+  /* parse date entry */
+  uppercase (DateKeyword);
+  fits_scan (header, DateKeyword, "%s",  1, line);
+  /* remove possible separators: ':', '/' '.', '-' */
+  for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
+  for (c = strchr (line, 0x2f); c != (char *) NULL; c = strchr (line, 0x2f)) { *c = ' '; }
+  for (c = strchr (line, 0x2e); c != (char *) NULL; c = strchr (line, 0x2e)) { *c = ' '; }
+  for (c = strchr (line, 0x2d); c != (char *) NULL; c = strchr (line, 0x2d)) { *c = ' '; }
+
+  switch (mode) {
+  case 1:
+    Nf = sscanf (line, "%d %d %d", &year, &month, &day);
+    break;
+  case 2:
+    Nf = sscanf (line, "%d %d %d", &year, &day, &month);
+    break;
+  case 3:
+    Nf = sscanf (line, "%d %d %d", &month, &day, &year);
+    break;
+  case 4:
+    Nf = sscanf (line, "%d %d %d", &day, &month, &year);
+    break;
+  }
+  if (Nf != 3) {
+    fprintf (stderr, "error in date entry (%s) or DATE-MODE format (%s)\n", line, DateMode);
+    exit (1);
+  }
+
+  if (year > 1000) {
+    if (Ny == 2) {
+      fprintf (stderr, "warning: mode line claims 2 digit year, but 4 digit year found\n");
+    }
+  } else {
+    if (Ny == 4) {
+      fprintf (stderr, "warning: mode line claims 4 digit year, but 2 digit year found\n");
+    }
+    if (year < 50) year += 100;
+    year += 1900;
+  }    
+
+  /* convert yy.mm.dd hh.mm.ss to Nsec since 1970 (jd = 2440587.5) */
+  /* note that in this section, tm_mon has range 1-12, unlike for gmtime () */
+  jd = day - 32075 + (int)(1461*(year + 4800 + (int)(((month)-14)/12))/4)
+    + (int)(367*((month) - 2 - (int)(((month) - 14)/12)*12)/12)
+    - (int)(3*(int)((year + 4900 + (int)(((month) - 14)/12))/100)/4) - 0.5;
+  /* jd is the julian day of the whole day only not the time */
+  Nsec = (jd - 2440587.5)*86400 + 3600.0*hour + min*60.0 + sec;
+  
+  return (Nsec);
+
+}
+
+void uppercase (char *string) {
+
+  int i;
+    
+  for (i = 0; i < strlen (string); i++) string[i] = toupper (string[i]);
+
+}
Index: /tags/start/Ohana/src/addstar/src/sort_lists.c
===================================================================
--- /tags/start/Ohana/src/addstar/src/sort_lists.c	(revision 12606)
+++ /tags/start/Ohana/src/addstar/src/sort_lists.c	(revision 12606)
@@ -0,0 +1,80 @@
+
+void sort_lists (float *X, float *Y, int *S, int N) {
+
+  int l,j,ir,i;
+  double tX, tY, tS;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    S[i] = tS;
+  }
+}
+
+void fsort (float *X, int N) {
+
+  int l,j,ir,i;
+  float tX;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+  }
+}
Index: /tags/start/Ohana/src/addstar/src/wcatalog.c
===================================================================
--- /tags/start/Ohana/src/addstar/src/wcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/addstar/src/wcatalog.c	(revision 12606)
@@ -0,0 +1,35 @@
+# include "addstar.h"
+
+void wcatalog (Catalog *catalog) {
+  
+  /* we'll leave these for now, but they are LONEOS specific */
+  fits_modify (&catalog[0].header, "MARKSTAR", "%t", 1, FALSE);
+  fits_modify (&catalog[0].header, "ADDUSNO", "%t", 1, FALSE);
+  fits_modify (&catalog[0].header, "MARKROCK", "%t", 1, FALSE);
+
+  if (!save_catalog (catalog, VERBOSE)) {
+    fprintf (stderr, "ERROR: failure saving catalog\n");
+    exit (1);
+  }
+
+  /* free, initialize data structures */
+
+  if (catalog[0].Naverage) {
+    free (catalog[0].average); 
+    catalog[0].Naverage = 0;
+  }
+  if (catalog[0].Nmeasure) {
+    free (catalog[0].measure); 
+    catalog[0].Nmeasure = 0;
+  }
+  if (catalog[0].Nmissing) {
+    free (catalog[0].missing); 
+    catalog[0].Nmissing = 0;
+  }
+  if (catalog[0].Nsecfilt) {
+    free (catalog[0].secfilt); 
+    catalog[0].Nsecfilt = 0;
+  }
+  fits_free_header (&catalog[0].header);
+}
+
Index: /tags/start/Ohana/src/addstar/src/wimage.c
===================================================================
--- /tags/start/Ohana/src/addstar/src/wimage.c	(revision 12606)
+++ /tags/start/Ohana/src/addstar/src/wimage.c	(revision 12606)
@@ -0,0 +1,52 @@
+# include "addstar.h"
+
+void wimage (FILE *f, int dbstate, Image *image, int Nstars) {
+  
+  int Nimages, status;
+  Header header;
+
+  /* place file pointer at beginning of file */
+  fseek (f, 0, SEEK_SET);
+
+  if (dbstate == LCK_EMPTY) {
+    if (VERBOSE) fprintf (stderr, "can't find %s, creating a new one\n", ImageCat);
+    if (!fits_read_header (ImageTemplate, &header)) {
+      fprintf (stderr, "ERROR: can't find template header %s\n", ImageTemplate);
+      exit (1);
+    }
+    /* assign Zero Point provided by first image in dB */
+    fits_modify (&header, "ZERO_PT", "%lf", 1, ZeroPt);
+  } else {
+    if (!fits_load_header (f, &header)) {
+      fprintf (stderr, "ERROR: can't read image header %s\n", ImageCat);
+      exit (1);
+    }
+  }
+  
+  Nimages = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimages);
+  Nimages ++;
+  fits_modify (&header, "NIMAGES", "%d", 1, Nimages);
+
+  /* position to begining of file to write header */
+  fseek (f, 0, SEEK_SET);
+  status = Fwrite (header.buffer, 1, header.size, f, "char");
+  if (status != header.size) {
+    fprintf (stderr, "ERROR: failed writing data to image header\n");
+    exit (1);
+  }
+
+  /* position to end of file for new image data */
+  fseek (f, 0, SEEK_END);
+  status = Fwrite (image, sizeof(Image), 1, f, "image");
+  if (status != 1) {
+    fprintf (stderr, "ERROR: failed writing data to image catalog\n");
+    exit (1);
+  }
+}
+
+/* the image we add in this routine is always a new image.  
+   We only need to do two things:
+     1) append the data for the image to the end of the file
+     2) update the NIMAGES field in the header (which means, read in header, re-write)
+ */
Index: /tags/start/Ohana/src/addusno/Makefile
===================================================================
--- /tags/start/Ohana/src/addusno/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/addusno/Makefile	(revision 12606)
@@ -0,0 +1,65 @@
+include ../../Configure
+CC      =       gcc -g  # override this for now for minimal test
+HOME 	=	$(ROOT)/src/addusno
+CONFIG  =	$(ROOT)/config
+PROGRAM =       addusno
+
+fix: addusno needs to be brought up-to-date with other addstar/addrefs functions
+install: fix
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#  
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lFITS -lohana -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS)
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+ADDUSNO = \
+$(SRC)/addusno.$(ARCH).o 	$(SRC)/gcatalog.$(ARCH).o   \
+$(SRC)/gcatstats.$(ARCH).o 	$(SRC)/getusno.$(ARCH).o    \
+$(SRC)/find_matches.$(ARCH).o 	$(SRC)/wcatalog.$(ARCH).o   \
+$(SRC)/sort_lists.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o 	\
+$(SRC)/check_lockfile.$(ARCH).o \
+$(SRC)/find_proper.$(ARCH).o 	$(SRC)/reset_catalog.$(ARCH).o 	\
+$(SRC)/check_permissions.$(ARCH).o
+
+OBJ = $(ADDUSNO)
+
+default: $(PROGRAM)
+
+$(ADDUSNO): $(INC)/addusno.h
+
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:	
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
+
+
Index: /tags/start/Ohana/src/addusno/include/addstar.h
===================================================================
--- /tags/start/Ohana/src/addusno/include/addstar.h	(revision 12606)
+++ /tags/start/Ohana/src/addusno/include/addstar.h	(revision 12606)
@@ -0,0 +1,14 @@
+# include <ohana.h>
+# include <loneos.h>
+
+/* global variables set in parameter file */
+char   ImageCat[256];
+char   ImageTemplate[256];
+char   CatTemplate[256];
+char   GSCFILE[256];
+char   CATDIR[256];
+double NSIGMA;
+double ALPHA;
+int    VERBOSE;
+int    XOVERSCAN, YOVERSCAN;
+int    NEWPHOTCODE, PHOTCODE;
Index: /tags/start/Ohana/src/addusno/include/addusno.h
===================================================================
--- /tags/start/Ohana/src/addusno/include/addusno.h	(revision 12606)
+++ /tags/start/Ohana/src/addusno/include/addusno.h	(revision 12606)
@@ -0,0 +1,46 @@
+# include <ohana.h>
+# include <loneos.h>
+
+/* global variables set in parameter file */
+char   CATDIR[256];
+int    VERBOSE;
+int    RESET;
+double RADIUS;
+double PROPER;
+int    USNO_RED;
+int    USNO_BLUE;
+char   CDROM[256];
+int    FORCE_RUN;
+char   PhotCodeFile[256];
+
+typedef struct {
+  double X;
+  double Y;
+  double R;
+  double D;
+  double M, dM;
+  char   dophot;
+  double sky;
+  double fx, fy, df;
+  double Mgal, Map;
+  int found;
+} Stars;
+
+typedef struct {
+  Coords coords;
+  float *X, *Y;
+  int *N;
+  double RA[2], DEC[2];
+  double Area, density, spacing;
+} CatStats;
+
+typedef struct {
+  double R, D;
+  double r, b;
+} USNOdata;
+
+typedef struct {
+  int *match;
+  float *X, *Y;
+  int *N;
+} USNOstats;
Index: /tags/start/Ohana/src/addusno/src/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/ConfigInit.c	(revision 12606)
@@ -0,0 +1,25 @@
+# include "addusno.h"
+
+ConfigInit (int argc, char **argv) {
+
+  char *config, *file;
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (&argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  ScanConfig (config, "PHOTCODE_FILE",         "%s",  0, PhotCodeFile);
+  ScanConfig (config, "USNO_RADIUS",           "%lf", 0, &RADIUS);
+  ScanConfig (config, "USNO_PROPER",           "%lf", 0, &PROPER);
+  ScanConfig (config, "USNO_CDROM",            "%s",  0, CDROM);
+  ScanConfig (config, "CATDIR",                "%s",  0, CATDIR);
+
+  free (config);
+  free (file);
+}
Index: /tags/start/Ohana/src/addusno/src/addusno.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/addusno.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/addusno.c	(revision 12606)
@@ -0,0 +1,77 @@
+# include "addusno.h"
+
+main (int argc, char **argv) {
+
+  int i, N, Nusno;
+  Catalog catalog;
+  CatStats catstats;
+  USNOstats usnostats;
+  USNOdata *usno, *getusno();
+  struct timeval now, then;  
+  PhotCodeData photcodes;
+  
+  gettimeofday (&then, (void *) NULL);
+  ConfigInit (argc, argv);
+
+  VERBOSE = FALSE;
+  if ((i = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  FORCE_RUN = FALSE;
+  if ((i = get_argument (argc, argv, "-f"))) {
+    FORCE_RUN = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  RESET = FALSE;
+  if ((i = get_argument (argc, argv, "-reset"))) {
+    RESET = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  if (argc < 2) {
+    fprintf (stderr, "ERROR: Usage: addusno (region)\n");
+    exit (0);
+  }
+
+  if (!LoadPhotcodes (PhotCodeFile)) {
+    fprintf (stderr, "error loading photcodes\n");
+    exit (0);
+  }
+  
+  USNO_RED = GetPhotcodebyName ("USNO_RED");
+  if (!USNO_RED) {
+    fprintf (stderr, "ERROR: USNO_RED photcode not found in photcode table\n");
+    exit (0);
+  }
+  USNO_BLUE = GetPhotcodebyName ("USNO_BLUE");
+  if (!USNO_BLUE) {
+    fprintf (stderr, "ERROR: USNO_BLUE photcode not found in photcode table\n");
+    exit (0);
+  }
+
+  /* if lockfile exists, program will complain and quit */
+  check_lockfile (); 
+  check_permissions (argv[1]);
+
+  gcatalog (argv[1], &catalog);
+
+  if (RESET) reset_catalog (&catalog);
+
+  gcatstats (&catalog, &catstats);
+
+  usno = getusno (&usnostats, &catstats, &Nusno);
+
+  find_matches (&catstats, &catalog, &usnostats, usno, Nusno);
+
+  find_proper (&catstats, &catalog, &usnostats, usno, Nusno);
+
+  wcatalog (argv[1], &catalog);
+
+  if (VERBOSE) {
+    gettimeofday (&now, (void *) NULL);
+    fprintf (stderr, "%s: elapsed time = %.2f sec\n", argv[1], 
+	     (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec));
+  }
+  clear_lockfile (); 
+  fprintf (stderr, "SUCCESS\n");
+}
Index: /tags/start/Ohana/src/addusno/src/check_lockfile.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/check_lockfile.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/check_lockfile.c	(revision 12606)
@@ -0,0 +1,39 @@
+# include "addusno.h"
+
+check_lockfile ()
+{
+  
+  FILE *f;
+  char filename[128];
+  struct stat filestat;
+
+  sprintf (filename, "%s/lock\0", CATDIR);
+  if (stat (filename, &filestat) != -1) {
+    fprintf (stderr, "ERROR: catalog %s is locked, try again later\n", CATDIR);
+    exit (0);
+  }
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't set lock file %s\n", filename);
+    exit (0);
+  }
+  fclose (f);
+
+}
+
+clear_lockfile ()
+{
+  
+  char filename[128], line[256];
+  struct stat filestat;
+
+  sprintf (filename, "%s/lock\0", CATDIR);
+  if (stat (filename, &filestat) != -1) {
+    sprintf (line, "rm %s\0", filename);
+    system (line);
+  } else {
+    fprintf (stderr, "can't remove lockfile, why not?\n");
+  }
+
+}
Index: /tags/start/Ohana/src/addusno/src/check_permissions.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/check_permissions.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/check_permissions.c	(revision 12606)
@@ -0,0 +1,63 @@
+# include "addusno.h"
+
+check_permissions (char *basefile) {
+  
+  FILE *f;
+  char *c, dir[256], filename[256];
+  struct stat filestat;
+  uid_t fuid, uid;
+  gid_t fgid, gid;
+  int status;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to write to directory */
+  sprintf (filename, "%s\0", basefile);
+  c = strrchr (filename, '/');
+  if (c == (char *) NULL) {
+    strcpy (dir, ".");
+  } else {
+    *c = 0;
+    strcpy (dir, filename);
+  }
+  status = stat (dir, &filestat);
+  if (status == -1) {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (0);
+  } 
+  if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRWXU)) ||
+      ((gid == filestat.st_gid) && (filestat.st_mode & S_IRWXG)) || 
+      (filestat.st_mode & S_IRWXO)) {
+  } else {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (0);
+  }
+  
+  /* check permission to write to file */
+  sprintf (filename, "%s\0", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (0);
+    }
+  }
+  
+  /* check permission to write to backup file */
+  sprintf (filename, "%s~\0", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (0);
+    }
+  }
+  
+}
Index: /tags/start/Ohana/src/addusno/src/config.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/config.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/config.c	(revision 12606)
@@ -0,0 +1,110 @@
+# include <ohana.h>
+# define D_NBYTES 4096
+
+char *LoadConfigFile (filename) 
+char *filename; 
+{
+  
+  FILE *f;
+  int i, done, Nbytes, NBYTES, size;
+  char *config;
+  
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "couldn't find %s\n", filename);
+    return ((char *) NULL);
+  }
+ 
+  NBYTES = D_NBYTES;
+  ALLOCATE (config, char, NBYTES);
+ 
+  size = 0;
+  done = FALSE;
+  for (i = 0; !done; i++) {
+    Nbytes = Fread (&config[i*D_NBYTES], sizeof(char), D_NBYTES, f, "char");
+    size += Nbytes;
+    if (Nbytes < D_NBYTES) 
+      done = TRUE;
+    else {
+      NBYTES += D_NBYTES;
+      REALLOCATE (config, char, NBYTES);
+    }
+  }
+  
+  config[size] = '\n';
+  config[size+1] = 0;
+  REALLOCATE (config, char, size + 2);
+ 
+  fclose (f);
+
+  return (config);
+}
+
+int ScanConfig /* we expect one more field: the pointer to the value requested */
+# ifndef ANSI
+(config, field, mode, va_alist) 
+ char *config; char *field, *mode; va_dcl
+# else
+(char       config[],
+ char       field[],
+ char       mode[],...)
+# endif
+{
+ 
+  int i, j;
+  char *p, *p2, tmp[256];
+  va_list argp;
+  double value;
+  
+# ifndef ANSI
+  va_start (argp);
+# else
+  va_start (argp, N);
+# endif
+  
+  /* find the correct line with field */
+  p2 = config;
+  for (i = 0; ; i++) {
+    if (!strncmp (field, p2, strlen(field))) {
+      p = p2 + strlen (field);
+      break;
+    }
+    else {
+      p2 = strchr (p2, '\n');
+      if (p2 == (char *) NULL) {
+	fprintf (stderr, "entry %s not found in config file\n", field);
+	return (FALSE);
+      }
+      else p2++;
+    }
+  }
+  if (!strcmp (mode, "%s")) {
+    p2 = strchr (p, '\n');
+    if (p2 == (char *) NULL)
+      p2 = config + strlen(config);
+    bcopy (p, tmp, (p2-p));
+    tmp[(p2-p)] = 0;
+    stripwhite (tmp);
+    p2 = va_arg (argp, char *);
+    strcpy (p2, tmp);
+  }
+  else {
+ 
+    /* try to get a numerical value from the field */
+    value = strtod (p, &p2);
+    if ((*p2 == 'd') || (*p2 == 'D')) 
+      value *= pow (10.0, atof (p2 + 1));
+    
+    if (!strcmp (mode, "%d"))  *va_arg (argp, int *)       = value;
+    if (!strcmp (mode, "%u"))  *va_arg (argp, unsigned *)  = value;
+    if (!strcmp (mode, "%ld")) *va_arg (argp, long *)      = value;
+    if (!strcmp (mode, "%hd")) *va_arg (argp, short *)     = value;
+    if (!strcmp (mode, "%f"))  *va_arg (argp, float *)     = value;
+    if (!strcmp (mode, "%lf")) *va_arg (argp, double *)    = value;
+    
+  }
+ 
+  va_end (argp);
+  return (TRUE);
+  
+}
Index: /tags/start/Ohana/src/addusno/src/coordops.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/coordops.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/coordops.c	(revision 12606)
@@ -0,0 +1,342 @@
+# include "addstar.h"
+
+XY_to_RD (ra, dec, x, y, coords)
+double *ra, *dec;
+double  x, y;
+Coords coords[];
+{
+
+  double L, M, X, Y, T;
+  double R, sphi, cphi, stht, ctht;
+  double alpha, delta, salp, calp, sdel, sdp, cdp;
+  
+  *ra  = 0;
+  *dec = 0;
+
+# if 1
+  if (!strcmp(&coords[0].ctype[4], "-PLY")) {
+    X = coords[0].cdelt1*(x - coords[0].crpix1 + x*x*coords[0].polyterms[0][0] + x*y*coords[0].polyterms[1][0] + y*y*coords[0].polyterms[2][0]
+			  + x*x*x*coords[0].polyterms[3][0] + x*x*y*coords[0].polyterms[4][0] + x*y*y*coords[0].polyterms[5][0] + y*y*y*coords[0].polyterms[6][0]);
+    Y = coords[0].cdelt2*(y - coords[0].crpix2 + x*x*coords[0].polyterms[0][1] + x*y*coords[0].polyterms[1][1] + y*y*coords[0].polyterms[2][1]
+			  + x*x*x*coords[0].polyterms[3][1] + x*x*y*coords[0].polyterms[4][1] + x*y*y*coords[0].polyterms[5][1] + y*y*y*coords[0].polyterms[6][1]);
+  } else {
+# else
+  {
+# endif
+    X = coords[0].cdelt1*(x - coords[0].crpix1);
+    Y = coords[0].cdelt2*(y - coords[0].crpix2);
+  }    
+
+  L = (X*coords[0].pc1_1 + Y*coords[0].pc1_2);
+  M = (X*coords[0].pc2_1 + Y*coords[0].pc2_2);
+
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    R = hypot (L,M);
+    if ((L == 0) && (M == 0)) {
+      sphi = 0;
+      cphi = 1;
+    }
+    else {
+      sphi =  L / R;
+      cphi = -M / R;
+    }
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN")) {
+      if (R == 0) {
+	stht = 1.0;
+	ctht = 0.0;
+      }
+      else {
+	T = DEG_RAD / R;
+	stht =   T / sqrt ( 1.0 + T*T);
+	ctht = 1.0 / sqrt ( 1.0 + T*T);
+      }
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      ctht = RAD_DEG * R;
+      stht = sqrt (1 - ctht*ctht);
+    }
+
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    
+    sdel = stht*sdp - ctht*cphi*cdp;
+    salp = ctht*sphi;
+    calp = stht*cdp + ctht*cphi*sdp;
+    alpha = atan2 (salp, calp);
+    delta = asin (sdel);
+    
+    *ra  = DEG_RAD*alpha + coords[0].crval1;
+    *dec = DEG_RAD*delta;
+  }
+  if (!strcmp(&coords[0].ctype[4], "-LIN") || !strcmp(&coords[0].ctype[0], "GENE")) {
+    *ra  = L + coords[0].crval1;
+    *dec = M + coords[0].crval2;
+  }
+
+}
+
+
+fXY_to_RD (ra, dec, x, y, coords)
+float *ra, *dec;
+double  x, y;
+Coords coords[];
+{
+
+  double L, M, X, Y, T;
+  double R, sphi, cphi, stht, ctht;
+  double alpha, delta, salp, calp, sdel, sdp, cdp;
+  
+  *ra  = 0;
+  *dec = 0;
+
+  if (!strcmp(&coords[0].ctype[4], "-PLY")) {
+    X = coords[0].cdelt1*(x - coords[0].crpix1 + x*x*coords[0].polyterms[0][0] + x*y*coords[0].polyterms[1][0] + y*y*coords[0].polyterms[2][0]
+			  + x*x*x*coords[0].polyterms[3][0] + x*x*y*coords[0].polyterms[4][0] + x*y*y*coords[0].polyterms[5][0] + y*y*y*coords[0].polyterms[6][0]);
+    Y = coords[0].cdelt2*(y - coords[0].crpix2 + x*x*coords[0].polyterms[0][1] + x*y*coords[0].polyterms[1][1] + y*y*coords[0].polyterms[2][1]
+			  + x*x*x*coords[0].polyterms[3][1] + x*x*y*coords[0].polyterms[4][1] + x*y*y*coords[0].polyterms[5][1] + y*y*y*coords[0].polyterms[6][1]);
+  } else {
+    X = coords[0].cdelt1*(x - coords[0].crpix1);
+    Y = coords[0].cdelt2*(y - coords[0].crpix2);
+  }    
+  L = (X*coords[0].pc1_1 + Y*coords[0].pc1_2);
+  M = (X*coords[0].pc2_1 + Y*coords[0].pc2_2);
+
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    R = hypot (L,M);
+    if ((L == 0) && (M == 0)) {
+      sphi = 0;
+      cphi = 1;
+    }
+    else {
+      sphi =  L / R;
+      cphi = -M / R;
+    }
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") ) {
+      if (R == 0) {
+	stht = 1.0;
+	ctht = 0.0;
+      }
+      else {
+	T = DEG_RAD / R;
+	stht =   T / sqrt ( 1.0 + T*T);
+	ctht = 1.0 / sqrt ( 1.0 + T*T);
+      }
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      ctht = RAD_DEG * R;
+      stht = sqrt (1 - ctht*ctht);
+    }
+
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    
+    sdel = stht*sdp - ctht*cphi*cdp;
+    salp = ctht*sphi;
+    calp = stht*cdp + ctht*cphi*sdp;
+    alpha = atan2 (salp, calp);
+    delta = asin (sdel);
+    
+    *ra  = DEG_RAD*alpha + coords[0].crval1;
+    *dec = DEG_RAD*delta;
+  }
+  if (!strcmp(&coords[0].ctype[4], "-LIN") || !strcmp(&coords[0].ctype[0], "GENE")) {
+    *ra  = L + coords[0].crval1;
+    *dec = M + coords[0].crval2;
+  }
+
+}
+
+
+RD_to_XY (x, y, ra, dec, coords)
+double *x, *y;
+double  ra, dec;
+Coords coords[];
+{
+
+  double tmp_d;
+  double X, Y, sphi, cphi, stht;
+  double salp, calp, sdel, cdel, sdp, cdp;
+
+  if (!strcmp(&coords[0].ctype[4], "-PLY")) {
+    /* fprintf (stderr, "approximate to polynomial TAN plane fit\n");  */
+  }
+
+  *x = 0;
+  *y = 0;
+  if (!strcmp(&coords[0].ctype[0], "GENE") || !strcmp(&coords[0].ctype[4], "-LIN")) {
+    X = (ra  - coords[0].crval1);
+    Y = (dec - coords[0].crval2);
+  }
+  
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    salp = sin(RAD_DEG*(ra - coords[0].crval1));
+    calp = cos(RAD_DEG*(ra - coords[0].crval1));
+    sdel = sin(RAD_DEG*dec);
+    cdel = cos(RAD_DEG*dec);
+
+    stht = sdel*sdp + cdel*cdp*calp;  /* sin(theta) */
+    sphi = cdel*salp;  /* = cos(theta)*sin(phi) */
+    cphi = cdel*sdp*calp - sdel*cdp; /* = cos(theta)*cos(phi) */
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") ) {
+      X =  DEG_RAD * sphi / stht;
+      Y = -DEG_RAD * cphi / stht;
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      X =  DEG_RAD * sphi;
+      Y = -DEG_RAD * cphi;
+    }
+    X = X;
+    Y = Y;
+  }
+  
+  tmp_d = 1.0 / (coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1);
+  *x = tmp_d * (coords[0].pc2_2*X - coords[0].pc1_2*Y) / coords[0].cdelt1 + coords[0].crpix1;
+  *y = tmp_d * (coords[0].pc1_1*Y - coords[0].pc2_1*X) / coords[0].cdelt2 + coords[0].crpix2;
+ 
+}
+
+
+fRD_to_XY (x, y, ra, dec, coords)
+float *x, *y;
+double  ra, dec;
+Coords coords[];
+{
+
+  double tmp_d;
+  double X, Y, sphi, cphi, stht;
+  double salp, calp, sdel, cdel, sdp, cdp;
+
+  *x = 0;
+  *y = 0;
+  if (!strcmp(&coords[0].ctype[0], "GENE") || !strcmp(&coords[0].ctype[4], "-LIN")) {
+    X = (ra  - coords[0].crval1);
+    Y = (dec - coords[0].crval2);
+  }
+  
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    salp = sin(RAD_DEG*(ra - coords[0].crval1));
+    calp = cos(RAD_DEG*(ra - coords[0].crval1));
+    sdel = sin(RAD_DEG*dec);
+    cdel = cos(RAD_DEG*dec);
+
+    stht = sdel*sdp + cdel*cdp*calp;  /* sin(theta) */
+    sphi = cdel*salp;  /* = cos(theta)*sin(phi) */
+    cphi = cdel*sdp*calp - sdel*cdp; /* = cos(theta)*cos(phi) */
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") ) {
+      X =  DEG_RAD * sphi / stht;
+      Y = -DEG_RAD * cphi / stht;
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      X =  DEG_RAD * sphi;
+      Y = -DEG_RAD * cphi;
+    }
+    X = X;
+    Y = Y;
+  }
+  
+  tmp_d = 1.0 / (coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1);
+  *x = tmp_d * (coords[0].pc2_2*X - coords[0].pc1_2*Y) / coords[0].cdelt1 + coords[0].crpix1;
+  *y = tmp_d * (coords[0].pc1_1*Y - coords[0].pc2_1*X) / coords[0].cdelt2 + coords[0].crpix2;
+ 
+}
+
+
+
+GetCoords (coords, header) 
+Coords coords[];
+Header header[];
+{
+
+  int status;
+  double rotate;
+
+  rotate = 0.0;
+  coords[0].crval1 = coords[0].crpix1 = coords[0].cdelt1 = 0.0;
+  coords[0].crval2 = coords[0].crpix2 = coords[0].cdelt2 = 0.0;
+  coords[0].pc1_1 = coords[0].pc2_2 = 1.0;
+  coords[0].pc2_1 = coords[0].pc1_2 = 0.0;
+  strcpy (coords[0].ctype, "NONE");
+
+  status = TRUE; 
+  if (fits_scan (header, "CTYPE2", "%s", 1, coords[0].ctype)) {
+    status  = fits_scan (header, "CRVAL1", "%lf", 1, &coords[0].crval1);
+    status &= fits_scan (header, "CRPIX1", "%lf", 1, &coords[0].crpix1);
+    status &= fits_scan (header, "CRVAL2", "%lf", 1, &coords[0].crval2);  
+    status &= fits_scan (header, "CRPIX2", "%lf", 1, &coords[0].crpix2);
+    if (fits_scan (header, "CDELT1", "%lf", 1, &coords[0].cdelt1)) {
+      status &= fits_scan (header, "CDELT2", "%lf", 1, &coords[0].cdelt2);
+      if (fits_scan (header, "CROTA2", "%lf", 1, &rotate)) {
+	coords[0].pc1_1 =  cos(rotate*RAD_DEG);
+	coords[0].pc1_2 = -sin(rotate*RAD_DEG);
+	coords[0].pc2_1 =  sin(rotate*RAD_DEG);
+	coords[0].pc2_2 =  cos(rotate*RAD_DEG);
+      }
+      if (fits_scan (header, "PC001001", "%lf", 1, &coords[0].pc1_1)) {
+	status &= fits_scan (header, "PC001002", "%lf", 1, &coords[0].pc1_2);
+	status &= fits_scan (header, "PC002001", "%lf", 1, &coords[0].pc2_1);
+	status &= fits_scan (header, "PC002002", "%lf", 1, &coords[0].pc2_2);
+      }
+    }
+    else {
+      if (fits_scan (header, "CD1_1", "%lf", 1, &coords[0].pc1_1)) {
+	status &= fits_scan (header, "CD1_2", "%lf", 1, &coords[0].pc1_2);
+	status &= fits_scan (header, "CD2_1", "%lf", 1, &coords[0].pc2_1);
+	status &= fits_scan (header, "CD2_2", "%lf", 1, &coords[0].pc2_2);
+	coords[0].cdelt1 = coords[0].cdelt2 = 1.0;
+      }
+      else {
+	status = FALSE;
+      }
+    }
+  }
+  else {
+    if (fits_scan (header, "RA_O", "%lf", 1, &coords[0].crval1)) {
+      status  = fits_scan (header, "RA_X", "%lf", 1, &coords[0].pc1_1);
+      status &= fits_scan (header, "RA_Y", "%lf", 1, &coords[0].pc1_2);
+      status &= fits_scan (header, "DEC_O", "%lf", 1, &coords[0].crval2);  
+      status &= fits_scan (header, "DEC_X", "%lf", 1, &coords[0].pc2_1);
+      status &= fits_scan (header, "DEC_Y", "%lf", 1, &coords[0].pc2_2);
+      coords[0].crpix1 = coords[0].crpix2 = 0.0;
+      coords[0].cdelt1 = coords[0].cdelt2 = 1.0;
+      strcpy (coords[0].ctype, "GENE");
+    }
+  }
+  if (!status) {
+    fprintf (stderr, "error getting all elements for coordinate mode %d\n", coords[0].ctype);
+    coords[0].crval1 = coords[0].crpix1 = coords[0].cdelt1 = 0.0;
+    coords[0].crval2 = coords[0].crpix2 = coords[0].cdelt2 = 0.0;
+    coords[0].pc1_1 = coords[0].pc2_2 = 1.0;
+    coords[0].pc2_1 = coords[0].pc1_2 = 0.0;
+    strcpy (coords[0].ctype, "NONE");
+  }
+}
+
+
+  /* -PLY projection is an extrapolation of the -TAN projection. 
+     In addition to the usual linear terms of CRPIXi, PC00i00j, there are 
+     higher order polynomial terms (up to 3rd order):
+     Axis 1 terms:
+     PCA1X2Y0 = coords.polyterm[0][0] = x^2                                             
+     PCA1X1Y1 = coords.polyterm[1][0] = xy                                          
+     PCA1X0Y2 = coords.polyterm[2][0] = y^2                                             
+     PCA1X3Y0 = coords.polyterm[3][0] = x^3                                             
+     PCA1X2Y1 = coords.polyterm[4][0] = x^2 y                                             
+     PCA1X1Y2 = coords.polyterm[5][0] = x y^2                                             
+     PCA1X0Y3 = coords.polyterm[6][0] = y^2                                              
+     Axis 2 terms:
+     PCA2X2Y0 = coords.polyterm[0][1] = x^2                                               
+     PCA2X1Y1 = coords.polyterm[1][1] = xy                                                
+     PCA2X0Y2 = coords.polyterm[2][1] = y^2                                               
+     PCA2X3Y0 = coords.polyterm[3][1] = x^3                                               
+     PCA2X2Y1 = coords.polyterm[4][1] = x^2 y                                             
+     PCA2X1Y2 = coords.polyterm[5][1] = x y^2                                             
+     PCA2X0Y3 = coords.polyterm[6][1] = y^2                                               
+  */
Index: /tags/start/Ohana/src/addusno/src/dumpcat.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/dumpcat.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/dumpcat.c	(revision 12606)
@@ -0,0 +1,60 @@
+# include "addstar.h"
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  int i, j, Nstars, Nimage, Nregions;
+  Average *average;
+  Measure *measure;
+  Missing *missing;
+  Catalog catalog;
+  GSCRegion region;
+  FILE *f;
+  
+  if (argc < 4) {
+    fprintf (stderr, "USAGE: dumpcat catalog output mode(0,1,2,3)\n");
+    exit (0);
+  }
+
+  strcpy (region.filename, argv[1]);
+
+  gcatalog (&region, &catalog);
+
+  f = fopen (argv[2], "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "failed to open file %s for write\n", argv[2]);
+    clear_lockfile ();
+    exit (0);
+  }
+
+  average = catalog.average;
+  for (i = 0; i < catalog.Naverage; i++) {
+    fprintf (f, "%10.6f %10.6f %7.3f %3d %3d %8d %d\n", average[i].R, average[i].D, 
+	     0.001*average[i].M, average[i].Nm, average[i].Nn, average[i].offset, catalog.measure[average[i].offset].t);
+    if ((atof(argv[3]) == 1) || (atof(argv[3]) == 3)) {
+      measure = &catalog.measure[average[i].offset];
+      for (j = 0; j < average[i].Nm; j++) {
+	fprintf (f, "  %d %d %f %f %d\n", measure[j].dR, measure[j].dD, 0.001*measure[j].M, 
+		  measure[j].t, measure[j].average);
+      }
+    }
+    if ((atof(argv[3]) == 2) || (atof(argv[3]) == 3)) {
+      if (average[i].Nn > 0) {
+	missing = &catalog.missing[average[i].missing];
+	for (j = 0; j < average[i].Nn; j++) {
+	  fprintf (f, "  %f\n", missing[j].t);
+	}
+      } else { 
+	fprintf (f, "no missing obs\n");
+      }
+    }
+  }
+
+    
+
+  fclose (f);
+    
+
+}
Index: /tags/start/Ohana/src/addusno/src/dumpusno.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/dumpusno.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/dumpusno.c	(revision 12606)
@@ -0,0 +1,144 @@
+# include <stdio.h>
+# include <math.h>
+
+# define NZONE 24
+
+int SPDzone[] = {
+  0, 75, 450, 375, 1500, 1650, 300, 1425, 1725, 525, 1275, 225, 
+  675, 150, 600, 1575, 750, 975, 900, 1050, 1125, 1200, 825, 1350};
+
+int USNOdisk[] = {
+  1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10};
+
+# ifndef ALLOCATE
+# define ALLOCATE(X,T,S)  \
+  X=(T *)malloc((unsigned) ((S)*sizeof(T)));\
+  if(X==NULL) \
+    { \
+      fprintf(stderr,"failed to malloc X\n");\
+        exit(0);\
+    } 
+# define REALLOCATE(X,T,S) \
+  X=(T *)realloc(X,(unsigned) ((S)*sizeof(T))); \
+  if(X==NULL) \
+    { \
+       fprintf(stderr,"failed to realloc X\n"); \
+       exit(0); \
+    }
+# endif /* ALLOCATE */
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  long int offset;
+  int i, bin, first, last, Nstars, nitems, Nitems, Nbins;
+  float hours[100];
+  int start[100], number[100], *buffer, *buf;
+  char filename[128], c;
+  FILE *f;
+  float r, b;
+  double RA0, DEC0, RA1, DEC1, tmp;
+  int iDEC0, iDEC1, iRA0, iRA1;
+  int spd, spd_start, spd_end, disk;
+  double atof();
+
+  if (argc != 6) {
+    fprintf (stderr, "USAGE: addusno RA DEC dRA dDEC (mnt)\n");
+    exit (0);
+  }
+
+  RA0 = atof (argv[1]);
+  DEC0 = atof (argv[2]);
+  RA1 = RA0 + atof (argv[3]);
+  DEC1 = DEC0 + atof (argv[4]);
+  iRA0 = RA0 * 360000.0;
+  iRA1 = RA1 * 360000.0;
+  iDEC0 = (DEC0 + 90.0) * 360000.0;
+  iDEC1 = (DEC1 + 90.0) * 360000.0;
+  
+  spd_start = (int)((DEC0 + 90) / 7.5) * 75.0;
+  tmp = (DEC1 + 90) / 7.5;
+  if (tmp > (int)(tmp)) {
+    spd_end =   (int)(1 + (DEC1 + 90) / 7.5) * 75.0;
+  } else {
+    spd_end =   (int)(0 + (DEC1 + 90) / 7.5) * 75.0;
+  }
+
+  for (spd = spd_start; spd < spd_end; spd += 75) {
+    disk = -1;
+    for (i = 0; i < NZONE; i++) {
+      if (spd == SPDzone[i]) 
+	disk = USNOdisk[i];
+    }
+    if (disk < 0) {
+      fprintf (stderr, "ERROR: can't find cdrom for spd %d\n",  spd);
+      exit (0);
+    }
+    
+    /* load accelerator file */
+    sprintf (filename, "%s/zone%04d.acc\0", argv[5], spd);
+    fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "can't open file %s, is cdrom %d in drive?\n", filename, disk);
+      fprintf (stderr, "press return when ready to continue: ");
+      fscanf (stdin, "%c", &c);
+      fprintf (stderr, "trying again...\n");
+      f = fopen (filename, "r");
+      if (f == (FILE *) NULL) {
+	fprintf (stderr, "still can't open file %s, is cdrom %d in drive?\n", filename, disk);
+	exit (0);  
+      }
+    }
+    for (i = 0; fscanf (f, "%f %d %d", &hours[i], &start[i], &number[i]) != EOF; i++);
+    Nbins = i;
+    fclose (f);
+    
+    first = RA0 / 3.75;
+    last  = RA1 / 3.75;
+    if ((first >= Nbins) || (last >= Nbins)) {
+      fprintf (stderr, "RA out of range\n");
+      exit (0);
+    }
+    
+    /* open data file */
+    sprintf (filename, "%s/zone%04d.cat\0", argv[5], spd);
+    fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "can't open file %s\n", filename);
+      exit (0);
+    }
+    /* advance file pointer to first slice */
+    offset = 3*sizeof(int)*(start[first] - 1);
+    fseek (f, offset, SEEK_SET);
+    /* on each loop, load data from an RA slice of the catalog */
+    for (bin = first; bin < last + 1; bin++) {
+      Nitems = 3*number[bin];
+      ALLOCATE (buffer, int, Nitems);
+      nitems = Fread (buffer, sizeof(int), Nitems, f, "int");
+      if (nitems != Nitems) {
+	fprintf (stderr, "error reading data from file %s (%d, %d, %d)\n", 
+		 filename, start[bin], number[bin], nitems);
+	exit (0);
+      }
+      buf = buffer;
+      /* print out data from slice within RA and DEC range */
+      for (i = 0; i < number[bin]; i++, buf+=3) {
+	if ((buf[0] > iRA0) && (buf[0] < iRA1) &&
+	    (buf[1] > iDEC0) && (buf[1] < iDEC1)) {
+	  r = 0.1*(buf[2] - 1000*((int)(buf[2]/1000)));
+	  b = 0.1*((int)(buf[2] - 1000000*((int)(buf[2]/1000000))) / 1000);
+	  fprintf (stdout, "%f %f %d %f %f\n", 
+		   buf[0]/360000.0, buf[1]/360000.0 - 90.0, buf[2], r, b);
+	}
+      }
+      free (buffer);
+    }
+    fclose (f);
+  }
+}
+
+
Index: /tags/start/Ohana/src/addusno/src/find_matches.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/find_matches.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/find_matches.c	(revision 12606)
@@ -0,0 +1,157 @@
+# include "addusno.h"
+
+find_matches (catstats, catalog, usnostats, usno, Nusno)
+CatStats catstats[];
+Catalog catalog[];
+USNOstats usnostats[];
+USNOdata usno[];
+int Nusno;
+{
+
+  int i, j, k, n, m, N, first_j;
+  double RADIUS2;
+  float *X1, *Y1, *X2, *Y2, *usnodist;
+  float dX, dY, dR;
+  int *N1, *N2,  *next, last, *catmatch;
+  int Nave, Nmeas, NMEAS, Nmatch;
+  unsigned int flags;
+  Measure *tmpmeasure;
+  Coords *tcoords;
+
+  X1 = catstats[0].X;
+  Y1 = catstats[0].Y;
+  N1 = catstats[0].N;
+  Nave = catalog[0].Naverage;
+
+  X2 = usnostats[0].X;
+  Y2 = usnostats[0].Y;
+  N2 = usnostats[0].N;
+
+  ALLOCATE (usnodist, float, Nave);
+  ALLOCATE (catmatch, int, Nave);
+  bzero (usnodist, Nave*sizeof(float));
+  bzero (catmatch, Nave*sizeof(int));
+
+  /* set up link listed pointers for new measurements */
+  Nmatch = 0;
+  Nmeas = catalog[0].Nmeasure;
+  NMEAS = Nmeas + 1000;
+  ALLOCATE (next, int, NMEAS);
+  REALLOCATE (catalog[0].measure, Measure, NMEAS);
+  /* set up pointers for linked list of measurements */
+  for (i = 0; i < Nmeas - 1; i++) {
+    next[i] = i+1;
+  }
+  next[i] = -1;
+  last = i;
+  
+  /* choose a radius for matches */
+  /* 0.02 corrects cerror to arcsec from storage units */
+  RADIUS2 = RADIUS*RADIUS;
+
+  /** find matched stars **/
+  for (i = j = 0; (i < Nave) && (j < Nusno); ) {
+    if (catalog[0].average[N1[i]].code & ID_MOVING) { 
+      /* this is not a star, skip */
+      i++;
+      continue;
+    }
+    dX = X1[i] - X2[j];
+    if (dX <= -2*RADIUS) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*RADIUS) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    for (; (dX > -2*RADIUS) && (j < Nusno); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < RADIUS2) {  /* new measurement of this star */
+	/** insert star in measurement list */
+	n = N1[i];  /* N1 refers to the average[] list */
+	N = N2[j];  /* N2 refers to the usno[] list */
+	if ((catalog[0].average[n].code & ID_USNO) && (usnodist[i] < dR)) {
+	  /* existing USNO match is closer than this new one, skip this one */
+	  continue;
+	}
+	if (catalog[0].average[n].code & ID_USNO) {
+	  /* this USNO match is closer than previous one, fix usno[N].match */
+	  /* old one isn't a match, unset it */
+	  usnostats[0].match[catmatch[i]] = -1;
+	  continue;
+	}
+	usnodist[i] = dR;
+	m = catalog[0].average[n].offset;  /* first measurement of this star */
+	for (k = 0; k < catalog[0].average[n].Nm - 1; k++)
+	  m = next[m];
+	next[Nmeas+1] = next[m]; /* insert 2 measurements in linked list */
+	next[Nmeas] = Nmeas + 1;
+	next[m] = Nmeas;
+	if (next[Nmeas+1] == -1) { /* last just was moved */
+	  last = Nmeas+1;
+	}
+	Nmatch ++;
+	
+	/** add measurements for this star **/
+	catalog[0].measure[Nmeas].dR  = 360000.0*(catalog[0].average[n].R - usno[N].R);
+	catalog[0].measure[Nmeas].dD  = 360000.0*(catalog[0].average[n].D - usno[N].D);
+	catalog[0].measure[Nmeas].M   = 1000.0*fabs(usno[N].r);
+	catalog[0].measure[Nmeas].Mcal= 0;    /* above measurement is exact */
+	catalog[0].measure[Nmeas].dM  = 100;  /* error in input files stored in thousandths of mag */
+	catalog[0].measure[Nmeas].t   = 0;    /* a flag: if 0, image is not in database */
+	catalog[0].measure[Nmeas].averef  = n;
+	catalog[0].measure[Nmeas].source = USNO_RED; 
+	catalog[0].measure[Nmeas].dophot = 0; 
+	catalog[0].measure[Nmeas+1].dR  = catalog[0].measure[Nmeas].dR;
+	catalog[0].measure[Nmeas+1].dD  = catalog[0].measure[Nmeas].dD;
+	catalog[0].measure[Nmeas+1].M   = 1000.0*fabs(usno[N].b);
+	catalog[0].measure[Nmeas+1].Mcal= 0;    /* above measurement is exact */
+	catalog[0].measure[Nmeas+1].dM  = 100;  /* error in input files stored in thousandths of mag */
+	catalog[0].measure[Nmeas+1].t   = 0;    /* a flag: if 0, image is not in database */
+	catalog[0].measure[Nmeas+1].averef  = n;
+	catalog[0].measure[Nmeas+1].source = USNO_BLUE; 
+	catalog[0].measure[Nmeas+1].dophot = 0; 
+	/* add flag in average to mark as matched with the USNO catalog */
+	catalog[0].average[n].code |= ID_USNO;
+	/* add matched value to usno list, to keep track for next round */
+	usnostats[0].match[N] = i;
+	catmatch[i] = N;
+	/* we add two measurement for each star: 1 in r, 1 in b */
+	catalog[0].average[n].Nm +=2;
+	Nmeas +=2;  
+	if (Nmeas == NMEAS - 2) {  /* just to be safe... */
+	  NMEAS = Nmeas + 1000;
+	  REALLOCATE (next, int, NMEAS);
+	  REALLOCATE (catalog[0].measure, Measure, NMEAS);
+	}
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+  REALLOCATE (catalog[0].measure, Measure, Nmeas);
+
+  /* fix order of Measure (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmeasure, Measure, Nmeas);
+  for (i = 0; i < Nave; i++) {
+    n = catalog[0].average[i].offset;
+    catalog[0].average[i].offset = N;
+    for (k = 0; k < catalog[0].average[i].Nm; k++, N++) {
+      tmpmeasure[N] = catalog[0].measure[n]; 
+      n = next[n];
+    }
+  }
+  free (catalog[0].measure);
+  catalog[0].measure = tmpmeasure;
+    
+  catalog[0].Nmeasure = Nmeas;
+  if (VERBOSE) fprintf (stderr, "Nusno, Nave, Nmeas: %d %d %d, (%d matches)\n", Nusno, Nave, Nmeas, Nmatch);
+}
+
Index: /tags/start/Ohana/src/addusno/src/find_proper.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/find_proper.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/find_proper.c	(revision 12606)
@@ -0,0 +1,158 @@
+# include "addusno.h"
+
+find_proper (catstats, catalog, usnostats, usno, Nusno)
+CatStats catstats[];
+Catalog catalog[];
+USNOstats usnostats[];
+USNOdata usno[];
+int Nusno;
+{
+
+  int i, j, k, n, m, N, first_j;
+  double RADIUS2, PROPER2;
+  float *X1, *Y1, *X2, *Y2, *usnodist;
+  float dX, dY, dR, dR2;
+  int *N1, *N2,  *next, last;
+  int Nave, Nmeas, NMEAS, Nmatch;
+  unsigned int flags;
+  Measure *tmpmeasure;
+  Coords *tcoords;
+  int already_matched, far_enough;
+
+  X1 = catstats[0].X;
+  Y1 = catstats[0].Y;
+  N1 = catstats[0].N;
+  Nave = catalog[0].Naverage;
+
+  /* no need to do this twice!! */
+  ALLOCATE (usnodist, float, Nave);
+  bzero (usnodist, Nave*sizeof(float));
+
+  X2 = usnostats[0].X;
+  Y2 = usnostats[0].Y;
+  N2 = usnostats[0].N;
+
+ /* set up link listed pointers for new measurements */
+  Nmatch = 0;
+  Nmeas = catalog[0].Nmeasure;
+  NMEAS = Nmeas + 1000;
+  ALLOCATE (next, int, NMEAS);
+  REALLOCATE (catalog[0].measure, Measure, NMEAS);
+  /* set up pointers for linked list of measurements */
+  for (i = 0; i < Nmeas - 1; i++) {
+    next[i] = i+1;
+  }
+  next[i] = -1;
+  last = i;
+  
+  /* choose a radius for matches */
+  PROPER2 = PROPER*PROPER;
+  RADIUS2 = RADIUS*RADIUS;
+
+  /** find matched stars **/
+  for (i = j = 0; (i < Nave) && (j < Nusno); ) {
+    if (catalog[0].average[N1[i]].code & ID_MOVING) { 
+      /* this is not a star, skip */
+      i++;
+      continue;
+    }
+    if (catalog[0].average[N1[i]].Nm < 3) { 
+      /* may just be a noise spike, skip */
+      i++;
+      continue;
+    }
+    if (catalog[0].average[N1[i]].code & ID_USNO) {
+      /* already matched with USNO, skip this one */
+      i++;
+      continue;
+    }
+    dX = X1[i] - X2[j];
+    if (dX <= -2*PROPER) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*PROPER) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    for (; (dX > -2*PROPER) && (j < Nusno); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < PROPER2) {  
+	n = N1[i];  /* N1 refers to the average[] list */
+	N = N2[j];  /* N2 refers to the usno[] list */
+	if (usnostats[0].match[N] > -1) 
+	  continue;
+	if ((catalog[0].average[n].code & ID_USNO) && (usnodist[i] < dR)) {
+	  /* existing USNO match is closer than this new one, skip this one */
+	  continue;
+	}
+	usnodist[i] = dR;
+	m = catalog[0].average[n].offset;  /* first measurement of this star */
+	for (k = 0; k < catalog[0].average[n].Nm - 1; k++)
+	  m = next[m];
+	next[Nmeas+1] = next[m]; /* insert 2 measurements in linked list */
+	next[Nmeas] = Nmeas + 1;
+	next[m] = Nmeas;
+	if (next[Nmeas+1] == -1) { /* last just was moved */
+	  last = Nmeas+1;
+	}
+	Nmatch ++;
+	
+	/** add measurements for this star **/
+	catalog[0].measure[Nmeas].dR  = 360000.0*(catalog[0].average[n].R - usno[N].R);
+	catalog[0].measure[Nmeas].dD  = 360000.0*(catalog[0].average[n].D - usno[N].D);
+	catalog[0].measure[Nmeas].M   = 1000.0*fabs(usno[N].r);
+	catalog[0].measure[Nmeas].Mcal= 0;    /* above measurement is exact */
+	catalog[0].measure[Nmeas].dM  = 100;  /* error in input files stored in thousandths of mag */
+	catalog[0].measure[Nmeas].t   = 0;    /* a flag: if 0, image is not in database */
+	catalog[0].measure[Nmeas].averef  = n;
+	catalog[0].measure[Nmeas].source = USNO_RED; 
+	catalog[0].measure[Nmeas+1].dR  = catalog[0].measure[Nmeas].dR;
+	catalog[0].measure[Nmeas+1].dD  = catalog[0].measure[Nmeas].dD;
+	catalog[0].measure[Nmeas+1].M   = 1000.0*fabs(usno[N].b);
+	catalog[0].measure[Nmeas+1].Mcal= 0;    /* above measurement is exact */
+	catalog[0].measure[Nmeas+1].dM  = 100;  /* error in input files stored in thousandths of mag */
+	catalog[0].measure[Nmeas+1].t   = 0;    /* a flag: if 0, image is not in database */
+	catalog[0].measure[Nmeas+1].averef  = n;
+	catalog[0].measure[Nmeas+1].source = USNO_BLUE; 
+	/* add flag in average to mark as matched with the USNO catalog */
+	catalog[0].average[n].code |= (ID_PROPER | ID_USNO);
+	
+	/* we add two measurement for each star: 1 in r, 1 in b */
+	catalog[0].average[n].Nm +=2;
+	Nmeas +=2;  
+	if (Nmeas == NMEAS - 2) {  /* just to be safe... */
+	  NMEAS = Nmeas + 1000;
+	  REALLOCATE (next, int, NMEAS);
+	  REALLOCATE (catalog[0].measure, Measure, NMEAS);
+	}
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+  REALLOCATE (catalog[0].measure, Measure, Nmeas);
+
+  /* fix order of Measure (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmeasure, Measure, Nmeas);
+  for (i = 0; i < Nave; i++) {
+    n = catalog[0].average[i].offset;
+    catalog[0].average[i].offset = N;
+    for (k = 0; k < catalog[0].average[i].Nm; k++, N++) {
+      tmpmeasure[N] = catalog[0].measure[n]; 
+      n = next[n];
+    }
+  }
+  free (catalog[0].measure);
+  catalog[0].measure = tmpmeasure;
+    
+  catalog[0].Nmeasure = Nmeas;
+  if (VERBOSE) fprintf (stderr, "Nusno, Nave, Nmeas: %d %d %d, (%d matches)\n", Nusno, Nave, Nmeas, Nmatch);
+}
+
Index: /tags/start/Ohana/src/addusno/src/gcatalog.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/gcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/gcatalog.c	(revision 12606)
@@ -0,0 +1,100 @@
+# include "addusno.h"
+
+gcatalog (catname, catalog)
+char *catname;
+Catalog catalog[];
+{
+  
+  char filename[128];
+  int Nitems, nitems;
+  int i, Nmeas, Nmiss, done;
+  FILE *f;
+  struct tm *local;
+  struct timeval now;
+
+
+  sprintf (filename, "%s/%s\0", CATDIR, catname);
+
+  /* read catalog header */
+  if (!fits_read_header (filename, &catalog[0].header)) {
+    fprintf (stderr, "ERROR: can't open catalog file: %s\n", filename);
+    exit (0);
+  }
+
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't open catalog file: %s\n", filename);
+    exit (0);
+  }
+  fseek (f, catalog[0].header.size, SEEK_SET); 
+
+  /** find number of stars, measurements **/
+  catalog[0].Nmissing = catalog[0].Naverage = catalog[0].Nmeasure = 0;
+  fits_scan (&catalog[0].header, "NSTARS", "%d", 1, &catalog[0].Naverage);
+  fits_scan (&catalog[0].header, "NMEAS", "%d", 1, &catalog[0].Nmeasure);
+  fits_scan (&catalog[0].header, "NMISS", "%d", 1, &catalog[0].Nmissing);
+  ALLOCATE (catalog[0].average, Average, MAX (catalog[0].Naverage, 1));
+  ALLOCATE (catalog[0].measure, Measure, MAX (catalog[0].Nmeasure, 1));
+  ALLOCATE (catalog[0].missing, Missing, MAX (catalog[0].Nmissing, 1));
+
+  done = FALSE;
+  fits_scan (&catalog[0].header, "ADDUSNO", "%t", 1, &done);
+  if (done && !FORCE_RUN) {
+    if (VERBOSE) fprintf (stderr, "SUCCESS: file already up-to-date %s\n", filename);
+    fclose (f);
+    clear_lockfile ();
+    exit (0);
+  }
+
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars yet in catalog %s\n", filename);
+    clear_lockfile ();
+    fclose (f);
+    exit (0);
+  }
+
+  /* read average values */
+  Nitems = catalog[0].Naverage;
+  nitems = Fread (catalog[0].average, sizeof(Average), Nitems, f, "average");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to read data from catalog file %s (1)\n", filename);
+    fclose (f);
+    exit (0);
+  }
+  
+  /* read measurements */
+  Nitems = catalog[0].Nmeasure;
+  nitems = Fread (catalog[0].measure, sizeof(Measure), Nitems, f, "measure");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to read data from catalog file %s (2)\n", filename);
+    fclose (f);
+    exit (0);
+  }
+  
+  /* read missing */
+  Nitems = catalog[0].Nmissing;
+  nitems = Fread (catalog[0].missing, sizeof(Missing), Nitems, f, "missing");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to read data from catalog file %s (3)\n", filename);
+    fclose (f);
+    exit (0);
+  }
+  
+  if (VERBOSE) fprintf (stderr, "read %d stars from catalog file %s (%d measurements, %d missing)\n", 
+	   catalog[0].Naverage, filename, catalog[0].Nmeasure, catalog[0].Nmissing);
+
+  for (i = Nmeas = Nmiss = 0; i < catalog[0].Naverage; i++) {
+    Nmeas += catalog[0].average[i].Nm; 
+    Nmiss += catalog[0].average[i].Nn; 
+  }
+  if ((Nmeas != catalog[0].Nmeasure) || (Nmiss != catalog[0].Nmissing)) {
+    fprintf (stderr, "ERROR: data in catalog %s is corrupt, sums don't check\n");
+    fprintf (stderr, "ERROR: Nmeas: %d, %d\n", Nmeas, catalog[0].Nmeasure);
+    fprintf (stderr, "ERROR: Nmiss: %d, %d\n", Nmiss, catalog[0].Nmissing);
+    exit (0);
+  }
+
+  fclose (f);
+
+}
+
Index: /tags/start/Ohana/src/addusno/src/gcatstats.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/gcatstats.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/gcatstats.c	(revision 12606)
@@ -0,0 +1,64 @@
+# include "addusno.h"
+
+gcatstats (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  int i;
+  double RaCenter, DecCenter;
+  double MinRA, MaxRA, MinDEC, MaxDEC;
+  float *X1, *Y1;
+  int *N1;
+  Coords *tcoords;
+  
+  fits_scan (&catalog[0].header, "RA0", "%lf", 1, &MinRA);
+  fits_scan (&catalog[0].header, "RA1", "%lf", 1, &MaxRA);
+  fits_scan (&catalog[0].header, "DEC0", "%lf", 1, &MinDEC);
+  fits_scan (&catalog[0].header, "DEC1", "%lf", 1, &MaxDEC);
+
+  /* 
+  MinRA = MaxRA = catalog[0].average[0].R;
+  MinDEC = MaxDEC = catalog[0].average[0].D;
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    MinRA =  MIN (catalog[0].average[i].R, MinRA);
+    MaxRA =  MAX (catalog[0].average[i].R, MaxRA);
+    MinDEC =  MIN (catalog[0].average[i].D, MinDEC);
+    MaxDEC =  MAX (catalog[0].average[i].D, MaxDEC);
+  }
+  */
+  /* double check on region RA and DEC ranges */
+  DecCenter = 0.5*(MinDEC + MaxDEC);
+  RaCenter = 0.5*(MinRA + MaxRA);
+
+  catstats[0].RA[0] = MinRA;
+  catstats[0].RA[1] = MaxRA;
+  catstats[0].DEC[0] = MinDEC;
+  catstats[0].DEC[1] = MaxDEC;
+
+  /** allocate local arrays **/
+  ALLOCATE (catstats[0].X, float, catalog[0].Naverage);
+  ALLOCATE (catstats[0].Y, float, catalog[0].Naverage);
+  ALLOCATE (catstats[0].N, int,   catalog[0].Naverage);
+
+  /* project onto rectilinear grid with 1 arcsec pixels, sort by X */
+  /* reference for coords is center of field  */
+  catstats[0].coords.crval1 = RaCenter;
+  catstats[0].coords.crval2 = DecCenter;
+  catstats[0].coords.crpix1 = catstats[0].coords.crpix2 = 0.0;
+  catstats[0].coords.cdelt1 = catstats[0].coords.cdelt2 = 1.0 / 3600.0;
+  catstats[0].coords.pc1_1 = catstats[0].coords.pc2_2 = 1.0;
+  catstats[0].coords.pc1_2 = catstats[0].coords.pc2_1 = 0.0;
+  strcpy (catstats[0].coords.ctype, "RA---TAN");
+
+  X1 = catstats[0].X;
+  Y1 = catstats[0].Y;
+  tcoords = &catstats[0].coords;
+  for (i = 0; i < catalog[0].Naverage; i++, X1++, Y1++) {
+    fRD_to_XY (X1, Y1, catalog[0].average[i].R, catalog[0].average[i].D, tcoords);
+    catstats[0].N[i] = i;
+  }
+  if (catalog[0].Naverage > 1) sort_lists (catstats[0].X, catstats[0].Y, catstats[0].N, catalog[0].Naverage);
+  
+}
+
Index: /tags/start/Ohana/src/addusno/src/getusno.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/getusno.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/getusno.c	(revision 12606)
@@ -0,0 +1,156 @@
+# include "addusno.h"
+# define NZONE 24
+
+int SPDzone[] = {
+  0, 75, 450, 375, 1500, 1650, 300, 1425, 1725, 525, 1275, 225, 
+  675, 150, 600, 1575, 750, 975, 900, 1050, 1125, 1200, 825, 1350};
+
+int USNOdisk[] = {
+  1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10};
+
+USNOdata *getusno (usnostats, catstats, Nusno)
+CatStats catstats[];
+USNOstats usnostats[];
+int *Nusno;
+{
+
+  long int offset;
+  int i, bin, first, last, Nstars, nitems, Nitems, Nbins, *N1;
+  float hours[100];
+  int start[100], number[100], *buffer, *buf;
+  char filename[128], c;
+  FILE *f;
+  float r, b, *X1, *Y1;
+  double RA0, DEC0, RA1, DEC1;
+  int iDEC0, iDEC1, iRA0, iRA1;
+  int spd, spd_start, spd_end, disk;
+  int NUSNO, nusno;
+  USNOdata *usno;
+  Coords *tcoords;
+
+  iRA0 = catstats[0].RA[0] * 360000.0;
+  iRA1 = catstats[0].RA[1] * 360000.0;
+  iDEC0 = (catstats[0].DEC[0] + 90.0) * 360000.0;
+  iDEC1 = (catstats[0].DEC[1] + 90.0) * 360000.0;
+  
+  spd_start = (int)(    (catstats[0].DEC[0] + 90) / 7.5) * 75.0;
+  DEC1 = (catstats[0].DEC[1] + 90) / 7.5;
+  if (DEC1 > (int)(DEC1)) {
+    spd_end =   (int)(1 + (catstats[0].DEC[1] + 90) / 7.5) * 75.0;
+  } else {
+    spd_end =   (int)(0 + (catstats[0].DEC[1] + 90) / 7.5) * 75.0;
+  }
+
+  NUSNO = 5000;
+  ALLOCATE (usno, USNOdata, NUSNO);
+  nusno = 0;
+
+  for (spd = spd_start; spd < spd_end; spd += 75) {
+    disk = -1;
+    for (i = 0; i < NZONE; i++) {
+      if (spd == SPDzone[i]) 
+	disk = USNOdisk[i];
+    }
+    if (disk < 0) {
+      fprintf (stderr, "ERROR: can't find cdrom for spd %d\n",  spd);
+      exit (0);
+    }
+    
+    /* load accelerator file */
+    sprintf (filename, "%s/zone%04d.acc\0", CDROM, spd); 
+    fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "can't open file %s, is cdrom %d in drive?\n", filename, disk);
+      fprintf (stderr, "press return when ready to continue: ");
+      fscanf (stdin, "%c", &c);
+      fprintf (stderr, "trying again...\n");
+      f = fopen (filename, "r");
+      if (f == (FILE *) NULL) {
+	fprintf (stderr, "still can't open file %s, is cdrom %d in drive?\n", filename, disk);
+	exit (0);  
+      }
+    }
+    for (i = 0; fscanf (f, "%f %d %d", &hours[i], &start[i], &number[i]) != EOF; i++);
+    Nbins = i;
+    fclose (f);
+    
+    first = catstats[0].RA[0] / 3.75;
+    if ((catstats[0].RA[1] / 3.75) == (int) (catstats[0].RA[1] / 3.75)) 
+      last  = catstats[0].RA[1] / 3.75;
+    else 
+      last  = 1 + catstats[0].RA[1] / 3.75;
+
+    if ((first > Nbins) || (last > Nbins)) {
+      fprintf (stderr, "RA out of range\n");
+      exit (0);
+    }
+    
+    /* open data file */
+    sprintf (filename, "%s/zone%04d.cat\0", CDROM, spd);
+    fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "can't open file %s\n", filename);
+      exit (0);
+    }
+    /* advance file pointer to first slice */
+    offset = 3*sizeof(int)*(start[first] - 1);
+    fseek (f, offset, SEEK_SET);
+    /* on each loop, load data from an RA slice of the catalog */
+    for (bin = first; bin < last; bin++) {
+      Nitems = 3*number[bin];
+      ALLOCATE (buffer, int, Nitems);
+      nitems = Fread (buffer, sizeof(int), Nitems, f, "int");
+      if (nitems != Nitems) {
+	fprintf (stderr, "error reading data from file %s (%d, %d, %d)\n", 
+		 filename, start[bin], number[bin], nitems);
+	exit (0);
+      }
+      buf = buffer;
+      /* print out data from slice within RA and DEC range */
+      for (i = 0; i < number[bin]; i++, buf+=3) {
+	if ((buf[0] > iRA0) && (buf[0] < iRA1) &&
+	    (buf[1] > iDEC0) && (buf[1] < iDEC1)) {
+	  usno[nusno].R = buf[0]/360000.0;
+	  usno[nusno].D = buf[1]/360000.0 - 90.0;
+	  usno[nusno].r = 0.1*(buf[2] - 1000*((int)(buf[2]/1000)));
+	  usno[nusno].b = 0.1*((int)(buf[2] - 1000000*((int)(buf[2]/1000000))) / 1000);
+	  nusno ++;
+	  if (nusno == NUSNO - 1) {
+	    NUSNO += 5000;
+	    REALLOCATE (usno, USNOdata, NUSNO);
+	  }	  
+	}
+      }
+      free (buffer);
+    }
+    fclose (f);
+  }
+
+  ALLOCATE (usnostats[0].X, float, nusno);
+  ALLOCATE (usnostats[0].Y, float, nusno);
+  ALLOCATE (usnostats[0].N, int, nusno);
+  ALLOCATE (usnostats[0].match, int, nusno);
+
+  X1 = usnostats[0].X;
+  Y1 = usnostats[0].Y;
+  N1 = usnostats[0].N;
+
+  /* project onto rectilinear grid with 1 arcsec pixels, sort by X */
+  /* reference for coords is center of field */
+  tcoords = &catstats[0].coords;
+  for (i = 0; i < nusno; i++) {
+    fRD_to_XY (&X1[i], &Y1[i], usno[i].R, usno[i].D, tcoords);
+    N1[i] = i;
+    usnostats[0].match[i] = -1;
+  }
+  if (nusno > 1) sort_lists (X1, Y1, N1, nusno);
+
+  REALLOCATE (usno, USNOdata, MAX (nusno, 1));
+  *Nusno = nusno;
+  return (usno);
+
+}
+
+
Index: /tags/start/Ohana/src/addusno/src/old/add_unfound.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/old/add_unfound.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/old/add_unfound.c	(revision 12606)
@@ -0,0 +1,35 @@
+  /* incorporate unmatched image stars -- after all catalogs searched... */
+  for (i = 0; i < Nstars; i++) {
+    if (!found[i]) {
+      catalog[0].average[Nave].R = stars[N1[i]].R;
+      catalog[0].average[Nave].D = stars[N1[i]].D;
+      catalog[0].average[Nave].M = 1000.0*stars[N1[i]].M;
+      catalog[0].average[Nave].Nm = 1;
+      catalog[0].average[Nave].Xp = catalog[0].average[Nave].Xm = 0.0;
+      catalog[0].average[Nave].offset = Nmeas;
+      catalog[0].measure[Nmeas].dR  = 0.0;
+      catalog[0].measure[Nmeas].dD  = 0.0;
+      catalog[0].measure[Nmeas].M   = 1000.0*stars[N1[i]].M;
+      catalog[0].measure[Nmeas].dM  = stars[N1[i]].dM;
+      catalog[0].measure[Nmeas].t  = 3600.0 + stars[N1[i]].Y*0.1;
+      catalog[0].measure[Nmeas].average = (0x00ffffff & Nave);
+      /* time of star = time of image + offset + Y*rate */
+      Nave ++;
+      if (Nave == 0x1000000) {
+	fprintf (stderr, "too many stars in catalog\n");
+	clear_lockfile ();
+	exit (0);
+      }
+      if (Nave == NAVE) {
+	NAVE = Nave + 1000;
+	REALLOCATE (next, int, NAVE);
+	REALLOCATE (catalog[0].average, Average, NAVE);
+      }
+      Nmeas ++;
+      if (Nmeas == NMEAS) {
+	NMEAS = Nmeas + 1000;
+	REALLOCATE (next, int, NMEAS);
+	REALLOCATE (catalog[0].measure, Measure, NMEAS);
+      }
+    }
+  }
Index: /tags/start/Ohana/src/addusno/src/old/addstar.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/old/addstar.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/old/addstar.c	(revision 12606)
@@ -0,0 +1,77 @@
+# include "addstar.h"
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  FILE *f;
+  int i, N, Nstars, Nimage, Nregions, Nmissed;
+  Stars *stars, *gstars();
+  Image image, *pimage, *gimages();
+  Catalog catalog;
+  GSCRegion *region, *gregions();
+  struct timeval now, then;  
+  
+  gettimeofday (&then, (void *) NULL);
+  ConfigInit (argc, argv);
+
+  VERBOSE = FALSE;
+  if ((i = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  NEWPHOTCODE = FALSE;
+  if ((N = get_argument (argc, argv, "-p"))) {
+    NEWPHOTCODE = TRUE;
+    remove_argument (N, &argc, argv);
+    PHOTCODE = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (argc < 2) {
+    fprintf (stderr, "ERROR: Usage: addstar filename\n");
+    exit (0);
+  }
+
+  /* if lockfile exists, program will complain and quit */
+  check_lockfile ();
+
+  stars = gstars (argv[1], &Nstars, &image);
+
+  pimage = gimages (&image, &Nimage);
+  region = gregions (&image, &Nregions);
+
+  for (i = 0; i < Nregions; i++) {
+    gcatalog (&region[i], &catalog);
+    find_matches (&region[i], stars, Nstars, &catalog, &image, pimage, Nimage);
+    wcatalog (&region[i], &catalog);
+  }
+  
+  for (Nmissed = i = 0; i < Nstars; i++) {
+    if (stars[i].found == -1) {
+      fprintf (stderr, "%d %f %f %f %f\n", i, stars[i].R, stars[i].D, stars[i].M, stars[i].dM);
+      Nmissed ++;
+    }
+  }
+  if (Nmissed) fprintf (stderr, "WARNING: %d stars in image were missed!\n", Nmissed);
+
+  wimage (argv[1], &image, Nstars);
+
+  if (VERBOSE) {
+    gettimeofday (&now, (void *) NULL);
+    fprintf (stderr, "%s: elapsed time = %.2f sec\n", argv[1], 
+	     (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec));
+  }
+  clear_lockfile ();
+  fprintf (stderr, "SUCCESS\n");
+}
+
+
+  /* stars within a file are not all within 1 region file:
+     1) check if unfound stars are in current region 
+     2) if not, keep unfound for next pass */
+
+
+/* input star lists should be adjusted so 1 e/sec is mag 25.000 */ 
+
+
Index: /tags/start/Ohana/src/addusno/src/old/aregion.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/old/aregion.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/old/aregion.c	(revision 12606)
@@ -0,0 +1,188 @@
+# include "addstar.h"
+
+double BigDecBounds[] = {0.0, 7.5, 15.0, 22.5, 30.0, 37.5, 45.0, 
+			 52.5, 60.0, 67.5, 75.0, 82.5, 90.0,
+			 0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, 
+			 -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+char *DecSections[] = {"N0000", "N0730", "N1500", "N2230", "N3000", "N3730", "N4500", 
+		       "N5230", "N6000", "N6730", "N7500", "N8230", "weirdness", 
+		       "S0000", "S0730", "S1500", "S2230", "S3000", "S3730", "S4500", 
+		       "S5230", "S6000", "S6730", "S7500", "S8230", "weirdness"};
+
+char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			"n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			"s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			"s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+char *disk[] = {"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", 
+		"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "weirdness", 
+		"disk 1", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", 
+		"disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "weirdness"};
+
+int NBigRASections [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3, 48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3};
+
+int NDecLines[] = {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 24, 
+                   0, 597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48};
+
+/* find region file which contains ra, dec */
+aregion (region, f, ra, dec) 
+GSCRegion region[];
+FILE *f;
+double ra, dec;
+{
+  
+  
+  char buffer[28800], temp[50], file[50];
+  double dr, dd;
+  double RA0, RA1, DEC0, DEC1;
+  int i, NBigDec, NLINES, done, nregion;
+  
+  while (ra < 0) {
+    ra += 360.0;
+  }
+    
+  if (dec >= 86.25) {
+    sprintf (file, "%s/n8230/pole.cpt\0", CATDIR);
+    region[0].DEC[0] = 86.25;
+    region[0].DEC[1] = 93.75;
+    region[0].RA[0] = -180.0;
+    region[0].RA[1] =  540.0;
+    strcpy (region[0].filename, file);
+    return;
+  }
+    
+  NBigDec = -1;
+  for (i = 0; i < 12; i++) {
+# ifdef DEBUG
+    fprintf (stderr, "%d %f %f %f\n", i, dec, BigDecBounds[i], BigDecBounds[i+1]);
+# endif
+    if ((dec >= BigDecBounds[i]) && (dec < BigDecBounds[i+1])) {
+      NBigDec = i;
+      break;
+    }
+  }
+  if (NBigDec < 0) {
+    for (i = 13; i < 24; i++) {
+# ifdef DEBUG
+      fprintf (stderr, "%d %f %f %f\n", i, dec, BigDecBounds[i], BigDecBounds[i+1]);
+# endif
+      if ((dec < BigDecBounds[i]) && (dec >= BigDecBounds[i+1])) {
+	NBigDec = i;
+	break;
+      }
+    }
+  }
+  if (NBigDec < 0) {
+    fprintf (stderr, "dec out of range: %f\n", dec);
+  }
+    
+  NLINES = 0;
+  for (i = 0; i < NBigDec; i++) {
+    NLINES += NDecLines[i];
+  }
+  fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+      
+  done = FALSE;
+  Fread (buffer, 1, 48*NDecLines[NBigDec], f, "char");
+  for (i = 0; !done && (i < NDecLines[NBigDec]); i++) {
+    strncpy (temp, &buffer[i*48], 48);
+    temp[49] = 0;
+    hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+    if (RA1 < RA0) RA1 += 360.0;
+# ifdef DEBUG
+    fprintf (stderr, "%f %f %f  %f %f %f  %s\n", DEC0, dec, DEC1, RA0, ra, RA1, temp);
+# endif
+    if ((dec >= 0) && (dec >= DEC0) && (dec < DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+    if ((dec < 0) && (dec < DEC0) && (dec >= DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+  }
+  if (!done) {
+    fprintf (stderr, "error in search: %f %f\n", ra, dec);
+    clear_lockfile ();
+    exit (0);
+  }
+  temp[5] = 0;
+  sprintf (file, "%s/%s/%s.cpt\0", CATDIR, Dec2Sections[NBigDec],&temp[1]);
+  if (DEC0 < DEC1) {
+    region[0].DEC[0] = DEC0;
+    region[0].DEC[1] = DEC1;
+  } else {
+    region[0].DEC[0] = DEC1;
+    region[0].DEC[1] = DEC0;
+  }     
+  region[0].RA[0] = RA0;
+  region[0].RA[1] = RA1;
+  strcpy (region[0].filename, file);
+  return;
+}
+
+
+/**********/
+int hms_to_deg (h0, h1, d0, d1, string) 
+     char *string;
+     double *h0, *h1, *d0, *d1;
+{
+  
+  int flag_d0, flag_d1, flag_h0, flag_h1;
+  double tmp;
+  
+  *d0 = *h0 = *d1 = *h1 = 0;
+
+  flag_h0 = dparse (h0, 1, string);
+  flag_h1 = dparse (h1, 4, string);
+  flag_d0 = dparse (d0, 7, string);
+  flag_d1 = dparse (d1, 9, string);
+  *h0 *= flag_h0;
+  *h1 *= flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  dparse (&tmp, 2, string);
+  *h0 += tmp/60.0;
+  dparse (&tmp, 3, string);
+  *h0 += tmp/3600.0;
+  
+  dparse (&tmp, 5, string);
+  *h1 += tmp/60.0;
+  dparse (&tmp, 6, string);
+  *h1 += tmp/3600.0;
+  
+  dparse (&tmp, 8, string);
+  *d0 += tmp/60.0;
+
+  dparse (&tmp, 10, string);
+  *d1 += tmp/60.0;
+
+  *h0 *= 15*flag_h0;
+  *h1 *= 15*flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  return (TRUE);
+}
+
+
+/*
+      if (buffer[i*48 + 19] == ' ') continue;
+      strncpy (temp, &buffer[i*48 + 19], 20);       temp[20] = 0;
+      hms_to_deg (&RA,  &DEC, temp, ' ', 3);
+
+
+  dBigRA = 360.0 / (int)(0.5 + 48*cos(3.1415927*0.5*(BigDecBounds[NBigDec] + BigDecBounds[NBigDec + 1])/180.0));
+
+  NBigRA = ra / dBigRA;
+
+  NBig = NBigRA;
+  for (i = 0; (i < 12) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+  for (i = 13; (i < 24) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+
+
+  fprintf (stderr, "%d %d %d %d %f %f -> %f %f %f\n", NBigDec, NBigRA, NBigRASections[NBigDec], NBig, ra, dec, BigDecBounds[NBigDec], BigDecBounds[NBigDec + 1], dBigRA);
+*/
Index: /tags/start/Ohana/src/addusno/src/old/gimages.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/old/gimages.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/old/gimages.c	(revision 12606)
@@ -0,0 +1,214 @@
+# include "addstar.h"
+double opening_angle ();
+
+Image *gimages (image, Npimage)
+Image image[];
+int *Npimage;
+{
+  
+  int i, j, k, NIMAGE, Nimage, addtolist;
+  int NTIMAGE, Ntimage, ntimage;
+  int NPIMAGE, npimage;
+  FILE *f;
+  Image *timage, *pimage;
+  Coords tcoords;
+  Header header;
+  double r, d;
+  double Xi[5], Yi[5], Xo[5], Yo[5];  /* image and original corners */
+
+  /* check if image datafile exists, get header */
+  if (!fits_read_header (ImageCat, &header)) {
+    if (VERBOSE) fprintf (stderr, "New image catalog %s (1)\n", ImageCat);
+    *Npimage = 0;
+    return ((Image *) NULL);
+  }
+
+  /* project onto rectilinear grid with 1 arcsec pixels */
+  /* we keep the original crpix1,2 and crref1,2 */
+  tcoords = image[0].coords;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1 = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2 = tcoords.pc2_1 = 0.0;
+  strcpy (tcoords.ctype, "RA---TAN");
+
+  /* define original corners */
+  Xo[0] = 0;           Yo[0] = 0;
+  Xo[1] = image[0].NX; Yo[1] = 0;
+  Xo[2] = image[0].NX; Yo[2] = image[0].NY;
+  Xo[3] = 0;           Yo[3] = image[0].NY;
+  Xo[4] = 0;           Yo[4] = 0;  /* so we can make a loop easily */
+  for (j = 0; j < 5; j++) {
+    XY_to_RD (&r, &d, Xo[j], Yo[j], &image[0].coords);
+    RD_to_XY (&Xo[j], &Yo[j], r, d, &tcoords);
+  }
+  
+  /* get ready to read data on images */ 
+  f = fopen (ImageCat, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "New image catalog: %s (2)\n", ImageCat);
+    free (header.buffer);
+    *Npimage = 0;
+    return ((Image *) NULL);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  Nimage = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+
+  NTIMAGE = 100;
+  ALLOCATE (timage, Image, NTIMAGE);
+
+  npimage = 0;
+  NPIMAGE = 20;
+  ALLOCATE (pimage, Image, NPIMAGE);
+
+  for (Ntimage = 0; Ntimage < Nimage; Ntimage += ntimage) {
+    ntimage = Fread (timage, sizeof(Image), NTIMAGE, f, "image");
+    for (i = 0; i < ntimage; i++) {
+      addtolist = FALSE;
+      /* define image corners */
+      Xi[0] = 0;            Yi[0] = 0;
+      Xi[1] = timage[i].NX; Yi[1] = 0;
+      Xi[2] = timage[i].NX; Yi[2] = timage[i].NY;
+      Xi[3] = 0;            Yi[3] = timage[i].NY;
+      Xi[4] = 0;            Yi[4] = 0;  /* so we can make a loop easily */
+      /* transform to tcoords */
+      for (j = 0; j < 5; j++) {
+	XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+	RD_to_XY (&Xi[j], &Yi[j], r, d, &tcoords);
+      }
+      /* check if any edges cross */
+      for (j = 0; j < 4; j++) {
+	for (k = 0; k < 4; k++) {
+	  addtolist |= edge_check (&Xi[j], &Yi[j], &Xo[k], &Yo[k]);
+	}
+      }
+      
+      /*
+      fprintf (stderr, "%f %f %f %d %f %f %d %d %d %f %f %s: %d\n", 0.1*timage[i].detection_limit, 0.1*timage[i].saturation_limit, 0.02*timage[i].cerror, 
+	       timage[i].tzero, 1e-4*timage[i].trate, 
+	       0.001*timage[i].secz, timage[i].nstar, timage[i].NX, timage[i].NY, 0.001*timage[i].Mcal, 0.1*timage[i].Xm, timage[i].name, addtolist);
+      
+      fprintf (stderr, "%s\n", timage[i].coords.ctype);
+      fprintf (stderr, "%f %f\n", timage[i].coords.crval1, timage[i].coords.crval2);
+      fprintf (stderr, "%f %f\n", timage[i].coords.crpix1, timage[i].coords.crpix2);
+      fprintf (stderr, "%f %f\n", timage[i].coords.pc1_1, timage[i].coords.pc1_2);
+      fprintf (stderr, "%f %f\n", timage[i].coords.pc2_1, timage[i].coords.pc2_2);
+      fprintf (stderr, "%f %f\n", timage[i].coords.cdelt1, timage[i].coords.cdelt2);      
+      */
+
+      if (addtolist) {
+	pimage[npimage] = timage[i];
+	npimage ++;
+	if (npimage == NPIMAGE) {
+	  NPIMAGE += 20;
+	  REALLOCATE (pimage, Image, NPIMAGE);
+	}
+      }
+    }
+
+    if (ntimage == 0) {
+      fprintf (stderr, "ERROR: expected %d images, only found %d\n", Nimage, Ntimage);
+      clear_lockfile ();
+      exit (0);
+    }
+  }
+
+  if (VERBOSE) fprintf (stderr, "found %d overlapping images\n", npimage);
+
+  fclose (f);
+  *Npimage = npimage;
+  return (pimage);
+
+}
+  
+int edge_check (x1, y1, x2, y2)
+double *x1, *y1, *x2, *y2;
+{
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+double opening_angle (x1, y1, x2, y2, x3, y3)
+double x1, y1, x2, y2, x3, y3;
+{
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
+
+
+
+
+/* probably not needed now 
+char *_parse_nextword();
+
+
+int fparse (X, NX, line)
+float *X;
+int NX;
+char *line;
+{
+
+  int i;
+  char *word;
+  char *ptr;
+
+  word = line;
+  for (i = 0; i < NX - 1; i++)
+    word = _parse_nextword (word);
+
+  *X = strtod (word, &ptr);
+  if (ptr == word)
+    return (FALSE);
+  else {
+    if (word[0] == '-') 
+      return (-1);
+    else
+      return (1);
+  }
+}
+
+*/
Index: /tags/start/Ohana/src/addusno/src/old/gregions.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/old/gregions.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/old/gregions.c	(revision 12606)
@@ -0,0 +1,57 @@
+# include "addstar.h"
+
+GSCRegion *gregions (image, Nregions)
+Image *image;
+int *Nregions;
+{
+  
+  GSCRegion *region;
+  FILE *f;
+  double x, y;
+  double dr, dd, dec, ra;
+  int i, j, done, nregion, NREGION;
+  
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find GSC region file %s\n", GSCFILE);
+    clear_lockfile ();
+    exit (0);
+  }
+  
+  /* find regions at image corners */
+  NREGION = 10;
+  ALLOCATE (region, GSCRegion, NREGION);
+  nregion = 0;
+
+  /* look for new regions on grid across image */ 
+  for (x = 0.0; x <= 1.0; x+=0.25) {
+    for (y = 0.0; y <= 1.0; y+=0.25) {
+      XY_to_RD (&ra, &dec, image[0].NX*(1.1*x - 0.05), image[0].NY*(1.1*y - 0.05), &image[0].coords);
+      aregion (&region[nregion], f, ra, dec);
+      done = FALSE;
+      for (j = 0; (j < nregion) && !done; j++) {
+	if (!strcmp (region[nregion].filename, region[j].filename)) {
+	  nregion --;
+	  done = TRUE;
+	}
+      }
+      nregion ++;
+      if (nregion == NREGION) {
+	NREGION += 10;
+	REALLOCATE (region, GSCRegion, NREGION);
+      }
+    }
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "found %d region files:\n", nregion);
+    for (i = 0; i < nregion; i++) {
+      fprintf (stderr, "  %d %s\n", i, region[i].filename);
+    }
+  }
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (region);
+  
+}
Index: /tags/start/Ohana/src/addusno/src/old/gstars.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/old/gstars.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/old/gstars.c	(revision 12606)
@@ -0,0 +1,189 @@
+# include "addstar.h"
+# define D_NSTARS 1000
+# define BYTES_STAR 31
+# define BLOCK 1000
+#include <sys/time.h>
+#include <time.h>
+
+Stars *gstars (file, NSTARS, image) 
+char file[];
+int *NSTARS;
+Image *image;
+{
+
+  FILE *f;
+  Header header;
+  int i, j, nstar;
+  int nbytes, Nbytes;
+  Stars *stars;
+  char *buffer, line[64], *c;
+  struct tm timeptr;
+  double tmp;
+
+  if (!fits_read_header (file, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s\n", file);
+    clear_lockfile ();
+    exit(0);
+  }
+
+  /* open file */
+  f = fopen (file, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find data file %s\n", file);
+    clear_lockfile ();
+    exit(0);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  c = strrchr (file, 0x2f);
+  if (c == (char *) NULL) {
+    strcpy (image[0].name, file);
+  } else { 
+    strcpy (image[0].name, (c+1));
+  }
+  /* get astrometry information */
+  strcpy (image[0].coords.ctype, "NONE");
+  fits_scan (&header, "CTYPE1",   "%s",  1, image[0].coords.ctype);
+  if (strcmp (image[0].coords.ctype, "RA---PLY")) {
+    fprintf (stderr, "ERROR: wrong astrometric info in header\n");
+    clear_lockfile ();
+    exit (0);
+  }
+  fits_scan (&header, "CDELT1",   "%f", 1, &image[0].coords.cdelt1); 
+  fits_scan (&header, "CDELT2",   "%f", 1, &image[0].coords.cdelt2);
+  fits_scan (&header, "CRVAL1",   "%lf", 1, &image[0].coords.crval1);
+  fits_scan (&header, "CRVAL2",   "%lf", 1, &image[0].coords.crval2);  
+  fits_scan (&header, "CRPIX1",   "%f", 1, &image[0].coords.crpix1);
+  fits_scan (&header, "CRPIX2",   "%f", 1, &image[0].coords.crpix2);
+  fits_scan (&header, "PC001001", "%f", 1, &image[0].coords.pc1_1);
+  fits_scan (&header, "PC001002", "%f", 1, &image[0].coords.pc1_2);
+  fits_scan (&header, "PC002001", "%f", 1, &image[0].coords.pc2_1);
+  fits_scan (&header, "PC002002", "%f", 1, &image[0].coords.pc2_2);
+  fits_scan (&header, "CERROR",   "%lf", 1, &tmp);
+  /* RA Terms */
+  fits_scan (&header, "PCA1X2Y0", "%f", 1, &image[0].coords.polyterms[0][0]);
+  fits_scan (&header, "PCA1X1Y1", "%f", 1, &image[0].coords.polyterms[1][0]);
+  fits_scan (&header, "PCA1X0Y2", "%f", 1, &image[0].coords.polyterms[2][0]);
+  fits_scan (&header, "PCA1X3Y0", "%f", 1, &image[0].coords.polyterms[3][0]);
+  fits_scan (&header, "PCA1X2Y1", "%f", 1, &image[0].coords.polyterms[4][0]);
+  fits_scan (&header, "PCA1X1Y2", "%f", 1, &image[0].coords.polyterms[5][0]);
+  fits_scan (&header, "PCA1X0Y3", "%f", 1, &image[0].coords.polyterms[6][0]);
+  /* Dec Terms */
+  fits_scan (&header, "PCA2X2Y0", "%f", 1, &image[0].coords.polyterms[0][1]);
+  fits_scan (&header, "PCA2X1Y1", "%f", 1, &image[0].coords.polyterms[1][1]);
+  fits_scan (&header, "PCA2X0Y2", "%f", 1, &image[0].coords.polyterms[2][1]);
+  fits_scan (&header, "PCA2X3Y0", "%f", 1, &image[0].coords.polyterms[3][1]);
+  fits_scan (&header, "PCA2X2Y1", "%f", 1, &image[0].coords.polyterms[4][1]);
+  fits_scan (&header, "PCA2X1Y2", "%f", 1, &image[0].coords.polyterms[5][1]);
+  fits_scan (&header, "PCA2X0Y3", "%f", 1, &image[0].coords.polyterms[6][1]);
+  image[0].coords.Npolyterms = 2; /* how many do we use? */
+  /* CERROR in data file is in pixels, convert to 20*arcsec */
+  image[0].cerror = tmp * 50.0 * image[0].coords.cdelt1 * 3600.0;
+  while (image[0].coords.crval1 < 0) image[0].coords.crval1 += 360.0;
+  while (image[0].coords.crval1 > 360.0) image[0].coords.crval1 -= 360.0;
+ 
+  fits_scan (&header, "NAXIS1",   "%hd", 1, &image[0].NX); 
+  fits_scan (&header, "NAXIS2",   "%hd", 1, &image[0].NY);
+  fits_scan (&header, "PHOTCODE", "%hd", 1, &image[0].source);
+  if (NEWPHOTCODE) {
+    image[0].source = PHOTCODE;
+  }
+  image[0].NX -= XOVERSCAN;
+  image[0].NY -= YOVERSCAN;
+
+  tmp = 0;
+  fits_scan (&header, "FLIMIT",   "%lf", 1, &tmp);
+  image[0].detection_limit = tmp * 10.0;
+
+  tmp = 0;
+  fits_scan (&header, "FSATUR",   "%lf", 1, &tmp);
+  image[0].saturation_limit = tmp * 10.0;
+
+  if (!fits_scan (&header, "TZERO",   "%d",  1, &image[0].tzero)) {
+    fits_scan (&header, "UT",   "%s",  1, line);
+    /* remove : characters */
+    for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (c, 0x3a))
+      *c = ' ';
+    sscanf (line, "%d %d %d", &timeptr.tm_hour, &timeptr.tm_min, &timeptr.tm_sec);
+    fits_scan (&header, "DATE-UT",   "%s",  1, line);
+    for (c = strchr (line, 0x2f); c != (char *) NULL; c = strchr (c, 0x2f))
+      *c = ' ';
+    sscanf (line, "%d %d %d", &timeptr.tm_year, &timeptr.tm_mon, &timeptr.tm_mday);
+    if (timeptr.tm_year < 90) { /* correct for year 2000 turnover */
+      timeptr.tm_year += 100;
+    }
+    image[0].tzero = mktime (&timeptr);
+  }
+
+  tmp = 0;
+  fits_scan (&header, "TRATE",   "%lf", 1, &tmp);
+  image[0].trate = 10000 * tmp;
+
+  tmp = 0;
+  fits_scan (&header, "AIRMASS", "%lf", 1, &tmp);
+  image[0].secz = 1000*tmp;
+
+  /* secz is in units milli-airmass */
+  image[0].Mcal =  ALPHA*(image[0].secz - 1000);
+  image[0].Xm   = 30.0;
+  image[0].code = 0;
+  bzero (image[0].dummy, sizeof(image[0].dummy));
+
+  /* find number of stars */
+  fits_scan (&header, "NSTARS", "%d", 1, &image[0].nstar);
+  if (image[0].nstar == 0) {
+    fprintf (stderr, "ERROR: can't get NSTARS from header\n");
+    clear_lockfile ();
+    exit (0);
+  }
+  ALLOCATE (stars, Stars, image[0].nstar);
+  Nbytes = image[0].nstar*BYTES_STAR;
+
+  /* load in stars by blocks of 1000 */
+  nstar = 0;
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR));
+  for (i = 0; i < (int)(Nbytes / (BLOCK*BYTES_STAR)); i++) {
+    nbytes = Fread (buffer, 1, (BLOCK*BYTES_STAR), f, "char");
+    if (nbytes != BLOCK*BYTES_STAR) {
+      fprintf (stderr, "ERROR: failed to read in stars (1)\n");
+      clear_lockfile ();
+      exit (0);
+    }
+    for (j = 0; j < BLOCK; j++, nstar++) {
+      dparse (&stars[nstar].X,  1, &buffer[j*BYTES_STAR]);
+      dparse (&stars[nstar].Y,  2, &buffer[j*BYTES_STAR]);
+      dparse (&stars[nstar].M,  3, &buffer[j*BYTES_STAR]);
+      dparse (&stars[nstar].dM, 4, &buffer[j*BYTES_STAR]);
+      XY_to_RD (&stars[nstar].R, &stars[nstar].D, stars[nstar].X, stars[nstar].Y, &image[0].coords);
+      stars[nstar].found = -1;
+    }
+  }
+  /* left over fraction of a block */
+  nbytes = Fread (buffer, 1, (Nbytes % (BLOCK*BYTES_STAR)), f, "char");
+  if (nbytes != (Nbytes % (BLOCK*BYTES_STAR))) {
+    fprintf (stderr, "ERROR: failed to read in stars (2)\n");
+    clear_lockfile ();
+    exit (0);
+  }
+  for (j = 0; j < nbytes / BYTES_STAR; j++, nstar++) {
+    dparse (&stars[nstar].X, 1, &buffer[j*BYTES_STAR]);
+    dparse (&stars[nstar].Y, 2, &buffer[j*BYTES_STAR]);
+    dparse (&stars[nstar].M, 3, &buffer[j*BYTES_STAR]);
+    dparse (&stars[nstar].dM, 4, &buffer[j*BYTES_STAR]);
+    XY_to_RD (&stars[nstar].R, &stars[nstar].D, stars[nstar].X, stars[nstar].Y, &image[0].coords);
+    stars[nstar].found = -1;
+  }
+
+  if (image[0].nstar != nstar) {
+    fprintf (stderr, "ERROR: failed to read in all stars (%d != %d)\n", image[0].nstar, nstar);
+    clear_lockfile ();
+    exit (0);
+  }
+  free (header.buffer);
+  free (buffer);
+ 
+  if (VERBOSE) fprintf (stderr, "read %d stars from target file\n", image[0].nstar);
+  *NSTARS = image[0].nstar;
+
+  return (stars);
+}
Index: /tags/start/Ohana/src/addusno/src/old/sort_stars.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/old/sort_stars.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/old/sort_stars.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include "relphot.h"
+
+void sort_stars (radec, stars, Nstars)
+int  **radec;
+Star  *stars;
+int    Nstars;
+{
+  
+  int i;
+  double *RAs;
+
+  ALLOCATE (radec[0], int, Nstars);
+  ALLOCATE (RAs, double, Nstars);
+  for (i = 0; i < Nstars; i++) {
+    radec[0][i] = i;
+    RAs[i] = stars[i].RA;
+  }
+
+  sort_seq (radec[0], RAs, Nstars);
+  free (RAs);
+
+}
+
+
+void sort_seq (seq, value, N) 
+int *seq;
+double *value;
+int N;
+{
+  int l,j,ir,i;
+  int temp;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      temp = seq[--l];
+    }
+    else {
+      temp = seq[ir];
+      seq[ir] = seq[0];
+      if (--ir == 0) {
+	seq[0] = temp;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && value[seq[j]] < value[seq[j+1]]) ++j;
+      if (value[temp] < value[seq[j]]) {
+	seq[i]=seq[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    seq[i] = temp;
+  }
+}
+
+
Index: /tags/start/Ohana/src/addusno/src/old/string.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/old/string.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/old/string.c	(revision 12606)
@@ -0,0 +1,64 @@
+# include <stdio.h>
+# include <math.h>
+# define TRUE  1
+# define FALSE 0
+
+int scan_line (f, line) 
+FILE *f;
+char line[];
+{
+
+  int i, status;
+  char c;
+  
+  status = EOF + 1;
+  
+  for (i = 0, c = 0; (c != '\n') && (status != EOF); i++) {
+    status = fscanf (f, "%c", &c);
+    line[i] = c;
+  }
+  line[i - 1] = 0;  /* this could make things crash! */
+
+  if (i > 1) {
+    status = EOF + 1;
+  }
+
+  return (status);
+
+}
+
+char *_parse_nextword(string)
+char *string;
+{
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (; isspace (*string); string++);
+  for (; (*string != 0) && !isspace (*string); string++);
+  for (; isspace (*string); string++);
+  return (string);
+}
+
+int dparse (X, NX, line)
+double *X;
+int NX;
+char *line;
+{
+
+  int i;
+  char *word;
+  char *ptr;
+
+  word = line;
+  for (i = 0; i < NX - 1; i++)
+    word = _parse_nextword (word);
+
+  *X = strtod (word, &ptr);
+  if (ptr == word)
+    return (FALSE);
+  else {
+    if (word[0] == '-') 
+      return (-1);
+    else
+      return (1);
+  }
+}
Index: /tags/start/Ohana/src/addusno/src/old/wimage.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/old/wimage.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/old/wimage.c	(revision 12606)
@@ -0,0 +1,67 @@
+# include "addstar.h"
+
+wimage (filename, image, Nstars)
+char *filename;
+Image image[];
+int Nstars;
+{
+  
+  int Nimages, status;
+  FILE *f;
+  Header header;
+
+  if (!fits_read_header (ImageCat, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't find %s, creating a new one\n", ImageCat);
+    if (!fits_read_header (ImageTemplate, &header)) {
+      fprintf (stderr, "ERROR: can't find template header %s\n", ImageTemplate);
+      clear_lockfile ();
+      exit (0);
+    }
+    f = fopen (ImageCat, "w");
+    if (f == NULL) {
+      fprintf (stderr, "ERROR: can't create/open image catalog file: %s\n", ImageCat);
+      clear_lockfile ();
+      exit (0);
+    }
+  }
+  
+  Nimages = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimages);
+  Nimages ++;
+  fits_modify (&header, "NIMAGES", "%d", 1, Nimages);
+
+  f = fopen (ImageCat, "r+");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't create/open image catalog file: %s\n", ImageCat);
+    clear_lockfile ();
+    exit (0);
+  }
+
+  /* position to begining of file to write header */
+  fseek (f, 0, SEEK_SET);
+  status = Fwrite (header.buffer, 1, header.size, f, "char");
+  if (status != header.size) {
+    fprintf (stderr, "ERRPR: failed writing data to image header\n");
+    clear_lockfile ();
+    exit (0);
+  }
+
+  fseek (f, 0, SEEK_END);
+  fprintf (stderr, "Image: %d\n", sizeof(Image));
+  status = Fwrite (image, sizeof(Image), 1, f, "image");
+  if (status != 1) {
+    fprintf (stderr, "ERRPR: failed writing data to image catalog\n");
+    clear_lockfile ();
+    exit (0);
+  }
+
+  fclose (f);
+  
+
+}
+
+/* the image we add in this routine is always a new image.  
+   We only need to do two things:
+     1) append the data for the image to the end of the file
+     2) update the NIMAGES field in the header (which means, read in header, re-write)
+ */
Index: /tags/start/Ohana/src/addusno/src/reset_catalog.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/reset_catalog.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/reset_catalog.c	(revision 12606)
@@ -0,0 +1,86 @@
+# include "addusno.h"
+
+reset_catalog (catalog)
+Catalog catalog[];
+{
+
+  int i, j, k, n, m, N, M, found;
+  int *next, last, this;
+  int Nave, Nmeas, Ndel;
+  unsigned int flags;
+  Measure *tmpmeasure;
+  unsigned short NotUSNO, NotProper;
+
+  Nave = catalog[0].Naverage;
+ 
+  /* set up link listed pointers for new measurements */
+  Nmeas = catalog[0].Nmeasure;
+  ALLOCATE (next, int, Nmeas);
+  /* set up pointers for linked list of measurements */
+  for (i = 0; i < Nmeas - 1; i++) {
+    next[i] = i+1;
+  }
+  next[i] = -1;
+  last = i;
+ 
+  /** find matched stars **/
+  NotUSNO = 0xffff ^ ID_USNO;
+  NotProper = 0xffff ^ ID_PROPER;
+  for (i = 0; i < Nave; i++) {
+    found = FALSE;
+    if (catalog[0].average[i].code & ID_USNO) {
+      catalog[0].average[i].code &= NotUSNO;
+      found = TRUE;
+    }
+    if (catalog[0].average[i].code & ID_PROPER) {
+      catalog[0].average[i].code &= NotProper;
+      found = TRUE;
+    }
+    if (found) {
+      M = catalog[0].average[i].offset;
+      Ndel = 0;
+      for (k = 0; k < catalog[0].average[i].Nm; k++) {
+	if (catalog[0].measure[M+k].t == 0) {
+	  if (M+k > 0) {
+	    this = next[M+k];
+	    if (next[M+k] == -1) {
+	      next[M+k-1] = -1;
+	    } else {
+	      for (j = M+k+1; (j < Nmeas) && (next[j] == -2); j++);
+	      if (j == Nmeas) {
+		next[M+k-1] = -1;
+		fprintf (stderr, "warning, why didn't I find last link to start with?\n");
+	      }
+	      else {
+		next[M+k-1] = this;
+	      }
+	    }
+	  }
+	  next[M+k] = -2; /* delete link */
+	  Ndel ++;
+	}
+      }
+      catalog[0].average[i].Nm -= Ndel;
+      Nmeas -= Ndel;
+    }
+  }
+  
+  /* fix order of Measure (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmeasure, Measure, Nmeas);
+  for (i = 0; i < Nave; i++) {
+    n = catalog[0].average[i].offset;
+    catalog[0].average[i].offset = N;
+    for (k = 0; k < catalog[0].average[i].Nm; k++, N++) {
+      tmpmeasure[N] = catalog[0].measure[n]; 
+      n = next[n];
+    }
+  }
+  free (catalog[0].measure);
+  catalog[0].measure = tmpmeasure;
+    
+  if (VERBOSE) fprintf (stderr, "deleted %d reference %d -> %d)\n", 
+			catalog[0].Nmeasure - Nmeas, catalog[0].Nmeasure, Nmeas);
+  catalog[0].Nmeasure = Nmeas;
+}
+
Index: /tags/start/Ohana/src/addusno/src/sort_lists.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/sort_lists.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/sort_lists.c	(revision 12606)
@@ -0,0 +1,48 @@
+
+sort_lists (X, Y, S, N) 
+float *X, *Y;
+int *S, N;
+{
+  int l,j,ir,i;
+  double tX, tY, tS;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    S[i] = tS;
+  }
+}
Index: /tags/start/Ohana/src/addusno/src/wcatalog.c
===================================================================
--- /tags/start/Ohana/src/addusno/src/wcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/addusno/src/wcatalog.c	(revision 12606)
@@ -0,0 +1,74 @@
+# include "addstar.h"
+
+wcatalog (catname, catalog)
+char *catname;
+Catalog catalog[];
+{
+  
+  char filename[256], line[256];
+  int i, Nitems, nitems, status, mode;
+  FILE *f;
+  struct stat filestat;
+
+  sprintf (filename, "%s/%s\0", CATDIR, catname);
+
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, make backup copy */
+    sprintf (line, "mv %s %s~\0", filename, filename);
+    status = system (line);
+    if (status) {
+      fprintf (stderr, "ERROR: unable to create %s~, exiting\n", filename);
+      exit (0);
+    }
+  }
+
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (FALSE);
+  }
+  
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't create new catalog file: %s\n", filename);
+    exit (0);
+  }
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  chmod (filename, mode);
+  
+  fits_modify (&catalog[0].header, "NSTARS", "%d", 1, catalog[0].Naverage);
+  fits_modify (&catalog[0].header, "NMEAS", "%d", 1, catalog[0].Nmeasure);
+  fits_modify (&catalog[0].header, "NMISS", "%d", 1, catalog[0].Nmissing);
+
+  fits_modify (&catalog[0].header, "ADDUSNO", "%t", 1, TRUE);
+
+  nitems = Fwrite (catalog[0].header.buffer, 1, catalog[0].header.size, f, "char");
+  if (nitems != catalog[0].header.size) {
+    fprintf (stderr, "ERROR: failed to write header\n");
+    exit (0);
+  }
+
+  Nitems = catalog[0].Naverage;
+  nitems = Fwrite (catalog[0].average, sizeof(Average), Nitems, f, "average");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to write catalog file aves %s\n", filename);
+    exit (0);
+  }
+  
+  Nitems = catalog[0].Nmeasure;
+  nitems = Fwrite (catalog[0].measure, sizeof(Measure), Nitems, f, "measure");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to write catalog file meas %s\n", filename);
+    exit (0);
+  }
+
+  Nitems = catalog[0].Nmissing;
+  nitems = Fwrite (catalog[0].missing, sizeof(Missing), Nitems, f, "missing");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to write catalog file miss %s\n", filename);
+    exit (0);
+  }
+
+  fclose (f);
+
+}
+
Index: /tags/start/Ohana/src/delstar/Makefile
===================================================================
--- /tags/start/Ohana/src/delstar/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/delstar/Makefile	(revision 12606)
@@ -0,0 +1,63 @@
+include ../../Configure
+CC      =       gcc -g  # override this for now for minimal test
+HOME 	=	$(ROOT)/src/delstar
+CONFIG  =	$(ROOT)/config
+PROGRAM =       delstar
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#  
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lFITS -lohana -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS)
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+DELSTAR = \
+$(SRC)/delstar.$(ARCH).o 	$(SRC)/gcatalog.$(ARCH).o   	\
+$(SRC)/gregions.$(ARCH).o 	$(SRC)/gimages.$(ARCH).o    	\
+$(SRC)/dimages.$(ARCH).o        $(SRC)/gtimes.$(ARCH).o     	\
+$(SRC)/find_matches.$(ARCH).o 	$(SRC)/wcatalog.$(ARCH).o   	\
+$(SRC)/ConfigInit.$(ARCH).o 	$(SRC)/args.$(ARCH).o	        \
+$(SRC)/aregion.$(ARCH).o	$(SRC)/delete_missed.$(ARCH).o  \
+$(SRC)/sort_lists.$(ARCH).o	$(SRC)/parse_time.$(ARCH).o     \
+$(SRC)/gcatstats.$(ARCH).o	$(SRC)/find_images.$(ARCH).o	\
+$(SRC)/match_images.$(ARCH).o	$(SRC)/delete_orphans.$(ARCH).o
+
+OBJ = $(DELSTAR)
+
+default: $(PROGRAM)
+
+$(DELSTAR): $(INC)/delstar.h
+
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:	
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
+
+
Index: /tags/start/Ohana/src/delstar/include/addstar.h
===================================================================
--- /tags/start/Ohana/src/delstar/include/addstar.h	(revision 12606)
+++ /tags/start/Ohana/src/delstar/include/addstar.h	(revision 12606)
@@ -0,0 +1,13 @@
+# include <ohana.h>
+# include <loneos.h>
+
+/* global variables set in parameter file */
+char   ImageCat[256];
+char   ImageTemplate[256];
+char   CatTemplate[256];
+char   GSCFILE[256];
+char   CATDIR[256];
+double NSIGMA;
+double ALPHA;
+int    VERBOSE;
+
Index: /tags/start/Ohana/src/delstar/include/delstar.h
===================================================================
--- /tags/start/Ohana/src/delstar/include/delstar.h	(revision 12606)
+++ /tags/start/Ohana/src/delstar/include/delstar.h	(revision 12606)
@@ -0,0 +1,25 @@
+# include <ohana.h>
+# include <loneos.h>
+# include <signal.h>
+
+/* global variables set in parameter file */
+char   ImageCat[256];
+char   ImageTemplate[256];
+char   CatTemplate[256];
+char   GSCFILE[256];
+char   CATDIR[256];
+double NSIGMA;
+double ALPHA;
+int    VERBOSE;
+int    ORPHAN;
+int    MISSED;
+
+typedef struct {
+  Coords coords;
+  float *X, *Y;
+  int *N;
+  double RA[2], DEC[2];
+  double Area, density, spacing;
+} CatStats;
+
+char DateKeyword[64], DateMode[64], UTKeyword[64], MJDKeyword[64], JDKeyword[64];
Index: /tags/start/Ohana/src/delstar/src/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/delstar/src/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/delstar/src/ConfigInit.c	(revision 12606)
@@ -0,0 +1,40 @@
+# include "delstar.h"
+
+ConfigInit (int *argc, char **argv) {
+
+  char *config, *file;
+  char PhotCodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (1);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  ScanConfig (config, "NSIGMA",                 "%lf", 0, &NSIGMA);
+  ScanConfig (config, "ALPHA",                  "%lf", 0, &ALPHA);
+  ScanConfig (config, "IMAGE_CATALOG",          "%s", 0, ImageCat);
+  ScanConfig (config, "IMAGE_CATALOG_TEMPLATE", "%s", 0, ImageTemplate);
+  ScanConfig (config, "CATALOG_TEMPLATE",       "%s", 0, CatTemplate);
+  ScanConfig (config, "GSCFILE",                "%s", 0, GSCFILE);
+  ScanConfig (config, "CATDIR",                 "%s", 0, CATDIR);
+  ScanConfig (config, "PHOTCODE_FILE",          "%s", 0, PhotCodeFile);
+
+  ScanConfig (config, "DATE-KEYWORD",           "%s", 0, DateKeyword);
+  ScanConfig (config, "DATE-MODE",              "%s", 0, DateMode);
+  ScanConfig (config, "UT-KEYWORD",             "%s", 0, UTKeyword);
+  ScanConfig (config, "MJD-KEYWORD",            "%s", 0, MJDKeyword);
+  ScanConfig (config, "JD-KEYWORD",             "%s", 0, JDKeyword);
+
+  if (!LoadPhotcodes (PhotCodeFile)) {
+    fprintf (stderr, "error loading photcodes\n");
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+}
Index: /tags/start/Ohana/src/delstar/src/aregion.c
===================================================================
--- /tags/start/Ohana/src/delstar/src/aregion.c	(revision 12606)
+++ /tags/start/Ohana/src/delstar/src/aregion.c	(revision 12606)
@@ -0,0 +1,186 @@
+# include "delstar.h"
+
+double BigDecBounds[] = {0.0, 7.5, 15.0, 22.5, 30.0, 37.5, 45.0, 
+			 52.5, 60.0, 67.5, 75.0, 82.5, 90.0,
+			 0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, 
+			 -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+char *DecSections[] = {"N0000", "N0730", "N1500", "N2230", "N3000", "N3730", "N4500", 
+		       "N5230", "N6000", "N6730", "N7500", "N8230", "weirdness", 
+		       "S0000", "S0730", "S1500", "S2230", "S3000", "S3730", "S4500", 
+		       "S5230", "S6000", "S6730", "S7500", "S8230", "weirdness"};
+
+char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			"n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			"s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			"s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+char *disk[] = {"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", 
+		"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "weirdness", 
+		"disk 1", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", 
+		"disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "weirdness"};
+
+int NBigRASections [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3, 48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3};
+
+int NDecLines[] = {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 24, 
+                   0, 597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48};
+
+/* find region file which contains ra, dec */
+aregion (region, f, ra, dec) 
+GSCRegion region[];
+FILE *f;
+double ra, dec;
+{
+  
+  
+  char buffer[28800], temp[50], file[50];
+  double dr, dd;
+  double RA0, RA1, DEC0, DEC1;
+  int i, NBigDec, NLINES, done, nregion;
+  
+  while (ra < 0) { ra += 360.0; }
+  while (ra >= 360.0) { ra -= 360.0; }
+    
+  if (dec >= 86.25) {
+    sprintf (file, "%s/n8230/pole.cpt\0", CATDIR);
+    region[0].DEC[0] = 86.25;
+    region[0].DEC[1] = 93.75;
+    region[0].RA[0] = -180.0;
+    region[0].RA[1] =  540.0;
+    strcpy (region[0].filename, file);
+    return;
+  }
+    
+  NBigDec = -1;
+  for (i = 0; i < 12; i++) {
+# ifdef DEBUG
+    fprintf (stderr, "%d %f %f %f\n", i, dec, BigDecBounds[i], BigDecBounds[i+1]);
+# endif
+    if ((dec >= BigDecBounds[i]) && (dec < BigDecBounds[i+1])) {
+      NBigDec = i;
+      break;
+    }
+  }
+  if (NBigDec < 0) {
+    for (i = 13; i < 24; i++) {
+# ifdef DEBUG
+      fprintf (stderr, "%d %f %f %f\n", i, dec, BigDecBounds[i], BigDecBounds[i+1]);
+# endif
+      if ((dec < BigDecBounds[i]) && (dec >= BigDecBounds[i+1])) {
+	NBigDec = i;
+	break;
+      }
+    }
+  }
+  if (NBigDec < 0) {
+    fprintf (stderr, "dec out of range: %f\n", dec);
+  }
+    
+  NLINES = 0;
+  for (i = 0; i < NBigDec; i++) {
+    NLINES += NDecLines[i];
+  }
+  fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+      
+  done = FALSE;
+  Fread (buffer, 1, 48*NDecLines[NBigDec], f, "char");
+  for (i = 0; !done && (i < NDecLines[NBigDec]); i++) {
+    strncpy (temp, &buffer[i*48], 48);
+    temp[49] = 0;
+    hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+    if (RA1 < RA0) RA1 += 360.0;
+# ifdef DEBUG
+    fprintf (stderr, "%f %f %f  %f %f %f  %s\n", DEC0, dec, DEC1, RA0, ra, RA1, temp);
+# endif
+    if ((dec >= 0) && (dec >= DEC0) && (dec < DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+    if ((dec < 0) && (dec < DEC0) && (dec >= DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+  }
+  if (!done) {
+    fprintf (stderr, "error in search: %f %f\n", ra, dec);
+    exit (1);
+  }
+  temp[5] = 0;
+  sprintf (file, "%s/%s/%s.cpt\0", CATDIR, Dec2Sections[NBigDec],&temp[1]);
+  if (DEC0 < DEC1) {
+    region[0].DEC[0] = DEC0;
+    region[0].DEC[1] = DEC1;
+  } else {
+    region[0].DEC[0] = DEC1;
+    region[0].DEC[1] = DEC0;
+  }     
+  region[0].RA[0] = RA0;
+  region[0].RA[1] = RA1;
+  strcpy (region[0].filename, file);
+  return;
+}
+
+
+/**********/
+int hms_to_deg (h0, h1, d0, d1, string) 
+     char *string;
+     double *h0, *h1, *d0, *d1;
+{
+  
+  int flag_d0, flag_d1, flag_h0, flag_h1;
+  double tmp;
+  
+  *d0 = *h0 = *d1 = *h1 = 0;
+
+  flag_h0 = dparse (h0, 1, string);
+  flag_h1 = dparse (h1, 4, string);
+  flag_d0 = dparse (d0, 7, string);
+  flag_d1 = dparse (d1, 9, string);
+  *h0 *= flag_h0;
+  *h1 *= flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  dparse (&tmp, 2, string);
+  *h0 += tmp/60.0;
+  dparse (&tmp, 3, string);
+  *h0 += tmp/3600.0;
+  
+  dparse (&tmp, 5, string);
+  *h1 += tmp/60.0;
+  dparse (&tmp, 6, string);
+  *h1 += tmp/3600.0;
+  
+  dparse (&tmp, 8, string);
+  *d0 += tmp/60.0;
+
+  dparse (&tmp, 10, string);
+  *d1 += tmp/60.0;
+
+  *h0 *= 15*flag_h0;
+  *h1 *= 15*flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  return (TRUE);
+}
+
+
+/*
+      if (buffer[i*48 + 19] == ' ') continue;
+      strncpy (temp, &buffer[i*48 + 19], 20);       temp[20] = 0;
+      hms_to_deg (&RA,  &DEC, temp, ' ', 3);
+
+
+  dBigRA = 360.0 / (int)(0.5 + 48*cos(3.1415927*0.5*(BigDecBounds[NBigDec] + BigDecBounds[NBigDec + 1])/180.0));
+
+  NBigRA = ra / dBigRA;
+
+  NBig = NBigRA;
+  for (i = 0; (i < 12) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+  for (i = 13; (i < 24) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+
+
+  fprintf (stderr, "%d %d %d %d %f %f -> %f %f %f\n", NBigDec, NBigRA, NBigRASections[NBigDec], NBig, ra, dec, BigDecBounds[NBigDec], BigDecBounds[NBigDec + 1], dBigRA);
+*/
Index: /tags/start/Ohana/src/delstar/src/args.c
===================================================================
--- /tags/start/Ohana/src/delstar/src/args.c	(revision 12606)
+++ /tags/start/Ohana/src/delstar/src/args.c	(revision 12606)
@@ -0,0 +1,49 @@
+# include "delstar.h"
+
+void help () {
+
+  fprintf (stderr, "USAGE: delstar (filename) or (start range) or -orphan (region)\n");
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -v (verbose mode)\n");
+  fprintf (stderr, "\n"); 
+  exit (2);
+
+}
+
+int args (int *argc, char **argv) {
+  
+
+  int N;
+
+  ConfigInit (argc, argv);
+
+  /* check for help request */
+  if (get_argument (*argc, argv, "-help") ||
+      get_argument (*argc, argv, "-h")) {
+    help ();
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (*argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  ORPHAN = FALSE;
+  if ((N = get_argument (*argc, argv, "-orphan"))) {
+    ORPHAN = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  MISSED = FALSE;
+  if ((N = get_argument (*argc, argv, "-missed"))) {
+    MISSED = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  if ((*argc != 2) && (*argc != 3)) {
+    fprintf (stderr, "ERROR: Usage: delstar (filename) or (start range) or -orphan (region)\n");
+    exit (2);
+  }
+
+}
Index: /tags/start/Ohana/src/delstar/src/delete_missed.c
===================================================================
--- /tags/start/Ohana/src/delstar/src/delete_missed.c	(revision 12606)
+++ /tags/start/Ohana/src/delstar/src/delete_missed.c	(revision 12606)
@@ -0,0 +1,22 @@
+# include "delstar.h"
+
+delete_missed (Catalog *catalog) {
+
+  int i;
+  int Nave, Nmeas, Nmiss;
+
+  Nave = catalog[0].Naverage;
+  Nmeas = catalog[0].Nmeasure;
+  Nmiss = catalog[0].Nmissing;
+  
+  if (VERBOSE) fprintf (stderr, "starting with Nave, Nmeas, Nmiss: %d %d %d\n", Nave, Nmeas, Nmiss);
+
+  /* set up references for missing to average */
+  for (i = 0; i < Nave; i++) {
+    catalog[0].average[i].Nn = 0;
+  }
+  REALLOCATE (catalog[0].missing, Missing, 1);
+  catalog[0].Nmissing = 0;
+  if (VERBOSE) fprintf (stderr, "  ending with Nave, Nmeas, Nmiss: %d %d %d\n", Nave, Nmeas, Nmiss);
+}
+
Index: /tags/start/Ohana/src/delstar/src/delete_orphans.c
===================================================================
--- /tags/start/Ohana/src/delstar/src/delete_orphans.c	(revision 12606)
+++ /tags/start/Ohana/src/delstar/src/delete_orphans.c	(revision 12606)
@@ -0,0 +1,248 @@
+# include "delstar.h"
+
+delete_orphans (Catalog *catalog) {
+
+  int i, j, k, n, m, N, M, found;
+  int *N1, *N2,  *next, *next_miss, *ave_miss, last, last_miss;
+  int Nave, NAVE, Nmeas, NMEAS, Nmiss, NMISS, Nmatch;
+  int start, end, Nmeasfound, Nsecfilt;
+  unsigned int flags;
+  Measure *tmpmeasure;
+  Missing *tmpmissing;
+  Coords tcoords;
+
+
+  /** allocate local arrays **/
+  Nave = catalog[0].Naverage;
+
+  Nmeas = catalog[0].Nmeasure;
+  ALLOCATE (next, int, Nmeas);
+  
+  Nmiss = catalog[0].Nmissing;
+  ALLOCATE (next_miss, int, Nmiss);
+  ALLOCATE (ave_miss, int, Nmiss);
+  
+  if (VERBOSE) fprintf (stderr, "starting with Nave, Nmeas, Nmiss: %d %d %d\n", Nave, Nmeas, Nmiss);
+
+  /* set up pointers for linked list of measure */
+  for (i = 0; i < Nmeas - 1; i++) {
+    next[i] = i+1;
+  }
+  next[i] = -1;
+  last = i;
+  /* set up pointers for linked list of missing */
+  for (i = 0; i < Nmiss - 1; i++) {
+    next_miss[i] = i+1;
+  }
+  next_miss[i] = -1;
+  last_miss = i;
+  /* set up references for missing to average */
+  for (i = 0; i < Nave; i++) {
+    for (j = 0; j < catalog[0].average[i].Nn; j++) {
+      ave_miss[catalog[0].average[i].missing + j] = i;
+    }
+  }
+  Nmeasfound = 0;
+  Nsecfilt = catalog[0].Nsecfilt;
+
+  /* fprintf (stderr, "fixing the measures...\n"); */
+  for (i = 0; (i < Nmeas); i++) {
+    if ((catalog[0].measure[i].t != 0) && (catalog[0].image[i] == -1)) { 
+      /* this star is an orphan */
+      Nmeasfound ++;
+      next[i] = -2; /* we delete this one */
+      /* fix the list links: connect the previous valid link to the next valid link */
+      for (j = i; (j >= 0) && (next[j] == -2); j--); /* find previous entry to fix link */
+      if (j >= 0) { /* if j < 0, there is no previous valid link, ignore this step */
+	if (next[j] != i) {
+	  fprintf (stderr, "error?  this link seems to have been lost\n");
+	  exit (1);
+	}
+	/* find next valid entry to fix link */
+	for (k = i; (k < Nmeas) && (next[k] == -2); k++);
+	if (k < Nmeas)
+	  next[j] = k;
+	else 
+	  next[j] = -1;  /* last link in list gets a -1 */
+      }
+      
+      /*** fix the corresponding average entry ***/
+      n = catalog[0].measure[i].averef;
+      if (catalog[0].average[n].Nm == 0) { /* this should never happen */
+	fprintf (stderr, "error? we deleted one too many objects?\n");
+	exit (1);
+      }
+      catalog[0].average[n].Nm --;
+      /* this was only entry in list: will be deleted below.  meanwhile, delete all missing entries*/
+      if ((catalog[0].average[n].Nm < 1) && (catalog[0].average[n].Nn > 0)) { 
+	m = catalog[0].average[n].missing;
+	for (j = 0; j < catalog[0].average[n].Nn; j++) {
+	  M = next_miss[m];
+	  next_miss[m] = -2;
+	  m = M;
+	}
+	m = catalog[0].average[n].missing;
+	/* fix the list links: connect the previous valid link to the next valid link */
+	for (j = m; (j >= 0) && (next_miss[j] == -2); j--); /* find previous entry to fix link */
+	if (j >= 0) { /* if j < 0, there is no previous valid link, ignore this step */
+	  if (next_miss[j] != m) {
+	    fprintf (stderr, "error?  this link seems to have been lost\n");
+	    exit (1);
+	  }
+	  /* find next valid entry to fix link */
+	  for (k = m; (k < Nmiss) && (next_miss[k] == -2); k++);
+	  if (k < Nmiss)
+	    next_miss[j] = k;
+	  else 
+	    next_miss[j] = -1;  /* last link in list gets a -1 */
+	}
+      }
+      /* this was first entry in list */
+      if ((catalog[0].average[n].offset == i) && (catalog[0].average[n].Nm > 0)) { 
+	m = catalog[0].average[n].offset;
+	/* find next valid entry -- notice lack of error checking... */
+	for (j = 0; (j < Nmeas) && (next[m+j] == -2); j++);
+	catalog[0].average[n].offset = m + j;
+      }
+
+    }
+  }
+  fprintf (stderr, "found %d meas to remove\n", Nmeasfound);
+
+  /* fprintf (stderr, "fixing the missing...\n"); */
+  /** find missing in time range of image **/
+  for (i = 0; (i < Nmiss); i++) {
+    if ((next_miss[i] != -2) && (catalog[0].missing[i].t >= start) && (catalog[0].missing[i].t <= end)) { 
+      /* this star is in this image */
+
+      next_miss[i] = -2; /* we delete this one */
+      /* fix the list links: connect the previous valid link to the next valid link */
+      for (j = i; (j >= 0) && (next_miss[j] == -2); j--); /* find previous entry to fix link */
+      if (j >= 0) { /* if j < 0, there is no previous valid link, ignore this step */
+	if (next_miss[j] != i) {
+	  fprintf (stderr, "error?  this link seems to have been lost\n");
+	  exit (1);
+	}
+	/* find next valid entry to fix link */
+	for (k = i; (k < Nmiss) && (next_miss[k] == -2); k++);
+	if (k < Nmiss)
+	  next_miss[j] = k;
+	else 
+	  next_miss[j] = -1;  /* last link in list gets a -1 */
+      }
+      
+      /* find the corresponding avearge entry 
+      found = FALSE;
+      for (n = 0; !found && (n < Nave); n++) {
+	if ((catalog[0].average[n].missing > 0) && (catalog[0].average[n].missing <= i) && (catalog[0].average[n].missing + catalog[0].average[n].Nn > i)) 
+	  found = TRUE;
+      }
+      n--; */
+      /*** fix the corresponding average entry ***/
+      n = ave_miss[i];
+      if (catalog[0].average[n].Nn == 0) { /* this should never happen */
+	fprintf (stderr, "error? we deleted one too many missing?\n");
+	exit (1);
+      }
+      catalog[0].average[n].Nn --;
+      /* this was first entry in list */
+      if ((catalog[0].average[n].missing == i) && (catalog[0].average[n].Nn > 0)) { 
+	m = catalog[0].average[n].missing;
+	for (j = 0; (j < Nmiss) && (next_miss[m+j] == -2); j++);
+	catalog[0].average[n].missing = m + j;
+      }
+
+    }
+  }
+
+  /* currently not worked out, but we will need to delete the references to blended image and cat stars */
+# if 0
+  /*** handle multiple stars */
+  /* this image star matches more than one catalog star */
+  if (stars[N].found > -1) {
+    catalog[0].measure[stars[N].found].flags |= BLEND_IMAGE;
+    catalog[0].measure[Nmeas].flags |= BLEND_IMAGE;
+  } 
+  if (stars[N].found == -2) { /* this image star matches a catalog star on a neighboring catalog */
+    catalog[0].measure[Nmeas].flags |= BLEND_IMAGE_NEIGHBOR;
+  } 
+  if (stars[N].found == -1) { /* this image star matches only this star */
+    stars[N].found = Nmeas;  /* save first match, in case coincidences are found */
+  }
+  /* this catalog star matches more than one image star */
+  if (catalog[0].found[n] > -1) {
+    catalog[0].measure[catalog[0].found[n]].flags |= BLEND_CATALOG;
+    catalog[0].measure[Nmeas].flags |= BLEND_CATALOG;
+  } else {
+    catalog[0].found[n] = Nmeas;
+  }
+# endif  
+
+  /* fprintf (stderr, "fixing the averages...\n"); */
+  /* fix Average list: delete entries with Nm == 0 */
+  for (i = j = 0; (i < Nave) && (j < Nave); i++, j++) {
+    for (; (j < Nave) && (catalog[0].average[j].Nm == 0); j++);
+    if ((i != j) && (j < Nave)) {
+      catalog[0].average[i] = catalog[0].average[j];
+      for (k = 0; k < catalog[0].Nsecfilt; k++) {
+	catalog[0].secfilt[i*Nsecfilt + k] = catalog[0].secfilt[j*Nsecfilt + k];
+      }
+    }
+    if (j == Nave) i--;
+  }
+  Nave = i;
+  REALLOCATE (catalog[0].average, Average, Nave);
+  REALLOCATE (catalog[0].secfilt, SecFilt, MAX (1, Nave*Nsecfilt));
+  
+  /* fprintf (stderr, "fixing the measure order...\n"); */
+  /* fix order of Measure (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmeasure, Measure, Nmeas);
+  for (i = 0; i < Nave; i++) {
+    n = catalog[0].average[i].offset;
+    catalog[0].average[i].offset = N;
+    for (k = 0; k < catalog[0].average[i].Nm; k++, N++) {
+      if ((n == -1) || (n == -2)) {
+	fprintf (stderr, "error: linked list is confused\n");
+	exit (1);
+      }
+      tmpmeasure[N] = catalog[0].measure[n]; 
+      tmpmeasure[N].averef = i;
+      n = next[n];
+    }
+  }
+  Nmeas = N;
+  free (catalog[0].measure);
+  catalog[0].measure = tmpmeasure;
+  REALLOCATE (catalog[0].measure, Measure, Nmeas);
+    
+  /* fprintf (stderr, "fixing the mising order...\n"); */
+  /* fix order of Missing (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmissing, Missing, Nmiss);
+  for (i = 0; i < Nave; i++) {
+    if (catalog[0].average[i].Nn > 0) {
+      n = catalog[0].average[i].missing;
+      catalog[0].average[i].missing = N;
+      for (k = 0; k < catalog[0].average[i].Nn; k++, N++) {
+	if ((n == -1) || (n == -2)) {
+	  fprintf (stderr, "error: linked list is confused\n");
+	  exit (1);
+	}
+	tmpmissing[N] = catalog[0].missing[n]; 
+	n = next_miss[n];
+      }
+    }
+  }
+  Nmiss = N;
+  free (catalog[0].missing);
+  catalog[0].missing = tmpmissing;
+  REALLOCATE (catalog[0].missing, Missing, Nmiss);
+
+  catalog[0].Naverage = Nave;
+  catalog[0].Nmeasure = Nmeas;
+  catalog[0].Nmissing = Nmiss;
+  if (VERBOSE) fprintf (stderr, "  ending with Nave, Nmeas, Nmiss: %d %d %d\n", Nave, Nmeas, Nmiss);
+
+}
+
Index: /tags/start/Ohana/src/delstar/src/delstar.c
===================================================================
--- /tags/start/Ohana/src/delstar/src/delstar.c	(revision 12606)
+++ /tags/start/Ohana/src/delstar/src/delstar.c	(revision 12606)
@@ -0,0 +1,212 @@
+# include "delstar.h"
+
+/* these variables are needed by Shutdown */
+static FILE *f = (FILE *) NULL;
+static int Protect = FALSE;
+static int Trapped = FALSE;
+
+/* clean up open / locked ImageCat before shutting down */
+int Shutdown () {  
+  int dbstate;
+
+  Protect = TRUE;
+  fclearlockfile (ImageCat, f, LCK_HARD, &dbstate);
+  fprintf (stderr, "ERROR: delstar halted\n");
+  exit (1);
+}
+
+void TrapSignal (int sig) {
+    fprintf (stderr, "trapped signal %d, exiting gracefully\n", sig);
+    if (sig == 11) {
+      fprintf (stderr, "seg fault\n");
+      exit (1);
+    }
+    if (Protect) {
+      Trapped = TRUE;
+      fprintf (stderr, "blocking until protected sections are clear\n");
+      return;
+    }
+    Shutdown ();
+}    
+
+main (int argc, char **argv) {
+
+  int i, j, k, found, Nimage, Nregions, Ntregions, NREGIONS;
+  int start, end, dbstate;
+  Image *image, *gimages(), *gtimes(), *find_images();
+  Catalog catalog;
+  CatStats catstats;
+  GSCRegion *region, *tregion, *gregions();
+  
+  SetSignals ();
+  args (&argc, argv);
+
+  /* lock the image catalog */
+  f = fsetlockfile (ImageCat, 3600.0, LCK_HARD, &dbstate);
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't lock image catalog\n");
+    exit (1);
+  }
+  fseek (f, 0, SEEK_SET);
+
+  /* delete orphaned measurements (no image) from catalog */ 
+  if (ORPHAN) {
+    ALLOCATE (region, GSCRegion, 1);
+    catalog.filename = argv[1];
+    gcatalog (&catalog);
+    gcatstats (&catalog, &catstats);
+    image = find_images (f, &catstats, &Nimage);
+    match_images (&catalog, image, Nimage);
+    delete_orphans (&catalog);
+    wcatalog (&catalog);
+    fclearlockfile (ImageCat, f, LCK_HARD, &dbstate);
+    fprintf (stderr, "SUCCESS\n");
+    exit (0);
+  } 
+
+  /* delete missed measurements from catalog */ 
+  if (MISSED) {
+    catalog.filename = argv[1];
+    switch (lock_catalog (&catalog, LCK_XCLD)) {
+    case 0:
+      fprintf (stderr, "ERROR: can't lock file\n");
+      exit (1);
+    case 1:
+      gcatalog (&catalog);
+      break;
+    case 2:
+      fprintf (stderr, "no data in %s, skipping\n", catalog.filename);
+      catalog.Naverage = 0;
+      catalog.Nmeasure = 0;
+      break;
+    default:
+      fprintf (stderr, "weird lock_catalog exit state\n");
+      exit (1);
+    }
+    delete_missed (&catalog);
+    wcatalog (&catalog);
+    fclearlockfile (ImageCat, f, LCK_HARD, &dbstate);
+    fprintf (stderr, "SUCCESS\n");
+    exit (0);
+  } 
+
+  /* delete given image from catalogs */
+  if (argc == 2) {
+    image = gimages (argv[1]);
+  
+    fprintf (stderr, "deleting %s\n", image[0].name);
+    region = gregions (&image[0], &Nregions);
+
+    for (i = 0; i < Nregions; i++) {
+      fprintf (stderr, "deleting from %s\n", region[i].filename);
+      catalog.filename = region[i].filename;  /* don't free region before catalog! */
+      switch (lock_catalog (&catalog, LCK_SOFT)) {
+      case 0:
+	fprintf (stderr, "ERROR: can't lock file\n");
+	exit (1);
+      case 1:
+	gcatalog (&catalog);
+	break;
+      case 2:
+	fprintf (stderr, "no data in %s, skipping\n", catalog.filename);
+	catalog.Naverage = 0;
+	catalog.Nmeasure = 0;
+	break;
+      default:
+	fprintf (stderr, "weird lock_catalog exit state\n");
+	exit (1);
+      }
+      find_matches (&catalog, &image[0], 0, 0);
+      wcatalog (&catalog);
+    }
+
+    dimages (f, image, 1); 
+    fclearlockfile (ImageCat, f, LCK_HARD, &dbstate);
+    fprintf (stderr, "SUCCESS\n");
+    exit (0);
+  }
+
+  /* delete measurements in time range */
+  if (argc == 3) {
+    Nregions = 0;
+    NREGIONS = 10;
+    ALLOCATE (region, GSCRegion, NREGIONS);
+
+    /* find image for time range, delete each image */ 
+    image = gtimes (f, argv, &Nimage, &start, &end);
+    for (j = 0; j < Nimage; j++) {
+      fprintf (stderr, "finding regions for %s\n", image[j].name);
+      tregion = gregions (&image[j], &Ntregions);
+      for (i = 0; i < Ntregions; i++) {
+	found = FALSE;
+	for (k = 0; (k < Nregions) && !found; k++) {
+	  found = !strcmp (region[k].filename, tregion[i].filename);
+	}
+	if (!found) {
+	  strcpy (region[Nregions].filename, tregion[i].filename);
+	  region[Nregions].RA[0] = tregion[i].RA[0];
+	  region[Nregions].RA[1] = tregion[i].RA[1];
+	  region[Nregions].DEC[0] = tregion[i].DEC[0];
+	  region[Nregions].DEC[1] = tregion[i].DEC[1];
+	  Nregions ++;
+	  if (Nregions >= NREGIONS) {
+	    NREGIONS += 10;
+	    REALLOCATE (region, GSCRegion, NREGIONS);
+	  }
+	}
+      }
+    }
+    for (i = 0; i < Nregions; i++) {
+      fprintf (stderr, "deleting from %s\n", region[i].filename);
+      catalog.filename = region[i].filename;  /* don't free region before catalog! */
+      switch (lock_catalog (&catalog, LCK_SOFT)) {
+      case 0:
+	fprintf (stderr, "ERROR: can't lock file\n");
+	exit (1);
+      case 1:
+	gcatalog (&catalog);
+	break;
+      case 2:
+	fprintf (stderr, "no data in %s, skipping\n", catalog.filename);
+	catalog.Naverage = 0;
+	catalog.Nmeasure = 0;
+	break;
+      default:
+	fprintf (stderr, "weird lock_catalog exit state\n");
+	exit (1);
+      }
+      find_matches (&catalog, &image[0], start, end);
+      wcatalog (&catalog);
+    }
+    dimages (f, image, Nimage);
+    fclearlockfile (ImageCat, f, LCK_HARD, &dbstate);
+    fprintf (stderr, "SUCCESS\n");
+    exit (0);
+  }
+}
+
+int SetSignals () {
+
+  int i;
+
+  /* disable almost all signal interrupts */
+  for (i = 0; i < 36; i++) {
+    switch (i) {
+      /* can't redirect this signals */
+    case SIGKILL:    /* kill -9: cannot be caught or ignored */
+    case SIGSTOP:    /* SIGSTOP: cannot be caught or ignored */
+      /* ignore these signals */
+    case SIGCHLD:    /* child halted: ignore */
+    case SIGPWR:     /* power failure - why ignore this? */
+    case SIGWINCH:   /* window resized */
+    case SIGCONT:    /* continue - maintain this action */
+    case SIGTSTP:    /* stop signal sent from tty - why ignore? */
+    case SIGURG:     /* socket signal, ignore this */
+      break;
+      
+    default:
+      signal (i, TrapSignal);
+    }
+  }
+
+}
Index: /tags/start/Ohana/src/delstar/src/dimages.c
===================================================================
--- /tags/start/Ohana/src/delstar/src/dimages.c	(revision 12606)
+++ /tags/start/Ohana/src/delstar/src/dimages.c	(revision 12606)
@@ -0,0 +1,72 @@
+# include "addstar.h"
+
+dimages (FILE *f, Image *image, int Nimages) {
+  
+  int i, j, Ntimage, ntimage, mode;
+  int start, end, tstart, tend, status;
+  char line[256];
+  struct stat filestat;
+  Image *timage;
+  Header header;
+
+  /* use cp to make backup copy */
+  sprintf (line, "cp %s %s~\0", ImageCat, ImageCat);
+  status = system (line);
+  if (status) {
+    fprintf (stderr, "ERROR: unable to create %s~, exiting\n", ImageCat);
+    Shutdown ();
+  }
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  sprintf (line, "%s~\0", ImageCat);
+  chmod (line, mode);
+
+  /* check if image datafile exists, get header */
+  fseek (f, 0, SEEK_SET); 
+  if (!fits_fread_header (f, &header)) {
+    fprintf (stderr, "Can't find image catalog\n");
+    exit (1);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  fits_scan (&header, "NIMAGES", "%d", 1, &Ntimage);
+  ALLOCATE (timage, Image, Ntimage);
+  ntimage = Fread (timage, sizeof(Image), Ntimage, f, "image");
+  if (Ntimage != ntimage) {
+    fprintf (stderr, "failed to read in entire image file %s\n", ImageCat);
+    exit (1);
+  }
+
+  /* need to delete on basis of both image time & photcode */
+  /* first, mark the deleted images with a flag (NX = 0) */
+  for (i = 0; i < Ntimage; i++) {
+    for (j = 0; j < Nimages; j++) {
+      tstart = timage[i].tzero;
+      tend = timage[i].tzero + timage[i].trate * timage[i].NY;
+      start = image[j].tzero;
+      end = image[j].tzero + image[j].trate * image[j].NY;
+      if ((tstart <= end) && (tend >= start) && (timage[i].source == image[j].source)) {
+	fprintf (stderr, "deleting %s\n", timage[i].name);
+	timage[i].NX = 0;
+      }
+    }
+  }
+
+  /* delete the marked images */
+  for (i = 0, j = 0; j < Ntimage; j++) {
+    if (timage[j].NX) {
+      if (i != j) {
+	timage[i] = timage[j];
+      }
+      i++;
+    }
+  }
+  Ntimage = i;
+  REALLOCATE (timage, Image, Ntimage);
+  fits_modify (&header, "NIMAGES", "%d", 1, Ntimage);
+
+  /* should make a backup copy of the ImageCat file */
+  fseek (f, 0, SEEK_SET);
+  Fwrite (header.buffer, 1, header.size, f, "char");
+  Fwrite (timage, sizeof(Image), Ntimage, f, "image");
+
+}
Index: /tags/start/Ohana/src/delstar/src/find_images.c
===================================================================
--- /tags/start/Ohana/src/delstar/src/find_images.c	(revision 12606)
+++ /tags/start/Ohana/src/delstar/src/find_images.c	(revision 12606)
@@ -0,0 +1,190 @@
+# include "delstar.h"
+double opening_angle ();
+
+Image *find_images (FILE *f, CatStats *catstats, int *Nimages) {
+  
+  Header header;
+  Image *timage, *image;
+  int i, j, k, found, nimage, Nimage, NIMAGE, NTIMAGE, Nloop, Nlast;
+  int n, Nim, status;
+  double Xc[6], Yc[6], Xi[6], Yi[6], r, d, x, y, dx, dy;
+  Coords *tcoords;
+
+  /* we make positional comparisons in the projection of catalog */
+  tcoords = &catstats[0].coords;
+  /* define catalog corners */
+  Xc[0] = catstats[0].RA[0]; Yc[0] = catstats[0].DEC[0];
+  Xc[1] = catstats[0].RA[1]; Yc[1] = catstats[0].DEC[0];
+  Xc[2] = catstats[0].RA[1]; Yc[2] = catstats[0].DEC[1];
+  Xc[3] = catstats[0].RA[0]; Yc[3] = catstats[0].DEC[1];
+  Xc[4] = catstats[0].RA[0]; Yc[4] = catstats[0].DEC[0];
+  Xc[5] = catstats[0].RA[1]; Yc[5] = catstats[0].DEC[1];
+  for (j = 0; j < 6; j++) {
+    r = Xc[j]; d = Yc[j];
+    RD_to_XY (&Xc[j], &Yc[j], r, d, tcoords);
+  }
+  /* find Y positions of RA center */
+  r = 0.5*(catstats[0].RA[0] + catstats[0].RA[1]);
+  d = catstats[0].DEC[0];
+  RD_to_XY (&x, &y, r, d, tcoords);
+  Yc[0] = MIN (y, Yc[0]);
+  Yc[1] = MIN (y, Yc[1]);
+  Yc[4] = MIN (y, Yc[4]);
+  /* find Y positions of RA center */
+  r = 0.5*(catstats[0].RA[0] + catstats[0].RA[1]);
+  d = catstats[0].DEC[1];
+  RD_to_XY (&x, &y, r, d, tcoords);
+  Yc[2] = MAX (y, Yc[2]);
+  Yc[3] = MAX (y, Yc[3]);
+  Yc[5] = MAX (y, Yc[5]);
+
+  dx = 0.02*(Xc[2] - Xc[0]);
+  dy = 0.02*(Yc[2] - Yc[0]);
+  Xc[0] -= dx; Yc[0] -= dy;
+  Xc[1] += dx; Yc[1] -= dy;
+  Xc[2] += dx; Yc[2] += dy;
+  Xc[3] -= dx; Yc[3] += dy;
+  Xc[4] -= dx; Yc[4] -= dy;
+  Xc[5] -= dx; Yc[5] -= dy;
+
+  /* check if image datafile exists, get header, number of images */
+  if (!fits_fread_header (f, &header)) {
+    fprintf (stderr, "ERROR: error reading image catalog header\n");
+    exit (1);
+  }
+  Nimage = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+  if (Nimage == 0) {
+    fprintf (stderr, "ERROR: No images in catalog %s (1)\n", ImageCat);
+    Shutdown ();
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* set up buffers for images, temporary storage */
+  NTIMAGE = 100;
+  ALLOCATE (timage, Image, NTIMAGE);
+  NIMAGE = 100;
+  ALLOCATE (image, Image, NIMAGE);
+  nimage = 0;
+  Nloop = Nimage / NTIMAGE + 1;
+  Nlast = Nimage % NTIMAGE;
+  
+  /* read in images in groups of NTIMAGE (100) */
+  for (n = 0; n < Nloop; n++) {
+    Nim = (n == Nloop - 1) ? Nlast : NTIMAGE;
+    status = Fread (timage, sizeof(Image), Nim, f, "image");
+    if (status != Nim) {
+      fprintf (stderr, "ERROR: couldn't read images from image catalog: %s\n", ImageCat);
+      exit (1);
+    }
+    /* test each image in block */
+    for (i = 0; i < Nim; i++) {
+      /* define image corners */
+      Xi[0] = 0;            Yi[0] = 0;
+      Xi[1] = timage[i].NX; Yi[1] = 0;
+      Xi[2] = timage[i].NX; Yi[2] = timage[i].NY;
+      Xi[3] = 0;            Yi[3] = timage[i].NY;
+      Xi[4] = 0;            Yi[4] = 0;
+      Xi[5] = timage[i].NX; Yi[5] = timage[i].NY;
+      found = FALSE;
+      /* transform to tcoords */
+      if (catstats[0].DEC[1] > 86.25) { /* pole */
+	for (j = 0; j < 6; j++) {
+	  XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+	  if (d > catstats[0].DEC[0] - 0.5) found = TRUE;
+	}
+      } else {
+	for (j = 0; j < 6; j++) {
+	  XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+	  RD_to_XY (&Xi[j], &Yi[j], r, d, tcoords);
+	}
+	/* check if edges cross */
+	for (j = 0; (j < 5) && !found; j++) {
+	  for (k = 0; (k < 5) && !found; k++) {
+	    found |= edge_check (&Xi[j], &Yi[j], &Xc[k], &Yc[k]);
+	  }
+	}
+      }
+      if (found) {
+	image[nimage] = timage[i]; 
+	image[nimage].code = 0;
+	nimage ++;
+	if (nimage == NIMAGE) {
+	  NIMAGE += 100;
+	  REALLOCATE (image, Image, NIMAGE);
+	}
+      }
+    }
+  }
+      
+  if (VERBOSE) { 
+    for (i = 0; i < nimage; i++) {
+      XY_to_RD (&r, &d, 0.5*image[i].NX, 0.5*image[i].NY, &image[i].coords);
+      fprintf (stderr, "associated images: %d %8.4f %8.4f %10d %6d  %5.3f %6.3f %6.3f\n", 
+	       i, r, d, image[i].tzero, image[i].nstar, 0.001*image[i].secz, 
+	       0.001*image[i].Mcal, 0.001*image[i].dMcal);
+    }
+  }
+
+  REALLOCATE (image, Image, MAX (nimage, 1));
+  free (timage);
+  *Nimages = nimage;
+  return (image);
+}
+
+int edge_check (x1, y1, x2, y2)
+double *x1, *y1, *x2, *y2;
+{
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+double opening_angle (x1, y1, x2, y2, x3, y3)
+double x1, y1, x2, y2, x3, y3;
+{
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
Index: /tags/start/Ohana/src/delstar/src/find_matches.c
===================================================================
--- /tags/start/Ohana/src/delstar/src/find_matches.c	(revision 12606)
+++ /tags/start/Ohana/src/delstar/src/find_matches.c	(revision 12606)
@@ -0,0 +1,270 @@
+# include "delstar.h"
+
+find_matches (Catalog *catalog, Image *image, int start, int end) {
+
+  int i, j, k, n, m, N, M, found;
+  int *N1, *N2,  *next, *next_miss, *ave_miss, last, last_miss;
+  int Nave, NAVE, Nmeas, NMEAS, Nmiss, NMISS, Nmatch, photcode;
+  int Nmeasfound, Nsecfilt;
+  int this, prev;
+  unsigned int flags;
+  Measure *tmpmeasure;
+  Missing *tmpmissing;
+  Coords tcoords;
+
+  /** allocate local arrays **/
+  Nave = catalog[0].Naverage;
+
+  Nmeas = catalog[0].Nmeasure;
+  ALLOCATE (next, int, MAX(Nmeas,1));
+  
+  Nmiss = catalog[0].Nmissing;
+  ALLOCATE (next_miss, int, MAX(Nmiss,1));
+  ALLOCATE (ave_miss, int, MAX(Nmiss,1));
+  
+  if (VERBOSE) fprintf (stderr, "starting with Nave, Nmeas, Nmiss: %d %d %d\n", Nave, Nmeas, Nmiss);
+
+  /* set up pointers for linked list of measure */
+  for (i = 0; i < Nmeas - 1; i++) {
+    next[i] = i+1;
+  }
+  next[i] = -1;
+  last = i;
+  /* set up pointers for linked list of missing */
+  for (i = 0; i < Nmiss - 1; i++) {
+    next_miss[i] = i+1;
+  }
+  next_miss[i] = -1;
+  last_miss = i;
+  /* set up references for missing to average */
+  for (i = 0; i < Nave; i++) {
+    for (j = 0; j < catalog[0].average[i].Nn; j++) {
+      ave_miss[catalog[0].average[i].missing + j] = i;
+    }
+  }
+  photcode = -1;
+  if ((start == 0) && (end == 0)) {
+    start = image[0].tzero;
+    end   = image[0].tzero + 1e-4*image[0].NY*image[0].trate;  /* trate is in 0.1 msec / row */
+    photcode = image[0].source;
+  }
+  if (VERBOSE) fprintf (stderr, "deleting for range %d to %d (photcode %d)\n", start, end, photcode);
+  Nmeasfound = 0;
+  Nsecfilt = catalog[0].Nsecfilt;
+
+  /* fprintf (stderr, "fixing the measures...\n"); */
+  /** find measure in time range of image **/
+  this = prev = -1;
+  for (i = 0; (i < Nmeas); i++) {
+    if ((i % 10000) == 0) fprintf (stderr, ". ");
+    if ((catalog[0].measure[i].t >= start) && (catalog[0].measure[i].t <= end) && (photcode == catalog[0].measure[i].source)) { 
+      Nmeasfound ++;
+      /* this star is in this image */
+      this = next[i];
+      next[i] = -2; /* we delete this one */
+      if (prev != -1) { next[prev] = this; }
+# if (0) 
+      /* why is this section disabled? */
+      /* fix the list links: connect the previous valid link to the next valid link */
+      for (j = i; (j >= 0) && (next[j] == -2); j--); /* find previous entry to fix link */
+      if (j >= 0) { /* if j < 0, there is no previous valid link, ignore this step */
+	if (next[j] != i) {
+	  fprintf (stderr, "error? (1)  this link seems to have been lost\n");
+	  fprintf (stderr, "j: %d, next[j]: %d, i: %d\n", j, next[j], i);
+	  exit (1);
+	}
+	/* find next valid entry to fix link */
+	for (k = i; (k < Nmeas) && (next[k] == -2); k++);
+	if (k < Nmeas)
+	  next[j] = k;
+	else 
+	  next[j] = -1;  /* last link in list gets a -1 */
+      }
+# endif      
+      /*** fix the corresponding average entry ***/
+      n = catalog[0].measure[i].averef;
+      if (catalog[0].average[n].Nm == 0) { /* this should never happen */
+	fprintf (stderr, "error? we deleted one too many objects?\n");
+	exit (1);
+      }
+      catalog[0].average[n].Nm --;
+      /* this was only entry in list: will be deleted below.  meanwhile, delete all missing entries*/
+      if ((catalog[0].average[n].Nm < 1) && (catalog[0].average[n].Nn > 0)) { 
+	m = catalog[0].average[n].missing;
+	for (j = 0; j < catalog[0].average[n].Nn; j++) {
+	  M = next_miss[m];
+	  next_miss[m] = -2;
+	  m = M;
+	}
+	m = catalog[0].average[n].missing;
+	/* fix the list links: connect the previous valid link to the next valid link */
+	for (j = m; (j >= 0) && (next_miss[j] == -2); j--); /* find previous entry to fix link */
+	if (j >= 0) { /* if j < 0, there is no previous valid link, ignore this step */
+	  if (next_miss[j] != m) {
+	    fprintf (stderr, "error? (2) this link seems to have been lost\n");
+	    fprintf (stderr, "j: %d, next_miss[j]: %d, i: %d\n", j, next_miss[j], i);
+	    exit (1);
+	  }
+	  /* find next valid entry to fix link */
+	  for (k = m; (k < Nmiss) && (next_miss[k] == -2); k++);
+	  if (k < Nmiss)
+	    next_miss[j] = k;
+	  else 
+	    next_miss[j] = -1;  /* last link in list gets a -1 */
+	}
+      }
+      /* this was first entry in list */
+      if ((catalog[0].average[n].offset == i) && (catalog[0].average[n].Nm > 0)) { 
+	m = catalog[0].average[n].offset;
+	/* find next valid entry -- notice lack of error checking... */
+	for (j = 0; (j < Nmeas) && (next[m+j] == -2); j++);
+	catalog[0].average[n].offset = m + j;
+      }
+    } else {
+      prev = i;
+    }
+  }
+  fprintf (stderr, "found %d meas to remove\n", Nmeasfound);
+
+  /* fprintf (stderr, "fixing the missing...\n"); */
+  /** find missing in time range of image **/
+  for (i = 0; (i < Nmiss); i++) {
+    if ((next_miss[i] != -2) && (catalog[0].missing[i].t >= start) && (catalog[0].missing[i].t <= end)) { 
+      /* this star is in this image */
+
+      next_miss[i] = -2; /* we delete this one */
+      /* fix the list links: connect the previous valid link to the next valid link */
+      for (j = i; (j >= 0) && (next_miss[j] == -2); j--); /* find previous entry to fix link */
+      if (j >= 0) { /* if j < 0, there is no previous valid link, ignore this step */
+	if (next_miss[j] != i) {
+	  fprintf (stderr, "error? (3) this link seems to have been lost\n");
+	  fprintf (stderr, "j: %d, next_miss[j]: %d, i: %d\n", j, next_miss[j], i);
+	  exit (1);
+	}
+	/* find next valid entry to fix link */
+	for (k = i; (k < Nmiss) && (next_miss[k] == -2); k++);
+	if (k < Nmiss)
+	  next_miss[j] = k;
+	else 
+	  next_miss[j] = -1;  /* last link in list gets a -1 */
+      }
+      
+      /* find the corresponding avearge entry 
+      found = FALSE;
+      for (n = 0; !found && (n < Nave); n++) {
+	if ((catalog[0].average[n].missing > 0) && (catalog[0].average[n].missing <= i) && (catalog[0].average[n].missing + catalog[0].average[n].Nn > i)) 
+	  found = TRUE;
+      }
+      n--; */
+      /*** fix the corresponding average entry ***/
+      n = ave_miss[i];
+      if (catalog[0].average[n].Nn == 0) { /* this should never happen */
+	fprintf (stderr, "error? we deleted one too many missing?\n");
+	exit (1);
+      }
+      catalog[0].average[n].Nn --;
+      /* this was first entry in list */
+      if ((catalog[0].average[n].missing == i) && (catalog[0].average[n].Nn > 0)) { 
+	m = catalog[0].average[n].missing;
+	for (j = 0; (j < Nmiss) && (next_miss[m+j] == -2); j++);
+	catalog[0].average[n].missing = m + j;
+      }
+
+    }
+  }
+
+  /* currently not worked out, but we will need to delete the references to blended image and cat stars */
+# if 0
+  /*** handle multiple stars */
+  /* this image star matches more than one catalog star */
+  if (stars[N].found > -1) {
+    catalog[0].measure[stars[N].found].flags |= BLEND_IMAGE;
+    catalog[0].measure[Nmeas].flags |= BLEND_IMAGE;
+  } 
+  if (stars[N].found == -2) { /* this image star matches a catalog star on a neighboring catalog */
+    catalog[0].measure[Nmeas].flags |= BLEND_IMAGE_NEIGHBOR;
+  } 
+  if (stars[N].found == -1) { /* this image star matches only this star */
+    stars[N].found = Nmeas;  /* save first match, in case coincidences are found */
+  }
+  /* this catalog star matches more than one image star */
+  if (catalog[0].found[n] > -1) {
+    catalog[0].measure[catalog[0].found[n]].flags |= BLEND_CATALOG;
+    catalog[0].measure[Nmeas].flags |= BLEND_CATALOG;
+  } else {
+    catalog[0].found[n] = Nmeas;
+  }
+# endif  
+
+  /* fix Average list: delete entries with Nm == 0 */
+  for (i = j = 0; (i < Nave) && (j < Nave); i++, j++) {
+    for (; (j < Nave) && (catalog[0].average[j].Nm == 0); j++);
+    if ((i != j) && (j < Nave)) {
+      catalog[0].average[i] = catalog[0].average[j];
+      for (k = 0; k < catalog[0].Nsecfilt; k++) {
+	catalog[0].secfilt[i*Nsecfilt + k] = catalog[0].secfilt[j*Nsecfilt + k];
+      }
+    }    
+    if (j == Nave) i--;
+  }
+  Nave = i;
+  REALLOCATE (catalog[0].average, Average, Nave);
+  REALLOCATE (catalog[0].secfilt, SecFilt, MAX (1, Nave*Nsecfilt));
+
+  /* fix order of Measure (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmeasure, Measure, Nmeas);
+  for (i = 0; i < Nave; i++) {
+    n = catalog[0].average[i].offset;
+    catalog[0].average[i].offset = N;
+    for (k = 0; k < catalog[0].average[i].Nm; k++, N++) {
+      if ((n == -1) || (n == -2)) {
+	fprintf (stderr, "error: linked list is confused\n");
+	exit (1);
+      }
+      tmpmeasure[N] = catalog[0].measure[n]; 
+      tmpmeasure[N].averef = i;
+      n = next[n];
+    }
+  }
+  Nmeas = N;
+  free (catalog[0].measure);
+  catalog[0].measure = tmpmeasure;
+  REALLOCATE (catalog[0].measure, Measure, Nmeas);
+    
+  /* fprintf (stderr, "fixing the mising order...\n"); */
+  /* fix order of Missing (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmissing, Missing, Nmiss);
+  for (i = 0; i < Nave; i++) {
+    if (catalog[0].average[i].Nn > 0) {
+      n = catalog[0].average[i].missing;
+      catalog[0].average[i].missing = N;
+      for (k = 0; k < catalog[0].average[i].Nn; k++, N++) {
+	if ((n == -1) || (n == -2)) {
+	  fprintf (stderr, "error: linked list is confused\n");
+	  exit (1);
+	}
+	tmpmissing[N] = catalog[0].missing[n]; 
+	n = next_miss[n];
+      }
+    }
+  }
+  Nmiss = N;
+  free (catalog[0].missing);
+  catalog[0].missing = tmpmissing;
+  REALLOCATE (catalog[0].missing, Missing, Nmiss);
+
+  fprintf (stderr, "\n");
+
+  catalog[0].Naverage = Nave;
+  catalog[0].Nmeasure = Nmeas;
+  catalog[0].Nmissing = Nmiss;
+  if (VERBOSE) fprintf (stderr, "  ending with Nave, Nmeas, Nmiss: %d %d %d\n", Nave, Nmeas, Nmiss);
+
+  free (next);
+  free (next_miss);
+  free (ave_miss);
+
+}
+
Index: /tags/start/Ohana/src/delstar/src/gcatalog.c
===================================================================
--- /tags/start/Ohana/src/delstar/src/gcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/delstar/src/gcatalog.c	(revision 12606)
@@ -0,0 +1,45 @@
+# include "delstar.h"
+
+int gcatalog (Catalog *catalog) {
+  
+  int Nsecfilt;
+  char mode;
+
+  /* read catalog header */
+  mode = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+  if (!load_catalog (catalog, mode, VERBOSE)) {
+    fprintf (stderr, "ERROR: failure loading catalog\n");
+    exit (1);
+  }
+
+  /* check Nsecfile value, update if needed */
+  Nsecfilt = GetPhotcodeNsecfilt ();
+  if (catalog[0].Nsecfilt < Nsecfilt) {
+
+    int i, j, Nextra, in, out;
+    SecFilt *insec, *outsec;
+
+    Nextra = Nsecfilt - catalog[0].Nsecfilt;
+    insec = catalog[0].secfilt;
+    ALLOCATE (outsec, SecFilt, catalog[0].Naverage * Nsecfilt);
+    for (in = out = i = 0; i < catalog[0].Naverage; i++) {
+      for (j = 0; j < catalog[0].Nsecfilt; j++, in++, out++) {
+	outsec[out].M = insec[in].M;
+	outsec[out].Xm = insec[in].Xm;
+      }
+      for (j = 0; j < Nextra; j++, out++) {
+	outsec[out].M = NO_MAG;
+	outsec[out].Xm = NO_MAG;
+      }
+    }
+    free (catalog[0].secfilt);
+    catalog[0].secfilt = outsec;
+    catalog[0].Nsecfilt = Nsecfilt;
+  }
+
+  if (catalog[0].Nsecfilt > Nsecfilt) {
+    fprintf (stderr, "ERROR: can't reduce number of secondary filters\n");
+    exit (1);
+  }
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/delstar/src/gcatstats.c
===================================================================
--- /tags/start/Ohana/src/delstar/src/gcatstats.c	(revision 12606)
+++ /tags/start/Ohana/src/delstar/src/gcatstats.c	(revision 12606)
@@ -0,0 +1,57 @@
+# include "delstar.h"
+
+gcatstats (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  int i;
+  double RaCenter, DecCenter;
+  double MinRA, MaxRA, MinDEC, MaxDEC;
+  float *X1, *Y1;
+  int *N1;
+  Coords tcoords;
+  
+  fits_scan (&catalog[0].header, "RA0", "%lf", 1, &MinRA);
+  fits_scan (&catalog[0].header, "RA1", "%lf", 1, &MaxRA);
+  fits_scan (&catalog[0].header, "DEC0", "%lf", 1, &MinDEC);
+  fits_scan (&catalog[0].header, "DEC1", "%lf", 1, &MaxDEC);
+
+  /* double check on region RA and DEC ranges */
+  DecCenter = 0.5*(MinDEC + MaxDEC);
+  RaCenter = 0.5*(MinRA + MaxRA);
+  if (MaxDEC > 86.25) {  /* we are on the pole */
+    DecCenter = 90.0;
+    RaCenter = 0.0;
+  }
+
+  catstats[0].RA[0] = MinRA;
+  catstats[0].RA[1] = MaxRA;
+  catstats[0].DEC[0] = MinDEC;
+  catstats[0].DEC[1] = MaxDEC;
+
+  /** allocate local arrays **/
+  ALLOCATE (catstats[0].X, float, catalog[0].Naverage);
+  ALLOCATE (catstats[0].Y, float, catalog[0].Naverage);
+  ALLOCATE (catstats[0].N, int,   catalog[0].Naverage);
+
+  /* project onto rectilinear grid with 1 arcsec pixels, sort by X */
+  /* reference for coords is center of field  */
+  catstats[0].coords.crval1 = RaCenter;
+  catstats[0].coords.crval2 = DecCenter;
+  catstats[0].coords.crpix1 = catstats[0].coords.crpix2 = 0.0;
+  catstats[0].coords.cdelt1 = catstats[0].coords.cdelt2 = 1.0 / 3600.0;
+  catstats[0].coords.pc1_1 = catstats[0].coords.pc2_2 = 1.0;
+  catstats[0].coords.pc1_2 = catstats[0].coords.pc2_1 = 0.0;
+  strcpy (catstats[0].coords.ctype, "RA---TAN");
+
+  X1 = catstats[0].X;
+  Y1 = catstats[0].Y;
+  for (i = 0; i < catalog[0].Naverage; i++, X1++, Y1++) {
+    fRD_to_XY (X1, Y1, catalog[0].average[i].R, catalog[0].average[i].D, &catstats[0].coords);
+    catstats[0].N[i] = i;
+  }
+  if (catalog[0].Naverage > 1) sort_lists (catstats[0].X, catstats[0].Y, catstats[0].N, catalog[0].Naverage);
+  
+}
+
Index: /tags/start/Ohana/src/delstar/src/gimages.c
===================================================================
--- /tags/start/Ohana/src/delstar/src/gimages.c	(revision 12606)
+++ /tags/start/Ohana/src/delstar/src/gimages.c	(revision 12606)
@@ -0,0 +1,88 @@
+# include "delstar.h"
+
+Image *gimages (char *filename) {
+ 
+  FILE *f;
+  Header header;
+  char line[64], photcode[64], *c;
+  struct tm timeptr;
+  double tmp, jd;
+  Image *image;
+  int Nsec, Nc;
+
+  ALLOCATE (image, Image, 1);
+  /* load header */
+  if (!fits_read_header (filename, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s\n", filename);
+    Shutdown ();
+  }
+
+  /* open file */
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find data file %s\n", filename);
+    Shutdown ();
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* add file name to image structure */
+  c = strrchr (filename, 0x2f);
+  if (c == (char *) NULL) {
+    strcpy (image[0].name, filename);
+  } else { 
+    strcpy (image[0].name, (c+1));
+  }
+
+  /* get astrometry information */
+  if (!GetCoords (&image[0].coords, &header)) {
+    fprintf (stderr, "ERROR: no astrometric solution in header\n");
+    Shutdown ();
+  }
+  while (image[0].coords.crval1 < 0) image[0].coords.crval1 += 360.0;
+  while (image[0].coords.crval1 > 360.0) image[0].coords.crval1 -= 360.0;
+
+  /* CERROR in data file is in pixels, convert to 20*arcsec */
+  image[0].cerror = tmp * 50.0 * image[0].coords.cdelt1 * 3600.0;
+  while (image[0].coords.crval1 < 0) image[0].coords.crval1 += 360.0;
+  while (image[0].coords.crval1 > 360.0) image[0].coords.crval1 -= 360.0;
+ 
+  /* get other header info */
+  fits_scan (&header, "NAXIS1",   "%hd", 1, &image[0].NX); 
+  fits_scan (&header, "NAXIS2",   "%hd", 1, &image[0].NY);
+
+  fits_scan (&header, "PHOTCODE", "%s", 1, photcode);
+  Nc = GetPhotcodeCodebyName (photcode);
+  if (!Nc) {
+    fprintf (stderr, "ERROR: photcode %s not found in photcode table\n", photcode);
+    Shutdown ();
+  }
+  image[0].source = Nc;
+
+  tmp = 0;
+  fits_scan (&header, "FLIMIT",   "%lf", 1, &tmp);
+  image[0].detection_limit = tmp * 10.0;
+
+  tmp = 0;
+  fits_scan (&header, "FSATUR",   "%lf", 1, &tmp);
+  image[0].saturation_limit = tmp * 10.0;
+
+  if (!fits_scan (&header, "TZERO",   "%d",  1, &image[0].tzero)) {
+    image[0].tzero = parse_time (&header);
+  }
+
+  tmp = 0;
+  fits_scan (&header, "TRATE",   "%lf", 1, &tmp);
+  image[0].trate = 10000 * tmp;
+
+  tmp = 0;
+  fits_scan (&header, "AIRMASS", "%lf", 1, &tmp);
+  image[0].secz = 1000*tmp;
+
+  /* secz is in units milli-airmass */
+  image[0].Mcal =  ALPHA*(image[0].secz - 1000);
+  image[0].Xm   = NO_MAG;
+
+  free (header.buffer);
+ 
+  return (image);
+}
Index: /tags/start/Ohana/src/delstar/src/gregions.c
===================================================================
--- /tags/start/Ohana/src/delstar/src/gregions.c	(revision 12606)
+++ /tags/start/Ohana/src/delstar/src/gregions.c	(revision 12606)
@@ -0,0 +1,53 @@
+# include "delstar.h"
+
+GSCRegion *gregions (Image *image, int *Nregions) {
+  
+  GSCRegion *region;
+  FILE *f;
+  double x, y;
+  double dr, dd, dec, ra;
+  int i, j, done, nregion, NREGION;
+  
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find GSC region file %s\n", GSCFILE);
+    exit (1);
+  }
+  
+  /* find regions at image corners */
+  NREGION = 10;
+  ALLOCATE (region, GSCRegion, NREGION);
+  nregion = 0;
+
+  /* look for new regions on grid across image */ 
+  for (x = 0; x <= 1; x+=0.25) {
+    for (y = 0; y <= 1; y+=0.25) {
+      XY_to_RD (&ra, &dec, image[0].NX*(1.1*x - 0.05), image[0].NY*(1.1*y - 0.05), &image[0].coords);
+      aregion (&region[nregion], f, ra, dec);
+      done = FALSE;
+      for (j = 0; (j < nregion) && !done; j++) {
+	if (!strcmp (region[nregion].filename, region[j].filename)) {
+	  nregion --;
+	  done = TRUE;
+	}
+      }
+      nregion ++;
+      if (nregion == NREGION) {
+	NREGION += 10;
+	REALLOCATE (region, GSCRegion, NREGION);
+      }
+    }
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "found %d region files:\n", nregion);
+    for (i = 0; i < nregion; i++) {
+      fprintf (stderr, "  %d %s\n", i, region[i].filename);
+    }
+  }
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (region);
+  
+}
Index: /tags/start/Ohana/src/delstar/src/gtimes.c
===================================================================
--- /tags/start/Ohana/src/delstar/src/gtimes.c	(revision 12606)
+++ /tags/start/Ohana/src/delstar/src/gtimes.c	(revision 12606)
@@ -0,0 +1,66 @@
+# include "delstar.h"
+
+Image *gtimes (FILE *f, char **argv, int *NIMAGE, int *START, int *END) {
+ 
+  int i, npimage, NPIMAGE, ntimage, Ntimage, NTIMAGE, Nimage;
+  int start, end, range, tstart, tend;
+  double Ra, Dec;
+  Image *pimage, *timage;
+  Header header;
+
+  start = atof(argv[1]);
+  range = atof(argv[2]);
+  if (range < 2) {
+    start = start - 1;
+    range = 2;
+  }
+  end = start + range;
+  *START = start;
+  *END = end;
+
+  /* get image header */
+  fseek (f, 0, SEEK_SET); 
+  if (!fits_fread_header (f, &header)) {
+    fprintf (stderr, "Can't find image catalog: %s\n", ImageCat);
+    exit (1);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  Nimage = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+
+  NTIMAGE = 100;
+  ALLOCATE (timage, Image, NTIMAGE);
+
+  npimage = 0;
+  NPIMAGE = 20;
+  ALLOCATE (pimage, Image, NPIMAGE);
+
+  for (Ntimage = 0; Ntimage < Nimage; Ntimage += ntimage) {
+    ntimage = Fread (timage, sizeof(Image), NTIMAGE, f, "image");
+    for (i = 0; i < ntimage; i++) {
+      tstart = timage[i].tzero;
+      tend = timage[i].tzero + 1e-4*timage[i].trate*timage[i].NY;
+      if ((tstart <= end) && (tend >= start)) {
+	pimage[npimage] = timage[i];
+	npimage ++;
+	if (npimage == NPIMAGE) {
+	  NPIMAGE += 20;
+	  REALLOCATE (pimage, Image, NPIMAGE);
+	}
+      }
+    }
+  }
+  free (timage);
+
+  fprintf (stderr, "found the following images:\n");
+  for (i = 0; i < npimage; i++) {
+    XY_to_RD (&Ra, &Dec, 0.5*pimage[i].NX, 0.5*pimage[i].NY, &pimage[i].coords);
+    fprintf (stderr, "%3d %s %8.4f %8.4f %d %d\n", i, pimage[i].name, Ra, Dec,
+	     pimage[i].tzero, pimage[i].nstar);
+  }
+
+  *NIMAGE = npimage;
+  return (pimage);
+
+}
Index: /tags/start/Ohana/src/delstar/src/match_images.c
===================================================================
--- /tags/start/Ohana/src/delstar/src/match_images.c	(revision 12606)
+++ /tags/start/Ohana/src/delstar/src/match_images.c	(revision 12606)
@@ -0,0 +1,56 @@
+# include "delstar.h"
+
+match_images (catalog, image, Nimage)
+Catalog catalog[];
+Image   image[];
+int Nimage;
+{
+  
+  int j, k, found;
+  unsigned int *start, *stop;
+
+  /* this must be allocated so future free will not fail */
+  ALLOCATE (catalog[0].image, int, MAX (catalog[0].Nmeasure, 1));
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (FALSE);
+  }
+
+  ALLOCATE (start, unsigned int, Nimage);
+  ALLOCATE (stop,  unsigned int, Nimage);
+  for (j = 0; j < Nimage; j++) {
+    start[j] = image[j].tzero - MAX(0.05*image[j].trate*image[j].NY, 1);
+    stop[j]  = image[j].tzero + MAX(1.05*image[j].trate*image[j].NY, 1);
+  }
+
+  for (j = 0; j < catalog[0].Nmeasure; j++) {
+    found = FALSE;
+    if (catalog[0].measure[j].t == 0) {
+      catalog[0].image[j] = -1;
+      found = TRUE;
+    }
+    for (k = 0; (k < Nimage) && !found; k++) {
+      if ((catalog[0].measure[j].t >= start[k]) && 
+	  (catalog[0].measure[j].t <= stop[k])) {
+	catalog[0].image[j] = k;
+	found = TRUE;
+      }
+    }
+    if (!found) {
+      catalog[0].image[j] = -1;
+      /* fprintf (stderr, "missing: %d %d\n", catalog[0].image[j], catalog[0].measure[j].t); */
+    }
+  }
+  free (start);
+  free (stop);
+}
+
+  /* this routine uses the time of each measurement to match the
+measurement with an image.  Since the measurement is only store to 1
+sec accuracy, which corresponds to roughly 30 rows at nominal speed,
+we can't tell exactly which image the star come from.  However, this
+doesn't matter, and in fact this helps a bit: a measurement from the
+top of one image is the same as from the bottom of the next.
+Therefore, we intentionally blur the edges of the images by 5%, which
+will help to tie together neighboring images... */
+
Index: /tags/start/Ohana/src/delstar/src/parse_time.c
===================================================================
--- /tags/start/Ohana/src/delstar/src/parse_time.c	(revision 12606)
+++ /tags/start/Ohana/src/delstar/src/parse_time.c	(revision 12606)
@@ -0,0 +1,126 @@
+# include "delstar.h"
+
+parse_time (Header *header) {
+
+  double jd;
+  int Ny, Nf, mode;
+  int Nsec, hour, min, sec, year, month, day;
+  char *py, *pm, *pd, *c;
+  char line[256];
+
+  /* we want to find JD or MJD to get Nsec (seconds since 01/01/1970) */
+
+  /* try JD first */
+  if (strcasecmp (JDKeyword, "NONE")) {
+    uppercase (JDKeyword);
+    fits_scan (header, JDKeyword, "%lf", 1, &jd);
+    Nsec = (jd - 2440587.5)*86400;
+    return (Nsec);
+  }
+
+  /* try MJD next */
+  if (strcasecmp (MJDKeyword, "NONE")) {
+    uppercase (MJDKeyword);
+    fits_scan (header, MJDKeyword, "%lf", 1, &jd);
+    Nsec = (jd - 40587.0)*86400;
+    return (Nsec);
+  }
+    
+  /* get UT and DATE */
+  uppercase (UTKeyword);
+  fits_scan (header, UTKeyword, "%s", 1, line);
+  /* remove ':' characters */
+  for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
+  sscanf (line, "%d %d %d", &hour, &min, &sec);
+
+  /* parse mode line */
+  uppercase (DateMode);
+  for (Ny = 0, c = strchr (DateMode, 'Y'); c != (char ) NULL; c = strchr (c + 1, 'Y'), Ny++);
+  if ((Ny != 2) && (Ny != 4)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    Shutdown ();
+  }
+  py = strchr (DateMode, 'Y');
+  pm = strchr (DateMode, 'M');
+  pd = strchr (DateMode, 'D');
+  if ((py == (char *) NULL) || (pm == (char *) NULL) || (pd == (char *) NULL)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    Shutdown ();
+  }
+  if ((py > pm) && (py < pd)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    Shutdown ();
+  }
+  if ((py > pd) && (py < pm)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    Shutdown ();
+  }
+  mode = 0;
+  if ((py < pm) && (pm < pd)) { mode = 1; }  /* yyyy-mm-dd */
+  if ((py < pm) && (pm > pd)) { mode = 2; }  /* yyyy-dd-mm */
+  if ((py > pm) && (pm < pd)) { mode = 3; }  /* mm-dd-yyyy */
+  if ((py > pm) && (pm > pd)) { mode = 4; }  /* dd-mm-yyyy */
+  if (!mode) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    Shutdown ();
+  }
+
+  /* parse date entry */
+  uppercase (DateKeyword);
+  fits_scan (header, DateKeyword, "%s",  1, line);
+  /* remove possible separators: ':', '/' '.', '-' */
+  for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
+  for (c = strchr (line, 0x2f); c != (char *) NULL; c = strchr (line, 0x2f)) { *c = ' '; }
+  for (c = strchr (line, 0x2e); c != (char *) NULL; c = strchr (line, 0x2e)) { *c = ' '; }
+  for (c = strchr (line, 0x2d); c != (char *) NULL; c = strchr (line, 0x2d)) { *c = ' '; }
+
+  switch (mode) {
+  case 1:
+    Nf = sscanf (line, "%d %d %d", &year, &month, &day);
+    break;
+  case 2:
+    Nf = sscanf (line, "%d %d %d", &year, &day, &month);
+    break;
+  case 3:
+    Nf = sscanf (line, "%d %d %d", &month, &day, &year);
+    break;
+  case 4:
+    Nf = sscanf (line, "%d %d %d", &day, &month, &year);
+    break;
+  }
+  if (Nf != 3) {
+    fprintf (stderr, "error in date entry (%s) or DATE-MODE format (%s)\n", line, DateMode);
+    Shutdown ();
+  }
+
+  if (year > 1000) {
+    if (Ny == 2) {
+      fprintf (stderr, "warning: mode line claims 2 digit year, but 4 digit year found\n");
+    }
+  } else {
+    if (Ny == 4) {
+      fprintf (stderr, "warning: mode line claims 4 digit year, but 2 digit year found\n");
+    }
+    if (year < 50) year += 100;
+    year += 1900;
+  }    
+
+  /* convert yy.mm.dd hh.mm.ss to Nsec since 1970 (jd = 2440587.5) */
+  /* note that in this section, tm_mon has range 1-12, unlike for gmtime () */
+  jd = day - 32075 + (int)(1461*(year + 4800 + (int)(((month)-14)/12))/4)
+    + (int)(367*((month) - 2 - (int)(((month) - 14)/12)*12)/12)
+    - (int)(3*(int)((year + 4900 + (int)(((month) - 14)/12))/100)/4) - 0.5;
+  /* jd is the julian day of the whole day only not the time */
+  Nsec = (jd - 2440587.5)*86400 + 3600.0*hour + min*60.0 + sec;
+  
+  return (Nsec);
+
+}
+
+uppercase (char *string) {
+
+  int i;
+    
+  for (i = 0; i < strlen (string); i++) string[i] = toupper (string[i]);
+
+}
Index: /tags/start/Ohana/src/delstar/src/sort_lists.c
===================================================================
--- /tags/start/Ohana/src/delstar/src/sort_lists.c	(revision 12606)
+++ /tags/start/Ohana/src/delstar/src/sort_lists.c	(revision 12606)
@@ -0,0 +1,48 @@
+
+sort_lists (X, Y, S, N) 
+float *X, *Y;
+int *S, N;
+{
+  int l,j,ir,i;
+  double tX, tY, tS;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    S[i] = tS;
+  }
+}
Index: /tags/start/Ohana/src/delstar/src/wcatalog.c
===================================================================
--- /tags/start/Ohana/src/delstar/src/wcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/delstar/src/wcatalog.c	(revision 12606)
@@ -0,0 +1,37 @@
+# include "delstar.h"
+
+wcatalog (Catalog *catalog) {
+  
+  int status;
+
+  /* we'll leave these for now, but they are LONEOS specific */
+  fits_modify (&catalog[0].header, "MARKSTAR", "%t", 1, FALSE);
+  fits_modify (&catalog[0].header, "ADDUSNO", "%t", 1, FALSE);
+  fits_modify (&catalog[0].header, "MARKROCK", "%t", 1, FALSE);
+
+  if (!save_catalog (catalog, VERBOSE)) {
+    fprintf (stderr, "ERROR: failure saving catalog\n");
+    exit (1);
+  }
+
+  /* free, initialize data structures */
+
+  if (catalog[0].Naverage) {
+    free (catalog[0].average); 
+    catalog[0].Naverage = 0;
+  }
+  if (catalog[0].Nmeasure) {
+    free (catalog[0].measure); 
+    catalog[0].Nmeasure = 0;
+  }
+  if (catalog[0].Nmissing) {
+    free (catalog[0].missing); 
+    catalog[0].Nmissing = 0;
+  }
+  if (catalog[0].Nsecfilt) {
+    free (catalog[0].secfilt); 
+    catalog[0].Nsecfilt = 0;
+  }
+  fits_free_header (&catalog[0].header);
+}
+
Index: /tags/start/Ohana/src/elixir/Makefile
===================================================================
--- /tags/start/Ohana/src/elixir/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/elixir/Makefile	(revision 12606)
@@ -0,0 +1,63 @@
+include ../../Configure
+HOME 	=	$(ROOT)/src/elixir
+CONFIG  =	$(ROOT)/config
+PROGRAM =	elixir
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#  
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lFITS -lohana -lsocket -lnsl -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS)
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+ELIXIR = \
+$(SRC)/elixir.$(ARCH).o			$(SRC)/ConfigInit.$(ARCH).o		\
+$(SRC)/MachineOps.$(ARCH).o		$(SRC)/FifoOps.$(ARCH).o		\
+$(SRC)/QueueOps.$(ARCH).o		$(SRC)/CheckCluster.$(ARCH).o		\
+$(SRC)/CheckDepend.$(ARCH).o		$(SRC)/CheckEndingState.$(ARCH).o	\
+$(SRC)/CheckMachineStatus.$(ARCH).o	$(SRC)/CheckProcess.$(ARCH).o		\
+$(SRC)/InitProcess.$(ARCH).o		$(SRC)/StartMachine.$(ARCH).o		\
+$(SRC)/SockScan.$(ARCH).o		$(SRC)/LoadPending.$(ARCH).o		\
+$(SRC)/Photcodes.$(ARCH).o		$(SRC)/rconnect.$(ARCH).o		\
+$(SRC)/DefineProcesses.$(ARCH).o        $(SRC)/ProcessOps.$(ARCH).o		\
+$(SRC)/DumpStatus.$(ARCH).o		$(SRC)/CheckMessages.$(ARCH).o		\
+$(SRC)/MsgOps.$(ARCH).o			$(SRC)/LogOpen.$(ARCH).o		\
+$(SRC)/ConfigPID.$(ARCH).o		$(SRC)/RemoteOps.$(ARCH).o
+
+default: elixir
+
+$(ELIXIR): $(INC)/controller.h
+
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(ELIXIR)
+	$(CC) $(ELIXIR) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:	
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f $(SRC)/*.o
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
+
+
Index: /tags/start/Ohana/src/elixir/doc/README
===================================================================
--- /tags/start/Ohana/src/elixir/doc/README	(revision 12606)
+++ /tags/start/Ohana/src/elixir/doc/README	(revision 12606)
@@ -0,0 +1,13 @@
+
+There are two parts to elixir which are a bit dangerous (and limit the
+possibilities).  
+
+First, the number of arguments which describe an object is limited to
+7.  This is limited in LoadPending.c and is due to the dumb way I
+parse these input lines.
+
+Second, in a similar way, the number of arguments to a command line
+argument (the 'process.arg' entries) is limited to 5, again for about
+the same reason.  this is in 'ParseLine' in ProcessOps.c
+
+
Index: /tags/start/Ohana/src/elixir/doc/notes.txt
===================================================================
--- /tags/start/Ohana/src/elixir/doc/notes.txt	(revision 12606)
+++ /tags/start/Ohana/src/elixir/doc/notes.txt	(revision 12606)
@@ -0,0 +1,40 @@
+
+
+typedef struct {
+  char *buffer;
+  int   Nalloc;
+  int   Nmaxread;
+  int   Nextra;
+  int   Nlast;
+  int   Nbuffer;
+} Fifo;
+
+typedef struct {
+  int argc; char **argv; /* a list of words that define this object */
+  struct timeval start, accum, timer;
+  int   status;
+  char *logfile;
+  char *lastproc;
+} Object;
+
+typedef struct {
+  Object **object;
+  int    Nobject;
+  int    NOBJECT;
+} Queue;
+
+typedef struct {
+  char   *hostname;
+  int     rsock, wsock;
+  int     status; /* idle, busy, etc... */
+  struct  timeval start, accum, timer;
+  Fifo    fifo;
+  int     code;
+  Object *object;
+} Machine;
+
+
+currently, the transport is /usr/bin/rsh, defined in InitMachines.c 
+
+the shell on the remote machines is /bin/tcsh, defined by rconnect.c
+
Index: /tags/start/Ohana/src/elixir/include/controller.h
===================================================================
--- /tags/start/Ohana/src/elixir/include/controller.h	(revision 12606)
+++ /tags/start/Ohana/src/elixir/include/controller.h	(revision 12606)
@@ -0,0 +1,171 @@
+# include <ohana.h>
+# include <signal.h>
+# include <errno.h>
+
+# define CR 0x0D
+# define LF 0x0A
+
+# define IDLE     0x00
+# define BUSY     0x01
+# define DOWN     0x02
+# define DONE     0x04
+# define MESSAGE  0x08
+# define SUCCESS  0x10
+# define FAILURE  0x20
+# define JOBDONE  0x40
+# define WAITING  0x80
+# define ERROR    0x100
+# define CRASH    0x200
+# define TIMEOUT  0x400
+
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+
+/* represents a socketed connection to a remote host
+   which may or may not be currently running a process */
+
+typedef struct {
+  char *buffer;
+  int   Nalloc;
+  int   Nmaxread;
+  int   Nextra;
+  int   Nlast;
+  int   Nbuffer;
+} Fifo;
+
+typedef struct {
+  int argc; char **argv; /* a list of words that define this object */
+  struct timeval start, accum, timer;
+  int   status;
+  char *logfile;
+  char *lastproc;
+} Object;
+
+typedef struct {
+  Object **object;
+  int    Nobject;
+  int    NOBJECT;
+} Queue;
+
+typedef struct {
+  char   *hostname;
+  int     rsock, wsock, pid;
+  int     status; /* idle, busy, etc... */
+  struct  timeval start, accum, timer, quiet;
+  Fifo    fifo;
+  int     code;
+  Object *object;
+} Machine;
+
+typedef struct {
+  Machine **machine;
+  int     Nmachine;
+  int     NMACHINE;
+} Cluster;
+
+typedef struct {
+  char    *name;
+  Queue   *pending;
+  Queue   *success;
+  Queue   *failure;
+  Cluster *cluster;
+  int     argc;
+  char    **argv;
+} Process;
+
+/* we have one ProcessTimer for each existing machine
+   each ProcessTimer has one element for each process */
+typedef struct {
+  struct timeval *timer;
+  double       *timesum;
+  int          *Njobs;
+  int          *active;
+  Machine      *machine;
+  Process     **process;
+} ProcessTimers;
+
+int   VERBOSE;
+char  CONNECT[128];
+
+/* prototypes */
+
+Process **DefineProcesses (Process *global, int *nprocess, char *config);
+Process **GetProcessInfo (Process **gb, int *np, int *no);
+char 	 *BaseFilename (char *file);
+char 	 *BuildCode (char *line);
+char 	 *BuildName (char *line);
+char 	 *ConfigInit (int *argc, char **argv);
+Process  *ConfigProcess (char *config, char *procname);
+char 	 *ExpandEntry (char *entry, int argc, char **argv);
+Machine  *GetMachine (Cluster *cluster);
+Object   *GetObject (Queue *queue);
+char 	 *GetPhotcode (char *file);
+char 	 *GetPhotcodeExt (char *file);
+char 	 *GetPhotcodeMef (char *file);
+Machine  *GrabMachine ();
+Cluster  *InitCluster ();
+Process  *InitProcess (char *name, Queue *pending, Queue *failure, int (*mkargs)());
+Queue    *InitQueue ();
+FILE     *LogOpen (char *filename);
+char 	 *PathFilename (char *file);
+char 	 *RootFilename (char *file);
+int 	  CheckCluster (Cluster *cluster, Queue *success, Queue *failure, Queue *pending);
+int 	  CheckDepend (Object *object, int argc, char **argv, int *argd);
+int 	  CheckEndingState (Process *global, int Nobjects, int Dynamic);
+int 	  CheckMachineStatus (Machine *machine);
+int 	  CheckMessages ();
+int 	  CheckProcess (Process *process);
+void 	  CloseMachine (Machine *machine);
+void 	  ConfigPID (char *PIDFile);
+int 	  ConnectMachine (Machine *machine);
+void 	  DownMachine (Machine *machine);
+void 	  DumpFinished (Queue *queue, int Nstart, char *filename);
+void 	  DumpMachineStatus (FILE *f);
+int 	  DumpProcessTimes (char *filename);
+int 	  DumpStatus (char *filename);
+void 	  ElixirStop ();
+int 	  FlushFifo (Fifo *fifo);
+void 	  FreeArgs (int argc, char **argv, int *argd);
+void 	  FreeFifo (Fifo *fifo);
+int 	  GetDynamicState ();
+double    GetTimeout ();
+void 	  HaltElixir (char *pidfile);
+int 	  HalttoRestart (char *pidfile);
+void 	  IdleMachine (Machine *machine);
+int 	  InitFifo (Fifo *fifo, int Nalloc, int Nextra);
+void 	  InitMachines (char *config);
+int 	  InitMsgFile (char *file);
+void 	  InitProcessTimers (Process **process, int Nprocess);
+void 	  KillElixir (char *pidfile);
+int 	  LoadPID (char *file, pid_t *pid, char *username, char *machine);
+int 	  LoadPending (Process *global, char *inlist, int *state, int *dynamic);
+int 	  MakeArgs (Process *process, Object *object, int *cargc, char ***cargv, int **cargd);
+void 	  ParseLine (char *testline, int argc, char **argv, int *depend, char **outline);
+void 	  PushMachine (Machine *machine, Cluster *cluster);
+void 	  PushObject (Queue *queue, Object *object);
+void 	  PutMachine (Machine *machine, Cluster *cluster);
+void 	  PutObject (Queue *queue, Object *object);
+int 	  ReadMsg (char *fifo, char **message);
+int 	  ReadtoFifo (Fifo *fifo, int sock);
+void 	  RegisterTimeout (double value);
+void 	  RemovePID ();
+void 	  Restart (char **argv);
+void 	  RestartMachines ();
+void 	  SIG_DIE (int sig);
+void 	  SIG_MESSAGE (int sig);
+void 	  SIG_PIPE (int sig);
+void 	  SIG_RELOAD (int sig);
+void 	  SIG_STOP (int sig);
+int 	  SetExitTimer ();
+void 	  SetMessageFile (char *filename);
+int 	  ShiftFifo (Fifo *fifo);
+void 	  Shutdown (int status);
+int 	  SockScan (char *string, Fifo *fifo, int sock);
+int 	  StartMachine (Machine *machine, Object *object, int argc, char **argv);
+void 	  StartProcessTimer (Process *process, Machine *machine);
+void 	  StatusElixir (char *pidfile, char *msgfile);
+void 	  StopProcessTimer (Machine *machine);
+int 	  TestMachine (Machine *machine);
+int 	  WaitMsg (char *fifo, char **message, double maxdelay);
+int 	  WriteMsg (char *fifo, char *message);
+int 	  memstr (char *m1, char *m2, int n);
+int 	  rconnect (char *hostname, char *command, int *rsock, int *wsock);
Index: /tags/start/Ohana/src/elixir/src/CheckCluster.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/CheckCluster.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/CheckCluster.c	(revision 12606)
@@ -0,0 +1,113 @@
+# include "controller.h"
+
+int CheckCluster (Cluster *cluster, Queue *success, Queue *failure, Queue *pending) {
+
+  int i, j, status;
+  Machine *machine, **tmachine;
+  Object *object;
+  FILE *logfile;
+
+  /* check current status of all machines in cluster, idle those finished */
+  for (i = 0; i < cluster[0].Nmachine; i++) {
+    
+    machine = cluster[0].machine[i];
+    status = CheckMachineStatus (machine);
+
+    object = machine[0].object;
+    logfile = LogOpen (object[0].logfile);
+
+    if (status & MESSAGE) {
+      fprintf (logfile, "%s @ %s:", object[0].argv[0], machine[0].hostname);
+      fwrite (&machine[0].fifo.buffer[machine[0].fifo.Nlast], 1, machine[0].fifo.Nbuffer - machine[0].fifo.Nlast, logfile);
+    }      
+
+    if (status & DOWN) {
+      fprintf (stderr, "%s @ %s is down\n", object[0].argv[0], machine[0].hostname);
+      fprintf (logfile, "%s @ %s is down\n", object[0].argv[0], machine[0].hostname);
+      object[0].timer.tv_sec = 0; /* reset timer */
+      StopProcessTimer (machine);
+      /* PutObject (failure, object); */
+      /* if machine crashes, retry object later */
+      PutObject (pending, object);
+      DownMachine (machine);
+      cluster[0].machine[i] = (Machine *) NULL;
+      goto escape;
+    }
+    if (status & DONE) {
+      object[0].timer.tv_sec = 0; /* reset timer */
+      StopProcessTimer (machine);
+      fprintf (logfile, "%s @ %s is done\n", object[0].argv[0], machine[0].hostname);
+      if (status & SUCCESS) {
+	PutObject (success, object);
+      } 
+      if (status & FAILURE) {
+	PutObject (failure, object);
+      } 
+      IdleMachine (machine);
+      cluster[0].machine[i] = (Machine *) NULL;
+      goto escape;
+    }
+    if (status & CRASH) {
+      object[0].timer.tv_sec = 0; /* reset timer */
+      StopProcessTimer (machine);
+      fprintf (logfile, "%s @ %s had process crash\n", object[0].argv[0], machine[0].hostname);
+      PutObject (failure, object);
+      IdleMachine (machine);
+      cluster[0].machine[i] = (Machine *) NULL;
+      goto escape;
+    }
+    if (status & ERROR) {
+      object[0].timer.tv_sec = 0; /* reset timer */
+      StopProcessTimer (machine);
+      fprintf (logfile, "%s @ %s has an odd status\n", object[0].argv[0], machine[0].hostname);
+      PutObject (failure, object);
+      DownMachine (machine);
+      cluster[0].machine[i] = (Machine *) NULL;
+      goto escape;
+    }
+    if (status & TIMEOUT) {
+      object[0].timer.tv_sec = 0; /* reset timer */
+      /* don't include TIMEOUT in timer stats StopProcessTimer (machine); */
+      fprintf (logfile, "%s @ %s timed out, retrying\n", object[0].argv[0], machine[0].hostname);
+      PutObject (pending, object);
+      IdleMachine (machine);
+      cluster[0].machine[i] = (Machine *) NULL;
+      goto escape;
+    }
+
+  escape:
+    if (logfile != stderr) fclose (logfile);
+  }
+
+  /* remove idle machines from this cluster's list */
+  ALLOCATE (tmachine, Machine *, cluster[0].NMACHINE);
+  for (j = i = 0; i < cluster[0].Nmachine; i++) {
+    if (cluster[0].machine[i] != (Machine *) NULL) {
+      tmachine[j] = cluster[0].machine[i];
+      j++;
+    }
+  }
+  free (cluster[0].machine);
+  cluster[0].machine = tmachine;
+  cluster[0].Nmachine = j;
+
+  return (TRUE);
+}
+
+
+/*
+
+  possible ending states:
+
+  DONE & SUCCESS = process finished normally & succeeded
+  DONE & FAILURE = process finished normally & failed
+
+  CRASH = process crashed
+  DOWN  = machine crashed
+  IDLE  = no process (should never show up here!)
+  ERROR = unexpected state!
+
+  whenever an object is done, in any of the possible states, the
+  arg dependency timer must be reset 
+
+*/
Index: /tags/start/Ohana/src/elixir/src/CheckDepend.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/CheckDepend.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/CheckDepend.c	(revision 12606)
@@ -0,0 +1,52 @@
+# include "controller.h"
+
+int CheckDepend (Object *object, int argc, char **argv, int *argd) {
+
+  int i;
+  struct stat filestat;
+  uid_t uid;
+  gid_t gid;
+  int status;
+  struct timeval now;
+  FILE *logfile;
+  double dtime;
+
+  uid = getuid();
+  gid = getgid();
+
+  for (i = 0; i < argc; i++) {
+    if (argd[i]) {
+      /* check permission to read file */
+      status = stat (argv[i], &filestat);
+      
+      /* continue if file exists and is accessible */
+      if (!status) {
+	if ((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR)) continue;
+	if ((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP)) continue;
+	if (filestat.st_mode & S_IROTH) continue;
+      }
+
+      /* if the file doesn't exist or is inaccessible, check the timer on this object */
+      if (object[0].timer.tv_sec == 0) {
+	gettimeofday (&object[0].timer, (void *) NULL);
+	return (0);
+      } 
+      
+      gettimeofday (&now, (void *) NULL);
+      dtime = DTIME (now, object[0].timer);
+      if (dtime > argd[i]) {
+	logfile = LogOpen (object[0].logfile);
+	fprintf (logfile, "timeout on %s: %f > %d\n", argv[i], dtime, argd[i]);
+	if (logfile != stderr) fclose (logfile);
+	object[0].status &= TIMEOUT;
+	return (2);
+      } else {
+	return (0);
+      }
+    }
+  }
+
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/elixir/src/CheckEndingState.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/CheckEndingState.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/CheckEndingState.c	(revision 12606)
@@ -0,0 +1,80 @@
+# include "controller.h"
+
+static int Nsuccess = 0;
+static int Nfailure = 0;
+static double timeout;
+struct timeval start;
+static int Reload = FALSE;
+
+int CheckEndingState (Process *global, int Nobjects, int Dynamic) {
+  
+  int Ndone;
+  struct timeval now;
+  double dtime;
+  
+  /* check the success and failure queues for newly added objects */
+  
+  if (global[0].success[0].Nobject > Nsuccess) {
+    DumpFinished (global[0].success, Nsuccess, global[0].argv[0]);
+    Nsuccess = global[0].success[0].Nobject;
+  }
+  if (global[0].failure[0].Nobject > Nfailure) {
+    DumpFinished (global[0].failure, Nfailure, global[0].argv[1]);
+    Nfailure = global[0].failure[0].Nobject;
+  }
+
+  if (Dynamic) return  (TRUE);
+  
+  Ndone = 0;
+  Ndone += global[0].success[0].Nobject;
+  Ndone += global[0].failure[0].Nobject;
+
+  if (Reload) {
+    gettimeofday (&now, (void *) NULL);
+    dtime = DTIME (now, start);
+    if (dtime > timeout) return (FALSE);
+  }
+  
+  if (Ndone == Nobjects)  
+    return (FALSE);
+  else
+    return (TRUE);
+}
+
+void DumpFinished (Queue *queue, int Nstart, char *filename) {
+  
+  int i, j;
+  FILE *f;
+  
+  f = fopen (filename, "a");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't output status of finished objects to %s\n", filename);
+    f = stderr;
+  }
+  
+  for (i = Nstart; i < queue[0].Nobject; i++) {
+    
+    for (j = 0; j < queue[0].object[i][0].argc; j++) {
+      fprintf (f, "%s ", queue[0].object[i][0].argv[j]);
+    }
+    fprintf (f, "%08x %s\n", queue[0].object[i][0].status, queue[0].object[i][0].lastproc);
+  }
+  
+  if (f != stderr) fclose (f);
+  
+}
+
+int SetExitTimer () {
+
+  timeout = GetTimeout ();
+  gettimeofday (&start, (void *) NULL);
+  Reload = TRUE;
+  return (TRUE);
+}
+
+/* 
+   
+   global.success = global[0].argv[0]
+   global.failure = global[0].argv[1]
+   
+*/
Index: /tags/start/Ohana/src/elixir/src/CheckMachineStatus.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/CheckMachineStatus.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/CheckMachineStatus.c	(revision 12606)
@@ -0,0 +1,131 @@
+# include "controller.h"
+# define MAXTIME 120
+
+static double timeout;
+
+void RegisterTimeout (double value) {
+ timeout = value;
+}
+
+double GetTimeout () {
+  return (timeout);
+}
+
+int CheckMachineStatus (Machine *machine) {
+
+  unsigned int status;
+  int Nread;
+  struct timeval now;
+  FILE *logfile;
+  float dtime;
+
+  status = machine[0].status;
+
+  if (status == IDLE) return (status);
+  if (status == DONE) return (status);
+  if (status == DOWN) return (status);
+
+  status &= ~MESSAGE; /* clear MESSAGE status */
+  
+  /* read from socket into fifo */
+  ShiftFifo (&machine[0].fifo);
+
+  Nread = ReadtoFifo (&machine[0].fifo, machine[0].rsock);
+  
+  /* evaluate data in message */
+  switch (Nread) {
+  case 0:
+    status = DOWN;
+    break;
+  case -1:
+    status |= BUSY;
+    gettimeofday (&now, (void *) NULL);
+    dtime = DTIME (now, machine[0].quiet);
+    if (dtime > timeout) {
+      logfile = LogOpen (machine[0].object[0].logfile);
+      fprintf (logfile, "%s: process is taking too long, giving up\n", machine[0].hostname);
+      if (logfile != stderr) fclose (logfile);
+      fprintf (stderr, "process on %s hung?  killing and retrying...\n", machine[0].hostname);
+      /* interrupt process which is running */
+      kill (machine[0].pid, SIGINT);
+      status = TIMEOUT;
+      /* status = (JOBDONE | FAILURE); */
+    }
+    break;
+  default:
+    status |= MESSAGE;
+    gettimeofday (&machine[0].quiet, (void *) NULL);
+    if (memstr (machine[0].fifo.buffer, "ERROR",        machine[0].fifo.Nbuffer))
+      status |= FAILURE;
+    if (memstr (machine[0].fifo.buffer, "SUCCESS",      machine[0].fifo.Nbuffer))
+      status |= SUCCESS;
+    if (memstr (machine[0].fifo.buffer, "PROCESS DONE", machine[0].fifo.Nbuffer))
+      status |= JOBDONE;
+    break;
+  }
+
+  /* evaluate status completion-type status signals */
+  switch (status & (JOBDONE | SUCCESS | FAILURE)) {
+  case FAILURE:
+  case SUCCESS:
+  case JOBDONE:
+    if (status & WAITING) break;
+    status |= WAITING;
+    gettimeofday (&machine[0].timer, (void *) NULL);
+    break;
+  case (JOBDONE | SUCCESS):
+  case (JOBDONE | FAILURE):
+    status |= DONE;
+    break;
+  case (FAILURE | SUCCESS):
+  case (JOBDONE | FAILURE | SUCCESS):
+    status |= ERROR;
+    break;
+  default:
+    break;
+  }
+
+  /* check for completion timeout */
+  if (status & WAITING) {
+    gettimeofday (&now, (void *) NULL);
+    if (DTIME (now, machine[0].timer) > MAXTIME) {
+      switch (status & (JOBDONE | SUCCESS | FAILURE)) {
+      case JOBDONE:
+	status |= CRASH;
+	break;
+      case SUCCESS:
+      case FAILURE:
+      default:
+	status |= ERROR;
+	break;
+      }
+    }
+  }
+
+  machine[0].object[0].status = status;
+  machine[0].status = status;
+
+  return (status);
+
+}
+
+
+/* machine status:
+
+   the machine can have several possible statuss, made up of specific bits
+   in the status variable:
+
+   IDLE 0x00 - no process running on host
+   DOWN 0x01 - no connection to host
+   BUSY 0x02 - no message on socket
+   DONE 0x04 - process completed
+
+   MESSAGE 0x08 - message on socket
+   FAILURE 0x10 - process reported 'failure'
+   SUCCESS 0x20 - process reported 'success'
+   JOBDONE 0x40 - process reported 'jobdone'
+   WAITING 0x80 - process reported 'jobdone'
+
+   ERROR   0x010 - unexpected return values
+   CRASH   0x020 - process crashed
+*/
Index: /tags/start/Ohana/src/elixir/src/CheckMessages.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/CheckMessages.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/CheckMessages.c	(revision 12606)
@@ -0,0 +1,68 @@
+# include "controller.h"
+
+static struct timeval then = {0,0};
+static char *MessageFile = (char *) NULL;
+
+void SetMessageFile (char *filename) {
+  MessageFile = filename;
+}
+
+int CheckMessages () {
+  
+  int status, Message;
+  struct timeval now;
+  char *message, *p, *p2;
+  char file[256], cmd[64];
+
+  /* we should only do this check every 200ms or so */
+  gettimeofday (&now, (void *) NULL);
+  if (DTIME (now, then) < 0.2) return (1);
+
+  if (MessageFile == (char *) NULL) {
+    fprintf (stderr, "not ready for messages\n");
+    return (FALSE);
+  }
+
+  status = WaitMsg (MessageFile, &message, 0.1);
+  then = now;
+  if (!status) return (FALSE);
+
+  Message = 0;
+
+  /* loop over all lines in message */
+  p = message;
+  while (strlen (p) > 0) {
+    p2 = strchr (p, '\n');
+    if (p2 == (char *) NULL) {
+      p2 = p + strlen (p) - 1;
+    } else {
+      *p2 = 0;
+    }
+
+    sscanf (p, "%s %s", cmd, file);
+
+    if (!strcasecmp (cmd, "ALIVE"))  {
+      WriteMsg (file, "BUSY");
+    }
+    if (!strcasecmp (cmd, "TIMES")) {
+      DumpProcessTimes (file);
+    }
+    if (!strcasecmp (cmd, "STATUS")) {
+      DumpStatus (file); 
+    }
+    if (!strcasecmp (cmd, "STOP"))   {
+      WriteMsg (file, "Elixir will end when processes are done");
+      ElixirStop ();
+    }
+    if (!strcasecmp (cmd, "ABORT"))  {
+      WriteMsg (file, "Elixir is exiting without finishing");
+      Shutdown (1);
+    }
+
+    p = p2 + 1;
+
+  }
+
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/elixir/src/CheckProcess.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/CheckProcess.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/CheckProcess.c	(revision 12606)
@@ -0,0 +1,57 @@
+# include "controller.h"
+
+int CheckProcess (Process *process) {
+
+  Machine *machine;
+  int cargc, *cargd;
+  char **cargv;
+  Object *object;
+
+  CheckCluster (process[0].cluster, process[0].success, process[0].failure, process[0].pending);
+  if (drand48() > 0.5) return (FALSE);
+
+
+  if ((object = GetObject (process[0].pending)) == (Object *) NULL) return (FALSE);
+  object[0].lastproc = process[0].name;
+
+  /* can't create arguments, some dependencies might not be ready */
+  if (!MakeArgs (process, object, &cargc, &cargv, &cargd)) {
+    FreeArgs (cargc, cargv, cargd);
+    PutObject (process[0].pending, object);
+    return (FALSE);
+  }
+
+  /* dependencies not ready */
+  switch (CheckDepend (object, cargc, cargv, cargd)) {
+  case 0:
+    FreeArgs (cargc, cargv, cargd);
+    PutObject (process[0].pending, object);
+    return (FALSE);
+  case 2:
+    FreeArgs (cargc, cargv, cargd);
+    PutObject (process[0].failure, object);
+    return (FALSE);
+  case 1:
+  default:
+    break;
+  }
+    
+  /* no machine ready */
+  if ((machine = GrabMachine ()) == (Machine *) NULL) {
+    /* need to free appropriate items from above */
+    FreeArgs (cargc, cargv, cargd);
+    PushObject (process[0].pending, object);
+    return (FALSE);
+  }
+
+  StartMachine (machine, object, cargc, cargv);
+  FreeArgs (cargc, cargv, cargd);
+  StartProcessTimer (process, machine);
+
+  PutMachine (machine, process[0].cluster);
+  return (TRUE);
+}
+
+/* objects that are not ready go to the bottom of the stack (PutObject)
+   objects that are ready, but have no machine free, go to top of stack (PushObject) 
+*/
Index: /tags/start/Ohana/src/elixir/src/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/ConfigInit.c	(revision 12606)
@@ -0,0 +1,187 @@
+# include "controller.h"
+
+void SIG_STOP (int sig) {
+  fprintf (stderr, "trapped signal %d, exiting when jobs are done\n", sig);
+  ElixirStop ();
+}
+
+void SIG_MESSAGE (int sig) {
+  fprintf (stderr, "trapped signal %d, reading message\n", sig);
+  CheckMessages ();
+}
+
+void SIG_DIE (int sig) {
+  fprintf (stderr, "trapped signal %d, exiting\n", sig);
+  Shutdown (1);
+}
+
+void SIG_PIPE (int sig) {
+  fprintf (stderr, "pipe signal %d\n", sig);
+}
+
+char *ConfigInit (int *argc, char **argv) {
+
+  int N;
+  char *config, *file;
+
+  /* use default settings */
+  signal (SIGKILL,   SIG_DFL);    
+  signal (SIGCONT,   SIG_DFL);    
+  signal (SIGSTOP,   SIG_DFL);    
+
+  /* exit on these signals */
+  signal (SIGILL,    SIG_DIE);     
+  signal (SIGABRT,   SIG_DIE);    
+  signal (SIGFPE,    SIG_DIE);     
+  signal (SIGSEGV,   SIG_DIE);    
+  signal (SIGTERM,   SIG_DIE);    
+  signal (SIGBUS,    SIG_DIE);     
+  signal (SIGTRAP,   SIG_DIE);    
+  signal (SIGXCPU,   SIG_DIE);    
+  signal (SIGXFSZ,   SIG_DIE);    
+  signal (SIGIOT,    SIG_DIE);     
+  signal (SIGPWR,    SIG_DIE);     
+  signal (SIGHUP,    SIG_IGN);
+  signal (SIGINT,    SIG_DIE);
+  signal (SIGQUIT,   SIG_IGN);
+  signal (SIGPIPE,   SIG_PIPE);    
+  signal (SIGALRM,   SIG_IGN);    
+  signal (SIGUSR1,   SIG_STOP);    
+  signal (SIGUSR2,   SIG_MESSAGE);    
+  signal (SIGCHLD,   SIG_IGN);    
+  signal (SIGTSTP,   SIG_IGN);    
+  signal (SIGTTIN,   SIG_IGN);    
+  signal (SIGTTOU,   SIG_IGN);    
+  signal (SIGPOLL,   SIG_IGN);    
+  signal (SIGPROF,   SIG_IGN);    
+  signal (SIGURG,    SIG_IGN);     
+  signal (SIGVTALRM, SIG_IGN);  
+  signal (SIGIO,     SIG_IGN);      
+  signal (SIGWINCH,  SIG_IGN);   
+
+  /* signals which are not always defined */
+# ifdef SIGSYS
+  signal (SIGSYS,    SIG_DIE);     
+# endif
+# ifdef SIGEMT
+ signal (SIGEMT,     SIG_DIE); 
+# endif
+# ifdef SIGSTKFLT
+  signal (SIGSTKFLT, SIG_DIE);  
+# endif
+# ifdef SIGINFO
+ signal (SIGINFO,    SIG_DIE); 
+# endif
+# ifdef SIGCLD
+  signal (SIGCLD,    SIG_IGN);     
+# endif
+# ifdef SIGLOST
+  signal (SIGLOST,   SIG_IGN); 
+# endif
+# ifdef SIGUNUSED
+  signal (SIGUNUSED, SIG_IGN); 
+# endif
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  if (file == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't choose configuration file\n");
+    Shutdown (1);
+  }    
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    Shutdown (1);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+  free (file);
+
+  if ((N = get_argument (*argc, argv, "-restart"))) {
+    char pidfile[128];
+
+    remove_argument (N, argc, argv);
+    if (!ScanConfig (config, "global.pid", "%s",  0, pidfile)) {
+      fprintf (stderr, "pid file not defined: global.pid\n");
+      exit (1);
+    }
+    HalttoRestart (pidfile);
+  }
+
+  if ((*argc != 2) && (*argc != 1)) {
+    fprintf (stderr, "USAGE: elixir [list]\n");
+    fprintf (stderr, "       elixir [-kill]\n");
+    fprintf (stderr, "       elixir [-stop]\n");
+    fprintf (stderr, "       elixir [-status]\n");
+    Shutdown (1);
+  }
+  
+  /* special command-line options */
+  { 
+    char pidfile[128], msgfile[128];
+
+    if (!ScanConfig (config, "global.pid", "%s",  0, pidfile)) {
+      fprintf (stderr, "pid file not defined: global.pid\n");
+      exit (1);
+    }
+    
+    if (!ScanConfig (config, "global.msg", "%s",  0, msgfile)) {
+      fprintf (stderr, "msg file not defined: global.msg\n");
+      exit (1);
+    }
+    
+    if (!ScanConfig (config, "CONNECT", "%s",  0, CONNECT)) {
+      sprintf (CONNECT, "/usr/bin/rsh");
+    }
+    
+    if (get_argument (*argc, argv, "-kill"))   KillElixir (pidfile);
+    if (get_argument (*argc, argv, "-stop"))   HaltElixir (pidfile);
+    if (get_argument (*argc, argv, "-status")) StatusElixir (pidfile, msgfile);
+  }
+
+  return (config);
+
+}
+
+/*
+
+  SIGHUP             1        A      Hangup detected on controlling terminal
+                                     or death of controlling process
+  SIGINT             2        A      Interrupt from keyboard
+  SIGQUIT            3        C      Quit from keyboard
+  SIGILL             4        C      Illegal Instruction
+  SIGABRT            6        C      Abort signal from abort(3)
+  SIGFPE             8        C      Floating point exception
+  SIGKILL            9       AEF     Kill signal
+  SIGSEGV           11        C      Invalid memory reference
+  SIGPIPE           13        A      Broken pipe: write to pipe with no readers
+  SIGALRM           14        A      Timer signal from alarm(2)
+  SIGTERM           15        A      Termination signal
+  SIGUSR1        30,10,16     A      User-defined signal 1
+  SIGUSR2        31,12,17     A      User-defined signal 2
+  SIGCHLD        20,17,18     B      Child stopped or terminated
+  SIGCONT        19,18,25            Continue if stopped
+  SIGSTOP        17,19,23    DEF     Stop process
+  SIGTSTP        18,20,24     D      Stop typed at tty
+  SIGTTIN        21,21,26     D      tty input for background process
+  SIGTTOU        22,22,27     D      tty output for background process
+  SIGBUS         10,7,10      C      Bus error (bad memory access)
+  SIGPOLL                     A      Pollable event (Sys V). Synonym of SIGIO
+  SIGPROF        27,27,29     A      Profiling timer expired
+  SIGSYS         12,-,12      C      Bad argument to routine (SVID)
+  SIGTRAP           5         C      Trace/breakpoint trap
+  SIGURG         16,23,21     B      Urgent condition on socket (4.2 BSD)
+  SIGVTALRM      26,26,28     A      Virtual alarm clock (4.2 BSD)
+  SIGXCPU        24,24,30     C      CPU time limit exceeded (4.2 BSD)
+  SIGXFSZ        25,25,31     C      File size limit exceeded (4.2 BSD)
+  SIGIOT            6         C      IOT trap. A synonym for SIGABRT
+  SIGEMT          7,-,7
+  SIGSTKFLT       -,16,-      A      Stack fault on coprocessor
+  SIGIO          23,29,22     A      I/O now possible (4.2 BSD)
+  SIGCLD          -,-,18             A synonym for SIGCHLD
+  SIGPWR         29,30,19     A      Power failure (System V)
+  SIGINFO         29,-,-             A synonym for SIGPWR
+  SIGLOST         -,-,-       A      File lock lost
+  SIGWINCH       28,28,20     B      Window resize signal (4.3 BSD, Sun)
+  SIGUNUSED       -,31,-      A      Unused signal (will be SIGSYS)
+*/
Index: /tags/start/Ohana/src/elixir/src/ConfigPID.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/ConfigPID.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/ConfigPID.c	(revision 12606)
@@ -0,0 +1,63 @@
+# include "controller.h"
+
+static char *PIDMaster = (char *) NULL;
+
+void ConfigPID (char *PIDFile) {
+
+  pid_t pid;
+  char *username, machine[256];
+  FILE *f;
+
+  f = fopen (PIDFile, "r");
+  if (f == (FILE *) NULL) { 
+
+    pid = getpid ();
+    username = getenv ("USER");
+    if (username == (char *) NULL) {
+      fprintf (stderr, "error getting username\n");
+      exit (2);
+    }
+    bzero (machine, 256);
+    if (gethostname (machine, 256)) {
+      fprintf (stderr, "error getting hostname\n");
+      exit (2);
+    }
+
+    f = fopen (PIDFile, "w");
+    if (f == (FILE *) NULL) { 
+      fprintf (stderr, "can't write to PID file %s\n", PIDFile);
+      exit (2);
+    }
+
+    fprintf (f, "PID:     %d\n", pid);
+    fprintf (f, "USER:    %-s\n", username);
+    fprintf (f, "MACHINE: %-s\n", machine);
+    fclose (f);
+
+    PIDMaster = PIDFile;
+    return; 
+  }
+
+  ALLOCATE (username, char, 256);
+  fscanf (f, "%*s %d", &pid);
+  fscanf (f, "%*s %s", username);
+  fscanf (f, "%*s %s", machine);
+  fclose (f);
+
+  fprintf (stderr, "elixir is apparently running:\n\n");
+  fprintf (stderr, "  machine: %s\n", machine);
+  fprintf (stderr, "  user: %s\n", username);
+  fprintf (stderr, "  PID: %d\n", pid);
+  fprintf (stderr, "  remove %s if elixir has died unexpectedly\n", PIDFile);
+  Shutdown (1);
+}
+
+void RemovePID () {
+  
+  if (PIDMaster == (char *) NULL) 
+    return;
+  
+  if (unlink (PIDMaster)) {
+    fprintf (stderr, "error deleting PID File %s\n", PIDMaster);
+  }   
+}
Index: /tags/start/Ohana/src/elixir/src/DefineProcesses.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/DefineProcesses.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/DefineProcesses.c	(revision 12606)
@@ -0,0 +1,142 @@
+# include "controller.h"
+
+Process **DefineProcesses (Process *global, int *nprocess, char *config) {
+
+  int i, j, status;
+  char procname[256], entry[256], field[256];
+  Process **process;
+  int Nprocess, NPROCESS;
+  double timeout;
+
+  global[0].success = InitQueue ();
+  global[0].failure = InitQueue ();
+  
+  ALLOCATE (global[0].argv, char *, 8);
+  ALLOCATE (global[0].argv[0], char, 256);
+  ALLOCATE (global[0].argv[1], char, 256);
+  ALLOCATE (global[0].argv[2], char, 256);
+  ALLOCATE (global[0].argv[3], char, 256);
+  ALLOCATE (global[0].argv[4], char, 256);
+  ALLOCATE (global[0].argv[5], char, 256);
+  ALLOCATE (global[0].argv[6], char, 256);
+  ALLOCATE (global[0].argv[7], char, 256);
+  
+  status =  (int) ScanConfig (config, "global.Nargs",   "%d",  0, &global[0].argc);
+  status &= (int) ScanConfig (config, "global.success", "%s",  0, global[0].argv[0]);
+  status &= (int) ScanConfig (config, "global.failure", "%s",  0, global[0].argv[1]);
+  status &= (int) ScanConfig (config, "global.pending", "%s",  0, global[0].argv[2]);
+  status &= (int) ScanConfig (config, "global.logfile", "%s",  0, global[0].argv[3]);
+  status &= (int) ScanConfig (config, "global.source",  "%s",  0, global[0].argv[4]);
+  status &= (int) ScanConfig (config, "global.msg",     "%s",  0, global[0].argv[5]);
+  status &= (int) ScanConfig (config, "global.end",     "%s",  0, global[0].argv[6]);
+  status &= (int) ScanConfig (config, "global.pid",     "%s",  0, global[0].argv[7]);
+  if (!status) { 
+    fprintf (stderr, "missing global entry from config\n");
+    fprintf (stderr, "global.Nargs: %d\n", global[0].argc);
+    fprintf (stderr, "global.argv[0]: %s\n", global[0].argv[0]);
+    fprintf (stderr, "global.argv[1]: %s\n", global[0].argv[1]);
+    fprintf (stderr, "global.argv[2]: %s\n", global[0].argv[2]);
+    fprintf (stderr, "global.argv[3]: %s\n", global[0].argv[3]);
+    fprintf (stderr, "global.argv[4]: %s\n", global[0].argv[4]);
+    fprintf (stderr, "global.argv[5]: %s\n", global[0].argv[5]);
+    fprintf (stderr, "global.argv[6]: %s\n", global[0].argv[6]);
+    fprintf (stderr, "global.argv[7]: %s\n", global[0].argv[7]);
+    Shutdown (1);
+  }
+
+  ScanConfig (config, "global.timeout", "%lf", 0, &timeout);
+  if (timeout < 1) {
+    fprintf (stderr, "global.timeout is absurd: %f\n", timeout);
+    Shutdown (1);
+  }
+  if (timeout < 100) {
+    fprintf (stderr, "**** global.timeout is very short (%f) ****\n", timeout);
+  }
+  RegisterTimeout (timeout);
+  
+  Nprocess = 0;
+  NPROCESS = 5;
+  ALLOCATE (process, Process *, NPROCESS);
+
+  /* find all entries in config file labeled 'process' */
+  for (i = 1; ScanConfig (config, "process", "%s", i, procname); i++) {
+    process[Nprocess] = ConfigProcess (config, procname);
+    Nprocess ++;
+    if (Nprocess == NPROCESS) {
+      NPROCESS += 5;
+      REALLOCATE (process, Process *, NPROCESS);
+    }
+  }
+  if (Nprocess == 0) {
+    fprintf (stderr, "no processes defined in config file\n");
+    Shutdown (1);
+  }
+
+  /* make links between processes */
+  for (i = 0; i < Nprocess; i++) {
+    /* connect this process success queue */
+    sprintf (field, "%s.success", process[i][0].name);
+    if (!ScanConfig (config, field, "%s", 0, entry)) {
+      fprintf (stderr, "missing process.success entry for %s\n", process[i][0].name);
+      Shutdown (1);
+    }
+    if (!strcasecmp (entry, "global")) {
+      process[i][0].success = global[0].success;
+      goto stage1;
+    }
+    for (j = 0; j < Nprocess; j++) {
+      if (!strcasecmp (entry, process[j][0].name)) {
+	if (i == j) {
+	  fprintf (stderr, "ERROR: can't connect a process to itself: %s\n", process[i][0].name);
+	  Shutdown (1);
+	}
+	process[i][0].success = process[j][0].pending;
+	goto stage1;
+      }
+    }
+    fprintf (stderr, "ERROR: can't connect process %s to target %s\n", process[i][0].name, entry);
+    Shutdown (1);
+    
+  stage1:
+    /* connect this process failure queue */
+    sprintf (field, "%s.failure", process[i][0].name);
+    if (!ScanConfig (config, field, "%s", 0, entry)) {
+      fprintf (stderr, "missing process.failure entry for %s\n", process[i][0].name);
+      Shutdown (1);
+    }
+    if (!strcasecmp (entry, "global")) {
+      process[i][0].failure = global[0].failure;
+      goto stage2;
+    }
+    for (j = 0; j < Nprocess; j++) {
+      if (!strcasecmp (entry, process[j][0].name)) {
+	if (i == j) {
+	  fprintf (stderr, "ERROR: can't connect a process to itself: %s\n", process[i][0].name);
+	  Shutdown (1);
+	}
+	process[i][0].failure = process[j][0].pending;
+	goto stage2;
+      }
+    }
+    fprintf (stderr, "ERROR: can't connect process %s to target %s\n", process[i][0].name, entry);
+    Shutdown (1);
+    
+  stage2:
+    continue;
+  }
+
+  /* link global process to first process */
+  for (j = 0; j < Nprocess; j++) {
+    if (!strcasecmp (global[0].argv[2], process[j][0].name)) {
+      global[0].pending = process[j][0].pending;
+      goto stage3;
+    }
+  }
+  fprintf (stderr, "ERROR: can't connect global process to target %s\n", global[0].argv[2]);
+  Shutdown (1);
+ 
+stage3:
+  *nprocess = Nprocess;
+  return (process);
+
+}
Index: /tags/start/Ohana/src/elixir/src/DumpStatus.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/DumpStatus.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/DumpStatus.c	(revision 12606)
@@ -0,0 +1,86 @@
+# include "controller.h"
+
+int DumpStatus (char *filename) {
+
+  FILE *f;
+  int i, fd, state, total, mode;
+  Process *global, **process;
+  int Nprocess, Nobject, Dynamic;
+
+  process = GetProcessInfo (&global, &Nprocess, &Nobject);
+  Dynamic = GetDynamicState ();
+
+  if (filename == (char *) NULL) {
+    system ("tput clear");
+    f = stderr;
+  } else {
+    /* lock file */
+    fd = setlockfile2 (filename, 0.1, LCK_XCLD, &state);
+    if (fd == -1) return (2);
+    f = fdopen (fd, "r+");
+    if (f == (FILE *) NULL) {
+      mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+      fchmod (fd, mode);
+      clearlockfile2 (filename, fd, LCK_XCLD, &state);
+      return (2);
+    }
+    fseek (f, 0, SEEK_END);
+  }  
+  
+  fprintf (f, "processes status:\n");
+  fprintf (f, "            name   pending  success  failure  total\n");
+  fprintf (f, "----------------------------------------------------------------\n");
+  total = global[0].pending[0].Nobject + global[0].success[0].Nobject + global[0].failure[0].Nobject;
+  fprintf (f, "%16s    %6d   %6d   %6d   %4d\n", "global", 
+	   global[0].pending[0].Nobject, global[0].success[0].Nobject, global[0].failure[0].Nobject, total); 
+  for (i = 0; i < Nprocess; i++) {
+    fprintf (f, "%16s    %6d\n", process[i][0].name, process[i][0].pending[0].Nobject); 
+  }
+  fprintf (f, "\n");
+
+  DumpMachineStatus (f);
+
+  fprintf (f, "\n");
+  fprintf (f, "objects loaded so far: %d\n\n", Nobject);
+  if (Dynamic) {
+    fprintf (f, "accepting input from FIFO\n");
+  } else {
+    fprintf (f, "NOT accepting input from FIFO\n");
+  }    
+  
+  if (f != stderr) {
+    mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    fchmod (fd, mode);
+    clearlockfile2 (filename, fd, LCK_XCLD, &state);
+    fclose (f);
+  }
+  return (TRUE);
+}
+
+/*
+
+processes status:
+            name  pending  success  failure  total
+----------------------------------------------------------------
+          global        1        0        4      5
+           mkdir        1
+         flatten        0
+          dophot        0
+         imclean        0
+          gastro        0
+         addstar        0
+          rmfile        5
+
+machine status:
+          name  process  status
+----------------------------------------------------------------
+         kiawe  rmfile   1
+         kiawe  addstar  9
+          milo  addstar  1
+
+objects loaded so far: 13
+
+accepting input from FIFO
+
+
+*/
Index: /tags/start/Ohana/src/elixir/src/FifoOps.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/FifoOps.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/FifoOps.c	(revision 12606)
@@ -0,0 +1,96 @@
+# include "controller.h"
+
+int InitFifo (Fifo *fifo, int Nalloc, int Nextra) {
+
+  if (Nextra >= Nalloc) {
+    fprintf (stderr, "absurd fifo definition\n");
+    return (FALSE);
+  }
+
+  fifo[0].Nalloc = Nalloc;
+  fifo[0].Nextra = Nextra;
+  fifo[0].Nmaxread = Nalloc - Nextra;
+  fifo[0].Nlast = 0;
+  fifo[0].Nbuffer = 0;
+
+  ALLOCATE (fifo[0].buffer, char, fifo[0].Nalloc);
+
+  return (TRUE);
+
+}
+
+int FlushFifo (Fifo *fifo) {
+
+  fifo[0].Nlast = 0;
+  fifo[0].Nbuffer = 0;
+
+  return (TRUE);
+
+}
+
+/* after a shift, we can always read 
+   fifo[0].Nmaxread 
+   bytes into 
+   &fifo[0].buffer[Nbuffer] 
+   which is the byte after then end of existing data */
+
+int ShiftFifo (Fifo *fifo) {
+
+  int Nextra, Nshift;
+
+  Nextra = fifo[0].Nextra;
+  Nshift = fifo[0].Nbuffer - fifo[0].Nextra;
+  if (Nshift <= 0) return (TRUE);
+
+  memcpy (fifo[0].buffer, &fifo[0].buffer[Nshift], Nextra);
+  fifo[0].Nbuffer = Nextra;
+  fifo[0].Nlast = Nextra;
+
+  return (TRUE);
+}
+
+/* like a standard read, ReadtoFifo returns Nbytes read,
+   -1 for sock busy, or 0 for sock closed */
+
+int ReadtoFifo (Fifo *fifo, int sock) {
+
+  int Nread;
+  int Nbuffer, Nmaxread;
+
+  if (sock == 0) {
+    fprintf (stderr, "error with socket?\n");
+    return (0);
+  }
+
+  fifo[0].Nlast = fifo[0].Nbuffer;
+
+  Nbuffer = fifo[0].Nbuffer;
+  Nmaxread = fifo[0].Nmaxread;
+  Nread = read (sock, &fifo[0].buffer[Nbuffer], Nmaxread);
+
+  if (Nread > 0) fifo[0].Nbuffer += Nread;
+
+  if (Nread == -1) {
+    /* check for possible errors.  anything other than EAGAIN
+       is bad and should indicate the connection is down */
+    switch (errno) {
+    case EAGAIN:
+    case EIO:
+      Nread = -1;
+      break;
+    default:
+      fprintf (stderr, "read error: %d\n", errno);
+      Nread = 0;
+      break;
+    }
+  }
+
+  return (Nread);
+}
+
+void FreeFifo (Fifo *fifo) {
+
+  if (fifo[0].buffer != (char *) NULL) {
+    free (fifo[0].buffer);
+  }
+}
Index: /tags/start/Ohana/src/elixir/src/InitProcess.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/InitProcess.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/InitProcess.c	(revision 12606)
@@ -0,0 +1,19 @@
+# include "controller.h"
+
+Process *InitProcess (char *name, Queue *pending, Queue *failure, int (*mkargs)()) {
+
+  Process *process;
+
+  ALLOCATE (process, Process, 1);
+
+  process[0].success = InitQueue ();
+  process[0].failure = failure;
+  process[0].pending = pending;
+
+  process[0].name    = strcreate (name);
+  /* process[0].mkarg   = mkargs; */
+
+  process[0].cluster = InitCluster ();
+
+  return (process);
+}
Index: /tags/start/Ohana/src/elixir/src/LoadPending.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/LoadPending.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/LoadPending.c	(revision 12606)
@@ -0,0 +1,132 @@
+# include "controller.h"
+
+static struct timeval then = {0.0, 0.0};
+
+/* LoadPending returns the number of objects loaded from inlist
+   
+   state can be: 
+   0 - success
+   1 - file locked
+   2 - file has EOF flag
+   3 - error in input 
+*/
+
+int LoadPending (Process *global, char *filename, int *state, int *dynamic) {
+
+  int i, status, depend, Nobjects;
+  int fd, lockstate, mode;
+  FILE *f;
+  char name[7][256], line[1024];
+  struct timeval now;
+  Object *object;
+
+  *state = 0;
+  Nobjects = 0;
+
+  /* we should only do this check every 1sec or so */
+  gettimeofday (&now, (void *) NULL);
+  if (DTIME (now, then) < 1.0) return (Nobjects);
+  then = now;
+
+  /* if dynamic, we must lock the file first, but not if not dynamic */
+  if (*dynamic) {
+    
+    /* check lockfile - don't remove list if locked */
+    fd = setlockfile2 (filename, 1.0, LCK_XCLD, &lockstate);
+    if (fd == -1) { 
+      *state = 1;
+      return (Nobjects);
+    }
+    f = fdopen (fd, "r+");
+    if (f == (FILE *) NULL) {
+      clearlockfile2 (filename, fd, LCK_XCLD, &lockstate);
+      *state = 1;
+      return (Nobjects);
+    }
+  } else {
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      *state = 1;
+      return (Nobjects);
+    }
+  }
+
+  /* read lines, parse each line */
+  while (1) {
+    if (scan_line (f, line) == EOF) goto escape;
+
+    switch (global[0].argc) {
+    case 1:
+      status = sscanf (line, "%s", name[0]);
+      break;
+    case 2:
+      status = sscanf (line, "%s%s", name[0], name[1]);
+      break;
+    case 3:
+      status = sscanf (line, "%s%s%s", name[0], name[1], name[2]);
+      break;
+    case 4:
+      status = sscanf (line, "%s%s%s%s", name[0], name[1], name[2], name[3]);
+      break;
+    case 5:
+      status = sscanf (line, "%s%s%s%s%s", name[0], name[1], name[2], name[3], name[4]);
+      break;
+    case 6:
+      status = sscanf (line, "%s%s%s%s%s%s", name[0], name[1], name[2], name[3], name[4], name[5]);
+      break;
+    case 7:
+      status = sscanf (line, "%s%s%s%s%s%s%s", name[0], name[1], name[2], name[3], name[4], name[5], name[6]);
+      break;
+    default:
+      fprintf (stderr, "ERROR: unexpected number of entries per line in input file\n");
+      *state = 3;
+      goto escape;
+    }
+
+    if (status == 0) continue;  /* an empty or blank line */
+
+    if (!strcasecmp (name[0], "EOF")) {
+      /* dynamic -> static */
+      *state = 2;
+      goto escape;
+    }
+
+    /* silently ignore lines with the wrong number of args */
+    if (status != global[0].argc) continue;
+
+    ALLOCATE (object, Object, 1);
+    object[0].argc = status;
+    ALLOCATE (object[0].argv, char *, status);
+    for (i = 0; i < status; i++) {
+      object[0].argv[i] = strcreate (name[i]);
+    }
+    
+    /* convert the global.logfile description to a specific logfile for this object */
+    ParseLine (global[0].argv[3], object[0].argc, object[0].argv, &depend, &object[0].logfile);
+    object[0].status = 0;
+    object[0].timer.tv_sec = 0;
+    object[0].lastproc = (char *) NULL;
+    PutObject (global[0].pending, object);
+    Nobjects ++;
+  }
+
+  escape:
+  if (*dynamic) {
+    if (ftruncate (fd, 0)) {
+      fprintf (stderr, "failed to clear source %s (errno %d)\n", filename, errno);
+      Shutdown (1);
+    }
+
+    /* clean up fifo - set mode to 666, unlock */
+    mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    fchmod (fd, mode);
+    clearlockfile2 (filename, fd, LCK_XCLD, &lockstate);
+  }
+  fclose (f);
+
+  if ((*state == 2) && *dynamic) {
+    *dynamic = FALSE;
+  }
+  return (Nobjects);
+
+}
Index: /tags/start/Ohana/src/elixir/src/LogOpen.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/LogOpen.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/LogOpen.c	(revision 12606)
@@ -0,0 +1,22 @@
+# include "controller.h"
+
+FILE *LogOpen (char *filename) {
+
+  FILE *f;
+  char *path;
+
+  f = fopen (filename, "a");
+
+  /* probably don't have needed directory */
+  if ((f == (FILE *) NULL) && (errno == ENOENT)) {
+    path = pathname (filename);
+    if (!mkdirhier (path)) f = fopen (filename, "a");
+  }
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "LogOpen could not open the log file %s, errno: %d\n", filename, errno);
+    f = stderr;
+  }
+
+  return (f);
+
+}
Index: /tags/start/Ohana/src/elixir/src/MachineOps.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/MachineOps.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/MachineOps.c	(revision 12606)
@@ -0,0 +1,493 @@
+# include "controller.h"
+
+/* this is in libohana -> should be in ohana.h */
+char *getcwd_cfht (char *path, int size);
+
+static Cluster *fullpool = (Cluster *) NULL;
+static Cluster *idlepool = (Cluster *) NULL;
+static Cluster *downpool = (Cluster *) NULL;
+static char *ConfigFilename;
+
+/* put machine on top of cluster */
+void PushMachine (Machine *machine, Cluster *cluster) {
+
+  int i;
+
+  if (cluster[0].Nmachine == cluster[0].NMACHINE) {
+    cluster[0].NMACHINE += 5;
+    REALLOCATE (cluster[0].machine, Machine *, cluster[0].NMACHINE);
+  }
+  for (i = cluster[0].Nmachine; i > 0; i--) {
+    cluster[0].machine[i] = cluster[0].machine[i-1];
+  }
+  cluster[0].machine[0] = machine;
+  cluster[0].Nmachine ++;
+}
+
+/* put machine on bottom of cluster */
+void PutMachine (Machine *machine, Cluster *cluster) {
+
+  if (cluster[0].Nmachine == cluster[0].NMACHINE) {
+    cluster[0].NMACHINE += 5;
+    REALLOCATE (cluster[0].machine, Machine *, cluster[0].NMACHINE);
+  }
+  cluster[0].machine[cluster[0].Nmachine] = machine;
+  cluster[0].Nmachine ++;
+}
+
+/* Get a machine from top of cluster */
+Machine *GetMachine (Cluster *cluster) {
+
+  int i;
+  Machine *machine;
+
+  if (cluster[0].Nmachine == 0) return ((Machine *) NULL);
+
+  machine = cluster[0].machine[0];
+  cluster[0].Nmachine --;
+  for (i = 0; i < cluster[0].Nmachine; i++) {
+    cluster[0].machine[i] = cluster[0].machine[i+1];
+  }
+  return (machine);
+}
+
+void IdleMachine (Machine *machine) {
+
+  machine[0].status = IDLE;
+  machine[0].object = (Object *) NULL;
+  PutMachine (machine, idlepool);
+ 
+}
+
+void DownMachine (Machine *machine) {
+
+  machine[0].status = DOWN;
+  machine[0].object = (Object *) NULL;
+  gettimeofday (&machine[0].start, (void *) NULL);
+  gettimeofday (&machine[0].timer, (void *) NULL);
+  machine[0].timer.tv_sec += 5;
+  PutMachine (machine, downpool);
+ 
+}
+
+# define NRETRIES 50
+int TestMachine (Machine *machine) {
+
+  int i, status;
+  char buffer[64];
+
+  FlushFifo (&machine[0].fifo);
+
+  if ((machine[0].wsock == 0) || (machine[0].rsock == 0)) return (FALSE);
+
+  /* writes are non-blocking.  check for EPIPE in case pipe is closed */
+  sprintf (buffer, "echo CONNECTION TEST\n");
+  status = write (machine[0].wsock, buffer, strlen(buffer));
+  if ((status == -1) && (errno == EPIPE)) {
+    fprintf (stderr, "socket unexpectedly closed in test\n");
+    CloseMachine (machine);
+    return (FALSE);
+  }
+
+  status = -1;
+  for (i = 0; (i < NRETRIES) && (status == -1); i++) {
+    status = SockScan ("CONNECTION TEST", &machine[0].fifo, machine[0].rsock);
+    if (status == 0) {
+      fprintf (stderr, "socket unexpectedly closed in test\n");
+      CloseMachine (machine);
+      return (FALSE);
+    }
+  }
+  if (i == NRETRIES) {
+    fprintf (stderr, "no response from machine, shutting it down\n");
+    CloseMachine (machine);
+    return (FALSE);
+  }
+  FlushFifo (&machine[0].fifo);
+  return (TRUE);
+}
+
+Machine *GrabMachine () {
+
+  Machine *machine;
+
+  machine = GetMachine (idlepool);
+  if (machine == (Machine *) NULL) return (machine);
+
+  if (!TestMachine (machine)) {
+    DownMachine (machine);
+    return ((Machine *) NULL);
+  }
+  return (machine);
+}
+
+Cluster *InitCluster () {
+
+  Cluster *cluster;
+
+  ALLOCATE (cluster, Cluster, 1);
+  cluster[0].NMACHINE = 5;
+  cluster[0].Nmachine = 0;
+  ALLOCATE (cluster[0].machine, Machine *, cluster[0].NMACHINE);
+  
+  return (cluster);
+
+}
+
+void InitMachines (char *config) {
+
+  int i, Nm, fd, Nout, status;
+  char name[256];
+  Machine *machine;
+  char *cwd;
+
+  fullpool = InitCluster ();
+  idlepool = InitCluster ();
+  downpool = InitCluster ();
+
+  /* processes run on these machines need to have access to the
+     exact config file used by elixir.  Therefore, we write the 
+     config file to a unique filename in this directory and pass 
+     that name to the processes which start machines.  it is 
+     crucial that the cwd be visible on the other machines, and have
+     the same path name.  when we exit (Shutdown(n)), we will delete
+     this file (but not before!). */
+  
+  /* get cwd and create config file here */
+  if ((cwd = getcwd_cfht (NULL, 1024)) == NULL) {
+    fprintf (stderr, "error getting cwd\n");
+    Shutdown (1);
+  }
+  sprintf (name, "%s/elixir.XXXXXX", cwd);
+  if ((fd = mkstemp (name)) == -1) {
+    fprintf (stderr, "can't store current config in cwd\n");
+    Shutdown (1);
+  }
+  Nout = write (fd, config, strlen (config));
+  if (Nout != strlen (config)) {
+    fprintf (stderr, "can't store current config in cwd\n");
+    Shutdown (1);
+  }
+  status = close (fd);
+  if (status == -1) {
+    fprintf (stderr, "can't store current config in cwd\n");
+    Shutdown (1);
+  }
+  ConfigFilename = strcreate (name);
+
+  /* create connection to each of the machines */
+  Nm = 0;
+  for (i = 1; ScanConfig (config, "MACHINE", "%s", i, name); i++) {
+    ALLOCATE (machine, Machine, 1);
+    machine[0].hostname = strcreate (name);
+    InitFifo (&machine[0].fifo, 0x4000, 0x1000);
+    if (ConnectMachine (machine)) {
+      IdleMachine (machine);
+    } else {
+      DownMachine (machine);
+    }
+    PutMachine (machine, fullpool);
+    Nm ++;
+  }
+  if (Nm == 0) {
+    fprintf (stderr, "no available machines, exiting\n");
+    Shutdown (1);
+  }
+      
+}
+
+int ConnectMachine (Machine *machine) {
+
+  int rsock, wsock, pid;
+  char line[256];
+
+  pid = rconnect (machine[0].hostname, CONNECT, &rsock, &wsock);
+  if (pid) {
+    machine[0].rsock = rsock;
+    machine[0].wsock = wsock;
+    machine[0].pid   = pid;
+    /* we can set up the shell here */
+    sprintf (line, "setenv PTOLEMY %s\n", ConfigFilename);
+    write (wsock, line, strlen (line));
+    sprintf (line, "umask 002\n");
+    write (wsock, line, strlen (line));
+    return (TRUE);
+  } else {
+    fprintf (stderr, "can't make connection to %s, skipping for now\n", machine[0].hostname);
+    machine[0].rsock = 0;
+    machine[0].wsock = 0;
+    machine[0].pid   = 0;
+    return (FALSE);
+  }
+}
+
+/* machine which are claimed as down need to be restarted.  
+   first, check that they really are down, then restart as needed */
+void RestartMachines () {
+  
+  int i;
+  Machine *machine;
+  double dtime;
+  struct timeval now;
+
+  for (i = 0; i < downpool[0].Nmachine; i++) {
+    machine = GetMachine (downpool);
+    if (machine == (Machine *) NULL) return;
+
+    /* we only try to reconnect if timer is expired */
+    gettimeofday (&now, (void *) NULL);
+    dtime = DTIME (machine[0].timer, now);
+    if (dtime > 0) {
+      PutMachine (machine, downpool);
+      continue;
+    }
+
+    fprintf (stderr, "restarting machine %s\n", machine[0].hostname);
+    if (TestMachine (machine)) {
+      /* machine is still alive, return to idlepool */
+      fprintf (stderr, "%s is alive\n", machine[0].hostname);
+      IdleMachine (machine);
+      continue;
+    }
+
+    if (ConnectMachine (machine)) {
+      fprintf (stderr, "connection to %s successfully restarted\n", machine[0].hostname);
+      IdleMachine (machine);
+    } else {
+      /* advance dtime so restarts happen later and later */
+      dtime = DTIME (machine[0].timer, machine[0].start);
+      dtime = dtime * 2;
+      dtime = MIN (600, dtime);
+      gettimeofday (&machine[0].start, (void *) NULL);
+      gettimeofday (&machine[0].timer, (void *) NULL);
+      machine[0].timer.tv_sec += dtime;
+      PutMachine (machine, downpool);
+    }
+  }
+
+}
+
+void Shutdown (int status) {
+
+  int i;
+
+  if (unlink (ConfigFilename) == -1) {
+    fprintf (stderr, "trouble deleting config file: %s\n", ConfigFilename);
+  }
+
+  RemovePID ();
+
+  if (fullpool == (Cluster *) NULL) exit (status);
+    
+  for (i = 0; i < fullpool[0].Nmachine; i++) {
+    CloseMachine (fullpool[0].machine[i]);
+  }
+
+  exit (status);
+
+}
+
+void Restart (char **argv) {
+
+  int i;
+
+  if (unlink (ConfigFilename) == -1) {
+    fprintf (stderr, "trouble deleting config file: %s\n", ConfigFilename);
+  }
+
+  RemovePID ();
+
+  if (fullpool == (Cluster *) NULL) execvp (argv[0], argv);
+    
+  for (i = 0; i < fullpool[0].Nmachine; i++) {
+    CloseMachine (fullpool[0].machine[i]);
+  }
+
+  execvp (argv[0], argv);
+}
+
+
+int InitMsgFile (char *file) {
+  
+  char line[256];
+  int status;
+  struct stat filestat;
+
+  if (stat (file, &filestat) == -1) return (TRUE);
+  sprintf (line, "mv -f %s %s~", file, file);
+  status = system (line);
+  return (status);
+}
+
+void CloseMachine (Machine *machine) {
+
+  char buffer[128];
+
+  sprintf (buffer, "exit\n");
+  write (machine[0].wsock, buffer, strlen(buffer));
+  close (machine[0].wsock);
+  close (machine[0].rsock);
+  fprintf (stderr, "shutdown machine %s, pid %d\n", machine[0].hostname, machine[0].pid); 
+
+}
+
+void DumpMachineStatus (FILE *f) {
+  
+  int i;
+
+  if (fullpool == (Cluster *) NULL) return;
+
+  fprintf (f, "machine status:\n");
+  fprintf (f, "          name  process  status\n");
+  fprintf (f, "----------------------------------------------------------------\n");
+  for (i = 0; i < fullpool[0].Nmachine; i++) {
+    if (fullpool[0].machine[i][0].object == (Object *) NULL) {
+      fprintf (f, "%14s %8s      %2d\n", 
+	       fullpool[0].machine[i][0].hostname,
+	       "(none)",
+	       fullpool[0].machine[i][0].status);
+      
+    } else {      
+      fprintf (f, "%14s %8s      %2d\n", 
+	       fullpool[0].machine[i][0].hostname,
+	       fullpool[0].machine[i][0].object[0].lastproc,
+	       fullpool[0].machine[i][0].status);
+    }
+
+  }
+
+}
+
+static int Nprocs, Nmachine;
+static ProcessTimers *proctimers;
+
+/* this must be called after machines have been loaded, registered */
+void InitProcessTimers (Process **process, int Nprocess) {
+  int i, j;
+
+  Nmachine = fullpool[0].Nmachine;
+  Nprocs = Nprocess;
+  ALLOCATE (proctimers, ProcessTimers, Nmachine);
+
+  for (i = 0; i < Nmachine; i++) {
+    ALLOCATE (proctimers[i].timer,   struct timeval, Nprocs);
+    ALLOCATE (proctimers[i].timesum, double,         Nprocs);
+    ALLOCATE (proctimers[i].Njobs,   int,            Nprocs);
+    ALLOCATE (proctimers[i].active,  int,            Nprocs);
+    ALLOCATE (proctimers[i].process, Process *,      Nprocs);
+    
+    for (j = 0; j < Nprocess; j++) {
+      proctimers[i].timer[j].tv_sec = 0;
+      proctimers[i].timer[j].tv_usec = 0;
+      proctimers[i].timesum[j] = 0;
+      proctimers[i].Njobs[j] = 0;
+      proctimers[i].active[j] = FALSE;
+      proctimers[i].process[j] = process[j];
+    }
+
+    proctimers[i].machine = fullpool[0].machine[i];
+
+  }
+  
+}
+
+void StartProcessTimer (Process *process, Machine *machine) {
+  
+  int i, j;
+
+  /* identify the machine */
+  for (i = 0; i < Nmachine; i++) {
+    if (proctimers[i].machine == machine) {
+      for (j = 0; j < Nprocs; j++) {
+	if (proctimers[i].process[j] == process) {
+	  gettimeofday (&proctimers[i].timer[j], (void *) NULL);
+	  proctimers[i].active[j] = TRUE;
+	  return;
+	}
+      }
+    }
+  }
+
+  fprintf (stderr, "can't find this machine, process combination!\n");
+  fprintf (stderr, "machine: %x, process: %x\n", (unsigned int) machine, (unsigned int) process);
+  return;
+}
+
+void StopProcessTimer (Machine *machine) {
+  
+  int i, j;
+  struct timeval stop;
+  double dtime;
+
+  /* identify the machine */
+  for (i = 0; i < Nmachine; i++) {
+    if (proctimers[i].machine == machine) {
+      for (j = 0; j < Nprocs; j++) {
+	if (proctimers[i].active[j]) {
+ 	  gettimeofday (&stop, (void *) NULL);
+	  dtime = DTIME (stop, proctimers[i].timer[j]);
+	  proctimers[i].timesum[j] += dtime;
+	  proctimers[i].active[j] = FALSE;
+	  proctimers[i].Njobs[j] ++;
+	  return;
+	}
+      }
+    }
+  }
+
+  fprintf (stderr, "can't find an active process for this machine!\n");
+  fprintf (stderr, "machine: %x\n", (unsigned int) machine);
+
+}
+
+int DumpProcessTimes (char *filename) {
+  
+  int i, j, fd, state, mode;
+  FILE *f;
+  double dt;
+
+  if (filename == (char *) NULL) {
+    system ("tput clear");
+    f = stderr;
+  } else {
+
+    /* check lockfile */
+    fd = setlockfile2 (filename, 0.1, LCK_XCLD, &state);
+    if (fd == -1) return (2);
+    f = fdopen (fd, "r+");
+    if (f == (FILE *) NULL) {
+      mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+      fchmod (fd, mode);
+      clearlockfile2 (filename, fd, LCK_XCLD, &state);
+      return (2);
+    }
+    fseek (f, 0, SEEK_END);
+  }  
+
+  fprintf (f, "               .");
+  for (j = 0; j < Nprocs; j++) {
+    fprintf (f, "   %-14s", proctimers[0].process[j][0].name);
+  }
+  fprintf (f, "\n");
+  for (i = 0; i < Nmachine; i++) {
+    fprintf (f, "%16s ", proctimers[i].machine[0].hostname);
+    for (j = 0; j < Nprocs; j++) {
+      if (proctimers[i].Njobs[j] > 0) {
+	dt = proctimers[i].timesum[j] / proctimers[i].Njobs[j];
+      } else {
+	dt = 0;
+      }
+      fprintf (f, "%7.3f %-6d   ", dt, proctimers[i].Njobs[j]);
+    }
+    fprintf (f, "\n");
+  }
+
+  if (f != stderr) {
+    mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    fchmod (fd, mode);
+    clearlockfile2 (filename, fd, LCK_XCLD, &state);
+    fclose (f);
+  }
+  return (1);
+}
+
Index: /tags/start/Ohana/src/elixir/src/MsgOps.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/MsgOps.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/MsgOps.c	(revision 12606)
@@ -0,0 +1,138 @@
+# include "controller.h"
+
+/*** this file should be updated to use fsetlockfile / fclearlockfile ***/
+
+int WaitMsg (char *fifo, char **message, double maxdelay) {
+
+  int status, Nsleep;
+  struct timeval now, then;
+  double dtime;
+  struct stat filestats;
+
+  /* maxdelay is the longest we will wait if the file is locked.  
+     if the file doesn't exist, or is empty, skip it */
+  /* limit our reads to only 10 tries, waiting for a little while in between */
+  Nsleep = 100000 * maxdelay;
+
+  status = stat (fifo, &filestats);
+  if (status == -1) return (0);
+  if (filestats.st_size == 0) return (0);
+
+  gettimeofday (&then, (void *) NULL);
+  while (TRUE) {
+    status = ReadMsg (fifo, message);
+    switch (status) {
+    case 1:
+      return (1);
+    default:
+      gettimeofday (&now, (void *) NULL);
+      dtime = DTIME (now, then);
+      if (dtime > maxdelay) return (0);
+    }
+    usleep (Nsleep);
+  }
+}
+
+int ReadMsg (char *fifo, char **message) {
+
+  int nbytes, Nbytes, NBYTES;
+  char *buffer;
+  int fd, state, mode;
+  FILE *f;
+
+  /* check lockfile */
+  fd = setlockfile2 (fifo, 0.1, LCK_XCLD, &state);
+  if (fd == -1) return (2);
+  f = fdopen (fd, "r+");
+  if (f == (FILE *) NULL) {
+    mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    fchmod (fd, mode);
+    clearlockfile2 (fifo, fd, LCK_XCLD, &state);
+    return (2);
+  }
+  
+  /* if file is empty, return 0 */
+  if (state == LCK_EMPTY) {
+    mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    fchmod (fd, mode);
+    clearlockfile2 (fifo, fd, LCK_XCLD, &state);
+    fclose (f);
+    return (0);
+  }  
+  
+  /* read data from file */
+  Nbytes = 0;
+  NBYTES = 0x1000;
+  ALLOCATE (buffer, char, NBYTES);
+  while (TRUE) {
+    nbytes = fread (&buffer[Nbytes], 1, 0x1000, f);
+    if (nbytes < 0) { 
+      fprintf (stderr, "error in ReadMsg -- got -1 bytes\n");
+      exit (0);
+    }
+    if (nbytes == 0) break;
+    Nbytes += nbytes;
+    NBYTES += 0x1000;
+    REALLOCATE (buffer, char, NBYTES);
+  }
+  buffer[Nbytes] = 0;
+  
+  /* file will remain until unlocked and fclosed below, 
+     but cannot be written to because it is locked */
+  if (ftruncate (fd, 0)) {
+    fprintf (stderr, "failed to clear fifo file %s (errno: %d)\n", fifo, errno);
+    Shutdown (1);
+  }
+  
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  fchmod (fd, mode);
+  clearlockfile2 (fifo, fd, LCK_XCLD, &state);
+  fclose (f);
+  
+  if (Nbytes == 0) {
+    free (buffer);
+    return (0);
+  }
+
+  *message = buffer;
+  return (1);
+
+}
+
+int WriteMsg (char *fifo, char *message) {
+
+  int fd, state, mode;
+  FILE *f;
+
+  /* check lockfile */
+  fd = setlockfile2 (fifo, 0.1, LCK_XCLD, &state);
+  if (fd == -1) return (2);
+  f = fdopen (fd, "r+");
+  if (f == (FILE *) NULL) {
+    mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    fchmod (fd, mode);
+    clearlockfile2 (fifo, fd, LCK_XCLD, &state);
+    return (2);
+  }
+
+  /* write message to end of file */
+  fseek (f, 0, SEEK_END);
+  fprintf (f, "%s\n", message);
+
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  fchmod (fd, mode);
+  clearlockfile2 (fifo, fd, LCK_XCLD, &state);
+  fclose (f);
+
+  return (1);
+
+}
+
+
+/*  possible return states:
+
+    0 - no message (fifo file empty or non-existent) 
+    1 - message received
+    2 - busy (fifo file locked)
+
+*/
Index: /tags/start/Ohana/src/elixir/src/Photcodes.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/Photcodes.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/Photcodes.c	(revision 12606)
@@ -0,0 +1,256 @@
+# include "controller.h"
+
+char *GetPhotcode (char *file) {
+
+  char *code;
+  Header header;
+  char detector[80], filter[80];
+  int i, imageid;
+
+  /* read in image header, open image data region */
+  if (!fits_read_header (file, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s (1)\n", file);
+    exit(0);
+  }
+
+  /** WARNING: this should use the abstracted keyword names **/
+  fits_scan (&header, "DETECTOR", "%s", 1, detector);
+  fits_scan (&header, "FILTER",   "%s", 1, filter);
+  fits_scan (&header, "IMAGEID",  "%d", 1, &imageid);
+
+  fits_free_header (&header);
+
+  for (i = 0; i < strlen(detector); i++) { detector[i] = toupper (detector[i]); }
+  for (i = 0; i < strlen(filter); i++) { filter[i] = toupper (filter[i]); }
+
+  ALLOCATE (code, char, 256);
+  sprintf (code, "%s.%s.%02d", detector, filter, imageid);
+  return (code);
+
+}
+
+/** WARNING: this is pretty weak **/
+char *GetPhotcodeMef (char *file) {
+
+  char *code;
+  Header header;
+  char detector[80], filter[80];
+  int i, imageid;
+  char *filename, *p;
+
+  /* file contains file and extend number */
+  ALLOCATE (filename, char, strlen(file) + 1);
+  
+  p = file;
+  while ((p = strchr (p, ',')) != (char *) NULL) { *p = ' '; }
+  sscanf (file, "%s %d", filename, &imageid);
+
+  /* read in image header, open image data region */
+  if (!fits_read_header (filename, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s (1)\n", file);
+    exit(0);
+  }
+  free (filename);
+
+  fits_scan (&header, "DETECTOR", "%s", 1, detector);
+  fits_scan (&header, "FILTER",   "%s", 1, filter);
+  fits_free_header (&header);
+
+  for (i = 0; i < strlen(detector); i++) { detector[i] = toupper (detector[i]); }
+  for (i = 0; i < strlen(filter); i++) { filter[i] = toupper (filter[i]); }
+
+  ALLOCATE (code, char, 256);  sprintf (code, "%s.%s.%02d", detector, filter, imageid);
+  return (code);
+
+}
+
+char *BuildCode (char *line) {
+
+  char *code, *p;
+  Header header;
+  char fullname[256], detector[80], filter[80];
+  char name[256], path[256], ccd[80], mode[80];
+  int i;
+
+  p = line;
+  while ((p = strchr (p, ',')) != (char *) NULL) { *p = ' '; }
+  sscanf (line, "%s %s %s %s", path, name, ccd, mode);
+
+  if (!strcasecmp (mode, "MEF")) {
+    sprintf (fullname, "%s/%s.fits", path, name);
+  } else {
+    sprintf (fullname, "%s/%s/%s%s.fits", path, name, name, ccd);
+  }
+
+  if (!fits_read_header (fullname, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s (1)\n", fullname);
+    exit(0);
+  }
+  fits_scan (&header, "DETECTOR", "%s", 1, detector);
+  fits_scan (&header, "FILTER",   "%s", 1, filter);
+  fits_free_header (&header);
+  
+  for (i = 0; i < strlen(detector); i++) { detector[i] = toupper (detector[i]); }
+  for (i = 0; i < strlen(filter); i++) { filter[i] = toupper (filter[i]); }
+
+  ALLOCATE (code, char, 256);
+  sprintf (code, "%s.%s.%s", detector, filter, ccd);
+  return (code);
+
+}
+
+char *BuildName (char *line) {
+
+  char *fullname;
+  char name[256], path[256], ccd[80], mode[80];
+  char *p;
+
+  ALLOCATE (fullname, char, 256);
+
+  p = line;
+  while ((p = strchr (p, ',')) != (char *) NULL) { *p = ' '; }
+  sscanf (line, "%s %s %s %s", path, name, ccd, mode);
+
+  if (!strcasecmp (mode, "MEF")) {
+    sprintf (fullname, "%s/%s.fits", path, name);
+  } else {
+    sprintf (fullname, "%s/%s/%s%s.fits", path, name, name, ccd);
+  }
+
+  return (fullname);
+
+}
+
+char *GetPhotcodeExt (char *file) {
+
+  char *code;
+  Header header;
+  char detector[80], filter[80];
+  int i, imageid, extend;
+  char *filename, *p;
+
+  /* file contains file and extend number */
+  ALLOCATE (filename, char, strlen(file) + 1);
+  
+  p = file;
+  while ((p = strchr (p, ',')) != (char *) NULL) { *p = ' '; }
+  sscanf (file, "%s %d", filename, &extend);
+
+  /* read in image header, open image data region */
+  if (!fits_read_Xheader (filename, &header, extend)) {
+    fprintf (stderr, "ERROR: can't find image file %s (1)\n", file);
+    exit(0);
+  }
+  free (filename);
+
+  fits_scan (&header, "DETECTOR", "%s", 1, detector);
+  fits_scan (&header, "FILTER",   "%s", 1, filter);
+  fits_scan (&header, "IMAGEID",  "%d", 1, &imageid);
+  fits_free_header (&header);
+
+  for (i = 0; i < strlen(detector); i++) { detector[i] = toupper (detector[i]); }
+  for (i = 0; i < strlen(filter); i++) { filter[i] = toupper (filter[i]); }
+
+  ALLOCATE (code, char, 256);
+  sprintf (code, "%s.%s.%02d", detector, filter, imageid);
+  return (code);
+
+}
+
+/* given path/filename.ext return filename */
+char *RootFilename (char *file) {
+
+  int Nbyte;
+  char *root, *p1, *p2;
+
+  p1 = strrchr (file, '/');
+  if (p1 == (char *) NULL) p1 = file;
+
+  p2 = strrchr (file, '.');
+  if (p2 == (char *) NULL) p2 = p1 + strlen(p1);
+  Nbyte = p2-p1;
+
+  ALLOCATE (root, char, Nbyte + 1);
+  strncpy (root, p1, Nbyte);
+  root[Nbyte] = 0;
+  
+  return (root);
+
+}  
+
+/* given: path/filename
+   return: path or ./ if none */
+char *PathFilename (char *file) {
+
+  int Nbyte;
+  char *path, *p1;
+
+  p1 = strrchr (file, '/');
+  if (p1 == (char *) NULL) {
+    ALLOCATE (p1, char, 2);
+    strcpy (p1, ".");
+    return (p1);
+  }
+
+  Nbyte = p1-file;
+  ALLOCATE (path, char, Nbyte + 1);
+  strncpy (path, file, Nbyte);
+  path[Nbyte] = 0;
+  
+  return (path);
+
+}  
+
+/* given: A/B/D/filename
+   return: D or ./ if none 
+   if /filename, return '/' 
+   if filename, return ./
+*/
+char *BaseFilename (char *file) {
+
+  int Nbyte;
+  char *path, *p1, *p2;
+
+  p1 = strrchr (file, '/');
+  if (p1 == (char *) NULL) {
+    ALLOCATE (p1, char, 2);
+    strcpy (p1, ".");
+    return (p1);
+  }
+  if (p1 == file) {
+    ALLOCATE (p1, char, 2);
+    strcpy (p1, "/");
+    return (p1);
+  }
+
+  p2 = p1 - 1;
+  while ((p2 > file) && (*p2 != '/')) p2--;
+  if (p2 != file) {
+    p2 ++;
+  }
+
+  Nbyte = (p1 - p2);
+  ALLOCATE (path, char, Nbyte + 1);
+  strncpy (path, p2, Nbyte);
+  path[Nbyte] = 0;
+  
+  return (path);
+
+}  
+
+
+/*
+
+There are two methods to implement the Photcode determination for MEF files. 
+The difference is in whether the IMAGEID is used to refer to the ccd, or the EXTNUM.
+Originally, EXTNUM was used, which meant we needed to determine the IMAGEID for a given EXTNUM.
+The old implementation of PhotCodeMef returned the photcode based on the input MEF filename
+and the EXTNUM.  This is now maintained as PhotCodeExt, but not used in elixir.
+
+As of 13/2/00, we've converted to only using the IMAGEID.  this means that PhotCodeMef returns 
+the photcode, based on the MEF filename and the IMAGEID.  To go along with this change, the 
+function flatten.mef operates on the given IMAGEID not EXTNUM as well.                             
+
+*/
+
+
Index: /tags/start/Ohana/src/elixir/src/ProcessOps.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/ProcessOps.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/ProcessOps.c	(revision 12606)
@@ -0,0 +1,240 @@
+# include "controller.h"
+
+/* take entry and return char with filled out value,
+   perform recursively */
+
+char *ExpandEntry (char *entry, int argc, char **argv) {
+
+  char *p1, *p2, *p3;
+  int Nbyte, N;
+  char *function, *operand, *value;
+  int Nout, Ncpy;
+
+  if (entry[0] == '!') {
+    p1 = strchr (entry, '!'); p1++;
+    p2 = strchr (entry, '(');
+    p3 = strchr (entry, ')');
+    if ((p2 == (char *) NULL) || (p3 == (char *) NULL)) {
+      fprintf (stderr, "syntax error in process defs\n");
+      Shutdown (1);
+    }
+    Nbyte = p2 - p1;
+    function = strncreate (p1, Nbyte);
+
+    p2 ++;
+    Nbyte = p3 - p2;
+    operand = strncreate (p2, Nbyte);
+    value = ExpandEntry (operand, argc, argv); 
+    free (operand);
+    operand = value; 
+    
+    value = (char *) NULL;
+    if (!strcasecmp (function, "buildname")) {
+      value = BuildName (operand);
+    }
+    if (!strcasecmp (function, "buildcode")) {
+      value = BuildCode (operand);
+    }
+    if (!strcasecmp (function, "photcode")) {
+      value = GetPhotcode (operand);
+    }
+    if (!strcasecmp (function, "photcodemef")) {
+      value = GetPhotcodeMef (operand);
+    }
+    if (!strcasecmp (function, "root")) {
+      value = RootFilename (operand);
+    }
+    if (!strcasecmp (function, "path")) {
+      value = PathFilename (operand);
+    }
+    if (!strcasecmp (function, "base")) {
+      value = BaseFilename (operand);
+    }
+    if (value == (char *) NULL) {
+      fprintf (stderr, "unknown process command %s\n", function);
+      Shutdown (1);
+    }
+    free (function); 
+    free (operand); 
+  } else {
+    Nbyte = strlen (entry) + 50;
+    ALLOCATE (value, char, Nbyte);
+
+    Nout = 0;
+    p1 = entry;
+    while ((p2 = strchr (p1, '&')) != (char *) NULL) {
+      Ncpy = p2 - p1;
+      if (Nout + Ncpy >= Nbyte - 1) {
+	Nbyte = Nout + Ncpy + 50;
+	REALLOCATE (value, char, Nbyte);
+      }    
+      strncpy (&value[Nout], p1, Ncpy);
+      Nout += Ncpy;
+      p2 ++;
+      N = strtod (p2, &p1);
+      if ((N > argc - 1) || (N < 0)) {
+	fprintf (stderr, "ERROR: command expects too many object arguments\n");
+	Shutdown (1);
+      }
+      Ncpy = strlen (argv[N]);
+      if (Nout + Ncpy >= Nbyte - 1) {
+	Nbyte = Nout + Ncpy + 50;
+	REALLOCATE (value, char, Nbyte);
+      }    
+      strcpy (&value[Nout], argv[N]);
+      Nout += Ncpy;
+    }
+    Ncpy = strlen (p1);
+    if (Nout + Ncpy >= Nbyte - 1) {
+      Nbyte = Nout + Ncpy + 50;
+      REALLOCATE (value, char, Nbyte);
+    }    
+    strncpy (&value[Nout], p1, Ncpy);
+    Nout += Ncpy;
+    value[Nout] = 0;
+  }
+
+  return (value);
+
+}
+
+Process *ConfigProcess (char *config, char *procname) {
+  
+  int j, NPAR;
+  char argname[256], argline[256];
+  Process *process;
+
+  NPAR = 10;
+  ALLOCATE (process, Process, 1);
+  ALLOCATE (process[0].argv, char *, NPAR);
+
+  process[0].name = strcreate (procname);
+
+  /* find all lines of form procname.arg - the argument lines */
+  sprintf (argname, "%s.arg", procname);
+  for (j = 0; ScanConfig (config, argname, "%s", j+1, argline); j++) {
+    process[0].argv[j] = strcreate (argline);
+    if (j == NPAR) {
+      NPAR += 10;
+      REALLOCATE (process[0].argv, char *, NPAR);
+    }
+  }
+  process[0].argc = j;
+  REALLOCATE (process[0].argv, char *, MAX (j,1));
+  if (j == 0) {
+    fprintf (stderr, "ERROR: process %s has no arguments defined\n", procname);
+    Shutdown (1);
+  }
+    
+  process[0].pending = InitQueue ();
+  process[0].failure = (Queue *) NULL;
+  process[0].success = (Queue *) NULL;
+  process[0].cluster = InitCluster ();
+
+  return (process);
+  
+}
+
+/* need a return value */
+int MakeArgs (Process *process, Object *object, int *cargc, char ***cargv, int **cargd) {
+
+  int i;
+  int Cargc, *Cargd;
+  char **Cargv;
+
+  Cargc = process[0].argc;
+  ALLOCATE (Cargv, char *, Cargc);
+  ALLOCATE (Cargd, int, Cargc);
+  
+  /* convert par to entry */
+  for (i = 0; i < Cargc; i++) {
+    ParseLine (process[0].argv[i], object[0].argc, object[0].argv, &Cargd[i], &Cargv[i]);
+  }
+  *cargc = Cargc;
+  *cargv = Cargv;
+  *cargd = Cargd;
+
+  return (TRUE);
+
+}
+
+/* 'process' carries around a list of strings which MakeArgs uses to create the command line
+   arguments and the dependencies (cargc, cargv, cargd) */
+
+void FreeArgs (int argc, char **argv, int *argd) {
+
+  int i;
+
+  for (i = 0; i < argc; i++) {
+    free (argv[i]);
+  }
+
+  free (argv);
+  free (argd);
+
+}
+
+
+void ParseLine (char *testline, int argc, char **argv, int *depend, char **outline) {
+
+  int i, k;
+  char format[256], *line, *value;
+  int NTERMS, Nterms;
+  char **terms;
+  
+
+  NTERMS = 8;
+  ALLOCATE (terms, char *, NTERMS);
+  for (i = 0; i < NTERMS; i++) {
+    ALLOCATE (terms[i], char, 256);
+  }
+
+  Nterms = sscanf (testline, "%d%s%s%s%s%s%s%s%s%s", depend, format, 
+		   terms[0], terms[1], terms[2], terms[3], terms[4], terms[5], terms[6], terms[7]);
+  Nterms -= 2;
+      
+  for (k = 0; k < Nterms; k++) {
+    value = ExpandEntry (terms[k], argc, argv);
+    strcpy (terms[k], value);
+    free (value);
+  }
+      
+  ALLOCATE (line, char, 256);
+  switch (Nterms) {
+  case 0:
+    sprintf (line, format); 
+    break;
+  case 1:
+    sprintf (line, format, terms[0]); 
+    break;
+  case 2:
+    sprintf (line, format, terms[0], terms[1]); 
+    break;
+  case 3:
+    sprintf (line, format, terms[0], terms[1], terms[2]); 
+    break;
+  case 4:
+    sprintf (line, format, terms[0], terms[1], terms[2], terms[3]); 
+    break;
+  case 5:
+    sprintf (line, format, terms[0], terms[1], terms[2], terms[3], terms[4]); 
+    break;
+  case 6:
+    sprintf (line, format, terms[0], terms[1], terms[2], terms[3], terms[4], terms[5]); 
+    break;
+  case 7:
+    sprintf (line, format, terms[0], terms[1], terms[2], terms[3], terms[4], terms[5], terms[6]); 
+    break;
+  case 8:
+    sprintf (line, format, terms[0], terms[1], terms[2], terms[3], terms[4], terms[5], terms[6], terms[7]); 
+    break;
+  default: 
+    fprintf (stderr, "too many terms for command line argument (lim = 5)\n");
+    Shutdown (1);
+  }
+  *outline = line;
+
+  for (i = 0; i < NTERMS; i++) { free (terms[i]); }
+  free (terms);
+
+}
Index: /tags/start/Ohana/src/elixir/src/QueueOps.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/QueueOps.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/QueueOps.c	(revision 12606)
@@ -0,0 +1,60 @@
+# include "controller.h"
+
+/* get object from top of stack */
+Object *GetObject (Queue *queue) {
+
+  int i;
+  Object *object;
+  
+  if (queue[0].Nobject == 0) return ((Object *) NULL);
+
+  object = queue[0].object[0];
+  queue[0].Nobject --;
+  for (i = 0; i < queue[0].Nobject; i++) {
+    queue[0].object[i] = queue[0].object[i+1];
+  }
+  return (object);
+}
+
+/* put object on bottom of stack */
+void PutObject (Queue *queue, Object *object) {
+
+  if (queue[0].Nobject == queue[0].NOBJECT) {
+    queue[0].NOBJECT += 100;
+    REALLOCATE (queue[0].object, Object *, queue[0].NOBJECT);
+  }
+  queue[0].object[queue[0].Nobject] = object;
+  queue[0].Nobject ++;
+
+}
+
+/* push object on top of stack */
+void PushObject (Queue *queue, Object *object) {
+
+  int i;
+
+  if (queue[0].Nobject == queue[0].NOBJECT) {
+    queue[0].NOBJECT += 100;
+    REALLOCATE (queue[0].object, Object *, queue[0].NOBJECT);
+  }
+  for (i = queue[0].Nobject; i > 0; i--) {
+    queue[0].object[i] = queue[0].object[i-1];
+  }
+  queue[0].object[0] = object;
+  queue[0].Nobject ++;
+
+}
+
+/* allocate queue, setup with default values, allocate data */
+Queue *InitQueue () {
+
+  Queue *queue;
+
+  ALLOCATE (queue, Queue, 1);
+
+  queue[0].Nobject = 0;
+  queue[0].NOBJECT = 50;
+  ALLOCATE (queue[0].object, Object *, queue[0].NOBJECT);
+  return (queue);
+
+}
Index: /tags/start/Ohana/src/elixir/src/RemoteOps.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/RemoteOps.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/RemoteOps.c	(revision 12606)
@@ -0,0 +1,189 @@
+# include "controller.h"
+
+void HaltElixir (char *pidfile) {
+  
+  pid_t pid;
+  char username[256], machine[256];
+  char line[512];
+  int i, wsock, rsock;
+  struct stat filestat;
+
+  if (!LoadPID (pidfile, &pid, username, machine)) {
+    fprintf (stderr, "elixir is not running\n");
+    exit (0);
+  }
+
+  /* set signal to remote machine */
+  if (!rconnect (machine, CONNECT, &rsock, &wsock)) {
+    fprintf (stderr, "can't make connection to machine %s to kill process\n", machine);
+    exit (1);
+  }
+  sprintf (line, "kill -USR1 %d\n", pid);
+  write (wsock, line, strlen (line));
+
+  for (i = 0; i < 100; i++) {
+    if (stat (pidfile, &filestat) == -1) exit (0);
+    usleep (100000);
+  }
+  fprintf (stderr, "elixir is still running\n");
+  exit (2);
+}
+
+void KillElixir (char *pidfile) {
+  
+  pid_t pid;
+  char username[256], machine[256];
+  char line[512];
+  int i, wsock, rsock;
+  struct stat filestat;
+
+  if (!LoadPID (pidfile, &pid, username, machine)) {
+    fprintf (stderr, "elixir is not running\n");
+    exit (0);
+  }
+
+  /* send signal to remote machine */
+  if (!rconnect (machine, CONNECT, &rsock, &wsock)) {
+    fprintf (stderr, "can't make connection to machine %s to kill process\n", machine);
+    exit (1);
+  }
+  sprintf (line, "kill -TERM %d\n", pid);
+  write (wsock, line, strlen (line));
+
+  for (i = 0; i < 100; i++) {
+    if (stat (pidfile, &filestat) == -1) exit (0);
+    usleep (100000);
+  }
+  fprintf (stderr, "elixir is still running\n");
+  exit (2);
+}
+
+void StatusElixir (char *pidfile, char *msgfile) {
+  
+  pid_t pid;
+  char username[256], machine[256], response[256], message[512];
+  char *answer;
+  char line[512];
+  int i, done, status, wsock, rsock;
+  struct stat filestat;
+  struct timeval now, then;
+
+  if (!LoadPID (pidfile, &pid, username, machine)) {
+    fprintf (stderr, "elixir is not running\n");
+    exit (0);
+  }
+
+  sprintf (response, "%s.XXXXXX", msgfile);
+  mkstemp (response);
+  sprintf (message, "STATUS %s", response);
+  if (VERBOSE) fprintf (stderr, "sending message: %s\n", message);
+  WriteMsg (msgfile, message);
+
+  /* send signal to remote machine */
+  if (!rconnect (machine, CONNECT, &rsock, &wsock)) {
+    fprintf (stderr, "can't make connection to machine %s to signal process\n", machine);
+    exit (1);
+  }
+  sprintf (line, "kill -USR2 %d\n", pid);
+  write (wsock, line, strlen (line));
+
+  /* wait (2 sec) for file to exist, then try to read it */
+  for (i = 0; ((status = stat (response, &filestat)) == -1) && (i < 20); i++) {
+    if (VERBOSE) fprintf (stderr, "waiting for response: %d\n", status);
+    usleep (100000);
+  }
+  if (i >= 20) {
+    fprintf (stderr, "no response\n");
+    exit (2);
+  }
+
+  done = FALSE;
+  gettimeofday (&then, (void *) NULL);
+  if (VERBOSE) fprintf (stderr, "reading message: %s\n", message);
+  while (!done) {
+    status = ReadMsg (response, &answer);
+    switch (status) {
+    case 1:
+      done = TRUE;
+      break;
+    default:
+      gettimeofday (&now, (void *) NULL);
+      if (DTIME (now, then) > 5.0) {
+	fprintf (stderr, "no response from elixir\n");
+	exit (2);
+      }
+    }
+    usleep (10000);
+  }
+  fprintf (stderr, "%s\n", answer);
+  gettimeofday (&now, (void *) NULL);
+  if (VERBOSE) fprintf (stderr, "response in %f\n", DTIME (now, then));
+
+  unlink (response);
+  exit (0);
+}
+
+int HalttoRestart (char *pidfile) {
+  
+  pid_t pid;
+  char username[256], machine[256];
+  char line[512];
+  int i, wsock, rsock;
+  struct stat filestat;
+
+  if (!LoadPID (pidfile, &pid, username, machine)) {
+    fprintf (stderr, "previous elixir not running\n");
+    return (TRUE);
+  }
+  /* check username matches: can only send signals to own process */
+
+  /* make connection to remote machine */
+  if (!rconnect (machine, CONNECT, &rsock, &wsock)) {
+    fprintf (stderr, "can't make connection to machine %s to kill process\n", machine);
+    exit (1);
+  }
+	     
+  /* send TERM signal */
+  sprintf (line, "kill -TERM %d\n", pid);
+  write (wsock, line, strlen (line));
+
+  /* wait for cleanup to finish */
+  for (i = 0; i < 100; i++) {
+    if (stat (pidfile, &filestat) == -1) {
+      fprintf (stderr, "previous elixir halted\n");
+      goto success;
+    }
+    usleep (100000);
+  }
+
+  /* kill meanly */
+  sprintf (line, "kill -KILL %d", pid);
+  write (wsock, line, strlen (line));
+  unlink (pidfile);
+
+  /* test if process is still alive? */
+ success:
+  sprintf (line, "exit\n");
+  write (wsock, line, strlen(line));
+  close (wsock);
+  close (rsock);
+  return (TRUE);
+  
+}
+
+int LoadPID (char *file, pid_t *pid, char *username, char *machine) {
+
+  FILE *f;
+
+  f = fopen (file, "r");
+  if (f == (FILE *) NULL) { 
+    return (FALSE);
+  }
+
+  fscanf (f, "%*s %d", pid);
+  fscanf (f, "%*s %s", username);
+  fscanf (f, "%*s %s", machine);
+  fclose (f);
+
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/elixir/src/SockScan.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/SockScan.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/SockScan.c	(revision 12606)
@@ -0,0 +1,53 @@
+# include "controller.h"
+# include <errno.h>
+# define MAXTIME 10
+
+int SockScan (char *string, Fifo *fifo, int sock) {
+  
+  int i, done, status;
+
+  done = 0;
+  for (i = 0; (i < MAXTIME) && !done; i++) {
+    ShiftFifo (fifo);
+    status = ReadtoFifo (fifo, sock);
+    switch (status) {
+    case 0:
+      break;
+    case -1:
+      usleep (1000);
+      break;
+    default:
+      done = memstr (fifo[0].buffer, string, fifo[0].Nbuffer);
+      break;
+    }
+  }
+  return (status);
+}
+
+/* returns (offset to m2) + 1, or 0 if failure */ 
+int memstr (char *m1, char *m2, int n) {
+
+  int i, N;
+
+  N = strlen (m2);
+  for (i = 0; (i < n - N + 1) && memcmp (m1, m2, N); i++, m1++);
+  if (memcmp (m1, m2, N)) {
+    return (0);
+  }
+  else {
+    return (i+1);
+  }
+
+}
+ 
+/* SockScan reads from the given socket looking for the given string
+   SockScan stores data read from socket in the fifo buffer to ensure 
+   it catches the given string.  a single invocation of SockScan will 
+   wait for up to 10 msec for data to come down the pipe before giving up.
+   SockScan can only search for one string in the output stream.
+   */
+
+
+/* need a way of signalling that the socket has closed...
+   maybe change the sock entry to 0?
+*/
Index: /tags/start/Ohana/src/elixir/src/StartMachine.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/StartMachine.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/StartMachine.c	(revision 12606)
@@ -0,0 +1,35 @@
+# include "controller.h"
+
+int StartMachine (Machine *machine, Object *object, int argc, char **argv) {
+
+  int i, Nbyte, Nout;
+  char command[1024];
+  FILE *logfile;
+
+  logfile = LogOpen (object[0].logfile);
+  machine[0].object = object;
+
+  Nbyte = Nout = 0;
+  for (i = 0; i < argc; i++) {
+    Nout = sprintf (&command[Nbyte], "%s ", argv[i]);
+    Nbyte += Nout;
+  }
+    
+  fprintf (logfile, "%s @ %s: %s\n", object[0].argv[0], machine[0].hostname, command);
+  if (logfile != stderr) {
+    fflush (logfile);
+    fclose (logfile);
+  }
+
+  Nout = sprintf (&command[Nbyte], "\n echo PROCESS DONE\n");
+  write (machine[0].wsock, command, strlen(command));
+
+  gettimeofday (&machine[0].object[0].start, (void *) NULL);
+  gettimeofday (&machine[0].quiet, (void *) NULL);
+
+  machine[0].status = BUSY;
+  return (TRUE);
+}
+
+/* machine[0].quiet times since last message received from process. 
+   if process is too quiet for too long, we assume it died */
Index: /tags/start/Ohana/src/elixir/src/elixir.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/elixir.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/elixir.c	(revision 12606)
@@ -0,0 +1,126 @@
+# include "controller.h"
+
+static int Dynamic;
+static int Reload;
+
+static int      Nobjects;
+static int      Nprocess;
+static Process **process;
+static Process   global;
+
+int main (int argc, char **argv) {
+  
+  int i, Nnew, state;
+  char *config;
+  int nloop;
+  char **targv;
+
+  /* save complete arglist incase we reload */
+  ALLOCATE (targv, char *, argc + 1);
+  for (i = 0; i < argc; i++) {
+    targv[i] = strcreate (argv[i]);
+  }
+  targv[i] = (char *) NULL;
+
+  config = ConfigInit (&argc, argv);
+
+  process = DefineProcesses (&global, &Nprocess, config);
+
+  /* PID filename stored in global.argv[7] */
+  ConfigPID (global.argv[7]);
+
+  InitMsgFile (global.argv[0]); /* success */
+  InitMsgFile (global.argv[1]); /* failure */
+  InitMsgFile (global.argv[5]); /* message */
+  InitMsgFile (global.argv[6]); /* end stat */
+  InitMachines (config);
+  free (config);
+
+  SetMessageFile (global.argv[5]);
+
+  InitProcessTimers (process, Nprocess);
+
+  Nobjects = 0;
+  Reload = FALSE;
+  Dynamic = TRUE;
+  nloop = 0;
+
+  /* any remaining entry is a file to load in static mode */
+  if (argc == 2) {
+    Dynamic = FALSE;
+    Nobjects = LoadPending (&global, argv[1], &state, &Dynamic);
+    if (state) {
+      fprintf (stderr, "error with input file %s (state %d)\n", argv[1], state);
+      Shutdown (1);
+    }
+  }
+
+  while (CheckEndingState (&global, Nobjects, Dynamic)) {
+
+    if (Dynamic) { 
+      Nnew = LoadPending (&global, global.argv[4], &state, &Dynamic);
+      Nobjects += Nnew;
+    }
+
+    for (i = 0; i < Nprocess; i++) {
+      CheckProcess (process[i]);
+    }
+
+    for (i = Nprocess - 1; i >= 0; i--) {
+      CheckProcess (process[i]);
+    }
+
+    CheckMessages ();
+    /* CheckMessages (&global, process, Nprocess, &Dynamic, Nobjects); */
+    RestartMachines ();
+
+    usleep (1000000);
+    if (nloop > 3000) {
+      fprintf (stderr, ".");
+      nloop = 0;
+    }
+    nloop ++;
+  }
+
+  DumpProcessTimes (global.argv[6]);
+ 
+  /* DumpStatus (global.argv[6], &global, process, Nprocess, Dynamic, Nobjects);  */
+  DumpStatus (global.argv[6]);
+
+  WriteMsg (global.argv[6], "DONE");
+
+  if (Reload) Restart (targv);
+
+  Shutdown (0);
+  exit (0);
+}
+
+void SIG_RELOAD (int sig) {
+  fprintf (stderr, "got signal RELOAD\n");
+  SetExitTimer ();
+  Dynamic = FALSE;
+  Reload = TRUE;
+}
+
+void ElixirStop () {
+  Dynamic = FALSE;
+}
+
+int GetDynamicState () {
+  return (Dynamic);
+}
+
+Process **GetProcessInfo (Process **gb, int *np, int *no) {
+  *np = Nprocess;
+  *no = Nobjects;
+  *gb = &global;
+  return (process);
+}
+
+/* create 'reload' mode:
+   0 - Reload = TRUE;
+   1 - Dynamic = FALSE;
+   2 - start timer (in CheckEndingState.c)
+   3 - if timer expires, set exit state
+   4 - if (Reload) exec (argc, arg)
+*/
Index: /tags/start/Ohana/src/elixir/src/rconnect.c
===================================================================
--- /tags/start/Ohana/src/elixir/src/rconnect.c	(revision 12606)
+++ /tags/start/Ohana/src/elixir/src/rconnect.c	(revision 12606)
@@ -0,0 +1,103 @@
+# include "controller.h"
+/*
+# include <stdio.h> 
+# include <math.h>
+# include <string.h>
+# include <signal.h>
+*/ 
+/* rconnect opens a remote shell on hostname and returns two file descriptors:
+   one for read, one for write */
+
+int rconnect (char *hostname, char *command, int *rsock, int *wsock) {
+
+  int i, rfd[2], wfd[2], status;
+  pid_t pid;
+  char buffer[0x4000];
+  char *file;
+  Fifo fifo;
+
+  InitFifo (&fifo, 0x4000, 0x1000);
+
+  status = pipe (rfd);
+  if (status < 0) {
+    perror ("pipe");
+    return (FALSE);
+  }
+  status = pipe (wfd);
+  if (status < 0) {
+    perror ("pipe");
+    return (FALSE);
+  }
+
+  file = filebasename (command);
+  pid = fork ();
+  if (!pid) { /* must be child process */
+    fprintf (stderr, "starting remote connection to %s...", hostname);
+    /* close the excess sockets */
+    close (wfd[1]);
+    close (rfd[0]);
+    dup2 (wfd[0], STDIN_FILENO);
+    dup2 (rfd[1], STDOUT_FILENO);
+    dup2 (rfd[1], STDERR_FILENO);
+    setvbuf (stdin,  (char *) NULL, _IONBF, BUFSIZ);
+    setvbuf (stdout, (char *) NULL, _IONBF, BUFSIZ);
+    setvbuf (stderr, (char *) NULL, _IONBF, BUFSIZ);
+
+    status = execl (command, file, hostname, "/bin/csh", 0); 
+    fprintf (stderr, "error starting remote shell process\n");
+    Shutdown (1);
+  }
+  *wsock = wfd[1];
+  *rsock = rfd[0];
+   close (wfd[0]);
+   close (rfd[1]);
+
+  fcntl (*rsock, F_SETFL, O_NONBLOCK);
+  fcntl (*wsock, F_SETFL, O_NONBLOCK);
+
+  sprintf (buffer, "echo PTOLEMY STARTED\n");
+  status = write (*wsock, buffer, strlen(buffer));
+  if ((status == -1) && (errno == EPIPE)) {
+    fprintf (stderr, "socket closed unexpectedly\n");
+    close (*wsock);
+    close (*rsock);
+    return (FALSE);
+  }
+
+  /* try to get evidence connection is alive - wait upto a few seconds */
+  status = -1;
+  for (i = 0; (i < 100) && (status == -1); i++) {
+    fcntl (*rsock, F_SETFL, O_NONBLOCK);
+    status = SockScan ("PTOLEMY STARTED", &fifo, *rsock);
+    if (status == 0) {
+      fprintf (stderr, "socket closed unexpectedly\n");
+      close (*wsock);
+      close (*rsock);
+      return (FALSE);
+    }
+  }
+  if (i == 100) {
+    fprintf (stderr, "timeout while connecting\n");
+    close (*wsock);
+    close (*rsock);
+    return (FALSE);
+  }
+  fprintf (stderr, "Connected\n");
+
+  /* the onintr command works with csh/tcsh type shells to
+     prevent trapping of SIGTERM, used to kill hung jobs.
+     for bash/sh type shells, you can use SIGQUIT instead
+     without setting onintr */
+  sprintf (buffer, "onintr\n");
+  write (*wsock, buffer, strlen(buffer));
+  if ((status == -1) && (errno == EPIPE)) {
+    fprintf (stderr, "socket closed unexpectedly\n");
+    close (*wsock);
+    close (*rsock);
+    return (FALSE);
+  }
+
+  FreeFifo (&fifo);
+  return (pid);
+
+}
Index: /tags/start/Ohana/src/elixir/test/README
===================================================================
--- /tags/start/Ohana/src/elixir/test/README	(revision 12606)
+++ /tags/start/Ohana/src/elixir/test/README	(revision 12606)
@@ -0,0 +1,149 @@
+
+This directory includes a very simple elixir script, test.pro, to test
+that elixir is working correctly.  
+
+To run it, create an input list with one element per line.  The
+elements can be any word; an example is provided in test.list.
+
+Make sure the machines listed above represent valid machine names in
+your cluster.  Also, be certain that you can rsh to these machines
+without a password.
+
+Run the test by exectuting:
+
+elixir -c test.pro test.list
+
+the result of this test will be several files in your home directory:
+
+elixir-test.log
+elixir-test.end
+elixir-test.success
+
+elixir-test.log:
+
+The first file, elixir-test.log, shows the output from all of the
+processing steps.  In this test example, the log file is defined to be
+a single file, but it is also possible to use the &0 style
+command-line arguments to create a different file for each input line.
+All output from each of the processes goes into this file in the order
+received by the elixir program.  The resulting lines may look a bit
+confusing sometime as a result.  In addition, elixir adds some extra
+information to aid in debugging.  Here are a few example lines:
+
+foo @ kiawe: ls foo ; echo SUCCESS 
+bar @ milo: ls bar ; echo SUCCESS 
+foo @ kiawe:ls: foo: No such file or directory
+SUCCESS
+PROCESS DONE
+foo @ kiawe is done
+bar @ milo:ls: bar: No such file or directory
+SUCCESS
+PROCESS DONE
+bar @ milo is done
+
+Every output line from the processes are prepended with:
+
+(&0) @ (machine): 
+
+In this example, I used the two machines, kiawe & milo.  The first two
+lines show the first two commands being executed: 
+
+ls foo ; echo SUCCESS
+
+The next three lines show the output from the process executing on foo:
+
+ls: foo: No such file or directory 
+SUCCESS
+PROCESS DONE
+
+The 'ls' command did not find a file 'foo' in the home directory -
+note that all commands, since they are run remotely, execute in the
+user's home directory.  The word "SUCCESS" comes from the 'echo
+SUCCESS' portion of the command.  Currently, elixir uses the words
+SUCCESS, ERROR, and PROCESS DONE for process monitoring.  Ideally, the
+program called by elixir should check its output state and echo either
+SUCCESS or ERROR as appropriate.  In this test example, we simply
+force all processes to claim they succeeded with the 'echo SUCCESS'
+command.  The PROCESS DONE is added by elixir when it creates the
+command.  This lets elixir detect programs which crash and thereby
+fail to send either SUCCESS or ERROR.
+
+Side Note: this SUCCESS / ERROR flow control construct will soon be
+replaced by tests of the actual process exit status.  This will make
+elixir able to more cleanly support unix commnands.  
+
+The 6th line in the example above is the output from elixir noting
+that the process for 'foo' ended.  The next few lines show the output
+for the process on 'bar'.
+
+elixir-test.end:
+
+This file is created at the end of the elixir run and provides
+information about the run.  This same status information can be
+retrieved from elixir while it is running by using the 'status'
+program.  Here is the output from the above example:
+
+##################################################################
+               .   test1            test2            test3         
+           kiawe   0.120 3          5.056 2          0.130 1        
+            milo   0.110 1          5.062 2          0.109 3        
+processes status:
+            name   pending  success  failure  total
+----------------------------------------------------------------
+          global         0        4        0      4
+           test1         0
+           test2         0
+           test3         0
+
+machine status:
+          name  process  status
+----------------------------------------------------------------
+         kiawe   (none)       0
+          milo   (none)       0
+
+objects loaded so far: 4
+
+NOT accepting input from FIFO
+DONE
+##################################################################
+
+The first section shows a grid with processes across the top and
+machines in the left column.  The entries for each pair of machine &
+process are the average execution time and the number of instances of
+the given process which was run on the given machine.  So, in this
+example, the process 'test1' (which is the 'ls') was run on 'kiawe' 3
+times for an average of 0.120 sec and on 'milo' for an average of
+0.110 sec.  
+
+The second section shows the state of the different queues when the
+elixir process ended.  The left hand column shows the possible queues
+(global, test1, test2, test3).  For all nodes except the global node,
+the success and failure queues are always linked to a queue of another
+node.  Jobs which land in the success or failure queue of a node are
+instantly moved to the pending queue of another job.  Therefore, we
+only show the pending queue for the nodes except for 'global'.  Each
+number represents the number of jobs waiting in the given queue.
+(note: the global.pending queue is identical to one of the other
+pending queues and therefore represents a duplication).  The 'total'
+entry is the sum of jobs in each of the global queues.  Note that this
+table does not show the processes which are actually being executed,
+as these are considered to be 'in' a node, not on the queue of a node.
+They are represented in the next section.  
+
+The third section lists the status of all machines available.  The
+first column is the machine name; the second is the name of the
+process being executed, or '(none)' if the machine is idle; the third
+is a numerical status indication (which is generally ignored).  
+
+The next line shows the number of objects loaded by elixir.  Since
+elixir has the capability of loading new objects dynamically, this
+value on this line may increment as time goes by.  The next line shows
+whether elixir is accepting input during runtime or not.
+
+elixir-test.success:
+
+This file lists the processes which elixir successfully finished.  (An
+equivalent file, elixir-test.failure, would include jobs which did not
+succeed).  Entries are added to this file as the jobs complete.  In
+this way, it can be used to monitor the process of an elixir run.  
+
Index: /tags/start/Ohana/src/elixir/test/save.source
===================================================================
--- /tags/start/Ohana/src/elixir/test/save.source	(revision 12606)
+++ /tags/start/Ohana/src/elixir/test/save.source	(revision 12606)
@@ -0,0 +1,4 @@
+msg1
+msg2
+msg3
+msg4
Index: /tags/start/Ohana/src/elixir/test/test.end
===================================================================
--- /tags/start/Ohana/src/elixir/test/test.end	(revision 12606)
+++ /tags/start/Ohana/src/elixir/test/test.end	(revision 12606)
@@ -0,0 +1,21 @@
+               .   test1            test2            test3         
+       localhost   1.565 2          5.180 2          1.030 2        
+       localhost   1.575 2          5.180 2          1.030 2        
+processes status:
+            name   pending  success  failure  total
+----------------------------------------------------------------
+          global         0        4        0      4
+           test1         0
+           test2         0
+           test3         0
+
+machine status:
+          name  process  status
+----------------------------------------------------------------
+     localhost   (none)       0
+     localhost   (none)       0
+
+objects loaded so far: 4
+
+NOT accepting input from FIFO
+DONE
Index: /tags/start/Ohana/src/elixir/test/test.pro
===================================================================
--- /tags/start/Ohana/src/elixir/test/test.pro	(revision 12606)
+++ /tags/start/Ohana/src/elixir/test/test.pro	(revision 12606)
@@ -0,0 +1,54 @@
+# Elixir test config file
+
+CONNECT         /usr/bin/ssh
+MACHINE		localhost
+MACHINE		localhost
+elixir		test
+
+# FIFO files
+global.success	$elixir.success
+global.failure	$elixir.failure
+global.source	$elixir.source
+global.msg	$elixir.msg
+global.end	$elixir.end
+global.pid	$elixir.pid
+
+# process definition
+global.Nargs	1
+global.logfile  0 %s $elixir.log
+global.pending	test1
+global.timeout	100
+
+# test1: ls (will ls &0 user home dir)
+process	test1 
+test1.arg 0 ls
+test1.arg 0 %s  &0
+test1.arg 0 ;
+test1.arg 0 echo
+test1.arg 0 SUCCESS
+test1.success test2
+test1.failure global
+
+# test2 sleep 5
+process	test2 
+test2.arg 0 sleep
+test2.arg 0 5
+test2.arg 0 ;
+test2.arg 0 echo
+test2.arg 0 SUCCESS
+test2.success test3
+test2.failure global
+
+# test3 echo &0
+process	test3 
+test3.arg 0 echo 
+test3.arg 0 %s  &0
+test3.arg 0 ;
+test3.arg 0 echo
+test3.arg 0 SUCCESS
+test3.success global
+test3.failure global
+
+# this is a very simple elixir script to test that elixir is working
+# correctly.  See the README file for instructions.
+ 
Index: /tags/start/Ohana/src/elixir/test/test.success
===================================================================
--- /tags/start/Ohana/src/elixir/test/test.success	(revision 12606)
+++ /tags/start/Ohana/src/elixir/test/test.success	(revision 12606)
@@ -0,0 +1,4 @@
+msg1 0000005d test3
+msg2 0000005d test3
+msg3 0000005d test3
+msg4 0000005d test3
Index: /tags/start/Ohana/src/fixcat/Makefile
===================================================================
--- /tags/start/Ohana/src/fixcat/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/Makefile	(revision 12606)
@@ -0,0 +1,61 @@
+include ../../Configure
+CC      =       gcc -g  # override this for now for minimal test
+HOME 	=	$(ROOT)/src/fixcat
+CONFIG  =	$(ROOT)/config
+PROGRAM =       fixcat
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#  
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lFITS -lohana -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS)
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+FIXCAT = \
+$(SRC)/fixcat.$(ARCH).o 	$(SRC)/gcatalog.$(ARCH).o   \
+$(SRC)/coordops.$(ARCH).o	$(SRC)/sorts.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o 	$(SRC)/config.$(ARCH).o     \
+$(SRC)/Fread.$(ARCH).o		$(SRC)/check_lockfile.$(ARCH).o \
+$(SRC)/find_images.$(ARCH).o	$(SRC)/match_images.$(ARCH).o	\
+$(SRC)/gregions.$(ARCH).o	$(SRC)/aregion.$(ARCH).o	\
+$(SRC)/find_funnymags.$(ARCH).o	$(SRC)/gcatstats.$(ARCH).o\
+$(SRC)/find_matches.$(ARCH).o	$(SRC)/check_permissions.$(ARCH).o
+
+
+OBJ = $(FIXCAT)
+
+default: $(PROGRAM)
+
+$(MARKSTAR): $(INC)/markstar.h
+
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:	
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
Index: /tags/start/Ohana/src/fixcat/doc/example.txt
===================================================================
--- /tags/start/Ohana/src/fixcat/doc/example.txt	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/doc/example.txt	(revision 12606)
@@ -0,0 +1,13 @@
+
+rats: foreach f ( */*.cpt )
+foreach? echo $f
+foreach? echo $f >> bright.log
+foreach? (markstar -v $f >> bright.dat) >>& bright.log
+foreach? end
+
+
+
+ echo $f
+ echo $f >> bright.log
+ (markstar -v $f >> bright.dat) >>& bright.log
+ end
Index: /tags/start/Ohana/src/fixcat/include/markstar.h
===================================================================
--- /tags/start/Ohana/src/fixcat/include/markstar.h	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/include/markstar.h	(revision 12606)
@@ -0,0 +1,42 @@
+# include <ohana.h>
+# include <loneos.h>
+
+int    VERBOSE;
+int    RESET;
+int    FORCE_RUN;
+
+/* global variables set in parameter file */
+char   CATDIR[256];
+char   GSCDIR[256];
+char   ImageCat[256];
+char   GSCFILE[256];
+
+double RADIUS;
+double TRAIL_WIDTH;
+int    NBINS;
+int    NPTSINLINE;
+double MIN_DENSITY;
+double NSIGMA;
+
+double BRIGHT_HALO_MAG;
+double BRIGHT_HALO_SLOPE;
+double BRIGHT_XTRAIL_WIDTH;
+double BRIGHT_XTRAIL_MAG;
+double BRIGHT_XTRAIL_SLOPE;
+double BRIGHT_YTRAIL_WIDTH;
+double BRIGHT_YTRAIL_MAG;
+double BRIGHT_YTRAIL_SLOPE;
+
+double GHOST_MAG;
+double GHOST_RADIUS;
+double OPTICAL_AXIS1;
+double OPTICAL_AXIS2;
+
+typedef struct {
+  Coords coords;
+  float *X, *Y;
+  int *N;
+  double RA[2], DEC[2];
+  double Area, density, spacing;
+} CatStats;
+
Index: /tags/start/Ohana/src/fixcat/src/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/ConfigInit.c	(revision 12606)
@@ -0,0 +1,45 @@
+# include "markstar.h"
+
+ConfigInit (int argc, char **argv) {
+
+  char *config, *file;
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (&argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  /* used in other pipeline functions */
+  ScanConfig (config, "IMAGE_CATALOG",   "%s",  0, ImageCat);
+  ScanConfig (config, "CATDIR",          "%s",  0, CATDIR);
+  ScanConfig (config, "GSCDIR",          "%s",  0, GSCDIR);
+  ScanConfig (config, "GSCFILE",         "%s",  0, GSCFILE);
+  /* unique to markstar */
+  ScanConfig (config, "SEARCH_RADIUS",   "%lf", 0, &RADIUS);
+  ScanConfig (config, "TRAIL_WIDTH",     "%lf", 0, &TRAIL_WIDTH);
+  ScanConfig (config, "NANGLE_BINS",     "%d",  0, &NBINS);
+  ScanConfig (config, "NPTSINLINE",      "%d",  0, &NPTSINLINE);
+  ScanConfig (config, "MIN_DENSITY",     "%lf", 0, &MIN_DENSITY);
+  ScanConfig (config, "SPACE_SIGMA",     "%lf", 0, &NSIGMA); 
+
+  ScanConfig (config, "BRIGHT_HALO_MAG",     "%lf", 0, &BRIGHT_HALO_MAG);
+  ScanConfig (config, "BRIGHT_HALO_SLOPE",   "%lf", 0, &BRIGHT_HALO_SLOPE);
+  ScanConfig (config, "BRIGHT_XTRAIL_WIDTH", "%lf", 0, &BRIGHT_XTRAIL_WIDTH);
+  ScanConfig (config, "BRIGHT_XTRAIL_MAG",   "%lf", 0, &BRIGHT_XTRAIL_MAG);
+  ScanConfig (config, "BRIGHT_XTRAIL_SLOPE", "%lf", 0, &BRIGHT_XTRAIL_SLOPE);
+  ScanConfig (config, "BRIGHT_YTRAIL_WIDTH", "%lf", 0, &BRIGHT_YTRAIL_WIDTH);
+  ScanConfig (config, "BRIGHT_YTRAIL_MAG",   "%lf", 0, &BRIGHT_YTRAIL_MAG);
+  ScanConfig (config, "BRIGHT_YTRAIL_SLOPE", "%lf", 0, &BRIGHT_YTRAIL_SLOPE);
+
+  ScanConfig (config, "GHOST_MAG",       "%lf", 0, &GHOST_MAG);
+  ScanConfig (config, "GHOST_RADIUS",    "%lf", 0, &GHOST_RADIUS);
+  ScanConfig (config, "OPTICAL_AXIS1",   "%lf", 0, &OPTICAL_AXIS1);
+  ScanConfig (config, "OPTICAL_AXIS2",   "%lf", 0, &OPTICAL_AXIS2);
+ 
+  free (config);
+}
Index: /tags/start/Ohana/src/fixcat/src/aregion.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/aregion.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/aregion.c	(revision 12606)
@@ -0,0 +1,186 @@
+# include "markstar.h"
+
+double BigDecBounds[] = {0.0, 7.5, 15.0, 22.5, 30.0, 37.5, 45.0, 
+			 52.5, 60.0, 67.5, 75.0, 82.5, 90.0,
+			 0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, 
+			 -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+char *DecSections[] = {"N0000", "N0730", "N1500", "N2230", "N3000", "N3730", "N4500", 
+		       "N5230", "N6000", "N6730", "N7500", "N8230", "weirdness", 
+		       "S0000", "S0730", "S1500", "S2230", "S3000", "S3730", "S4500", 
+		       "S5230", "S6000", "S6730", "S7500", "S8230", "weirdness"};
+
+char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			"n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			"s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			"s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+char *disk[] = {"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", 
+		"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "weirdness", 
+		"disk 1", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", 
+		"disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "weirdness"};
+
+int NBigRASections [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3, 48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3};
+
+int NDecLines[] = {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 24, 
+                   0, 597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48};
+
+/* find region file which contains ra, dec */
+aregion (region, f, ra, dec) 
+GSCRegion region[];
+FILE *f;
+double ra, dec;
+{
+  
+  
+  char buffer[28800], temp[50], file[50];
+  double dr, dd;
+  double RA0, RA1, DEC0, DEC1;
+  int i, NBigDec, NLINES, done, nregion;
+  
+  while (ra < 0) { ra += 360.0; }
+  while (ra >= 360.0) { ra -= 360.0; }
+    
+  if (dec >= 86.25) {
+    sprintf (file, "%s/n8230/pole.cpt\0", GSCDIR);
+    region[0].DEC[0] = 86.25;
+    region[0].DEC[1] = 93.75;
+    region[0].RA[0] = -180.0;
+    region[0].RA[1] =  540.0;
+    strcpy (region[0].filename, file);
+    return;
+  }
+    
+  NBigDec = -1;
+  for (i = 0; i < 12; i++) {
+# ifdef DEBUG
+    fprintf (stderr, "%d %f %f %f\n", i, dec, BigDecBounds[i], BigDecBounds[i+1]);
+# endif
+    if ((dec >= BigDecBounds[i]) && (dec < BigDecBounds[i+1])) {
+      NBigDec = i;
+      break;
+    }
+  }
+  if (NBigDec < 0) {
+    for (i = 13; i < 24; i++) {
+# ifdef DEBUG
+      fprintf (stderr, "%d %f %f %f\n", i, dec, BigDecBounds[i], BigDecBounds[i+1]);
+# endif
+      if ((dec < BigDecBounds[i]) && (dec >= BigDecBounds[i+1])) {
+	NBigDec = i;
+	break;
+      }
+    }
+  }
+  if (NBigDec < 0) {
+    fprintf (stderr, "dec out of range: %f\n", dec);
+  }
+    
+  NLINES = 0;
+  for (i = 0; i < NBigDec; i++) {
+    NLINES += NDecLines[i];
+  }
+  fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+      
+  done = FALSE;
+  Fread (buffer, 1, 48*NDecLines[NBigDec], f, "char");
+  for (i = 0; !done && (i < NDecLines[NBigDec]); i++) {
+    strncpy (temp, &buffer[i*48], 48);
+    temp[49] = 0;
+    hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+    if (RA1 < RA0) RA1 += 360.0;
+# ifdef DEBUG
+    fprintf (stderr, "%f %f %f  %f %f %f  %s\n", DEC0, dec, DEC1, RA0, ra, RA1, temp);
+# endif
+    if ((dec >= 0) && (dec >= DEC0) && (dec < DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+    if ((dec < 0) && (dec < DEC0) && (dec >= DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+  }
+  if (!done) {
+    fprintf (stderr, "error in search: %f %f\n", ra, dec);
+    exit (0);
+  }
+  temp[5] = 0;
+  sprintf (file, "%s/%s/%s.cpt\0", GSCDIR, Dec2Sections[NBigDec],&temp[1]);
+  if (DEC0 < DEC1) {
+    region[0].DEC[0] = DEC0;
+    region[0].DEC[1] = DEC1;
+  } else {
+    region[0].DEC[0] = DEC1;
+    region[0].DEC[1] = DEC0;
+  }     
+  region[0].RA[0] = RA0;
+  region[0].RA[1] = RA1;
+  strcpy (region[0].filename, file);
+  return;
+}
+
+
+/**********/
+int hms_to_deg (h0, h1, d0, d1, string) 
+     char *string;
+     double *h0, *h1, *d0, *d1;
+{
+  
+  int flag_d0, flag_d1, flag_h0, flag_h1;
+  double tmp;
+  
+  *d0 = *h0 = *d1 = *h1 = 0;
+
+  flag_h0 = dparse (h0, 1, string);
+  flag_h1 = dparse (h1, 4, string);
+  flag_d0 = dparse (d0, 7, string);
+  flag_d1 = dparse (d1, 9, string);
+  *h0 *= flag_h0;
+  *h1 *= flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  dparse (&tmp, 2, string);
+  *h0 += tmp/60.0;
+  dparse (&tmp, 3, string);
+  *h0 += tmp/3600.0;
+  
+  dparse (&tmp, 5, string);
+  *h1 += tmp/60.0;
+  dparse (&tmp, 6, string);
+  *h1 += tmp/3600.0;
+  
+  dparse (&tmp, 8, string);
+  *d0 += tmp/60.0;
+
+  dparse (&tmp, 10, string);
+  *d1 += tmp/60.0;
+
+  *h0 *= 15*flag_h0;
+  *h1 *= 15*flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  return (TRUE);
+}
+
+
+/*
+      if (buffer[i*48 + 19] == ' ') continue;
+      strncpy (temp, &buffer[i*48 + 19], 20);       temp[20] = 0;
+      hms_to_deg (&RA,  &DEC, temp, ' ', 3);
+
+
+  dBigRA = 360.0 / (int)(0.5 + 48*cos(3.1415927*0.5*(BigDecBounds[NBigDec] + BigDecBounds[NBigDec + 1])/180.0));
+
+  NBigRA = ra / dBigRA;
+
+  NBig = NBigRA;
+  for (i = 0; (i < 12) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+  for (i = 13; (i < 24) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+
+
+  fprintf (stderr, "%d %d %d %d %f %f -> %f %f %f\n", NBigDec, NBigRA, NBigRASections[NBigDec], NBig, ra, dec, BigDecBounds[NBigDec], BigDecBounds[NBigDec + 1], dBigRA);
+*/
Index: /tags/start/Ohana/src/fixcat/src/check_lockfile.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/check_lockfile.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/check_lockfile.c	(revision 12606)
@@ -0,0 +1,39 @@
+# include "markstar.h"
+
+check_lockfile ()
+{
+  
+  FILE *f;
+  char filename[128];
+  struct stat filestat;
+
+  sprintf (filename, "%s/lock\0", CATDIR);
+  if (stat (filename, &filestat) != -1) {
+    fprintf (stderr, "ERROR: catalog %s is locked, try again later\n", CATDIR);
+    exit (0);
+  }
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't set lock file %s\n", filename);
+    exit (0);
+  }
+  fclose (f);
+
+}
+
+clear_lockfile ()
+{
+  
+  char filename[128], line[256];
+  struct stat filestat;
+
+  sprintf (filename, "%s/lock\0", CATDIR);
+  if (stat (filename, &filestat) != -1) {
+    sprintf (line, "rm %s\0", filename);
+    system (line);
+  } else {
+    fprintf (stderr, "can't remove lockfile, why not?\n");
+  }
+
+}
Index: /tags/start/Ohana/src/fixcat/src/check_permissions.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/check_permissions.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/check_permissions.c	(revision 12606)
@@ -0,0 +1,63 @@
+# include "markstar.h"
+
+check_permissions (char *basefile) {
+  
+  FILE *f;
+  char *c, dir[256], filename[256];
+  struct stat filestat;
+  uid_t fuid, uid;
+  gid_t fgid, gid;
+  int status;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to write to directory */
+  sprintf (filename, "%s\0", basefile);
+  c = strrchr (filename, '/');
+  if (c == (char *) NULL) {
+    strcpy (dir, ".");
+  } else {
+    *c = 0;
+    strcpy (dir, filename);
+  }
+  status = stat (dir, &filestat);
+  if (status == -1) {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (0);
+  } 
+  if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRWXU)) ||
+      ((gid == filestat.st_gid) && (filestat.st_mode & S_IRWXG)) || 
+      (filestat.st_mode & S_IRWXO)) {
+  } else {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (0);
+  }
+  
+  /* check permission to write to file */
+  sprintf (filename, "%s\0", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (0);
+    }
+  }
+  
+  /* check permission to write to backup file */
+  sprintf (filename, "%s~\0", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (0);
+    }
+  }
+  
+}
Index: /tags/start/Ohana/src/fixcat/src/config.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/config.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/config.c	(revision 12606)
@@ -0,0 +1,110 @@
+# include <ohana.h>
+# define D_NBYTES 4096
+
+char *LoadConfigFile (filename) 
+char *filename; 
+{
+  
+  FILE *f;
+  int i, done, Nbytes, NBYTES, size;
+  char *config;
+  
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "couldn't find %s\n", filename);
+    return ((char *) NULL);
+  }
+ 
+  NBYTES = D_NBYTES;
+  ALLOCATE (config, char, NBYTES);
+ 
+  size = 0;
+  done = FALSE;
+  for (i = 0; !done; i++) {
+    Nbytes = Fread (&config[i*D_NBYTES], sizeof(char), D_NBYTES, f, "char");
+    size += Nbytes;
+    if (Nbytes < D_NBYTES) 
+      done = TRUE;
+    else {
+      NBYTES += D_NBYTES;
+      REALLOCATE (config, char, NBYTES);
+    }
+  }
+  
+  config[size] = '\n';
+  config[size+1] = 0;
+  REALLOCATE (config, char, size + 2);
+ 
+  fclose (f);
+
+  return (config);
+}
+
+int ScanConfig /* we expect one more field: the pointer to the value requested */
+# ifndef ANSI
+(config, field, mode, va_alist) 
+ char *config; char *field, *mode; va_dcl
+# else
+(char       config[],
+ char       field[],
+ char       mode[],...)
+# endif
+{
+ 
+  int i, j;
+  char *p, *p2, tmp[256];
+  va_list argp;
+  double value;
+  
+# ifndef ANSI
+  va_start (argp);
+# else
+  va_start (argp, N);
+# endif
+  
+  /* find the correct line with field */
+  p2 = config;
+  for (i = 0; ; i++) {
+    if (!strncmp (field, p2, strlen(field))) {
+      p = p2 + strlen (field);
+      break;
+    }
+    else {
+      p2 = strchr (p2, '\n');
+      if (p2 == (char *) NULL) {
+	fprintf (stderr, "entry %s not found in config file\n", field);
+	return (FALSE);
+      }
+      else p2++;
+    }
+  }
+  if (!strcmp (mode, "%s")) {
+    p2 = strchr (p, '\n');
+    if (p2 == (char *) NULL)
+      p2 = config + strlen(config);
+    bcopy (p, tmp, (p2-p));
+    tmp[(p2-p)] = 0;
+    stripwhite (tmp);
+    p2 = va_arg (argp, char *);
+    strcpy (p2, tmp);
+  }
+  else {
+ 
+    /* try to get a numerical value from the field */
+    value = strtod (p, &p2);
+    if ((*p2 == 'd') || (*p2 == 'D')) 
+      value *= pow (10.0, atof (p2 + 1));
+    
+    if (!strcmp (mode, "%d"))  *va_arg (argp, int *)       = value;
+    if (!strcmp (mode, "%u"))  *va_arg (argp, unsigned *)  = value;
+    if (!strcmp (mode, "%ld")) *va_arg (argp, long *)      = value;
+    if (!strcmp (mode, "%hd")) *va_arg (argp, short *)     = value;
+    if (!strcmp (mode, "%f"))  *va_arg (argp, float *)     = value;
+    if (!strcmp (mode, "%lf")) *va_arg (argp, double *)    = value;
+    
+  }
+ 
+  va_end (argp);
+  return (TRUE);
+  
+}
Index: /tags/start/Ohana/src/fixcat/src/coordops.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/coordops.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/coordops.c	(revision 12606)
@@ -0,0 +1,342 @@
+# include "markstar.h"
+
+XY_to_RD (ra, dec, x, y, coords)
+double *ra, *dec;
+double  x, y;
+Coords coords[];
+{
+
+  double L, M, X, Y, T;
+  double R, sphi, cphi, stht, ctht;
+  double alpha, delta, salp, calp, sdel, sdp, cdp;
+  
+  *ra  = 0;
+  *dec = 0;
+
+# if 1
+  if (!strcmp(&coords[0].ctype[4], "-PLY")) {
+    X = coords[0].cdelt1*(x - coords[0].crpix1 + x*x*coords[0].polyterms[0][0] + x*y*coords[0].polyterms[1][0] + y*y*coords[0].polyterms[2][0]
+			  + x*x*x*coords[0].polyterms[3][0] + x*x*y*coords[0].polyterms[4][0] + x*y*y*coords[0].polyterms[5][0] + y*y*y*coords[0].polyterms[6][0]);
+    Y = coords[0].cdelt2*(y - coords[0].crpix2 + x*x*coords[0].polyterms[0][1] + x*y*coords[0].polyterms[1][1] + y*y*coords[0].polyterms[2][1]
+			  + x*x*x*coords[0].polyterms[3][1] + x*x*y*coords[0].polyterms[4][1] + x*y*y*coords[0].polyterms[5][1] + y*y*y*coords[0].polyterms[6][1]);
+  } else {
+# else
+  {
+# endif
+    X = coords[0].cdelt1*(x - coords[0].crpix1);
+    Y = coords[0].cdelt2*(y - coords[0].crpix2);
+  }    
+
+  L = (X*coords[0].pc1_1 + Y*coords[0].pc1_2);
+  M = (X*coords[0].pc2_1 + Y*coords[0].pc2_2);
+
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    R = hypot (L,M);
+    if ((L == 0) && (M == 0)) {
+      sphi = 0;
+      cphi = 1;
+    }
+    else {
+      sphi =  L / R;
+      cphi = -M / R;
+    }
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN")) {
+      if (R == 0) {
+	stht = 1.0;
+	ctht = 0.0;
+      }
+      else {
+	T = DEG_RAD / R;
+	stht =   T / sqrt ( 1.0 + T*T);
+	ctht = 1.0 / sqrt ( 1.0 + T*T);
+      }
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      ctht = RAD_DEG * R;
+      stht = sqrt (1 - ctht*ctht);
+    }
+
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    
+    sdel = stht*sdp - ctht*cphi*cdp;
+    salp = ctht*sphi;
+    calp = stht*cdp + ctht*cphi*sdp;
+    alpha = atan2 (salp, calp);
+    delta = asin (sdel);
+    
+    *ra  = DEG_RAD*alpha + coords[0].crval1;
+    *dec = DEG_RAD*delta;
+  }
+  if (!strcmp(&coords[0].ctype[4], "-LIN") || !strcmp(&coords[0].ctype[0], "GENE")) {
+    *ra  = L + coords[0].crval1;
+    *dec = M + coords[0].crval2;
+  }
+
+}
+
+
+fXY_to_RD (ra, dec, x, y, coords)
+float *ra, *dec;
+double  x, y;
+Coords coords[];
+{
+
+  double L, M, X, Y, T;
+  double R, sphi, cphi, stht, ctht;
+  double alpha, delta, salp, calp, sdel, sdp, cdp;
+  
+  *ra  = 0;
+  *dec = 0;
+
+  if (!strcmp(&coords[0].ctype[4], "-PLY")) {
+    X = coords[0].cdelt1*(x - coords[0].crpix1 + x*x*coords[0].polyterms[0][0] + x*y*coords[0].polyterms[1][0] + y*y*coords[0].polyterms[2][0]
+			  + x*x*x*coords[0].polyterms[3][0] + x*x*y*coords[0].polyterms[4][0] + x*y*y*coords[0].polyterms[5][0] + y*y*y*coords[0].polyterms[6][0]);
+    Y = coords[0].cdelt2*(y - coords[0].crpix2 + x*x*coords[0].polyterms[0][1] + x*y*coords[0].polyterms[1][1] + y*y*coords[0].polyterms[2][1]
+			  + x*x*x*coords[0].polyterms[3][1] + x*x*y*coords[0].polyterms[4][1] + x*y*y*coords[0].polyterms[5][1] + y*y*y*coords[0].polyterms[6][1]);
+  } else {
+    X = coords[0].cdelt1*(x - coords[0].crpix1);
+    Y = coords[0].cdelt2*(y - coords[0].crpix2);
+  }    
+  L = (X*coords[0].pc1_1 + Y*coords[0].pc1_2);
+  M = (X*coords[0].pc2_1 + Y*coords[0].pc2_2);
+
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    R = hypot (L,M);
+    if ((L == 0) && (M == 0)) {
+      sphi = 0;
+      cphi = 1;
+    }
+    else {
+      sphi =  L / R;
+      cphi = -M / R;
+    }
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") ) {
+      if (R == 0) {
+	stht = 1.0;
+	ctht = 0.0;
+      }
+      else {
+	T = DEG_RAD / R;
+	stht =   T / sqrt ( 1.0 + T*T);
+	ctht = 1.0 / sqrt ( 1.0 + T*T);
+      }
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      ctht = RAD_DEG * R;
+      stht = sqrt (1 - ctht*ctht);
+    }
+
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    
+    sdel = stht*sdp - ctht*cphi*cdp;
+    salp = ctht*sphi;
+    calp = stht*cdp + ctht*cphi*sdp;
+    alpha = atan2 (salp, calp);
+    delta = asin (sdel);
+    
+    *ra  = DEG_RAD*alpha + coords[0].crval1;
+    *dec = DEG_RAD*delta;
+  }
+  if (!strcmp(&coords[0].ctype[4], "-LIN") || !strcmp(&coords[0].ctype[0], "GENE")) {
+    *ra  = L + coords[0].crval1;
+    *dec = M + coords[0].crval2;
+  }
+
+}
+
+
+RD_to_XY (x, y, ra, dec, coords)
+double *x, *y;
+double  ra, dec;
+Coords coords[];
+{
+
+  double tmp_d;
+  double X, Y, sphi, cphi, stht;
+  double salp, calp, sdel, cdel, sdp, cdp;
+
+  if (!strcmp(&coords[0].ctype[4], "-PLY")) {
+    /* fprintf (stderr, "approximate to polynomial TAN plane fit\n");  */
+  }
+
+  *x = 0;
+  *y = 0;
+  if (!strcmp(&coords[0].ctype[0], "GENE") || !strcmp(&coords[0].ctype[4], "-LIN")) {
+    X = (ra  - coords[0].crval1);
+    Y = (dec - coords[0].crval2);
+  }
+  
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    salp = sin(RAD_DEG*(ra - coords[0].crval1));
+    calp = cos(RAD_DEG*(ra - coords[0].crval1));
+    sdel = sin(RAD_DEG*dec);
+    cdel = cos(RAD_DEG*dec);
+
+    stht = sdel*sdp + cdel*cdp*calp;  /* sin(theta) */
+    sphi = cdel*salp;  /* = cos(theta)*sin(phi) */
+    cphi = cdel*sdp*calp - sdel*cdp; /* = cos(theta)*cos(phi) */
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") ) {
+      X =  DEG_RAD * sphi / stht;
+      Y = -DEG_RAD * cphi / stht;
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      X =  DEG_RAD * sphi;
+      Y = -DEG_RAD * cphi;
+    }
+    X = X;
+    Y = Y;
+  }
+  
+  tmp_d = 1.0 / (coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1);
+  *x = tmp_d * (coords[0].pc2_2*X - coords[0].pc1_2*Y) / coords[0].cdelt1 + coords[0].crpix1;
+  *y = tmp_d * (coords[0].pc1_1*Y - coords[0].pc2_1*X) / coords[0].cdelt2 + coords[0].crpix2;
+ 
+}
+
+
+fRD_to_XY (x, y, ra, dec, coords)
+float *x, *y;
+double  ra, dec;
+Coords coords[];
+{
+
+  double tmp_d;
+  double X, Y, sphi, cphi, stht;
+  double salp, calp, sdel, cdel, sdp, cdp;
+
+  *x = 0;
+  *y = 0;
+  if (!strcmp(&coords[0].ctype[0], "GENE") || !strcmp(&coords[0].ctype[4], "-LIN")) {
+    X = (ra  - coords[0].crval1);
+    Y = (dec - coords[0].crval2);
+  }
+  
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    salp = sin(RAD_DEG*(ra - coords[0].crval1));
+    calp = cos(RAD_DEG*(ra - coords[0].crval1));
+    sdel = sin(RAD_DEG*dec);
+    cdel = cos(RAD_DEG*dec);
+
+    stht = sdel*sdp + cdel*cdp*calp;  /* sin(theta) */
+    sphi = cdel*salp;  /* = cos(theta)*sin(phi) */
+    cphi = cdel*sdp*calp - sdel*cdp; /* = cos(theta)*cos(phi) */
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") ) {
+      X =  DEG_RAD * sphi / stht;
+      Y = -DEG_RAD * cphi / stht;
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      X =  DEG_RAD * sphi;
+      Y = -DEG_RAD * cphi;
+    }
+    X = X;
+    Y = Y;
+  }
+  
+  tmp_d = 1.0 / (coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1);
+  *x = tmp_d * (coords[0].pc2_2*X - coords[0].pc1_2*Y) / coords[0].cdelt1 + coords[0].crpix1;
+  *y = tmp_d * (coords[0].pc1_1*Y - coords[0].pc2_1*X) / coords[0].cdelt2 + coords[0].crpix2;
+ 
+}
+
+
+
+GetCoords (coords, header) 
+Coords coords[];
+Header header[];
+{
+
+  int status;
+  double rotate;
+
+  rotate = 0.0;
+  coords[0].crval1 = coords[0].crpix1 = coords[0].cdelt1 = 0.0;
+  coords[0].crval2 = coords[0].crpix2 = coords[0].cdelt2 = 0.0;
+  coords[0].pc1_1 = coords[0].pc2_2 = 1.0;
+  coords[0].pc2_1 = coords[0].pc1_2 = 0.0;
+  strcpy (coords[0].ctype, "NONE");
+
+  status = TRUE; 
+  if (fits_scan (header, "CTYPE2", "%s", 1, coords[0].ctype)) {
+    status  = fits_scan (header, "CRVAL1", "%lf", 1, &coords[0].crval1);
+    status &= fits_scan (header, "CRPIX1", "%lf", 1, &coords[0].crpix1);
+    status &= fits_scan (header, "CRVAL2", "%lf", 1, &coords[0].crval2);  
+    status &= fits_scan (header, "CRPIX2", "%lf", 1, &coords[0].crpix2);
+    if (fits_scan (header, "CDELT1", "%lf", 1, &coords[0].cdelt1)) {
+      status &= fits_scan (header, "CDELT2", "%lf", 1, &coords[0].cdelt2);
+      if (fits_scan (header, "CROTA2", "%lf", 1, &rotate)) {
+	coords[0].pc1_1 =  cos(rotate*RAD_DEG);
+	coords[0].pc1_2 = -sin(rotate*RAD_DEG);
+	coords[0].pc2_1 =  sin(rotate*RAD_DEG);
+	coords[0].pc2_2 =  cos(rotate*RAD_DEG);
+      }
+      if (fits_scan (header, "PC001001", "%lf", 1, &coords[0].pc1_1)) {
+	status &= fits_scan (header, "PC001002", "%lf", 1, &coords[0].pc1_2);
+	status &= fits_scan (header, "PC002001", "%lf", 1, &coords[0].pc2_1);
+	status &= fits_scan (header, "PC002002", "%lf", 1, &coords[0].pc2_2);
+      }
+    }
+    else {
+      if (fits_scan (header, "CD1_1", "%lf", 1, &coords[0].pc1_1)) {
+	status &= fits_scan (header, "CD1_2", "%lf", 1, &coords[0].pc1_2);
+	status &= fits_scan (header, "CD2_1", "%lf", 1, &coords[0].pc2_1);
+	status &= fits_scan (header, "CD2_2", "%lf", 1, &coords[0].pc2_2);
+	coords[0].cdelt1 = coords[0].cdelt2 = 1.0;
+      }
+      else {
+	status = FALSE;
+      }
+    }
+  }
+  else {
+    if (fits_scan (header, "RA_O", "%lf", 1, &coords[0].crval1)) {
+      status  = fits_scan (header, "RA_X", "%lf", 1, &coords[0].pc1_1);
+      status &= fits_scan (header, "RA_Y", "%lf", 1, &coords[0].pc1_2);
+      status &= fits_scan (header, "DEC_O", "%lf", 1, &coords[0].crval2);  
+      status &= fits_scan (header, "DEC_X", "%lf", 1, &coords[0].pc2_1);
+      status &= fits_scan (header, "DEC_Y", "%lf", 1, &coords[0].pc2_2);
+      coords[0].crpix1 = coords[0].crpix2 = 0.0;
+      coords[0].cdelt1 = coords[0].cdelt2 = 1.0;
+      strcpy (coords[0].ctype, "GENE");
+    }
+  }
+  if (!status) {
+    fprintf (stderr, "error getting all elements for coordinate mode %d\n", coords[0].ctype);
+    coords[0].crval1 = coords[0].crpix1 = coords[0].cdelt1 = 0.0;
+    coords[0].crval2 = coords[0].crpix2 = coords[0].cdelt2 = 0.0;
+    coords[0].pc1_1 = coords[0].pc2_2 = 1.0;
+    coords[0].pc2_1 = coords[0].pc1_2 = 0.0;
+    strcpy (coords[0].ctype, "NONE");
+  }
+}
+
+
+  /* -PLY projection is an extrapolation of the -TAN projection. 
+     In addition to the usual linear terms of CRPIXi, PC00i00j, there are 
+     higher order polynomial terms (up to 3rd order):
+     Axis 1 terms:
+     PCA1X2Y0 = coords.polyterm[0][0] = x^2                                             
+     PCA1X1Y1 = coords.polyterm[1][0] = xy                                          
+     PCA1X0Y2 = coords.polyterm[2][0] = y^2                                             
+     PCA1X3Y0 = coords.polyterm[3][0] = x^3                                             
+     PCA1X2Y1 = coords.polyterm[4][0] = x^2 y                                             
+     PCA1X1Y2 = coords.polyterm[5][0] = x y^2                                             
+     PCA1X0Y3 = coords.polyterm[6][0] = y^2                                              
+     Axis 2 terms:
+     PCA2X2Y0 = coords.polyterm[0][1] = x^2                                               
+     PCA2X1Y1 = coords.polyterm[1][1] = xy                                                
+     PCA2X0Y2 = coords.polyterm[2][1] = y^2                                               
+     PCA2X3Y0 = coords.polyterm[3][1] = x^3                                               
+     PCA2X2Y1 = coords.polyterm[4][1] = x^2 y                                             
+     PCA2X1Y2 = coords.polyterm[5][1] = x y^2                                             
+     PCA2X0Y3 = coords.polyterm[6][1] = y^2                                               
+  */
Index: /tags/start/Ohana/src/fixcat/src/find_bright_stars.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/find_bright_stars.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/find_bright_stars.c	(revision 12606)
@@ -0,0 +1,142 @@
+# include "markstar.h"
+
+find_bright_stars (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  int i, j, n, m, first_j, Nave, Ngsc;
+  Catalog GSCdata;
+  double MinRA, MinDEC, MaxRA, MaxDEC, RaCenter, DecCenter;
+  Coords *tcoords;
+  float *X1, *Y1, *X2, *Y2;
+  int *N1, *N2;
+  char *mark;
+  double dX, dY, dR, MaxDist, MaxDist1, MaxRadius, radius, radius2;
+
+  load_gsc_data (&GSCdata, catstats);
+
+  Nave = catalog[0].Naverage;
+  Ngsc = GSCdata.Naverage;
+    
+  /* in the function below, it is better to have the catalog with
+     more stars associated with index 2 (j) */ 
+  X2 = catstats[0].X;
+  Y2 = catstats[0].Y;
+  N2 = catstats[0].N;
+  ALLOCATE (X1, float, Ngsc);
+  ALLOCATE (Y1, float, Ngsc);
+  ALLOCATE (N1, int, Ngsc);
+  ALLOCATE (mark, char, Nave);
+  bzero (mark, Nave);
+
+  tcoords = &catstats[0].coords;
+  for (i = 0; i < Ngsc; i++) {
+    fRD_to_XY (&X1[i], &Y1[i], GSCdata.average[i].R, GSCdata.average[i].D, tcoords);
+    N1[i] = i;
+  }
+  if (Ngsc > 1) sort_lists (X1, Y1, N1, Ngsc);
+  
+  /* first find stellar halos */
+  /* max radius (mag = -1) */
+  /** the j index moves quickly and is better associated with the catalog with more stars */
+  MaxRadius = BRIGHT_HALO_SLOPE * (-1.0 - BRIGHT_HALO_MAG); 
+  /** find catalog stars near GSC stars **/
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -2*MaxRadius) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*MaxRadius) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    radius = MAX (BRIGHT_HALO_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_HALO_MAG), 0.0);
+    if (radius == 0) {
+      i++; 
+      continue;
+    }
+    radius2 = radius*radius;
+    for (; (dX > -2*radius) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < radius2) {  /* new measurement of this star */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+  /* next find y spikes */
+  /** find catalog stars near GSC stars **/
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -BRIGHT_YTRAIL_WIDTH) {
+      i++;
+      continue;
+    }
+    if (dX >= BRIGHT_YTRAIL_WIDTH) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    MaxDist = MAX (BRIGHT_YTRAIL_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_YTRAIL_MAG), 0.0);
+    for (; (dX > -BRIGHT_YTRAIL_WIDTH) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      if ((fabs(dX) < BRIGHT_YTRAIL_WIDTH) && (fabs(dY) < MaxDist)) {  /* star on spike */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+  /* next find x spikes */
+  /** find catalog stars near GSC stars **/
+  MaxDist = MAX (BRIGHT_XTRAIL_SLOPE * (-1.0 - BRIGHT_XTRAIL_MAG), 0.0);
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -MaxDist) {
+      i++;
+      continue;
+    }
+    if (dX >= MaxDist) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    MaxDist1 = MAX (BRIGHT_XTRAIL_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_XTRAIL_MAG), 0.0);
+    for (; (dX > -MaxDist1) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      if ((fabs(dY) < BRIGHT_XTRAIL_WIDTH) && (fabs(dX) < MaxDist1)) {  /* star on spike */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+
+  /* done with search, mark selected stars */
+  for (i = 0; i < Nave; i++) {
+    if (mark[i]) {
+      catalog[0].average[N2[i]].code = ID_BLEED;
+    }
+  } 
+  
+  free (X1);
+  free (Y1);
+  free (N1);
+  free (mark);
+  free (GSCdata.average);
+
+}
+
Index: /tags/start/Ohana/src/fixcat/src/find_funnymags.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/find_funnymags.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/find_funnymags.c	(revision 12606)
@@ -0,0 +1,27 @@
+# include "markstar.h"
+
+find_funnymags (catalog, images, Nimage)
+Catalog catalog[];
+Image images[];
+int Nimage;
+{
+
+  int i;
+  int *bad;
+
+  ALLOCATE (bad, int, Nimage);
+  bzero (bad, Nimage*sizeof(int));
+
+  for (i = 0; i < catalog[0].Nmeasure; i++) {
+    if (catalog[0].measure[i].M < 9000) {
+      bad[catalog[0].image[i]] ++;
+    }
+  }
+
+  for (i = 0; i < Nimage; i++) {
+    if (bad[i] > 0) {
+      fprintf (stdout, "%s %d %d\n", images[i].name, images[i].tzero, bad[i]);
+    }
+  }
+
+}
Index: /tags/start/Ohana/src/fixcat/src/find_ghosts.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/find_ghosts.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/find_ghosts.c	(revision 12606)
@@ -0,0 +1,70 @@
+# include "markstar.h"
+
+find_ghosts (catalog, catstats, filename, image, Nimage)
+Catalog catalog[];
+CatStats catstats[];
+char *filename;
+Image image[];
+int Nimage;
+{
+
+  int i, j, first_j, Nave, Ngsc, Nregions;
+  Catalog GSCdata, Ghostdata;
+  double MinRA, MinDEC, MaxRA, MaxDEC, RaCenter, DecCenter;
+  Coords *tcoords;
+  float *X1, *Y1, *X2, *Y2;
+  int *N1, *N2, *match;
+  char *mark;
+  double dX, dY, dR, RADIUS2, BRIGHT_RADIUS, radius, X, Y, R, D;
+  Image timage;
+  GSCRegion *region, *gregions2();
+
+  for (i = 0; i < Nimage; i++) {
+    
+    /* coords structure for ghost image */
+    timage = image[i];
+    timage.coords.cdelt1 = -1*image[i].coords.cdelt1;
+    timage.coords.cdelt2 = -1*image[i].coords.cdelt2;
+    timage.coords.crpix1 = 2*OPTICAL_AXIS1 - image[i].coords.crpix1;
+    timage.coords.crpix2 = 2*OPTICAL_AXIS2 - image[i].coords.crpix2;
+
+    region = gregions2 (&timage, &Nregions);
+    
+    /* find ghost stars */
+    load_gsc_data_ghost (&GSCdata, region, Nregions, &timage);
+
+    /* refect ghost stars to find locations of ghosts */
+    ALLOCATE (Ghostdata.average, Average, MAX (GSCdata.Naverage, 1));
+    for (j = 0; j < GSCdata.Naverage; j++) {
+      RD_to_XY (&X, &Y, GSCdata.average[j].R, GSCdata.average[j].D, &timage);
+      fXY_to_RD (&Ghostdata.average[j].R, &Ghostdata.average[j].D, X, Y, &image[i]);
+      Ghostdata.average[j].M = GSCdata.average[j].M;
+    }    
+    Ghostdata.Naverage = GSCdata.Naverage;
+
+    /* match ghosts and image stars, mark ghosts */
+    find_matches (catalog, catstats, &Ghostdata, i);
+
+    free (Ghostdata.average);
+    free (GSCdata.average);
+  }
+
+}
+
+/* 
+
+   just to be clear on some of the terms:
+
+   the "ghost" is the fuzzy patch of light on an image caused by
+     a reflected star
+
+   the "ghost star" is the star in the sky which causes a ghost
+
+   the "ghost image" is the image location on the sky 
+     where ghost stars may come from.
+
+   the "image stars" are observed stars at the location of the
+     ghost - these are detections of the ghost
+
+
+*/
Index: /tags/start/Ohana/src/fixcat/src/find_group.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/find_group.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/find_group.c	(revision 12606)
@@ -0,0 +1,69 @@
+# include "markstar.h"
+
+find_group (catstats, mark, Npts, i, ANGLE)
+     CatStats catstats[];
+     double *ANGLE;
+     int i, Npts;
+     char *mark;
+{
+ 
+  float *R, *D;
+  int j, N, bin, Ndegbin;
+  unsigned short int *A;
+  double Ra, De, dR, dD, angle, limit;
+
+   /* assign some parameter values */
+  
+  R = catstats[0].X;
+  D = catstats[0].Y;
+  limit = 10.0*sqrt((double)(M_PI*RADIUS*RADIUS*catstats[0].density)/(double)(NBINS));
+  Ndegbin = NBINS / 180.0;
+  ALLOCATE (A, unsigned short int, NBINS)
+  bzero (A, NBINS*sizeof(short));
+
+  /* look for points concentrated in an angle bin */
+  if (mark[i]) return (FALSE);
+  Ra = R[i];
+  De = D[i];
+  N = 0;
+  /* points east */
+  for (j = i + 1; (j < Npts) && (R[j] - Ra < RADIUS); j++) {
+    if (mark[j]) continue;
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) 
+	continue;
+      if (angle < 0) angle += M_PI;
+      bin = 1 + angle*DEG_RAD*Ndegbin;
+      A[bin] ++;
+      if (A[bin] > limit) {
+	*ANGLE = (bin - 1.0) / (DEG_RAD*Ndegbin);
+	return (TRUE);
+      }
+      N ++;
+    }
+  }
+  /* points west */
+  for (j = i - 1; (j >= 0) && (Ra - R[j] < RADIUS); j--) {
+    if (mark[j]) continue;
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) 
+	continue;
+      if (angle < 0) angle += M_PI;
+      bin = 1 + angle*DEG_RAD*Ndegbin;
+      A[bin] ++;	
+      if (A[bin] > limit) {
+	*ANGLE = (bin - 1.0) / (DEG_RAD*Ndegbin);
+	return (TRUE);
+      }
+      N ++;
+    }
+  }
+  return (FALSE);
+}
+  
Index: /tags/start/Ohana/src/fixcat/src/find_images.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/find_images.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/find_images.c	(revision 12606)
@@ -0,0 +1,261 @@
+# include "markstar.h"
+# define OLDSTYLE 1
+# if (OLDSTYLE)
+double opening_angle ();
+# endif
+
+Image *find_images (catstats, Nimages)
+CatStats catstats[];
+int *Nimages;
+{
+  
+  Header header;
+  Image *timage, *image;
+  int i, j, k, found, nimage, Nimage, NIMAGE, NTIMAGE, Nloop, Nlast;
+  int n, Nim, status;
+  FILE *f;
+  double Xc[6], Yc[6], Xi[6], Yi[6], r, d, x, y, dx, dy;
+  Coords *tcoords;
+
+  /* we make positional comparisons in the projection of catalog */
+  tcoords = &catstats[0].coords;
+  /* define catalog corners */
+  Xc[0] = catstats[0].RA[0]; Yc[0] = catstats[0].DEC[0];
+  Xc[1] = catstats[0].RA[1]; Yc[1] = catstats[0].DEC[0];
+  Xc[2] = catstats[0].RA[1]; Yc[2] = catstats[0].DEC[1];
+  Xc[3] = catstats[0].RA[0]; Yc[3] = catstats[0].DEC[1];
+  Xc[4] = catstats[0].RA[0]; Yc[4] = catstats[0].DEC[0];
+  Xc[5] = catstats[0].RA[1]; Yc[5] = catstats[0].DEC[1];
+  for (j = 0; j < 6; j++) {
+    r = Xc[j]; d = Yc[j];
+    RD_to_XY (&Xc[j], &Yc[j], r, d, tcoords);
+  }
+  /* find Y positions of RA center */
+  r = 0.5*(catstats[0].RA[0] + catstats[0].RA[1]);
+  d = catstats[0].DEC[0];
+  RD_to_XY (&x, &y, r, d, tcoords);
+  Yc[0] = MIN (y, Yc[0]);
+  Yc[1] = MIN (y, Yc[1]);
+  Yc[4] = MIN (y, Yc[4]);
+  /* find Y positions of RA center */
+  r = 0.5*(catstats[0].RA[0] + catstats[0].RA[1]);
+  d = catstats[0].DEC[1];
+  RD_to_XY (&x, &y, r, d, tcoords);
+  Yc[2] = MAX (y, Yc[2]);
+  Yc[3] = MAX (y, Yc[3]);
+  Yc[5] = MAX (y, Yc[5]);
+
+  dx = 0.02*(Xc[2] - Xc[0]);
+  dy = 0.02*(Yc[2] - Yc[0]);
+  Xc[0] -= dx; Yc[0] -= dy;
+  Xc[1] += dx; Yc[1] -= dy;
+  Xc[2] += dx; Yc[2] += dy;
+  Xc[3] -= dx; Yc[3] += dy;
+  Xc[4] -= dx; Yc[4] -= dy;
+  Xc[5] -= dx; Yc[5] -= dy;
+
+  /* check if image datafile exists, get header, number of images */
+  if (!fits_read_header (ImageCat, &header)) {
+    fprintf (stderr, "ERROR: No images in catalog %s (1)\n", ImageCat);
+    exit (0);
+  }
+  Nimage = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+  if (Nimage == 0) {
+    fprintf (stderr, "ERROR: No images in catalog %s (1)\n", ImageCat);
+    exit (0);
+  }
+
+  /* get ready to read data on images */ 
+  f = fopen (ImageCat, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: trouble opening Image catalog: %s (2)\n", ImageCat);
+    exit (0);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* set up buffers for images, temporary storage */
+  NTIMAGE = 100;
+  ALLOCATE (timage, Image, NTIMAGE);
+  NIMAGE = 100;
+  ALLOCATE (image, Image, NIMAGE);
+  nimage = 0;
+  Nloop = Nimage / NTIMAGE + 1;
+  Nlast = Nimage % NTIMAGE;
+  
+  /* read in images in groups of NTIMAGE (100) */
+  for (n = 0; n < Nloop; n++) {
+    Nim = (n == Nloop - 1) ? Nlast : NTIMAGE;
+    status = Fread (timage, sizeof(Image), Nim, f, "image");
+    if (status != Nim) {
+      fprintf (stderr, "ERROR: couldn't read images from image catalog: %s\n", ImageCat);
+      exit (0);
+    }
+    /* test each image in block */
+    for (i = 0; i < Nim; i++) {
+      /* define image corners */
+      Xi[0] = 0;            Yi[0] = 0;
+      Xi[1] = timage[i].NX; Yi[1] = 0;
+      Xi[2] = timage[i].NX; Yi[2] = timage[i].NY;
+      Xi[3] = 0;            Yi[3] = timage[i].NY;
+      Xi[4] = 0;            Yi[4] = 0;
+      Xi[5] = timage[i].NX; Yi[5] = timage[i].NY;
+      found = FALSE;
+      /* transform to tcoords */
+      if (catstats[0].DEC[1] > 86.25) { /* pole */
+	for (j = 0; j < 6; j++) {
+	  XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+	  if (d > catstats[0].DEC[0] - 0.5) found = TRUE;
+	}
+      } else {
+	for (j = 0; j < 6; j++) {
+	  XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+	  RD_to_XY (&Xi[j], &Yi[j], r, d, tcoords);
+	}
+	/* check if edges cross */
+	for (j = 0; (j < 5) && !found; j++) {
+	  for (k = 0; (k < 5) && !found; k++) {
+	    found |= edge_check (&Xi[j], &Yi[j], &Xc[k], &Yc[k]);
+	  }
+	}
+      }
+      if (found) {
+	image[nimage] = timage[i]; 
+	image[nimage].code = 0;
+	nimage ++;
+	if (nimage == NIMAGE) {
+	  NIMAGE += 100;
+	  REALLOCATE (image, Image, NIMAGE);
+	}
+      }
+    }
+  }
+      
+  if (VERBOSE) { 
+    for (i = 0; i < nimage; i++) {
+      XY_to_RD (&r, &d, 0.5*image[i].NX, 0.5*image[i].NY, &image[i].coords);
+      fprintf (stderr, "associated images: %d %8.4f %8.4f %10d %6d  %5.3f %6.3f %6.3f\n", 
+	       i, r, d, image[i].tzero, image[i].nstar, 0.001*image[i].secz, 
+	       0.001*image[i].Mcal, 0.001*image[i].dMcal);
+    }
+  }
+
+  REALLOCATE (image, Image, MAX (nimage, 1));
+  free (timage);
+  *Nimages = nimage;
+  fclose (f);
+  return (image);
+}
+
+# if (OLDSTYLE)
+int edge_check (x1, y1, x2, y2)
+double *x1, *y1, *x2, *y2;
+{
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+double opening_angle (x1, y1, x2, y2, x3, y3)
+double x1, y1, x2, y2, x3, y3;
+{
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
+#else 
+
+int edge_check (x1, y1, x2, y2)
+double *x1, *y1, *x2, *y2;
+{
+
+  double dot;
+  double dx1, dx2, dy1, dy2, dx3, dy3, x, y;
+  double cross, L1, L3, d1, d2;
+
+  dx1 = x1[1] - x1[0]; dy1 = y1[1] - y1[0];
+  dx2 = x2[1] - x2[0]; dy2 = y2[1] - y2[0];
+
+  cross = dx2*dy1 - dx1*dy2;
+  
+  if (cross == 0) {  /* lines are parallel, are they inline? */
+    dx3 = x2[1] - x1[0]; dy2 = y2[1] - y1[0];
+    L1 = hypot (dx1,dy1);
+    L3 = hypot (dx3,dy3);
+
+    dot = fabs (dx1*dx3 + dy1*dy3) / (L1*L3);
+    if (dot == 1.0) { /* lines are inline, do they overlap? */
+      d1 = (x1[1]-x2[1])*(x1[1]-x2[0]) + (y1[1]-y2[1])*(y1[1]-y2[0]);
+      d2 = (x1[0]-x2[1])*(x1[0]-x2[0]) + (y1[0]-y2[1])*(y1[0]-y2[0]);
+      if (d1*d2 < 0) { /* lines overlap */
+	return (TRUE);
+      } else {
+	return (FALSE);
+      }
+    } else {
+      return (FALSE);
+    }
+  }
+
+  x = (dx1*dx2*(y2[0] - y1[0]) + (x1[0]*dy1*dx2 - x2[0]*dy2*dx1)) / cross;
+
+  if (dx1 != 0) {
+    y = y1[0] + (x - x1[0])*dy1/dx1;
+  } else {
+    y = y2[0] + (x - x2[0])*dy2/dx2;
+  }
+
+  d1 = (x - x1[0])*(x - x1[1]) + (y - y1[0])*(y - y1[1]);
+  d2 = (x - x2[0])*(x - x2[1]) + (y - y2[0])*(y - y2[1]);
+  if ((d1 > 0) || (d2 > 0)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+      
+
+#endif
+
Index: /tags/start/Ohana/src/fixcat/src/find_line.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/find_line.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/find_line.c	(revision 12606)
@@ -0,0 +1,161 @@
+# include "markstar.h"
+
+find_line (catstats, mark, Npts, i, M, B, Angle)
+     CatStats catstats[];
+     double *M, *B, Angle;
+     int i, Npts;
+     char *mark;
+{
+  
+  float *R, *D;
+  int j, N;
+  double X, Y, X2, Y2, XY, m, b, det;
+  double dR, dD, Ra, De, angle;
+  char Flipped;
+  
+  R = catstats[0].X;
+  D = catstats[0].Y;
+
+  /* fit a line to points near line */
+  Ra = R[i];
+  De = D[i];
+  X = Ra;
+  Y = De;
+  X2 = Ra*Ra;
+  Y2 = De*De;
+  XY = Ra*De;
+  N = 1;
+  /* points to the east */
+  for (j = i + 1; (j < Npts) && (R[j] - Ra < RADIUS); j++) {
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) continue;
+      if (angle < 0) angle += M_PI;
+      if (fabs(angle - Angle) < RAD_DEG) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* points to the west */
+  for (j = i - 1; !mark[i] && (j >= 0) && (Ra - R[j] < RADIUS); j--) {
+    if (mark[j]) continue;
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) continue;
+      if (angle < 0) angle += M_PI;
+      if (fabs(angle - Angle) < RAD_DEG) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* determine coeffs */
+  Flipped = 0;
+  det = 1.0 / (X2*N - X*X);
+  m = det * (XY*N - X*Y);
+  b = det * (X2*Y - XY*X);
+  if (fabs(m) > 1.1) { /* use a line of R = m*D + b instead */
+    /* fprintf (stderr, "high slope object: %f %f  -> ", m, b); */
+    det = 1.0 / (Y2*N - Y*Y);
+    m = det * (XY*N - X*Y);
+    b = det * (Y2*X - XY*Y);
+    Flipped = 1;
+    /* fprintf (stderr, "%f %f\n", m, b); */
+  }
+
+  *M = m;
+  *B = b;
+  return (Flipped);
+
+}
+
+
+find_better_line (catstats, mark, Npts, i, M, B, axis)
+     CatStats catstats[];
+     double *M, *B;
+     int i, Npts, axis;
+     char *mark;
+{
+  
+  float *R, *D;
+  int j, N;
+  double X, Y, X2, Y2, XY, m, b, det;
+  double dR, dD, Ra, De, delta;
+  
+  R = catstats[0].X;
+  D = catstats[0].Y;
+
+  /* fit a line to points near line */
+  Ra = R[i];
+  De = D[i];
+  X = Y = X2 = Y2 = XY = N = 0;
+  m = *M;  b = *B;
+
+  /* points to the east */
+  for (j = i; (j < Npts) && (R[j] - Ra < RADIUS); j++) {
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      if (axis == 1) 
+	delta = R[j] - m*D[j] - b;
+      else
+	delta = D[j] - m*R[j] - b;
+      if (fabs(delta) < 2*TRAIL_WIDTH) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* points to the west */
+  for (j = i - 1; (j >= 0) && (Ra - R[j] < RADIUS); j--) {
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      if (axis == 1) 
+	delta = R[j] - m*D[j] - b;
+      else
+	delta = D[j] - m*R[j] - b;
+      if (fabs(delta) < 2*TRAIL_WIDTH) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* determine coeffs */
+  if (axis == 0) {
+    det = 1.0 / (X2*N - X*X);
+    m = det * (XY*N - X*Y);
+    b = det * (X2*Y - XY*X);
+  } else {
+    det = 1.0 / (Y2*N - Y*Y);
+    m = det * (XY*N - X*Y);
+    b = det * (Y2*X - XY*Y);
+  }
+
+  /* fprintf (stderr, "%f %f %d\n", m, b, N); */
+
+  *M = m;
+  *B = b;
+
+}
Index: /tags/start/Ohana/src/fixcat/src/find_matches.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/find_matches.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/find_matches.c	(revision 12606)
@@ -0,0 +1,87 @@
+# include "markstar.h"
+
+find_matches (catalog, catstats, Ghostdata, Nimage)
+CatStats catstats[];
+Catalog catalog[], Ghostdata[];
+int Nimage;
+{
+
+  int i, j, k, n, m, N, M, first_j;
+  double X, Y, RADIUS, RADIUS2;
+  float *X1, *Y1, *X2, *Y2;
+  float dX, dY, dR;
+  int *N1, *N2;
+  int Nstar, Nghost, Ng;
+  unsigned int flags;
+  Coords *tcoords;
+
+  Nstar = catalog[0].Naverage;
+  Nghost = Ghostdata[0].Naverage;
+
+  if (Nghost < 1) return (0);
+
+  /* it is better to have the catalog with fewer stars
+     assigned to the X1 set */
+  X2 = catstats[0].X;
+  Y2 = catstats[0].Y;
+  N2 = catstats[0].N;
+
+  ALLOCATE (X1, float, Nghost);
+  ALLOCATE (Y1, float, Nghost);
+  ALLOCATE (N1, int, Nghost);
+
+  /* project ghosts to the frame of the catalog */
+  tcoords = &catstats[0].coords;
+  for (i = 0; i < Nghost; i++) {
+    fRD_to_XY (&X1[i], &Y1[i], Ghostdata[0].average[i].R, Ghostdata[0].average[i].D, tcoords);
+    N1[i] = i;
+  }
+  if (Nghost > 1) sort_lists (X1, Y1, N1, Nghost);
+
+  /* choose a radius for matches */
+  RADIUS2 = GHOST_RADIUS*GHOST_RADIUS;
+
+  /** find matched stars **/
+  for (i = j = 0; (i < Nghost) && (j < Nstar); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -2*GHOST_RADIUS) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*GHOST_RADIUS) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    for (; (dX > -2*GHOST_RADIUS) && (j < Nstar); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < RADIUS2) {  
+	/* this object may be a ghost star, 
+	   but only mark those measurements on the correct image */
+	M = N2[j];
+	m = catalog[0].average[M].offset;
+	Ng = 0;
+	for (k = 0; k < catalog[0].average[M].Nm; k++) {
+	  if (catalog[0].image[m+k] == Nimage) {
+	    catalog[0].measure[m+k].average |= GHOST_DATA;
+	    Ng ++;
+	  }
+	}
+	/* all measurements are ghosts */
+	if (catalog[0].average[M].Nm == Ng) {
+	  catalog[0].average[M].code = ID_GHOST;
+	}
+      }
+    }
+    j = first_j;
+    i++;
+  }
+
+  free (X1);
+  free (Y1);
+  free (N1);
+
+}
Index: /tags/start/Ohana/src/fixcat/src/find_trails.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/find_trails.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/find_trails.c	(revision 12606)
@@ -0,0 +1,41 @@
+# include "markstar.h"
+
+find_trails (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  int i, j, N, Nave, axis, marked;
+  double density, spacing, Area, Angle, m, b, RaCenter, DecCenter;
+  double MinRA, MaxRA, MinDEC, MaxDEC;
+  float *X1, *Y1;
+  char *mark;
+  int *N1;
+  Coords tcoords;
+  
+  Nave = catalog[0].Naverage;
+  N1 = catstats[0].N;
+
+  ALLOCATE (mark, char, Nave);
+  bzero (mark, Nave);
+
+  for (i = 0; i < Nave; i++) {
+    /* already marked, ignore */
+    if ((mark[i]) || 
+	(catalog[0].average[N1[i]].code == ID_BLEED) || 
+	(catalog[0].average[N1[i]].code == ID_GHOST))
+      continue;
+    /* a good star, ignore */
+    if ((catalog[0].average[N1[i]].Nm > 3) && 
+	(catalog[0].average[N1[i]].Nm > 4*catalog[0].average[N1[i]].Nn)) {
+      continue;
+    }
+    if (find_group (catstats, mark, Nave, i, &Angle)) {
+      /* this point has an excess nearby concentration, find the line */
+      axis = find_line (catstats, mark, Nave, i, &m, &b, Angle);
+      find_better_line (catstats, mark, Nave, i, &m, &b, axis);
+      mark_trail (catstats, mark, Nave, i, m, b, axis, catalog);
+    }
+  }
+}
+
Index: /tags/start/Ohana/src/fixcat/src/fixcat.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/fixcat.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/fixcat.c	(revision 12606)
@@ -0,0 +1,49 @@
+# include "markstar.h"
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  FILE *f;
+  int i, Nimages;
+  Image *image, *find_images();
+  Catalog catalog;
+  CatStats catstats;
+  struct timeval now, then;  
+  
+  gettimeofday (&then, (void *) NULL);
+  ConfigInit (argc, argv);
+
+  VERBOSE = FALSE;
+  if ((i = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  if (argc < 2) {
+    fprintf (stderr, "ERROR: Usage: fixcat (catalog)\n");
+    exit (0);
+  }
+
+  /* if lockfile exists, program will complain and quit */
+  check_lockfile (); 
+
+  gcatalog (argv[1], &catalog);
+
+  gcatstats (&catalog, &catstats);
+
+  image = find_images (&catstats, &Nimages);
+
+  match_images (&catalog, image, Nimages);
+    
+  find_funnymags (&catalog, image, Nimages);  
+
+  if (VERBOSE) {
+    gettimeofday (&now, (void *) NULL);
+    fprintf (stderr, "%s: elapsed time = %.2f sec\n", argv[1], 
+	     (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec));
+  }
+  clear_lockfile (); 
+  fprintf (stderr, "SUCCESS\n");
+}
+
Index: /tags/start/Ohana/src/fixcat/src/gcatalog.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/gcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/gcatalog.c	(revision 12606)
@@ -0,0 +1,108 @@
+# include "markstar.h"
+
+gcatalog (catname, catalog)
+char *catname;
+Catalog catalog[];
+{
+  
+  char filename[128], line[64];
+  int Nitems, nitems;
+  int i, Nmeas, Nmiss, done;
+  FILE *f;
+  struct tm *local;
+  struct timeval now;
+  unsigned int NotTrail;
+  unsigned short NotBad;
+
+  sprintf (filename, "%s/%s\0", CATDIR, catname);
+
+  /* read catalog header */
+  if (!fits_read_header (filename, &catalog[0].header)) {
+    fprintf (stderr, "ERROR: file doesn't exist %s\n", filename);
+    exit (0);
+  }
+
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't open catalog file: %s\n", filename);
+    exit (0);
+  }
+  fseek (f, catalog[0].header.size, SEEK_SET); 
+
+  /** find number of stars, measurements **/
+  catalog[0].Nmissing = catalog[0].Naverage = catalog[0].Nmeasure = 0;
+  fits_scan (&catalog[0].header, "NSTARS", "%d", 1, &catalog[0].Naverage);
+  fits_scan (&catalog[0].header, "NMEAS", "%d", 1, &catalog[0].Nmeasure);
+  fits_scan (&catalog[0].header, "NMISS", "%d", 1, &catalog[0].Nmissing);
+
+  ALLOCATE (catalog[0].average, Average, MAX (catalog[0].Naverage, 1));
+  ALLOCATE (catalog[0].measure, Measure, MAX (catalog[0].Nmeasure, 1));
+  ALLOCATE (catalog[0].missing, Missing, MAX (catalog[0].Nmissing, 1));
+  if (catalog[0].Naverage == 0) {
+    /* this is a valid ending state: no stars */
+    if (VERBOSE) fprintf (stderr, "SUCCESS: no stars yet in catalog %s\n", filename);
+    fclose (f);
+    clear_lockfile ();
+    exit (0);
+  }
+
+  /* read average values */
+  Nitems = catalog[0].Naverage;
+  nitems = Fread (catalog[0].average, sizeof(Average), Nitems, f, "average");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to read data from catalog file %s (1)\n", filename);
+    fclose (f);
+    exit (0);
+  }
+  
+  /* read measurements */
+  Nitems = catalog[0].Nmeasure;
+  nitems = Fread (catalog[0].measure, sizeof(Measure), Nitems, f, "measure");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to read data from catalog file %s (2)\n", filename);
+    fclose (f);
+    exit (0);
+  }
+  
+  /* read missing */
+  Nitems = catalog[0].Nmissing;
+  nitems = Fread (catalog[0].missing, sizeof(Missing), Nitems, f, "missing");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to read data from catalog file %s (3)\n", filename);
+    fclose (f);
+    exit (0);
+  }
+  
+  if (VERBOSE) fprintf (stderr, "read %d stars from catalog file %s (%d measurements, %d missing)\n", 
+	   catalog[0].Naverage, filename, catalog[0].Nmeasure, catalog[0].Nmissing);
+
+  for (i = Nmeas = Nmiss = 0; i < catalog[0].Naverage; i++) {
+    Nmeas += catalog[0].average[i].Nm; 
+    Nmiss += catalog[0].average[i].Nn; 
+  }
+  if ((Nmeas != catalog[0].Nmeasure) || (Nmiss != catalog[0].Nmissing)) {
+    fprintf (stderr, "ERROR: data in catalog %s is corrupt, sums don't check\n");
+    fprintf (stderr, "ERROR: Nmeas: %d, %d\n", Nmeas, catalog[0].Nmeasure);
+    fprintf (stderr, "ERROR: Nmiss: %d, %d\n", Nmiss, catalog[0].Nmissing);
+    exit (0);
+  }
+
+  if (RESET) {
+    NotBad = (0xffff ^ 0xc003);
+    for (i = 0; i < catalog[0].Naverage; i++) {
+      if ((catalog[0].average[i].code & ID_MOVING) &&
+	  (catalog[0].average[i].code & ID_BAD_OBJECT) &&
+	  (catalog[0].average[i].code & 0x0003)) {
+	/* this will set the correct bit for each to 0 */ 
+	catalog[0].average[i].code &= NotBad;
+      }
+    }
+    for (i = 0; i < catalog[0].Nmeasure; i++) {
+      catalog[0].measure[i].average &= ~PART_OF_TRAIL;
+    }
+  }
+
+
+  fclose (f);
+
+}
Index: /tags/start/Ohana/src/fixcat/src/gcatstats.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/gcatstats.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/gcatstats.c	(revision 12606)
@@ -0,0 +1,66 @@
+# include "markstar.h"
+
+gcatstats (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  int i;
+  double RaCenter, DecCenter;
+  double MinRA, MaxRA, MinDEC, MaxDEC;
+  float *X1, *Y1;
+  int *N1;
+  Coords tcoords;
+  
+  fits_scan (&catalog[0].header, "RA0", "%lf", 1, &MinRA);
+  fits_scan (&catalog[0].header, "RA1", "%lf", 1, &MaxRA);
+  fits_scan (&catalog[0].header, "DEC0", "%lf", 1, &MinDEC);
+  fits_scan (&catalog[0].header, "DEC1", "%lf", 1, &MaxDEC);
+
+  /* double check on region RA and DEC ranges */
+  DecCenter = 0.5*(MinDEC + MaxDEC);
+  RaCenter = 0.5*(MinRA + MaxRA);
+  if (MaxDEC > 86.25) {  /* we are on the pole */
+    DecCenter = 90.0;
+    RaCenter = 0.0;
+  }
+
+  catstats[0].RA[0] = MinRA;
+  catstats[0].RA[1] = MaxRA;
+  catstats[0].DEC[0] = MinDEC;
+  catstats[0].DEC[1] = MaxDEC;
+  catstats[0].Area = (MaxDEC - MinDEC)*(MaxRA - MinRA) / cos (RAD_DEG*DecCenter);
+  if (MaxDEC > 86.25) {  /* we are on the pole */
+    catstats[0].Area = 44.2;
+  }
+  catstats[0].density = catalog[0].Naverage / (3600*3600*catstats[0].Area);
+  catstats[0].spacing = 1.0 / (NSIGMA * catstats[0].density * 2*TRAIL_WIDTH);
+  fprintf (stderr, "Area, density, spacing: %f %f %f\n", catstats[0].Area, 
+	   catstats[0].density, catstats[0].spacing);
+  /* number of stars per square arcsec */
+
+  /** allocate local arrays **/
+  ALLOCATE (catstats[0].X, float, catalog[0].Naverage);
+  ALLOCATE (catstats[0].Y, float, catalog[0].Naverage);
+  ALLOCATE (catstats[0].N, int,   catalog[0].Naverage);
+
+  /* project onto rectilinear grid with 1 arcsec pixels, sort by X */
+  /* reference for coords is center of field  */
+  catstats[0].coords.crval1 = RaCenter;
+  catstats[0].coords.crval2 = DecCenter;
+  catstats[0].coords.crpix1 = catstats[0].coords.crpix2 = 0.0;
+  catstats[0].coords.cdelt1 = catstats[0].coords.cdelt2 = 1.0 / 3600.0;
+  catstats[0].coords.pc1_1 = catstats[0].coords.pc2_2 = 1.0;
+  catstats[0].coords.pc1_2 = catstats[0].coords.pc2_1 = 0.0;
+  strcpy (catstats[0].coords.ctype, "RA---TAN");
+
+  X1 = catstats[0].X;
+  Y1 = catstats[0].Y;
+  for (i = 0; i < catalog[0].Naverage; i++, X1++, Y1++) {
+    fRD_to_XY (X1, Y1, catalog[0].average[i].R, catalog[0].average[i].D, &catstats[0].coords);
+    catstats[0].N[i] = i;
+  }
+  if (catalog[0].Naverage > 1) sort_lists (catstats[0].X, catstats[0].Y, catstats[0].N, catalog[0].Naverage);
+  
+}
+
Index: /tags/start/Ohana/src/fixcat/src/gregions.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/gregions.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/gregions.c	(revision 12606)
@@ -0,0 +1,134 @@
+# include "markstar.h"
+
+GSCRegion *gregions1 (catstats, Nregions)
+CatStats catstats[];
+int *Nregions;
+{
+  
+  GSCRegion *region;
+  int i, j, k, x, y, done, nregion, nregion2, NREGION;
+  double ra, dec, dx, dy, Xo[4], Yo[4];
+  FILE *f;
+
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: could not open GSC region file %s\n", GSCFILE);
+    exit (0);
+  }
+  nregion = 0;
+  NREGION = 10;
+  ALLOCATE (region, GSCRegion, NREGION);
+
+  if (catstats[0].DEC[0] == 86.25) { /* pole region */
+    dec = 86.0;
+    for (ra = 0.1; ra < 370; ra+= 30.0) {
+      aregion (&region[nregion], f, ra, dec);
+      done = FALSE;
+      for (j = 0; (j < nregion - 1) && !done; j++) {
+	if (!strcmp (region[nregion].filename, region[j].filename)) {
+	  nregion --;
+	  done = TRUE;
+	}
+      }
+      nregion ++;
+      if (nregion == NREGION) {
+	NREGION += 10;
+	REALLOCATE (region, GSCRegion, NREGION);
+      }
+    }
+  } else {
+    for (x = 0; x < 2; x++) {
+      for (y = 0; y < 2; y++) {
+	for (dx = -0.1; dx <= 0.1; dx += 0.2) {
+	  for (dy = -0.1; dy <= 0.1; dy += 0.2) {
+	    ra  = catstats[0].RA[x] + dx;
+	    dec = catstats[0].DEC[y] + dy;
+	    aregion (&region[nregion], f, ra, dec);
+	    done = FALSE;
+	    for (j = 0; (j < nregion) && !done; j++) {
+	      if (!strcmp (region[nregion].filename, region[j].filename)) {
+		done = TRUE;
+	      }
+	    }
+	    if (!done) {
+	      nregion ++;
+	    } 
+	    if (nregion == NREGION) {
+	      NREGION += 10;
+	      REALLOCATE (region, GSCRegion, NREGION);
+	    }
+	  }
+	}
+      }
+    }
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "using %d regions\n", nregion);
+    for (i = 0; i < nregion; i++) {
+      fprintf (stderr, "region %d: %f %f  %f %f\n", i, region[i].RA[0], region[i].RA[1], region[i].DEC[0], region[i].DEC[1]);
+    } 
+  }
+
+  REALLOCATE (region, GSCRegion, MAX (nregion, 1));
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (region);
+  
+}
+
+GSCRegion *gregions2 (image, Nregions)
+Image *image;
+int *Nregions;
+{
+  
+  GSCRegion *region;
+  FILE *f;
+  double x, y;
+  double dr, dd, dec, ra;
+  int i, j, done, nregion, NREGION;
+  
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find GSC region file %s\n", GSCFILE);
+    exit (0);
+  }
+  
+  /* find regions at image corners */
+  NREGION = 10;
+  ALLOCATE (region, GSCRegion, NREGION);
+  nregion = 0;
+
+  /* look for new regions on grid across image */ 
+  for (x = 0.0; x <= 1.0; x+=0.25) {
+    for (y = 0.0; y <= 1.0; y+=0.25) {
+      XY_to_RD (&ra, &dec, image[0].NX*(1.1*x - 0.05), image[0].NY*(1.1*y - 0.05), &image[0].coords);
+      aregion (&region[nregion], f, ra, dec);
+      done = FALSE;
+      for (j = 0; (j < nregion) && !done; j++) {
+	if (!strcmp (region[nregion].filename, region[j].filename)) {
+	  nregion --;
+	  done = TRUE;
+	}
+      }
+      nregion ++;
+      if (nregion == NREGION) {
+	NREGION += 10;
+	REALLOCATE (region, GSCRegion, NREGION);
+      }
+    }
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "found %d region files:\n", nregion);
+    for (i = 0; i < nregion; i++) {
+      fprintf (stderr, "  %d %s\n", i, region[i].filename);
+    }
+  }
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (region);
+  
+}
Index: /tags/start/Ohana/src/fixcat/src/load_gsc_data.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/load_gsc_data.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/load_gsc_data.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include "markstar.h"
+# define NBYTES 160000
+# define BYTES_STAR 23
+# define BLOCK 1000
+# define DNSTARS 1000
+
+load_gsc_data (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  /* load data from the GSC files */
+  char filename[128];
+  char *tbuffer;
+  int nstar, NSTARS;
+  int i, j, Nbytes, nbytes, Nregions;
+  double R, D, M, MagLimit;
+  FILE *f;
+  GSCRegion *region, *gregions1(), *gregions2();
+  
+  region = gregions1 (catstats, &Nregions);
+
+  MagLimit = MAX (MAX (BRIGHT_HALO_MAG, BRIGHT_XTRAIL_MAG), BRIGHT_YTRAIL_MAG); 
+  nstar = 0;
+  NSTARS = DNSTARS;
+  ALLOCATE (tbuffer, char, (BLOCK*BYTES_STAR));
+  ALLOCATE (catalog[0].average, Average, NSTARS);
+  Nbytes = BLOCK*BYTES_STAR;
+  
+  for (j = 0; j < Nregions; j++) {
+    f = fopen (region[j].filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "GSC file for region %s missing\n", region[j].filename);
+      exit (0);
+    }
+    
+    while ((nbytes = fread (tbuffer, 1, Nbytes, f)) > 0) {
+      for (i = 0; i < nbytes / BYTES_STAR; i++) {
+	dparse (&M, 3, &tbuffer[i*BYTES_STAR]);
+	if (M > MagLimit) continue;
+	dparse (&R, 1, &tbuffer[i*BYTES_STAR]);
+	dparse (&D, 2, &tbuffer[i*BYTES_STAR]);
+	catalog[0].average[nstar].R = R;
+	catalog[0].average[nstar].D = D;
+	catalog[0].average[nstar].M = M * 1000.0;
+	nstar++;
+	if (nstar == NSTARS - 1) {
+	  NSTARS += DNSTARS;
+	  REALLOCATE (catalog[0].average, Average, NSTARS);
+	}
+      }
+    }
+    fclose (f);
+  }
+
+  free (tbuffer);
+  REALLOCATE (catalog[0].average, Average, nstar);
+  catalog[0].Naverage = nstar;
+  
+}
+
Index: /tags/start/Ohana/src/fixcat/src/load_gsc_data_ghost.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/load_gsc_data_ghost.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/load_gsc_data_ghost.c	(revision 12606)
@@ -0,0 +1,75 @@
+# include "markstar.h"
+# define NBYTES 160000
+# define BYTES_STAR 23
+# define BLOCK 1000
+# define DNSTARS 1000
+
+/* this routine is basically identical to load_gsc_data, but
+   it is not limited to a single region file, and it merges the 
+   results */
+
+load_gsc_data_ghost (catalog, region, Nregion, image)
+Catalog catalog[];
+GSCRegion *region;
+int Nregion;
+Image image[];
+{
+
+  /* load data from the GSC files */
+  char filename[128];
+  char *tbuffer;
+  int nstar, NSTARS;
+  int i, j, Nbytes, nbytes;
+  double R, D, M, X, Y;
+  FILE *f;
+  Coords *tcoords;
+  int MinX, MinY, MaxX, MaxY;
+  
+  nstar = 0;
+  NSTARS = DNSTARS;
+  ALLOCATE (tbuffer, char, (BLOCK*BYTES_STAR));
+  ALLOCATE (catalog[0].average, Average, NSTARS);
+  tcoords = &image[0].coords;
+  MinX = 0;
+  MinY = 0;
+  MaxX = image[0].NX;
+  MaxY = image[0].NY;
+  
+  for (j = 0; j < Nregion; j++) {
+    
+    f = fopen (region[j].filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "no GSC file for region %s (2)\n", region[j].filename);
+      exit (0);
+    }
+    
+    Nbytes = BLOCK*BYTES_STAR;
+    while ((nbytes = fread (tbuffer, 1, Nbytes, f)) > 0) {
+      for (i = 0; i < nbytes / BYTES_STAR; i++) {
+	dparse (&M, 3, &tbuffer[i*BYTES_STAR]);
+	if (M > GHOST_MAG) continue;
+	dparse (&R, 1, &tbuffer[i*BYTES_STAR]);
+	dparse (&D, 2, &tbuffer[i*BYTES_STAR]);
+	RD_to_XY (&X, &Y, R, D, tcoords);
+	if ((X < MinX) || (X > MaxX) || (Y < MinY) || (Y > MaxY)) continue;
+	catalog[0].average[nstar].R = R;
+	catalog[0].average[nstar].D = D;
+	catalog[0].average[nstar].M = M * 1000.0;
+	nstar++;
+	if (nstar == NSTARS - 1) {
+	  NSTARS += DNSTARS;
+	  REALLOCATE (catalog[0].average, Average, NSTARS);
+	}
+      }
+    }
+    fclose (f);
+
+  }
+
+  free (tbuffer);
+  REALLOCATE (catalog[0].average, Average, MAX (nstar, 1));
+  catalog[0].Naverage = nstar;
+
+}
+
+
Index: /tags/start/Ohana/src/fixcat/src/mark_trail.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/mark_trail.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/mark_trail.c	(revision 12606)
@@ -0,0 +1,272 @@
+# include "markstar.h"
+int *make_common_list ();
+int *check_common_list ();
+
+mark_trail (catstats, mark, Nave, i, m, b, axis, catalog)
+     CatStats catstats[];
+     char *mark;
+     int i, Nave, axis;
+     double m, b;
+     Catalog catalog[];
+{
+
+  float *R, *D;
+  int j, k, jj, kk, N, NPTS, marked, start, end, Nm;
+  int *good, *seq, *N1;
+  double *dist, *dist2;
+  double d2, di, Di, dD, n, Dist, scale, norm;
+  double spacing;
+  int *list, Nlist;
+  int M, Nmeas, thisimage;
+
+  R = catstats[0].X;
+  D = catstats[0].Y;
+  N1 = catstats[0].N;
+  spacing = catstats[0].spacing;
+
+  NPTS = 200;
+  ALLOCATE (good, int, NPTS);
+  ALLOCATE (dist, double, NPTS);
+  ALLOCATE (dist2, double, NPTS);
+  ALLOCATE (seq, int, NPTS);
+
+  /* Find all points which lie near line */
+  /* save the entry number and distance along line */
+  N = 0;
+  scale = sqrt (1.0 + m*m);
+
+  if (axis == 1) {
+    for (j = 0; j < Nave; j++) {
+      norm = scale * fabs(R[j] - m*D[j] - b);
+      if (!mark[j] && (norm < TRAIL_WIDTH)) {
+	good[N] = j;
+	dist[N] = scale * (D[j] - D[i] + m*(R[j] - R[i]));
+	seq[N] = N;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 200;
+	  REALLOCATE (good, int, NPTS);
+	  REALLOCATE (dist, double, NPTS);
+	  REALLOCATE (dist2, double, NPTS);
+	  REALLOCATE (seq, int, NPTS);
+	}
+      }
+    }
+  } else {
+    for (j = 0; j < Nave; j++) {
+      norm = scale * fabs(D[j] - m*R[j] - b);
+      if (!mark[j] && (norm < TRAIL_WIDTH)) {
+	good[N] = j;
+	dist[N] = scale * (R[j] - R[i] + m*(D[j] - D[i]));
+	seq[N] = N;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 200;
+	  REALLOCATE (good, int, NPTS);
+	  REALLOCATE (dist, double, NPTS);
+	  REALLOCATE (dist2, double, NPTS);
+	  REALLOCATE (seq, int, NPTS);
+	}
+      }
+    }
+  }
+  
+  if (N < NPTSINLINE) 
+    return (0);
+
+  sort_seq (dist, seq, N);
+  
+  start = -1; end = -1;
+  for (j = 0; j < N-1; j++) {
+    /* if we have part of a line, and next point is in the line, check for common images */
+    if ((start != -1) && (fabs(dist[j] - dist[j+1]) < spacing)) {
+      list = check_common_list (list, N1[good[seq[j+1]]], &Nlist, catalog);
+      if (Nlist == 0) { /* if no common images, dump list and continue */
+	end = j + 1;
+	if (end - start > NPTSINLINE) {
+	  if (axis == 0)
+	    fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", m, b, N, end-start, start, end, dist[start], dist[end-1]);
+	  else
+	    fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", 1.0/m, -1.0*b/m, N, end-start, start, end, dist[start], dist[end-1]);
+	  for (k = start; k < end; k++) {
+	    M = N1[good[seq[k]]];
+	    mark[good[seq[k]]] = TRUE;
+	    /* we need to mark measurements from all images in common on the line */
+	    Nm = 0;
+	    for (jj = 0; jj < catalog[0].average[M].Nm; jj++) {
+	      Nmeas = catalog[0].average[M].offset + jj;
+	      thisimage = catalog[0].image[Nmeas];
+	      for (kk = 0; kk < Nlist; kk++) {
+		if (thisimage == list[kk]) {
+		  catalog[0].measure[Nmeas].average |= PART_OF_TRAIL;
+		  Nm ++;
+		}
+	      }
+	    }
+	    /* if there is only 1 measurement, mark object as bad */
+	    if (catalog[0].average[M].Nm == Nm) {
+	      catalog[0].average[M].code = ID_TRAIL;
+	    }
+	    catalog[0].average[M].code = ID_TRAIL;
+	  }
+	}
+	start = -1;
+	end = -1;
+      }
+    }
+    /* if we haven't yet found a line segment, check for the beginning */
+    if ((start < 0) && (fabs(dist[j] - dist[j+1]) < spacing)) {
+      start = j;
+      list = make_common_list (N1[good[seq[j]]], N1[good[seq[j+1]]], &Nlist, catalog);
+      if (Nlist == 0) { /* if no common images, move on */
+	start = -1;
+	free (list);
+      }
+    }
+    /* if we have a complete line, check for validity.  if it has enough members,
+	 mark them and continue searching for lines */
+    if ((start != -1) && ((fabs(dist[j] - dist[j+1]) >= spacing) || (j == N-2))) {
+      end = j + 1;
+      if (end - start > NPTSINLINE) {
+	if (axis == 0)
+	  fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", m, b, N, end-start, start, end, dist[start], dist[end-1]);
+	else
+	  fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", 1.0/m, -1.0*b/m, N, end-start, start, end, dist[start], dist[end-1]);
+	for (k = start; k < end; k++) {
+	  M = N1[good[seq[k]]];
+	  mark[good[seq[k]]] = TRUE;
+	  if (catalog[0].average[M].code == ID_BLEED) continue;
+	  /* we need to mark measurements from all images in common on the line */
+	  Nm = 0;
+	  for (jj = 0; jj < catalog[0].average[M].Nm; jj++) {
+	    Nmeas = catalog[0].average[M].offset + jj;
+	    thisimage = catalog[0].image[Nmeas];
+	    for (kk = 0; kk < Nlist; kk++) {
+	      if (thisimage == list[kk]) {
+		catalog[0].measure[Nmeas].average |= PART_OF_TRAIL;
+		Nm ++;
+	      }
+	    }
+	  }
+	  /* if there is only 1 measurement, mark object as bad */
+	  if (catalog[0].average[M].Nm == Nm) {
+	    catalog[0].average[M].code = ID_TRAIL;
+	  }
+	  catalog[0].average[M].code = ID_TRAIL;
+	}
+      }
+      free (list);
+      start = -1;
+      end = -1;
+    }
+  }
+}
+
+
+/* I is Average seq number for star 1, J for star 2 */
+/* make a list of images in common between two measurements */
+int *make_common_list (I, J, Nlist, catalog)
+int I, J, *Nlist;
+Catalog catalog[];
+{
+
+  int i, j, N1, N2, nlist, NLIST;
+  int *list;
+  int k, already;
+
+  NLIST = 50;
+  ALLOCATE (list, int, NLIST);
+  nlist = 0;
+
+  for (i = 0; i < catalog[0].average[I].Nm; i++) {
+    N1 = catalog[0].average[I].offset + i;
+    if (catalog[0].image[N1] == -1)
+      continue; /* not a real measurement */
+    for (j = 0; j < catalog[0].average[J].Nm; j++) {
+      N2 = catalog[0].average[J].offset + j;
+      if (catalog[0].image[N2] == -1)
+	continue; /* not a real measurement */
+      if (catalog[0].image[N1] == catalog[0].image[N2]) {
+	already = FALSE; 
+	for (k = 0; !already && (k < nlist); k++) {
+	  if (catalog[0].image[N1] == list[k]) { 
+	    already = TRUE;
+	  }
+	}
+	if (!already) {
+	  list[nlist] = catalog[0].image[N1];
+	  nlist ++;
+	  if (nlist == NLIST - 1) {
+	    NLIST += 50;
+	    REALLOCATE (list, int, NLIST);
+	  }
+	}
+      }
+    }
+  }
+  
+  REALLOCATE (list, int, MAX(nlist, 1));
+  *Nlist = nlist;
+  return (list);
+
+}
+
+
+
+/* J is Average seq number for star */
+
+int *check_common_list (inlist, J, Nlist, catalog)
+int *inlist, J, *Nlist;
+Catalog catalog[];
+{
+
+  int i, j, N2, Ninlist;
+  int *list, NLIST, nlist;
+  int already, found, k;
+
+  NLIST = 50;
+  ALLOCATE (list, int, NLIST);
+  nlist = 0;
+  Ninlist = *Nlist;
+
+  for (j = 0; j < catalog[0].average[J].Nm; j++) {
+    N2 = catalog[0].average[J].offset + j;
+    found = FALSE;
+    for (i = 0; !found && (i < Ninlist); i++) {
+      if (catalog[0].image[N2] == -1)
+	continue; /* not a real measurement */
+      if (inlist[i] == catalog[0].image[N2]) {
+	found = TRUE;
+	already = FALSE; 
+	for (k = 0; !already && (k < nlist); k++) {
+	  if (inlist[i] == list[k]) {
+	    already = TRUE;
+	  }
+	}
+	if (!already) {
+	  list[nlist] = inlist[i];
+	  nlist ++;
+	  if (nlist == NLIST - 1) {
+	    NLIST += 50;
+	    REALLOCATE (list, int, NLIST);
+	  }
+	}
+      }
+    }
+  }
+  
+  /* if there are no common images, return the input list */
+  if (nlist != 0) {
+    free (inlist);
+    REALLOCATE (list, int, MAX(nlist, 1));
+    *Nlist = nlist;
+    return (list);
+  } else {
+    return (inlist);
+  }
+
+}
+
+
+/* measurements associated with image number -1 are not 
+   measurements we made, but are added, like USNO */
Index: /tags/start/Ohana/src/fixcat/src/markstar.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/markstar.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/markstar.c	(revision 12606)
@@ -0,0 +1,66 @@
+# include "markstar.h"
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  FILE *f;
+  int i, Nstars, Nimage, Nregions, Nmissed;
+  Image *image, *find_images();
+  Catalog catalog;
+  CatStats catstats;
+  struct timeval now, then;  
+  
+  gettimeofday (&then, (void *) NULL);
+  ConfigInit (argc, argv);
+
+  VERBOSE = FALSE;
+  if ((i = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  FORCE_RUN = FALSE;
+  if ((i = get_argument (argc, argv, "-f"))) {
+    FORCE_RUN = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  RESET = FALSE;
+  if ((i = get_argument (argc, argv, "-reset"))) {
+    RESET = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  if (argc < 2) {
+    fprintf (stderr, "ERROR: Usage: markstar (catalog)\n");
+    exit (0);
+  }
+
+  /* if lockfile exists, program will complain and quit */
+  check_lockfile (); 
+  check_permissions (argv[1]);
+
+  gcatalog (argv[1], &catalog);
+
+  gcatstats (&catalog, &catstats);
+
+  image = find_images (&catstats, &Nimage);
+
+  match_images (&catalog, image, Nimage);
+    
+  find_bright_stars (&catalog, &catstats); 
+
+  find_ghosts (&catalog, &catstats, argv[1], image, Nimage);  
+
+  find_trails (&catalog, &catstats);  
+
+  wcatalog (argv[1], &catalog);
+
+  if (VERBOSE) {
+    gettimeofday (&now, (void *) NULL);
+    fprintf (stderr, "%s: elapsed time = %.2f sec\n", argv[1], 
+	     (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec));
+  }
+  clear_lockfile (); 
+  fprintf (stderr, "SUCCESS\n");
+}
+
Index: /tags/start/Ohana/src/fixcat/src/match_images.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/match_images.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/match_images.c	(revision 12606)
@@ -0,0 +1,57 @@
+# include "markstar.h"
+
+match_images (catalog, image, Nimage)
+Catalog catalog[];
+Image   image[];
+int Nimage;
+{
+  
+  int j, k, found;
+  unsigned int *start, *stop;
+
+  /* this must be allocated so future free will not fail */
+  ALLOCATE (catalog[0].image, int, MAX (catalog[0].Nmeasure, 1));
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (FALSE);
+  }
+
+  ALLOCATE (start, unsigned int, Nimage);
+  ALLOCATE (stop,  unsigned int, Nimage);
+  for (j = 0; j < Nimage; j++) {
+    start[j] = image[j].tzero - MAX(0.05*image[j].trate*image[j].NY, 1);
+    stop[j]  = image[j].tzero + MAX(1.05*image[j].trate*image[j].NY, 1);
+  }
+
+  for (j = 0; j < catalog[0].Nmeasure; j++) {
+    found = FALSE;
+    if (catalog[0].measure[j].t == 0) {
+      catalog[0].image[j] = -1;
+      found = TRUE;
+    }
+    for (k = 0; (k < Nimage) && !found; k++) {
+      if ((catalog[0].measure[j].t >= start[k]) && 
+	  (catalog[0].measure[j].t <= stop[k])) {
+	catalog[0].image[j] = k;
+	found = TRUE;
+      }
+    }
+    if (!found) {
+      fprintf (stderr, "ERROR: can't find source image for this measurement: %d\n",
+	       catalog[0].measure[j].t);
+      exit (0);
+    }
+  }
+  free (start);
+  free (stop);
+}
+
+  /* this routine uses the time of each measurement to match the
+measurement with an image.  Since the measurement is only store to 1
+sec accuracy, which corresponds to roughly 30 rows at nominal speed,
+we can't tell exactly which image the star come from.  However, this
+doesn't matter, and in fact this helps a bit: a measurement from the
+top of one image is the same as from the bottom of the next.
+Therefore, we intentionally blur the edges of the images by 5%, which
+will help to tie together neighboring images... */
+
Index: /tags/start/Ohana/src/fixcat/src/sorts.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/sorts.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/sorts.c	(revision 12606)
@@ -0,0 +1,175 @@
+
+
+sort_lists (X, Y, S, N) 
+float *X, *Y;
+int *S, N;
+{
+  int l,j,ir,i;
+  double tX, tY, tS;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    S[i] = tS;
+  }
+}
+
+sort_entries (X, Y, N) 
+     double *X, *Y;
+     int N;
+{
+  int l,j,ir,i;
+  double tX, tY;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+  }
+}
+
+
+
+sort (X, N) 
+     double *X;
+     int N;
+{
+  int l,j,ir,i;
+  double tX;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+  }
+}
+
+
+sort_seq (X, S, N) 
+     double *X;
+     int *S;
+     int N;
+{
+  int l,j,ir,i;
+  int tS;
+  double tX;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    S[i] = tS;
+  }
+}
+
Index: /tags/start/Ohana/src/fixcat/src/wcatalog.c
===================================================================
--- /tags/start/Ohana/src/fixcat/src/wcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/fixcat/src/wcatalog.c	(revision 12606)
@@ -0,0 +1,74 @@
+# include "markstar.h"
+
+wcatalog (catname, catalog)
+char *catname;
+Catalog catalog[];
+{
+  
+  int i, Nitems, nitems, status, mode;
+  char filename[128], line[256];
+  FILE *f;
+  struct stat filestat;
+
+  sprintf (filename, "%s/%s\0", CATDIR, catname);
+
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, make backup copy */
+    sprintf (line, "mv %s %s~\0", filename, filename);
+    status = system (line);
+    if (status) {
+      fprintf (stderr, "ERROR: unable to create %s~, exiting\n", filename);
+      exit (0);
+    }
+  }
+
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (FALSE);
+  }
+  
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't create new catalog file: %s\n", filename);
+    exit (0);
+  }
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  chmod (filename, mode);
+  
+  fits_modify (&catalog[0].header, "NSTARS", "%d", 1, catalog[0].Naverage);
+  fits_modify (&catalog[0].header, "NMEAS", "%d", 1, catalog[0].Nmeasure);
+  fits_modify (&catalog[0].header, "NMISS", "%d", 1, catalog[0].Nmissing);
+
+  fits_modify (&catalog[0].header, "MARKSTAR", "%t", 1, TRUE);
+
+  nitems = Fwrite (catalog[0].header.buffer, 1, catalog[0].header.size, f, "char");
+  if (nitems != catalog[0].header.size) {
+    fprintf (stderr, "ERROR: failed to write header\n");
+    exit (0);
+  }
+
+  Nitems = catalog[0].Naverage;
+  nitems = Fwrite (catalog[0].average, sizeof(Average), Nitems, f, "average");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to write catalog file aves %s\n", filename);
+    exit (0);
+  }
+  
+  Nitems = catalog[0].Nmeasure;
+  nitems = Fwrite (catalog[0].measure, sizeof(Measure), Nitems, f, "measure");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to write catalog file meas %s\n", filename);
+    exit (0);
+  }
+
+  Nitems = catalog[0].Nmissing;
+  nitems = Fwrite (catalog[0].missing, sizeof(Missing), Nitems, f, "missing");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to write catalog file miss %s\n", filename);
+    exit (0);
+  }
+
+  fclose (f);
+
+}
+
Index: /tags/start/Ohana/src/gastro/Makefile
===================================================================
--- /tags/start/Ohana/src/gastro/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/gastro/Makefile	(revision 12606)
@@ -0,0 +1,158 @@
+include ../../Configure
+HOME 	=	$(ROOT)/src/gastro
+CONFIG  =	$(ROOT)/config
+
+default: gastro
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#  
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lFITS -lsocket -lnsl -lohana -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS)
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+OBJS	= \
+$(SRC)/get_stars.$(ARCH).o 		$(SRC)/delta.$(ARCH).o        \
+$(SRC)/line_fit.$(ARCH).o 		$(SRC)/ranges.$(ARCH).o       \
+$(SRC)/find_shift.$(ARCH).o 		
+
+# 
+# -----------------------
+EOBJ	= \
+$(SRC)/extract.$(ARCH).o 		$(SRC)/extract_catalog.$(ARCH).o \
+$(SRC)/precess.$(ARCH).o		$(SRC)/stats.$(ARCH).o
+
+
+$(EOBJ):  $(INC)/astro.h
+
+extract: $(BIN)/extract
+
+$(BIN)/extract: $(EOBJ)
+	$(CC) $(EOBJ) -o $(BIN)/extract $(CCFLAGS) 
+
+install.extract:
+	rm -f $(DESTBIN)/extract
+	cp $(BIN)/extract   $(DESTBIN)/
+# -----------------------
+SOBJ	= \
+$(SRC)/simulate.$(ARCH).o 		$(SRC)/gregions2.$(ARCH).o \
+$(SRC)/gcatalog.$(ARCH).o		$(SRC)/coordops.$(ARCH).o \
+$(SRC)/gproject.$(ARCH).o		$(SRC)/gaussian.$(ARCH).o
+
+$(SOBJ):  $(INC)/astro.h
+
+simulate: $(BIN)/simulate.$(ARCH)
+
+$(BIN)/simulate: $(SOBJ)
+	$(CC) $(SOBJ) -o $(BIN)/simulate.$(ARCH) $(CCFLAGS) 
+
+install.simulate:
+	rm -f $(DESTBIN)/simulate
+	cp $(BIN)/simulate.$(ARCH) $(DESTBIN)/simulate
+
+# -----------------------
+GOBJ	= \
+$(SRC)/gastro.$(ARCH).o 		$(SRC)/gstars.$(ARCH).o \
+$(SRC)/gargs.$(ARCH).o			$(SRC)/gregions2.$(ARCH).o \
+$(SRC)/gcatalog.$(ARCH).o		\
+$(SRC)/gcenter.$(ARCH).o		$(SRC)/granges.$(ARCH).o  \
+$(SRC)/gfit.$(ARCH).o			$(SRC)/rotate.$(ARCH).o   \
+$(SRC)/gproject.$(ARCH).o		$(SRC)/gheader.$(ARCH).o  \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/sort.$(ARCH).o			$(SRC)/gfitpoly.$(ARCH).o \
+$(SRC)/gaussj.$(ARCH).o \
+$(SRC)/get_region_coords.$(ARCH).o \
+$(SRC)/greference.$(ARCH).o		$(SRC)/getusno.$(ARCH).o	\
+$(SRC)/plotstuff.$(ARCH).o		$(SRC)/gptolemy.$(ARCH).o	\
+$(SRC)/g2mass.$(ARCH).o			$(SRC)/misc.$(ARCH).o
+
+$(GOBJ):  $(INC)/gastro.h
+
+gastro: $(BIN)/gastro.$(ARCH)
+
+$(BIN)/gastro.$(ARCH): $(GOBJ)
+	$(CC) $(GOBJ) -o $(BIN)/gastro.$(ARCH) $(CCFLAGS) 
+
+install.gastro: $(DESTBIN)/gastro
+
+$(DESTBIN)/gastro: $(BIN)/gastro.$(ARCH)
+	rm -f $(DESTBIN)/gastro
+	cp $(BIN)/gastro.$(ARCH)   $(DESTBIN)/gastro
+# -----------------------
+DOBJ	= \
+$(SRC)/gscdump.$(ARCH).o 		$(SRC)/gstars.$(ARCH).o \
+$(SRC)/gargs.$(ARCH).o			$(SRC)/gregions2.$(ARCH).o \
+$(SRC)/gcatalog.$(ARCH).o		$(SRC)/coordops.$(ARCH).o \
+$(SRC)/gcenter.$(ARCH).o		$(SRC)/granges.$(ARCH).o  \
+$(SRC)/gfit.$(ARCH).o			$(SRC)/rotate.$(ARCH).o   \
+$(SRC)/gproject.$(ARCH).o		$(SRC)/gheader.$(ARCH).o  \
+$(SRC)/config.$(ARCH).o			$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/sort.$(ARCH).o
+
+$(DOBJ):  $(INC)/gastro.h
+
+gscdump: $(BIN)/gscdump.$(ARCH)
+
+$(BIN)/gscdump.$(ARCH): $(DOBJ)
+	$(CC) $(DOBJ) -o $(BIN)/gscdump.$(ARCH) $(CCFLAGS) 
+
+install.gscdump: $(DESTBIN)/gscdump
+
+$(DESTBIN)/gscdump: $(BIN)/gscdump.$(ARCH)
+	rm -f $(DESTBIN)/gscdump
+	cp $(BIN)/gscdump.$(ARCH)   $(DESTBIN)/gscdump
+# -----------------------
+AOBJ	= $(OBJS) \
+$(SRC)/stats.$(ARCH).o 			$(SRC)/astro.$(ARCH).o \
+$(SRC)/get_catalog_stars.$(ARCH).o 	$(SRC)/extract_catalog.$(ARCH).o \
+$(SRC)/precess.$(ARCH).o		$(SRC)/alter_header.$(ARCH).o \
+$(SRC)/args.$(ARCH).o			
+
+$(AOBJ):  $(INC)/astro.h
+
+astro: $(BIN)/astro
+
+$(BIN)/astro: $(AOBJ)
+	$(CC) $(AOBJ) -o $(BIN)/astro $(CCFLAGS) 
+
+# -----------------------
+ROBJ	= $(OBJS) \
+$(SRC)/rastro.$(ARCH).o 		$(SRC)/ralter_header.$(ARCH).o \
+$(SRC)/rargs.$(ARCH).o			$(SRC)/get_argument.$(ARCH).o \
+$(SRC)/remove_argument.$(ARCH).o
+
+$(ROBJ):  $(INC)/astro.h
+
+rastro: $(BIN)/rastro
+
+$(BIN)/rastro: $(ROBJ)
+	$(CC) $(ROBJ) -o $(BIN)/rastro $(CCFLAGS) 
+
+# -----------------------
+install: install.gastro
+
+clean:
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+dist: clean
+	rm -f $(BIN)/astro
+	rm -f $(BIN)/rastro
+
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
+
+
Index: /tags/start/Ohana/src/gastro/include/astro.h
===================================================================
--- /tags/start/Ohana/src/gastro/include/astro.h	(revision 12606)
+++ /tags/start/Ohana/src/gastro/include/astro.h	(revision 12606)
@@ -0,0 +1,63 @@
+# include <ohana.h>
+
+# define DEFAULT_RADIUS  8.0    /* rough search radius, pixels */
+# define DEFAULT_NPIX   100
+# define CCD_NX 2048  /* CCD width -- not used, determined from header */
+# define CCD_NY 4096  /* CCD height -- not used, determined from header  */
+# define CCD_PC1_1 1  /* CCD orientation */
+# define CCD_PC2_2 -1
+# define CCD_PC1_2 0
+# define CCD_PC2_1 0
+# define CCD_DELT_X 1
+# define CCD_DELT_Y -1 
+# define NFIELD 1.5   /* search region */
+# define MMIN 9.0     /* very saturated */
+
+typedef struct {
+  double X;
+  double Y;
+  double mag;
+} Stars;
+
+typedef struct {
+  char      ctype[16];
+  double    crval1, crpix1, cdelt1;
+  double    crval2, crpix2, cdelt2;
+  double    pc1_1, pc1_2;
+  double    pc2_1, pc2_2;
+} Coords;
+
+static char GSCFILE[] = "./GSCregions.tbl";
+static char GSC_DIR[] = "./gsc";
+
+void   args                PROTO((int *, char **));
+void   rargs               PROTO((int *, char **));
+void   alter_header        PROTO((char *, char **, int, double, double, double, double, double, double, double, double, int));
+void   ralter_header       PROTO((char *, char *, double, double, double, double, double, double, double, double, int));
+void   delta               PROTO((Stars *, Stars *, int, int, double *, double *, double *, double *));
+void   find_shift          PROTO((Stars *, Stars *, int, int, double, double, int *, double *, double *, double *));
+Stars *get_stars           PROTO((char *, int *));
+int    line_fit            PROTO((Stars *, Stars *, int, int, double, double, double, double, 
+			          double *, double *, double *, double *, double *, double *, double *, double *));
+void   ranges              PROTO((Stars *, Stars *, int, int, double *, double *, double *, double *, double, double));
+void   stats               PROTO((char *, double *, double *, double *, double *, double));
+double dms_to_deg          PROTO((char *, int));
+void   extract_catalog     PROTO((char *, double **, double **, double **, int *));
+Stars *get_catalog_stars   PROTO((double *, double *, double *, int, double, double, double, double, int *));
+void   precess             PROTO((double *, double *, double, double));
+
+extern double hypot PROTO((double, double));
+/*  this seems to be a problem: is not included from math.h with the -ansi flag */
+
+double RADIUS;
+double ASEC_PIX;
+int    FLIP;
+int    ROTATE;
+int    N2NUMBER;
+int    NPIX;
+int    FORCE;
+int    DUMP;
+double F_RA;
+double F_DEC;
+double NIM;
+
Index: /tags/start/Ohana/src/gastro/include/gastro.h
===================================================================
--- /tags/start/Ohana/src/gastro/include/gastro.h	(revision 12606)
+++ /tags/start/Ohana/src/gastro/include/gastro.h	(revision 12606)
@@ -0,0 +1,140 @@
+# include <ohana.h>
+# include <loneos.h>
+
+double DEFAULT_RADIUS;
+double MINIMUM_RADIUS;
+double MAX_ERROR, MAX_NONLINEAR;
+double MIN_PRECISE;
+double CCD_PC1_1;
+double CCD_PC2_2;
+double CCD_PC1_2;
+double CCD_PC2_1;
+double NFIELD;
+double SEARCH_RADIUS;
+double MMIN;
+double ROT_ZERO;
+double dROT;
+double RA_OFFSET, DEC_OFFSET;
+double POLE_RA, POLE_DEC;
+int POLAR_ALIGNMENT;
+int NROT;
+int VERBOSE;
+int LONEOS_COORDS;
+int CATDUMP;
+int MATCHDUMP;
+int NOMATCHDUMP;
+int NEWPHOTCODE;
+int MIN_MATCHES;
+char *PHOTCODE;
+int FLIPX, FLIPY;
+int NPOLYTERMS;
+char CDROM[256];
+char CATDIR[256];
+char REFCAT[256];
+char HEADER[256];
+int PLOTSTUFF;
+int MAGLIMS;
+int NMAX_STARS;
+char PhotCodeFile[256];
+
+int    FORCE;
+double F_RA;
+double F_DEC;
+
+char GSCFILE[256], GSC_DIR[256], LONEOS_REGION_FILE[256];
+double ASEC_PIX;
+char ROUGH_ASTROMETRY[64];
+
+typedef struct {
+  double xmin, xmax, ymin, ymax;
+  int style, ptype, ltype, etype, color;
+  double lweight, size;
+} Graphdata;
+
+/* simple structure to carry around data on an array of stars */
+typedef struct {
+  double X;
+  double Y;
+  double mag;
+} SStars;
+
+typedef struct {
+  Coords coords;
+  float *X, *Y;
+  int *N;
+  double RA[2], DEC[2];
+  double Area, density, spacing;
+} CatStats;
+
+typedef struct {
+  double R, D;
+  double r, b;
+} USNOdata;
+
+typedef struct {
+  int *match;
+  float *X, *Y;
+  int *N;
+} USNOstats;
+
+typedef struct {
+  char name[10];
+  double RA[2], DEC[2];
+} CatalogRegion;
+
+/*  this seems to be a problem: is not included from math.h with the -ansi flag */
+extern double hypot PROTO((double, double));
+
+char    **find_dec_bands      PROTO((CatalogRegion area, char **names, int *Nnames));
+char    **gregions	      PROTO((CatStats *catstats, int *nnames));
+char    **load_ra_blocks      PROTO((int Ndec, CatalogRegion area, char **names, int *Ntnames));
+SStars   *get_catalog_stars   PROTO((double *, double *, double *, int, double, double, double, double, int *));
+SStars   *get_stars           PROTO((char *, int *));
+USNOdata *getusno	      PROTO((USNOstats *usnostats, CatStats *catstats, int *Nusno));
+SStars   *gstars	      PROTO((char *file, int *NSTARS, Coords *coords, int *NX, int *NY, double *dNdM));
+void 	  ConfigInit	      PROTO((int *argc, char **argv));
+void 	  DonePlotting	      PROTO((Graphdata *graphmode, int N));
+void 	  PlotReset	      PROTO((int N));
+void 	  PlotVector	      PROTO((int Npts, float *vect, int mode, int N));
+void 	  PrepPlotting	      PROTO((int Npts, Graphdata *graphmode, int N));
+void 	  XDead		      PROTO(());
+void 	  ahelp		      PROTO(());
+void   	  alter_header        PROTO((char *, char **, int, double, double, double, double, double, double, double, double, int));
+void 	  area_of_region      PROTO((CatStats *region));
+void   	  args                PROTO((int *, char **));
+void 	  define_region	      PROTO((CatStats *catstats, Coords *coords, int NX, int NY));
+void   	  delta               PROTO((SStars *, SStars *, int, int, double *, double *, double *, double *));
+int 	  dms_to_ddd	      PROTO((double *Value, char *string));
+void   	  extract_catalog     PROTO((char *, double **, double **, double **, int *));
+void   	  find_shift          PROTO((SStars *, SStars *, int, int, double, double, int *, double *, double *, double *));
+int 	  g2mass	      PROTO((char *fullpath, SStars **stars, int *Nstars));
+void 	  gargs		      PROTO((int *argc, char **argv, Coords *coords));
+int 	  gaussj	      PROTO((double **a, int n, double **b, int m));
+int 	  gcatalog	      PROTO((char *filename, SStars **stars, int *Nstars));
+int 	  gcenter	      PROTO((SStars *stars1in, SStars *stars2, int N1, int N2, Coords *coords, int NX, int NY, double *dR));
+int 	  get_region_coords   PROTO((double *ra, double *dec, int rnumber, char *side));
+int 	  gfit		      PROTO((SStars *stars1, SStars *stars2, int N1, int N2, Coords *coords, int NX, int NY, double *Radius, double *DR, int *Nmatch, int mode));
+void 	  gfitpoly	      PROTO((SStars *stars1, SStars *stars2, int N1, int N2, Coords *coords, double *Radius, double *DR, int *Nmatch));
+void 	  gheader	      PROTO((char *file, Coords coords, double dR, int Nmatch));
+void 	  gproject	      PROTO((SStars *catalog, SStars **stars, int Ncat, int *Nstars, Coords *coords, int NX, int NY, double dNdM, int N1));
+int 	  gptolemy	      PROTO((char *fullpath, SStars **stars, int *Nstars));
+void 	  granges	      PROTO((SStars *stars1, SStars *stars2, int N1, int N2, int NPIX, double *gx, double *gy, double *gx0, double *gy0));
+int 	  greference	      PROTO((SStars **cat, int *Ncat, Coords *coords, int NX, int NY));
+void 	  hh_hms	      PROTO((double hh, int *hr, int *mn, double *sc));
+void 	  hms_format	      PROTO((char *line, double value));
+int       line_fit            PROTO((SStars *, SStars *, int, int, double, double, double, double, double *, double *, double *, double *, double *, double *, double *, double *));
+int 	  mk_polyterm	      PROTO((int n, int m, int norder));
+int 	  mk_vector	      PROTO((int n, int m, int norder));
+int 	  open_graph	      PROTO((int N));
+int 	  parse_GSC_line      PROTO((CatalogRegion *region, char *line));
+void   	  precess             PROTO((double *, double *, double, double));
+void   	  ralter_header       PROTO((char *, char *, double, double, double, double, double, double, double, double, int));
+void   	  ranges              PROTO((SStars *, SStars *, int, int, double *, double *, double *, double *, double, double));
+void   	  rargs               PROTO((int *, char **));
+void 	  rotate	      PROTO((SStars *stars, int Nstars, double angle, int Xo, int Yo));
+void 	  sort_stars	      PROTO((SStars *stars, int N));
+void      sort_lists          PROTO((double *X, double *Y, int *S, int N));
+void   	  stats               PROTO((char *, double *, double *, double *, double *, double));
+int 	  str_to_radec	      PROTO((double *ra, double *dec, char *str1, char *str2));
+void 	  svd		      PROTO((double ** matrix, int N, double **vector, int M));
+void 	  svdcmp	      PROTO((double **a, int m, int n, double **w, double **v));
Index: /tags/start/Ohana/src/gastro/src/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/ConfigInit.c	(revision 12606)
@@ -0,0 +1,56 @@
+# include "gastro.h"
+
+void ConfigInit (int *argc, char **argv) {
+  
+  char *config, *file;
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  ScanConfig (config, "OFFSET_RADIUS",     "%lf", 0, &SEARCH_RADIUS);
+  ScanConfig (config, "MIN_MATCHES",       "%d",  0, &MIN_MATCHES);
+  ScanConfig (config, "DEFAULT_RADIUS",    "%lf", 0, &DEFAULT_RADIUS);
+  ScanConfig (config, "MINIMUM_RADIUS",    "%lf", 0, &MINIMUM_RADIUS);
+  ScanConfig (config, "MAX_ERROR",         "%lf", 0, &MAX_ERROR);
+  ScanConfig (config, "MAX_NONLINEAR",     "%lf", 0, &MAX_NONLINEAR);
+  ScanConfig (config, "MAX_PRECISE",       "%lf", 0, &MIN_PRECISE);
+  ScanConfig (config, "CCD_PC1_1",         "%lf", 0, &CCD_PC1_1);
+  ScanConfig (config, "CCD_PC2_2",         "%lf", 0, &CCD_PC2_2);
+  ScanConfig (config, "CCD_PC1_2",         "%lf", 0, &CCD_PC1_2);
+  ScanConfig (config, "CCD_PC2_1",         "%lf", 0, &CCD_PC2_1);
+  ScanConfig (config, "ASEC_PIX",          "%lf", 0, &ASEC_PIX);
+  ScanConfig (config, "NFIELD",            "%lf", 0, &NFIELD);
+  ScanConfig (config, "NPOLYTERMS",        "%d",  0, &NPOLYTERMS);
+  ScanConfig (config, "MMIN",              "%lf", 0, &MMIN);
+  ScanConfig (config, "ROT_ZERO",          "%lf", 0, &ROT_ZERO);
+  ScanConfig (config, "dROT",              "%lf", 0, &dROT);
+  ScanConfig (config, "NROT",              "%d",  0, &NROT);
+  ScanConfig (config, "POLAR_ALIGNMENT",   "%d",  0, &POLAR_ALIGNMENT);
+  ScanConfig (config, "GSCFILE",           "%s",  0, GSCFILE);
+  ScanConfig (config, "GSCDIR",            "%s",  0, GSC_DIR);
+  ScanConfig (config, "POLAR_AXIS_RA",     "%lf", 0, &POLE_RA);
+  ScanConfig (config, "POLAR_AXIS_DEC",    "%lf", 0, &POLE_DEC);
+  ScanConfig (config, "RA_OFFSET",         "%lf", 0, &RA_OFFSET);
+  ScanConfig (config, "DEC_OFFSET",        "%lf", 0, &DEC_OFFSET);
+  ScanConfig (config, "LONEOS_REGIONS",    "%s",  0, LONEOS_REGION_FILE);
+  ScanConfig (config, "USNO_CDROM",        "%s",  0, CDROM);
+  ScanConfig (config, "ASTRO_REFCAT",      "%s",  0, REFCAT);
+  ScanConfig (config, "CATDIR",            "%s",  0, CATDIR);
+  ScanConfig (config, "ROUGH_ASTROMETRY",  "%s",  0, ROUGH_ASTROMETRY);
+  ScanConfig (config, "PHOTCODE_FILE",     "%s",  0, PhotCodeFile);
+
+  if (strcasecmp (ROUGH_ASTROMETRY, "header") && 
+      strcasecmp (ROUGH_ASTROMETRY, "config")) {
+    fprintf (stderr, "ROUGH_ASTROMETRY must be one of: header, config\n");
+    exit (0);
+  }
+  free (config);
+  free (file);
+}
Index: /tags/start/Ohana/src/gastro/src/alter_header.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/alter_header.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/alter_header.c	(revision 12606)
@@ -0,0 +1,60 @@
+# include "astro.h"
+
+void alter_header (head, argv, argc, X_O, X_X, X_Y, dX, Y_O, Y_X, Y_Y, dY, N)
+char head[], **argv;
+int argc;
+double X_O, X_X, X_Y, dX, Y_O, Y_X, Y_Y, dY;
+int N;
+{
+
+  Header header;
+  char tmp[200], line[500], *c;
+  int i;
+
+  fits_read_header (head, &header);
+
+  fits_modify (&header, "RA_O", "%lf", 1, X_O);
+  fits_modify (&header, "DEC_O", "%lf", 1, Y_O);
+  if (ROTATE) {
+    fits_modify (&header, "RA_X", "%le", 1, X_Y);
+    fits_modify (&header, "RA_Y", "%le", 1, X_X);
+    fits_modify (&header, "DEC_X", "%le", 1, Y_Y);
+    fits_modify (&header, "DEC_Y", "%le", 1, Y_X);
+  }
+  else {
+    fits_modify (&header, "RA_X", "%le", 1, X_X);
+    fits_modify (&header, "RA_Y", "%le", 1, X_Y);
+    fits_modify (&header, "DEC_X", "%le", 1, Y_X);
+    fits_modify (&header, "DEC_Y", "%le", 1, Y_Y);
+  }    
+  fits_modify (&header,  "dRA", "%lf", 1,  dX);
+  fits_modify (&header,  "dDEC", "%lf", 1,  dY);
+  fits_modify (&header,  "Nastro", "%d", 1,  N);
+  for (i = 3; i < argc; i++) {
+    if ((c = strrchr (argv[i], '/')) != NULL) 
+      fits_modify (&header, "REF", "%s", i-2, c+1);
+    else
+      fits_modify (&header, "REF", "%s", i-2, argv[i]);
+  }
+
+  fits_modify (&header, "RA_O", "%C", 1, "astro coeff");
+  fits_modify (&header, "RA_X", "%C", 1, "astro coeff");
+  fits_modify (&header, "RA_Y", "%C", 1, "astro coeff");
+  fits_modify (&header,  "dRA", "%C", 1, "error (pixels)");
+  fits_modify (&header, "DEC_O", "%C", 1, "astro coeff");
+  fits_modify (&header, "DEC_X", "%C", 1, "astro coeff");
+  fits_modify (&header, "DEC_Y", "%C", 1, "astro coeff");
+  fits_modify (&header,  "dDEC", "%C", 1, "error (pixels)");
+  fits_modify (&header,  "Nastro", "%C", 1, "Number of stars used");
+  for (i = 3; i < argc; i++) 
+    fits_modify (&header, "REF", "%C", i-2, "astro ref file");
+
+  strcpy (tmp, head);
+  strcat (tmp, "~");
+  sprintf (line, "mv %s %s\0", head, tmp);
+  system (line);
+
+  fits_write_header (head, &header);
+  fits_free_header (&header);
+
+}
Index: /tags/start/Ohana/src/gastro/src/args.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/args.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/args.c	(revision 12606)
@@ -0,0 +1,148 @@
+# include "astro.h"
+# define NARGS 3  /* minimum is:  astro ASEC_PIX catalog */
+
+void ahelp ()
+{
+
+  fprintf (stderr, "astro -- an astrometry routine\n");
+
+  fprintf (stderr, "  USAGE: astro <arcsec/pix> <catalog1>, [<catalog2>,...]  \n");
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -N          -- number of input stars used (default: 100) \n");
+  fprintf (stderr, "  -f RA,DEC   -- force image center to RA,DEC \n");
+  fprintf (stderr, "  -R radius   -- default radius of search   (default: %f asec) \n",  DEFAULT_RADIUS);
+  fprintf (stderr, "  -G N        -- grid search spacing        (default: %d ) \n", DEFAULT_NPIX);
+  fprintf (stderr, "  -F n        -- quadrant for search        (default: all) \n");
+  fprintf (stderr, "  -rot        -- rotated axes               (default: no) \n");
+  fprintf (stderr, "                 (see below)\n");
+  fprintf (stderr, "\n");
+  fprintf (stderr, "  -dump -- dumps the catalog stars to stdout\n");
+  fprintf (stderr, "  -help -- print this list\n");
+  fprintf (stderr, "\n");
+  fprintf (stderr, "\n");
+  fprintf (stderr, " Effect of -F and -rot:\n");
+  fprintf (stderr, "  		                            \n");
+  fprintf (stderr, "  without -rot:        with -rot:       \n");
+  fprintf (stderr, "  -------------        ----------       \n");                     
+  fprintf (stderr, "    2  n n  1           2  e e  1       \n");
+  fprintf (stderr, "       | |                 | |          \n");
+  fprintf (stderr, "    e -   - e           n -   - n       \n");
+  fprintf (stderr, "                                        \n");
+  fprintf (stderr, "    e -   - e           n -   - n       \n");
+  fprintf (stderr, "       | |                 | |          \n");
+  fprintf (stderr, "    3  n n  4           3  e e  4       \n");
+  fprintf (stderr, "\n"); 
+  exit (0);
+
+}
+
+void args (argc, argv)
+int     *argc;
+char   **argv;
+{
+  
+  int N;
+  char line[500];
+
+  if (N = get_argument (*argc, argv, "-dump")) {
+    remove_argument (N, argc, argv);
+    DUMP = TRUE;
+  }
+  else
+    DUMP = FALSE;
+
+  if (get_argument (*argc, argv, "-help") ||
+      get_argument (*argc, argv, "-h")) {
+    ahelp ();
+  }
+
+  /** optional arguments **/
+  if (N = get_argument (*argc, argv, "-N")) {
+    remove_argument (N, argc, argv);
+    N2NUMBER = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  else {
+    N2NUMBER = 100;
+  }
+  
+  if (N = get_argument (*argc, argv, "-NIM")) {
+    remove_argument (N, argc, argv);
+    NIM = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  else {
+    NIM = 2;
+  }
+  
+  if (N = get_argument (*argc, argv, "-F")) {
+    remove_argument (N, argc, argv);
+    FLIP = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  else {
+    FLIP = 0;
+  }
+  
+  if (N = get_argument (*argc, argv, "-rot")) {
+    remove_argument (N, argc, argv);
+    ROTATE = TRUE;
+  }
+  else {
+    ROTATE = FALSE;
+  }
+  
+  if (N = get_argument (*argc, argv, "-f")) {
+    FORCE = TRUE;
+    remove_argument (N, argc, argv);
+    F_RA = atof (argv[N]);
+    remove_argument (N, argc, argv);
+    F_DEC = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  else {
+    FORCE = FALSE;
+  }
+  
+  if (N = get_argument (*argc, argv, "-R")) {
+    remove_argument (N, argc, argv);
+    RADIUS = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  else {
+    RADIUS = DEFAULT_RADIUS;
+  }
+  
+  if (N = get_argument (*argc, argv, "-G")) {
+    remove_argument (N, argc, argv);
+    NPIX = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  else {
+    NPIX = DEFAULT_NPIX;
+  }
+  
+  if (*argc < NARGS) {
+    fprintf (stderr, "USAGE: astro <arcsec/pix> <catalog1>, [<catalog2>,...]  \n");
+    fprintf (stderr, "  enter filenames, followed by EOF\n");
+    exit (0);
+  }
+  
+  ASEC_PIX = atof (argv[1]);
+  remove_argument (1, argc, argv);
+  if (ASEC_PIX < 0.01) {
+    fprintf (stderr, "%f arcsec / pixel, is this really true?\n", 
+	     ASEC_PIX);
+    fscanf (stdin, "%s", line);
+    if (strcasecmp(line, "y") || strcasecmp(line, "yes"))
+      exit (0);
+  }
+  if (ASEC_PIX > 5) {
+    fprintf (stderr, "WARNING: your image may have too large\n");
+    fprintf (stderr, "         a field to be well modeled with\n");
+    fprintf (stderr, "         a linear astrometric solution\n");
+  }
+  
+  
+}
+
Index: /tags/start/Ohana/src/gastro/src/astro.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/astro.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/astro.c	(revision 12606)
@@ -0,0 +1,85 @@
+# include "astro.h"
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  int i, N1, N2, Ncat, Nlast, Nused;
+  double dx, dy, Rx, Ry;
+  double RA, DEC, dRA, dDEC;
+  double *ra, *dec, *mag;
+  double X_O, X_X, X_Y, dX, Y_O, Y_X, Y_Y, dY;
+  char *c, *ref, filename[200], head[200], obj[200], line[200];
+  Stars *stars1, *stars2;
+
+  args (&argc, argv);
+
+  Nlast = Ncat = 0;
+  for (i = 1; i < argc; i++) {
+    extract_catalog (argv[i], &ra, &dec, &mag, &Ncat);
+    fprintf (stderr, "catalog %s, %d stars (%d total)\n", argv[i], Ncat-Nlast, Ncat);
+    Nlast = Ncat;
+  }
+  
+  if (DUMP) {
+    for (i = 0; i < Ncat; i++) {
+      fprintf (stdout, "%d %f %f %f\n", i, ra[i], dec[i], mag[i]);
+    }
+    exit (0);
+  }
+
+  fprintf (stderr, "enter filenames, followed by EOF\n");
+  while (fscanf (stdin, "%s", filename) != EOF) {
+    /**** See comment 1 below ****/
+    strcpy (head, filename);
+    if ((c = strrchr(head, '.')) != NULL)
+      strcpy(strrchr(head, '.'), ".head");
+    else 
+      strcat(head, ".head");
+    strcpy (obj, filename);
+    if ((c = strrchr(obj, '.')) != NULL)
+      strcpy(strrchr(obj, '.'), ".obj_out");
+    else 
+      strcat(obj, ".obj_out");
+
+    stats (head, &RA, &DEC, &dRA, &dDEC, ASEC_PIX);
+    if (FORCE) 
+      stars1 = get_catalog_stars (ra, dec, mag, Ncat, F_RA, F_DEC, dRA, dDEC, &N1);
+    else {
+      stars1 = get_catalog_stars (ra, dec, mag, Ncat, RA, DEC, dRA, dDEC, &N1);
+    }
+    N2 = N2NUMBER;
+    stars2 = get_stars (obj, &N2);
+    if (N2 >= 3) {
+      if (FORCE)
+	Rx = ASEC_PIX / (3600 * cos (F_DEC*RAD_DEG));
+      else
+	Rx = ASEC_PIX / (3600 * cos (DEC*RAD_DEG));
+      Ry = ASEC_PIX / 3600;
+      delta (stars1, stars2, N1, N2, &dx, &dy, &Rx, &Ry);
+      fprintf (stderr, "USING: %f %f %f %f\n", dx, dy, Rx, Ry);
+      Nused = line_fit (stars1, stars2, N1, N2, dx, dy, Rx, Ry,
+		&X_O, &X_X, &X_Y, &dX, &Y_O, &Y_X, &Y_Y, &dY);
+      alter_header (head, argv, argc, X_O, X_X, X_Y, dX, Y_O, Y_X, Y_Y, dY, Nused);
+    }
+    else {
+      fprintf (stderr, "too few stars in %s, skipped\n", filename);
+    }
+    free (stars2);
+    free (stars1);  
+  }
+}
+
+
+
+
+    /* comment 1:
+       assign the assumed names: 
+       filename.head, filename.obj_out 
+       if filename is of the form xxxx.xxx, cut off
+       extention before attaching .head, .obj_out
+       this entire problem can be removed by making the 
+       Dophot output file contain the header info from
+       the image, but until this is the Dophot output
+       format... */
Index: /tags/start/Ohana/src/gastro/src/config.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/config.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/config.c	(revision 12606)
@@ -0,0 +1,110 @@
+# include <ohana.h>
+# define D_NBYTES 4096
+
+char *LoadConfigFile (filename) 
+char *filename; 
+{
+  
+  FILE *f;
+  int i, done, Nbytes, NBYTES, size;
+  char *config;
+  
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "couldn't find %s\n", filename);
+    return ((char *) NULL);
+  }
+ 
+  NBYTES = D_NBYTES;
+  ALLOCATE (config, char, NBYTES);
+ 
+  size = 0;
+  done = FALSE;
+  for (i = 0; !done; i++) {
+    Nbytes = fread (&config[i*D_NBYTES], sizeof(char), D_NBYTES, f);
+    size += Nbytes;
+    if (Nbytes < D_NBYTES) 
+      done = TRUE;
+    else {
+      NBYTES += D_NBYTES;
+      REALLOCATE (config, char, NBYTES);
+    }
+  }
+  
+  config[size] = '\n';
+  config[size+1] = 0;
+  REALLOCATE (config, char, size + 2);
+ 
+  fclose (f);
+
+  return (config);
+}
+
+int ScanConfig /* we expect one more field: the pointer to the value requested */
+# ifndef ANSI
+(config, field, mode, va_alist) 
+ char *config; char *field, *mode; va_dcl
+# else
+(char       config[],
+ char       field[],
+ char       mode[],...)
+# endif
+{
+ 
+  int i, j;
+  char *p, *p2, tmp[256];
+  va_list argp;
+  double value;
+  
+# ifndef ANSI
+  va_start (argp);
+# else
+  va_start (argp, N);
+# endif
+  
+  /* find the correct line with field */
+  p2 = config;
+  for (i = 0; ; i++) {
+    if (!strncmp (field, p2, strlen(field))) {
+      p = p2 + strlen (field);
+      break;
+    }
+    else {
+      p2 = strchr (p2, '\n');
+      if (p2 == (char *) NULL) {
+	fprintf (stderr, "entry %s not found in config file\n", field);
+	return (FALSE);
+      }
+      else p2++;
+    }
+  }
+  if (!strcmp (mode, "%s")) {
+    p2 = strchr (p, '\n');
+    if (p2 == (char *) NULL)
+      p2 = config + strlen(config);
+    bcopy (p, tmp, (p2-p));
+    tmp[(p2-p)] = 0;
+    stripwhite (tmp);
+    p2 = va_arg (argp, char *);
+    strcpy (p2, tmp);
+  }
+  else {
+ 
+    /* try to get a numerical value from the field */
+    value = strtod (p, &p2);
+    if ((*p2 == 'd') || (*p2 == 'D')) 
+      value *= pow (10.0, atof (p2 + 1));
+    
+    if (!strcmp (mode, "%d"))  *va_arg (argp, int *)       = value;
+    if (!strcmp (mode, "%u"))  *va_arg (argp, unsigned *)  = value;
+    if (!strcmp (mode, "%ld")) *va_arg (argp, long *)      = value;
+    if (!strcmp (mode, "%hd")) *va_arg (argp, short *)     = value;
+    if (!strcmp (mode, "%f"))  *va_arg (argp, float *)     = value;
+    if (!strcmp (mode, "%lf")) *va_arg (argp, double *)    = value;
+    
+  }
+ 
+  va_end (argp);
+  return (TRUE);
+  
+}
Index: /tags/start/Ohana/src/gastro/src/coordops.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/coordops.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/coordops.c	(revision 12606)
@@ -0,0 +1,362 @@
+# include "gastro.h"
+
+XY_to_RD (ra, dec, x, y, coords)
+double *ra, *dec;
+double  x, y;
+Coords coords[];
+{
+
+  double L, M, X, Y, T, Z;
+  double R, sphi, cphi, stht, ctht;
+  double alpha, delta, salp, calp, sdel, sdp, cdp;
+  
+  *ra  = 0;
+  *dec = 0;
+  stht = ctht = 1;
+
+  /** convert pixel coordinates to cartesian system **/
+  X = coords[0].cdelt1*(x - coords[0].crpix1);
+  Y = coords[0].cdelt2*(y - coords[0].crpix2);
+  if (!strcmp(&coords[0].ctype[4], "-PLY")) {
+    if (coords[0].Npolyterms > 2) {
+      X += coords[0].cdelt1*(x*x*coords[0].polyterms[0][0] + x*y*coords[0].polyterms[1][0] + y*y*coords[0].polyterms[2][0]);
+      Y += coords[0].cdelt2*(x*x*coords[0].polyterms[0][1] + x*y*coords[0].polyterms[1][1] + y*y*coords[0].polyterms[2][1]);
+    }
+    if (coords[0].Npolyterms > 2) {
+      X += coords[0].cdelt1*(x*x*x*coords[0].polyterms[3][0] + x*x*y*coords[0].polyterms[4][0] + x*y*y*coords[0].polyterms[5][0] + y*y*y*coords[0].polyterms[6][0]);
+      Y += coords[0].cdelt2*(x*x*x*coords[0].polyterms[3][1] + x*x*y*coords[0].polyterms[4][1] + x*y*y*coords[0].polyterms[5][1] + y*y*y*coords[0].polyterms[6][1]);
+    }
+  }
+
+  L = (X*coords[0].pc1_1 + Y*coords[0].pc1_2);
+  M = (X*coords[0].pc2_1 + Y*coords[0].pc2_2);
+  /* in FITS ref, L,M = x, y  alpha, delta = phi, theta */
+
+  /**** Zenithal Projections ****/
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || 
+      !strcmp(&coords[0].ctype[4], "-TAN") || 
+      !strcmp(&coords[0].ctype[4], "-SIN") || 
+      !strcmp(&coords[0].ctype[4], "-ZEA") || 
+      !strcmp(&coords[0].ctype[0], "MM")) {
+    R = hypot (L,M);
+    if ((L == 0) && (M == 0)) {
+      sphi = 0;
+      cphi = 1;
+    }
+    else {
+      sphi =  L / R;
+      cphi = -M / R;
+    }
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || 
+	!strcmp(&coords[0].ctype[4], "-TAN")) {
+      if (R == 0) {
+	stht = 1.0;
+	ctht = 0.0;
+      }
+      else {
+	T = DEG_RAD / R;
+	stht =   T / sqrt ( 1.0 + T*T);
+	ctht = 1.0 / sqrt ( 1.0 + T*T);
+      }
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || 
+	!strcmp(&coords[0].ctype[0], "MM")) {
+      ctht = RAD_DEG * R;
+      stht = sqrt (1 - ctht*ctht);
+    }
+    if (!strcmp(&coords[0].ctype[4], "-ZEA")) {
+      stht = 1 - 0.5*SQ(R*RAD_DEG);
+      ctht = sqrt (1 - stht*stht);
+    }
+
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    
+    sdel = stht*sdp - ctht*cphi*cdp;
+    salp = ctht*sphi;
+    calp = stht*cdp + ctht*cphi*sdp;
+    alpha = atan2 (salp, calp);
+    delta = asin (sdel);
+    
+    *ra  = DEG_RAD*alpha + coords[0].crval1;
+    *dec = DEG_RAD*delta;
+  }
+  
+  /**** Locally Cartesian Projections ****/
+  if (!strcmp(&coords[0].ctype[4], "-LIN") || 
+      !strcmp(&coords[0].ctype[0], "GENE")) {
+    *ra  = L + coords[0].crval1;
+    *dec = M + coords[0].crval2;
+  }
+  
+  /**** Other Conventional Projections ****/
+  if (!strcmp(&coords[0].ctype[4], "-AIT")) {
+    Z = sqrt (1.0 - SQ(RAD_DEG*0.25*L) - SQ(RAD_DEG*0.5*M));
+    alpha = 2.0 * DEG_RAD * atan2 (RAD_DEG*0.5*Z*L, 2.0*SQ(Z) - 1.0);
+    delta = DEG_RAD * asin (RAD_DEG*M*Z);
+    *ra  = alpha + coords[0].crval1;
+    *dec = delta + coords[0].crval2;
+  }
+  if (!strcmp(&coords[0].ctype[4], "-GLS")) {
+    /* L,M in degrees, alpha,delta in degrees */
+    alpha = L / cos (RAD_DEG * M);
+    delta = M;
+    *ra  = alpha + coords[0].crval1;
+    *dec = delta + coords[0].crval2;
+  }
+  if (!strcmp(&coords[0].ctype[4], "-PAR")) {
+    /* L,M in degrees, alpha,delta in degrees */
+    alpha = L / (1.0 - SQ(2.0*M/180));
+    delta = 3 * DEG_RAD * asin (M/180.0);
+    *ra  = alpha + coords[0].crval1;
+    *dec = delta + coords[0].crval2;
+  }
+}
+
+RD_to_XY (x, y, ra, dec, coords)
+double *x, *y;
+double  ra, dec;
+Coords coords[];
+{
+
+  double phi, theta;
+  double tmp_d;
+  double X, Y, sphi, cphi, stht;
+  double salp, calp, sdel, cdel, sdp, cdp;
+  double P, CP, A, Rc;
+  int status;
+
+  if (!strcmp(&coords[0].ctype[4], "-PLY")) {
+    /* fprintf (stderr, "approximate to polynomial TAN plane fit\n");  */
+  }
+
+  X = Y = 1;
+  status = TRUE;
+  *x = 0;
+  *y = 0;
+
+  /**** Locally Cartesian Projections ****/
+  if (!strcmp(&coords[0].ctype[0], "GENE") || !strcmp(&coords[0].ctype[4], "-LIN")) {
+    X = (ra  - coords[0].crval1);
+    Y = (dec - coords[0].crval2);
+  }
+  
+  /**** Zenithal Projections ****/
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || 
+      !strcmp(&coords[0].ctype[4], "-TAN") || 
+      !strcmp(&coords[0].ctype[4], "-ZEA") || 
+      !strcmp(&coords[0].ctype[4], "-SIN") || 
+      !strcmp(&coords[0].ctype[0], "MM")) {
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    salp = sin(RAD_DEG*(ra - coords[0].crval1));
+    calp = cos(RAD_DEG*(ra - coords[0].crval1));
+    sdel = sin(RAD_DEG*dec);
+    cdel = cos(RAD_DEG*dec);
+
+    stht = sdel*sdp + cdel*cdp*calp;    /* sin(theta) */
+    sphi = cdel*salp;                   /* = cos(theta)*sin(phi) */
+    cphi = cdel*sdp*calp - sdel*cdp;    /* = cos(theta)*cos(phi) */
+    if (stht < 0) status = FALSE;
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") ) {
+      X =  DEG_RAD * sphi / stht;
+      Y = -DEG_RAD * cphi / stht;
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      X =  DEG_RAD * sphi;
+      Y = -DEG_RAD * cphi;
+    }
+    if (!strcmp(&coords[0].ctype[4], "-ZEA")) {
+      Rc = DEG_RAD * M_SQRT2 / sqrt (1 + stht);
+      X =  Rc * sphi;
+      Y = -Rc * cphi;
+      status = TRUE;
+    }
+  }
+
+  /**** Other Standard Projections ****/
+  if (!strcmp(&coords[0].ctype[4], "-AIT")) {
+    phi = RAD_DEG*(ra - coords[0].crval1);
+    theta = RAD_DEG*(dec - coords[0].crval2);
+    P = 1.0 + cos (theta) * cos (0.5*phi);
+    if (P != 0.0) {
+      A =  DEG_RAD * sqrt (2.0 / P);
+      X =  2.0 * A * cos (theta) * sin (0.5*phi);
+      Y =  A * sin (theta);
+    } else { 
+      X =  0.0;
+      Y =  0.0;
+    }	
+  }
+  if (!strcmp(&coords[0].ctype[4], "-GLS")) {
+    phi = ra - coords[0].crval1;
+    theta = dec - coords[0].crval2;
+    X = phi * cos(RAD_DEG * theta);
+    Y = theta;
+  }
+  if (!strcmp(&coords[0].ctype[4], "-PAR")) {
+    phi = ra - coords[0].crval1;
+    theta = dec - coords[0].crval2;
+    X = phi * (2.0*cos(2*RAD_DEG*theta/3.0) - 1);
+    Y = 180.0 * sin (RAD_DEG*theta/3.0);
+  }
+    
+  tmp_d = 1.0 / (coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1);
+  *x = tmp_d * (coords[0].pc2_2*X - coords[0].pc1_2*Y) / coords[0].cdelt1 + coords[0].crpix1;
+  *y = tmp_d * (coords[0].pc1_1*Y - coords[0].pc2_1*X) / coords[0].cdelt2 + coords[0].crpix2;
+
+  return (status);
+  
+}
+
+fRD_to_XY (x, y, ra, dec, coords)
+float *x, *y;
+double  ra, dec;
+Coords coords[];
+{
+
+  int status;
+  double tmpx, tmpy;
+
+  status = RD_to_XY (&tmpx, &tmpy, ra, dec, coords);
+  *x = tmpx;
+  *y = tmpy;
+  
+  return (status);
+
+}
+
+fXY_to_RD (ra, dec, x, y, coords)
+float *ra, *dec;
+double  x, y;
+Coords coords[];
+{
+
+  int status;
+  double tmpr, tmpd;
+
+  status = XY_to_RD (&tmpr, &tmpd, x, y, coords);
+  *ra = tmpr;
+  *dec = tmpd;
+  
+  return (status);
+
+}
+
+int GetCoords (coords, header) 
+Coords coords[];
+Header header[];
+{
+
+  int status;
+  double rotate;
+
+  rotate = 0.0;
+  coords[0].crval1 = coords[0].crpix1 = coords[0].cdelt1 = 0.0;
+  coords[0].crval2 = coords[0].crpix2 = coords[0].cdelt2 = 0.0;
+  coords[0].pc1_1 = coords[0].pc2_2 = 1.0;
+  coords[0].pc2_1 = coords[0].pc1_2 = 0.0;
+  strcpy (coords[0].ctype, "NONE");
+
+  status = TRUE; 
+  if (fits_scan (header, "CTYPE2", "%s", 1, coords[0].ctype)) {
+    status  = fits_scan (header, "CRVAL1", "%lf", 1, &coords[0].crval1);
+    status &= fits_scan (header, "CRPIX1", "%lf", 1, &coords[0].crpix1);
+    status &= fits_scan (header, "CRVAL2", "%lf", 1, &coords[0].crval2);  
+    status &= fits_scan (header, "CRPIX2", "%lf", 1, &coords[0].crpix2);
+    if (fits_scan (header, "CDELT1", "%lf", 1, &coords[0].cdelt1)) {
+      status &= fits_scan (header, "CDELT2", "%lf", 1, &coords[0].cdelt2);
+      if (fits_scan (header, "CROTA2", "%lf", 1, &rotate)) {
+	coords[0].pc1_1 =  cos(rotate*RAD_DEG);
+	coords[0].pc1_2 = -sin(rotate*RAD_DEG);
+	coords[0].pc2_1 =  sin(rotate*RAD_DEG);
+	coords[0].pc2_2 =  cos(rotate*RAD_DEG);
+      }
+      if (fits_scan (header, "PC001001", "%lf", 1, &coords[0].pc1_1)) {
+	status &= fits_scan (header, "PC001002", "%lf", 1, &coords[0].pc1_2);
+	status &= fits_scan (header, "PC002001", "%lf", 1, &coords[0].pc2_1);
+	status &= fits_scan (header, "PC002002", "%lf", 1, &coords[0].pc2_2);
+      }
+      if (!strcmp (coords[0].ctype, "RA---PLY")) {
+	if (!fits_scan (header, "NPLYTERM", "%d", 1, &coords[0].Npolyterms)) {
+	  coords[0].Npolyterms = 3;
+	}
+	switch (coords[0].Npolyterms) {
+	case 3:
+	  status &= fits_scan (&header, "PCA1X3Y0", "%le", 1, &coords.polyterms[3][0]);
+	  status &= fits_scan (&header, "PCA1X2Y1", "%le", 1, &coords.polyterms[4][0]);
+	  status &= fits_scan (&header, "PCA1X1Y2", "%le", 1, &coords.polyterms[5][0]);
+	  status &= fits_scan (&header, "PCA1X0Y3", "%le", 1, &coords.polyterms[6][0]);
+	  status &= fits_scan (&header, "PCA2X3Y0", "%le", 1, &coords.polyterms[3][1]);
+	  status &= fits_scan (&header, "PCA2X2Y1", "%le", 1, &coords.polyterms[4][1]);
+	  status &= fits_scan (&header, "PCA2X1Y2", "%le", 1, &coords.polyterms[5][1]);
+	  status &= fits_scan (&header, "PCA2X0Y3", "%le", 1, &coords.polyterms[6][1]);
+	case 2:
+	  status &= fits_scan (&header, "PCA1X2Y0", "%le", 1, &coords.polyterms[0][0]);
+	  status &= fits_scan (&header, "PCA1X1Y1", "%le", 1, &coords.polyterms[1][0]);
+	  status &= fits_scan (&header, "PCA1X0Y2", "%le", 1, &coords.polyterms[2][0]);
+	  status &= fits_scan (&header, "PCA2X2Y0", "%le", 1, &coords.polyterms[0][1]);
+	  status &= fits_scan (&header, "PCA2X1Y1", "%le", 1, &coords.polyterms[1][1]);
+	  status &= fits_scan (&header, "PCA2X0Y2", "%le", 1, &coords.polyterms[2][1]);
+	case 0:
+	case 1:
+      }
+    }
+    else {
+      if (fits_scan (header, "CD1_1", "%lf", 1, &coords[0].pc1_1)) {
+	status &= fits_scan (header, "CD1_2", "%lf", 1, &coords[0].pc1_2);
+	status &= fits_scan (header, "CD2_1", "%lf", 1, &coords[0].pc2_1);
+	status &= fits_scan (header, "CD2_2", "%lf", 1, &coords[0].pc2_2);
+	coords[0].cdelt1 = coords[0].cdelt2 = 1.0;
+      }
+      else {
+	status = FALSE;
+      }
+    }
+  }
+  else {
+    if (fits_scan (header, "RA_O", "%lf", 1, &coords[0].crval1)) {
+      status  = fits_scan (header, "RA_X", "%lf", 1, &coords[0].pc1_1);
+      status &= fits_scan (header, "RA_Y", "%lf", 1, &coords[0].pc1_2);
+      status &= fits_scan (header, "DEC_O", "%lf", 1, &coords[0].crval2);  
+      status &= fits_scan (header, "DEC_X", "%lf", 1, &coords[0].pc2_1);
+      status &= fits_scan (header, "DEC_Y", "%lf", 1, &coords[0].pc2_2);
+      coords[0].crpix1 = coords[0].crpix2 = 0.0;
+      coords[0].cdelt1 = coords[0].cdelt2 = 1.0;
+      strcpy (coords[0].ctype, "GENE");
+    }
+  }
+  if (!status) {
+    fprintf (stderr, "error getting all elements for coordinate mode %d\n", coords[0].ctype);
+    coords[0].crval1 = coords[0].crpix1 = coords[0].cdelt1 = 0.0;
+    coords[0].crval2 = coords[0].crpix2 = coords[0].cdelt2 = 0.0;
+    coords[0].pc1_1 = coords[0].pc2_2 = 1.0;
+    coords[0].pc2_1 = coords[0].pc1_2 = 0.0;
+    strcpy (coords[0].ctype, "NONE");
+  }
+  return (status);
+}
+
+
+  /* -PLY projection is an extrapolation of the -TAN projection. 
+     In addition to the usual linear terms of CRPIXi, PC00i00j, there are 
+     higher order polynomial terms (up to 3rd order):
+     Axis 1 terms:
+     PCA1X2Y0 = coords.polyterm[0][0] = x^2                                             
+     PCA1X1Y1 = coords.polyterm[1][0] = xy                                          
+     PCA1X0Y2 = coords.polyterm[2][0] = y^2                                             
+     PCA1X3Y0 = coords.polyterm[3][0] = x^3                                             
+     PCA1X2Y1 = coords.polyterm[4][0] = x^2 y                                             
+     PCA1X1Y2 = coords.polyterm[5][0] = x y^2                                             
+     PCA1X0Y3 = coords.polyterm[6][0] = y^2                                              
+     Axis 2 terms:
+     PCA2X2Y0 = coords.polyterm[0][1] = x^2                                               
+     PCA2X1Y1 = coords.polyterm[1][1] = xy                                                
+     PCA2X0Y2 = coords.polyterm[2][1] = y^2                                               
+     PCA2X3Y0 = coords.polyterm[3][1] = x^3                                               
+     PCA2X2Y1 = coords.polyterm[4][1] = x^2 y                                             
+     PCA2X1Y2 = coords.polyterm[5][1] = x y^2                                             
+     PCA2X0Y3 = coords.polyterm[6][1] = y^2                                               
+  */
Index: /tags/start/Ohana/src/gastro/src/dastro.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/dastro.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/dastro.c	(revision 12606)
@@ -0,0 +1,86 @@
+# include "astro.h"
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  int status;
+  Header header;
+  char  filename[1024], reffile[1024];
+  double X_O, X_X, X_Y, Y_O, Y_X, Y_Y;
+  double RA_O, RA_X, RA_Y, DEC_O, DEC_X, DEC_Y;
+  double ra_o, ra_x, ra_y, dec_o, dec_x, dec_y;
+  double dRA, dDEC, dX, dY, dra, ddec;
+
+  while (fscanf (stdin, "%s", filename) != EOF) {
+
+    status = fits_read_header (filename, &header);
+    if (!status) {
+      fprintf (stderr, "error opening file %s", filename);
+      continue;
+    }
+    status = fits_scan (&header, "rREF", "%s", 1, reffile);
+    status &= fits_scan (&header, "X_O", "%lf", 1, &X_O);
+    status &= fits_scan (&header, "X_X", "%lf", 1, &X_X);
+    status &= fits_scan (&header, "X_Y", "%lf", 1, &X_Y);
+    status &= fits_scan (&header, "Y_O", "%lf", 1, &Y_O);
+    status &= fits_scan (&header, "Y_X", "%lf", 1, &Y_X);
+    status &= fits_scan (&header, "Y_Y", "%lf", 1, &Y_Y);
+    status &= fits_scan (&header, "dX", "%lf", 1, &dX);
+    status &= fits_scan (&header, "dY", "%lf", 1, &dY);
+    if (!status) {
+      fprintf (stderr, "file missing rastro info: %s", filename);
+      fits_free_header (&header);
+      continue;
+    }
+
+    status  = fits_read_header (reffilename, &refhead);
+    if (!status) {
+      fprintf (stderr, "error opening file %s", reffilename);
+      continue;
+    }
+    status &= fits_scan (&refhead, "RA_O", "%lf", 1, &RA_O);
+    status &= fits_scan (&refhead, "RA_X", "%lf", 1, &RA_X);
+    status &= fits_scan (&refhead, "RA_Y", "%lf", 1, &RA_Y);
+    status &= fits_scan (&refhead, "DEC_O", "%lf", 1, &DEC_O);
+    status &= fits_scan (&refhead, "DEC_X", "%lf", 1, &DEC_X);
+    status &= fits_scan (&refhead, "DEC_Y", "%lf", 1, &DEC_Y);
+    status &= fits_scan (&refhead, "dRA",   "%lf", 1, &dRA);
+    status &= fits_scan (&refhead, "dDEC",  "%lf", 1, &dDEC);
+    if (!status) {
+      fprintf (stderr, "file missing rastro info: %s", reffile);
+      fits_free_header (&header);
+      fits_free_header (&refhead);
+      continue;
+    }
+
+    
+    ra_o = RA_X*X_O + RA_Y*Y_O + RA_O;
+    dec_o = DEC_X*X_O + DEC_Y*Y_O + DEC_O;
+    
+    ra_x = RA_X*X_X + RA_Y*Y_X;
+    ra_y = RA_X*X_Y + RA_Y*Y_Y;
+    dec_x = DEC_X*X_X + DEC_Y*Y_X;
+    dec_y = DEC_X*X_Y + DEC_Y*Y_Y;
+    
+    dra = sqrt(dRA*dRA + SQ(3600*dX*RA_X) + SQ(3600*dY*RA_Y));
+    ddec = sqrt(dDEC*dDEC + SQ(3600*dX*DEC_X) + SQ(3600*dY*DEC_Y));
+			   
+    status  = fits_modify (&header, "rREF", "%s", 1, reffile);
+    status &= fits_modify (&header, "RA_O", "%lf", 1, RA_O);
+    status &= fits_modify (&header, "RA_X", "%lf", 1, RA_X);
+    status &= fits_modify (&header, "RA_Y", "%lf", 1, RA_Y);
+    status &= fits_modify (&header, "DEC_O", "%lf", 1, DEC_O);
+    status &= fits_modify (&header, "DEC_X", "%lf", 1, DEC_X);
+    status &= fits_modify (&header, "DEC_Y", "%lf", 1, DEC_Y);
+    status &= fits_modify (&header, "dRA",   "%lf", 1, dRA);
+    status &= fits_modify (&header, "dDEC",  "%lf", 1, dDEC);
+    
+    fits_free_header (&header);
+    fits_free_header (&refhead);
+    
+  }
+
+}
+
Index: /tags/start/Ohana/src/gastro/src/delta.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/delta.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/delta.c	(revision 12606)
@@ -0,0 +1,53 @@
+# include "astro.h"
+# define FIND_SHIFT(A,B) \
+  find_shift (stars1, stars2, N1, N2, (A), (B), &N, &S, &dX, &dY); \
+  if (S < s) { \
+      s = S; \
+    *Rx =  (A); \
+    *Ry =  (B); \
+    *dx = dX; \
+    *dy = dY; \
+      n = N; \
+  }
+
+void delta (stars1, stars2, N1, N2, dx, dy, Rx, Ry)
+Stars stars1[], stars2[];
+int N1, N2; 
+double *dx, *dy, *Rx, *Ry; 
+{
+  
+  int N, n;
+  double dX, dY, RX, RY, s, S;
+
+  n = 0;
+  s = 10000;
+  RX = *Rx;
+  RY = *Ry;
+
+  if (!FLIP || (FLIP == 1)) {
+/*    FIND_SHIFT( 0.9*RX,  0.9*RY);  */
+    FIND_SHIFT( 1.0*RX,  1.0*RY);
+/*    FIND_SHIFT( 1.1*RX,  1.1*RY);  */
+  }
+
+  if (!FLIP || (FLIP == 2)) {
+/*    FIND_SHIFT(-0.9*RX,  0.9*RY);  */
+    FIND_SHIFT(-1.0*RX,  1.0*RY);
+/*    FIND_SHIFT(-1.1*RX,  1.1*RY);  */
+  }
+
+  if (!FLIP || (FLIP == 3)) {
+/*    FIND_SHIFT(-0.9*RX, -0.9*RY);  */
+    FIND_SHIFT(-1.0*RX, -1.0*RY);
+/*    FIND_SHIFT(-1.1*RX, -1.1*RY);  */
+  }
+
+  if (!FLIP || (FLIP == 4)) {
+/*    FIND_SHIFT( 0.9*RX, -0.9*RY);  */
+    FIND_SHIFT( 1.0*RX, -1.0*RY);
+/*    FIND_SHIFT( 1.1*RX, -1.1*RY);  */
+  }
+
+  fprintf (stderr, "USING: %f %f %f %f\n", *dx, *dy, *Rx, *Ry);
+
+}
Index: /tags/start/Ohana/src/gastro/src/delta.number
===================================================================
--- /tags/start/Ohana/src/gastro/src/delta.number	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/delta.number	(revision 12606)
@@ -0,0 +1,41 @@
+# include "astro.h"
+# define FIND_SHIFT(A,B) \
+  find_shift (stars1, stars2, N1, N2, (A), (B), &N, &dX, &dY); \
+  if (N > n) { \
+    *Rx =  (A); \
+    *Ry =  (B); \
+    *dx = dX; \
+    *dy = dY; \
+      n = N; \
+  }
+
+void delta (stars1, stars2, N1, N2, dx, dy, Rx, Ry)
+Stars stars1[], stars2[];
+int N1, N2; 
+double *dx, *dy, *Rx, *Ry; 
+{
+  
+  int N, n;
+  double dX, dY, RX, RY;
+
+  n = 0;
+  RX = *Rx;
+  RY = *Ry;
+  FIND_SHIFT( 0.9*RX,  0.9*RY);
+  FIND_SHIFT(-0.9*RX,  0.9*RY);
+  FIND_SHIFT( 0.9*RX, -0.9*RY);
+  FIND_SHIFT(-0.9*RX, -0.9*RY);
+
+  FIND_SHIFT( 1.0*RX,  1.0*RY);
+  FIND_SHIFT(-1.0*RX,  1.0*RY);
+  FIND_SHIFT( 1.0*RX, -1.0*RY);
+  FIND_SHIFT(-1.0*RX, -1.0*RY);
+
+  FIND_SHIFT( 1.1*RX,  1.1*RY);
+  FIND_SHIFT(-1.1*RX,  1.1*RY);
+  FIND_SHIFT( 1.1*RX, -1.1*RY);
+  FIND_SHIFT(-1.1*RX, -1.1*RY);
+  
+  fprintf (stderr, "USING: %f %f %f %f\n", *dx, *dy, *Rx, *Ry);
+
+}
Index: /tags/start/Ohana/src/gastro/src/extract.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/extract.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/extract.c	(revision 12606)
@@ -0,0 +1,36 @@
+# include "astro.h"
+# define MMIN 14.5
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  int i, N1, N2, Ncat, Nlast, Nused;
+  double dx, dy, Rx, Ry;
+  double RA, DEC, dRA, dDEC;
+  double *ra, *dec, *mag;
+  double X_O, X_X, X_Y, dX, Y_O, Y_X, Y_Y, dY;
+  char *c, *ref, filename[200], head[200], obj[200], line[200];
+  Stars *stars1, *stars2;
+
+  RA = 500.0;  DEC = 500.0;
+
+  if (argc < 2) {
+    fprintf (stderr, "USAGE: extract (gscfile) \n");
+    exit (0);
+  }
+
+  Ncat = 0.0;
+  extract_catalog (argv[1], &ra, &dec, &mag, &Ncat);
+
+  for (i = 0; i < Ncat; i++) {
+    if ((hypot (ra[i] - RA, dec[i] - DEC) > 0.0006) && (mag[i] < MMIN)) {
+      fprintf (stdout, "%8.4f %8.4f %4.1f\n", ra[i], dec[i], mag[i]);
+    }
+    RA = ra[i];  DEC = dec[i];
+  }
+
+}
+
+
Index: /tags/start/Ohana/src/gastro/src/extract_catalog.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/extract_catalog.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/extract_catalog.c	(revision 12606)
@@ -0,0 +1,179 @@
+# include "astro.h"
+# define NBYTES 160000
+
+void extract_catalog (filename, ra, dec, mag, Nstars)
+char *filename;
+double **ra;
+double **dec;
+double **mag;
+int     *Nstars;
+{
+  
+  Header  header;
+  Table   table;
+  char **temp1;
+  char origin[300];
+  int i;
+  double *temp2, R, D, minM, maxM;
+  double minR, maxR, minD, maxD;
+
+  if (*Nstars == 0) {
+    ALLOCATE (*ra, double, 1);
+    ALLOCATE (*dec, double, 1);
+    ALLOCATE (*mag, double, 1);
+  }
+  
+  fits_read_header (filename, &header);
+  fits_scan (&header, "ORIGIN", "%s", 1, origin);
+  fits_free_header (&header);
+
+  minM = 100;
+  maxM = 0;
+  minR = 390;
+  maxR = -10;
+  minD = 100;
+  maxD = -100;
+  if (!strcmp (origin, "ST ScI")) {   /* Assuming it is guide star catalog.. */
+    fits_read_table   (filename, &table);  
+    fits_table_column (&table, "RA_DEG", "%lf", &temp2);
+    REALLOCATE (*ra, double, *Nstars + table.Naxis[1]);
+    for (i = 0; i < table.Naxis[1]; i++) {
+      (*ra)[*Nstars+i] = temp2[i];
+      minR = MIN (temp2[i], minR);
+      maxR = MAX (temp2[i], maxR);
+    }
+    free (temp2);
+    fits_table_column (&table, "DEC_DEG", "%lf", &temp2);
+    REALLOCATE (*dec, double, *Nstars + table.Naxis[1]);
+    for (i = 0; i < table.Naxis[1]; i++) {
+      (*dec)[*Nstars+i] = temp2[i];
+      minD = MIN (temp2[i], minD);
+      maxD = MAX (temp2[i], maxD);
+    }
+    free (temp2);
+    fits_table_column (&table, "MAG", "%lf", &temp2);
+    REALLOCATE (*mag, double, *Nstars + table.Naxis[1]);
+    for (i = 0; i < table.Naxis[1]; i++) {
+      (*mag)[*Nstars+i] = temp2[i];
+      minM = MIN (temp2[i], minM);
+      maxM = MAX (temp2[i], maxM);
+    }
+    *Nstars += table.Naxis[1];
+    free (temp2);
+    fprintf (stderr, "mag range: %f -- %f\n", minM, maxM);
+    fprintf (stderr, "RA  range: %f -- %f, \n", minR, maxR);
+    fprintf (stderr, "DEC range: %f -- %f, \n", minD, maxD);
+    return;
+  }
+
+  if (!strncmp (origin, "U.Minn. PDP11/60", strlen("U.Minn. PDP11/60"))) {  /* Assuming it is Berkhuijsen etal catalog.. */
+    fits_read_table   (filename, &table);  
+    fits_table_column (&table, "RA(1950)", "%s", &temp1);
+    REALLOCATE (*ra, double, *Nstars + table.Naxis[1]);
+    for (i = 0; i < table.Naxis[1]; i++) {
+      (*ra)[*Nstars+i] = 15*dms_to_deg (temp1[i], ':');
+      minR = MIN ((*ra)[*Nstars+i], minR);
+      maxR = MAX ((*ra)[*Nstars+i], maxR);
+      free (temp1[i]);
+    }
+    free (temp1);
+    fits_table_column (&table, "DEC(1950)", "%s", &temp1);
+    REALLOCATE (*dec, double, *Nstars + table.Naxis[1]);
+    for (i = 0; i < table.Naxis[1]; i++) {
+      (*dec)[*Nstars+i] = dms_to_deg (temp1[i], ':');
+      minD = MIN ((*dec)[*Nstars+i], minD);
+      maxD = MAX ((*dec)[*Nstars+i], maxD);
+      free (temp1[i]);
+    }
+    free (temp1);
+    fits_table_column (&table, "V-MAG", "%lf", &temp2);
+    REALLOCATE (*mag, double, *Nstars + table.Naxis[1]);
+    for (i = 0; i < table.Naxis[1]; i++) {
+      (*mag)[*Nstars+i] = temp2[i];
+      minM = MIN (temp2[i], minM);
+      maxM = MAX (temp2[i], maxM);
+    }
+    free (temp2);
+    for (i = *Nstars; i < *Nstars + table.Naxis[1]; i++) {
+      if (i < 20) 
+	fprintf (stderr, "%lf %lf -> ", (*ra)[i], (*dec)[i]);
+      /* see Magnier et al. 1993 A&A 272 695 */
+      R = 0.99999848*(*ra)[i]  - 0.00152332*(*dec)[i] + 0.0614972;
+      D = 0.99999848*(*dec)[i] + 0.0009958* (*ra)[i]  - 0.0093577;
+      precess (&R, &D, 1949.999790, 2000.0);  /* B1950.0 -> J2000.0 */
+      (*ra)[i] = R;
+      (*dec)[i] = D;
+      if (i < 20) 
+	fprintf (stderr, "%lf %lf\n", (*ra)[i], (*dec)[i]);
+    }
+    *Nstars += table.Naxis[1];
+    fprintf (stderr, "mag range: %f -- %f\n", minM, maxM);
+    return;
+  }
+
+  if (!strncmp (origin, "MIT-CSR", strlen("MIT-CSR"))) {  /* Assuming it is Magnier etal catalog.. */
+    fits_read_table   (filename, &table);  
+    fits_table_column (&table, "RA", "%lf", &temp2);
+    REALLOCATE (*ra, double, *Nstars + table.Naxis[1]);
+    for (i = 0; i < table.Naxis[1]; i++) {
+      (*ra)[*Nstars+i] = temp2[i];
+      minR = MIN ((*ra)[*Nstars+i], minR);
+      maxR = MAX ((*ra)[*Nstars+i], maxR);
+    }
+    free (temp2);
+    fits_table_column (&table, "DEC", "%lf", &temp2);
+    REALLOCATE (*dec, double, *Nstars + table.Naxis[1]);
+    for (i = 0; i < table.Naxis[1]; i++) {
+      (*dec)[*Nstars+i] = temp2[i];
+      minD = MIN ((*dec)[*Nstars+i], minD);
+      maxD = MAX ((*dec)[*Nstars+i], maxD);
+    }
+    free (temp2);
+    fits_table_column (&table, "V-MAG", "%lf", &temp2);
+    REALLOCATE (*mag, double, *Nstars + table.Naxis[1]);
+    for (i = 0; i < table.Naxis[1]; i++) {
+      (*mag)[*Nstars+i] = temp2[i];
+      minM = MIN (temp2[i], minM);
+      maxM = MAX (temp2[i], maxM);
+    }
+    free (temp2);
+    *Nstars += table.Naxis[1];
+    fprintf (stderr, "mag range: %f -- %f\n", minM, maxM);
+    return;
+  }
+
+  if (!strncmp (origin, "RELPHOT", strlen("RELPHOT"))) {  /* Assuming it is from relphot.c */
+    fits_read_table   (filename, &table);  
+    fits_table_column (&table, "RA", "%lf", &temp2);
+    REALLOCATE (*ra, double, *Nstars + table.Naxis[1]);
+    for (i = 0; i < table.Naxis[1]; i++) {
+      (*ra)[*Nstars+i] = temp2[i];
+      minR = MIN ((*ra)[*Nstars+i], minR);
+      maxR = MAX ((*ra)[*Nstars+i], maxR);
+    }
+    free (temp2);
+    fits_table_column (&table, "DEC", "%lf", &temp2);
+    REALLOCATE (*dec, double, *Nstars + table.Naxis[1]);
+    for (i = 0; i < table.Naxis[1]; i++) {
+      (*dec)[*Nstars+i] = temp2[i];
+      minD = MIN ((*dec)[*Nstars+i], minD);
+      maxD = MAX ((*dec)[*Nstars+i], maxD);
+    }
+    free (temp2);
+    fits_table_column (&table, "MAG", "%lf", &temp2);
+    REALLOCATE (*mag, double, *Nstars + table.Naxis[1]);
+    for (i = 0; i < table.Naxis[1]; i++) {
+      (*mag)[*Nstars+i] = temp2[i];
+      minM = MIN (temp2[i], minM);
+      maxM = MAX (temp2[i], maxM);
+    }
+    free (temp2);
+    *Nstars += table.Naxis[1];
+    fprintf (stderr, "mag range: %f -- %f\n", minM, maxM);
+    return;
+  }
+
+  fprintf (stderr, "unknown catalog format, ORIGIN: %s\n", origin);
+  exit (0);
+
+}
Index: /tags/start/Ohana/src/gastro/src/find_shift.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/find_shift.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/find_shift.c	(revision 12606)
@@ -0,0 +1,87 @@
+# include "astro.h"
+# define TIME {gettimeofday (&now, (struct timeval *) NULL); \
+fprintf (stderr, "start time: %f\n", now.tv_sec+now.tv_usec*1e-6);}
+
+void find_shift (stars1, stars2, N1, N2, Rx, Ry, n, S, dx, dy)
+Stars stars1[], stars2[];
+int N1, N2;
+double Rx, Ry;
+double *dx, *dy;
+double *S;
+int *n;
+{
+
+  double *DX, *DX2, *DY, *DY2, *N;
+  double Xrange, Yrange, Xzero, Yzero;
+  double dX, dY, sx, sy, s, dN, mean, sigma;
+  double *buf;
+  int i, j, dxi, dyi;
+  struct timeval now;  
+  double fx1, fx2, fy1, fy2;
+  int k;
+
+  *S = 1000000;
+  *n = *dx = *dy = 0;
+  NPIX = 1 + 30 * sqrt(N1*N2) / MIN (N1, N2);
+  mean = 2*N1*N2 / (NPIX*NPIX);
+  sigma = sqrt (mean);
+  ALLOCATE (N,    double, NPIX*NPIX);
+  ALLOCATE (DX,   double, NPIX*NPIX);
+  ALLOCATE (DY,   double, NPIX*NPIX);
+  ALLOCATE (DX2,  double, NPIX*NPIX);
+  ALLOCATE (DY2,  double, NPIX*NPIX);
+  bzero (N,   NPIX*NPIX*sizeof(double));
+  bzero (DX,  NPIX*NPIX*sizeof(double));
+  bzero (DY,  NPIX*NPIX*sizeof(double));
+  bzero (DX2, NPIX*NPIX*sizeof(double));
+  bzero (DY2, NPIX*NPIX*sizeof(double));
+  ranges (stars1, stars2, N1, N2, &Xrange, &Yrange, &Xzero, &Yzero, Rx, Ry);
+  fx1 = (NPIX - 1) / Xrange;
+  fx2 = -fx1 * Xzero;
+  fy1 = (NPIX - 1) / Yrange;
+  fy2 = -fy1 * Yzero;
+  for (i = 0; i < N1; i++) {
+    for (j = 0; j < N2; j++) {
+      dX = stars1[i].X - stars2[j].X;
+      dY = stars1[i].Y - stars2[j].Y;
+      dxi = fx1*dX + fx2;
+      dyi = fy1*dY + fy2;
+      k = dxi*NPIX + dyi;
+      N[k]   += 1.0;
+      DX[k]  += dX;
+      DY[k]  += dY;
+      DX2[k] += dX*dX;
+      DY2[k] += dY*dY;
+    }
+  }
+
+  for (i = 0; i < NPIX; i++) {
+    for (j = 0; j < NPIX; j++) {
+      if (N[i*NPIX + j] < 4) 
+	continue;
+      if (N[i*NPIX + j] - mean < 5*sigma) 
+	continue;
+		 
+      sx = DX2[i*NPIX + j] / (N[i*NPIX + j]) - SQ(DX[i*NPIX + j]) / SQ(N[i*NPIX + j]);
+      sy = DY2[i*NPIX + j] / (N[i*NPIX + j]) - SQ(DY[i*NPIX + j]) / SQ(N[i*NPIX + j]);
+      /* sx, sy are the positional scatter in the bin */
+      s = sqrt (sx + sy + 1e-11) / SQ(N[i*NPIX + j] - 3);
+      if (N[i*NPIX + j] > mean + 10*sigma) {
+	if (s < *S) { 
+	  *S = s;
+	  *n = N[i*NPIX + j];
+	  *dx = DX[i*NPIX + j] / (double) N[i*NPIX + j];
+	  *dy = DY[i*NPIX + j] / (double) N[i*NPIX + j];
+	}
+	/* fprintf (stderr, "point: %f %f  %f %f\n", s, N[i*NPIX + j],  DX[i*NPIX + j] / (double) N[i*NPIX + j], DY[i*NPIX + j] / (double) N[i*NPIX + j]);  */
+      }
+    }
+  }
+
+  free (N);
+  free (DX);
+  free (DY);
+  free (DX2);
+  free (DY2);
+
+}
Index: /tags/start/Ohana/src/gastro/src/g2mass.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/g2mass.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/g2mass.c	(revision 12606)
@@ -0,0 +1,45 @@
+# include "gastro.h"
+
+/* filename has path to GSC, strip off path, use filename with CATDIR path */
+
+int g2mass (char *fullpath, SStars **stars, int *Nstars) {
+  
+  int nstar, NSTARS;
+  float ra, dec, mag;
+  FILE *f;
+
+  f = fopen (fullpath, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't load catalog data\n");
+    return (FALSE);
+  }
+
+  /* for now, 2Mass data is just stored in a plain file with 
+     ra, dec, mag */
+
+  nstar = *Nstars;
+  NSTARS = *Nstars + 1000;
+  if (*Nstars == 0) {
+    ALLOCATE (stars[0], SStars, NSTARS);
+  } else {
+    REALLOCATE (stars[0], SStars, NSTARS);
+  }
+
+  while (fscanf (f, "%f %f %f", &ra, &dec, &mag) != EOF) {
+    stars[0][nstar].X = ra;
+    stars[0][nstar].Y = dec;
+    stars[0][nstar].mag = mag;
+    nstar ++;
+    if (nstar == NSTARS) {
+      NSTARS += 1000;
+      REALLOCATE (stars[0], SStars, NSTARS);
+    }
+  }
+
+  fclose (f);
+
+  *Nstars = nstar;
+  
+  return (TRUE);
+  
+}
Index: /tags/start/Ohana/src/gastro/src/gargs.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/gargs.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/gargs.c	(revision 12606)
@@ -0,0 +1,125 @@
+# include "gastro.h"
+# define NARGS 2  /* minimum is:  gastro catalog */
+
+void ahelp () {
+
+  fprintf (stderr, "gastro -- astrometry for LONEOS\n");
+
+  fprintf (stderr, "  USAGE: gastro pixscale filename");
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -v (verbose mode)\n");
+  fprintf (stderr, "  -dump (dump catalog stars, don't complete astrometry)\n");
+  fprintf (stderr, "  -mdmp (dump matched catalog stars)\n");
+  fprintf (stderr, "\n"); 
+  exit (0);
+
+}
+
+void gargs (int *argc, char **argv, Coords *coords) {
+  
+  int N;
+
+  if (get_argument (*argc, argv, "-help") ||
+      get_argument (*argc, argv, "-h")) {
+    ahelp ();
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (*argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  LONEOS_COORDS = FALSE;
+  if ((N = get_argument (*argc, argv, "-loneos"))) {
+    LONEOS_COORDS = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  NEWPHOTCODE = FALSE;
+  if ((N = get_argument (*argc, argv, "-p"))) {
+    NEWPHOTCODE = TRUE;
+    remove_argument (N, argc, argv);
+    PHOTCODE = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  PLOTSTUFF = FALSE;
+  if ((N = get_argument (*argc, argv, "-plot"))) {
+    PLOTSTUFF = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  MAGLIMS = TRUE;
+  if ((N = get_argument (*argc, argv, "-maglims"))) {
+    MAGLIMS = FALSE;
+    remove_argument (N, argc, argv);
+  }
+
+  NMAX_STARS = 300;
+  if ((N = get_argument (*argc, argv, "-nstars"))) {
+    remove_argument (N, argc, argv);
+    NMAX_STARS = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  HEADER[0] = 0;
+  if ((N = get_argument (*argc, argv, "-header"))) {
+    remove_argument (N, argc, argv);
+    strcpy (HEADER, argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  HEADER[0] = 0;
+  if ((N = get_argument (*argc, argv, "-head"))) {
+    remove_argument (N, argc, argv);
+    strcpy (HEADER, argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  FLIPX = FALSE;
+  if ((N = get_argument (*argc, argv, "-fx"))) {
+    FLIPX = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  FLIPY = FALSE;
+  if ((N = get_argument (*argc, argv, "-fy"))) {
+    FLIPY = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  FORCE = FALSE;
+  if ((N = get_argument (*argc, argv, "-coords"))) {
+    FORCE = TRUE;
+    remove_argument (N, argc, argv);
+    F_RA = atof (argv[N]);
+    remove_argument (N, argc, argv);
+    F_DEC = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  CATDUMP = FALSE;
+  if ((N = get_argument (*argc, argv, "-dump"))) {
+    CATDUMP = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  MATCHDUMP = FALSE;
+  if ((N = get_argument (*argc, argv, "-mdmp"))) {
+    MATCHDUMP = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  NOMATCHDUMP = FALSE;
+  if ((N = get_argument (*argc, argv, "-cdmp"))) {
+    NOMATCHDUMP = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  if (*argc != NARGS) {
+    fprintf (stderr, "USAGE: gastro filename\n");
+    exit (0);
+  }
+
+}
+
Index: /tags/start/Ohana/src/gastro/src/gastro.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/gastro.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/gastro.c	(revision 12606)
@@ -0,0 +1,84 @@
+# include "gastro.h"
+# define ABORT \
+{ Nmatch = 1; dR = 0; \
+  gheader (argv[1], coords, dR, Nmatch); \
+  exit (0); }
+
+int main (int argc, char **argv) {
+
+  int N1, N2, Ncat, NX, NY, Nmatch, Nminterms;
+  SStars *catalog, *stars1, *stars2;
+  struct timeval now, then;  
+  Coords coords;
+  double dNdM, dR, Radius;
+  
+  gettimeofday (&then, (void *) NULL);
+
+  ConfigInit (&argc, argv);
+  gargs (&argc, argv, &coords); 
+
+  /* load stars from image (*.cmp file) */
+  N1 = NMAX_STARS;  /* we only want a small number of stars */
+  stars1 = gstars (argv[1], &N1, &coords, &NX, &NY, &dNdM);
+
+  /* load stars from reference catalogs */
+  greference (&catalog, &Ncat, &coords, NX, NY);
+
+  /* get rough alignment with reference stars */
+  gproject (catalog, &stars2, Ncat, &N2, &coords, NX, NY, dNdM, N1);
+  gcenter (stars1, stars2, N1, N2, &coords, NX, NY, &Radius);
+  free (stars2);
+
+  /* reload reference, get good astrometry */
+  if (!greference (&catalog, &Ncat, &coords, NX, NY)) ABORT;
+  /* NFIELD = 1.2; */
+  gproject (catalog, &stars2, Ncat, &N2, &coords, NX, NY, dNdM, N1);
+  if (!gfit (stars1, stars2, N1, N2, &coords, NX, NY, &Radius, &dR, &Nmatch, 1)) ABORT;
+  free (stars2);
+ 
+  gproject (catalog, &stars2, Ncat, &N2, &coords, NX, NY, dNdM, N1);
+  gfitpoly (stars1, stars2, N1, N2, &coords, &Radius, &dR, &Nmatch);
+
+  if (dR > MAX_ERROR) {
+    fprintf (stderr, "ERROR: bad solution! %f %f (%d stars)\n", dR, (dR / sqrt(1.0*Nmatch)), Nmatch);
+    ABORT;
+  }
+  fprintf (stderr, "good solution: %f %f (%d stars)\n", dR, (dR / sqrt(1.0*Nmatch)), Nmatch);
+
+  switch (NPOLYTERMS) {
+  case 0:
+  case 1:
+    /* we don't really allow zero order fits */
+    Nminterms = MIN_MATCHES;
+    break;
+  case 2:
+    Nminterms = 20;
+    break;
+  case 3:
+    Nminterms = 40;
+    break;
+  }
+    
+  if (Nmatch <= Nminterms) { 
+    fprintf (stderr, "ERROR: too few stars for reliable solution, only %d\n", Nmatch);
+    ABORT;
+  }
+
+  gheader (argv[1], coords, dR, Nmatch);
+
+  if (VERBOSE) {
+    gettimeofday (&now, (void *) NULL);
+    fprintf (stderr, "%s: elapsed time = %.2f sec\n", argv[1], 
+	     (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec));
+  }
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
+
+/*
+  free (stars2);
+
+  DEFAULT_RADIUS = DEFAULT_RADIUS / 4;
+  gproject (catalog, &stars2, Ncat, &N2, &coords, NX, NY, dNdM, N1);
+  if (!gfit (stars1, stars2, N1, N2, &coords, NX, NY, &Radius, &dR, &Nmatch, 0)) ABORT;
+*/
Index: /tags/start/Ohana/src/gastro/src/gaussian.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/gaussian.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/gaussian.c	(revision 12606)
@@ -0,0 +1,60 @@
+# include <ohana.h>
+double drand48();
+double gaussian();
+double rnd_gauss();
+
+# define NGAUSS 2048
+double gaussint[NGAUSS];
+
+double rnd_gauss (double mean, double sigma)
+{
+  
+  double y;
+
+  y = gaussint[(int)(NGAUSS*drand48())];
+  
+  return (y*sigma + mean);
+
+}
+
+gauss_init ()
+{
+
+  int i;
+  long A, B;
+  double val, x, dx, dx1, dx2, dx3, df;
+  double mean, sigma;
+
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+
+  val = 0;
+  dx = 0.001;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+  mean = 0.0;
+  sigma = 1.0;
+
+  for (i = 0, x = -7.0; (i < NGAUSS) && (x < 7.0); x += dx)  {
+    df = (3.0*gaussian(x    , mean, sigma) + 
+	  9.0*gaussian(x+dx1, mean, sigma) +
+	  9.0*gaussian(x+dx2, mean, sigma) + 
+	  3.0*gaussian(x+dx3, mean, sigma)) * (dx1/8.0);
+    val += df;
+    if (val > (i / (double) NGAUSS)) {
+      gaussint[i] = x + dx / 2.0;
+      i++;
+    }
+  }
+}
+
+double gaussian (double x, double mean, double sigma)
+{
+
+  double f, X;
+  f = exp (-0.5 * SQ(x - mean) / SQ(sigma)) / sqrt(2 * M_PI * SQ(sigma));
+  return (f);
+
+}
Index: /tags/start/Ohana/src/gastro/src/gaussj.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/gaussj.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/gaussj.c	(revision 12606)
@@ -0,0 +1,75 @@
+# include <ohana.h>
+
+int gaussj (double **a, int n, double **b, int m) {
+
+  int *indxc,*indxr,*ipiv;
+  int i, icol, irow, j, k, l, ll;
+  double big,dum,pivinv;
+  
+  ALLOCATE (indxc, int, n);
+  ALLOCATE (indxr, int, n);
+  ALLOCATE (ipiv, int, n);
+  for (j = 0; j < n; j++) 
+    ipiv[j] = 0;
+
+  for (i = 0; i < n; i++) {
+    big = 0.0;
+    for (j = 0; j < n; j++) {
+      if (ipiv[j] != 1) {
+	for (k = 0; k < n; k++) {
+	  if (ipiv[k] == 0) {
+	    if (fabs (a[j][k]) >= big) {
+	      big  = fabs (a[j][k]);
+	      irow = j;
+	      icol = k;
+	    }
+	  } 
+	  else 
+	    if (ipiv[k] > 1) {
+	      fprintf (stderr, "GAUSSJ: Singular Matrix! (1)\n");
+	      return (0);
+	    }
+	}
+      }
+    }
+    ipiv[icol]++;
+    if (irow != icol) {
+      for (l = 0; l < n; l++) 
+	SWAP (a[irow][l], a[icol][l]);
+      for (l = 0; l < m; l++) 
+	SWAP (b[irow][l], b[icol][l]);
+    }
+    indxr[i] = irow;
+    indxc[i] = icol;
+    if (a[icol][icol] == 0.0) {
+      fprintf (stderr, "GAUSSJ: Singular Matrix! (2)\n");
+      return (0);
+    }
+    pivinv = 1.0 / a[icol][icol];
+    a[icol][icol] = 1.0;
+    for (l = 0; l < n; l++) 
+      a[icol][l] *= pivinv;
+    for (l = 0; l < m; l++) 
+      b[icol][l] *= pivinv;
+    for (ll = 0; ll < n; ll++) {
+      if (ll != icol) {
+	dum = a[ll][icol];
+	a[ll][icol] = 0.0;
+	for (l = 0; l < n; l++) 
+	  a[ll][l] -= a[icol][l]*dum;
+	for (l = 0; l < m; l++) 
+	  b[ll][l] -= b[icol][l]*dum;
+      }
+    }
+  }
+
+  for (l = n - 1; l >= 0; l--) {
+    if (indxr[l] != indxc[l])
+      for (k = 0; k < n; k++)
+	SWAP (a[k][indxr[l]], a[k][indxc[l]]);
+  }
+  free (ipiv);
+  free (indxr);
+  free (indxc);
+  return (1);
+}
Index: /tags/start/Ohana/src/gastro/src/gcatalog.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/gcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/gcatalog.c	(revision 12606)
@@ -0,0 +1,43 @@
+# include "gastro.h"
+# define BYTES_STAR 23
+# define BLOCK 1000
+# define DNSTARS 1000
+
+int gcatalog (char *filename, SStars **stars, int *Nstars) {
+  
+  int i, NSTARS, nstar, Nbytes, nbytes;
+  char *buffer;
+  FILE *f;
+
+  if (*Nstars == 0) ALLOCATE (*stars, SStars, 1);
+  nstar = *Nstars;
+  NSTARS = nstar + DNSTARS;
+
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find catalog file %s\n", filename);
+    return (FALSE);
+  }
+  
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR));
+  Nbytes = BLOCK*BYTES_STAR;
+  REALLOCATE (*stars, SStars, NSTARS);
+  while ((nbytes = fread (buffer, 1, Nbytes, f)) > 0) {
+    for (i = 0; i < nbytes / BYTES_STAR; i++) {
+      dparse (&(*stars)[nstar].X,   1, &buffer[i*BYTES_STAR]);
+      dparse (&(*stars)[nstar].Y,   2, &buffer[i*BYTES_STAR]);
+      dparse (&(*stars)[nstar].mag, 3, &buffer[i*BYTES_STAR]);
+      nstar++;
+      if (nstar == NSTARS - 1) {
+	NSTARS += DNSTARS;
+	REALLOCATE (*stars, SStars, NSTARS);
+      }
+    }
+  }
+  free (buffer);
+  REALLOCATE (*stars, SStars, nstar);
+  *Nstars = nstar;
+  
+  return (TRUE);
+  
+}
Index: /tags/start/Ohana/src/gastro/src/gcenter.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/gcenter.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/gcenter.c	(revision 12606)
@@ -0,0 +1,253 @@
+# include "gastro.h"
+# define NSIGMA 2.0
+
+/* stars1.X,Y and stars2.X,Y are in image pixels 
+   stars2 (ref catalog) is approx, based on guess for scale */
+
+int gcenter (SStars *stars1in, SStars *stars2, int N1, int N2, Coords *coords, int NX, int NY, double *dR) {
+
+  double mean, sigma, gx, gy, gx0, gy0, n, SearchRadius;
+  int NPIX, minN, Nmin, Nmin0;
+  int i, j, k;
+  double *N, *DX, *DY, *D2, *tX1, *tY1, *tX2, *tY2;
+  double rot, Rot, Smin, Smin0, s, Fmin, Fmin0, f;
+  double Xmin, Xmin0, Ymin, Ymin0;
+  double RA, DEC, RAo, DECo;
+  double dX, dY, refX, refY;
+  double cs, sn;
+  double dR1, dD1, dR2, dD2, d1, d2;
+  double *sx1, *sy1, *sx2, *sy2;
+  SStars *stars1;  
+  char c;
+  Graphdata graphdata;
+  float *xvect, *yvect;
+  int Nvect, NVECT;
+  
+  SearchRadius = NX * SEARCH_RADIUS;
+
+  if (PLOTSTUFF) {
+    Nvect = 0;
+    NVECT = N1*N2;
+    ALLOCATE (xvect, float, NVECT);
+    ALLOCATE (yvect, float, NVECT);
+    graphdata.xmin = 0;
+    graphdata.xmax = 2000;
+    graphdata.ymin = 0;
+    graphdata.ymax =  4000;
+    graphdata.style = 2;
+    graphdata.ptype = 2;
+    graphdata.ltype = 0;
+    graphdata.etype = 0;
+    graphdata.color = 0;
+    graphdata.lweight = 0;
+    graphdata.size = 0.5;
+  }
+ 
+  /*  NPIX = MAX (300, sqrt (20*(N1*N2) / MIN (N1, N2))); */
+  /* NPIX = 10 * sqrt (N2); */
+  NPIX = 300;
+  mean = 2 * N1*N2 / (NPIX*NPIX);
+  sigma = sqrt (mean);
+  minN =  MAX (6, mean + NSIGMA*sigma);
+  fprintf (stderr, "N1: %d, N2: %d, minN: %d\n", N1, N2, minN);
+
+  ALLOCATE (N,    double, NPIX*NPIX);
+  ALLOCATE (DX,   double, NPIX*NPIX);
+  ALLOCATE (DY,   double, NPIX*NPIX);
+  ALLOCATE (D2,   double, NPIX*NPIX);
+
+  ALLOCATE (stars1, SStars, N1);
+  for (i = 0; i < N1; i++) {
+    stars1[i] = stars1in[i];
+  }
+  
+  if (PLOTSTUFF) {
+    for (i = 0; i < N1; i++) {
+      xvect[Nvect] = stars1in[i].X;
+      yvect[Nvect] = stars1in[i].Y;
+      Nvect ++;
+    }
+  }
+  if (PLOTSTUFF) {
+    PlotReset (0);
+    PrepPlotting (Nvect, &graphdata, 0);
+    PlotVector (Nvect, xvect, 0, 0);
+    PlotVector (Nvect, yvect, 1, 0);
+    DonePlotting (&graphdata, 0);
+    usleep (300000);
+    fprintf (stderr, "plotting %d points\n", Nvect);
+    fprintf (stderr, "type return to continue");
+    fscanf (stdin, "%c", &c);
+    Nvect = 0;
+  }
+
+
+  Fmin = Smin = 1000000.0;
+  rot = Rot = ROT_ZERO-dROT*NROT;
+  rotate (stars1, N1, Rot, (int)coords[0].crpix1, (int)coords[0].crpix2); 
+
+  graphdata.xmin = -200;
+  graphdata.xmax =  200;
+  graphdata.ymin = -200;
+  graphdata.ymax =  200;
+
+  ALLOCATE (tX1, double, N1);
+  ALLOCATE (tY1, double, N1);
+  ALLOCATE (tX2, double, N2);
+  ALLOCATE (tY2, double, N2);
+  for (i = 0; i < N2; i++) {
+    tX2[i] = stars2[i].X;
+    tY2[i] = stars2[i].Y;
+  }
+  for (Rot = ROT_ZERO-dROT*NROT; Rot <= ROT_ZERO+dROT*NROT; Rot += dROT) {
+    granges (stars1, stars2, N1, N2, NPIX, &gx, &gy, &gx0, &gy0);
+    bzero (N,   NPIX*NPIX*sizeof(double));
+    bzero (DX,  NPIX*NPIX*sizeof(double));
+    bzero (DY,  NPIX*NPIX*sizeof(double));
+    bzero (D2,  NPIX*NPIX*sizeof(double));
+    for (i = 0; i < N1; i++) {
+      tX1[i] = stars1[i].X;
+      tY1[i] = stars1[i].Y;
+    }
+    sx1 = tX1; sy1 = tY1;
+    for (i = 0; i < N1; i++, sx1++, sy1++) {
+      sx2 = tX2; sy2 = tY2;
+      for (j = 0; j < N2; j++, sx2++, sy2++) {
+	dX = *sx1 - *sx2;
+	dY = *sy1 - *sy2;
+	if (hypot (dX, dY) > SearchRadius) continue;
+	if (PLOTSTUFF) {
+	  xvect[Nvect] = stars1[i].X - stars2[j].X;
+	  yvect[Nvect] = stars1[i].Y - stars2[j].Y;
+	  Nvect ++;
+	}
+	k = NPIX*(int)(gx*dX+gx0) + (int)(gy*dY+gy0);
+	N[k]   += 1.0;
+	DX[k]  += dX;
+	DY[k]  += dY;
+	D2[k]  += dX*dX + dY*dY;
+      }
+    }
+
+    Fmin0 = 1000.0;
+    for (k = 0; k < NPIX*NPIX; k++) {
+      n = N[k]; /* 1*/ 
+      if (n < minN)
+	continue;
+      s = D2[k] - (SQ(DX[k]) + SQ(DY[k])) / n; 
+      f = s / (pow(n,4.0)); /* = 12 ops */
+      
+      if (f < Fmin0) { 
+	Fmin0 = f;
+	Smin0 = s;
+	Nmin0 = n;
+	Xmin0 = DX[k] / n;
+	Ymin0 = DY[k] / n;
+      }
+    }
+    if (VERBOSE) fprintf (stderr, "best offset: %7.1f %7.1f at %.1f deg  (%f %f %d)\n", Xmin0, Ymin0, Rot, Fmin0, sqrt(Smin0), Nmin0);
+    if (Fmin0 < Fmin) {
+      Fmin = Fmin0;
+      Smin = Smin0;
+      Nmin = Nmin0;
+      Xmin = Xmin0;
+      Ymin = Ymin0;
+      rot  = Rot;
+    }
+    if (PLOTSTUFF) {
+      PlotReset (0);
+      PrepPlotting (Nvect, &graphdata, 0);
+      PlotVector (Nvect, xvect, 0, 0);
+      PlotVector (Nvect, yvect, 1, 0);
+      DonePlotting (&graphdata, 0);
+      usleep (300000);
+      fprintf (stderr, "plotting %d points\n", Nvect);
+      fprintf (stderr, "type return to continue");
+      fscanf (stdin, "%c", &c);
+      Nvect = 0;
+    }
+    
+    rotate (stars1, N1, dROT, (int)coords[0].crpix1, (int)coords[0].crpix2);
+  }
+  rotate (stars1, N1, -ROT_ZERO-dROT*NROT, (int)coords[0].crpix1, (int)coords[0].crpix2);
+
+  free (N);
+  free (DX);
+  free (DY);
+  free (D2);
+
+  /* dx = dy = 10 pix */
+  refX = coords[0].crpix1 - Xmin;
+  refY = coords[0].crpix2 - Ymin;
+  XY_to_RD (&RA, &DEC, refX, refY, coords);
+  XY_to_RD (&RAo, &DECo, (refX + 10), refY, coords);
+  dR1 = (RAo - RA)*cos(DEC*RAD_DEG);
+  dD1 = (DECo - DEC);
+  XY_to_RD (&RAo, &DECo, refX, (refY + 10), coords);
+  dR2 = (RAo - RA)*cos(DEC*RAD_DEG);
+  dD2 = (DECo - DEC);
+  d1 = coords[0].cdelt1;  d2 = coords[0].cdelt2;
+  cs = cos(RAD_DEG*rot);  sn = sin(RAD_DEG*rot);
+
+  coords[0].pc1_1 =  cs*dR1 / (10*d1) + sn*dR2 / (10*d1);    coords[0].pc1_2 = cs*dR2 / (10*d1) - sn*dR1 / (10*d1);
+  coords[0].pc2_1 =  cs*dD1 / (10*d2) + sn*dD2 / (10*d2);    coords[0].pc2_2 = cs*dD2 / (10*d2) - sn*dD1 / (10*d2);
+  coords[0].crval1 = RA;
+  coords[0].crval2 = DEC;
+
+  /* diameter of 1 pixel box */
+  *dR = 1*sqrt(Smin);
+
+  fprintf (stderr, "%f x %f, %f\n", 1/gx, 1/gy, *dR);
+  if (VERBOSE) fprintf (stderr, "using: %7.1f %7.1f at %.1f deg\n", Xmin, Ymin, rot);
+
+# if (0)
+  if (VERBOSE) {
+    fprintf (stderr, "%s\n", coords[0].ctype);
+    fprintf (stderr, "%f %f\n", coords[0].crval1, coords[0].crval2);
+    fprintf (stderr, "%f %f\n", coords[0].crpix1, coords[0].crpix2);
+    fprintf (stderr, "%f %f\n", coords[0].pc1_1, coords[0].pc1_2);
+    fprintf (stderr, "%f %f\n", coords[0].pc2_1, coords[0].pc2_2);
+    fprintf (stderr, "%f %f\n", coords[0].cdelt1, coords[0].cdelt2);
+  }
+# endif
+
+  DEFAULT_RADIUS = MAX ((5*NX / NPIX), DEFAULT_RADIUS);
+  return (TRUE);
+}
+
+  /* we now have Xmin, Ymin, rot, get coords in unrotate stars1 frame of correct crref 
+  RAo = coords[0].crval1;
+  DECo = coords[0].crval2;
+
+  cs = cos(RAD_DEG*rot);  sn = sin(RAD_DEG*rot);
+  refX = coords[0].crpix1;
+  refY = coords[0].crpix2;
+
+  coords[0].crpix1 =  Xmin*cs + Ymin*sn + refX;
+  coords[0].crpix2 = -Xmin*sn + Ymin*cs + refY;
+
+  xx = coords[0].pc1_1; xy = coords[0].pc1_2; 
+  yx = coords[0].pc2_1; yy = coords[0].pc2_2; 
+  coords[0].pc1_1 =  cs*xx + sn*xy;    coords[0].pc1_2 = cs*xy - sn*xx;
+  coords[0].pc2_1 =  cs*yx + sn*yy;    coords[0].pc2_2 = cs*yy - sn*yx;
+
+  XY_to_RD (&RA, &DEC, refX, refY, coords);
+  if (fabs(RAo - RA) > 90) {
+    RA = (RA > 180.0) ? (RA - 180) : (RA + 180);
+    DEC = (DEC > 0.0) ? (180.0 - DEC) : (-180.0 - DEC);
+  }
+  coords[0].crval1 = RA;
+  coords[0].crval2 = DEC;
+  coords[0].crpix1 = refX;
+  coords[0].crpix2 = refY;
+
+  Rot = RAo - RA;
+  cs = cos(RAD_DEG*rot);  sn = sin(RAD_DEG*rot);
+  xx = coords[0].pc1_1; xy = coords[0].pc1_2; 
+  yx = coords[0].pc2_1; yy = coords[0].pc2_2; 
+  coords[0].pc1_1 =  cs*xx + sn*xy;    coords[0].pc1_2 = cs*xy - sn*xx;
+  coords[0].pc2_1 =  cs*yx + sn*yy;    coords[0].pc2_2 = cs*yy - sn*yx;
+
+  
+
+*/
Index: /tags/start/Ohana/src/gastro/src/gdelta.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/gdelta.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/gdelta.c	(revision 12606)
@@ -0,0 +1,53 @@
+# include "astro.h"
+# define FIND_SHIFT(A,B) \
+  find_shift (stars1, stars2, N1, N2, (A), (B), &N, &S, &dX, &dY); \
+  if (S < s) { \
+      s = S; \
+    *Rx =  (A); \
+    *Ry =  (B); \
+    *dx = dX; \
+    *dy = dY; \
+      n = N; \
+  }
+
+void delta (stars1, stars2, N1, N2, dx, dy, Rx, Ry)
+Stars stars1[], stars2[];
+int N1, N2; 
+double *dx, *dy, *Rx, *Ry; 
+{
+  
+  int N, n;
+  double dX, dY, RX, RY, s, S;
+
+  n = 0;
+  s = 10000;
+  RX = *Rx;
+  RY = *Ry;
+
+  if (!FLIP || (FLIP == 1)) {
+/*    FIND_SHIFT( 0.9*RX,  0.9*RY);  */
+    FIND_SHIFT( 1.0*RX,  1.0*RY);
+/*    FIND_SHIFT( 1.1*RX,  1.1*RY);  */
+  }
+
+  if (!FLIP || (FLIP == 2)) {
+/*    FIND_SHIFT(-0.9*RX,  0.9*RY);  */
+    FIND_SHIFT(-1.0*RX,  1.0*RY);
+/*    FIND_SHIFT(-1.1*RX,  1.1*RY);  */
+  }
+
+  if (!FLIP || (FLIP == 3)) {
+/*    FIND_SHIFT(-0.9*RX, -0.9*RY);  */
+    FIND_SHIFT(-1.0*RX, -1.0*RY);
+/*    FIND_SHIFT(-1.1*RX, -1.1*RY);  */
+  }
+
+  if (!FLIP || (FLIP == 4)) {
+/*    FIND_SHIFT( 0.9*RX, -0.9*RY);  */
+    FIND_SHIFT( 1.0*RX, -1.0*RY);
+/*    FIND_SHIFT( 1.1*RX, -1.1*RY);  */
+  }
+
+  fprintf (stderr, "USING: %f %f %f %f\n", *dx, *dy, *Rx, *Ry);
+
+}
Index: /tags/start/Ohana/src/gastro/src/get_argument.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/get_argument.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/get_argument.c	(revision 12606)
@@ -0,0 +1,19 @@
+# include "astro.h"
+
+int get_argument (argc, argv, arg)
+int    argc;
+char **argv;
+char  *arg;
+{
+
+  int i;
+
+  for (i = 0; i < argc; i++) {
+    if (!strcmp(argv[i], arg))
+      return (i);
+  }
+  
+  return ((int)NULL);
+}
+
+
Index: /tags/start/Ohana/src/gastro/src/get_catalog_stars.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/get_catalog_stars.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/get_catalog_stars.c	(revision 12606)
@@ -0,0 +1,40 @@
+# include "astro.h"
+# define D_NSTARS 1000
+
+Stars *get_catalog_stars (ra, dec, mag, Ncat, RA, DEC, dRA, dDEC, Nstars)
+double *ra;
+double *dec;
+double *mag;
+int     Ncat;
+double RA, DEC, dRA, dDEC;
+int   *Nstars;
+{
+
+  int i, j, NSTARS;
+  Stars  *stars;
+
+  NSTARS = D_NSTARS;
+  ALLOCATE (stars, Stars, NSTARS);
+  fprintf (stderr,"%f %f  %f %f\n", RA, DEC, dRA, dDEC);
+
+  j = 0;
+  for (i = 0; i < Ncat; i++) {
+    if ((ra[i]  > RA  - NIM*dRA)  && (ra[i]  < RA  + NIM*dRA) &&
+	(dec[i] > DEC - NIM*dDEC) && (dec[i] < DEC + NIM*dDEC)) {
+      stars[j].X = ra[i];
+      stars[j].Y = dec[i];
+      stars[j].mag = mag[i];
+      j++;
+      if (j == NSTARS - 1) {
+	NSTARS += D_NSTARS;
+	REALLOCATE (stars, Stars, NSTARS);
+      }
+    }
+  }
+
+  *Nstars = j;
+  fprintf (stderr, "using %d stars from catalog\n", j);
+
+  return (stars);
+
+}
Index: /tags/start/Ohana/src/gastro/src/get_region_coords.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/get_region_coords.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/get_region_coords.c	(revision 12606)
@@ -0,0 +1,57 @@
+# include "gastro.h"
+# define NBYTE_LINE 53
+# define NLINES 100
+
+int get_region_coords (double *ra, double *dec, int rnumber, char *side) {
+  
+  FILE *f;
+  int i, j, done, found, Nbytes, Nline, num, NBYTES;
+  char *buffer;
+  double R, D;
+  
+  f = fopen (LONEOS_REGION_FILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "couldn't find region map %s\n", LONEOS_REGION_FILE);
+    return (FALSE);
+  }
+ 
+  NBYTES = NBYTE_LINE * NLINES;
+  ALLOCATE (buffer, char, NBYTES);
+ 
+  found = done = FALSE;
+  for (i = 0; !done && !found; i++) {
+    Nbytes = fread (buffer, sizeof(char), NBYTES, f);
+    if (Nbytes < 1) done = TRUE;
+    Nline = Nbytes / NBYTE_LINE;
+    for (j = 0; !found && (j < Nline); j++) {
+      num = atof (&buffer[j*NBYTE_LINE]);
+      if (num == rnumber) {
+	found = TRUE;
+	sscanf (&buffer[j*NBYTE_LINE], "%*d %lf %lf", &R, &D);
+	fwrite (&buffer[j*NBYTE_LINE], 1, 106, stderr);
+	fprintf (stderr, "\n\n%f %f\n", R, D);
+	if (!strncasecmp (side, "east", 4)) {
+	  R += 0.026 / cos (D);  
+	  /* if the word says "east", we need to offset by 1 chip width,
+	     R and D are in radians here, so 0.026 is 1.5 deg in radians */
+	}
+	R *= (180.0 / M_PI);
+	D *= (180.0 / M_PI);
+      }
+    }
+  }
+
+  free (buffer);
+  fclose (f);
+
+  if (!found) {
+    fprintf (stderr, "error: can't find desired region number %d\n", rnumber);
+    *ra = *dec = 0;
+    return (FALSE);
+  }
+
+  *ra = R;
+  *dec = D;
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/gastro/src/get_stars.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/get_stars.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/get_stars.c	(revision 12606)
@@ -0,0 +1,91 @@
+# include "astro.h"
+# define D_NSTARS 1000
+# define NFIELD 4
+
+Stars *get_stars (file, Nstars) 
+char file[];
+int *Nstars;
+{
+
+  FILE *f;
+  int n, i, type, NSTARS;
+  Stars *stars;
+  double tmp;
+
+  f = fopen (file, "r");
+  if (f == NULL) {
+    fprintf (stderr, "could not find object file %s\n", file);
+    exit(0);
+  }
+
+  NSTARS = D_NSTARS;
+  ALLOCATE (stars, Stars, NSTARS);
+  i = 0;
+  while ((n = fscanf (f, "%*f%d%lf%lf%lf%*f%*f%*f%*f%*f%*f%*f%*f%*f%*f", 
+		     &type, &stars[i].X, 
+		     &stars[i].Y, &stars[i].mag)) == NFIELD) {
+    if (ROTATE) {
+      tmp = stars[i].X;
+      stars[i].X = stars[i].Y;
+      stars[i].Y = tmp;
+    }
+    i++;
+    if (type != 1)
+     i--;
+    if (i == NSTARS - 1) {
+      NSTARS += D_NSTARS;
+      REALLOCATE (stars, Stars, NSTARS);
+    }
+  }
+  fclose(f);
+  if ((n != EOF) && (i < *Nstars))
+    fprintf (stderr, "error reading in file %s\n", file);
+  fprintf (stderr, " %d stars read from %s, ", i, file);
+  NSTARS = i;
+
+  sort_stars (stars, NSTARS);
+  
+  NSTARS = *Nstars = MIN (NSTARS, *Nstars);
+  REALLOCATE (stars, Stars, NSTARS);
+  fprintf (stderr, "using %5d\n", NSTARS);
+  
+  return (stars);
+}
+
+sort_stars (stars, N) 
+Stars *stars;
+int N;
+{
+  int l,j,ir,i;
+  int temp;
+  Stars tempstar;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      tempstar = stars[--l];
+    }
+    else {
+      tempstar = stars[ir];
+      stars[ir] = stars[0];
+      if (--ir == 0) {
+	stars[0] = tempstar;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && stars[j].mag < stars[j+1].mag) ++j;
+      if (tempstar.mag < stars[j].mag) {
+	stars[i] = stars[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    stars[i] = tempstar;
+  }
+}
+
+
Index: /tags/start/Ohana/src/gastro/src/getusno.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/getusno.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/getusno.c	(revision 12606)
@@ -0,0 +1,131 @@
+# include "gastro.h"
+# define NZONE 24
+
+int SPDzone[] = {
+  0, 75, 450, 375, 1500, 1650, 300, 1425, 1725, 525, 1275, 225, 
+  675, 150, 600, 1575, 750, 975, 900, 1050, 1125, 1200, 825, 1350};
+
+int USNOdisk[] = {
+  1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10};
+
+USNOdata *getusno (USNOstats *usnostats, CatStats *catstats, int *Nusno) {
+
+  long int offset;
+  int i, bin, first, last, nitems, Nitems, Nbins;
+  float hours[100];
+  int start[100], number[100], *buffer, *buf;
+  char filename[128], c;
+  FILE *f;
+  double DEC1;
+  int iDEC0, iDEC1, iRA0, iRA1;
+  int spd, spd_start, spd_end, disk;
+  int NUSNO, nusno;
+  USNOdata *usno;
+
+  iRA0 = catstats[0].RA[0] * 360000.0;
+  iRA1 = catstats[0].RA[1] * 360000.0;
+  iDEC0 = (catstats[0].DEC[0] + 90.0) * 360000.0;
+  iDEC1 = (catstats[0].DEC[1] + 90.0) * 360000.0;
+  
+  spd_start = (int)(    (catstats[0].DEC[0] + 90) / 7.5) * 75.0;
+  DEC1 = (catstats[0].DEC[1] + 90) / 7.5;
+  if (DEC1 > (int)(DEC1)) {
+    spd_end =   (int)(1 + (catstats[0].DEC[1] + 90) / 7.5) * 75.0;
+  } else {
+    spd_end =   (int)(0 + (catstats[0].DEC[1] + 90) / 7.5) * 75.0;
+  }
+
+  NUSNO = 5000;
+  ALLOCATE (usno, USNOdata, NUSNO);
+  nusno = 0;
+
+  for (spd = spd_start; spd < spd_end; spd += 75) {
+    disk = -1;
+    for (i = 0; i < NZONE; i++) {
+      if (spd == SPDzone[i]) 
+	disk = USNOdisk[i];
+    }
+    if (disk < 0) {
+      fprintf (stderr, "ERROR: can't find cdrom for spd %d\n",  spd);
+      exit (0);
+    }
+    
+    /* load accelerator file */
+    sprintf (filename, "%s/zone%04d.acc", CDROM, spd); 
+    fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "can't open file %s, is cdrom %d in drive?\n", filename, disk);
+      fprintf (stderr, "press return when ready to continue: ");
+      fscanf (stdin, "%c", &c);
+      fprintf (stderr, "trying again...\n");
+      f = fopen (filename, "r");
+      if (f == (FILE *) NULL) {
+	fprintf (stderr, "still can't open file %s, is cdrom %d in drive?\n", filename, disk);
+	exit (0);  
+      }
+    }
+    for (i = 0; fscanf (f, "%f %d %d", &hours[i], &start[i], &number[i]) != EOF; i++);
+    Nbins = i;
+    fclose (f);
+    
+    first = catstats[0].RA[0] / 3.75;
+    if ((catstats[0].RA[1] / 3.75) == (int) (catstats[0].RA[1] / 3.75)) 
+      last  = catstats[0].RA[1] / 3.75;
+    else 
+      last  = 1 + catstats[0].RA[1] / 3.75;
+
+    if ((first > Nbins) || (last > Nbins)) {
+      fprintf (stderr, "RA out of range\n");
+      exit (0);
+    }
+    
+    /* open data file */
+    sprintf (filename, "%s/zone%04d.cat", CDROM, spd);
+    fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "can't open file %s\n", filename);
+      exit (0);
+    }
+    /* advance file pointer to first slice */
+    offset = 3*sizeof(int)*(start[first] - 1);
+    fseek (f, offset, SEEK_SET);
+    /* on each loop, load data from an RA slice of the catalog */
+    for (bin = first; bin < last; bin++) {
+      Nitems = 3*number[bin];
+      ALLOCATE (buffer, int, Nitems);
+      nitems = Fread (buffer, sizeof(int), Nitems, f, "int");
+      if (nitems != Nitems) {
+	fprintf (stderr, "error reading data from file %s (%d, %d, %d)\n", 
+		 filename, start[bin], number[bin], nitems);
+	exit (0);
+      }
+      buf = buffer;
+      /* print out data from slice within RA and DEC range */
+      for (i = 0; i < number[bin]; i++, buf+=3) {
+	if ((buf[0] > iRA0) && (buf[0] < iRA1) &&
+	    (buf[1] > iDEC0) && (buf[1] < iDEC1)) {
+	  usno[nusno].R = buf[0]/360000.0;
+	  usno[nusno].D = buf[1]/360000.0 - 90.0;
+	  usno[nusno].r = 0.1*(buf[2] - 1000*((int)(buf[2]/1000)));
+	  usno[nusno].b = 0.1*((int)(buf[2] - 1000000*((int)(buf[2]/1000000))) / 1000);
+	  nusno ++;
+	  if (nusno == NUSNO - 1) {
+	    NUSNO += 5000;
+	    REALLOCATE (usno, USNOdata, NUSNO);
+	  }	  
+	}
+      }
+      free (buffer);
+    }
+    fclose (f);
+  }
+
+  REALLOCATE (usno, USNOdata, MAX (nusno, 1));
+  *Nusno = nusno;
+  return (usno);
+
+}
+
+
Index: /tags/start/Ohana/src/gastro/src/gfit.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/gfit.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/gfit.c	(revision 12606)
@@ -0,0 +1,457 @@
+# include "gastro.h"
+
+/* stars1.X,Y and stars2.X,Y are both in image pixels. 
+   The conversion terms (X_O, X_X, etc) make linear 
+   corrections in pixel coordinates */
+
+int gfit (SStars *stars1, SStars *stars2, int N1, int N2, Coords *coords, int NX, int NY, double *Radius, double *DR, int *Nmatch, int mode) {
+  
+  int i, j, iteration, Niter, last, halt, first_j, *Nextra, extras;
+  int *tmpN1, *tmpN2;
+  double X_O, X_X, X_Y, dX;
+  double Y_O, Y_X, Y_Y, dY;
+  double x, y, x2, y2, xy, N, R, wt;
+  double X, Y, Xx, Yy, Xy, Yx;
+  double Dx, Dy, DD, d2X, d2Y;
+  double RA, DEC, radius, radius2, fratio;
+  double *tmpX1, *tmpX2, *tmpY1, *tmpY2;
+  double tX1, tX2, tY1, tY2;
+  double dS;
+
+  char c;
+  Graphdata graphdata;
+  float *xvect, *yvect;
+  float *xvect2, *yvect2;
+  int Nvect, NVECT;
+  int Nvect2, NVECT2;
+  
+  if (PLOTSTUFF) {
+    Nvect2 = 0;
+    NVECT2 = MAX(N1, N2);
+    Nvect = 0;
+    NVECT = MAX(N1, N2);
+    ALLOCATE (xvect, float, NVECT);
+    ALLOCATE (yvect, float, NVECT);
+    ALLOCATE (xvect2, float, NVECT2);
+    ALLOCATE (yvect2, float, NVECT2);
+  }
+    
+
+  /* allocate space for star coords */
+  ALLOCATE (tmpX1, double, N1);
+  ALLOCATE (tmpY1, double, N1);
+  ALLOCATE (tmpN1, int, N1);
+  
+  ALLOCATE (tmpX2, double, N2);
+  ALLOCATE (tmpY2, double, N2);
+  ALLOCATE (tmpN2, int, N2);
+  ALLOCATE (Nextra, int, N2);
+  bzero (Nextra, sizeof(int) * N2);
+
+  /* assign and sort list */
+  for (i = 0; i < N1; i++) {
+    tmpX1[i] = stars1[i].X;
+    tmpY1[i] = stars1[i].Y;
+    tmpN1[i] = i;
+  }
+  if (N1 > 1) sort_lists (tmpX1, tmpY1, tmpN1, N1);
+
+   
+  /* choose iteration ranges */
+  fratio = 1.41421;
+  extras = halt = last = FALSE;
+  radius = *Radius;
+  Niter = 2 + log (radius/MINIMUM_RADIUS) / log (fratio);
+  
+  /* initial values for fit coeffs */
+  X_X = 1; X_Y = 0; X_O = 0;
+  Y_X = 0; Y_Y = 1; Y_O = 0;
+  
+  for (iteration = 0; iteration < Niter; iteration ++) {
+
+    if (iteration >= Niter - 1) { /* next loop is the last one */
+      radius *= fratio;
+      last = TRUE;
+    }
+
+    /* setup and define */
+    radius2 = radius*radius;
+    dX = dY = d2X = d2Y = x = y = x2 = y2 = xy = X = Y = Xx = Xy = Yx = Yy = N = R = 0;
+    for (i = 0; i < N2; i++) {
+      tmpX2[i] = (X_O) + (X_X)*stars2[i].X + (X_Y)*stars2[i].Y;
+      tmpY2[i] = (Y_O) + (Y_X)*stars2[i].X + (Y_Y)*stars2[i].Y;
+      tmpN2[i] = i;
+    }
+    
+    if (PLOTSTUFF) {
+      for (i = 0; i < N1; i++) {
+	xvect2[i] = tmpX1[i];
+	yvect2[i] = tmpY1[i];
+      }
+      Nvect2 = N1;
+
+      graphdata.xmin = 0;
+      graphdata.xmax = 2000;
+      graphdata.ymin = 4000;
+      graphdata.ymax =  0;
+      graphdata.style = 2;
+      graphdata.ptype = 3;
+      graphdata.ltype = 0;
+      graphdata.etype = 0;
+      graphdata.color = 0;
+      graphdata.lweight = 0;
+      graphdata.size = 1.5;
+    
+      PlotReset (1);
+      PrepPlotting (Nvect2, &graphdata, 1);
+      PlotVector (Nvect2, xvect2, 0, 1);
+      PlotVector (Nvect2, yvect2, 1, 1);
+      DonePlotting (&graphdata, 1);
+      Nvect2 = 0;
+
+      for (i = 0; i < N2; i++) {
+	xvect2[i] = tmpX2[i];
+	yvect2[i] = tmpY2[i];
+      }
+      Nvect2 = N2;
+
+      graphdata.ptype = 1;
+
+      PrepPlotting (Nvect2, &graphdata, 1);
+      PlotVector (Nvect2, xvect2, 0, 1);
+      PlotVector (Nvect2, yvect2, 1, 1);
+      DonePlotting (&graphdata, 1);
+      Nvect2 = 0;
+    }
+
+    if (N2 > 1) sort_lists (tmpX2, tmpY2, tmpN2, N2);
+    
+    /* find matched stars */
+    for (i = j = 0; (i < N1) && (j < N2); ) {  
+      tX1 = tmpX1[i];
+      tX2 = tmpX2[j];
+      Dx = tX1 - tX2;
+      if (Dx <= -2.0*radius) {
+	i++;
+	continue;
+      }
+      if (Dx >= 2.0*radius) {
+	j++;
+	continue;
+      }
+
+      /**** possible improvement: find only the closest match 
+	    for stars that have more than one (save DD and i for each
+            cat star j */
+      /* in the right range */
+      first_j = j;
+      for (; (Dx > -2.0*radius) && (j < N2); j++) {
+	tY1 = tmpY1[i];
+	tX2 = tmpX2[j];
+	tY2 = tmpY2[j];
+	Dx = tX1 - tX2;
+	Dy = tY1 - tY2;
+	DD = Dx*Dx + Dy*Dy;
+	/* stars matched */
+	if (DD < radius2) {
+	  if (PLOTSTUFF) {
+	    xvect[Nvect] = Dx;
+	    yvect[Nvect] = tmpY1[i];
+	    Nvect ++;
+	    if (Nvect == NVECT) {
+	      NVECT += 100;
+	      REALLOCATE (xvect, float, NVECT);
+	      REALLOCATE (yvect, float, NVECT);
+	    }
+	    xvect2[Nvect2] = tmpX1[i];
+	    yvect2[Nvect2] = tmpY1[i];
+	    Nvect2 ++;
+	    if (Nvect2 == NVECT2 - 1) {
+	      NVECT2 += 100;
+	      REALLOCATE (xvect2, float, NVECT2);
+	    REALLOCATE (yvect2, float, NVECT2);
+	    }
+	  }
+	  /* wt = sqrt(sqrt(DD)); */
+	  wt = DD + 1;
+	  dX += Dx;
+	  dY += Dy;
+	  d2X += Dx*Dx;
+	  d2Y += Dy*Dy;
+	  x  += tX2/wt;
+	  y  += tY2/wt;
+	  x2 += tX2*tX2/wt;
+	  y2 += tY2*tY2/wt;
+	  xy += tX2*tY2/wt;
+	  X  += tX1/wt;
+	  Y  += tY1/wt;
+	  Xx += tX1*tX2/wt;
+	  Xy += tX1*tY2/wt;
+	  Yx += tY1*tX2/wt;
+	  Yy += tY1*tY2/wt;
+	  N  += 1.0;
+	  R  += 1.0/wt;
+	  if (last && MATCHDUMP && mode) {
+	    XY_to_RD (&RA, &DEC, stars2[tmpN2[j]].X, stars2[tmpN2[j]].Y, coords);
+	    fprintf (stdout, "%f %f %f %f %f\n", RA, DEC, stars2[tmpN2[j]].X, stars2[tmpN2[j]].Y, stars2[tmpN2[j]].mag);
+	  } 
+	}
+      }
+      j = first_j;
+      i++;
+    }
+    
+    if (PLOTSTUFF) {
+      
+      graphdata.xmin = 0;
+      graphdata.xmax = 2000;
+      graphdata.ymin = 4000;
+      graphdata.ymax =  0;
+      graphdata.style = 2;
+      graphdata.ptype = 2;
+      graphdata.ltype = 0;
+      graphdata.etype = 0;
+      graphdata.color = 0;
+      graphdata.lweight = 0;
+      graphdata.size = 1.5;
+
+      PrepPlotting (Nvect2, &graphdata, 1);
+      PlotVector (Nvect2, xvect2, 0, 1);
+      PlotVector (Nvect2, yvect2, 1, 1);
+      DonePlotting (&graphdata, 1);
+
+      graphdata.xmin = -150;
+      graphdata.xmax = 150;
+      graphdata.ymin = 0;
+      graphdata.ymax =  4000;
+      graphdata.style = 2;
+      graphdata.ptype = 2;
+      graphdata.ltype = 0;
+      graphdata.etype = 0;
+      graphdata.color = 0;
+      graphdata.lweight = 0;
+      graphdata.size = 1.5;
+    
+      PlotReset (0);
+      PrepPlotting (Nvect, &graphdata, 0);
+      PlotVector (Nvect, xvect, 0, 0);
+      PlotVector (Nvect, yvect, 1, 0);
+      DonePlotting (&graphdata, 0);
+      usleep (300000);
+      fprintf (stderr, "plotting %d points\n", Nvect);
+      fprintf (stderr, "type return to continue");
+      fscanf (stdin, "%c", &c);
+      Nvect = 0;
+    }
+
+    /* 
+    if (extras == 1) {
+      extras = 2;
+      halt = last = FALSE;
+      iteration -= 2;
+      radius *= fratio*fratio;
+    }
+    */
+
+    if (MATCHDUMP && mode && last) exit (0);
+    
+    if (NOMATCHDUMP && mode && last) {
+      for (i = 0; i < N2; i++) {
+	XY_to_RD (&RA, &DEC, stars2[i].X, stars2[i].Y, coords);
+	fprintf (stdout, "%f %f %f %f %f\n", RA, DEC, stars2[i].X, stars2[i].Y, stars2[i].mag);
+      }
+      exit (0);
+    }
+    
+    /* calculate the fit parameters */
+    if (!last) { 
+      double XX1, XY1, YX1, YY1, XO1, YO1;
+      double XX0, XY0, YX0, YY0, XO0, YO0;
+      double **matrix, **vector;
+      int NR, NC;
+      
+      if (VERBOSE) fprintf (stderr, "radius: %f, No. of matched stars: %d\n", radius, (int) N);
+      
+      if (N < 3) {
+	fprintf (stderr, "ERROR: too few stars\n");
+	X_O = X_X = X_Y = Y_O = Y_X = Y_Y = 0;
+	return (FALSE);
+      }
+      
+      NR = 3; NC = 2;
+      ALLOCATE (matrix, double *, NR);
+      ALLOCATE (vector, double *, NR);
+      for (i = 0; i < NR; i++) {
+	ALLOCATE (matrix[i], double, NR);
+	ALLOCATE (vector[i], double, NC);
+	bzero (vector[i], NC*sizeof(double));
+	bzero (matrix[i], NR*sizeof(double));
+      }
+
+      matrix[0][0] = R;
+      matrix[0][1] = matrix[1][0] = x;
+      matrix[0][2] = matrix[2][0] = y;
+      matrix[1][2] = matrix[2][1] = xy;
+      matrix[1][1] = x2;
+      matrix[2][2] = y2;
+
+      vector[0][0] = X;
+      vector[1][0] = Xx;
+      vector[2][0] = Xy;
+
+      vector[0][1] = Y;
+      vector[1][1] = Yx;
+      vector[2][1] = Yy;
+
+      gaussj (matrix, NR, vector, NC); 
+      
+      /* 
+      Sx2 = x2 - x*x/N;
+      Sy2 = y2 - y*y/N;
+      Sxy = xy - x*y/N;
+      SXx = Xx - X*x/N;
+      SXy = Xy - X*y/N;
+      SYx = Yx - Y*x/N;
+      SYy = Yy - Y*y/N;
+      */
+
+      XX0 = X_X; XY0 = X_Y; XO0 = X_O;
+      YX0 = Y_X; YY0 = Y_Y; YO0 = Y_O;
+      
+      /* fit parameters relative to rotated frame */
+      /* 
+      XX1 = (SXx*Sy2 - SXy*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+      XY1 = (SXy*Sx2 - SXx*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+      XO1 = X/N - (XX1)*x/N - (XY1)*y/N;
+      
+      YX1 = (SYx*Sy2 - SYy*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+      YY1 = (SYy*Sx2 - SYx*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+      YO1 = Y/N - (YX1)*x/N - (YY1)*y/N;
+      */
+
+      XO1 = vector[0][0];
+      XX1 = vector[1][0];
+      XY1 = vector[2][0];
+			
+      YO1 = vector[0][1];
+      YX1 = vector[1][1];
+      YY1 = vector[2][1];
+
+      fprintf (stderr, "%f %f %f\n", vector[0][0], vector[1][0], vector[2][0]);
+      fprintf (stderr, "%f %f %f\n", vector[0][1], vector[1][1], vector[2][1]);
+
+      /* fit parameters relative to original frame */
+      X_X = XX1*XX0 + XY1*YX0;
+      X_Y = XX1*XY0 + XY1*YY0;
+      X_O = XX1*XO0 + XY1*YO0 + XO1;
+      
+      Y_X = YX1*XX0 + YY1*YX0;
+      Y_Y = YX1*XY0 + YY1*YY0;
+      Y_O = YX1*XO0 + YY1*YO0 + YO1;
+      
+    }
+    dX = sqrt(d2X/N - dX*dX/(N*N));  /* scatter in pixels in the X direction */
+    dY = sqrt(d2Y/N - dY*dY/(N*N));  /* scatter in pixels in the Y direction */
+    dS = hypot (dX, dY) / sqrt(N);
+    if (VERBOSE) {
+      fprintf (stderr, "scatter in pixels: %5.2f x %5.2f -- %5.2f %d %d %d %d\n", dX, dY, dS, halt, last, extras, iteration);
+    }
+# if (0)
+    if (!halt && !extras) {
+      if (iteration > 0) {
+	dSS = (Sprev - dS) / Sprev;
+      } else {
+	dSS = 1.0;
+      }
+      if (dSS < 0.05) { /* no fractional improvement, stop at last value */
+	radius = Rprev * fratio;
+	halt = TRUE;
+	/* recalculate fit parameters on first, get scatter on second, exit on third */
+      }
+      Rprev = radius;
+      Sprev = dS;
+    }
+# endif
+    radius /= fratio;
+  }
+  radius *= fratio;
+  
+  /* convert X_X, etc to coords */ 
+  { 
+    double X0, Y0, S1, S2, p11, p21, p12, p22;
+    double delt, A, B, C, D, dRot;
+    
+    *Nmatch = N;
+    
+    delt = 1.0 / (X_X*Y_Y - X_Y*Y_X);
+    X = (coords[0].crpix1 - X_O);
+    Y = (coords[0].crpix2 - Y_O);
+    X0 = delt * (X*Y_Y - Y*X_Y);
+    Y0 = delt * (Y*X_X - X*Y_X);
+    XY_to_RD (&RA, &DEC, X0, Y0, coords);
+    
+    S1 = coords[0].cdelt1;
+    S2 = coords[0].cdelt2;
+    p11 = coords[0].pc1_1;    p12 = coords[0].pc1_2;
+    p21 = coords[0].pc2_1;    p22 = coords[0].pc2_2;
+    
+    A =  S1*p11*Y_Y - S2*p12*Y_X;   B = S2*p12*X_X - S1*p11*X_Y;
+    C =  S1*p21*Y_Y - S2*p22*Y_X;   D = S2*p22*X_X - S2*p21*X_Y;
+    
+    coords[0].cdelt1 = sqrt (A*A + C*C);
+    coords[0].cdelt2 = sqrt (B*B + D*D);
+    
+    coords[0].pc1_1 = A / coords[0].cdelt1; 
+    coords[0].pc1_2 = B / coords[0].cdelt2; 
+    coords[0].pc2_1 = C / coords[0].cdelt1; 
+    coords[0].pc2_2 = D / coords[0].cdelt2; 
+    
+    coords[0].cdelt1 = coords[0].cdelt1 * delt;
+    coords[0].cdelt2 = coords[0].cdelt2 * delt;
+    if ((fabs(coords[0].cdelt1) > 2.0*ASEC_PIX/3600.0) || 
+	(fabs(coords[0].cdelt1) < 0.5*ASEC_PIX/3600.0) ||
+	(fabs(coords[0].cdelt2) > 2.0*ASEC_PIX/3600.0) || 
+	(fabs(coords[0].cdelt2) < 0.5*ASEC_PIX/3600.0)) {
+      fprintf (stderr, "ERROR: absurd solution\n");
+      return (FALSE);
+    }
+    
+    dRot = coords[0].crval1 - RA ;
+    coords[0].crval1 = RA;
+    coords[0].crval2 = DEC;
+    
+    A = cos (dRot*RAD_DEG);
+    B = sin (dRot*RAD_DEG);
+
+    p11 = coords[0].pc1_1;    p12 = coords[0].pc1_2;
+    p21 = coords[0].pc2_1;    p22 = coords[0].pc2_2;
+    
+    coords[0].pc1_1 = p11*A - p12*B;
+    coords[0].pc1_2 = p11*B + p12*A;
+    coords[0].pc2_1 = p21*A - p22*B;
+    coords[0].pc2_2 = p21*B + p22*A;
+
+  }
+
+  while (coords[0].crval1 < 0) coords[0].crval1 += 360.0;
+  while (coords[0].crval1 > 360.0) coords[0].crval1 -= 360.0;
+
+  *DR = sqrt (SQ(dX*coords[0].cdelt1*3600.0) + SQ(dY*coords[0].cdelt1*3600.0));
+  *Radius = radius;
+
+  if ((mode == 1) && VERBOSE) {
+    fprintf (stderr, "linear astrometric solution:\n");
+    fprintf (stderr, "mode: %s\n", coords[0].ctype);
+    fprintf (stderr, "ref value: %f %f\n", coords[0].crval1, coords[0].crval2);
+    fprintf (stderr, "ref pixel: %f %f\n", coords[0].crpix1, coords[0].crpix2);
+    fprintf (stderr, "ra  terms: %f %f\n", coords[0].pc1_1, coords[0].pc1_2);
+    fprintf (stderr, "dec terms: %f %f\n", coords[0].pc2_1, coords[0].pc2_2);
+    fprintf (stderr, "plt scale: %f %f\n", coords[0].cdelt1, coords[0].cdelt2);
+    fprintf (stderr, "accuracy:  %f %f\n", *DR, *DR / sqrt ((double)(*Nmatch)));
+  }
+
+  return (TRUE);
+
+  
+
+}
Index: /tags/start/Ohana/src/gastro/src/gfit.test.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/gfit.test.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/gfit.test.c	(revision 12606)
@@ -0,0 +1,496 @@
+# include "gastro.h"
+
+/* stars1.X,Y and stars2.X,Y are both in image pixels. 
+   The conversion terms (X_O, X_X, etc) make linear 
+   corrections in pixel coordinates */
+
+int gfit (stars1, stars2, N1, N2, coords, NX, NY, Radius, DR, Nmatch, mode)
+     SStars stars1[], stars2[];
+     int N1, N2, NX, NY, *Nmatch, mode;
+     double *Radius, *DR;
+     Coords *coords;
+{
+  
+  int i, j, iteration, Niter, last, halt, first_j, *Nextra, extras;
+  int *tmpN1, *tmpN2;
+  double dx, dy, Rx, Ry, dr;
+  double X_O, X_X, X_Y, dX;
+  double Y_O, Y_X, Y_Y, dY;
+  double x, y, x2, y2, xy, N, R, wt;
+  double X, Y, Xx, Yy, Xy, Yx;
+  double Dx, Dy, DD, d2X, d2Y, dX_Y, dY_X;
+  double RA, DEC, radius, radius2, scale, fratio;
+  double *tmpX1, *tmpX2, *tmpY1, *tmpY2;
+  double tX1, tX2, tY1, tY2;
+  double Rprev, Sprev, dSS, dS;
+  int *match;
+  double *dmatch;
+
+  char c;
+  typedef struct {
+    double xmin, xmax, ymin, ymax;
+    int style, ptype, ltype, etype, color;
+    double lweight, size;
+  } Graphdata;
+  Graphdata graphdata;
+  float *xvect, *yvect;
+  float *xvect2, *yvect2;
+  int Nvect, NVECT;
+  int Nvect2, NVECT2;
+  
+  if (PLOTSTUFF) {
+    Nvect2 = 0;
+    NVECT2 = MAX(N1, N2);
+    Nvect = 0;
+    NVECT = MAX(N1, N2);
+    ALLOCATE (xvect, float, NVECT);
+    ALLOCATE (yvect, float, NVECT);
+    ALLOCATE (xvect2, float, NVECT2);
+    ALLOCATE (yvect2, float, NVECT2);
+  }
+    
+
+  /* match arrays, init to -1 (no match) */
+  ALLOCATE (match, int, N2);
+  ALLOCATE (dmatch, double, N2);
+  for (i = 0; i < N2; i++) match[i] = -1;
+
+  /* allocate space for star coords */
+  ALLOCATE (tmpX1, double, N1);
+  ALLOCATE (tmpY1, double, N1);
+  ALLOCATE (tmpN1, int, N1);
+  
+  ALLOCATE (tmpX2, double, N2);
+  ALLOCATE (tmpY2, double, N2);
+  ALLOCATE (tmpN2, int, N2);
+  ALLOCATE (Nextra, int, N2);
+  bzero (Nextra, sizeof(int) * N2);
+
+  /* assign and sort list */
+  for (i = 0; i < N1; i++) {
+    tmpX1[i] = stars1[i].X;
+    tmpY1[i] = stars1[i].Y;
+    tmpN1[i] = i;
+  }
+  if (N1 > 1) sort_lists (tmpX1, tmpY1, tmpN1, N1);
+
+   
+  /* choose iteration ranges */
+  fratio = 1.41421;
+  extras = halt = last = FALSE;
+  radius = *Radius;
+  Niter = 2 + log (radius/MINIMUM_RADIUS) / log (fratio);
+  
+  /* initial values for fit coeffs */
+  X_X = 1; X_Y = 0; X_O = 0;
+  Y_X = 0; Y_Y = 1; Y_O = 0;
+  
+  for (iteration = 0; iteration < Niter; iteration ++) {
+
+    if (iteration >= Niter - 1) { /* next loop is the last one */
+      radius *= fratio;
+      last = TRUE;
+    }
+
+    /* setup and define */
+    radius2 = radius*radius;
+    dX = dY = d2X = d2Y = x = y = x2 = y2 = xy = X = Y = Xx = Xy = Yx = Yy = N = R = 0;
+    for (i = 0; i < N2; i++) {
+      tmpX2[i] = (X_O) + (X_X)*stars2[i].X + (X_Y)*stars2[i].Y;
+      tmpY2[i] = (Y_O) + (Y_X)*stars2[i].X + (Y_Y)*stars2[i].Y;
+      tmpN2[i] = i;
+    }
+    
+    if (PLOTSTUFF) {
+      for (i = 0; i < N1; i++) {
+	xvect2[i] = tmpX1[i];
+	yvect2[i] = tmpY1[i];
+      }
+      Nvect2 = N1;
+
+      graphdata.xmin = 0;
+      graphdata.xmax = 2000;
+      graphdata.ymin = 4000;
+      graphdata.ymax =  0;
+      graphdata.style = 2;
+      graphdata.ptype = 3;
+      graphdata.ltype = 0;
+      graphdata.etype = 0;
+      graphdata.color = 0;
+      graphdata.lweight = 0;
+      graphdata.size = 1.5;
+    
+      PlotReset (1);
+      PrepPlotting (Nvect2, &graphdata, 1);
+      PlotVector (Nvect2, xvect2, 0, 1);
+      PlotVector (Nvect2, yvect2, 1, 1);
+      DonePlotting (&graphdata, 1);
+      Nvect2 = 0;
+
+      for (i = 0; i < N2; i++) {
+	xvect2[i] = tmpX2[i];
+	yvect2[i] = tmpY2[i];
+      }
+      Nvect2 = N2;
+
+      graphdata.ptype = 1;
+
+      PrepPlotting (Nvect2, &graphdata, 1);
+      PlotVector (Nvect2, xvect2, 0, 1);
+      PlotVector (Nvect2, yvect2, 1, 1);
+      DonePlotting (&graphdata, 1);
+      Nvect2 = 0;
+    }
+
+    if (N2 > 1) sort_lists (tmpX2, tmpY2, tmpN2, N2);
+    
+    /* find matched stars */
+    for (i = j = 0; (i < N1) && (j < N2); ) {  
+      tX1 = tmpX1[i];
+      tX2 = tmpX2[j];
+      Dx = tX1 - tX2;
+      if (Dx <= -2.0*radius) {
+	i++;
+	continue;
+      }
+      if (Dx >= 2.0*radius) {
+	j++;
+	continue;
+      }
+
+      /* in the right range */
+      first_j = j;
+      for (; (Dx > -2.0*radius) && (j < N2); j++) {
+	tY1 = tmpY1[i];
+	tX2 = tmpX2[j];
+	tY2 = tmpY2[j];
+	Dx = tX1 - tX2;
+	Dy = tY1 - tY2;
+	DD = Dx*Dx + Dy*Dy;
+	/* stars matched, keep only if closest */
+	if (DD < radius2) {
+	  if (match[j] == -1) {
+	    match[j] = i;
+	    dmatch[j] = DD;
+	  } 
+	  if (DD < dmatch[j]) {
+	    match[j] = i;
+	    dmatch[j] = DD;
+	  } 
+	}
+      }
+      j = first_j;
+      i++;
+    }
+    
+    /* measure statistics for matched stars */
+    for (j = 0; j < N2; j++) {  
+      if (match[j] == -1) continue;
+      i = match[j];
+
+      tX1 = tmpX1[i];
+      tX2 = tmpX2[j];
+      Dx = tX1 - tX2;
+      tY1 = tmpY1[i];
+      tY2 = tmpY2[j];
+      Dy = tY1 - tY2;
+      DD = Dx*Dx + Dy*Dy;
+      
+      if (PLOTSTUFF) {
+	xvect[Nvect] = Dx;
+	yvect[Nvect] = tmpY1[i];
+	Nvect ++;
+	if (Nvect == NVECT) {
+	  NVECT += 100;
+	  REALLOCATE (xvect, float, NVECT);
+	  REALLOCATE (yvect, float, NVECT);
+	}
+	xvect2[Nvect2] = tmpX1[i];
+	yvect2[Nvect2] = tmpY1[i];
+	Nvect2 ++;
+	if (Nvect2 == NVECT2 - 1) {
+	  NVECT2 += 100;
+	  REALLOCATE (xvect2, float, NVECT2);
+	  REALLOCATE (yvect2, float, NVECT2);
+	}
+      }
+      /* wt = sqrt(sqrt(DD)); */
+      wt = DD + 1;
+      dX += Dx;
+      dY += Dy;
+      d2X += Dx*Dx;
+      d2Y += Dy*Dy;
+      x  += tX2/wt;
+      y  += tY2/wt;
+      x2 += tX2*tX2/wt;
+      y2 += tY2*tY2/wt;
+      xy += tX2*tY2/wt;
+      X  += tX1/wt;
+      Y  += tY1/wt;
+      Xx += tX1*tX2/wt;
+      Xy += tX1*tY2/wt;
+      Yx += tY1*tX2/wt;
+      Yy += tY1*tY2/wt;
+      N  += 1.0;
+      R  += 1.0/wt;
+      if (last && MATCHDUMP && mode) {
+	XY_to_RD (&RA, &DEC, stars2[tmpN2[j]].X, stars2[tmpN2[j]].Y, coords);
+	fprintf (stdout, "%f %f %f %f %f\n", RA, DEC, stars2[tmpN2[j]].X, stars2[tmpN2[j]].Y, stars2[tmpN2[j]].mag);
+      } 
+    }
+    
+    if (PLOTSTUFF) {
+      
+      graphdata.xmin = 0;
+      graphdata.xmax = 2000;
+      graphdata.ymin = 4000;
+      graphdata.ymax =  0;
+      graphdata.style = 2;
+      graphdata.ptype = 2;
+      graphdata.ltype = 0;
+      graphdata.etype = 0;
+      graphdata.color = 0;
+      graphdata.lweight = 0;
+      graphdata.size = 1.5;
+
+      PrepPlotting (Nvect2, &graphdata, 1);
+      PlotVector (Nvect2, xvect2, 0, 1);
+      PlotVector (Nvect2, yvect2, 1, 1);
+      DonePlotting (&graphdata, 1);
+
+      graphdata.xmin = -150;
+      graphdata.xmax = 150;
+      graphdata.ymin = 0;
+      graphdata.ymax =  4000;
+      graphdata.style = 2;
+      graphdata.ptype = 2;
+      graphdata.ltype = 0;
+      graphdata.etype = 0;
+      graphdata.color = 0;
+      graphdata.lweight = 0;
+      graphdata.size = 1.5;
+    
+      PlotReset (0);
+      PrepPlotting (Nvect, &graphdata, 0);
+      PlotVector (Nvect, xvect, 0, 0);
+      PlotVector (Nvect, yvect, 1, 0);
+      DonePlotting (&graphdata, 0);
+      usleep (300000);
+      fprintf (stderr, "plotting %d points\n", Nvect);
+      fprintf (stderr, "type return to continue");
+      fscanf (stdin, "%c", &c);
+      Nvect = 0;
+    }
+
+    /* 
+    if (extras == 1) {
+      extras = 2;
+      halt = last = FALSE;
+      iteration -= 2;
+      radius *= fratio*fratio;
+    }
+    */
+
+    if (MATCHDUMP && mode && last) exit (0);
+    
+    if (NOMATCHDUMP && mode && last) {
+      for (i = 0; i < N2; i++) {
+	XY_to_RD (&RA, &DEC, stars2[i].X, stars2[i].Y, coords);
+	fprintf (stdout, "%f %f %f %f %f\n", RA, DEC, stars2[i].X, stars2[i].Y, stars2[i].mag);
+      }
+      exit (0);
+    }
+    
+    /* calculate the fit parameters */
+    if (!last) { 
+      double Sx2, Sy2, Sxy, SXx, SXy, SYx, SYy;
+      double XX1, XY1, YX1, YY1, XO1, YO1;
+      double XX0, XY0, YX0, YY0, XO0, YO0;
+      double **matrix, **vector;
+      int NR, NC;
+      
+      if (VERBOSE) fprintf (stderr, "radius: %f, No. of matched stars: %d\n", radius, (int) N);
+      
+      if (N < 3) {
+	fprintf (stderr, "ERROR: too few stars\n");
+	X_O = X_X = X_Y = Y_O = Y_X = Y_Y = 0;
+	return (FALSE);
+      }
+      
+      NR = 3; NC = 2;
+      ALLOCATE (matrix, double *, NR);
+      ALLOCATE (vector, double *, NR);
+      for (i = 0; i < NR; i++) {
+	ALLOCATE (matrix[i], double, NR);
+	ALLOCATE (vector[i], double, NC);
+	bzero (vector[i], NC*sizeof(double));
+	bzero (matrix[i], NR*sizeof(double));
+      }
+
+      matrix[0][0] = R;
+      matrix[0][1] = matrix[1][0] = x;
+      matrix[0][2] = matrix[2][0] = y;
+      matrix[1][2] = matrix[2][1] = xy;
+      matrix[1][1] = x2;
+      matrix[2][2] = y2;
+
+      vector[0][0] = X;
+      vector[1][0] = Xx;
+      vector[2][0] = Xy;
+
+      vector[0][1] = Y;
+      vector[1][1] = Yx;
+      vector[2][1] = Yy;
+
+      gaussj (matrix, NR, vector, NC); 
+      
+      /* 
+      Sx2 = x2 - x*x/N;
+      Sy2 = y2 - y*y/N;
+      Sxy = xy - x*y/N;
+      SXx = Xx - X*x/N;
+      SXy = Xy - X*y/N;
+      SYx = Yx - Y*x/N;
+      SYy = Yy - Y*y/N;
+      */
+
+      XX0 = X_X; XY0 = X_Y; XO0 = X_O;
+      YX0 = Y_X; YY0 = Y_Y; YO0 = Y_O;
+      
+      /* fit parameters relative to rotated frame */
+      /* 
+      XX1 = (SXx*Sy2 - SXy*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+      XY1 = (SXy*Sx2 - SXx*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+      XO1 = X/N - (XX1)*x/N - (XY1)*y/N;
+      
+      YX1 = (SYx*Sy2 - SYy*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+      YY1 = (SYy*Sx2 - SYx*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+      YO1 = Y/N - (YX1)*x/N - (YY1)*y/N;
+      */
+
+      XO1 = vector[0][0];
+      XX1 = vector[1][0];
+      XY1 = vector[2][0];
+			
+      YO1 = vector[0][1];
+      YX1 = vector[1][1];
+      YY1 = vector[2][1];
+
+      fprintf (stderr, "%f %f %f\n", vector[0][0], vector[1][0], vector[2][0]);
+      fprintf (stderr, "%f %f %f\n", vector[0][1], vector[1][1], vector[2][1]);
+
+      /* fit parameters relative to original frame */
+      X_X = XX1*XX0 + XY1*YX0;
+      X_Y = XX1*XY0 + XY1*YY0;
+      X_O = XX1*XO0 + XY1*YO0 + XO1;
+      
+      Y_X = YX1*XX0 + YY1*YX0;
+      Y_Y = YX1*XY0 + YY1*YY0;
+      Y_O = YX1*XO0 + YY1*YO0 + YO1;
+      
+    }
+    dX = sqrt(d2X/N - dX*dX/(N*N));  /* scatter in pixels in the X direction */
+    dY = sqrt(d2Y/N - dY*dY/(N*N));  /* scatter in pixels in the Y direction */
+    dS = hypot (dX, dY) / sqrt(N);
+    if (VERBOSE) {
+      fprintf (stderr, "scatter in pixels: %5.2f x %5.2f -- %5.2f %d %d %d %d\n", dX, dY, dS, halt, last, extras, iteration);
+    }
+# if (0)
+    if (!halt && !extras) {
+      if (iteration > 0) {
+	dSS = (Sprev - dS) / Sprev;
+      } else {
+	dSS = 1.0;
+      }
+      if (dSS < 0.05) { /* no fractional improvement, stop at last value */
+	radius = Rprev * fratio;
+	halt = TRUE;
+	/* recalculate fit parameters on first, get scatter on second, exit on third */
+      }
+      Rprev = radius;
+      Sprev = dS;
+    }
+# endif
+    radius /= fratio;
+  }
+  radius *= fratio;
+  
+  /* convert X_X, etc to coords */ 
+  { 
+    double X0, Y0, S1, S2, p11, p21, p12, p22;
+    double delt, A, B, C, D, dRot;
+    
+    *Nmatch = N;
+    
+    delt = 1.0 / (X_X*Y_Y - X_Y*Y_X);
+    X = (coords[0].crpix1 - X_O);
+    Y = (coords[0].crpix2 - Y_O);
+    X0 = delt * (X*Y_Y - Y*X_Y);
+    Y0 = delt * (Y*X_X - X*Y_X);
+    XY_to_RD (&RA, &DEC, X0, Y0, coords);
+    
+    S1 = coords[0].cdelt1;
+    S2 = coords[0].cdelt2;
+    p11 = coords[0].pc1_1;    p12 = coords[0].pc1_2;
+    p21 = coords[0].pc2_1;    p22 = coords[0].pc2_2;
+    
+    A =  S1*p11*Y_Y - S2*p12*Y_X;   B = S2*p12*X_X - S1*p11*X_Y;
+    C =  S1*p21*Y_Y - S2*p22*Y_X;   D = S2*p22*X_X - S2*p21*X_Y;
+    
+    coords[0].cdelt1 = sqrt (A*A + C*C);
+    coords[0].cdelt2 = sqrt (B*B + D*D);
+    
+    coords[0].pc1_1 = A / coords[0].cdelt1; 
+    coords[0].pc1_2 = B / coords[0].cdelt2; 
+    coords[0].pc2_1 = C / coords[0].cdelt1; 
+    coords[0].pc2_2 = D / coords[0].cdelt2; 
+    
+    coords[0].cdelt1 = coords[0].cdelt1 * delt;
+    coords[0].cdelt2 = coords[0].cdelt2 * delt;
+    if ((fabs(coords[0].cdelt1) > 2.0*ASEC_PIX/3600.0) || 
+	(fabs(coords[0].cdelt1) < 0.5*ASEC_PIX/3600.0) ||
+	(fabs(coords[0].cdelt2) > 2.0*ASEC_PIX/3600.0) || 
+	(fabs(coords[0].cdelt2) < 0.5*ASEC_PIX/3600.0)) {
+      fprintf (stderr, "ERROR: absurd solution\n");
+      return (FALSE);
+    }
+    
+    dRot = coords[0].crval1 - RA ;
+    coords[0].crval1 = RA;
+    coords[0].crval2 = DEC;
+    
+    A = cos (dRot*RAD_DEG);
+    B = sin (dRot*RAD_DEG);
+
+    p11 = coords[0].pc1_1;    p12 = coords[0].pc1_2;
+    p21 = coords[0].pc2_1;    p22 = coords[0].pc2_2;
+    
+    coords[0].pc1_1 = p11*A - p12*B;
+    coords[0].pc1_2 = p11*B + p12*A;
+    coords[0].pc2_1 = p21*A - p22*B;
+    coords[0].pc2_2 = p21*B + p22*A;
+
+  }
+
+  while (coords[0].crval1 < 0) coords[0].crval1 += 360.0;
+  while (coords[0].crval1 > 360.0) coords[0].crval1 -= 360.0;
+
+  *DR = sqrt (SQ(dX*coords[0].cdelt1*3600.0) + SQ(dY*coords[0].cdelt1*3600.0));
+  *Radius = radius;
+
+  if ((mode == 1) && VERBOSE) {
+    fprintf (stderr, "linear astrometric solution:\n");
+    fprintf (stderr, "mode: %s\n", coords[0].ctype);
+    fprintf (stderr, "ref value: %f %f\n", coords[0].crval1, coords[0].crval2);
+    fprintf (stderr, "ref pixel: %f %f\n", coords[0].crpix1, coords[0].crpix2);
+    fprintf (stderr, "ra  terms: %f %f\n", coords[0].pc1_1, coords[0].pc1_2);
+    fprintf (stderr, "dec terms: %f %f\n", coords[0].pc2_1, coords[0].pc2_2);
+    fprintf (stderr, "plt scale: %f %f\n", coords[0].cdelt1, coords[0].cdelt2);
+    fprintf (stderr, "accuracy:  %f %f\n", *DR, *DR / sqrt ((double)(*Nmatch)));
+  }
+
+  return (TRUE);
+
+  
+
+}
Index: /tags/start/Ohana/src/gastro/src/gfitpoly.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/gfitpoly.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/gfitpoly.c	(revision 12606)
@@ -0,0 +1,387 @@
+# include "gastro.h"
+
+void gfitpoly (SStars *stars1, SStars *stars2, int N1, int N2, Coords *coords, double *Radius, double *DR, int *Nmatch) {
+  
+  int i, j, m, n, M, N;
+  int first_j, last;
+  int *tmpN1, *tmpN2;
+  int NORDER, NTERM, NPARS, NPOWR;
+  double **sum, **xsum, **ysum;
+  double **matrix, **vector;
+  double Dx, Dy, DD, dX, dY, d2X, d2Y;
+  double radius, radius2;
+  double *tmpX1, *tmpX2, *tmpY1, *tmpY2;
+  double tX1, tX2, tY1, tY2;
+  double xterm, yterm, term, max;
+
+  NORDER = NPOLYTERMS;
+  NPOWR = NORDER + 1;
+  NTERM = 2*NORDER + 1;
+  NPARS = (NORDER + 1)*(NORDER + 2) / 2;
+  if (NPOLYTERMS < 2) {
+    coords[0].Npolyterms = 0;
+    {
+      double nominal_det, measure_det, min_det, max_det, d1, d2, diffangle, tmp;
+      
+      nominal_det = CCD_PC1_1 * CCD_PC2_2 - CCD_PC1_2 * CCD_PC2_1;
+      min_det = nominal_det / 1.05;
+      max_det = nominal_det * 1.05;
+      if (min_det > max_det) {
+	tmp = max_det; max_det = min_det; min_det = tmp;
+      }
+      
+      measure_det = coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1;
+      if ((measure_det > max_det) || (measure_det < min_det)) {
+	fprintf (stderr, "absurd solution, not cartesian\n");
+	*DR = 1e9;
+      }
+      d1 = hypot (coords[0].pc1_2, coords[0].pc1_1);
+      d2 = hypot (coords[0].pc2_2, coords[0].pc2_1);
+      diffangle = fabs (coords[0].pc2_1*coords[0].pc1_1 + coords[0].pc1_2*coords[0].pc2_2) / (d1*d2);
+      if (diffangle > MAX_NONLINEAR) {
+	fprintf (stderr, "absurd solution, not cartesian\n");
+	*DR = 1e9;
+      }
+    }
+    return;
+  }
+
+  fprintf (stderr, "\nattempting higher order fit\n");
+
+  /* allocate space for star coords */
+  ALLOCATE (tmpX1, double, N1);
+  ALLOCATE (tmpY1, double, N1);
+  ALLOCATE (tmpN1, int, N1);
+
+  ALLOCATE (tmpX2, double, N2);
+  ALLOCATE (tmpY2, double, N2);
+  ALLOCATE (tmpN2, int, N2);
+
+  /* assign and sort list */
+  for (i = 0; i < N1; i++) {
+    tmpX1[i] = stars1[i].X;
+    tmpY1[i] = stars1[i].Y;
+    tmpN1[i] = i;
+  }
+  if (N1 > 1) sort_lists (tmpX1, tmpY1, tmpN1, N1);
+  for (i = 0; i < N2; i++) {
+    tmpX2[i] = stars2[i].X;
+    tmpY2[i] = stars2[i].Y;
+    tmpN2[i] = i;
+  }
+  if (N2 > 1) sort_lists (tmpX2, tmpY2, tmpN2, N2);
+  
+  /* choose iteration ranges */
+  radius = MINIMUM_RADIUS;
+  radius2 = radius*radius;
+
+  /* allocate arrays for fit solution */
+  ALLOCATE (sum, double *, NTERM);
+  ALLOCATE (xsum, double *, NTERM);
+  ALLOCATE (ysum, double *, NTERM);
+  for (i = 0; i < NTERM; i++) {
+    ALLOCATE (sum[i], double, NTERM);
+    bzero (sum[i], NTERM*sizeof(double));
+    ALLOCATE (xsum[i], double, NTERM);
+    bzero (xsum[i], NTERM*sizeof(double));
+    ALLOCATE (ysum[i], double, NTERM);
+    bzero (ysum[i], NTERM*sizeof(double));
+  }
+  ALLOCATE (matrix, double *, NPARS);
+  ALLOCATE (vector, double *, NPARS);
+  for (i = 0; i < NPARS; i++) {
+    ALLOCATE (matrix[i], double, NPARS);
+    ALLOCATE (vector[i], double, 2);
+    bzero (vector[i], 2*sizeof(double));
+    bzero (matrix[i], NPARS*sizeof(double));
+  }
+  
+  /* do the following loop twice.  
+     on first pass, find the coeffs.
+     on next pass, find just the residuals */
+  for (last = 0; last < 2; last++) {
+    if (last) {
+      /* assign values based on determined coeffs */
+      for (i = 0; i < N1; i++) {
+	tmpX1[i] = tmpY1[i] = 0;
+	yterm = 1;
+	for (m = 0; m < NPOWR; m++) { 
+	  xterm = 1;
+	  for (n = 0; n < NPOWR - m; n++) {
+	    tmpX1[i] += xterm*yterm*xsum[n][m];
+	    tmpY1[i] += xterm*yterm*ysum[n][m];
+	    xterm *= stars1[i].X;
+	  }	
+	  yterm *= stars1[i].Y;
+	}
+	tmpN1[i] = i;
+      }
+      if (N1 > 1) sort_lists (tmpX1, tmpY1, tmpN1, N1);
+      dX = dY = d2X = d2Y = N = 0;
+    }
+    /* find matched stars */
+    for (i = j = 0; (i < N1) && (j < N2); ) {  
+      tX1 = tmpX1[i];
+      tX2 = tmpX2[j];
+      Dx = tX1 - tX2;
+      if (Dx <= -2.0*radius) {
+	i++;
+	continue;
+      }
+      if (Dx >= 2.0*radius) {
+	j++;
+	continue;
+      }
+      /* in the right range */
+      first_j = j;
+      for (; (Dx > -2.0*radius) && (j < N2); j++) {
+	tY1 = tmpY1[i];
+	tX2 = tmpX2[j];
+	tY2 = tmpY2[j];
+	Dx = tX1 - tX2;
+	Dy = tY1 - tY2;
+	DD = Dx*Dx + Dy*Dy;
+	/* stars matched */
+	if (DD < radius2) {
+	  if (last) {  /* calculate residuals */
+	    dX += Dx;
+	    dY += Dy;
+	    d2X += Dx*Dx;
+	    d2Y += Dy*Dy;
+	    N  += 1.0; 
+	  } else {    /* accumulate data for coeffs */
+	    xterm = 1;
+	    for (n = 0; n < NTERM; n++) {
+	      yterm = 1;
+	      for (m = 0; m < NTERM; m++) {
+		term = xterm*yterm;
+		if (n+m < NTERM) {
+		  sum[n][m] += term;
+		}
+		if (n+m < NPOWR) {
+		  xsum[n][m] += tX2*term;
+		  ysum[n][m] += tY2*term;
+		}
+		yterm *= tY1;
+	      }
+	      xterm *= tX1;
+	    }
+	  }
+	}
+      }
+      j = first_j;
+      i++;
+    }
+    
+    if (!last) { /* calculate polyterm coeffs */
+      fprintf (stderr, "matched %.0f stars for polyterms\n", sum[0][0]);
+      i = 0;
+      for (m = 0; m < NPOWR; m++) {
+	for (n = 0; n < NPOWR - m; n++, i++) {
+	  vector[i][0] = xsum[n][m];
+	  vector[i][1] = ysum[n][m];
+	}	
+      }
+      j = 0;
+      for (M = 0; M < NPOWR; M++) {
+	for (N = 0; N < NPOWR - M; N++, j++) {
+	  i = 0;
+	  for (m = 0; m < NPOWR; m++) {
+	    for (n = 0; n < NPOWR - m; n++, i++) {
+	      matrix[i][j] = sum[n+N][m+M];
+	    }	
+	  }
+	}
+      }       
+      max = 0.0;
+      for (i = 0; i < NPARS; i++) {
+	for (j = 0; j < NPARS; j++) {
+	  max = MAX (max, fabs(matrix[i][j]));
+	}
+	max = MAX (max, fabs(vector[i][0]));
+	max = MAX (max, fabs(vector[i][1]));
+      }
+      for (i = 0; i < NPARS; i++) {
+	for (j = 0; j < NPARS; j++) {
+	  matrix[i][j] /= max;
+	}
+	vector[i][0] /= max;
+	vector[i][1] /= max;
+      }
+      /* svd (matrix, NPARS, vector, 2);  */
+      gaussj (matrix, NPARS, vector, 2); 
+      i = 0;
+      for (m = 0; m < NPOWR; m++) {
+	for (n = 0; n < NPOWR - m; n++, i++) {
+	  xsum[n][m] = vector[i][0];
+	  ysum[n][m] = vector[i][1];
+	}	
+      }
+      i = 0;
+      for (m = 0; m < NPOWR; m++) {
+	for (n = 0; n < NPOWR - m; n++, i++) {
+	  fprintf (stderr, "RA x^%dy^%d: %10.4g    DEC x^%dy^%d: %10.4g \n", 
+		   n, m, vector[i][0], n, m, vector[i][1]);
+	}	
+      }
+    } else {
+      fprintf (stderr, "%d stars matched for residuals\n", N);
+      
+      dX = sqrt(d2X/N - dX*dX/(N*N));  /* scatter in pixels in the X direction */
+      dY = sqrt(d2Y/N - dY*dY/(N*N));  /* scatter in pixels in the Y direction */
+      if (VERBOSE) fprintf (stderr, "scatter in pixels: %5.2f x %5.2f -- %5.2f\n", dX, dY, hypot(dX,dY) / sqrt(N));
+      *DR = sqrt (SQ(dX*coords[0].cdelt1*3600.0) + SQ(dY*coords[0].cdelt1*3600.0));
+      *Nmatch = N;
+
+    }
+  } 
+
+  /* convert new terms to adjustments in coords and to polyterms */
+  {
+    double S1, S2, p11, p12, p21, p22;
+    double a0, a1, a2, b0, b1, b2, det;
+    double X, Y;
+    int Np, Nv;
+    
+    S1 = coords[0].cdelt1;
+    S2 = coords[0].cdelt2;
+    p11 = coords[0].pc1_1;    p12 = coords[0].pc1_2;
+    p21 = coords[0].pc2_1;    p22 = coords[0].pc2_2;
+    
+    /* get the correct vector entries for the linear terms */
+    N = mk_vector (0, 0, NORDER);
+    a0 = vector[N][0];  b0 = vector[N][1];
+    N = mk_vector (1, 0, NORDER);
+    a1 = vector[N][0];  b1 = vector[N][1];
+    N = mk_vector (0, 1, NORDER);
+    a2 = vector[N][0];  b2 = vector[N][1];
+
+    det = 1.0 / (a1*b2 - a2*b1);
+
+    coords[0].pc1_1 = p11*a1 + p12*b1*(S2/S1);
+    coords[0].pc2_1 = p21*a1 + p22*b1*(S2/S1);
+    
+    coords[0].pc1_2 = p12*b2 + p11*a2*(S1/S2);
+    coords[0].pc2_2 = p22*b2 + p21*a2*(S1/S2);
+    
+    X = (coords[0].crpix1 - a0);
+    Y = (coords[0].crpix2 - b0);
+    coords[0].crpix1 = det*(X*b2 - Y*a2);
+    coords[0].crpix2 = det*(Y*a1 - X*b1);
+
+    coords[0].Npolyterms = NORDER;
+    strcpy (coords[0].ctype, "DEC--PLY");
+
+    /* generate higher order terms from vector */
+
+    for (i = 0; i < NORDER + 1; i++) {
+      for (j = 0; j < (NORDER - i + 1); j++) {
+	if (i + j < 2) continue;
+	Np = mk_polyterm (i, j, NORDER);
+	Nv = mk_vector (i, j, NORDER);
+	coords[0].polyterms[Np][0] = det*(vector[Nv][0]*b2  - vector[Nv][1]*a2);  /* x2 y0 */
+	coords[0].polyterms[Np][1] = det*(vector[Nv][1]*a1  - vector[Nv][0]*b1);  /* x2 y0 */
+      }
+    }
+  }
+
+  while (coords[0].crval1 < 0) coords[0].crval1 += 360.0;
+  while (coords[0].crval1 > 360.0) coords[0].crval1 -= 360.0;
+
+  {
+    double nominal_det, measure_det, min_det, max_det, tmp;
+    
+    nominal_det = CCD_PC1_1 * CCD_PC2_2 - CCD_PC1_2 * CCD_PC2_1;
+    min_det = nominal_det / 1.05;
+    max_det = nominal_det * 1.05;
+    if (min_det > max_det) {
+      tmp = max_det; max_det = min_det; min_det = tmp;
+    }
+    
+    measure_det = coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1;
+    if ((measure_det > max_det) || (measure_det < min_det)) {
+      fprintf (stderr, "absurd solution, not cartesian: %f (%f - %f)\n", measure_det, max_det, min_det);
+      *DR = 1e9;
+    }
+  }
+}
+
+int mk_polyterm (int n, int m, int norder) {
+  
+  int i, nt, N;
+  
+  N = 0;
+  nt = n + m;
+  for (i = 2; i < nt; i++) {
+    N += i + 1;
+  }
+  N += m;
+  return (N);
+}
+
+int mk_vector (int n, int m, int norder) {
+  
+  int i, N;
+  
+  N = 0;
+  for (i = 0; i < m; i++) {
+    N += (norder - i + 1);
+  }
+  N += n;
+  return (N);
+}
+
+
+
+/**********************
+
+  vector vs polyterms:
+
+  the variable 'vector' is similar to, but not exactly like polyterms. 
+  vector[i][j] provides coeffs for all of the x,y terms, 
+    polyterms[i][j] only provides coeffs for the terms or order > 2.
+
+  vector[i][j] and polyterms[i][j] also use a slightly different order:
+
+  vector[i][j] runs in this order:
+
+                   n     m  norder = 3
+  vector[0][0] * x^0 * y^0
+  vector[1][0] * x^1 * y^0
+  vector[2][0] * x^2 * y^0
+  vector[3][0] * x^3 * y^0
+  vector[4][0] * x^0 * y^1
+  vector[5][0] * x^1 * y^1
+  vector[6][0] * x^2 * y^1
+  vector[7][0] * x^0 * y^2
+  vector[8][0] * x^1 * y^2
+  vector[9][0] * x^0 * y^3
+
+  to generate the vector entry from n, m, norder:
+  N = 0;
+  for (i = 0; i < m; i++) {
+    N += (norder - i + 1);
+  }
+  N += n;
+
+  polyterms[i][j] runs in this order:
+
+                      n     m
+  polyterms[0][0] * x^2 * y^0 = vector[2][0]
+  polyterms[1][0] * x^1 * y^1 = vector[5][0]
+  polyterms[2][0] * x^0 * y^2 = vector[7][0]
+  polyterms[3][0] * x^3 * y^0 = vector[3][0]
+  polyterms[4][0] * x^2 * y^1 = vector[6][0]
+  polyterms[5][0] * x^1 * y^2 = vector[8][0]
+  polyterms[6][0] * x^0 * y^3 = vector[9][0]
+  
+  to generate the polyterms entry from n, m, norder:
+
+  N = 0;
+  nt = n + m;
+  for (i = 2; i < nt; i++) {
+    N += i + 1;
+  }
+  N += m;
+
+  */
Index: /tags/start/Ohana/src/gastro/src/gheader.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/gheader.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/gheader.c	(revision 12606)
@@ -0,0 +1,135 @@
+# include "gastro.h"
+
+void gheader (char *file, Coords coords, double dR, int Nmatch) {
+
+  Header header;
+  FILE *f, *g;
+  int i, oldsize, nbytes, status;
+  char line[1024];
+
+  if (!fits_read_header (file, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s (3)\n", file);
+    exit(0);
+  }
+  oldsize = header.size;
+
+  if (NEWPHOTCODE) {
+    /* we are going to write the photcode into the header
+       here we are just checking that the photcode provided
+       is a valid code */
+    if (!LoadPhotcodes (PhotCodeFile)) {
+      fprintf (stderr, "error loading photcodes\n");
+      exit (0);
+    }
+    if (!GetPhotcodeCodebyName (PHOTCODE)) {
+      fprintf (stderr, "ERROR: photcode not found in photcode table\n");
+      exit (0);
+    }
+    fits_modify (&header, "PHOTCODE", "%s", 1, PHOTCODE);
+  }    
+  
+  if (Nmatch < 2) {
+    fits_modify (&header, "NASTRO", "%d", 1, 0);
+    fits_modify (&header, "NASTRO", "%C", 1, "number of stars used for astrometry");
+    goto skipstuff;
+  }
+  
+  fits_modify (&header, "NASTRO", "%d", 1, Nmatch);
+  fits_modify (&header, "NASTRO", "%C", 1, "number of stars used for astrometry");
+
+  if (coords.Npolyterms > 1) {
+    fits_modify (&header, "CTYPE1",   "%s",  1, "RA---PLY");
+    fits_modify (&header, "CTYPE2",   "%s",  1, "DEC--PLY");
+  } else {
+    fits_modify (&header, "CTYPE1",   "%s",  1, "RA---TAN");
+    fits_modify (&header, "CTYPE2",   "%s",  1, "DEC--TAN");
+  }    
+  fits_modify (&header, "CDELT1",   "%le", 1, coords.cdelt1); 
+  fits_modify (&header, "CDELT2",   "%le", 1, coords.cdelt2);
+  fits_modify (&header, "CRVAL1",   "%lf", 1, coords.crval1);
+  fits_modify (&header, "CRVAL2",   "%lf", 1, coords.crval2);  
+  fits_modify (&header, "CRPIX1",   "%lf", 1, coords.crpix1);
+  fits_modify (&header, "CRPIX2",   "%lf", 1, coords.crpix2);
+  fits_modify (&header, "PC001001", "%le", 1, coords.pc1_1);
+  fits_modify (&header, "PC001002", "%le", 1, coords.pc1_2);
+  fits_modify (&header, "PC002001", "%le", 1, coords.pc2_1);
+  fits_modify (&header, "PC002002", "%le", 1, coords.pc2_2);
+  fits_modify (&header, "NPLYTERM", "%d", 1, coords.Npolyterms);
+  if (coords.Npolyterms > 1) {
+    /* RA Terms */
+    fits_modify (&header, "PCA1X2Y0", "%le", 1, coords.polyterms[0][0]);   /* polyterms[0]); */
+    fits_modify (&header, "PCA1X1Y1", "%le", 1, coords.polyterms[1][0]);   /* polyterms[1]); */
+    fits_modify (&header, "PCA1X0Y2", "%le", 1, coords.polyterms[2][0]);   /* polyterms[2]); */
+
+    if (coords.Npolyterms > 2) {
+      fits_modify (&header, "PCA1X3Y0", "%le", 1, coords.polyterms[3][0]);   /* polyterms[3]); */
+      fits_modify (&header, "PCA1X2Y1", "%le", 1, coords.polyterms[4][0]);   /* polyterms[4]); */
+      fits_modify (&header, "PCA1X1Y2", "%le", 1, coords.polyterms[5][0]);   /* polyterms[5]); */
+      fits_modify (&header, "PCA1X0Y3", "%le", 1, coords.polyterms[6][0]);   /* polyterms[6]); */
+    }
+    /* Dec Terms */
+    fits_modify (&header, "PCA2X2Y0", "%le", 1, coords.polyterms[0][1]);   /* polyterms[7]); */
+    fits_modify (&header, "PCA2X1Y1", "%le", 1, coords.polyterms[1][1]);   /* polyterms[8]); */
+    fits_modify (&header, "PCA2X0Y2", "%le", 1, coords.polyterms[2][1]);   /* polyterms[9]); */
+
+    if (coords.Npolyterms > 2) {
+      fits_modify (&header, "PCA2X3Y0", "%le", 1, coords.polyterms[3][1]);   /* polyterms[10]); */
+      fits_modify (&header, "PCA2X2Y1", "%le", 1, coords.polyterms[4][1]);   /* polyterms[11]); */
+      fits_modify (&header, "PCA2X1Y2", "%le", 1, coords.polyterms[5][1]);   /* polyterms[12]); */
+      fits_modify (&header, "PCA2X0Y3", "%le", 1, coords.polyterms[6][1]);   /* polyterms[13]); */
+    }
+  }
+  fits_modify (&header, "CERROR", "%lf", 1, dR);
+  fits_modify (&header, "CERROR", "%C", 1, "scatter in astrometry soln (arcsec)");
+  fits_modify (&header, "CPRECISE", "%lf", 1, dR / sqrt(1.0*Nmatch));
+  fits_modify (&header, "CPRECISE", "%C", 1, "precision of astrometry soln (arcsec)");
+  fits_modify (&header, "EQUINOX", "%lf", 1, 2000.0);
+  /* we force equinox to be 2000.0 for all images */
+
+skipstuff:
+  if (header.size > oldsize) {
+    if (VERBOSE) fprintf (stderr, "header expanded, creating new copy\n");
+    sprintf (line, "mv %s %s~", file, file);
+    status = system (line);
+    if (status) {
+      fprintf (stderr, "ERROR: unable to create %s~, exiting\n", file);
+      exit (0);
+    }
+    sprintf (line, "%s~", file);
+    f = fopen (line, "r");
+    g = fopen (file, "w");
+    if (f == NULL) {
+      fprintf (stderr, "ERROR: can't find image file %s (4)\n", line);
+      exit(0);
+    }
+    if (g == NULL) {
+      fprintf (stderr, "ERROR: can't open output image file %s (4)\n", file);
+      exit(0);
+    }
+    nbytes = fwrite (header.buffer, 1, header.size, g);
+    fseek (f, oldsize, SEEK_SET);
+    for (i = 0; (nbytes = fread (header.buffer, 1, header.size, f)) > 0; i++) {
+      if (nbytes != fwrite (header.buffer, 1, nbytes, g)) {
+	fprintf (stderr, "ERROR: failure writing output data file\n");
+	exit (0);
+      }
+    }
+    fclose (f);
+    fclose (g);
+  } else {
+    f = fopen (file, "r+");
+    if (f == NULL) {
+      fprintf (stderr, "ERROR: can't find image file %s (4)\n", file);
+      exit(0);
+    }
+    
+    fseek (f, 0, SEEK_SET);
+    nbytes = fwrite (header.buffer, 1, header.size, f);
+    
+    fclose (f);
+  }
+  free (header.buffer);
+
+}
+
+
Index: /tags/start/Ohana/src/gastro/src/gproject.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/gproject.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/gproject.c	(revision 12606)
@@ -0,0 +1,97 @@
+# include "gastro.h"
+# define MMIN 2
+# define dM 0.5
+# define NMBIN 64
+
+void gproject (SStars *catalog, SStars **stars, int Ncat, int *Nstars, Coords *coords, int NX, int NY, double dNdM, int N1) {
+  
+  double mbin[NMBIN], ratio;
+  int i, j, NSTARS, nstar, nstar2;
+  double X, Y, m0, Mmin, Mmax;
+  int XMIN, XMAX, YMIN, YMAX;
+  SStars *tstars, *t2stars;
+
+  NSTARS = Ncat;
+  ALLOCATE (tstars, SStars, NSTARS);
+
+  XMIN = 0.5*(1.0 - NFIELD)*NX;
+  XMAX = 0.5*(1.0 + NFIELD)*NX;
+  YMIN = 0.5*(1.0 - NFIELD)*NY;
+  YMAX = 0.5*(1.0 + NFIELD)*NY;
+  
+  /* project to local coords, select stars within region */
+  for (nstar = i = 0; i < Ncat; i++) {
+    RD_to_XY (&X, &Y, catalog[i].X, catalog[i].Y, coords);
+    if ((X > XMIN) && (X < XMAX) && (Y > YMIN) && (Y < YMAX)) {
+      tstars[nstar].X = X;
+      tstars[nstar].Y = Y;
+      tstars[nstar].mag = catalog[i].mag;
+      nstar++;
+      if (CATDUMP) {
+	fprintf (stdout, "%f %f %f %f %f\n", catalog[i].X, catalog[i].Y, X, Y, catalog[i].mag);
+      }
+    }
+  }
+  if (CATDUMP) {
+    exit (0);
+  }
+
+  REALLOCATE (tstars, SStars, nstar);
+  if (VERBOSE) fprintf (stderr, "%d total reference stars\n", nstar);
+  
+  /* find appropriate magnitude range */ 
+  ratio = NFIELD * NFIELD;
+  m0 = 0;
+  bzero (mbin, NMBIN * sizeof (double));
+  for (i = 0; i < nstar; i++) {
+    if (tstars[i].mag < MMIN) {
+      fprintf (stderr, "%d %f %f %f\n", i, tstars[i].X, tstars[i].Y, tstars[i].mag);
+    }
+    j = (tstars[i].mag - MMIN) / dM;
+    j = MIN (MAX (j, 0), (NMBIN - 1));
+    mbin[j] ++;
+  }
+  for (i = 0; i < NMBIN; i++) {
+    if (ratio * dNdM < mbin[i] / dM) {
+      m0 = (i - 1) * dM + MMIN;
+      break;
+    }
+  }
+  
+  Mmin = m0 - 1.0;
+  Mmax = m0 + MAX (N1/dNdM, 1) + 1.0;
+  if (m0 == 0) {
+    Mmin = 0;
+    Mmax = 32;
+  }
+  if (VERBOSE) fprintf (stderr, "choosing magnitude range for reference stars: ");
+  if (VERBOSE) fprintf (stderr, " %5.2f to %5.2f mags\n", Mmin, Mmax);
+
+
+  ALLOCATE (t2stars, SStars, nstar);
+  if (MAGLIMS) {
+    /* make cut on mags */
+    for (nstar2 = i = 0; i < nstar; i++) {
+      if ((tstars[i].mag > Mmin) && (tstars[i].mag < Mmax)) { 
+	t2stars[nstar2] = tstars[i];
+	nstar2 ++;
+      }
+    }
+  } else {
+    bcopy (tstars, t2stars, nstar*sizeof(SStars));
+    nstar2 = nstar;
+  }
+    
+
+  free (tstars);
+  *stars = t2stars;
+  *Nstars = nstar2;
+  if (VERBOSE) fprintf (stderr, "%d reference stars in mag range\n\n", nstar2);
+
+}
+
+
+/* in this routine, 
+   catalog[i].X,Y are RA,DEC in dec degrees
+   stars[i].X.Y   are projected coords in approx pixels on image
+   */
Index: /tags/start/Ohana/src/gastro/src/gptolemy.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/gptolemy.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/gptolemy.c	(revision 12606)
@@ -0,0 +1,82 @@
+# include "gastro.h"
+
+/* filename has path to GSC, strip off path, use filename with CATDIR path */
+
+int gptolemy (char *fullpath, SStars **stars, int *Nstars) {
+  
+  int i, Nsec, NSTARS, nstar;
+  char filename[256], *fileroot, *filepath, *subdir;
+  Catalog catalog;
+
+  filepath = pathname (fullpath);
+  fileroot = filebasename (fullpath);
+  subdir = filebasename (filepath);
+  sprintf (filename, "%s/%s/%s", CATDIR, subdir, fileroot);
+
+  catalog.filename = filename;
+  switch (lock_catalog (&catalog, LCK_SOFT)) {
+  case 0:
+  case 2:
+    fprintf (stderr, "can't load catalog data\n");
+    return (FALSE);
+  case 1:
+    break;
+  }
+  if (!load_catalog (&catalog, LOAD_AVES | LOAD_MEAS, FALSE)) {
+    fprintf (stderr, "can't load catalog data\n");
+    return (FALSE);
+  }
+  unlock_catalog (&catalog);
+
+  nstar = *Nstars;
+  NSTARS = *Nstars + catalog.Naverage;
+  if (*Nstars == 0) {
+    ALLOCATE (stars[0], SStars, NSTARS);
+  } else {
+    REALLOCATE (stars[0], SStars, NSTARS);
+  }
+
+  Nsec = catalog.Nsecfilt;
+
+  /* select all entries, ignore magnitudes */
+  for (i = 0; i < catalog.Naverage; i++, nstar++) {
+    stars[0][nstar].X = catalog.average[i].R;
+    stars[0][nstar].Y = catalog.average[i].D;
+    stars[0][nstar].mag = 0.001*catalog.measure[catalog.average[i].offset].M;
+  }
+
+  /* select only entries with valid magnitudes */ 
+# if (0)  
+  for (i = 0; i < catalog.Naverage; i++, nstar++) {
+    stars[0][nstar].X = catalog.average[i].R;
+    stars[0][nstar].Y = catalog.average[i].D;
+    GotIt = FALSE;
+    if (catalog.average[i].M != NO_MAG) {
+      stars[0][nstar].mag = 0.001*catalog.average[i].M;
+      GotIt = TRUE;
+    }
+    for (j = 0; !GotIt && (j < Nsec); j++) {
+      if (catalog.secfilt[i*Nsec + j].M != NO_MAG) {
+	stars[0][nstar].mag = 0.001*catalog.secfilt[i*Nsec + j].M;
+	GotIt = TRUE;
+      }
+    }
+    if (!GotIt) nstar --; /* skip this star */
+  }
+# endif
+
+  free (catalog.average);
+
+  *Nstars = nstar;
+  
+  return (TRUE);
+  
+}
+
+/* this function is still only occasionally used.  there is some trouble with the
+   issue of magnitudes.  do we depend on the existence of an 'average.M' value, 
+   or not?
+
+   should this be selectable?
+
+*/
Index: /tags/start/Ohana/src/gastro/src/granges.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/granges.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/granges.c	(revision 12606)
@@ -0,0 +1,40 @@
+# include "gastro.h"
+
+void granges (SStars *stars1, SStars *stars2, int N1, int N2, int NPIX, double *gx, double *gy, double *gx0, double *gy0) {
+
+  int i;
+  double maxX1, minX1, maxY1, minY1;
+  double maxX2, minX2, maxY2, minY2;
+  double Xzero, Xrange, Yzero, Yrange;
+
+  maxX1 = minX1 = stars1[0].X;
+  maxY1 = minY1 = stars1[0].Y;
+  for (i = 0; i < N1; i++) {
+    maxX1 = MAX (maxX1, stars1[i].X);    
+    minX1 = MIN (minX1, stars1[i].X);    
+    maxY1 = MAX (maxY1, stars1[i].Y);    
+    minY1 = MIN (minY1, stars1[i].Y);    
+  }
+
+  maxX2 = minX2 = stars2[0].X;
+  maxY2 = minY2 = stars2[0].Y;
+  for (i = 0; i < N2; i++) {
+    maxX2 = MAX (maxX2, (stars2[i].X));    
+    minX2 = MIN (minX2, (stars2[i].X));    
+    maxY2 = MAX (maxY2, (stars2[i].Y));    
+    minY2 = MIN (minY2, (stars2[i].Y));    
+  }
+
+  Xzero = minX1 - maxX2;
+  Yzero = minY1 - maxY2;
+  Xrange = ((maxX1 - minX1) + (maxX2 - minX2));
+  Yrange = ((maxY1 - minY1) + (maxY2 - minY2));
+  
+  *gx = (NPIX - 1.0) / Xrange;
+  *gy = (NPIX - 1.0) / Yrange;
+  *gx0  = (1.0 - NPIX)*Xzero/Xrange;
+  *gy0  = (1.0 - NPIX)*Yzero/Yrange;
+
+  fprintf (stderr, "gx, gy: %f %f\n", *gx, *gy);
+
+}
Index: /tags/start/Ohana/src/gastro/src/greference.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/greference.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/greference.c	(revision 12606)
@@ -0,0 +1,123 @@
+# include "gastro.h"
+
+# define USNO 1
+# define GSC  0
+
+int greference (SStars **cat, int *Ncat, Coords *coords, int NX, int NY) {
+
+  char **regions;
+  int  i, Nregions, Nusno;
+  CatStats catstats;
+  USNOstats usnostats;
+  USNOdata *usno;
+
+  if (VERBOSE) fprintf (stderr, "\nloading astrometric reference data from %s\n", REFCAT); 
+
+  *Ncat = 0;
+
+  define_region (&catstats, coords, NX, NY);
+
+  /* get stars from the USNO catalog for the given region */
+  if (!strcmp (REFCAT, "USNO") || !strcmp (REFCAT, "BOTH")) {
+    while (catstats.RA[0] > 360.0) catstats.RA[0] -= 360.0;
+    while (catstats.RA[0] <   0.0) catstats.RA[0] += 360.0;
+    while (catstats.RA[1] > 360.0) catstats.RA[1] -= 360.0;
+    while (catstats.RA[1] <   0.0) catstats.RA[1] += 360.0;
+
+    /* if RA crosses 0,360 boundary, do 2 passes */
+    if (catstats.RA[0] > catstats.RA[1]) {
+        CatStats substats;
+	USNOdata *usno1, *usno2;
+	int Nusno1, Nusno2;
+
+	substats = catstats;
+	substats.RA[0] = 0.0;
+	usno1 = getusno (&usnostats, &substats, &Nusno1);
+
+	substats = catstats;
+	substats.RA[1] = 360.0;
+	usno2 = getusno (&usnostats, &substats, &Nusno2);
+
+	ALLOCATE (*cat, SStars, MAX (Nusno1 + Nusno2, 1));
+	for (i = 0; i < Nusno1; i++) {
+	  cat[0][i].X = usno1[i].R;
+	  cat[0][i].Y = usno1[i].D;
+	  cat[0][i].mag = fabs(usno1[i].r);
+	}      
+	for (i = Nusno1; i < Nusno2; i++) {
+	  cat[0][i].X = usno2[i].R;
+	  cat[0][i].Y = usno2[i].D;
+	  cat[0][i].mag = fabs(usno2[i].r);
+	}      
+	*Ncat = Nusno1 + Nusno2;
+	free (usno1);
+	free (usno2);
+    } else {
+	usno = getusno (&usnostats, &catstats, &Nusno);
+
+	ALLOCATE (*cat, SStars, MAX (Nusno, 1));
+	for (i = 0; i < Nusno; i++) {
+	  cat[0][i].X = usno[i].R;
+	  cat[0][i].Y = usno[i].D;
+	  cat[0][i].mag = fabs(usno[i].r);
+	}      
+	*Ncat = Nusno;
+	free (usno);
+    }
+    if (VERBOSE) fprintf (stderr, "%d stars from USNO 1.0\n", *Ncat);
+  }
+
+  if (!strcmp (REFCAT, "GSC") || !strcmp (REFCAT, "BOTH")) {
+    regions = gregions (&catstats, &Nregions);
+    for (i = 0; i < Nregions; i++) {
+      if (!gcatalog (regions[i], cat, Ncat))       
+	return (FALSE);
+    }
+    if (VERBOSE) fprintf (stderr, "%d stars from HST GSC\n", *Ncat);
+  }
+
+  if (!strcmp (REFCAT, "PTOLEMY")) {
+    regions = gregions (&catstats, &Nregions);
+    for (i = 0; i < Nregions; i++) {
+      if (!gptolemy (regions[i], cat, Ncat)) continue;
+    }
+    if (VERBOSE) fprintf (stderr, "%d stars from PTOLEMY\n", *Ncat);
+  }
+
+  if (!strcmp (REFCAT, "2MASS")) {
+    /* this needs to be written to handle the complete 2mass catalog.
+       at the moment, I only have a small subset */
+    if (!g2mass ("/data/milo/eugene/elixir/refs/2mass/2mass.dat", cat, Ncat)) exit (1);
+    if (VERBOSE) fprintf (stderr, "%d stars from 2MASS\n", *Ncat);
+  }
+
+  return (TRUE);
+
+}
+
+void define_region (CatStats *catstats, Coords *coords, int NX, int NY) {
+   
+  int i, j;
+  double X, Y, R, D;
+
+  catstats[0].RA[0] = catstats[0].DEC[0] =  360.0;
+  catstats[0].RA[1] = catstats[0].DEC[1] = -360.0;
+
+  for (i = -1; i < 2; i++) {
+    for (j = -1; j < 2; j++) {
+      X = 0.5*(1.0 + i*NFIELD)*NX;
+      Y = 0.5*(1.0 + j*NFIELD)*NY;
+      XY_to_RD (&R, &D, X, Y, coords);
+      /* coords returns a region all in same phase 
+      while (R < 0.0)    R += 360.0;
+      while (R >= 360.0) R -= 360.0;
+      */
+      catstats[0].RA[0]  = MIN (catstats[0].RA[0], R);
+      catstats[0].RA[1]  = MAX (catstats[0].RA[1], R);
+      catstats[0].DEC[0] = MIN (catstats[0].DEC[0], D);
+      catstats[0].DEC[1] = MAX (catstats[0].DEC[1], D);
+    }
+  }
+  fprintf (stderr, "full region: %f - %f, %f - %f\n", 
+	   catstats[0].RA[0], catstats[0].RA[1], catstats[0].DEC[0], catstats[0].DEC[1]);
+}
Index: /tags/start/Ohana/src/gastro/src/gregions.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/gregions.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/gregions.c	(revision 12606)
@@ -0,0 +1,218 @@
+# include "gastro.h"
+# define DEBUG 0
+double BigDecBounds[] = {0.0, 7.5, 15.0, 22.5, 30.0, 37.5, 45.0, 
+			 52.5, 60.0, 67.5, 75.0, 82.5, 90.0,
+			 0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, 
+			 -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+
+double Areas[] = {2700.0, 2665.4505, 2563.567, 2399.5344, 2181.6343, 1920.7299, 1629.5942, 1322.1251, 1012.5, 714.32555, 439.83856, 199.21043, 0.0,
+		  2700.0, 2665.4505, 2563.567, 2399.5344, 2181.6343, 1920.7299, 1629.5942, 1322.1251, 1012.5, 714.32555, 439.83856, 199.21043, 0.0};
+
+char *DecSections[] = {"N0000", "N0730", "N1500", "N2230", "N3000", "N3730", "N4500", 
+		       "N5230", "N6000", "N6730", "N7500", "N8230", "weirdness", 
+		       "S0000", "S0730", "S1500", "S2230", "S3000", "S3730", "S4500", 
+		       "S5230", "S6000", "S6730", "S7500", "S8230", "weirdness"};
+
+char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			"n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			"s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			"s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+char *disk[] = {"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", 
+		"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "weirdness", 
+		"disk 1", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", 
+		"disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "weirdness"};
+
+int NBigRASections [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3, 48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3};
+
+int NDecLines[] = {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 24, 
+                   0, 597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48};
+
+char **gregions (CatStats *catstats, int *Nregions) {
+  
+  char buffer[28800], temp[50], file[50], line[50];
+  char *p, prefix[1024];
+  char **regions;
+  FILE *f;
+  double dBigRA, RA, DEC, tmp, dr, dd, dec, ra, Ra;
+  double BigRABounds[2], RA0, RA1, DEC0, DEC1;
+  int i, NBigDec, NBigRA, NBig, VMS, N;
+  int NRA, NDEC, NLINES, done, NBLOCKS, nregion, NREGION;
+  
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find GSC regions file %s\n", GSCFILE);
+    exit (0);
+  }
+  
+  /* create space to save names */
+  nregion = 0;
+  NREGION = 50;
+  ALLOCATE (regions, char *, NREGION);
+
+  /* smallest region files are 2.0 deg tall */
+  /* uses arbitrary distance (3.0 deg) for width of image */
+  dd = dr = 0.5;
+  for (Ra = catstats[0].RA[0]; Ra < catstats[0].RA[1] + dr; Ra += dr) {
+    for (dec = catstats[0].DEC[0]; dec < catstats[0].DEC[1] + dd; dec += dd) {
+      ra = Ra;
+      while (ra < 0) { ra += 360.0; }
+      while (ra >= 360.0) { ra -= 360.0; }
+      
+      /* use the pole regions, if near pole */
+      if (dec > 86.25) {
+	sprintf (file, "%s/n8230/pole.cpt\0", GSC_DIR);
+	for (i = 0; i < nregion; i++) {
+	  if (!strcmp (regions[i], file)) {
+	    goto skip1;
+	  }
+	}
+	regions[nregion] = strcreate (file);
+	nregion ++;
+	if (nregion == NREGION) {
+	  NREGION += 50;
+	  REALLOCATE (regions, char *, NREGION);
+	}
+      skip1:
+	continue;
+      }
+
+      /* find large DEC region (directory) */
+      NBigDec = -1;
+      for (i = 0; i < 12; i++) {
+	if ((dec >= BigDecBounds[i]) && (dec < BigDecBounds[i+1])) {
+	  NBigDec = i;
+	  break;
+	}
+      }
+      if (NBigDec < 0) {
+	for (i = 13; i < 24; i++) {
+	  if ((dec < BigDecBounds[i]) && (dec >= BigDecBounds[i+1])) {
+	    NBigDec = i;
+	    break;
+	  }
+	}
+      }
+      if (NBigDec < 0) {
+	fprintf (stderr, "ERROR: Dec out of range: %f\n", dec);
+	exit (0);
+      }
+      
+      /* count lines before section */
+      NLINES = 0;
+      for (i = 0; i < NBigDec; i++) {
+	NLINES += NDecLines[i];
+      }
+      fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+      
+      /* should be in this section.  if not, there is a problem counting... */
+      done = FALSE;
+      fread (buffer, 48*NDecLines[NBigDec], 1, f);
+      for (i = 0; !done && (i < NDecLines[NBigDec]); i++) {
+	strncpy (temp, &buffer[i*48], 48);
+	temp[49] = 0;
+	hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+	if (RA1 < RA0) RA1 += 360.0;
+	if ((dec >= 0) && (dec >= DEC0) && (dec < DEC1) && (ra >= RA0) && (ra < RA1)) {
+	  done = TRUE;
+	}
+	if ((dec < 0) && (dec < DEC0) && (dec >= DEC1) && (ra >= RA0) && (ra < RA1)) {
+	  done = TRUE;
+	}
+      }
+      if (!done) {
+	fprintf (stderr, "ERROR: can't find coords in region file: %f %f\n", ra, dec);
+	exit (0);
+      }
+      temp[5] = 0;
+      sprintf (file, "%s/%s/%s.cpt\0", GSC_DIR, Dec2Sections[NBigDec],&temp[1]);
+      for (i = 0; i < nregion; i++) {
+	if (!strcmp (regions[i], file)) {
+	  goto skip2;
+	}
+      }
+      regions[nregion] = strcreate (file);
+      nregion ++;
+      if (nregion == NREGION) {
+	NREGION += 50;
+	REALLOCATE (regions, char *, NREGION);
+      }
+    skip2:
+    }
+  }
+  fclose (f);
+
+  *Nregions = nregion;
+  return (regions);
+  
+}
+
+
+
+/**********/
+int hms_to_deg (h0, h1, d0, d1, string) 
+     char *string;
+     double *h0, *h1, *d0, *d1;
+{
+  
+  char *c;
+  int i, flag_d0, flag_d1, flag_h0, flag_h1;
+  double tmp;
+  
+  *d0 = *h0 = *d1 = *h1 = 0;
+
+  flag_h0 = dparse (h0, 1, string);
+  flag_h1 = dparse (h1, 4, string);
+  flag_d0 = dparse (d0, 7, string);
+  flag_d1 = dparse (d1, 9, string);
+  *h0 *= flag_h0;
+  *h1 *= flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  dparse (&tmp, 2, string);
+  *h0 += tmp/60.0;
+  dparse (&tmp, 3, string);
+  *h0 += tmp/3600.0;
+  
+  dparse (&tmp, 5, string);
+  *h1 += tmp/60.0;
+  dparse (&tmp, 6, string);
+  *h1 += tmp/3600.0;
+  
+  dparse (&tmp, 8, string);
+  *d0 += tmp/60.0;
+
+  dparse (&tmp, 10, string);
+  *d1 += tmp/60.0;
+
+  *h0 *= 15*flag_h0;
+  *h1 *= 15*flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  return (TRUE);
+}
+
+
+/*
+      if (buffer[i*48 + 19] == ' ') continue;
+      strncpy (temp, &buffer[i*48 + 19], 20);       temp[20] = 0;
+      hms_to_deg (&RA,  &DEC, temp, ' ', 3);
+
+
+  dBigRA = 360.0 / (int)(0.5 + 48*cos(3.1415927*0.5*(BigDecBounds[NBigDec] + BigDecBounds[NBigDec + 1])/180.0));
+
+  NBigRA = ra / dBigRA;
+
+  NBig = NBigRA;
+  for (i = 0; (i < 12) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+  for (i = 13; (i < 24) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+
+
+  fprintf (stderr, "%d %d %d %d %f %f -> %f %f %f\n", NBigDec, NBigRA, NBigRASections[NBigDec], NBig, ra, dec, BigDecBounds[NBigDec], BigDecBounds[NBigDec + 1], dBigRA);
+*/
Index: /tags/start/Ohana/src/gastro/src/gregions2.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/gregions2.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/gregions2.c	(revision 12606)
@@ -0,0 +1,242 @@
+# include "gastro.h"
+
+# define NDECBANDS 12
+double DecBand[] = {0.0, +7.5, +15.0, +22.5, +30.0, +37.5, +45.0, +52.5, +60.0, +67.5, +75.0, +82.5, +90.0,
+		    0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+
+int NDecLines[] =  {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 24, 0, 
+		    597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48, 0};
+
+int NRaBlocks [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 0, 
+		    48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 0};
+
+char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			"n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			"s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			"s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+/* given RA[0] - RA[1] & DEC[0] - DEC[1], return all that fall in range */
+char **gregions (CatStats *catstats, int *nnames) {
+  
+  CatalogRegion area;
+  double dtmp;
+  int i, Nnames;
+  char **names, file[256];
+
+  Nnames = 0;
+  ALLOCATE (names, char *, 1);
+
+  /* force RA[i] to be in range 0 - 360 */
+  while (catstats[0].RA[0] > 360.0) { catstats[0].RA[0] -= 360.0; }
+  while (catstats[0].RA[0] < 0.0)   { catstats[0].RA[0] += 360.0; }
+     
+  while (catstats[0].RA[1] > 360.0) { catstats[0].RA[1] -= 360.0; }
+  while (catstats[0].RA[1] < 0.0)   { catstats[0].RA[1] += 360.0; }
+     
+  /* force DEC[0] < DEC[1] */
+  if (catstats[0].DEC[0] > catstats[0].DEC[1]) {
+    dtmp = catstats[0].DEC[0];
+    catstats[0].DEC[0] = catstats[0].DEC[1];
+    catstats[0].DEC[1] = dtmp;
+  }
+
+  /* include the pole if dec > 86.25 is included (ADD SOUTH POLE!)  */
+  if (catstats[0].DEC[1] > 86.25) {
+    sprintf (file, "n8230/pole");
+    names[Nnames] = strcreate (file);
+    Nnames ++;
+  }
+  
+  /* if RA[0] > RA[1], split in two passes */
+  if (catstats[0].RA[0] > catstats[0].RA[1]) {
+    area.RA[0]  = 0.0;
+    area.RA[1]  = catstats[0].RA[1];
+    area.DEC[0] = catstats[0].DEC[0]; 
+    area.DEC[1] = catstats[0].DEC[1];
+    names = find_dec_bands (area, names, &Nnames);
+
+    area.RA[0]  = catstats[0].RA[0];
+    area.RA[1]  = 360.0;
+    area.DEC[0] = catstats[0].DEC[0]; 
+    area.DEC[1] = catstats[0].DEC[1];
+    names = find_dec_bands (area, names, &Nnames);
+
+  } else {
+
+    area.RA[0]  = catstats[0].RA[0];
+    area.RA[1]  = catstats[0].RA[1];
+    area.DEC[0] = catstats[0].DEC[0]; 
+    area.DEC[1] = catstats[0].DEC[1];
+    names = find_dec_bands (area, names, &Nnames);
+  }
+
+  /* add the full path to the short names */
+  for (i = 0; i < Nnames; i++) {
+    sprintf (file, "%s/%s.cpt", GSC_DIR, names[i]);
+    free (names[i]);
+    names[i] = strcreate (file);
+  }
+
+  *nnames = Nnames;
+  return (names);
+
+}
+
+/* given an area [RA[0] - RA[1], DEC[0] - DEC[1],
+   where 0.0 < RA[0] < RA[1] < 360.0 
+   and -90.0 < (DEC[0], DEC[1]) < 90.0 
+   and DEC[0] < DEC[1]
+   search through the dec bands to identify ones which overlap the area */
+
+/* must pass in an allocted pointer names, and Nnames contains the number so far */
+char **find_dec_bands (CatalogRegion area, char **names, int *Nnames) {
+
+  int i;
+
+  /* for NORTH region (DecBand[i] < DecBand[i+1]) */
+  for (i = 0; i < NDECBANDS; i++) {
+    if ((area.DEC[1] > DecBand[i]) || (area.DEC[0] < DecBand[i+1])) {
+      names = load_ra_blocks (i, area, names, Nnames);
+    }
+  }
+
+  /* for SOUTH region (DecBand[i] > DecBand[i+1]) */
+  for (i = NDECBANDS+1; i < 2*NDECBANDS; i++) {
+    if ((area.DEC[0] < DecBand[i]) || (area.DEC[1] > DecBand[i+1])) {
+      names = load_ra_blocks (i, area, names, Nnames);
+    }
+  }
+
+  return (names);
+}
+
+
+/* given the number of a DecBlock and a defined area, return all area names in that block */
+/* area is defined so that RA[0] < RA[1], DEC[0] < DEC[1] */
+char **load_ra_blocks (int Ndec, CatalogRegion area, char **names, int *Ntnames) {
+
+  CatalogRegion region;
+  int i, Nlines, Nnames;
+  char *buffer, file[256];
+  FILE *f;
+
+  /* open file */ 
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find GSC regions file %s\n", GSCFILE);
+    exit (0);
+  }
+
+  /* count lines before Dec Band */
+  Nlines = 0;
+  for (i = 0; i < Ndec; i++) Nlines += NDecLines[i];
+
+  /* seek to start of Dec Band */
+  fseek (f, 5*2880 + 48*Nlines, SEEK_SET);
+  
+  /* load data into buffer */
+  Nlines = NDecLines[Ndec];
+  ALLOCATE (buffer, char, 48*Nlines);
+  fread (buffer, 48*Nlines, 1, f);
+  fclose (f);
+
+  /* must pass in a pointer which is already allocated */
+  Nnames = *Ntnames;
+  REALLOCATE (names, char *, MAX (Nnames + Nlines, 1));
+
+  for (i = 0; i < Nlines; i++) {
+    parse_GSC_line (&region, &buffer[i*48]);
+    if (area.RA[0] > region.RA[1]) continue;
+    if (area.RA[1] < region.RA[0]) continue;
+    if (area.DEC[0] > region.DEC[1]) continue;
+    if (area.DEC[1] < region.DEC[0]) continue;
+    sprintf (file, "%s/%s", Dec2Sections[Ndec], region.name);
+    names[Nnames] = strcreate (file);
+    Nnames ++;
+  }
+
+  free (buffer);
+  REALLOCATE (names, char *, MAX (Nnames, 1));
+  *Ntnames = Nnames;
+  return (names);
+
+}
+
+/* parse the GSC line, placing values in 'region'.
+   force RA[0] < RA[1], DEC[0] < DEC[1] */
+int parse_GSC_line (CatalogRegion *region, char *line) {
+  
+  double v0, s, dtmp;
+  char tmp[10];
+
+  /* copy name (4 chars) */
+  bzero (region[0].name, 10);
+  strncpy (region[0].name, &line[1], 4);
+
+  /* get RA[0] */
+  bzero (tmp, 10);
+  strncpy (tmp, &line[7], 2);
+  v0 = atof (tmp);
+  
+  bzero (tmp, 10);
+  strncpy (tmp, &line[10], 2);
+  v0 += atof (tmp) / 60.0;
+  
+  bzero (tmp, 10);
+  strncpy (tmp, &line[13], 5);
+  v0 += atof (tmp) / 3600.0;
+  region[0].RA[0] = v0 * 15.0;
+
+  /* get RA[1] */
+  bzero (tmp, 10);
+  strncpy (tmp, &line[19], 2);
+  v0 = atof (tmp);
+  
+  bzero (tmp, 10);
+  strncpy (tmp, &line[22], 2);
+  v0 += atof (tmp) / 60.0;
+  
+  bzero (tmp, 10);
+  strncpy (tmp, &line[25], 5);
+  v0 += atof (tmp) / 3600.0;
+  region[0].RA[1] = v0 * 15.0;
+
+  /* this only happens at the 0,360 boundary */
+  if (region[0].RA[1] < region[0].RA[0]) region[0].RA[1] += 360.0;
+
+  /* get DEC[0] */
+  if (line[31] == '-') s = -1;
+  else s = +1;
+
+  bzero (tmp, 10);
+  strncpy (tmp, &line[32], 2);
+  v0 = atof (tmp);
+  
+  bzero (tmp, 10);
+  strncpy (tmp, &line[35], 2);
+  v0 += atof (tmp) / 60.0;
+  region[0].DEC[0] = s * v0;
+
+  /* get DEC[1] */
+  if (line[40] == '-') s = -1;
+  else s = +1;
+
+  bzero (tmp, 10);
+  strncpy (tmp, &line[41], 2);
+  v0 = atof (tmp);
+  
+  bzero (tmp, 10);
+  strncpy (tmp, &line[44], 2);
+  v0 += atof (tmp) / 60.0;
+  region[0].DEC[1] = s * v0;
+
+  if (region[0].DEC[0] > region[0].DEC[1]) {
+    dtmp = region[0].DEC[1];
+    region[0].DEC[1] = region[0].DEC[0];
+    region[0].DEC[0] = dtmp;
+  }
+
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/gastro/src/gscdump.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/gscdump.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/gscdump.c	(revision 12606)
@@ -0,0 +1,36 @@
+# include "gastro.h"
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  int i, N1, N2, Ncat, Nregions, NX, NY, Nmatch, status;
+  char **regions, **gregions();
+  Stars *catalog, *stars1, *stars2, *gstars();
+  struct timeval now, then;  
+  Coords coords, dcoords;
+  double dNdM, dR, TotalArea;
+  float val;
+
+  ConfigInit ();
+  if (argc < 4) {
+    fprintf (stderr, "USAGE gscdump RA DEC Radius\n");
+    exit (0);
+  }
+
+  coords.crval1 = atof (argv[1]);
+  coords.crval2 = atof (argv[2]);
+  NX = NY = 0;
+
+  regions = gregions (&coords, &Nregions, &TotalArea);
+
+  for (Ncat = i = 0; i < Nregions; i++) {
+    status = gcatalog (regions[i], &catalog, &Ncat, 0, 0);
+  }
+
+  for (i = 0; i < Ncat; i++) {
+    fprintf (stdout, "%f %f %f\n", catalog[i].X, catalog[i].Y, catalog[i].mag);
+  }
+}
+
Index: /tags/start/Ohana/src/gastro/src/gstars.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/gstars.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/gstars.c	(revision 12606)
@@ -0,0 +1,254 @@
+# include "gastro.h"
+# define dcos(a) (cos((double)((a)*(RAD_DEG))))
+# define dsin(a) (sin((double)((a)*(RAD_DEG))))
+
+/* by necesity hard wired */
+# define D_NSTARS 1000
+# define BYTES_STAR 66
+# define BLOCK 1000
+# include <sys/time.h>
+# include <time.h>
+
+SStars *gstars (char *file, int *NSTARS, Coords *coords, int *NX, int *NY, double *dNdM) {
+
+  char line[64], side[64];
+  Header header, theader;
+  FILE *f;
+  int j, Ninstar, nstar, rnumber, N, Nstars, nbytes, Nbytes;
+  SStars *stars;
+  char *buffer;
+  double X, Y, T1, T2, T3, type, csign;
+  double PD, PR, DE, RE;
+  double ra, dec, dmag;
+
+  /* read in image header, open image data region */
+  if (!fits_read_header (file, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s (1)\n", file);
+    exit(0);
+  }
+  /* get complete info from header */
+  fits_scan (&header, "NAXIS1", "%d", 1, NX);
+  fits_scan (&header, "NAXIS2", "%d", 1, NY);
+
+  /* attempt to get detailed astrometric information from header */
+  if (!strcasecmp (ROUGH_ASTROMETRY, "header")) {
+    if (!HEADER[0]) {
+      GetCoords (coords, &header);
+    } else {
+      fits_read_header (HEADER, &theader);
+      GetCoords (coords, &theader);
+    }
+    if (!strcmp (coords[0].ctype, "NONE") || (coords[0].cdelt1 == 0) ||  (coords[0].cdelt2 == 0)) {
+      fprintf (stderr, "header coordinates incomplete, trying for rough coordinates\n");
+      strcpy (ROUGH_ASTROMETRY, "config");
+    } else {
+      if (FLIPX) {
+	coords[0].pc1_1 *= -1;
+	coords[0].crpix1 = *NX - coords[0].crpix1;
+      }
+      if (FLIPY) {
+	coords[0].pc2_2 *= -1;
+	coords[0].crpix2 = *NY - coords[0].crpix2;
+      }
+      ASEC_PIX = fabs (coords[0].cdelt1 * 3600.0);
+      csign = coords[0].cdelt1 / fabs (coords[0].cdelt1);
+      CCD_PC1_1 = coords[0].pc1_1 * csign;
+      CCD_PC2_1 = coords[0].pc2_1 * csign;
+      csign = coords[0].cdelt2 / fabs (coords[0].cdelt2);
+      CCD_PC1_2 = coords[0].pc1_2 * csign;
+      CCD_PC2_2 = coords[0].pc2_2 * csign;
+      if (!strcmp (&coords[0].ctype[4], "-PLY")) {
+	strcpy (coords[0].ctype, "DEC--TAN");
+      }
+    }
+  }
+  
+  /* get just RA & DEC from header, other terms from config file */
+  if (!strcasecmp (ROUGH_ASTROMETRY, "config")) {
+    /* default values for coords */
+    strcpy (coords[0].ctype, "RA---TAN");
+    coords[0].pc1_1 = CCD_PC1_1; coords[0].pc1_2 = CCD_PC1_2;
+    coords[0].pc2_1 = CCD_PC2_1; coords[0].pc2_2 = CCD_PC2_2;
+    coords[0].cdelt1 = coords[0].cdelt2 = ASEC_PIX / 3600.0;
+    coords[0].Npolyterms = 0;
+    coords[0].crpix1 = 0.5*(*NX);
+    coords[0].crpix2 = 0.5*(*NY);
+
+    /* get RA & DEC from header, unless FORCE is ste */
+    if (!FORCE) {
+      /* RA (in hours, not degrees) */
+      if (!fits_scan (&header, "RA", "%s", 1, line)) {
+	fprintf (stderr, "ERROR: no astrometry in header\n");
+	exit (1);
+      }
+      dms_to_ddd (&coords[0].crval1, line);
+      coords[0].crval1 = coords[0].crval1 * 15.0;
+
+      /* DEC */
+      if (!fits_scan (&header, "DEC", "%s", 1, line)) {
+	fprintf (stderr, "ERROR: no astrometry in header\n");
+	exit (1);
+      } 
+      dms_to_ddd (&coords[0].crval2, line);
+    }
+  }
+  if (VERBOSE) fprintf (stderr, "coordinates from header: %9.4f %9.4f\n", coords[0].crval1, coords[0].crval2);
+
+  /* use RA & DEC from command line arguments */
+  if (FORCE) {
+    coords[0].crval1 = F_RA;
+    coords[0].crval2 = F_DEC;
+    if (VERBOSE) fprintf (stderr, " forcing coordinates to: %9.4f %9.4f\n", coords[0].crval1, coords[0].crval2);
+  }    
+
+  /* the following two sections are LONEOS derived and may not be needed elsewhere */
+  if (LONEOS_COORDS) {
+    fits_scan (&header, "COMMENT", "%s", 1, line);
+    sscanf (line, "%*s%d%s", &rnumber, side);
+    if (get_region_coords (&ra, &dec, rnumber, side)) {
+      if (fabs(ra - coords[0].crval1) > 0.1) {
+	fprintf (stderr, "large offset from claimed position, using region coords %f %f -> %f %f (%d %s)\n", 
+		 coords[0].crval1, coords[0].crval2, ra, dec, rnumber, side);
+	coords[0].crval1 = ra;
+	coords[0].crval2 = dec;
+      }
+    }
+  }
+
+  /* at this point, we need to correct the crval1, crval2, and ROT_ZERO values
+     based on the pole axis angle and the ra, dec offsets */
+  if (POLAR_ALIGNMENT) {
+    X = coords[0].crval1;
+    Y = coords[0].crval2;
+    PD = POLE_DEC;  PR = POLE_RA;
+    DE = DEC_OFFSET; RE = RA_OFFSET;
+    
+    T1 = dcos(Y-DE) * dcos(X-RE) * dsin(PD) + dsin(Y-DE) * dcos(PD);
+    T2 = dcos(Y-DE) * dsin(X-RE);
+    T3 = dsin(Y-DE) * dsin(PD) - dcos(Y-DE) * dcos(X-RE) * dcos(PD);
+    
+    coords[0].crval1 = (DEG_RAD * atan2 (T2, T1)) + PR;
+    coords[0].crval2 = (DEG_RAD * asin (T3));
+    while (coords[0].crval1 < 0) coords[0].crval1 += 360.0;
+    while (coords[0].crval1 > 360.0) coords[0].crval1 -= 360.0;
+    
+    if (VERBOSE) fprintf (stderr, "  after polar alignment: %9.4f %9.4f\n", coords[0].crval1, coords[0].crval2);
+  }
+
+  Nstars = 0;
+  fits_scan (&header, "NSTARS", "%d", 1, &Nstars);
+  if (Nstars == -1) {
+    fprintf (stderr, "ERROR: failed to find NSTARS\n");
+    exit (0);
+  }
+  ALLOCATE (stars, SStars, Nstars);
+  Nbytes = Nstars*BYTES_STAR;
+
+  /* re-open file for stars */
+  f = fopen (file, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find image file %s (2)\n", file);
+    exit(0);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  N = nstar = 0;
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR));
+  
+  while ((nbytes = fread (buffer, 1, (BLOCK*BYTES_STAR), f)) != 0) {
+    Ninstar = nbytes / BYTES_STAR;
+    for (j = 0; j < Ninstar; j++, nstar++) {
+      dparse (&stars[N].X,   1, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].Y,   2, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].mag, 3, &buffer[j*BYTES_STAR]);
+      dparse (&dmag, 4, &buffer[j*BYTES_STAR]);
+      dparse (&type,         5, &buffer[j*BYTES_STAR]);
+      if ((type == 4) || (type == 6) || (type == 5) || (type == 9)) continue;
+      if (dmag > 100) continue;
+      N++;
+    }
+  }
+  free (header.buffer);
+  free (buffer);
+  fclose (f);
+ 
+  if (nstar != Nstars) {
+    fprintf (stderr, "WARNING: only read %d of %d stars\n", nstar, Nstars);
+  }
+  if (N < 5) { 
+    fprintf (stderr, "ERROR: too few stars for reliable solution, only %d\n",
+	     N);
+    exit (0);
+  }
+
+  sort_stars (stars, N);  /* sorting by magnitude */
+  Nstars = N;
+
+  if (VERBOSE) fprintf (stderr, "\nread %d stars from data file", Nstars);
+  if (*NSTARS < Nstars) {
+    REALLOCATE (stars, SStars, *NSTARS);
+    if (VERBOSE) fprintf (stderr, ", using %d\n", *NSTARS);
+  } else {
+    *NSTARS = Nstars;
+    if (VERBOSE) fprintf (stderr, "\n");
+  }
+
+  *dNdM = *NSTARS / (stars[(*NSTARS-1)].mag - stars[0].mag) ;
+  if (VERBOSE) fprintf (stderr, "brightest star in datafile: %f mag\n", stars[0].mag);
+  
+  return (stars);
+}
+
+void sort_stars (SStars *stars, int N) {
+
+  int l,j,ir,i;
+  SStars tempstar;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      tempstar = stars[--l];
+    }
+    else {
+      tempstar = stars[ir];
+      stars[ir] = stars[0];
+      if (--ir == 0) {
+	stars[0] = tempstar;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && stars[j].mag < stars[j+1].mag) ++j;
+      if (tempstar.mag < stars[j].mag) {
+	stars[i] = stars[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    stars[i] = tempstar;
+  }
+}
+
+
+# if (0)
+
+  /***  this is tailored for LONEOS ***/
+  Nccd = -1;
+  fits_scan (&header, "NCCD", "%d", 1, &Nccd);
+  if (Nccd == -1) {  /* no ccd info in header, not loneos */
+    coords[0].crpix1 = 0.5*(*NX);
+    coords[0].crpix2 = 0.5*(*NY);
+  }
+  if (Nccd == 0) {  /* chip 0 (a) *** might be wrong *** */
+    coords[0].crpix1 = 0;
+    coords[0].crpix2 = 0.5*(*NY);
+  }
+  if (Nccd == 1) {  /* chip 1 (b) */
+    coords[0].crpix1 = (*NX);
+    coords[0].crpix2 = 0.5*(*NY);
+  }
+
+# endif
Index: /tags/start/Ohana/src/gastro/src/gstars1.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/gstars1.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/gstars1.c	(revision 12606)
@@ -0,0 +1,260 @@
+# include "gastro.h"
+# define dcos(a) (cos((double)((a)*(RAD_DEG))))
+# define dsin(a) (sin((double)((a)*(RAD_DEG))))
+
+/* by necesity hard wired */
+# define D_NSTARS 1000
+# define BYTES_STAR 31
+# define BLOCK 1000
+# include <sys/time.h>
+# include <time.h>
+
+SStars *gstars (file, NSTARS, coords, NX, NY, dNdM) 
+char file[];
+int *NSTARS, *NX, *NY;
+double *dNdM;
+Coords *coords;
+{
+
+  char line[64], *p, side[64];
+  Header header, theader;
+  FILE *f;
+  int i, j, sign, Ninstar, nstar, rnumber, N, Nstars, nbytes, Nbytes, status, Nccd;
+  SStars *stars;
+  char *buffer;
+  double X, Y, T1, T2, T3, type, csign;
+  double PD, PR, DE, RE;
+  double ra, dec;
+
+  /* read in image header, open image data region */
+  if (!fits_read_header (file, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s (1)\n", file);
+    exit(0);
+  }
+  /* get complete info from header */
+  fits_scan (&header, "NAXIS1", "%d", 1, NX);
+  fits_scan (&header, "NAXIS2", "%d", 1, NY);
+
+  if (!strcasecmp (ROUGH_ASTROMETRY, "header")) {
+    if (!HEADER[0]) {
+      GetCoords (coords, &header);
+    } else {
+      fits_read_header (HEADER, &theader);
+      GetCoords (coords, &theader);
+    }
+    if (!strcmp (coords[0].ctype, "NONE") || (coords[0].cdelt1 == 0) ||  (coords[0].cdelt2 == 0)) {
+      fprintf (stderr, "header coordinates incomplete, trying for rough coordinates\n");
+      strcpy (ROUGH_ASTROMETRY, "config");
+    } else {
+      if (FLIPX) {
+	coords[0].pc1_1 *= -1;
+	coords[0].crpix1 = *NX - coords[0].crpix1;
+      }
+      if (FLIPY) {
+	coords[0].pc2_2 *= -1;
+	coords[0].crpix2 = *NY - coords[0].crpix2;
+      }
+      ASEC_PIX = fabs (coords[0].cdelt1 * 3600.0);
+      csign = coords[0].cdelt1 / fabs (coords[0].cdelt1);
+      CCD_PC1_1 = coords[0].pc1_1 * csign;
+      CCD_PC2_1 = coords[0].pc2_1 * csign;
+      csign = coords[0].cdelt2 / fabs (coords[0].cdelt2);
+      CCD_PC1_2 = coords[0].pc1_2 * csign;
+      CCD_PC2_2 = coords[0].pc2_2 * csign;
+      if (!strcmp (&coords[0].ctype[4], "-PLY")) {
+	strcpy (coords[0].ctype, "DEC--TAN");
+      }
+    }
+  }
+  
+  /* get partial info from header */
+  if (!strcasecmp (ROUGH_ASTROMETRY, "config")) {
+    /* default values for coords */
+    strcpy (coords[0].ctype, "RA---TAN");
+    coords[0].pc1_1 = CCD_PC1_1; coords[0].pc1_2 = CCD_PC1_2;
+    coords[0].pc2_1 = CCD_PC2_1; coords[0].pc2_2 = CCD_PC2_2;
+    coords[0].cdelt1 = coords[0].cdelt2 = ASEC_PIX / 3600.0;
+    coords[0].Npolyterms = 0;
+    coords[0].crpix1 = 0.5*(*NX);
+    coords[0].crpix2 = 0.5*(*NY);
+    /* RA */
+    fits_scan (&header, "RA", "%s", 1, line);
+    coords[0].crval1 = atof(&line[0]);
+    p = strchr (line, ':');
+    coords[0].crval1 += atof((char *) (p+1)) / 60.0;
+    p = strchr (p+1, ':');
+    coords[0].crval1 += atof((char *) (p+1)) / 3600.0;
+    coords[0].crval1 = coords[0].crval1 * 15.0;
+    /* DEC */
+    fits_scan (&header, "DEC", "%s", 1, line);
+    coords[0].crval2 = atof(&line[0]);
+    sign = 1;
+    if (line[0] == '-') {
+      sign = -1;
+      coords[0].crval2 = fabs(coords[0].crval2 );
+    }
+    p = strchr (line, ':');
+    coords[0].crval2 += atof((char *) (p+1)) / 60.0;
+    p = strchr (p+1, ':');
+    coords[0].crval2 += atof((char *) (p+1)) / 3600.0;
+    coords[0].crval2 *= sign;
+  }
+  if (VERBOSE) fprintf (stderr, "coordinates from header: %9.4f %9.4f\n", coords[0].crval1, coords[0].crval2);
+
+  /* the following two sections are LONEOS derived and may not be needed elsewhere */
+  if (LONEOS_COORDS) {
+    fits_scan (&header, "COMMENT", "%s", 1, line);
+    sscanf (line, "%*s%d%s", &rnumber, side);
+    if (get_region_coords (&ra, &dec, rnumber, side)) {
+      if (fabs(ra - coords[0].crval1) > 0.1) {
+	fprintf (stderr, "large offset from claimed position, using region coords %f %f -> %f %f (%d %s)\n", 
+		 coords[0].crval1, coords[0].crval2, ra, dec, rnumber, side);
+	coords[0].crval1 = ra;
+	coords[0].crval2 = dec;
+      }
+    }
+  }
+
+  /* at this point, we need to correct the crval1, crval2, and ROT_ZERO values
+     based on the pole axis angle and the ra, dec offsets */
+  if (POLAR_ALIGNMENT) {
+    X = coords[0].crval1;
+    Y = coords[0].crval2;
+    PD = POLE_DEC;  PR = POLE_RA;
+    DE = DEC_OFFSET; RE = RA_OFFSET;
+    
+    T1 = dcos(Y-DE) * dcos(X-RE) * dsin(PD) + dsin(Y-DE) * dcos(PD);
+    T2 = dcos(Y-DE) * dsin(X-RE);
+    T3 = dsin(Y-DE) * dsin(PD) - dcos(Y-DE) * dcos(X-RE) * dcos(PD);
+    
+    coords[0].crval1 = (DEG_RAD * atan2 (T2, T1)) + PR;
+    coords[0].crval2 = (DEG_RAD * asin (T3));
+    while (coords[0].crval1 < 0) coords[0].crval1 += 360.0;
+    while (coords[0].crval1 > 360.0) coords[0].crval1 -= 360.0;
+    
+    if (VERBOSE) fprintf (stderr, "  after polar alignment: %9.4f %9.4f\n", coords[0].crval1, coords[0].crval2);
+  }
+
+  if (FORCE) {
+    coords[0].crval1 = F_RA;
+    coords[0].crval2 = F_DEC;
+    if (VERBOSE) fprintf (stderr, " forcing coordinates to: %9.4f %9.4f\n", coords[0].crval1, coords[0].crval2);
+  }    
+
+  Nstars = 0;
+  fits_scan (&header, "NSTARS", "%d", 1, &Nstars);
+  if (Nstars == -1) {
+    fprintf (stderr, "ERROR: failed to find NSTARS\n");
+    exit (0);
+  }
+  ALLOCATE (stars, SStars, Nstars);
+  Nbytes = Nstars*BYTES_STAR;
+
+  /* re-open file for stars */
+  f = fopen (file, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find image file %s (2)\n", file);
+    exit(0);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  N = nstar = 0;
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR));
+  
+  while ((nbytes = fread (buffer, 1, (BLOCK*BYTES_STAR), f)) != 0) {
+    Ninstar = nbytes / BYTES_STAR;
+    for (j = 0; j < Ninstar; j++, nstar++) {
+      dparse (&stars[N].X,   1, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].Y,   2, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].mag, 3, &buffer[j*BYTES_STAR]);
+      dparse (&type,         5, &buffer[j*BYTES_STAR]);
+      if ((type == 4) || (type == 6) || (type == 8)) continue;
+      N++;
+    }
+  }
+  free (header.buffer);
+  free (buffer);
+ 
+  if (nstar != Nstars) {
+    fprintf (stderr, "WARNING: only read %d of %d stars\n", nstar, Nstars);
+  }
+  if (N < 5) { 
+    fprintf (stderr, "ERROR: too few stars for reliable solution, only %d\n",
+	     N);
+    exit (0);
+  }
+
+  sort_stars (stars, N);  /* sorting by magnitude */
+  Nstars = N;
+
+  if (VERBOSE) fprintf (stderr, "\nread %d stars from data file", Nstars);
+  if (*NSTARS < Nstars) {
+    REALLOCATE (stars, SStars, *NSTARS);
+    if (VERBOSE) fprintf (stderr, ", using %d\n", *NSTARS);
+  } else {
+    *NSTARS = Nstars;
+    if (VERBOSE) fprintf (stderr, "\n");
+  }
+
+  *dNdM = *NSTARS / (stars[(*NSTARS-1)].mag - stars[0].mag) ;
+  if (VERBOSE) fprintf (stderr, "brightest star in datafile: %f mag\n", stars[0].mag);
+  
+  return (stars);
+}
+
+sort_stars (stars, N) 
+SStars *stars;
+int N;
+{
+  int l,j,ir,i;
+  int temp;
+  SStars tempstar;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      tempstar = stars[--l];
+    }
+    else {
+      tempstar = stars[ir];
+      stars[ir] = stars[0];
+      if (--ir == 0) {
+	stars[0] = tempstar;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && stars[j].mag < stars[j+1].mag) ++j;
+      if (tempstar.mag < stars[j].mag) {
+	stars[i] = stars[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    stars[i] = tempstar;
+  }
+}
+
+
+# if (0)
+
+  /***  this is tailored for LONEOS ***/
+  Nccd = -1;
+  fits_scan (&header, "NCCD", "%d", 1, &Nccd);
+  if (Nccd == -1) {  /* no ccd info in header, not loneos */
+    coords[0].crpix1 = 0.5*(*NX);
+    coords[0].crpix2 = 0.5*(*NY);
+  }
+  if (Nccd == 0) {  /* chip 0 (a) *** might be wrong *** */
+    coords[0].crpix1 = 0;
+    coords[0].crpix2 = 0.5*(*NY);
+  }
+  if (Nccd == 1) {  /* chip 1 (b) */
+    coords[0].crpix1 = (*NX);
+    coords[0].crpix2 = 0.5*(*NY);
+  }
+
+# endif
Index: /tags/start/Ohana/src/gastro/src/line_fit.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/line_fit.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/line_fit.c	(revision 12606)
@@ -0,0 +1,112 @@
+# include "astro.h"
+
+int line_fit (stars1, stars2, N1, N2, dx, dy, Rx, Ry,
+		X_O, X_X, X_Y, dX, Y_O, Y_X, Y_Y, dY)
+Stars stars1[], stars2[];
+int N1, N2;
+double dx, dy, Rx, Ry;
+double *X_O, *X_X, *X_Y, *dX;
+double *Y_O, *Y_X, *Y_Y, *dY;
+{
+
+  int i, j, iteration;
+  double Xmin, Ymin, Xmax, Ymax;
+  double x, y, x2, y2, xy, N;
+  double X, Y, X2, Y2, Xy, Yx;
+  double Sx2, Sy2, Sxy, SXx, SXy, SYx, SYy;
+  double Dx, Dy, DD, d2X, d2Y, factor, dX_Y, dY_X;
+  FILE *f;
+
+  factor = 1.0;
+  for (iteration = 0; iteration < 10; iteration ++) {
+    x = y = x2 = y2 = xy = X = Y = X2 = Xy = Yx = Y2 = N = 0;
+    for (i = 0; i < N1; i++) {
+      for (j = 0; j < N2; j++) {
+	if (iteration == 0) {
+	  /* first iteration, more lax, use 2*RADIUS */
+	  Dx = 0.5*(stars1[i].X - Rx*stars2[j].X - dx) / Rx;
+	  Dy = 0.5*(stars1[i].Y - Ry*stars2[j].Y - dy) / Ry;
+	}
+	else {
+	  Dx = (stars1[i].X - (*X_O) - (*X_X)*stars2[j].X - (*X_Y)*stars2[j].Y) / Rx;
+	  Dy = (stars1[i].Y - (*Y_O) - (*Y_X)*stars2[j].X - (*Y_Y)*stars2[j].Y) / Ry;
+	}
+	DD = factor * hypot (Dx, Dy);
+	if (DD < RADIUS) {
+	  x  += stars2[j].X;
+	  y  += stars2[j].Y;
+	  x2 += stars2[j].X*stars2[j].X;
+	  y2 += stars2[j].Y*stars2[j].Y;
+	  xy += stars2[j].X*stars2[j].Y;
+	  X  += stars1[i].X;
+	  Y  += stars1[i].Y;
+	  X2 += stars1[i].X*stars2[j].X;
+	  Xy += stars1[i].X*stars2[j].Y;
+	  Yx += stars1[i].Y*stars2[j].X;
+	  Y2 += stars1[i].Y*stars2[j].Y;
+	  N  += 1.0;
+	}
+      }
+    }
+
+    fprintf (stderr, "%d matched stars, iteration %d\n", (int) N, iteration + 1);
+    if (N < 3) {
+      fprintf (stderr, "too few stars, skipping\n");
+      *X_O = *X_X = *X_Y = *Y_O = *Y_X = *Y_Y = 0;
+      return (N);
+    }
+    Sx2 = x2 - x*x/N;
+    Sy2 = y2 - y*y/N;
+    Sxy = xy - x*y/N;
+    SXx = X2 - X*x/N;
+    SXy = Xy - X*y/N;
+    SYx = Yx - Y*x/N;
+    SYy = Y2 - Y*y/N;
+    
+    *X_X = (SXx*Sy2 - SXy*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+    *X_Y = (SXy*Sx2 - SXx*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+    *X_O = X/N - (*X_X)*x/N - (*X_Y)*y/N;
+    
+    *Y_X = (SYx*Sy2 - SYy*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+    *Y_Y = (SYy*Sx2 - SYx*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+    *Y_O = Y/N - (*Y_X)*x/N - (*Y_Y)*y/N;
+    /* make small course correction, keeping CCD rectilinear: */
+/*    dX_Y = (*X_Y + *Y_X*(*Y_Y / *X_X)); */
+/*    dY_X = 0.5*(*Y_X + *X_Y*(*X_Y / *Y_Y)); */
+/*    *X_Y -= dX_Y;  */
+/*    *Y_X -= dY_X; */
+    factor = factor * 1.1;
+  }
+  factor = factor / 1.1;
+  
+  d2X = d2Y = N = 0;
+  Ymin = Xmin = 10000;
+  Xmax = Ymax = 0;
+  for (i = 0; i < N1; i++) {
+    for (j = 0; j < N2; j++)  {
+      Dx = (stars1[i].X - (*X_O) - (*X_X)*stars2[j].X - (*X_Y)*stars2[j].Y) / Rx;
+      Dy = (stars1[i].Y - (*Y_O) - (*Y_X)*stars2[j].X - (*Y_Y)*stars2[j].Y) / Ry;
+      DD = factor * hypot (Dx, Dy);
+      if (DD < RADIUS) {
+	d2X += Dx*Dx;
+	d2Y += Dy*Dy;
+	N += 1.0;
+	Xmin = MIN (Xmin, stars2[j].X);
+	Xmax = MAX (Xmax, stars2[j].X);
+	Ymin = MIN (Ymin, stars2[j].Y);
+	Ymax = MAX (Ymax, stars2[j].Y);
+      }
+    }
+  }
+  fprintf (stderr, "NPOINTS: %f\n", N);
+  fprintf (stderr, "Xrange: %f -- %f\n", Xmin, Xmax);
+  fprintf (stderr, "Yrange: %f -- %f\n", Ymin, Ymax);
+  (*dX) = sqrt(d2X / (N - 3.0));
+  (*dY) = sqrt(d2Y / (N - 3.0));
+
+  fprintf (stderr, "%f %f %f %f\n", *X_O, *X_X, *X_Y, *dX);
+  fprintf (stderr, "%f %f %f %f\n", *Y_O, *Y_X, *Y_Y, *dY);
+
+  return ((int)N);
+
+}
Index: /tags/start/Ohana/src/gastro/src/misc.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/misc.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/misc.c	(revision 12606)
@@ -0,0 +1,129 @@
+# include "gastro.h"
+
+# define SIGN(X)  (((X) == 0) ? 0 : ((fabs((double)(X))) / (X)))
+
+void hh_hms (double hh, int *hr, int *mn, double *sc) {
+
+  int flag;
+
+  flag = SIGN(hh);
+  hh *= flag;
+  hh = 24.0*(hh/24.0 - (int)(hh/24.0));
+  *sc = 60.0*(60.0*hh - (int)(60.0*hh));
+  *mn = 60.0*(hh - (int)hh);
+  *hr = (int) hh;
+  *hr *= flag;
+
+}
+ 
+void hms_format (char *line, double value) {
+
+  int hr, mn;
+  double sc;
+
+  hh_hms (value, &hr, &mn, &sc);
+  hr = (int) value;
+  if (isnan (value))
+    sprintf (line, "xx:xx:xx.xx");
+  else {
+    if (value < 0) {
+      sprintf (line, "-%02d:%02d:%05.2f", abs(hr), mn, sc);
+    } else {
+      sprintf (line, "%02d:%02d:%05.2f", hr, mn, sc);
+    }
+  }      
+}
+
+/***** convert [-]00:00:00 to 0.0000 ****/
+int dms_to_ddd (double *Value, char *string) {
+  
+  int valid, neg, status;
+  double tmp, value;
+  char *p1, *p2, *px;
+
+  valid = FALSE; 
+  neg = FALSE;
+  stripwhite (string);
+  p1 = string;
+  px = string + strlen(string);
+
+  if (string[0] == '-') { 
+    valid = TRUE; 
+    neg = TRUE;
+    p1 = &string[1];
+  }
+  if (string[0] == '+') { 
+    valid = TRUE; 
+    neg = FALSE;
+    p1 = &string[1];
+  }
+  if (isdigit(string[0])) { 
+    valid = TRUE;
+    p1 = &string[0];
+  }
+  if (!valid) { return (FALSE); }
+
+  status = 1;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) return (FALSE); /* entry not a number: +fred */
+  value = tmp;
+  if (p2 == px) goto escape;    /* entry only number: +1.0 */ 
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:fred */
+  status = 2;
+  value += tmp / 60.0;
+  if (p2 == px) goto escape;    /* entry only number: +1:1 */
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:1:fred */
+  value += tmp / 3600.0;
+
+ escape:
+  if (neg) {
+    value *= -1;
+  }
+  *Value = value;
+
+  return (status);
+}
+
+/**********/
+int str_to_radec (double *ra, double *dec, char *str1, char *str2) {
+
+  double Ra, Dec;
+
+  *ra = *dec = 0;
+  switch (dms_to_ddd (&Ra, str1)) {
+  case 0:
+    fprintf (stderr, "syntax error in RA\n");
+    return (FALSE);
+  case 1:
+    break;
+  case 2:
+    Ra = Ra * 15;
+    break;
+  }
+  switch (dms_to_ddd (&Dec, str2)) {
+  case 0:
+    fprintf (stderr, "syntax error in DEC\n");
+    return (FALSE);
+  case 1:
+  case 2:
+    break;
+  }
+  *ra = Ra;
+  *dec = Dec;
+  return (TRUE);
+}
+
+void area_of_region (CatStats *region) {
+  
+  double area;
+
+  area = DEG_RAD*(region[0].RA[1] - region[0].RA[0])*(sin(region[0].DEC[1]*RAD_DEG) - sin(region[0].DEC[0]*RAD_DEG));
+  region[0].Area = area;
+}
+
Index: /tags/start/Ohana/src/gastro/src/nrutil.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/nrutil.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/nrutil.c	(revision 12606)
@@ -0,0 +1,208 @@
+#include <malloc.h>
+#include <stdio.h>
+
+void nrerror(error_text)
+char error_text[];
+{
+	void exit();
+
+	fprintf(stderr,"Numerical Recipes run-time error...\n");
+	fprintf(stderr,"%s\n",error_text);
+	fprintf(stderr,"...now exiting to system...\n");
+	exit(1);
+}
+
+
+
+float *vector(nl,nh)
+int nl,nh;
+{
+	float *v;
+
+	v=(float *)malloc((unsigned) (nh-nl+1)*sizeof(float));
+	if (!v) nrerror("allocation failure in vector()");
+	return v-nl;
+}
+
+int *ivector(nl,nh)
+int nl,nh;
+{
+	int *v;
+
+	v=(int *)malloc((unsigned) (nh-nl+1)*sizeof(int));
+	if (!v) nrerror("allocation failure in ivector()");
+	return v-nl;
+}
+
+double *dvector(nl,nh)
+int nl,nh;
+{
+	double *v;
+
+	v=(double *)malloc((unsigned) (nh-nl+1)*sizeof(double));
+	if (!v) nrerror("allocation failure in dvector()");
+	return v-nl;
+}
+
+
+
+float **matrix(nrl,nrh,ncl,nch)
+int nrl,nrh,ncl,nch;
+{
+	int i;
+	float **m;
+
+	m=(float **) malloc((unsigned) (nrh-nrl+1)*sizeof(float*));
+	if (!m) nrerror("allocation failure 1 in matrix()");
+	m -= nrl;
+
+	for(i=nrl;i<=nrh;i++) {
+		m[i]=(float *) malloc((unsigned) (nch-ncl+1)*sizeof(float));
+		if (!m[i]) nrerror("allocation failure 2 in matrix()");
+		m[i] -= ncl;
+	}
+	return m;
+}
+
+double **dmatrix(nrl,nrh,ncl,nch)
+int nrl,nrh,ncl,nch;
+{
+	int i;
+	double **m;
+
+	m=(double **) malloc((unsigned) (nrh-nrl+1)*sizeof(double*));
+	if (!m) nrerror("allocation failure 1 in dmatrix()");
+	m -= nrl;
+
+	for(i=nrl;i<=nrh;i++) {
+		m[i]=(double *) malloc((unsigned) (nch-ncl+1)*sizeof(double));
+		if (!m[i]) nrerror("allocation failure 2 in dmatrix()");
+		m[i] -= ncl;
+	}
+	return m;
+}
+
+int **imatrix(nrl,nrh,ncl,nch)
+int nrl,nrh,ncl,nch;
+{
+	int i,**m;
+
+	m=(int **)malloc((unsigned) (nrh-nrl+1)*sizeof(int*));
+	if (!m) nrerror("allocation failure 1 in imatrix()");
+	m -= nrl;
+
+	for(i=nrl;i<=nrh;i++) {
+		m[i]=(int *)malloc((unsigned) (nch-ncl+1)*sizeof(int));
+		if (!m[i]) nrerror("allocation failure 2 in imatrix()");
+		m[i] -= ncl;
+	}
+	return m;
+}
+
+
+
+float **submatrix(a,oldrl,oldrh,oldcl,oldch,newrl,newcl)
+float **a;
+int oldrl,oldrh,oldcl,oldch,newrl,newcl;
+{
+	int i,j;
+	float **m;
+
+	m=(float **) malloc((unsigned) (oldrh-oldrl+1)*sizeof(float*));
+	if (!m) nrerror("allocation failure in submatrix()");
+	m -= newrl;
+
+	for(i=oldrl,j=newrl;i<=oldrh;i++,j++) m[j]=a[i]+oldcl-newcl;
+
+	return m;
+}
+
+
+
+void free_vector(v,nl,nh)
+float *v;
+int nl,nh;
+{
+	free((char*) (v+nl));
+}
+
+void free_ivector(v,nl,nh)
+int *v,nl,nh;
+{
+	free((char*) (v+nl));
+}
+
+void free_dvector(v,nl,nh)
+double *v;
+int nl,nh;
+{
+	free((char*) (v+nl));
+}
+
+
+
+void free_matrix(m,nrl,nrh,ncl,nch)
+float **m;
+int nrl,nrh,ncl,nch;
+{
+	int i;
+
+	for(i=nrh;i>=nrl;i--) free((char*) (m[i]+ncl));
+	free((char*) (m+nrl));
+}
+
+void free_dmatrix(m,nrl,nrh,ncl,nch)
+double **m;
+int nrl,nrh,ncl,nch;
+{
+	int i;
+
+	for(i=nrh;i>=nrl;i--) free((char*) (m[i]+ncl));
+	free((char*) (m+nrl));
+}
+
+void free_imatrix(m,nrl,nrh,ncl,nch)
+int **m;
+int nrl,nrh,ncl,nch;
+{
+	int i;
+
+	for(i=nrh;i>=nrl;i--) free((char*) (m[i]+ncl));
+	free((char*) (m+nrl));
+}
+
+
+
+void free_submatrix(b,nrl,nrh,ncl,nch)
+float **b;
+int nrl,nrh,ncl,nch;
+{
+	free((char*) (b+nrl));
+}
+
+
+
+float **convert_matrix(a,nrl,nrh,ncl,nch)
+float *a;
+int nrl,nrh,ncl,nch;
+{
+	int i,j,nrow,ncol;
+	float **m;
+
+	nrow=nrh-nrl+1;
+	ncol=nch-ncl+1;
+	m = (float **) malloc((unsigned) (nrow)*sizeof(float*));
+	if (!m) nrerror("allocation failure in convert_matrix()");
+	m -= nrl;
+	for(i=0,j=nrl;i<=nrow-1;i++,j++) m[j]=a+ncol*i-ncl;
+	return m;
+}
+
+
+
+void free_convert_matrix(b,nrl,nrh,ncl,nch)
+float **b;
+int nrl,nrh,ncl,nch;
+{
+	free((char*) (b+nrl));
+}
Index: /tags/start/Ohana/src/gastro/src/plotstuff.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/plotstuff.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/plotstuff.c	(revision 12606)
@@ -0,0 +1,166 @@
+# include "gastro.h"
+# include <signal.h>
+
+static int Xgraph[5] = {0,0,0,0,0};
+static int active;
+
+void XDead () {
+  signal (SIGPIPE, XDead);
+  fprintf (stderr, "kapa is dead, must restart\n");
+  Xgraph[active] = -1;
+}
+
+int open_graph (int N) {
+
+# ifdef ANSI
+#   define F_SETFL      4   
+#   define O_NONBLOCK 0200000  
+#   define       AF_UNIX         1          
+#   define       SOCK_STREAM     1          
+#define ENOENT          2       /* No such file or directory    */
+# endif /* ANSI */
+
+  int InitSocket, status, addreslen;
+  struct sockaddr_un Address;
+  char temp[100];
+  char socket_name[100];
+  
+  active = N;
+  sprintf (socket_name, "/tmp/kapa%d", N);
+  sprintf (temp, "rm -f %s", socket_name);
+  system (temp);
+    
+  strcpy (Address.sun_path, socket_name); 
+  Address.sun_family = AF_UNIX; 
+  InitSocket = socket (AF_UNIX, SOCK_STREAM, 0); 
+  status = bind (InitSocket, (struct sockaddr *) &Address, sizeof (Address));
+  status = listen (InitSocket, 1);
+  
+  sprintf (temp, "kapa %s &", socket_name);
+# ifndef DEBUG
+  system (temp);
+# else  
+  fprintf (stderr, "start kapa, press return: %s\n", temp);
+  fscanf (stdin, "%d", &i);
+# endif
+  
+  addreslen =  sizeof (Address);
+  Xgraph[N] = accept (InitSocket, (struct sockaddr *) &Address, &addreslen);
+  if (Xgraph[N] < 0) {
+    fprintf (stderr, "error starting kapa\n");
+    return (FALSE);
+  }
+  else {
+    return (TRUE);
+  }
+  
+}
+
+void DonePlotting (Graphdata *graphmode, int N) {
+  char buffer[65], buffer2[65];
+
+  write (Xgraph[N], "DBOX", 4);
+  sprintf (buffer, "%f %f %f %f ", graphmode[0].xmin, graphmode[0].xmax, graphmode[0].ymin, graphmode[0].ymax);
+  sprintf (buffer2, "NBYTES: %6d ", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+
+  sprintf (buffer, "%s %s %s", "2222", "2222", "2222");
+  sprintf (buffer2, "NBYTES: %6d ", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+}
+
+void PrepPlotting (int Npts, Graphdata *graphmode, int N) {
+
+  int i, status;
+  char buffer[128], buffer2[128];
+
+  active = N;
+  if (Npts < 1) return;
+
+  /* test Xgraph[N], flush junk from pipe */
+  signal (SIGPIPE, XDead);
+  fcntl (Xgraph[N], F_SETFL,  O_NONBLOCK); 
+  for (i = 0; (read (Xgraph[N], buffer, 64) > 0) && (i < 20); i++);
+  fcntl (Xgraph[N], F_SETFL, !O_NONBLOCK); 
+  
+  if (Xgraph[N] < 1) if (!open_graph(N)) return;
+  
+  /* tell kapa to look for the incoming image */
+  status = write (Xgraph[N], "PLOT", 4); 
+
+  /* send Xgraph[N] the plot details */
+  sprintf (buffer, "%8d %8d %d %d %d %d %f %f ", 
+	   Npts, graphmode[0].style, 
+	   graphmode[0].ptype, graphmode[0].ltype, 
+	   graphmode[0].etype, graphmode[0].color, 
+	   graphmode[0].lweight, graphmode[0].size);
+  sprintf (buffer2, "NBYTES: %6d ", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+  
+  sprintf (buffer, "%f %f %f %f ", 
+	   graphmode[0].xmin, graphmode[0].xmax, 
+	   graphmode[0].ymin, graphmode[0].ymax);
+  sprintf (buffer2, "NBYTES: %6d ", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+
+}
+
+void PlotVector (int Npts, float *vect, int mode, int N) {
+
+  int Nbytes;
+
+  if (Npts < 1) return;
+
+  active = N;
+  Nbytes = Npts * sizeof (float);
+  write (Xgraph[N], vect, Nbytes);
+
+}
+
+void PlotReset (int N) {
+
+  char buffer[128];
+  int i;
+
+  /* test Xgraph[N], flush junk from pipe */
+  signal (SIGPIPE, XDead);
+  fcntl (Xgraph[N], F_SETFL,  O_NONBLOCK); 
+  for (i = 0; (read (Xgraph[N], buffer, 64) > 0) && (i < 20); i++);
+  fcntl (Xgraph[N], F_SETFL, !O_NONBLOCK); 
+  
+  if (Xgraph[N] < 1) if (!open_graph(N)) return;
+  
+  write (Xgraph[N], "ERAS", 4);
+
+}
+/* include these lines to plot a pair of vectors: 
+
+   typedef struct {
+   double xmin, xmax, ymin, ymax;
+   int style, ptype, ltype, etype, color;
+   double lweight, size;
+   } Graphdata;
+   Graphdata graphdata;
+   
+   graphdata.xmin = -200;
+   graphdata.xmax = 4200;
+   graphdata.ymin = -500;
+   graphdata.ymax = 500;
+   graphdata.style = 2;
+   graphdata.ptype = 2;
+   graphdata.ltype = 0;
+   graphdata.etype = 0;
+   graphdata.color = 0;
+   graphdata.lweight = 0;
+   graphdata.size = 0.5;
+   
+   PrepPlotting (N, &graphdata, n);
+   PlotVector (N, Y, 0, n);
+   PlotVector (N, dM, 1, n);
+   DonePlotting (&graphdata, n);
+   
+ */
Index: /tags/start/Ohana/src/gastro/src/precess.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/precess.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/precess.c	(revision 12606)
@@ -0,0 +1,31 @@
+# include "astro.h"
+
+void precess (Ra, Dec, in_epoch, out_epoch)
+double *Ra, *Dec;
+double in_epoch, out_epoch;
+{
+
+  double T, zeta, theta, z, A, D;
+  double SD, CD, SA, CA;
+
+  T = (out_epoch - in_epoch) / 100.0;
+  
+  zeta  = RAD_DEG*(0.6406161*T + 0.0000839*T*T + 0.0000050*T*T*T);
+  theta = RAD_DEG*(0.5567530*T - 0.0001185*T*T - 0.0000116*T*T*T);
+  z     =          0.6406161*T + 0.0003041*T*T + 0.0000051*T*T*T;
+
+  A = *Ra;
+  D = *Dec;
+
+  SD =  cos(RAD_DEG*A + zeta)*sin(theta)*cos(RAD_DEG*D) + cos(theta)*sin(RAD_DEG*D);
+  CD = sqrt (1 - SD*SD);
+  SA =  sin(RAD_DEG*A + zeta)*cos(RAD_DEG*D)/CD;
+  CA = (cos(RAD_DEG*A + zeta)*cos(theta)*cos(RAD_DEG*D) - sin(theta)*sin(RAD_DEG*D))/CD;
+  
+  *Dec = asin(SD) / RAD_DEG;
+  *Ra  = atan2(SA, CA) / RAD_DEG + z;
+  
+  if (*Ra < 0)
+    *Ra += 360;
+}  
+   
Index: /tags/start/Ohana/src/gastro/src/ralter_header.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/ralter_header.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/ralter_header.c	(revision 12606)
@@ -0,0 +1,47 @@
+# include "astro.h"
+
+void ralter_header (head, ref, X_O, X_X, X_Y, dX, Y_O, Y_X, Y_Y, dY, N)
+char head[], ref[];
+double X_O, X_X, X_Y, dX, Y_O, Y_X, Y_Y, dY;
+int N;
+{
+
+  Header header;
+  char tmp[200], line[500], *c;
+
+  fits_read_header (head, &header);
+
+  fits_modify (&header, "X_O", "%lf", 1, X_O);
+  fits_modify (&header, "X_X", "%lf", 1, X_X);
+  fits_modify (&header, "X_Y", "%lf", 1, X_Y);
+  fits_modify (&header,  "dX", "%lf", 1,  dX);
+  fits_modify (&header, "Y_O", "%lf", 1, Y_O);
+  fits_modify (&header, "Y_X", "%lf", 1, Y_X);
+  fits_modify (&header, "Y_Y", "%lf", 1, Y_Y);
+  fits_modify (&header,  "dY", "%lf", 1,  dY);
+  if ((c = strrchr (ref, '/')) != NULL) 
+    fits_modify (&header, "rREF", "%s", 1, c+1);
+  else
+    fits_modify (&header, "rREF", "%s", 1, ref);
+  fits_modify (&header, "rNSTARs", "%d", 1, N);
+
+  fits_modify (&header, "X_O", "%C", 1, "rastro coeff");
+  fits_modify (&header, "X_X", "%C", 1, "rastro coeff");
+  fits_modify (&header, "X_Y", "%C", 1, "rastro coeff");
+  fits_modify (&header,  "dX", "%C", 1, "error (pixels)");
+  fits_modify (&header, "Y_O", "%C", 1, "rastro coeff");
+  fits_modify (&header, "Y_X", "%C", 1, "rastro coeff");
+  fits_modify (&header, "Y_Y", "%C", 1, "rastro coeff");
+  fits_modify (&header,  "dY", "%C", 1, "error (pixels)");
+  fits_modify (&header, "rREF", "%C", 1, "rastro ref file");
+  fits_modify (&header, "rNSTARs", "%C", 1, "number of stars used");
+
+  strcpy (tmp, head);
+  strcat (tmp, "~");
+  sprintf (line, "mv %s %s\0", head, tmp);
+  system (line);
+
+  fits_write_header (head, &header);
+  fits_free_header (&header);
+
+}
Index: /tags/start/Ohana/src/gastro/src/ranges.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/ranges.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/ranges.c	(revision 12606)
@@ -0,0 +1,38 @@
+# include "astro.h"
+
+void ranges (stars1, stars2, N1, N2, Xrange, Yrange, Xzero, Yzero, Rx, Ry)
+Stars stars1[], stars2[];
+int N1, N2;
+double *Xrange, *Yrange, *Xzero, *Yzero;
+double Rx, Ry;
+{
+
+  int i;
+  double maxX1, minX1, maxY1, minY1;
+  double maxX2, minX2, maxY2, minY2;
+
+  maxX1 = minX1 = stars1[0].X;
+  maxY1 = minY1 = stars1[0].Y;
+
+  for (i = 0; i < N1; i++) {
+    maxX1 = MAX (maxX1, stars1[i].X);    
+    minX1 = MIN (minX1, stars1[i].X);    
+    maxY1 = MAX (maxY1, stars1[i].Y);    
+    minY1 = MIN (minY1, stars1[i].Y);    
+  }
+
+  maxX2 = minX2 = Rx*stars2[0].X;
+  maxY2 = minY2 = Ry*stars2[0].Y;
+  for (i = 0; i < N2; i++) {
+    maxX2 = MAX (maxX2, (Rx*stars2[i].X));    
+    minX2 = MIN (minX2, (Rx*stars2[i].X));    
+    maxY2 = MAX (maxY2, (Ry*stars2[i].Y));    
+    minY2 = MIN (minY2, (Ry*stars2[i].Y));    
+  }
+
+  *Xzero = minX1 - maxX2;
+  *Yzero = minY1 - maxY2;
+  *Xrange = ((maxX1 - minX2) - (minX1 - maxX2));
+  *Yrange = ((maxY1 - minY2) - (minY1 - maxY2));
+
+}
Index: /tags/start/Ohana/src/gastro/src/rargs.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/rargs.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/rargs.c	(revision 12606)
@@ -0,0 +1,82 @@
+# include "astro.h"
+# define NARGS 2
+
+void rhelp () 
+{
+
+  fprintf (stderr, "rastro -- a relative astrometry routine\n");
+
+  fprintf (stderr, "  USAGE: rastro <ref>\n");
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -N          -- number of input stars used (default: 100) \n");
+  fprintf (stderr, "  -F n        -- quadrant for search        (default: all) \n");
+  fprintf (stderr, "  -R radius   -- default radius of search   (default: %d asec) \n",  DEFAULT_RADIUS);
+  fprintf (stderr, "  -G N        -- grid search spacing        (default: %d ) \n", DEFAULT_NPIX);
+  fprintf (stderr, "\n");
+  fprintf (stderr, "  -help -- print this list\n");
+  exit (0);
+  
+}
+
+  
+
+
+void rargs (argc, argv)
+int     *argc;
+char   **argv;
+{
+  
+  int N;
+  char line[500];
+
+  if (N = get_argument (*argc, argv, "-help")) {
+    remove_argument (N, argc, argv);
+    rhelp ();
+  }
+
+  /** optional arguments **/
+  if (N = get_argument (*argc, argv, "-N")) {
+    remove_argument (N, argc, argv);
+    N2NUMBER = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  else {
+    N2NUMBER = 100;
+  }
+  
+  if (N = get_argument (*argc, argv, "-F")) {
+    remove_argument (N, argc, argv);
+    FLIP = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  else {
+    FLIP = 0;
+  }
+  
+  if (N = get_argument (*argc, argv, "-R")) {
+    remove_argument (N, argc, argv);
+    RADIUS = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  else {
+    RADIUS = DEFAULT_RADIUS;
+  }
+  
+  if (N = get_argument (*argc, argv, "-G")) {
+    remove_argument (N, argc, argv);
+    NPIX = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  else {
+    NPIX = DEFAULT_NPIX;
+  }
+  
+  if (*argc != NARGS) {
+    fprintf (stderr, "USAGE: rastro [-N NN -F mode -R radius] <ref>  \n");
+    fprintf (stderr, "  enter filenames, followed by EOF\n");
+    exit (0);
+  }
+  
+ 
+}
+
Index: /tags/start/Ohana/src/gastro/src/rastro.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/rastro.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/rastro.c	(revision 12606)
@@ -0,0 +1,66 @@
+# include "astro.h"
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  int N, N1, N2;
+  double dx, dy, Rx, Ry;
+  double X_O, X_X, X_Y, dX, Y_O, Y_X, Y_Y, dY;
+  char *c, *ref, filename[200], head[200], obj[200];
+  Stars *stars1, *stars2;
+
+  rargs (&argc, argv);
+
+  ref = argv[1];
+  N1 = 5000;
+  stars1 = get_stars (ref, &N1);
+
+  fprintf (stderr, "enter filenames, followed by EOF\n");
+  while (fscanf (stdin, "%s", filename) != EOF) {
+    /**** See comment 1 below ****/
+    strcpy (head, filename);
+    if ((c = strrchr(head, '.')) != NULL)
+      strcpy(strrchr(head, '.'), ".head");
+    else 
+      strcat(head, ".head");
+    strcpy (obj, filename);
+    if ((c = strrchr(obj, '.')) != NULL)
+      strcpy(strrchr(obj, '.'), ".obj_out");
+    else 
+      strcat(obj, ".obj_out");
+
+    N2 = N2NUMBER;
+    stars2 = get_stars (obj, &N2);
+    if (N2 >= 3) {
+      Rx = 1.0;
+      Ry = 1.0;
+      
+      delta (stars1, stars2, N1, N2, &dx, &dy, &Rx, &Ry);
+      N = line_fit (stars1, stars2, N1, N2, dx, dy, Rx, Ry, 
+		&X_O, &X_X, &X_Y, &dX, &Y_O, &Y_X, &Y_Y, &dY);
+      ralter_header (head, ref, X_O, X_X, X_Y, dX, Y_O, Y_X, Y_Y, dY, N);
+    }
+    else {
+      fprintf (stderr, "too few stars in %s, skipped\n", filename);
+    }
+    free (stars2);
+  }
+  free (stars1);
+}
+
+
+
+
+
+
+    /* comment 1:
+       assign the assumed names: 
+       filename.head, filename.obj_out 
+       if filename is of the form xxxx.xxx, cut off
+       extention before attaching .head, .obj_out
+       this entire problem can be removed by making the 
+       Dophot output file contain the header info from
+       the image, but until this is the Dophot output
+       format... */
Index: /tags/start/Ohana/src/gastro/src/remove_argument.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/remove_argument.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/remove_argument.c	(revision 12606)
@@ -0,0 +1,21 @@
+# include "astro.h"
+
+int remove_argument (N, argc, argv)
+int    N;
+int   *argc;
+char **argv;
+{
+
+  int i;
+
+  if ((N != (int)NULL) && (N != 0)) {
+    (*argc)--;
+    for (i = N; i < *argc; i++) {
+      argv[i] = argv[i+1];
+    }
+  }
+
+  return (N);
+    
+}
+
Index: /tags/start/Ohana/src/gastro/src/rotate.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/rotate.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/rotate.c	(revision 12606)
@@ -0,0 +1,44 @@
+# include "gastro.h"
+
+void rotate (SStars *stars, int Nstars, double angle, int Xo, int Yo) {
+  
+  int i;
+  double dX, dY, DX, DY, CS, SN;
+  double theta, theta2;
+
+  if (angle == 0.0) {
+    return;
+  }
+
+  theta = (angle*RAD_DEG);
+
+  if (fabs (angle) < 10) {
+    theta2 = 0.5*theta*theta;
+    for (i = 0; i < Nstars; i++) {
+      dX = (stars[i].X - Xo);
+      dY = (stars[i].Y - Yo);
+      stars[i].X += -theta*dY - theta2*dX;
+      stars[i].Y +=  theta*dX - theta2*dY;
+    }
+  } else {
+
+    CS = cos (theta);
+    SN = sin (theta);
+
+    for (i = 0; i < Nstars; i++) {
+      dX = (stars[i].X - Xo);
+      dY = (stars[i].Y - Yo);
+
+      DX = dX * CS - dY * SN;
+      DY = dX * SN + dY * CS;
+
+      stars[i].X = DX + Xo;
+      stars[i].Y = DY + Yo;
+    }
+  }
+    
+}
+
+
+  /* rotate the list 'stars' by an angle ccw from x axis */
+
Index: /tags/start/Ohana/src/gastro/src/simulate.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/simulate.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/simulate.c	(revision 12606)
@@ -0,0 +1,102 @@
+# include "astro.h"
+# define TIME {gettimeofday (&now, (struct timeval *) NULL); \
+fprintf (stderr, "start time: %f\n", now.tv_sec+now.tv_usec*1e-6);}
+double rnd_gauss();
+# define T970101 852076800
+# define DRIFT_RATE 33.168 /* msec per row */ 
+# define MAG_LIMIT 20.100
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  int i, N1, N2, NX, NY, Ncat, Nregions, nstar;
+  char **regions, **gregions();
+  Stars *catalog, *stars1, *stars2, *stars3;
+  struct timeval now;  
+  Coords coords;
+  Header header;
+  FILE *f;
+  double X, Y, M, Rsigma, Msigma, Moffset;
+
+  if (argc < 7) {
+    fprintf (stderr, "USAGE: simulate scale ra dec Moffset Msigma Rsigma template output\n");
+    exit (0);
+  }
+  
+  Moffset = atof (argv[4]);
+  Msigma = atof (argv[5]);
+  Rsigma = atof (argv[6]);
+
+  /* load in template file, determine size of "image" */
+  f = fopen (argv[7], "r");
+  if (f == NULL) {
+    fprintf (stderr, "could not find template file %s\n", argv[7]);
+    exit(0);
+  }
+  ALLOCATE (header.buffer, char, 8640);
+  fread (header.buffer, 1, 8640, f);
+  header.size = 8640;
+  fits_scan (&header, "NAXIS1", "%d", 1, &NX);
+  fits_scan (&header, "NAXIS2", "%d", 1, &NY);
+  gettimeofday (&now, (struct timeval *) NULL);
+  fprintf (stderr, "now: %d.%06d\n", now.tv_sec, now.tv_usec);
+  fits_modify (&header, "TZERO", "%d", 1, now.tv_sec - T970101);
+  fits_modify (&header, "TRATE", "%lf", 1, DRIFT_RATE);
+  fits_modify (&header, "FLIMIT", "%lf", 1, MAG_LIMIT);
+  fclose (f);
+
+  /* set up coordinates for image */
+  strcpy (coords.ctype, "RA---TAN");
+  coords.crpix1 = 0.5*NX;
+  coords.crpix2 = 0.5*NY;
+  coords.pc1_1 = 1; coords.pc1_2 = 0;
+  coords.pc2_1 = 0; coords.pc2_2 = 1;
+  coords.cdelt1 = coords.cdelt2 = atof (argv[1]) / 3600.0;
+  coords.crval1 = atof (argv[2]);
+  coords.crval2 = atof (argv[3]);
+  fits_modify (&header, "RA", "%lf", 1, coords.crval1);
+  fits_modify (&header, "DEC", "%lf", 1, coords.crval2);
+
+  /* find appropriate catalogs, load files */
+  regions = gregions (coords, &Nregions);
+  for (N2 = i = 0; i < Nregions; i++) {
+    gcatalog (regions[i], &catalog, &Ncat);
+  }
+  gproject (catalog, &stars2, Ncat, &N2, &coords, NX, NY);
+  free (catalog);
+
+  /* select catalog star within image region */ 
+  ALLOCATE (stars3, Stars, N2);
+  for (nstar = i = 0; i < N2; i++) {
+    if ((stars2[i].X > 0) && (stars2[i].X < NX) && 
+	(stars2[i].Y > 0) && (stars2[i].Y < NY)) {
+      stars3[nstar] = stars2[i];
+      nstar++;
+    }
+  }
+  free (stars2);
+  fits_modify (&header, "NSTARS", "%d", 1, nstar);
+
+  /* write header */
+  f = fopen (argv[8], "w");
+  if (f == NULL) {
+    fprintf (stderr, "could not open output file %s\n", argv[8]);
+    exit(0);
+  }
+  fwrite (header.buffer, 1, 8640, f);
+  
+  /* write data */
+  gauss_init ();
+  for (i = 0; i < nstar; i++) {
+    X = rnd_gauss (stars3[i].X, Rsigma);
+    Y = rnd_gauss (stars3[i].Y, Rsigma);
+    M = rnd_gauss (stars3[i].mag, Msigma) + Moffset;
+    fprintf (f, "%6.1f %6.1f %6.3f %03.0f 1 3.2\n", 
+	     X, Y, M, Msigma*1000.0);
+  }
+  fclose (f);
+
+}
+
Index: /tags/start/Ohana/src/gastro/src/sort.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/sort.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/sort.c	(revision 12606)
@@ -0,0 +1,46 @@
+
+void sort_lists (double *X, double *Y, int *S, int N) {
+
+  int l,j,ir,i;
+  double tX, tY, tS;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    S[i] = tS;
+  }
+}
Index: /tags/start/Ohana/src/gastro/src/stats.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/stats.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/stats.c	(revision 12606)
@@ -0,0 +1,82 @@
+# include "astro.h"
+
+void stats (head, RA, DEC, dRA, dDEC, ASEC_PIX)
+char head[];
+double *RA, *DEC;
+double *dRA, *dDEC;
+double  ASEC_PIX;
+{
+
+  int j, status;
+  Header header;
+  char ra[100], dec[100];
+  double epoch;
+  
+  status = fits_read_header (head, &header);
+
+  if (!status) {
+    fprintf (stderr, "file %s not found\n", head);
+    exit (0);
+  }
+
+  if (!FORCE) {
+    fits_scan (&header, "RA", "%s", 1, ra);
+    *RA = 15*dms_to_deg (ra, ':');
+    
+    fits_scan (&header, "DEC", "%s", 1, dec);
+    *DEC = dms_to_deg (dec, ':');
+
+    /* FITS uses either EPOCH or EQUINOX.  EPOCH is supposed to be
+       outmoded, but you can't tell,right?  fits_scan will not alter the
+       value if it fails, so 2000.0 will act as a default, and EQUINOX
+       will override EPOCH if both exist */
+    epoch = 2000.0;
+    fits_scan (&header, "EPOCH", "%lf", 1, &epoch);
+    fits_scan (&header, "EQUINOX", "%lf", 1, &epoch);
+
+    fprintf (stderr, "%s -> %lf %s -> %lf, %lf\n", ra, *RA, dec, *DEC, epoch);
+
+    precess (RA, DEC, epoch, 2000.0);  /* I want only 2000.0 here! */
+    
+    fprintf (stderr, "%s -> %lf %s -> %lf, %lf\n", ra, *RA, dec, *DEC, 2000.0);
+  }
+
+  *dRA  = header.Naxis[0] * ASEC_PIX / 3600.0;
+  *dDEC = header.Naxis[1] * ASEC_PIX / 3600.0;
+}
+
+double dms_to_deg (string, sep) 
+char *string;
+int  sep;  
+{
+  
+  char C[20];
+  int c, d;
+  double h, flag;
+  
+  d = h = 0;
+  if (strchr (string, sep) == NULL)
+    return (HUGE_VAL);
+  c = strlen(string) - strlen(strchr(string, sep));
+  strncpy (C, string, c);
+  C[c] = 0;
+  h = atof(C);
+  if (strchr(C, '-') != NULL) 
+    flag = -1.0;
+  else
+    flag = 1.0;
+  h *= flag;
+
+  d += c + 1;
+  c = strlen(&string[d]) - strlen(strchr(&string[d], sep));
+  strncpy (C, &string[d], c);
+  C[c] = 0;
+  h += atof(C)/60.0;
+
+  d += c + 1;
+  strcpy (C, &string[d]);
+  h += atof(C)/3600.;
+
+  h *= flag;
+  return (h);
+}
Index: /tags/start/Ohana/src/gastro/src/svbksb.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/svbksb.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/svbksb.c	(revision 12606)
@@ -0,0 +1,24 @@
+void svbksb(u,w,v,m,n,b,x)
+double **u,w[],**v,b[],x[];
+int m,n;
+{
+	int jj,j,i;
+	double s,*tmp,*vector();
+	void free_vector();
+
+	tmp=vector(1,n);
+	for (j=1;j<=n;j++) {
+		s=0.0;
+		if (w[j]) {
+			for (i=1;i<=m;i++) s += u[i][j]*b[i];
+			s /= w[j];
+		}
+		tmp[j]=s;
+	}
+	for (j=1;j<=n;j++) {
+		s=0.0;
+		for (jj=1;jj<=n;jj++) s += v[j][jj]*tmp[jj];
+		x[j]=s;
+	}
+	free_vector(tmp,1,n);
+}
Index: /tags/start/Ohana/src/gastro/src/svd.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/svd.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/svd.c	(revision 12606)
@@ -0,0 +1,90 @@
+# include <ohana.h>
+
+/*
+  matrix[0..N-1][0..N-1] is a square matrix to be inverted,
+  vector[0..N-1][0..M-1] are several vectors to find solns' 
+*/
+
+void svd (double ** matrix, int N, double **vector, int M) {
+
+  int i, j, k;
+  double **u, *b, *w, **v, *x;
+  double wmax, wmin, term;
+
+  ALLOCATE (u, double *, N + 1);
+  /* press routine wants u[1..N][1..N] */
+  for (i = 0; i < N; i++) {
+    ALLOCATE (u[i+1], double, N + 1);
+  }
+  for (i = 0; i < N; i++) {
+    for (j = 0; j < N; j++) {
+      u[i+1][j+1] = matrix[i][j];
+    }
+  }
+  ALLOCATE (v, double *, N + 1);
+  for (i = 0; i < N; i++) {
+    ALLOCATE (v[i+1], double, N + 1);
+    bzero (v[i+1], sizeof(double)*(N+1));
+  }
+  ALLOCATE (w, double, N + 1);
+  bzero (w, sizeof(double)*(N+1));
+  ALLOCATE (b, double, N + 1);
+  bzero (b, sizeof(double)*(N+1));
+  ALLOCATE (x, double, N + 1);
+  bzero (x, sizeof(double)*(N+1));
+
+  fprintf (stderr, "sending matrix to svdcmp\n");
+  svdcmp (u, N, N, w, v);
+  fprintf (stderr, "done with svdcmp\n");
+  wmax = 0.0;
+  for (j = 1; j <= N; j++) if (w[j] > wmax) wmax = w[j];
+  for (j = 1; j <= N; j++) fprintf (stderr, "%10.3e ", w[j]);
+  fprintf (stderr, "\n");
+  wmin = wmax * 1e-22;
+  for (j = 1; j <= N; j++) if (w[j] < wmin) w[j] = 0.0;
+  for (j = 1; j <= N; j++) fprintf (stderr, "%10.3e ", w[j]);
+  fprintf (stderr, "\n");
+
+  for (i = 0; i < M; i++) { 
+    fprintf (stderr, "preping backsub\n");
+    for (j = 0; j < N; j++) {
+      b[j+1] = vector[j][i];
+    }
+
+    fprintf (stderr, "running backsub\n");
+    for (j = 1; j <= N; j++) {
+      fprintf (stderr, "%10.3e ", b[j]);
+    }
+    fprintf (stderr, "\n");
+    svbksb (u, w, v, N, N, b, x);
+    fprintf (stderr, "done with backsub\n");
+    for (j = 0; j < N; j++) {
+      vector[j][i] = x[j+1];
+    }
+  }
+
+  /* replace matrix with inverse matrix */
+  /* transpose u, invert w */
+  for (i = 1; i <= N; i++) {
+    for (j = i+1; j <= N; j++) {
+      SWAP (u[i][j], u[j][i]);
+    }
+    if (w[i] != 0) {
+      w[i] = 1.0/w[i];
+    }
+  }
+      
+  for (i = 1; i <= N; i++) {
+    for (j = 1; j <= N; j++) {
+      term = 0;
+      for (k = 1; k <= N; k++) {
+	term += matrix[i-1][j-1] * v[i][k]*w[k]*u[k][j];
+      }
+      fprintf (stderr, "%6.4f ", term);
+    }
+    fprintf (stderr, "\n");
+  }
+  
+
+}
+
Index: /tags/start/Ohana/src/gastro/src/svdcmp.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/svdcmp.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/svdcmp.c	(revision 12606)
@@ -0,0 +1,204 @@
+#include <math.h>
+
+static double at,bt,ct;
+#define PYTHAG(a,b) ((at=fabs(a)) > (bt=fabs(b)) ? \
+(ct=bt/at,at*sqrt(1.0+ct*ct)) : (bt ? (ct=at/bt,bt*sqrt(1.0+ct*ct)): 0.0))
+
+static double maxarg1,maxarg2;
+#define MAX(a,b) (maxarg1=(a),maxarg2=(b),(maxarg1) > (maxarg2) ?\
+	(maxarg1) : (maxarg2))
+#define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
+
+void svdcmp (double **a, int m, int n, double **w, double **v) {
+
+	int flag,i,its,j,jj,k,l,nm;
+	double c,f,h,s,x,y,z;
+	double anorm=0.0,g=0.0,scale=0.0;
+	double *rv1,*dvector();
+	void nrerror(),free_dvector();
+
+	if (m < n) nrerror("SVDCMP: You must augment A with extra zero rows");
+	rv1=dvector(1,n);
+	for (i=1;i<=n;i++) {
+		l=i+1;
+		rv1[i]=scale*g;
+		g=s=scale=0.0;
+		if (i <= m) {
+			for (k=i;k<=m;k++) scale += fabs(a[k][i]);
+			if (scale) {
+				for (k=i;k<=m;k++) {
+					a[k][i] /= scale;
+					s += a[k][i]*a[k][i];
+				}
+				f=a[i][i];
+				g = -SIGN(sqrt(s),f);
+				h=f*g-s;
+				a[i][i]=f-g;
+				if (i != n) {
+					for (j=l;j<=n;j++) {
+						for (s=0.0,k=i;k<=m;k++) s += a[k][i]*a[k][j];
+						f=s/h;
+						for (k=i;k<=m;k++) a[k][j] += f*a[k][i];
+					}
+				}
+				for (k=i;k<=m;k++) a[k][i] *= scale;
+			}
+		}
+		w[i]=scale*g;
+		g=s=scale=0.0;
+		if (i <= m && i != n) {
+			for (k=l;k<=n;k++) scale += fabs(a[i][k]);
+			if (scale) {
+				for (k=l;k<=n;k++) {
+					a[i][k] /= scale;
+					s += a[i][k]*a[i][k];
+				}
+				f=a[i][l];
+				g = -SIGN(sqrt(s),f);
+				h=f*g-s;
+				a[i][l]=f-g;
+				for (k=l;k<=n;k++) rv1[k]=a[i][k]/h;
+				if (i != m) {
+					for (j=l;j<=m;j++) {
+						for (s=0.0,k=l;k<=n;k++) s += a[j][k]*a[i][k];
+						for (k=l;k<=n;k++) a[j][k] += s*rv1[k];
+					}
+				}
+				for (k=l;k<=n;k++) a[i][k] *= scale;
+			}
+		}
+		anorm=MAX(anorm,(fabs(w[i])+fabs(rv1[i])));
+	}
+	for (i=n;i>=1;i--) {
+		if (i < n) {
+			if (g) {
+				for (j=l;j<=n;j++)
+					v[j][i]=(a[i][j]/a[i][l])/g;
+				for (j=l;j<=n;j++) {
+					for (s=0.0,k=l;k<=n;k++) s += a[i][k]*v[k][j];
+					for (k=l;k<=n;k++) v[k][j] += s*v[k][i];
+				}
+			}
+			for (j=l;j<=n;j++) v[i][j]=v[j][i]=0.0;
+		}
+		v[i][i]=1.0;
+		g=rv1[i];
+		l=i;
+	}
+	for (i=n;i>=1;i--) {
+		l=i+1;
+		g=w[i];
+		if (i < n)
+			for (j=l;j<=n;j++) a[i][j]=0.0;
+		if (g) {
+			g=1.0/g;
+			if (i != n) {
+				for (j=l;j<=n;j++) {
+					for (s=0.0,k=l;k<=m;k++) s += a[k][i]*a[k][j];
+					f=(s/a[i][i])*g;
+					for (k=i;k<=m;k++) a[k][j] += f*a[k][i];
+				}
+			}
+			for (j=i;j<=m;j++) a[j][i] *= g;
+		} else {
+			for (j=i;j<=m;j++) a[j][i]=0.0;
+		}
+		++a[i][i];
+	}
+	for (k=n;k>=1;k--) {
+		for (its=1;its<=30;its++) {
+			flag=1;
+			for (l=k;l>=1;l--) {
+				nm=l-1;
+				if (fabs(rv1[l])+anorm == anorm) {
+					flag=0;
+					break;
+				}
+				if (fabs(w[nm])+anorm == anorm) break;
+			}
+			if (flag) {
+				c=0.0;
+				s=1.0;
+				for (i=l;i<=k;i++) {
+					f=s*rv1[i];
+					if (fabs(f)+anorm != anorm) {
+						g=w[i];
+						h=PYTHAG(f,g);
+						w[i]=h;
+						h=1.0/h;
+						c=g*h;
+						s=(-f*h);
+						for (j=1;j<=m;j++) {
+							y=a[j][nm];
+							z=a[j][i];
+							a[j][nm]=y*c+z*s;
+							a[j][i]=z*c-y*s;
+						}
+					}
+				}
+			}
+			z=w[k];
+			if (l == k) {
+				if (z < 0.0) {
+					w[k] = -z;
+					for (j=1;j<=n;j++) v[j][k]=(-v[j][k]);
+				}
+				break;
+			}
+			if (its == 30) nrerror("No convergence in 30 SVDCMP iterations");
+			x=w[l];
+			nm=k-1;
+			y=w[nm];
+			g=rv1[nm];
+			h=rv1[k];
+			f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
+			g=PYTHAG(f,1.0);
+			f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x;
+			c=s=1.0;
+			for (j=l;j<=nm;j++) {
+				i=j+1;
+				g=rv1[i];
+				y=w[i];
+				h=s*g;
+				g=c*g;
+				z=PYTHAG(f,h);
+				rv1[j]=z;
+				c=f/z;
+				s=h/z;
+				f=x*c+g*s;
+				g=g*c-x*s;
+				h=y*s;
+				y=y*c;
+				for (jj=1;jj<=n;jj++) {
+					x=v[jj][j];
+					z=v[jj][i];
+					v[jj][j]=x*c+z*s;
+					v[jj][i]=z*c-x*s;
+				}
+				z=PYTHAG(f,h);
+				w[j]=z;
+				if (z) {
+					z=1.0/z;
+					c=f*z;
+					s=h*z;
+				}
+				f=(c*g)+(s*y);
+				x=(c*y)-(s*g);
+				for (jj=1;jj<=m;jj++) {
+					y=a[jj][j];
+					z=a[jj][i];
+					a[jj][j]=y*c+z*s;
+					a[jj][i]=z*c-y*s;
+				}
+			}
+			rv1[l]=0.0;
+			rv1[k]=f;
+			w[k]=x;
+		}
+	}
+	free_dvector(rv1,1,n);
+}
+
+#undef SIGN
+#undef MAX
+#undef PYTHAG
Index: /tags/start/Ohana/src/gastro/src/test.c
===================================================================
--- /tags/start/Ohana/src/gastro/src/test.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro/src/test.c	(revision 12606)
@@ -0,0 +1,181 @@
+# include "../include/astro.h"
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+  
+  Coords coords;
+
+  coords.crpix1 = 1024;
+  coords.crpix2 = 512;
+  coords.crval1 = 10.0;
+  coords.crval2 = 89.0;
+
+  coords.cdelt1 = 2.6;
+  coords.cdelt2 = 2.6;
+
+  coords.pc1_1 = 1.0;    coords.pc1_2 = 1.0;
+  coords.pc2_1 = 1.0;    coords.pc2_2 = 1.0;
+
+
+  while (fscanf (stdin, "%lf%lf", &ra, &dec)!=EOF) {
+    RD_to_XY (&x, &y, ra, dec, &coords);
+    XY_to_RD (&Ra, &Dec, x, y, &coords);
+    fprintf (stderr, "%f %f --> %f %f --> %f %f\n", ra, dec, x, y, Ra, Dec);
+  }
+
+}
+ 
+XY_to_RD (ra, dec, x, y, coords)
+double *ra, *dec;
+double  x, y;
+Coords coords[];
+{
+
+  double L, M, X, Y, T;
+  double R, sphi, cphi, stht, ctht;
+  double alpha, delta, salp, calp, sdel, cdel, sdp, cdp;
+  
+  *ra  = 0;
+  *dec = 0;
+
+  X = coords[0].cdelt1*(x - coords[0].crpix1);
+  Y = coords[0].cdelt2*(y - coords[0].crpix2);
+  L = (X*coords[0].pc1_1 + Y*coords[0].pc1_2);
+  M = (X*coords[0].pc2_1 + Y*coords[0].pc2_2);
+
+  fprintf (stderr, "XY LM: %f %f %f %f\n", X, Y, L, M);
+  
+  if (!strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    R = hypot (L,M);
+    if ((L == 0) && (M == 0)) {
+      sphi = 0;
+      cphi = 1;
+    }
+    else {
+      sphi =  L / R;
+      cphi = -M / R;
+    }
+
+    if (!strcmp(&coords[0].ctype[4], "-TAN") ) {
+      if (R == 0) {
+	stht = 1.0;
+	ctht = 0.0;
+      }
+      else {
+	T = DEG_RAD / R;
+	stht =   T / sqrt ( 1.0 + T*T);
+	ctht = 1.0 / sqrt ( 1.0 + T*T);
+      }
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      ctht = RAD_DEG * R;
+      stht = sqrt (1 - ctht*ctht);
+    }
+
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    
+    sdel = stht*sdp - ctht*cphi*cdp;
+    salp = ctht*sphi;
+    calp = stht*cdp + ctht*cphi*sdp;
+    alpha = atan2 (calp, salp);
+    delta = asin (sdel);
+
+    *ra  = DEG_RAD*alpha + coords[0].crval1;
+    *dec = DEG_RAD*delta;
+  }
+  if (!strcmp(&coords[0].ctype[4], "-LIN") || !strcmp(&coords[0].ctype[0], "GENE")) {
+    *ra  = L + coords[0].crval1;
+    *dec = M + coords[0].crval2;
+  }
+
+}
+
+
+RD_to_XY (x, y, ra, dec, coords)
+double *x, *y;
+double  ra, dec;
+Coords coords[];
+{
+
+  double tmp_d;
+  double X, Y, R, sphi, cphi, stht, ctht;
+  double alpha, delta, salp, calp, sdel, cdel, sdp, cdp;
+
+  *x = 0;
+  *y = 0;
+  /* 
+  if (!strcmp(&coords[0].ctype[0], "GENE") || !strcmp(&coords[0].ctype[4], "-LIN")) {
+    X = (ra  - coords[0].crval1);
+    Y = (dec - coords[0].crval2);
+  }
+  */
+  
+  if (!strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    salp = sin(RAD_DEG*(ra - coords[0].crval1));
+    calp = cos(RAD_DEG*(ra - coords[0].crval1));
+    sdel = sin(RAD_DEG*dec);
+    cdel = cos(RAD_DEG*dec);
+
+    stht = sdel*sdp + cdel*cdp*calp;  
+    sphi = cdel*salp; 
+    cphi = cdel*sdp*calp - sdel*cdp; 
+
+    if (!strcmp(&coords[0].ctype[4], "-TAN") ) {
+      X =  DEG_RAD * sphi / stht;
+      Y = -DEG_RAD * cphi / stht;
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      X =  DEG_RAD * sphi;
+      Y = -DEG_RAD * cphi;
+    }
+  }
+  
+  tmp_d = 1.0 / (coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1);
+  *x = tmp_d * (coords[0].pc2_2*X - coords[0].pc1_2*Y) / coords[0].cdelt1 + coords[0].crpix1;
+  *y = tmp_d * (coords[0].pc1_1*Y - coords[0].pc2_1*X) / coords[0].cdelt2 + coords[0].crpix2;
+ 
+}
+
+
+/*** without sin/cos relationship simplifications **
+  if (!strcmp(&ctype[4], "-TAN") || !strcmp(&ctype[4], "-SIN") || !strcmp(&ctype[0], "MM")) {
+    X = (x - CRPIX1)*CDELT1;
+    Y = (y - CRPIX2)*CDELT2;
+  
+    R = hypot (X,Y);
+    if ((X == 0) && (tmp_Y == 0)) 
+      phi = 0;
+    else 
+      phi = atan2 (X,-Y);  *** phi in radians **
+    }
+    sphi = sin(phi);
+    cphi = cos(phi); 
+
+    if (!strcmp(&ctype[4], "-TAN") ) {
+      if (R == 0) 
+	tht = 0.0;
+      else 
+	tht = atan (DEG_RAD / R); *** R in degrees, tht in radians **
+    }
+    if (!strcmp(&ctype[4], "-SIN") || !strcmp(&ctype[0], "MM")) {
+      tht = acos (RAD_DEG * R);   *** R in degrees, tht in radians **
+    }
+
+    sdp  = sin(RAD_DEG*CRVAL2);
+    cdp  = cos(RAD_DEG*CRVAL2);
+    
+    sdel = stht*sdp - ctht*cphi*cdp;
+    salp = ctht*sphi;
+    calp = stht*cdp + ctht*cphi*sdp;
+    alpha = atan2 (salp, calp);
+    delta = asin (sdel);
+    
+    *ra = DEG_RAD*alpha + CRVAL1;
+    *dec = DEG_RAD*delta;
+  }
+*/
Index: /tags/start/Ohana/src/gastro2/Makefile
===================================================================
--- /tags/start/Ohana/src/gastro2/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/Makefile	(revision 12606)
@@ -0,0 +1,85 @@
+include ../../Configure
+HOME 	=	$(ROOT)/src/gastro2
+PROGRAM =       gastro2
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#  
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lFITS -lohana -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS)
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+2MASS = \
+$(SRC)/extr2mass.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/gregions2.$(ARCH).o
+
+GASTRO = \
+$(SRC)/getptolemy.$(ARCH).o \
+$(SRC)/gptolemy2.$(ARCH).o \
+$(SRC)/plots.$(ARCH).o \
+$(SRC)/gheader2.$(ARCH).o \
+$(SRC)/gfit2.$(ARCH).o \
+$(SRC)/plotstuff.$(ARCH).o \
+$(SRC)/rotate2.$(ARCH).o \
+$(SRC)/gcenter2.$(ARCH).o \
+$(SRC)/gproject2.$(ARCH).o \
+$(SRC)/grid.$(ARCH).o \
+$(SRC)/lumfunc.$(ARCH).o \
+$(SRC)/gregions2.$(ARCH).o \
+$(SRC)/gaussj.$(ARCH).o \
+$(SRC)/sort.$(ARCH).o \
+$(SRC)/misc.$(ARCH).o \
+$(SRC)/gargs.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/gastro2.$(ARCH).o \
+$(SRC)/gstars2.$(ARCH).o \
+$(SRC)/greference2.$(ARCH).o \
+$(SRC)/getusno.$(ARCH).o \
+$(SRC)/gcatalog.$(ARCH).o \
+$(SRC)/remove_clumps.$(ARCH).o
+
+OBJ = $(GASTRO)
+
+default: $(PROGRAM)
+
+all: $(PROGRAM) extr2mass
+
+$(GASTRO): $(INC)/gastro2.h
+
+extr2mass: $(2MASS)
+	$(CC) $(2MASS) -o $(BIN)/extr2mass.linux $(CCFLAGS)
+
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:	
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
+
+
Index: /tags/start/Ohana/src/gastro2/include/gastro2.h
===================================================================
--- /tags/start/Ohana/src/gastro2/include/gastro2.h	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/include/gastro2.h	(revision 12606)
@@ -0,0 +1,193 @@
+# include <ohana.h>
+# include <loneos.h>
+
+typedef struct {
+  double R;
+  double D;
+  double X;
+  double Y;
+  double M;
+  double dM;
+  int type;
+} StarData;
+
+typedef struct {
+  double dNdM;
+  double Mo;
+  double Mmin;
+  double Mmax;
+  double Mz;
+} LumStats;
+
+typedef struct {
+  double angle;
+  double Xoff;
+  double Yoff;
+  double Chi;
+  double dR;
+  int    N;
+} Answer;
+
+typedef struct {
+  Header header;   /* cmp file header */
+  LumStats lum;
+  Coords coords;   /* current best guess for astrometry */
+  Answer answer;
+
+  double Area;
+  StarData *stars; /* array with all star data */
+  int N;           /* number of stars */
+} CmpCatalog;
+
+typedef struct {
+  LumStats lum;
+
+  double Area;
+  double Moff;
+  double R0, R1;
+  double D0, D1;
+  int N;           /* number of stars */
+  
+  StarData *stars; /* array with all star data */
+} RefCatalog;
+
+typedef struct {
+  double RA[2], DEC[2];
+  double Area;
+  char *name;
+} CatStats;
+
+typedef struct {
+  double R, D;
+  double r, b;
+} USNOdata;
+
+typedef struct {
+  double R, D;
+  double M;
+} GSCdata;
+
+/* global variables, from ConfigInit or args */
+double DEFAULT_RADIUS;
+double MINIMUM_RADIUS;
+double MAX_ERROR, MAX_NONLINEAR;
+double MIN_PRECISE;
+double CCD_PC1_1;
+double CCD_PC2_2;
+double CCD_PC1_2;
+double CCD_PC2_1;
+double NFIELD;
+double SEARCH_RADIUS;
+double ROT_ZERO;
+double dROT;
+double RA_OFFSET, DEC_OFFSET;
+double POLE_RA, POLE_DEC;
+int POLAR_ALIGNMENT;
+int NROT;
+int VERBOSE;
+int LONEOS_COORDS;
+int CATDUMP;
+int MATCHDUMP;
+int NOMATCHDUMP;
+int NEWPHOTCODE;
+int MIN_MATCHES;
+char *PHOTCODE;
+int FLIPX, FLIPY;
+int NPOLYTERMS;
+char CDROM[256];
+char CATDIR[256];
+char REFCAT[256];
+char HEADER[256];
+int PLOTSTUFF;
+int MAGLIMS;
+int NMAX_STARS;
+char PhotCodeFile[256];
+int GASTRO_MAX_NSTARS;
+
+int    FORCE;
+double F_RA;
+double F_DEC;
+
+char GSCFILE[256], GSC_DIR[256], LONEOS_REGION_FILE[256];
+char TWO_MASS_DIR[256];
+double ASEC_PIX;
+char ROUGH_ASTROMETRY[64];
+
+typedef struct {
+  double xmin, xmax, ymin, ymax;
+  int style, ptype, ltype, etype, ebar, color;
+  double lweight, size;
+} Graphdata;
+
+GSCdata  *gptolemy (char *fullpath, int *Nstars);
+CatStats *gregions (CatStats *patch, int *nregion);
+StarData *remove_clumps (StarData *instars, int *nstars, int NX, int NY);
+void 	  ConfigInit (int *argc, char **argv);
+void 	  DonePlotting (Graphdata *graphmode, int N);
+void 	  PlotReset (int N);
+void 	  PlotVector (int Npts, float *vect, int mode, int N);
+void 	  PrepPlotting (int Npts, Graphdata *graphmode, int N);
+void 	  XDead ();
+void 	  add_to_regions (CatStats *area);
+void 	  ahelp ();
+void 	  area_of_region (CatStats *region);
+void 	  args (int *argc, char **argv, Coords *coords);
+void 	  define_region (CatStats *catstats, CmpCatalog *Target);
+int 	  dms_to_ddd (double *Value, char *string);
+void 	  dump_coords (CmpCatalog *Target);
+void 	  fill_lumfunc (StarData *stars, int N, float *lbin, float *bin, int *nb);
+int 	  find_dec_bands (CatStats *area);
+void 	  fit_add (double x1, double y1, double x2, double y2, double wt);
+int 	  fit_adjust (Coords *coords);
+void 	  fit_apply (double *x, double *y, double X, double Y);
+void 	  fit_eval ();
+void 	  fit_init (int order);
+void 	  fit_lum_bin (double *x, double *y, int N, double *C0, double *C1);
+void 	  fit_norm (); 
+double    fit_scat (StarData *st, StarData *sr);
+int 	  gaussj (double **a, int n, double **b, int m);
+void 	  gcenter (CmpCatalog *Target, RefCatalog *Ref);
+int 	  get_luminosity_func (StarData *stars, int N, LumStats *lum);
+int 	  getptolemy (CatStats *catstats, RefCatalog *Ref);
+int 	  getusno (CatStats *catstats, RefCatalog *Ref);
+int       get2mass (CatStats *catstats, RefCatalog *Ref);
+int       getgsc (CatStats *catstats, RefCatalog *Ref);
+
+void 	  gfit (CmpCatalog *Target, RefCatalog *Ref, int order);
+void 	  gheader (char *file, CmpCatalog *Target);
+void 	  gproject (CmpCatalog *Target, RefCatalog *Ref, RefCatalog *Subset);
+void 	  greference (CmpCatalog *Target, RefCatalog *Ref);
+void 	  grid (CmpCatalog *Target, RefCatalog *Subset, Answer *answer);
+int 	  gridbin (double dX, double dY);
+void 	  gridfree ();
+void 	  gridinit (double XMIN, double XMAX, double YMIN, double YMAX, int Nr, int Nt);
+void 	  gstars (char *filename, CmpCatalog *Target);
+void 	  hh_hms (double hh, int *hr, int *mn, double *sc);
+void 	  hms_format (char *line, double value);
+void 	  init_regions ();
+int 	  load_ra_blocks (int Ndec, CatStats *area);
+int 	  mk_polyterm (int n, int m, int norder);
+int 	  mk_vector (int n, int m, int norder);
+int 	  open_graph (int N);
+void 	  pair_add (int i1, int i2);
+void 	  pair_init ();
+int 	  parse_GSC_line (CatStats *tregion, char *line);
+int 	  plot_addpt_gridplot (double x, double y);
+void 	  plot_done_gridplot ();
+void 	  plot_fullfield (CmpCatalog *Target, RefCatalog *Ref);
+void 	  plot_fullfield_pairs (float *x, float *y, int n);
+void 	  plot_gridpts (double *pts, int Npts);
+void 	  plot_init_gridplot ();
+void 	  plot_lumfunc (CmpCatalog *Target, RefCatalog *Ref);
+void 	  plot_resid (StarData *st, StarData *sr);
+void 	  plot_resid_init (int version, double xmax);
+void 	  plot_resid_plot (int version, float *xvect, float *yvect, int Nvect);
+double    ptolemy_area (GSCdata *ptolemy, int N, CatStats *patch);
+void 	  rotate (RefCatalog *Subset, RefCatalog *Ref, double angle);
+void 	  set_catalog (char *catdir);
+void 	  sort (double *X, int N);
+void 	  sort_lists (double *X, double *Y, int *S, int N);
+void 	  sort_lum (double *R, double *X, double *Y, int N);
+void 	  sort_stars_X (StarData *stars, int N);
+void 	  sort_stars_mag (StarData *stars, int N);
+int 	  str_to_radec (double *ra, double *dec, char *str1, char *str2);
Index: /tags/start/Ohana/src/gastro2/src/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/ConfigInit.c	(revision 12606)
@@ -0,0 +1,57 @@
+# include "gastro2.h"
+
+void ConfigInit (int *argc, char **argv) {
+  
+  char *config, *file;
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  ScanConfig (config, "OFFSET_RADIUS",     "%lf", 0, &SEARCH_RADIUS);
+  ScanConfig (config, "MIN_MATCHES",       "%d",  0, &MIN_MATCHES);
+  ScanConfig (config, "DEFAULT_RADIUS",    "%lf", 0, &DEFAULT_RADIUS);
+  ScanConfig (config, "MINIMUM_RADIUS",    "%lf", 0, &MINIMUM_RADIUS);
+  ScanConfig (config, "MAX_ERROR",         "%lf", 0, &MAX_ERROR);
+  ScanConfig (config, "MAX_NONLINEAR",     "%lf", 0, &MAX_NONLINEAR);
+  ScanConfig (config, "MAX_PRECISE",       "%lf", 0, &MIN_PRECISE);
+  ScanConfig (config, "CCD_PC1_1",         "%lf", 0, &CCD_PC1_1);
+  ScanConfig (config, "CCD_PC2_2",         "%lf", 0, &CCD_PC2_2);
+  ScanConfig (config, "CCD_PC1_2",         "%lf", 0, &CCD_PC1_2);
+  ScanConfig (config, "CCD_PC2_1",         "%lf", 0, &CCD_PC2_1);
+  ScanConfig (config, "ASEC_PIX",          "%lf", 0, &ASEC_PIX);
+  ScanConfig (config, "NFIELD",            "%lf", 0, &NFIELD);
+  ScanConfig (config, "NPOLYTERMS",        "%d",  0, &NPOLYTERMS);
+  ScanConfig (config, "ROT_ZERO",          "%lf", 0, &ROT_ZERO);
+  ScanConfig (config, "dROT",              "%lf", 0, &dROT);
+  ScanConfig (config, "NROT",              "%d",  0, &NROT);
+  ScanConfig (config, "POLAR_ALIGNMENT",   "%d",  0, &POLAR_ALIGNMENT);
+  ScanConfig (config, "GSCFILE",           "%s",  0, GSCFILE);
+  ScanConfig (config, "GSCDIR",            "%s",  0, GSC_DIR);
+  ScanConfig (config, "2MASS_DIR",         "%s",  0, TWO_MASS_DIR);
+  ScanConfig (config, "POLAR_AXIS_RA",     "%lf", 0, &POLE_RA);
+  ScanConfig (config, "POLAR_AXIS_DEC",    "%lf", 0, &POLE_DEC);
+  ScanConfig (config, "RA_OFFSET",         "%lf", 0, &RA_OFFSET);
+  ScanConfig (config, "DEC_OFFSET",        "%lf", 0, &DEC_OFFSET);
+  ScanConfig (config, "LONEOS_REGIONS",    "%s",  0, LONEOS_REGION_FILE);
+  ScanConfig (config, "USNO_CDROM",        "%s",  0, CDROM);
+  ScanConfig (config, "ASTRO_REFCAT",      "%s",  0, REFCAT);
+  ScanConfig (config, "CATDIR",            "%s",  0, CATDIR);
+  ScanConfig (config, "ROUGH_ASTROMETRY",  "%s",  0, ROUGH_ASTROMETRY);
+  ScanConfig (config, "PHOTCODE_FILE",     "%s",  0, PhotCodeFile);
+  ScanConfig (config, "GASTRO_MAX_NSTARS", "%d",  0, &GASTRO_MAX_NSTARS);
+
+  if (strcasecmp (ROUGH_ASTROMETRY, "header") && 
+      strcasecmp (ROUGH_ASTROMETRY, "config")) {
+    fprintf (stderr, "ROUGH_ASTROMETRY must be one of: header, config\n");
+    exit (0);
+  }
+  free (config);
+  free (file);
+}
Index: /tags/start/Ohana/src/gastro2/src/extr2mass.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/extr2mass.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/extr2mass.c	(revision 12606)
@@ -0,0 +1,183 @@
+# include "gastro2.h"
+
+# define NDECLIST 24
+double DecList[] = {-90.0, -82.5, -75.0, -67.5, -60.0, -52.5, -45.0, -37.5, -30.0, -22.5, -15.0, -7.5, 0.0, 
+		    +7.5, +15.0, +22.5, +30.0, +37.5, +45.0, +52.5, +60.0, +67.5, +75.0, +82.5, +90.0};
+
+typedef struct {
+  char name[256];
+  float rmin, rmax;
+  int Nstar, Nbyte, Ncbyte;
+} TwoMassAcc;
+
+int main (int argc, char **argv) {
+
+  int i, j, k, Nregions;
+  TwoMassAcc acc[49];
+  CatStats patch, *regions;
+  char line[1024], filename[256], saveline[1024], *path, *Fullpath, *Basename, *Pathname;
+  FILE *f, *fout;
+  int status, done, Nacc, Nstar, NSTAR, Nout, Nscan;
+  double *ra, *dec, *mag, DecMin, DecMax;
+
+  ConfigInit (&argc, argv);
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: extr2mass (input) (acc) (outdir) (gsctbl)\n");
+    exit (2);
+  }
+  
+  /* load accelerator file */
+  f = fopen (argv[2], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't load accelerator file %s\n", argv[2]);
+    return (FALSE);
+  }
+  for (i = 0; i < 49; i++) {
+    status = fscanf (f, "%s %f %f %d %d %d", acc[i].name, &acc[i].rmin, &acc[i].rmax,
+	    &acc[i].Nstar, &acc[i].Nbyte, &acc[i].Ncbyte);
+    if (status != 6) { 
+      fprintf (stderr, "ERROR: can't read 2Mass accelerator file\n");
+      return (FALSE);
+    }
+    acc[i].rmin *= 15.0;
+    acc[i].rmax *= 15.0;
+  }
+  fclose (f);
+
+  /* find file in acc file */
+  Nacc = -1;
+  for (i = 0; (Nacc == -1) && (i < 49); i++) {
+    if (!strcmp (argv[1], acc[i].name)) Nacc = i; 
+  }
+  if (Nacc == -1) {
+    fprintf (stderr, "can't find file in acc file\n");
+    exit (1);
+  }
+
+  fprintf (stderr, "reading from %s, %d stars\n", acc[Nacc].name, acc[Nacc].Nstar);
+
+  /* load 2mass data file */
+  /*
+  sprintf (line, "gzip -cd %s > %s", acc[Nacc].name, acc[Nacc].name);
+  system (line);
+  */
+  
+  sprintf (line, "gzip -cd %s", acc[Nacc].name);
+  f = popen (line, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't read 2Mass data file: %s\n", line);
+    return (FALSE);
+  }
+
+  /* all data in 2mass file are sequential in DEC.  read stars while in dec range */
+
+  /* load data in DEC blocks */
+  saveline[0] = 0;
+  for (i = 0; i < NDECLIST; i++) {
+    
+    Nstar = 0;
+    NSTAR = 1000;
+    ALLOCATE (ra, double, NSTAR);
+    ALLOCATE (dec, double, NSTAR);
+    ALLOCATE (mag, double, NSTAR);
+    
+    DecMin = DecList[i];
+    DecMax = DecList[i+1];
+
+    done = FALSE;
+    while (!done) {
+      if (saveline[0]) {
+	strcpy (line, saveline);
+	saveline[0] = 0;
+      } else {
+	if (scan_line (f, line) == EOF) { goto escape; }
+      }
+      Nscan = sscanf (line, "%lf %lf %*s %*s %*s %*s %lf", &ra[Nstar], &dec[Nstar], &mag[Nstar]);
+      if (Nscan != 3) { 
+	fprintf (stderr, "read wrong number of entries: %d\n", Nscan);
+	fprintf (stderr, "%s\n", line);
+	exit (1);
+      }
+      if (dec[Nstar] > DecMax) {
+	strcpy (saveline, line);
+	goto escape; 
+      } 
+      Nstar ++;
+      if (Nstar == NSTAR) {
+	NSTAR += 1000;
+	REALLOCATE (ra, double, NSTAR);
+	REALLOCATE (dec, double, NSTAR);
+	REALLOCATE (mag, double, NSTAR);
+      }
+      if (Nstar > acc[Nacc].Nstar) {
+	fprintf (stderr, "problem!\n %s\n", line);
+	exit (1);
+      }
+    }
+  escape:
+      
+    fprintf (stderr, "read %d stars for DEC block %f %f\n", Nstar, DecMin, DecMax);
+
+    /* now we write the Nstar objects to the appropriate files */
+    patch.RA[0] = acc[Nacc].rmin;
+    patch.RA[1] = acc[Nacc].rmax;
+    patch.DEC[0] = DecMin;
+    patch.DEC[1] = DecMax;
+    
+    regions = gregions (&patch, &Nregions);
+    
+    for (j = 0; j < Nregions; j++) {
+      /* name has complete path to gsc, strip off path - 1 */
+      Fullpath = pathname (regions[j].name);
+      Basename = filebasename (regions[j].name);
+      Pathname = filebasename (Fullpath);
+      sprintf (filename, "%s/%s/%s", argv[3], Pathname, Basename);
+
+      path = pathname (filename);
+      mkdirhier (path);
+      
+      fout = fopen (filename, "a+");
+      if (fout == (FILE *) NULL) {
+	fprintf (stderr, "can't open output file %s\n", filename);
+	exit (1);
+      }
+
+      Nout = 0;
+      for (k = 0; k < Nstar; k++) {
+	if (ra[k] < regions[j].RA[0]) continue;
+	if (ra[k] >= regions[j].RA[1]) continue;
+	if (dec[k] < regions[j].DEC[0]) continue;
+	if (dec[k] >= regions[j].DEC[1]) continue;
+	fprintf (fout, "%8.4f %8.4f %4.1f\n", ra[k], dec[k], mag[k]);
+	Nout ++;
+      }
+      if (Nout > 0) {
+	fprintf (stderr, "wrote %d stars to %s\n", Nout, filename);
+      }
+      
+      free (path);
+      free (Fullpath);
+      free (Basename);
+      free (Pathname);
+      fclose (fout);
+    }
+
+    free (ra);
+    free (dec);
+    free (mag);
+  }
+
+  fclose (f);
+  exit (0);
+}
+
+
+void area_of_region (CatStats *region) {
+  
+  double area;
+
+  area = DEG_RAD*(region[0].RA[1] - region[0].RA[0])*(sin(region[0].DEC[1]*RAD_DEG) - sin(region[0].DEC[0]*RAD_DEG));
+  region[0].Area = area;
+}
+
Index: /tags/start/Ohana/src/gastro2/src/gargs.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/gargs.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/gargs.c	(revision 12606)
@@ -0,0 +1,125 @@
+# include "gastro2.h"
+# define NARGS 2  /* minimum is:  gastro catalog */
+
+void ahelp () {
+
+  fprintf (stderr, "gastro -- astrometry for LONEOS\n");
+
+  fprintf (stderr, "  USAGE: gastro pixscale filename");
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -v (verbose mode)\n");
+  fprintf (stderr, "  -dump (dump catalog stars, don't complete astrometry)\n");
+  fprintf (stderr, "  -mdmp (dump matched catalog stars)\n");
+  fprintf (stderr, "\n"); 
+  exit (0);
+
+}
+
+void args (int *argc, char **argv, Coords *coords) {
+  
+  int N;
+
+  if (get_argument (*argc, argv, "-help") ||
+      get_argument (*argc, argv, "-h")) {
+    ahelp ();
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (*argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  LONEOS_COORDS = FALSE;
+  if ((N = get_argument (*argc, argv, "-loneos"))) {
+    LONEOS_COORDS = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  NEWPHOTCODE = FALSE;
+  if ((N = get_argument (*argc, argv, "-p"))) {
+    NEWPHOTCODE = TRUE;
+    remove_argument (N, argc, argv);
+    PHOTCODE = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  PLOTSTUFF = FALSE;
+  if ((N = get_argument (*argc, argv, "-plot"))) {
+    PLOTSTUFF = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  MAGLIMS = TRUE;
+  if ((N = get_argument (*argc, argv, "-maglims"))) {
+    MAGLIMS = FALSE;
+    remove_argument (N, argc, argv);
+  }
+
+  NMAX_STARS = 300;
+  if ((N = get_argument (*argc, argv, "-nstars"))) {
+    remove_argument (N, argc, argv);
+    NMAX_STARS = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  HEADER[0] = 0;
+  if ((N = get_argument (*argc, argv, "-header"))) {
+    remove_argument (N, argc, argv);
+    strcpy (HEADER, argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  HEADER[0] = 0;
+  if ((N = get_argument (*argc, argv, "-head"))) {
+    remove_argument (N, argc, argv);
+    strcpy (HEADER, argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  FLIPX = FALSE;
+  if ((N = get_argument (*argc, argv, "-fx"))) {
+    FLIPX = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  FLIPY = FALSE;
+  if ((N = get_argument (*argc, argv, "-fy"))) {
+    FLIPY = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  FORCE = FALSE;
+  if ((N = get_argument (*argc, argv, "-coords"))) {
+    FORCE = TRUE;
+    remove_argument (N, argc, argv);
+    F_RA = atof (argv[N]);
+    remove_argument (N, argc, argv);
+    F_DEC = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  CATDUMP = FALSE;
+  if ((N = get_argument (*argc, argv, "-dump"))) {
+    CATDUMP = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  MATCHDUMP = FALSE;
+  if ((N = get_argument (*argc, argv, "-mdmp"))) {
+    MATCHDUMP = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  NOMATCHDUMP = FALSE;
+  if ((N = get_argument (*argc, argv, "-cdmp"))) {
+    NOMATCHDUMP = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  if (*argc != NARGS) {
+    fprintf (stderr, "USAGE: gastro filename\n");
+    exit (0);
+  }
+
+}
+
Index: /tags/start/Ohana/src/gastro2/src/gastro2.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/gastro2.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/gastro2.c	(revision 12606)
@@ -0,0 +1,91 @@
+# include "gastro2.h"
+
+int main (int argc, char **argv) {
+
+  int i;
+  RefCatalog Ref;
+  CmpCatalog Target;
+
+  /* start_timer (); */
+
+  ConfigInit (&argc, argv);
+  args (&argc, argv, &Target.coords); 
+
+  gstars (argv[1], &Target);
+  greference (&Target, &Ref);
+  gcenter (&Target, &Ref);
+
+  for (i = 0; i < 3; i++) {
+    gfit (&Target, &Ref, 1);
+    fprintf (stderr, "precision: %f\n", Target.answer.dR / sqrt(Target.answer.N));
+    if (VERBOSE) {
+      fprintf (stderr, "%s\n", Target.coords.ctype);
+      fprintf (stderr, "%f %f\n", Target.coords.crval1, Target.coords.crval2);
+      fprintf (stderr, "%f %f\n", Target.coords.crpix1, Target.coords.crpix2);
+      fprintf (stderr, "%f %f\n", Target.coords.pc1_1,  Target.coords.pc1_2);
+      fprintf (stderr, "%f %f\n", Target.coords.pc2_1,  Target.coords.pc2_2);
+      fprintf (stderr, "%f %f\n", Target.coords.cdelt1, Target.coords.cdelt2);
+    }
+
+  }
+
+  for (i = 0; i < 3; i++) {
+    gfit (&Target, &Ref, 1);
+    fprintf (stderr, "precision: %f\n", Target.answer.dR / sqrt(Target.answer.N));
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "%s\n", Target.coords.ctype);
+    fprintf (stderr, "%f %f\n", Target.coords.crval1, Target.coords.crval2);
+    fprintf (stderr, "%f %f\n", Target.coords.crpix1, Target.coords.crpix2);
+    fprintf (stderr, "%f %f\n", Target.coords.pc1_1,  Target.coords.pc1_2);
+    fprintf (stderr, "%f %f\n", Target.coords.pc2_1,  Target.coords.pc2_2);
+    fprintf (stderr, "%f %f\n", Target.coords.cdelt1, Target.coords.cdelt2);
+  }
+
+  gheader (argv[1], &Target);
+
+  /* print_timer (); */
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
+
+  /* 
+     load config & args 
+
+     load stars & header from cmp file
+     (this should include filtering based on CONFIG data:
+     limit number of stars, limit types, etc) 
+
+     identify and load reference catalog(s)
+     - load all catalogs available?
+     - keep ra, dec, mag
+
+     project catalog to initial guess
+
+     find simple x, y offset in limited number of rotations
+   
+     reload reference catalog if dx, dy large 
+
+     project to new guess
+
+     fit on star-by-star basis
+     - include weighting by dmag
+     - downweight by Nmatch to each star
+     - iterate a few times?
+
+     project to new guess (why is this not part of the routines?)
+
+     try a higher order fit
+
+     adjust header, re-write file
+
+     TODO:
+
+     1) downweight points by Nmatch
+     2) better criterion for success
+     3) better criterion for failure
+     4) polyterms are broken
+
+  */
Index: /tags/start/Ohana/src/gastro2/src/gaussj.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/gaussj.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/gaussj.c	(revision 12606)
@@ -0,0 +1,75 @@
+# include <ohana.h>
+
+int gaussj (double **a, int n, double **b, int m) {
+
+  int *indxc,*indxr,*ipiv;
+  int i, icol, irow, j, k, l, ll;
+  double big,dum,pivinv;
+  
+  ALLOCATE (indxc, int, n);
+  ALLOCATE (indxr, int, n);
+  ALLOCATE (ipiv, int, n);
+  for (j = 0; j < n; j++) 
+    ipiv[j] = 0;
+
+  for (i = 0; i < n; i++) {
+    big = 0.0;
+    for (j = 0; j < n; j++) {
+      if (ipiv[j] != 1) {
+	for (k = 0; k < n; k++) {
+	  if (ipiv[k] == 0) {
+	    if (fabs (a[j][k]) >= big) {
+	      big  = fabs (a[j][k]);
+	      irow = j;
+	      icol = k;
+	    }
+	  } 
+	  else 
+	    if (ipiv[k] > 1) {
+	      fprintf (stderr, "GAUSSJ: Singular Matrix! (1)\n");
+	      return (0);
+	    }
+	}
+      }
+    }
+    ipiv[icol]++;
+    if (irow != icol) {
+      for (l = 0; l < n; l++) 
+	SWAP (a[irow][l], a[icol][l]);
+      for (l = 0; l < m; l++) 
+	SWAP (b[irow][l], b[icol][l]);
+    }
+    indxr[i] = irow;
+    indxc[i] = icol;
+    if (a[icol][icol] == 0.0) {
+      fprintf (stderr, "GAUSSJ: Singular Matrix! (2)\n");
+      return (0);
+    }
+    pivinv = 1.0 / a[icol][icol];
+    a[icol][icol] = 1.0;
+    for (l = 0; l < n; l++) 
+      a[icol][l] *= pivinv;
+    for (l = 0; l < m; l++) 
+      b[icol][l] *= pivinv;
+    for (ll = 0; ll < n; ll++) {
+      if (ll != icol) {
+	dum = a[ll][icol];
+	a[ll][icol] = 0.0;
+	for (l = 0; l < n; l++) 
+	  a[ll][l] -= a[icol][l]*dum;
+	for (l = 0; l < m; l++) 
+	  b[ll][l] -= b[icol][l]*dum;
+      }
+    }
+  }
+
+  for (l = n - 1; l >= 0; l--) {
+    if (indxr[l] != indxc[l])
+      for (k = 0; k < n; k++)
+	SWAP (a[k][indxr[l]], a[k][indxc[l]]);
+  }
+  free (ipiv);
+  free (indxr);
+  free (indxc);
+  return (1);
+}
Index: /tags/start/Ohana/src/gastro2/src/gcatalog.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/gcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/gcatalog.c	(revision 12606)
@@ -0,0 +1,125 @@
+# include "gastro2.h"
+CatStats *gregions (CatStats *patch, int *nregion);
+GSCdata *gcatalog (char *filename, int *Nstars);
+
+int get2mass (CatStats *catstats, RefCatalog *Ref) {
+  
+  int i, j, k, Ns, Ngsc, Nregions; 
+  GSCdata *gsc;
+  CatStats *regions;
+
+  Ref[0].N = 0;
+  Ref[0].Area = 0;
+  ALLOCATE (Ref[0].stars, StarData, 1);
+
+  set_catalog (TWO_MASS_DIR);
+  regions = gregions (catstats, &Nregions);
+  
+  for (i = 0; i < Nregions; i++) {
+    gsc = gcatalog (regions[i].name, &Ngsc);
+
+    Ns = Ref[0].N;
+    Ref[0].N += Ngsc;
+    Ref[0].Area += regions[i].Area;
+
+    REALLOCATE (Ref[0].stars, StarData, MAX (1, Ref[0].N));
+    for (k = Ns, j = 0; j < Ngsc; k++, j++) {
+      Ref[0].stars[k].R = gsc[j].R;
+      Ref[0].stars[k].D = gsc[j].D;
+      Ref[0].stars[k].M = gsc[j].M;
+    }      
+  }
+  
+  Ref[0].R0 = catstats[0].RA[0];
+  Ref[0].R1 = catstats[0].RA[1];
+  Ref[0].D0 = catstats[0].DEC[0];
+  Ref[0].D1 = catstats[0].DEC[1];
+
+  /* calculate luminosity function of stars */
+  get_luminosity_func (Ref[0].stars, Ref[0].N, &Ref[0].lum);
+
+  if (VERBOSE) fprintf (stderr, "%d stars from 2MASS\n", Ref[0].N);
+  return (TRUE);
+}  
+
+int getgsc (CatStats *catstats, RefCatalog *Ref) {
+  
+  int i, j, k, Ns, Ngsc, Nregions; 
+  GSCdata *gsc;
+  CatStats *regions;
+
+  Ref[0].N = 0;
+  Ref[0].Area = 0;
+  ALLOCATE (Ref[0].stars, StarData, 1);
+
+  set_catalog (GSC_DIR);
+  regions = gregions (catstats, &Nregions);
+  
+  for (i = 0; i < Nregions; i++) {
+    gsc = gcatalog (regions[i].name, &Ngsc);
+
+    Ns = Ref[0].N;
+    Ref[0].N += Ngsc;
+    Ref[0].Area += regions[i].Area;
+
+    REALLOCATE (Ref[0].stars, StarData, MAX (1, Ref[0].N));
+    for (k = Ns, j = 0; j < Ngsc; k++, j++) {
+      Ref[0].stars[k].R = gsc[j].R;
+      Ref[0].stars[k].D = gsc[j].D;
+      Ref[0].stars[k].M = gsc[j].M;
+    }      
+  }
+  
+  Ref[0].R0 = catstats[0].RA[0];
+  Ref[0].R1 = catstats[0].RA[1];
+  Ref[0].D0 = catstats[0].DEC[0];
+  Ref[0].D1 = catstats[0].DEC[1];
+
+  /* calculate luminosity function of stars */
+  get_luminosity_func (Ref[0].stars, Ref[0].N, &Ref[0].lum);
+
+  if (VERBOSE) fprintf (stderr, "%d stars from HST GSC\n", Ref[0].N);
+  return (TRUE);
+}  
+
+# define BYTES_STAR 23
+# define BLOCK 1000
+GSCdata *gcatalog (char *filename, int *Nstars) {
+  
+  GSCdata *stars;
+  int i, NSTAR, nstar, Nbytes, nbytes;
+  char *buffer;
+  FILE *f;
+
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find catalog file %s\n", filename);
+    exit (1);
+  }
+  
+  nstar = 0;
+  NSTAR = 1000;
+  ALLOCATE (stars, GSCdata, NSTAR);
+
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR));
+  Nbytes = BLOCK*BYTES_STAR;
+
+  while ((nbytes = fread (buffer, 1, Nbytes, f)) > 0) {
+    for (i = 0; i < nbytes / BYTES_STAR; i++) {
+      dparse (&stars[nstar].R, 1, &buffer[i*BYTES_STAR]);
+      dparse (&stars[nstar].D, 2, &buffer[i*BYTES_STAR]);
+      dparse (&stars[nstar].M, 3, &buffer[i*BYTES_STAR]);
+      nstar++;
+      if (nstar == NSTAR) {
+	NSTAR += 1000;
+	REALLOCATE (stars, GSCdata, NSTAR);
+      }
+    }
+  }
+
+  free (buffer);
+
+  *Nstars = nstar;
+  return (stars);
+}
+
Index: /tags/start/Ohana/src/gastro2/src/gcenter2.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/gcenter2.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/gcenter2.c	(revision 12606)
@@ -0,0 +1,67 @@
+# include "gastro2.h"
+
+void gcenter (CmpCatalog *Target, RefCatalog *Ref) {
+
+  int i, N, Imin;
+  double angle, ChiMin;
+  Answer *answer;
+  RefCatalog Subset;
+
+  gproject (Target, Ref, &Subset);
+  if (PLOTSTUFF) plot_fullfield (Target, &Subset);
+
+  fprintf (stderr, "Target: %d, Ref: %d\n", Target[0].N, Subset.N);
+  dump_coords (Target);
+
+  ALLOCATE (answer, Answer, 2*NROT + 1);
+
+  N = 0;
+  for (angle = ROT_ZERO-dROT*NROT; angle <= ROT_ZERO+dROT*NROT; angle += dROT, N++) {
+
+    if (N == 2*NROT + 1) {
+      fprintf (stderr, "ERROR in logic: Nanswer > 2*NROT+1 (%d, %d)\n", N, 2*NROT+1);
+      exit (1);
+    }
+    answer[N].angle = angle;
+    grid (Target, &Subset, &answer[N]);
+  }
+
+  Imin = 0;
+  ChiMin = answer[0].Chi;
+  for (i = 0; i < N; i++) {
+    if (answer[i].Chi < ChiMin) {
+      Imin = i;
+      ChiMin = answer[i].Chi;
+    }
+  }
+      
+  fprintf (stderr, "best solution: angle: %6.1f, (%6.1f,%6.1f) - %10.8f for %d pairs\n", 
+	   answer[Imin].angle, answer[Imin].Xoff, answer[Imin].Yoff, answer[Imin].Chi, answer[Imin].N);
+
+  Target[0].answer = answer[Imin];
+
+  /* adjust original coordinates for new center */
+  { 
+
+    double cs, sn;
+    double pc11, pc12, pc21, pc22;
+    double Xo, Yo;
+
+    cs = cos(RAD_DEG*answer[Imin].angle);  sn = sin(RAD_DEG*answer[Imin].angle);
+    
+    pc11 = Target[0].coords.pc1_1;
+    pc12 = Target[0].coords.pc1_2;
+    pc21 = Target[0].coords.pc2_1;
+    pc22 = Target[0].coords.pc2_2;
+
+    Target[0].coords.pc1_1 =  pc11*cs - pc21*sn;
+    Target[0].coords.pc1_2 =  pc11*sn + pc12*cs;
+    Target[0].coords.pc2_1 =  pc21*cs - pc22*sn;
+    Target[0].coords.pc2_2 =  pc21*sn + pc22*cs;
+    
+    Xo = Target[0].coords.crpix1;
+    Yo = Target[0].coords.crpix2;
+    Target[0].coords.crpix1 = answer[Imin].Xoff + cs*Xo - sn*Yo;
+    Target[0].coords.crpix2 = answer[Imin].Yoff + sn*Xo + cs*Yo;
+  }
+}
Index: /tags/start/Ohana/src/gastro2/src/getptolemy.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/getptolemy.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/getptolemy.c	(revision 12606)
@@ -0,0 +1,82 @@
+# include "gastro2.h"
+
+int getptolemy (CatStats *catstats, RefCatalog *Ref) {
+  
+  int i, j, k, Ns, Nptolemy, Nregions; 
+  double FracArea;
+  GSCdata *ptolemy;
+  CatStats *regions;
+
+  Ref[0].N = 0;
+  Ref[0].Area = 0;
+  ALLOCATE (Ref[0].stars, StarData, 1);
+
+  regions = gregions (catstats, &Nregions);
+  
+  for (i = 0; i < Nregions; i++) {
+    ptolemy = gptolemy (regions[i].name, &Nptolemy);
+    if (Nptolemy == 0) continue;
+
+    FracArea = ptolemy_area (ptolemy, Nptolemy, &regions[i]);
+
+    Ns = Ref[0].N;
+    Ref[0].N += Nptolemy;
+    Ref[0].Area += regions[i].Area * FracArea;
+
+    REALLOCATE (Ref[0].stars, StarData, MAX (1, Ref[0].N));
+    for (k = Ns, j = 0; j < Nptolemy; k++, j++) {
+      Ref[0].stars[k].R = ptolemy[j].R;
+      Ref[0].stars[k].D = ptolemy[j].D;
+      Ref[0].stars[k].M = ptolemy[j].M;
+    }      
+    free (ptolemy);
+  }
+  
+  Ref[0].R0 = catstats[0].RA[0];
+  Ref[0].R1 = catstats[0].RA[1];
+  Ref[0].D0 = catstats[0].DEC[0];
+  Ref[0].D1 = catstats[0].DEC[1];
+
+  /* calculate luminosity function of stars */
+  get_luminosity_func (Ref[0].stars, Ref[0].N, &Ref[0].lum);
+
+  if (VERBOSE) fprintf (stderr, "%d stars from PTOLEMY\n", Ref[0].N);
+  return (TRUE);
+}  
+
+double ptolemy_area (GSCdata *ptolemy, int N, CatStats *patch) {
+
+  int i, xb, yb, Nb;
+  int bin[10][10];
+  double frac, Rmin, Rmax, Dmin, Dmax, dR, dD;
+
+  Rmin = patch[0].RA[0];
+  Rmax = patch[0].RA[1];
+  Dmin = patch[0].DEC[0];
+  Dmax = patch[0].DEC[1];
+  dR = Rmax - Rmin;
+  dD = Dmax - Dmin;
+
+  for (xb = 0; xb < 10; xb++) {
+    for (yb = 0; yb < 10; yb++) {
+      bin[xb][yb] = 0;
+    }
+  }
+
+  for (i = 0; i < N; i++) {
+    xb = MAX (MIN (0, 10 * (ptolemy[i].R - Rmin) / dR), 9);
+    yb = MAX (MIN (0, 10 * (ptolemy[i].D - Dmin) / dD), 9);
+    bin[xb][yb] ++;
+  }
+
+  Nb = 0;
+  for (xb = 0; xb < 10; xb++) {
+    for (yb = 0; yb < 10; yb++) {
+      if (bin[xb][yb]) Nb ++;
+    }
+  }
+
+  frac = Nb / 100.0;
+
+  return (frac);
+}
Index: /tags/start/Ohana/src/gastro2/src/getusno.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/getusno.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/getusno.c	(revision 12606)
@@ -0,0 +1,144 @@
+# include "gastro2.h"
+# define NZONE 24
+
+int SPDzone[] = {
+  0, 75, 450, 375, 1500, 1650, 300, 1425, 1725, 525, 1275, 225, 
+  675, 150, 600, 1575, 750, 975, 900, 1050, 1125, 1200, 825, 1350};
+
+int USNOdisk[] = {
+  1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10};
+
+int getusno (CatStats *catstats, RefCatalog *Ref) {
+
+  long int offset;
+  int i, bin, first, last, nitems, Nitems, Nbins;
+  float hours[100];
+  int start[100], number[100], *buffer, *buf;
+  char filename[128], c;
+  FILE *f;
+  double DEC1;
+  int iDEC0, iDEC1, iRA0, iRA1;
+  int spd, spd_start, spd_end, disk;
+  int NUSNO, Nusno;
+  StarData *stars;
+
+  /* identify ra & dec range of interest */
+  iRA0 = catstats[0].RA[0] * 360000.0;
+  iRA1 = catstats[0].RA[1] * 360000.0;
+  iDEC0 = (catstats[0].DEC[0] + 90.0) * 360000.0;
+  iDEC1 = (catstats[0].DEC[1] + 90.0) * 360000.0;
+  
+  /* data is organized in south-pole distance zones */
+  spd_start = (int)((catstats[0].DEC[0] + 90) / 7.5) * 75.0;
+  DEC1 = (catstats[0].DEC[1] + 90) / 7.5;
+  if (DEC1 > (int)(DEC1)) {
+    spd_end =   (int)(1 + (catstats[0].DEC[1] + 90) / 7.5) * 75.0;
+  } else {
+    spd_end =   (int)(0 + (catstats[0].DEC[1] + 90) / 7.5) * 75.0;
+  }
+
+  Nusno = 0;
+  NUSNO = 5000;
+  ALLOCATE (stars, StarData, NUSNO);
+
+  for (spd = spd_start; spd < spd_end; spd += 75) {
+    disk = -1;
+    for (i = 0; i < NZONE; i++) {
+      if (spd == SPDzone[i]) 
+	disk = USNOdisk[i];
+    }
+    if (disk < 0) {
+      fprintf (stderr, "ERROR: can't find cdrom for spd %d\n",  spd);
+      exit (0);
+    }
+    
+    /* load accelerator file */
+    sprintf (filename, "%s/zone%04d.acc", CDROM, spd); 
+    fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "can't open file %s, is cdrom %d in drive?\n", filename, disk);
+      fprintf (stderr, "press return when ready to continue: ");
+      fscanf (stdin, "%c", &c);
+      fprintf (stderr, "trying again...\n");
+      f = fopen (filename, "r");
+      if (f == (FILE *) NULL) {
+	fprintf (stderr, "ERROR: can't open file %s, is cdrom %d in drive?\n", filename, disk);
+	exit (1);  
+      }
+    }
+    for (i = 0; fscanf (f, "%f %d %d", &hours[i], &start[i], &number[i]) != EOF; i++);
+    Nbins = i;
+    fclose (f);
+    
+    first = catstats[0].RA[0] / 3.75;
+    if ((catstats[0].RA[1] / 3.75) == (int) (catstats[0].RA[1] / 3.75)) 
+      last  = catstats[0].RA[1] / 3.75;
+    else 
+      last  = 1 + catstats[0].RA[1] / 3.75;
+
+    if ((first > Nbins) || (last > Nbins)) {
+      fprintf (stderr, "ERROR: RA out of range\n");
+      exit (1);
+    }
+    
+    /* open data file */
+    sprintf (filename, "%s/zone%04d.cat", CDROM, spd);
+    fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't open file %s\n", filename);
+      exit (1);
+    }
+    /* advance file pointer to first slice */
+    offset = 3*sizeof(int)*(start[first] - 1);
+    fseek (f, offset, SEEK_SET);
+    /* on each loop, load data from an RA slice of the catalog */
+    for (bin = first; bin < last; bin++) {
+      Nitems = 3*number[bin];
+      ALLOCATE (buffer, int, Nitems);
+      nitems = Fread (buffer, sizeof(int), Nitems, f, "int");
+      if (nitems != Nitems) {
+	fprintf (stderr, "ERROR: failure reading data from file %s\n", filename);
+	exit (1);
+      }
+      buf = buffer;
+      /* print out data from slice within RA and DEC range */
+      for (i = 0; i < number[bin]; i++, buf+=3) {
+	if ((buf[0] > iRA0) && (buf[0] < iRA1) &&
+	    (buf[1] > iDEC0) && (buf[1] < iDEC1)) {
+	  stars[Nusno].R = buf[0]/360000.0;
+	  stars[Nusno].D = buf[1]/360000.0 - 90.0;
+	  stars[Nusno].M = fabs (0.1*(buf[2] - 1000*((int)(buf[2]/1000))));
+	  /* b = 0.1*((int)(buf[2] - 1000000*((int)(buf[2]/1000000))) / 1000); */
+	  Nusno ++;
+	  if (Nusno == NUSNO) {
+	    NUSNO += 5000;
+	    REALLOCATE (stars, StarData, NUSNO);
+	  }	  
+	}
+      }
+      free (buffer);
+    }
+    fclose (f);
+  }
+
+  area_of_region (catstats);
+
+  REALLOCATE (stars, StarData, MAX (1, Nusno));
+
+  Ref[0].stars = stars;
+  Ref[0].N     = Nusno;
+  Ref[0].R0    = catstats[0].RA[0];
+  Ref[0].R1    = catstats[0].RA[1];
+  Ref[0].D0    = catstats[0].DEC[0];
+  Ref[0].D1    = catstats[0].DEC[1];
+  Ref[0].Area  = catstats[0].Area;
+
+  get_luminosity_func (Ref[0].stars, Ref[0].N, &Ref[0].lum);
+  
+  if (VERBOSE) fprintf (stderr, "%d stars from USNO 1.0\n", Nusno);
+  return (TRUE);
+}
+
+
Index: /tags/start/Ohana/src/gastro2/src/gfit2.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/gfit2.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/gfit2.c	(revision 12606)
@@ -0,0 +1,446 @@
+# include "gastro2.h"
+
+static int NPAIR, Npair;
+static int *idx1, *idx2;
+
+void gfit (CmpCatalog *Target, RefCatalog *Ref, int order) {
+
+  int i, j, j0;
+  double Radius, Radius2;
+  double dX, dY, dR;
+  RefCatalog Subset;
+  StarData *st, *sr;
+
+  NFIELD = 0.1;
+  gproject (Target, Ref, &Subset);
+  if (PLOTSTUFF) plot_fullfield (Target, &Subset);
+
+  if (Subset.N < 3) {
+    fprintf (stderr, "ERROR: solution off target\n");
+    exit (1);
+  }
+
+  /* need the stars sorted in X */
+  sort_stars_X (Target[0].stars, Target[0].N);
+  sort_stars_X (Subset.stars, Subset.N);
+
+  Radius = MAX (2.0 * Target[0].answer.dR, 0.5);
+  Radius2 = Radius*Radius;
+
+  st = Target[0].stars;
+  sr = Subset.stars;
+
+  /* find the matched pairs of stars within the radius */
+  pair_init ();
+  for (i = j = 0; (i < Target[0].N) && (j < Subset.N);) {
+    /* get in right X range */
+    dX = st[i].X - sr[j].X;
+    if (dX < -Radius) {
+      i++;
+      continue;
+    }
+    if (dX > Radius) {
+      j++;
+      continue;
+    }
+
+    /* check for pairs in this X range */
+    j0 = j;
+    for (; (dX > -Radius) && (j < Subset.N); j++) {
+    
+      dX = st[i].X - sr[j].X;
+      dY = st[i].Y - sr[j].Y;
+
+      dR = dX*dX + dY*dY;
+      if (dR > Radius2) {
+	j++;
+	continue;
+      }
+      pair_add (i, j);
+    }
+    j = j0;
+    i ++;
+  }
+  
+# if (0)
+  pair_init ();
+  for (i = 0; i < Target[0].N; i++) {
+    pair_add (i, i);
+  }
+# endif
+
+  fit_init (order);
+  fit_norm ();
+
+  plot_resid_init (0, (double) Target[0].header.Naxis[0]);
+  plot_resid_init (1, (double) Target[0].header.Naxis[1]);
+  if (PLOTSTUFF) plot_resid (st, sr);
+
+  /* find fit for matched pairs */
+  fit_init (order);
+  for (i = 0; i < Npair; i++) {
+    fit_add (st[idx1[i]].X, st[idx1[i]].Y, sr[idx2[i]].X, sr[idx2[i]].Y, 1.0);
+  }
+  fit_eval ();
+
+  Target[0].answer.dR = fit_scat (st, sr);
+  Target[0].answer.N  = fit_adjust (&Target[0].coords);
+
+  plot_resid_init (0, (double) Target[0].header.Naxis[0]);
+  plot_resid_init (1, (double) Target[0].header.Naxis[1]);
+  if (PLOTSTUFF) plot_resid (st, sr);
+  free (idx1);
+  free (idx2);
+}
+
+static int NTERM, NPOWR, NPARS, NORDER, Npts;
+static double **sum, **xsum, **ysum;
+static double **matrix, **vector;
+
+void fit_init (int order) {
+
+  int i;
+
+  NORDER = order;
+  NPOWR = NORDER + 1;
+  NTERM = 2*NORDER + 1;
+  NPARS = (NORDER + 1)*(NORDER + 2) / 2;
+  Npts  = 0;
+
+  /* allocate arrays for fit solution */
+  ALLOCATE (sum, double *, NTERM);
+  ALLOCATE (xsum, double *, NTERM);
+  ALLOCATE (ysum, double *, NTERM);
+  for (i = 0; i < NTERM; i++) {
+    ALLOCATE (sum[i], double, NTERM);
+    bzero (sum[i], NTERM*sizeof(double));
+    ALLOCATE (xsum[i], double, NTERM);
+    bzero (xsum[i], NTERM*sizeof(double));
+    ALLOCATE (ysum[i], double, NTERM);
+    bzero (ysum[i], NTERM*sizeof(double));
+  }
+  ALLOCATE (matrix, double *, NPARS);
+  ALLOCATE (vector, double *, NPARS);
+  for (i = 0; i < NPARS; i++) {
+    ALLOCATE (matrix[i], double, NPARS);
+    ALLOCATE (vector[i], double, 2);
+    bzero (vector[i], 2*sizeof(double));
+    bzero (matrix[i], NPARS*sizeof(double));
+  }
+
+}
+
+void fit_add (double x1, double y1, double x2, double y2, double wt) {
+
+  int n, m;
+  double xterm, yterm, term;
+
+  xterm = 1;
+  for (n = 0; n < NTERM; n++) {
+    yterm = 1;
+    for (m = 0; m < NTERM; m++) {
+      term = xterm*yterm;
+      if (n+m < NTERM) {
+	sum[n][m] += term;
+      }
+      if (n+m < NPOWR) {
+	xsum[n][m] += x2*term;
+	ysum[n][m] += y2*term;
+      }
+      yterm *= y1;
+    }
+    xterm *= x1;
+  }
+  Npts ++;
+
+}
+
+void fit_eval () {
+
+  int i, j, n, m, M, N;
+  double max;
+
+  fprintf (stderr, "npts: %d\n", Npts);
+
+  i = 0;
+  for (m = 0; m < NPOWR; m++) {
+    for (n = 0; n < NPOWR - m; n++, i++) {
+      vector[i][0] = xsum[n][m];
+      vector[i][1] = ysum[n][m];
+    }	
+  }
+  j = 0;
+  for (M = 0; M < NPOWR; M++) {
+    for (N = 0; N < NPOWR - M; N++, j++) {
+      i = 0;
+      for (m = 0; m < NPOWR; m++) {
+	for (n = 0; n < NPOWR - m; n++, i++) {
+	  matrix[i][j] = sum[n+N][m+M];
+	}	
+      }
+    }
+  }       
+  max = 0.0;
+  for (i = 0; i < NPARS; i++) {
+    for (j = 0; j < NPARS; j++) {
+      max = MAX (max, fabs(matrix[i][j]));
+    }
+    max = MAX (max, fabs(vector[i][0]));
+    max = MAX (max, fabs(vector[i][1]));
+  }
+  for (i = 0; i < NPARS; i++) {
+    for (j = 0; j < NPARS; j++) {
+      matrix[i][j] /= max;
+    }
+    vector[i][0] /= max;
+    vector[i][1] /= max;
+  }
+# if (0)
+  for (i = 0; i < NPARS; i++) {
+    for (j = 0; j < NPARS; j++) {
+      fprintf (stderr, "%10.4e  ", matrix[i][j]);
+    }
+    fprintf (stderr, "  %10.4e  ", vector[i][0]);
+    fprintf (stderr, "  %10.4e  \n", vector[i][1]);
+  }
+# endif
+  gaussj (matrix, NPARS, vector, 2); 
+# if (0)
+  fprintf (stderr, "\n\n");
+  for (i = 0; i < NPARS; i++) {
+    for (j = 0; j < NPARS; j++) {
+      fprintf (stderr, "%11.4e  ", matrix[i][j]);
+    }
+    fprintf (stderr, "  %11.4e  ", vector[i][0]);
+    fprintf (stderr, "  %11.4e  \n", vector[i][1]);
+  }
+# endif
+  i = 0;
+  for (m = 0; m < NPOWR; m++) {
+    for (n = 0; n < NPOWR - m; n++, i++) {
+      xsum[n][m] = vector[i][0];
+      ysum[n][m] = vector[i][1];
+    }	
+  }
+  i = 0;
+  for (m = 0; m < NPOWR; m++) {
+    for (n = 0; n < NPOWR - m; n++, i++) {
+      fprintf (stderr, "RA x^%dy^%d: %10.4g    DEC x^%dy^%d: %10.4g \n", 
+	       n, m, vector[i][0], n, m, vector[i][1]);
+    }	
+  }
+}
+
+void fit_norm () { 
+
+  xsum[0][0] = 0;
+  xsum[1][0] = 1;
+  xsum[0][1] = 0;
+
+  ysum[0][0] = 0;
+  ysum[1][0] = 0;
+  ysum[0][1] = 1;
+}
+
+void fit_apply (double *x, double *y, double X, double Y) {
+
+  int m, n;
+  double xterm, yterm;
+  double Xo, Yo;
+
+  Xo = Yo = 0;
+  yterm = 1;
+  for (m = 0; m < NPOWR; m++) { 
+    xterm = 1;
+    for (n = 0; n < NPOWR - m; n++) {
+      Xo += xterm*yterm*xsum[n][m];
+      Yo += xterm*yterm*ysum[n][m];
+      xterm *= X;
+    }	
+    yterm *= Y;
+  }
+  
+  *x = Xo;
+  *y = Yo;
+}
+
+
+void pair_init () {
+
+  Npair = 0;
+  NPAIR = 100;
+  ALLOCATE (idx1, int, NPAIR);
+  ALLOCATE (idx2, int, NPAIR);
+
+}
+
+void pair_add (int i1, int i2) {
+
+  idx1[Npair] = i1;
+  idx2[Npair] = i2;
+
+  Npair ++;
+
+  if (Npair == NPAIR) {
+    NPAIR += 100;
+    REALLOCATE (idx1, int, NPAIR);
+    REALLOCATE (idx2, int, NPAIR);
+  }
+
+}
+
+double fit_scat (StarData *st, StarData *sr) {
+
+  int i;
+  double x, y, dx, dy, dX, dY, dX2, dY2, dR;
+  
+  dX = dY = dX2 = dY2 = 0;
+  for (i = 0; i < Npair; i++) {
+
+    fit_apply (&x, &y, sr[idx2[i]].X, sr[idx2[i]].Y);
+    
+    dx = x - st[idx1[i]].X;
+    dy = y - st[idx1[i]].Y;
+    
+    dX += dx;
+    dY += dy;
+    dX2 += dx*dx;
+    dY2 += dy*dy;
+    
+  }
+
+  dX = dX / Npair;
+  dY = dY / Npair;
+  fprintf (stderr, "scatter: %f, %f\n", sqrt(dX2/Npair - dX*dX), sqrt(dY2/Npair - dY*dY));
+  fprintf (stderr, "precise: %f, %f\n", sqrt((dX2/Npair - dX*dX) / Npair), sqrt((dY2/Npair - dY*dY)/Npair));
+
+  dR = 0.5 * sqrt(fabs(dX2/Npair - dX*dX)) + 0.5 * sqrt (fabs(dY2/Npair - dY*dY));
+  return (dR);
+}
+
+/* convert new terms to adjustments in coords and to polyterms */
+int fit_adjust (Coords *coords) {
+
+  int i, j, N;
+  double S1, S2, p11, p12, p21, p22;
+  double a0, a1, a2, b0, b1, b2, det;
+  double X, Y;
+  int Np, Nv;
+    
+  S1 = coords[0].cdelt1;
+  S2 = coords[0].cdelt2;
+  p11 = coords[0].pc1_1;    p12 = coords[0].pc1_2;
+  p21 = coords[0].pc2_1;    p22 = coords[0].pc2_2;
+    
+  /* get the correct vector entries for the linear terms */
+  N = mk_vector (0, 0, NORDER);
+  a0 = vector[N][0];  b0 = vector[N][1];
+  N = mk_vector (1, 0, NORDER);
+  a1 = vector[N][0];  b1 = vector[N][1];
+  N = mk_vector (0, 1, NORDER);
+  a2 = vector[N][0];  b2 = vector[N][1];
+
+  det = 1.0 / (a1*b2 - a2*b1);
+
+  coords[0].pc1_1 = p11*a1 + p12*b1*(S2/S1);
+  coords[0].pc2_1 = p21*a1 + p22*b1*(S2/S1);
+    
+  coords[0].pc1_2 = p12*b2 + p11*a2*(S1/S2);
+  coords[0].pc2_2 = p22*b2 + p21*a2*(S1/S2);
+    
+  X = (coords[0].crpix1 - a0);
+  Y = (coords[0].crpix2 - b0);
+  coords[0].crpix1 = det*(X*b2 - Y*a2);
+  coords[0].crpix2 = det*(Y*a1 - X*b1);
+
+  coords[0].Npolyterms = NORDER;
+  if (NORDER > 1) strcpy (coords[0].ctype, "DEC--PLY");
+
+  /* generate higher order terms from vector */
+  for (i = 0; i < NORDER + 1; i++) {
+    for (j = 0; j < (NORDER - i + 1); j++) {
+      if (i + j < 2) continue;
+      Np = mk_polyterm (i, j, NORDER);
+      Nv = mk_vector (i, j, NORDER);
+      coords[0].polyterms[Np][0] = det*(vector[Nv][0]*b2  - vector[Nv][1]*a2);  /* x2 y0 */
+      coords[0].polyterms[Np][1] = det*(vector[Nv][1]*a1  - vector[Nv][0]*b1);  /* x2 y0 */
+    }
+  }
+  while (coords[0].crval1 < 0) coords[0].crval1 += 360.0;
+  while (coords[0].crval1 > 360.0) coords[0].crval1 -= 360.0;
+
+  /* test for valid solution */
+  return (Npts);
+
+}
+
+int mk_polyterm (int n, int m, int norder) {
+  
+  int i, nt, N;
+  
+  N = 0;
+  nt = n + m;
+  for (i = 2; i < nt; i++) {
+    N += i + 1;
+  }
+  N += m;
+  return (N);
+}
+
+int mk_vector (int n, int m, int norder) {
+  
+  int i, N;
+  
+  N = 0;
+  for (i = 0; i < m; i++) {
+    N += (norder - i + 1);
+  }
+  N += n;
+  return (N);
+}
+
+void plot_resid (StarData *st, StarData *sr) {
+
+  int i;
+  double x, y, dx, dy;
+  float *xvect0, *yvect0, *xvect1, *yvect1, *xvect2, *yvect2;
+  int Nvect;
+
+  Nvect = Npair;
+  ALLOCATE (xvect0, float, Nvect);
+  ALLOCATE (yvect0, float, Nvect);
+  ALLOCATE (xvect1, float, Nvect);
+  ALLOCATE (yvect1, float, Nvect);
+
+  ALLOCATE (xvect2, float, 2*Nvect);
+  ALLOCATE (yvect2, float, 2*Nvect);
+  
+  for (i = 0; i < Npair; i++) {
+    fit_apply (&x, &y, st[idx1[i]].X, st[idx1[i]].Y);
+    
+    dx = x - sr[idx2[i]].X;
+    dy = y - sr[idx2[i]].Y;
+    
+    xvect0[i] = sr[idx2[i]].X;
+    xvect1[i] = sr[idx2[i]].Y;
+    yvect0[i] = dx;
+    yvect1[i] = dy;
+
+    xvect2[2*i+0] = sr[idx2[i]].X;
+    yvect2[2*i+0] = sr[idx2[i]].Y;
+    xvect2[2*i+1] = x;
+    yvect2[2*i+1] = y;
+  }
+
+  plot_resid_plot (0, xvect0, yvect0, Nvect);
+  plot_resid_plot (1, xvect1, yvect1, Nvect);
+  plot_fullfield_pairs (xvect2, yvect2, 2*Nvect);
+
+  free (xvect2);
+  free (yvect2);
+  free (xvect0);
+  free (yvect0);
+  free (xvect1);
+  free (yvect1);
+
+}
Index: /tags/start/Ohana/src/gastro2/src/gheader2.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/gheader2.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/gheader2.c	(revision 12606)
@@ -0,0 +1,123 @@
+# include "gastro2.h"
+
+void gheader (char *file, CmpCatalog *Target) {
+
+  double dR;
+  Header header;
+  FILE *f, *g;
+  int i, oldsize, nbytes, status;
+  char line[1024];
+
+  if (!fits_read_header (file, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s (3)\n", file);
+    exit(0);
+  }
+  oldsize = header.size;
+
+  if (Target[0].answer.N < 6) {
+    fits_modify (&header, "NASTRO", "%d", 1, 0);
+    fits_modify (&header, "NASTRO", "%C", 1, "number of stars used for astrometry");
+    goto skipstuff;
+  }
+  
+  fits_modify (&header, "NASTRO", "%d", 1, Target[0].answer.N);
+  fits_modify (&header, "NASTRO", "%C", 1, "number of stars used for astrometry");
+
+  if (Target[0].coords.Npolyterms > 1) {
+    fits_modify (&header, "CTYPE1",   "%s",  1, "RA---PLY");
+    fits_modify (&header, "CTYPE2",   "%s",  1, "DEC--PLY");
+  } else {
+    fits_modify (&header, "CTYPE1",   "%s",  1, "RA---TAN");
+    fits_modify (&header, "CTYPE2",   "%s",  1, "DEC--TAN");
+  }    
+  fits_modify (&header, "CDELT1",   "%le", 1, Target[0].coords.cdelt1); 
+  fits_modify (&header, "CDELT2",   "%le", 1, Target[0].coords.cdelt2);
+  fits_modify (&header, "CRVAL1",   "%lf", 1, Target[0].coords.crval1);
+  fits_modify (&header, "CRVAL2",   "%lf", 1, Target[0].coords.crval2);  
+  fits_modify (&header, "CRPIX1",   "%lf", 1, Target[0].coords.crpix1);
+  fits_modify (&header, "CRPIX2",   "%lf", 1, Target[0].coords.crpix2);
+  fits_modify (&header, "PC001001", "%le", 1, Target[0].coords.pc1_1);
+  fits_modify (&header, "PC001002", "%le", 1, Target[0].coords.pc1_2);
+  fits_modify (&header, "PC002001", "%le", 1, Target[0].coords.pc2_1);
+  fits_modify (&header, "PC002002", "%le", 1, Target[0].coords.pc2_2);
+  fits_modify (&header, "NPLYTERM", "%d", 1, Target[0].coords.Npolyterms);
+  if (Target[0].coords.Npolyterms > 1) {
+    /* RA Terms */
+    fits_modify (&header, "PCA1X2Y0", "%le", 1, Target[0].coords.polyterms[0][0]);   /* polyterms[0]); */
+    fits_modify (&header, "PCA1X1Y1", "%le", 1, Target[0].coords.polyterms[1][0]);   /* polyterms[1]); */
+    fits_modify (&header, "PCA1X0Y2", "%le", 1, Target[0].coords.polyterms[2][0]);   /* polyterms[2]); */
+
+    if (Target[0].coords.Npolyterms > 2) {
+      fits_modify (&header, "PCA1X3Y0", "%le", 1, Target[0].coords.polyterms[3][0]);   /* polyterms[3]); */
+      fits_modify (&header, "PCA1X2Y1", "%le", 1, Target[0].coords.polyterms[4][0]);   /* polyterms[4]); */
+      fits_modify (&header, "PCA1X1Y2", "%le", 1, Target[0].coords.polyterms[5][0]);   /* polyterms[5]); */
+      fits_modify (&header, "PCA1X0Y3", "%le", 1, Target[0].coords.polyterms[6][0]);   /* polyterms[6]); */
+    }
+    /* Dec Terms */
+    fits_modify (&header, "PCA2X2Y0", "%le", 1, Target[0].coords.polyterms[0][1]);   /* polyterms[7]); */
+    fits_modify (&header, "PCA2X1Y1", "%le", 1, Target[0].coords.polyterms[1][1]);   /* polyterms[8]); */
+    fits_modify (&header, "PCA2X0Y2", "%le", 1, Target[0].coords.polyterms[2][1]);   /* polyterms[9]); */
+
+    if (Target[0].coords.Npolyterms > 2) {
+      fits_modify (&header, "PCA2X3Y0", "%le", 1, Target[0].coords.polyterms[3][1]);   /* polyterms[10]); */
+      fits_modify (&header, "PCA2X2Y1", "%le", 1, Target[0].coords.polyterms[4][1]);   /* polyterms[11]); */
+      fits_modify (&header, "PCA2X1Y2", "%le", 1, Target[0].coords.polyterms[5][1]);   /* polyterms[12]); */
+      fits_modify (&header, "PCA2X0Y3", "%le", 1, Target[0].coords.polyterms[6][1]);   /* polyterms[13]); */
+    }
+  }
+
+  dR = fabs (Target[0].answer.dR*Target[0].coords.cdelt1*3600.0);
+  fits_modify (&header, "CERROR", "%lf", 1, dR);
+  fits_modify (&header, "CERROR", "%C", 1, "scatter in astrometry soln (arcsec)");
+  fits_modify (&header, "CPRECISE", "%lf", 1, dR / sqrt(1.0*Target[0].answer.N));
+  fits_modify (&header, "CPRECISE", "%C", 1, "precision of astrometry soln (arcsec)");
+  fits_modify (&header, "EQUINOX", "%lf", 1, 2000.0);
+  /* we force equinox to be 2000.0 for all images */
+
+skipstuff:
+  if (header.size > oldsize) {
+    if (VERBOSE) fprintf (stderr, "header expanded, creating new copy\n");
+    sprintf (line, "mv %s %s~", file, file);
+    status = system (line);
+    if (status) {
+      fprintf (stderr, "ERROR: unable to create %s~, exiting\n", file);
+      exit (0);
+    }
+    sprintf (line, "%s~", file);
+    f = fopen (line, "r");
+    g = fopen (file, "w");
+    if (f == NULL) {
+      fprintf (stderr, "ERROR: can't find image file %s (4)\n", line);
+      exit(0);
+    }
+    if (g == NULL) {
+      fprintf (stderr, "ERROR: can't open output image file %s (4)\n", file);
+      exit(0);
+    }
+    nbytes = fwrite (header.buffer, 1, header.size, g);
+    fseek (f, oldsize, SEEK_SET);
+    for (i = 0; (nbytes = fread (header.buffer, 1, header.size, f)) > 0; i++) {
+      if (nbytes != fwrite (header.buffer, 1, nbytes, g)) {
+	fprintf (stderr, "ERROR: failure writing output data file\n");
+	exit (0);
+      }
+    }
+    fclose (f);
+    fclose (g);
+  } else {
+    f = fopen (file, "r+");
+    if (f == NULL) {
+      fprintf (stderr, "ERROR: can't find image file %s (4)\n", file);
+      exit(0);
+    }
+    
+    fseek (f, 0, SEEK_SET);
+    nbytes = fwrite (header.buffer, 1, header.size, f);
+    
+    fclose (f);
+  }
+  free (header.buffer);
+
+}
+
+
Index: /tags/start/Ohana/src/gastro2/src/gproject2.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/gproject2.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/gproject2.c	(revision 12606)
@@ -0,0 +1,71 @@
+# include "gastro2.h"
+
+void gproject (CmpCatalog *Target, RefCatalog *Ref, RefCatalog *Subset) {
+
+  int i, N;
+  double X, Y, M, Moff;
+  double XMIN, XMAX, YMIN, YMAX, MMIN, MMAX;
+  Coords *coords;
+  StarData *in, *out;
+
+  Subset[0] = Ref[0];
+
+  ALLOCATE (Subset[0].stars, StarData, MAX (1, Ref[0].N));
+
+  in     = Ref[0].stars;
+  out    = Subset[0].stars;
+  coords = &Target[0].coords;
+
+  Moff = Ref[0].Moff;
+
+  XMIN = -0.5*NFIELD*Target[0].header.Naxis[0];
+  XMAX =  0.5*NFIELD*Target[0].header.Naxis[0] + Target[0].header.Naxis[0];
+  YMIN = -0.5*NFIELD*Target[0].header.Naxis[1];
+  YMAX =  0.5*NFIELD*Target[0].header.Naxis[1] + Target[0].header.Naxis[1];
+ 
+  /* need to allow some leeway? use a fixed +/- 0.5 mag for now */
+  MMAX = Target[0].lum.Mmax + 0.5;
+  MMIN = Target[0].lum.Mmin - 0.5;
+
+  if (MMAX < Ref[0].lum.Mmin + Moff) 
+    fprintf (stderr, "warning: reference catalog probably too faint:  %5.3f < %5.3f\n", Target[0].lum.Mmax, Ref[0].lum.Mmin + Moff);
+
+  if (MMIN > Ref[0].lum.Mmax + Moff) 
+    fprintf (stderr, "warning: reference catalog probably too bright: %5.3f > %5.3f\n", Target[0].lum.Mmin, Ref[0].lum.Mmax + Moff);
+
+  for (N = i = 0; i < Ref[0].N; i++) {
+    RD_to_XY (&X, &Y, in[i].R, in[i].D, coords);
+    M = in[i].M + Moff;
+
+    if (X < XMIN) continue;
+    if (X > XMAX) continue;
+    if (Y < YMIN) continue;
+    if (Y > YMAX) continue;
+
+    if (MAGLIMS) {
+      if (M < MMIN) continue;
+      if (M > MMAX) continue;
+    }
+
+    out[N] = in[i];
+    out[N].X = X;
+    out[N].Y = Y;
+    out[N].M = M;
+    N++;
+  }
+
+  if (N < 3) {
+    fprintf (stderr, "ERROR: too few reference stars accepted\n");
+    exit (1);
+  }
+    
+  Subset[0].N = N;
+  REALLOCATE (Subset[0].stars, StarData, MAX (1, Subset[0].N));
+
+}
+
+/* in this function, we convert the Ra & Dec coords to the rough X, Y coords
+   we also convert the magnitudes to the approximate system with Ref[0].Moff 
+   also, reduce the domain to those within X, Y, M limits 
+*/
+
Index: /tags/start/Ohana/src/gastro2/src/gptolemy2.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/gptolemy2.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/gptolemy2.c	(revision 12606)
@@ -0,0 +1,53 @@
+# include "gastro2.h"
+
+/* filename has path to GSC, strip off path, use filename with CATDIR path */
+
+GSCdata *gptolemy (char *fullpath, int *Nstars) {
+  
+  int i, nstar;
+  char filename[256], *fileroot, *filepath, *subdir;
+  Catalog catalog;
+  GSCdata *stars;
+
+  filepath = pathname (fullpath);
+  fileroot = filebasename (fullpath);
+  subdir = filebasename (filepath);
+  sprintf (filename, "%s/%s/%s", CATDIR, subdir, fileroot);
+
+  *Nstars = 0;
+  catalog.filename = filename;
+  switch (lock_catalog (&catalog, LCK_SOFT)) {
+  case 0:
+  case 2:
+    fprintf (stderr, "can't lock catalog data %s\n", filename);
+    return ((GSCdata *)NULL);
+  case 1:
+    break;
+  }
+  if (!load_catalog (&catalog, LOAD_AVES | LOAD_MEAS, FALSE)) {
+    fprintf (stderr, "can't load catalog data %s\n", filename);
+    return ((GSCdata *)NULL);
+  }
+  unlock_catalog (&catalog);
+
+  nstar = 0;
+  *Nstars = catalog.Naverage;
+  if (catalog.Naverage == 0) return ((GSCdata *)NULL);
+
+  ALLOCATE (stars, GSCdata, *Nstars);
+
+  /* select all entries, ignore magnitudes */
+  for (i = 0; i < catalog.Naverage; i++, nstar++) {
+    stars[nstar].R = catalog.average[i].R;
+    stars[nstar].D = catalog.average[i].D;
+    stars[nstar].M = 0.001*catalog.measure[catalog.average[i].offset].M;
+  }
+
+  free (catalog.average);
+
+  *Nstars = nstar;
+  REALLOCATE (stars, GSCdata, *Nstars);
+  
+  return (stars);
+
+}
Index: /tags/start/Ohana/src/gastro2/src/greference2.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/greference2.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/greference2.c	(revision 12606)
@@ -0,0 +1,80 @@
+# include "gastro2.h"
+
+void greference (CmpCatalog *Target, RefCatalog *Ref) {
+
+  CatStats catstats;
+
+  if (VERBOSE) fprintf (stderr, "loading astrometric reference data from %s\n", REFCAT); 
+
+  define_region (&catstats, Target);
+
+  Ref[0].N = 0;
+  /* get stars from the USNO catalog for the given region */
+  if (!strcmp (REFCAT, "USNO")) {
+    getusno (&catstats, Ref);
+    /* calculate Ref[0].Moff from Target & Ref dMdN, Mo */
+  }
+
+  /* get stars from the HST GSC catalog for the given region */
+  if (!strcmp (REFCAT, "GSC")) {
+    getgsc (&catstats, Ref);
+  }
+  
+  /* get stars from the HST GSC catalog for the given region */
+  if (!strcmp (REFCAT, "2MASS")) {
+    get2mass (&catstats, Ref);
+  }
+  
+  /* get stars from the HST GSC catalog for the given region */
+  if (!strcmp (REFCAT, "PTOLEMY")) {
+    getptolemy (&catstats, Ref);
+  }
+  
+  if (Ref[0].N == 0) {
+    fprintf (stderr, "no ref objs: %s\n", REFCAT);
+    exit (1);
+  }
+
+  Ref[0].lum.Mz = (2 + log (Ref[0].Area) / log (10.) - Ref[0].lum.Mo) / Ref[0].lum.dNdM;
+  Target[0].lum.Mz = (2 + log (Target[0].Area) / log (10.) - Target[0].lum.Mo) / Target[0].lum.dNdM;
+  Ref[0].Moff = Target[0].lum.Mz - Ref[0].lum.Mz;
+  fprintf (stderr, "mag offset: %f (Areas: %f vs %f)\n", Ref[0].Moff, Target[0].Area, Ref[0].Area);
+
+  if (PLOTSTUFF) plot_lumfunc (Target, Ref);
+
+}
+
+/* return RA, DEC bounds of the reigon of interest */  
+void define_region (CatStats *catstats, CmpCatalog *Target) {
+   
+  int NX, NY;
+  double x, y, X, Y, R, D, dX, dY, Xo, Yo;
+
+  NX = Target[0].header.Naxis[0];
+  NY = Target[0].header.Naxis[1];
+
+  dX = NX + NFIELD*NX;
+  dY = NY + NFIELD*NY;
+
+  Xo = -0.5*NFIELD*NX;
+  Yo = -0.5*NFIELD*NY;
+
+  catstats[0].RA[0] = catstats[0].DEC[0] =  360.0;
+  catstats[0].RA[1] = catstats[0].DEC[1] = -360.0;
+
+  for (x = 0; x <= 1.0; x += 0.5) {
+    for (y = 0; y <= 1.0; y += 0.5) {
+
+      X = x*dX + Xo;
+      Y = y*dY + Yo;
+      XY_to_RD (&R, &D, X, Y, &Target[0].coords);
+
+      catstats[0].RA[0]  = MIN (catstats[0].RA[0], R);
+      catstats[0].RA[1]  = MAX (catstats[0].RA[1], R);
+      catstats[0].DEC[0] = MIN (catstats[0].DEC[0], D);
+      catstats[0].DEC[1] = MAX (catstats[0].DEC[1], D);
+    }
+  }
+  if (VERBOSE) fprintf (stderr, "full region: %f - %f, %f - %f\n", 
+	   catstats[0].RA[0], catstats[0].RA[1], catstats[0].DEC[0], catstats[0].DEC[1]);
+}
Index: /tags/start/Ohana/src/gastro2/src/gregions2.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/gregions2.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/gregions2.c	(revision 12606)
@@ -0,0 +1,247 @@
+# include "gastro2.h"
+# define MAX_NAME 256
+
+static int Nregion, NREGION;
+static CatStats *region;
+static char *CatDir;
+
+/* data which defines the layout of the regions */
+# define NDECBANDS 12
+double DecBand[] = {0.0, +7.5, +15.0, +22.5, +30.0, +37.5, +45.0, +52.5, +60.0, +67.5, +75.0, +82.5, +90.0,
+		    0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+
+int NDecLines[] =  {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 24, 0, 
+		    597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48, 0};
+
+int NRaBlocks [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 0, 
+		    48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 0};
+
+char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			"n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			"s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			"s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+/* given patch on sky with RA[0] - RA[1] & DEC[0] - DEC[1], return all that fall in range */
+CatStats *gregions (CatStats *patch, int *nregion) {
+  
+  CatStats area;
+  double dtmp;
+  char file[MAX_NAME];
+
+  init_regions ();
+
+  /* force RA[i] to be in range 0 - 360 , DEC[0] < DEC[1] */
+  while (patch[0].RA[0] > 360.0) { patch[0].RA[0] -= 360.0; }
+  while (patch[0].RA[0] < 0.0)   { patch[0].RA[0] += 360.0; }
+  while (patch[0].RA[1] > 360.0) { patch[0].RA[1] -= 360.0; }
+  while (patch[0].RA[1] < 0.0)   { patch[0].RA[1] += 360.0; }
+  if (patch[0].DEC[0] > patch[0].DEC[1]) {
+    dtmp = patch[0].DEC[0];
+    patch[0].DEC[0] = patch[0].DEC[1];
+    patch[0].DEC[1] = dtmp;
+  }
+
+  /* include the pole if dec > 86.25 is included (ADD SOUTH POLE!)  */
+  if (patch[0].DEC[1] > 86.25) {
+    area.RA[0]  =   0.00;
+    area.RA[1]  = 360.00;
+    area.DEC[0] =  86.25;
+    area.DEC[1] =  90.00;
+    sprintf (file, "n8230/pole");
+    area.name = strcreate (file);
+    add_to_regions (&area);
+    free (area.name);
+  }
+  
+  /* if RA[0] > RA[1], split in two passes */
+  if (patch[0].RA[0] > patch[0].RA[1]) {
+    area = patch[0];
+    area.RA[0]  = 0.0;
+    find_dec_bands (&area);
+
+    area = patch[0];
+    area.RA[1]  = 360.0;
+    find_dec_bands (&area);
+  } else {
+    area = patch[0];
+    find_dec_bands (&area);
+  }
+
+  *nregion = Nregion;
+  return (region);
+}
+
+/* given an area [RA[0] - RA[1], DEC[0] - DEC[1],
+   where 0.0 < RA[0] < RA[1] < 360.0 
+   and -90.0 < (DEC[0], DEC[1]) < 90.0 
+   and DEC[0] < DEC[1]
+   search through the dec bands to identify ones which overlap the area */
+
+int find_dec_bands (CatStats *area) {
+
+  int i;
+
+  /* for NORTH region (DecBand[i] < DecBand[i+1]) */
+  for (i = 0; i < NDECBANDS; i++) {
+    if ((area[0].DEC[1] > DecBand[i]) || (area[0].DEC[0] < DecBand[i+1])) {
+      load_ra_blocks (i, area);
+    }
+  }
+
+  /* for SOUTH region (DecBand[i] > DecBand[i+1]) */
+  for (i = NDECBANDS+1; i < 2*NDECBANDS; i++) {
+    if ((area[0].DEC[0] < DecBand[i]) || (area[0].DEC[1] > DecBand[i+1])) {
+      load_ra_blocks (i, area);
+    }
+  }
+  return (TRUE);
+}
+
+/* given the number of a DecBlock and a defined area, return all area names in that block */
+/* area is defined so that RA[0] < RA[1], DEC[0] < DEC[1] */
+int load_ra_blocks (int Ndec, CatStats *area) {
+
+  CatStats tregion;
+  int i, Nlines, Nskip;
+  char *buffer, file[MAX_NAME];
+  FILE *f;
+
+  /* count lines before Dec Band, and in Dec Band */
+  Nskip = 0;
+  for (i = 0; i < Ndec; i++) Nskip += NDecLines[i];
+  Nlines = NDecLines[Ndec];
+
+  ALLOCATE (buffer, char, 48*Nlines);
+  ALLOCATE (tregion.name, char, MAX_NAME);
+
+  /* get data from GSC file */ 
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find GSC regions file %s\n", GSCFILE);
+    exit (1);
+  }
+  fseek (f, 5*2880 + 48*Nskip, SEEK_SET);
+  fread (buffer, 48*Nlines, 1, f);
+  fclose (f);
+
+  /* find overlapping regions */
+  for (i = 0; i < Nlines; i++) {
+    parse_GSC_line (&tregion, &buffer[i*48]);
+    if (area[0].RA[0] > tregion.RA[1]) continue;
+    if (area[0].RA[1] < tregion.RA[0]) continue;
+    if (area[0].DEC[0] > tregion.DEC[1]) continue;
+    if (area[0].DEC[1] < tregion.DEC[0]) continue;
+    sprintf (file, "%s/%s", Dec2Sections[Ndec], tregion.name);
+    strcpy (tregion.name, file);
+    add_to_regions (&tregion);
+  }
+
+  free (buffer);
+  free (tregion.name);
+  return (TRUE);
+}
+
+/* parse the GSC line, placing values in 'region'. force RA[0] < RA[1], DEC[0] < DEC[1] */
+int parse_GSC_line (CatStats *tregion, char *line) {
+  
+  double v0, s, dtmp;
+  char tmp[10];
+
+  /* copy name (4 chars) */
+  bzero (tregion[0].name, 10);
+  strncpy (tregion[0].name, &line[1], 4);
+
+  /* get RA[0] */
+  bzero (tmp, 10);
+  strncpy (tmp, &line[7], 2);
+  v0 = atof (tmp);
+  
+  bzero (tmp, 10);
+  strncpy (tmp, &line[10], 2);
+  v0 += atof (tmp) / 60.0;
+  
+  bzero (tmp, 10);
+  strncpy (tmp, &line[13], 5);
+  v0 += atof (tmp) / 3600.0;
+  tregion[0].RA[0] = v0 * 15.0;
+
+  /* get RA[1] */
+  bzero (tmp, 10);
+  strncpy (tmp, &line[19], 2);
+  v0 = atof (tmp);
+  
+  bzero (tmp, 10);
+  strncpy (tmp, &line[22], 2);
+  v0 += atof (tmp) / 60.0;
+  
+  bzero (tmp, 10);
+  strncpy (tmp, &line[25], 5);
+  v0 += atof (tmp) / 3600.0;
+  tregion[0].RA[1] = v0 * 15.0;
+
+  /* this only happens at the 0,360 boundary */
+  if (tregion[0].RA[1] < tregion[0].RA[0]) tregion[0].RA[1] += 360.0;
+
+  /* get DEC[0] */
+  if (line[31] == '-') s = -1;
+  else s = +1;
+
+  bzero (tmp, 10);
+  strncpy (tmp, &line[32], 2);
+  v0 = atof (tmp);
+  
+  bzero (tmp, 10);
+  strncpy (tmp, &line[35], 2);
+  v0 += atof (tmp) / 60.0;
+  tregion[0].DEC[0] = s * v0;
+
+  /* get DEC[1] */
+  if (line[40] == '-') s = -1;
+  else s = +1;
+
+  bzero (tmp, 10);
+  strncpy (tmp, &line[41], 2);
+  v0 = atof (tmp);
+  
+  bzero (tmp, 10);
+  strncpy (tmp, &line[44], 2);
+  v0 += atof (tmp) / 60.0;
+  tregion[0].DEC[1] = s * v0;
+
+  if (tregion[0].DEC[0] > tregion[0].DEC[1]) {
+    dtmp = tregion[0].DEC[1];
+    tregion[0].DEC[1] = tregion[0].DEC[0];
+    tregion[0].DEC[0] = dtmp;
+  }
+  return (TRUE);
+}
+
+void init_regions () {
+
+  Nregion = 0;
+  NREGION = 100;
+
+  ALLOCATE (region, CatStats, NREGION);
+
+}
+
+void add_to_regions (CatStats *area) {
+
+  region[Nregion] = area[0];
+  ALLOCATE (region[Nregion].name, char, MAX_NAME);
+  sprintf (region[Nregion].name, "%s/%s.%s", CatDir, area[0].name, "cpt");
+
+  area_of_region (&region[Nregion]);
+
+  Nregion ++;
+
+  if (Nregion == NREGION) {
+    NREGION += 100;
+    REALLOCATE (region, CatStats, NREGION);
+  }
+
+}
+
+void set_catalog (char *catdir) {
+  CatDir = catdir;
+}
Index: /tags/start/Ohana/src/gastro2/src/grid.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/grid.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/grid.c	(revision 12606)
@@ -0,0 +1,216 @@
+# include "gastro2.h"
+
+# define NPIX 50
+static int NX, NY, Nbin;
+static double C0x, C1x, C0y, C1y;
+static double *N, *DX, *DY, *D2;
+
+void grid (CmpCatalog *Target, RefCatalog *Subset, Answer *answer) {
+
+  int i, j, n, Imin, Nmin, Nval;
+  double XMIN, XMAX, YMIN, YMAX;
+  double dX, dY;
+  double s, f, Fmin, Smin, *ntmp;
+
+  RefCatalog Ref;
+  StarData *st, *sr;
+
+  /* Ref is temporary in this function.  Free Ref.stars before exiting */
+  rotate (Subset, &Ref, answer[0].angle);
+
+  st = Target[0].stars;
+  sr = Ref.stars;
+  
+  XMIN = -0.5*NFIELD*Target[0].header.Naxis[0];
+  XMAX = +0.5*NFIELD*Target[0].header.Naxis[0];
+  YMIN = -0.5*NFIELD*Target[0].header.Naxis[1];
+  YMAX = +0.5*NFIELD*Target[0].header.Naxis[1];
+
+  /* make two passes, with grids offset by 0.5 box for the second */
+  for (n = 0; n < 2; n++) {
+    gridinit (XMIN, XMAX, YMIN, YMAX, Ref.N, Target[0].N);
+    
+    if (PLOTSTUFF) plot_init_gridplot ();
+    /* fill in grid points */
+    for (i = 0; i < Target[0].N; i++) {
+      for (j = 0; j < Ref.N; j++) {
+	
+	dX = st[i].X - sr[j].X;
+	if (dX < XMIN) continue;
+	if (dX > XMAX) continue;
+	
+	dY = st[i].Y - sr[j].Y;
+	if (dY < YMIN) continue;
+	if (dY > YMAX) continue;
+	
+	gridbin (dX, dY);
+	if (PLOTSTUFF) plot_addpt_gridplot (dX, dY);
+      }
+    }
+
+    /* use sorted N list to define Nmin cut */
+    ALLOCATE (ntmp, double, Nbin);
+    bcopy (N, ntmp, Nbin*sizeof(double));
+    sort (ntmp, Nbin);
+    for (i = 0; (ntmp[i] == 0) && (i < Nbin); i++);
+    Nval = MIN (Nbin - 1, (int)(0.75*(Nbin - i)) + i);
+    Nmin = ntmp[Nval];
+    free (ntmp);
+    
+    /* select 'best' grid point - is this statistic good enough? */
+    Fmin = 1e10;
+    Imin = -1;
+    for (i = 0; i < Nbin; i++) {
+      
+      if (N[i] < Nmin) continue;
+      
+      /* s is the variance, f is varience overweighted by number */
+      s = fabs ((D2[i]/N[i]) - SQ(DX[i]/N[i]) - SQ(DY[i]/N[i]));
+      f = s / SQ(SQ(N[i]));
+      
+      if (f < Fmin) {
+	Smin = s;
+	Fmin = f;
+	Imin = i;
+      }
+    }
+    if (Imin == -1) { 
+      fprintf (stderr, "ERROR: odd min value\n");
+      exit (1);
+    }
+    
+    if ((n == 0) || (Fmin < answer[0].Chi)) {
+      Smin = fabs ((D2[Imin]/N[Imin]) - SQ(DX[Imin]/N[Imin]) - SQ(DY[Imin]/N[Imin]));
+      answer[0].Xoff = DX[Imin] / N[Imin];
+      answer[0].Yoff = DY[Imin] / N[Imin];
+      answer[0].dR   = sqrt (Smin);
+      answer[0].Chi  = Fmin;
+      answer[0].N    = N[Imin];
+    }
+    
+    fprintf (stderr, "angle: %6.1f, (%6.1f,%6.1f) - %6.2f : %10.8f for %d pairs\n", 
+	     answer[0].angle, answer[0].Xoff, answer[0].Yoff, answer[0].dR, answer[0].Chi, answer[0].N);
+
+    if (PLOTSTUFF) plot_gridpts (N, Nbin);
+    if (PLOTSTUFF) plot_done_gridplot (dX, dY);
+
+    XMIN -= 0.5*NPIX;
+    XMAX -= 0.5*NPIX;
+    YMIN -= 0.5*NPIX;
+    YMAX -= 0.5*NPIX;
+    gridfree ();
+  }
+
+  free (Ref.stars);
+
+}
+
+void gridinit (double XMIN, double XMAX, double YMIN, double YMAX, int Nr, int Nt) {
+
+  NX = (XMAX - XMIN) / NPIX;
+  NY = (YMAX - YMIN) / NPIX;
+
+  C1x =          NX / (XMAX - XMIN); 
+  C0x = - XMIN * NX / (XMAX - XMIN);
+
+  C1y =          NY / (YMAX - YMIN); 
+  C0y = - YMIN * NY / (YMAX - YMIN);
+
+  Nbin = NX*NY;
+
+  ALLOCATE (N, double, Nbin);
+  ALLOCATE (DX, double, Nbin);
+  ALLOCATE (DY, double, Nbin);
+  ALLOCATE (D2, double, Nbin);
+
+  bzero (N,  Nbin*sizeof(double));
+  bzero (DX, Nbin*sizeof(double));
+  bzero (DY, Nbin*sizeof(double));
+  bzero (D2, Nbin*sizeof(double));
+
+}
+
+int gridbin (double dX, double dY) {
+
+  int bin, xbin, ybin;
+
+  xbin = (int) (C0x + dX * C1x);
+  ybin = (int) (C0y + dY * C1y);
+
+  bin =  xbin + NX * ybin;
+
+  if (bin < 0)     return (0);
+  if (bin >= Nbin) return (0);
+
+  N[bin]   += 1.0;
+  DX[bin]  += dX;
+  DY[bin]  += dY;
+  D2[bin]  += dX*dX + dY*dY;
+  
+  return (bin);
+
+}
+  
+void gridfree () {
+
+  free (N);
+  free (DX);
+  free (DY);
+  free (D2);
+
+}
+
+# if (0) 
+  /* use sorted N list to define Nmin cut */
+  ALLOCATE (ntmp, double, Nbin);
+  bcopy (N, ntmp, Nbin*sizeof(double));
+  sort (ntmp, Nbin);
+  for (i = 0; (ntmp[i] == 0) && (i < Nbin); i++);
+  Nval = MIN (Nbin - 1, (int)(0.75*(Nbin - i)) + i);
+  Nmin = ntmp[Nval];
+  free (ntmp);
+
+  /* select 'best' grid point - is this statistic good enough? */
+  Fmin = 1e10;
+  Imin = -1;
+  for (i = 0; i < Nbin; i++) {
+
+    if (N[i] < Nmin) continue;
+
+    /* s is the variance, f is varience overweighted by number */
+    s = fabs ((D2[i]/N[i]) - SQ(DX[i]/N[i]) - SQ(DY[i]/N[i]));
+    f = s / SQ(SQ(N[i]));
+
+    if (f < Fmin) {
+      Smin = s;
+      Fmin = f;
+      Imin = i;
+    }
+  }
+  if (Imin == -1) { 
+    fprintf (stderr, "ERROR: odd min value\n");
+    exit (1);
+  }
+# endif
+
+# if (0)
+    /* find N sigma */
+    Ns = Ns2 = 0;
+    for (i = 0; i < Nbin; i++) {
+      Ns += N[i];
+      Ns2 += N[i]*N[i];
+    }
+    Ns = Ns / Nbin;
+    Ns2 = sqrt (Ns2 / Nbin - Ns*Ns);
+    fprintf (stderr, "N sigma: %f\n", Ns2);
+    
+    Imin = 0;
+    Fmin = N[0] / Ns2;
+    for (i = 0; i < Nbin; i++) {
+      f = N[i] / Ns2;
+      if (f > Fmin) {
+	Fmin = f;
+	Imin = i;
+      }
+    }
+# endif
Index: /tags/start/Ohana/src/gastro2/src/gstars2.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/gstars2.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/gstars2.c	(revision 12606)
@@ -0,0 +1,206 @@
+# include "gastro2.h"
+
+/* by necesity hard wired */
+# define D_NSTARS 1000
+# define BYTES_STAR 66
+# define BLOCK 1000
+
+void gstars (char *filename, CmpCatalog *Target) {
+
+  int i, N, Nstars, nstars, Ninstar;
+  int nbytes, Nbytes;
+  char line[80], *buffer;
+  double dmag, type, det;
+  int NX, NY, FoundAstrom;
+
+  FILE *f;
+  StarData *stars;
+
+  if (!fits_read_header (filename, &Target[0].header)) {
+    fprintf (stderr, "ERROR: can't load image header\n");
+    exit (1);
+  }
+  NX = Target[0].header.Naxis[0];
+  NY = Target[0].header.Naxis[1];
+
+  /* default values for coords */
+  strcpy (Target[0].coords.ctype, "RA---TAN");
+  Target[0].coords.pc1_1 = CCD_PC1_1; Target[0].coords.pc1_2 = CCD_PC1_2;
+  Target[0].coords.pc2_1 = CCD_PC2_1; Target[0].coords.pc2_2 = CCD_PC2_2;
+  Target[0].coords.cdelt1 = Target[0].coords.cdelt2 = ASEC_PIX / 3600.0;
+  Target[0].coords.Npolyterms = 0;
+  Target[0].coords.crpix1 = 0.5*NX;
+  Target[0].coords.crpix2 = 0.5*NY;
+  
+  /* attempt to get detailed astrometric information from header */
+  FoundAstrom = FALSE;
+  if (!strcasecmp (ROUGH_ASTROMETRY, "header")) {
+    if (!HEADER[0]) {
+      FoundAstrom = GetCoords (&Target[0].coords, &Target[0].header);
+    } else {
+      Header header;
+
+      if (!fits_read_header (HEADER, &header)) {
+	fprintf (stderr, "ERROR: can't load external header\n");
+	exit (1);
+      }
+      FoundAstrom = GetCoords (&Target[0].coords, &header);
+      fits_free_header (&header);
+    }
+    if (!FoundAstrom) {
+      fprintf (stderr, "header coordinates incomplete, trying for rough coordinates\n");
+      strcpy (ROUGH_ASTROMETRY, "config");
+    } else {
+      /* make optional adustments to header values (standard problems) */
+      if (FLIPX) {
+	Target[0].coords.pc1_1 *= -1;
+	Target[0].coords.crpix1 = NX - Target[0].coords.crpix1;
+      }
+      if (FLIPY) {
+	Target[0].coords.pc2_2 *= -1;
+	Target[0].coords.crpix2 = NY - Target[0].coords.crpix2;
+      }
+    }
+  }
+  
+  /*** abstract RA & DEC keywords, formats */
+  /* get just RA & DEC from header, other terms from config file */
+  if (!strcasecmp (ROUGH_ASTROMETRY, "config")) {
+    /* get RA & DEC from header */
+    FoundAstrom = TRUE;
+    FoundAstrom &= fits_scan (&Target[0].header, "RA", "%s", 1, line);
+    dms_to_ddd (&Target[0].coords.crval1, line);
+    Target[0].coords.crval1 = Target[0].coords.crval1 * 15.0;
+    FoundAstrom &= fits_scan (&Target[0].header, "DEC", "%s", 1, line);
+    dms_to_ddd (&Target[0].coords.crval2, line);
+  }
+
+  /* use RA & DEC from command line arguments */
+  if (FORCE) {
+    Target[0].coords.crval1 = F_RA;
+    Target[0].coords.crval2 = F_DEC;
+    if (VERBOSE) fprintf (stderr, " forcing coordinates to: %9.4f %9.4f\n", Target[0].coords.crval1, Target[0].coords.crval2);
+    FoundAstrom = TRUE;
+  }    
+
+  if (VERBOSE) fprintf (stderr, "using coordinates: %9.4f %9.4f\n", Target[0].coords.crval1, Target[0].coords.crval2);
+  if (!FoundAstrom) {
+    fprintf (stderr, "ERROR: can't get any valid coordinates, fix config file?\n");
+    exit (1);
+  }
+
+  /* at this point, we need to correct the crval1, crval2, and ROT_ZERO values
+     based on the pole axis angle and the ra, dec offsets */
+
+# define dcos(a) (cos((double)((a)*(RAD_DEG))))
+# define dsin(a) (sin((double)((a)*(RAD_DEG))))
+
+  if (POLAR_ALIGNMENT) {
+
+    double X, Y, PD, PR, DE, RE, T1, T2, T3;
+
+    X = Target[0].coords.crval1;
+    Y = Target[0].coords.crval2;
+    PD = POLE_DEC;   PR = POLE_RA;
+    DE = DEC_OFFSET; RE = RA_OFFSET;
+    
+    T1 = dcos(Y-DE) * dcos(X-RE) * dsin(PD) + dsin(Y-DE) * dcos(PD);
+    T2 = dcos(Y-DE) * dsin(X-RE);
+    T3 = dsin(Y-DE) * dsin(PD) - dcos(Y-DE) * dcos(X-RE) * dcos(PD);
+    
+    Target[0].coords.crval1 = (DEG_RAD * atan2 (T2, T1)) + PR;
+    Target[0].coords.crval2 = (DEG_RAD * asin (T3));
+    while (Target[0].coords.crval1 < 0) Target[0].coords.crval1 += 360.0;
+    while (Target[0].coords.crval1 > 360.0) Target[0].coords.crval1 -= 360.0;
+    
+    if (VERBOSE) fprintf (stderr, "  after polar alignment: %9.4f %9.4f\n", Target[0].coords.crval1, Target[0].coords.crval2);
+  }
+
+  /* get image area in deg^2 */
+  det = Target[0].coords.pc1_1 * Target[0].coords.pc2_2 - Target[0].coords.pc1_2 * Target[0].coords.pc2_1;
+  Target[0].Area = fabs (NX*NY*Target[0].coords.cdelt1*Target[0].coords.cdelt2*det);
+
+  /* allocate space for stars */
+  Nstars = -1;
+  fits_scan (&Target[0].header, "NSTARS", "%d", 1, &Nstars);
+  if (Nstars == -1) {
+    fprintf (stderr, "ERROR: failed to find NSTARS\n");
+    exit (1);
+  }
+  ALLOCATE (stars, StarData, MAX (Nstars, 1));
+  Nbytes = Nstars*BYTES_STAR;
+
+  /* open file for stars */
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open file to load stars\n");
+    exit (1);
+  }
+  fseek (f, Target[0].header.size, SEEK_SET); 
+
+  N = nstars = 0;
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR));
+  
+  while ((nbytes = fread (buffer, 1, (BLOCK*BYTES_STAR), f)) != 0) {
+    Ninstar = nbytes / BYTES_STAR;
+    for (i = 0; i < Ninstar; i++, nstars++) {
+      dparse (&stars[N].X, 1, &buffer[i*BYTES_STAR]);
+      dparse (&stars[N].Y, 2, &buffer[i*BYTES_STAR]);
+      dparse (&stars[N].M, 3, &buffer[i*BYTES_STAR]);
+      dparse (&dmag,       4, &buffer[i*BYTES_STAR]);
+      dparse (&type,       5, &buffer[i*BYTES_STAR]);
+
+      /* hardwired dophot exclusions should eventually be encapsulated elsewhere */
+      if ((type == 4) || (type == 6) || (type == 5) || (type == 9)) continue;
+      if (dmag > 100) continue;
+      stars[N].dM   = 0.001 * dmag;
+      stars[N].type = type;
+      N++;
+    }
+  }
+  free (buffer);
+  fclose (f);
+ 
+  if (nstars != Nstars) {
+    fprintf (stderr, "WARNING: only read %d of %d stars\n", nstars, Nstars);
+  }
+  if (N < 5) { 
+    fprintf (stderr, "ERROR: too few stars for reliable solution, only %d\n", N);
+    exit (1);
+  }
+
+  stars = remove_clumps (stars, &N, NX, NY);
+
+  sort_stars_mag (stars, N);  /* sorting by magnitude */
+  Target[0].stars = stars;
+  Target[0].N = N;
+
+  /* limit number of stars */
+  if (GASTRO_MAX_NSTARS && (GASTRO_MAX_NSTARS < Target[0].N)) {
+    Target[0].N = GASTRO_MAX_NSTARS;
+    REALLOCATE (Target[0].stars, StarData, Target[0].N);
+  }
+  if (VERBOSE) fprintf (stderr, "using %d stars from data file\n", Target[0].N);
+
+  /* calculate luminosity function of stars */
+  get_luminosity_func (stars, Target[0].N, &Target[0].lum);
+
+}
+
+/* 
+
+   load cmp file FITS header 
+
+   extract needed data from header:
+   - NX, NY?
+   - coords
+   
+   load stellar photometry
+
+   sort stars by mag
+
+   filter & limit numbers
+
+   find luminosity function slope, area?
+
+*/
Index: /tags/start/Ohana/src/gastro2/src/lumfunc.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/lumfunc.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/lumfunc.c	(revision 12606)
@@ -0,0 +1,110 @@
+# include "gastro2.h"
+
+/* mag range -5 - 35, dmag = 0.25, Nbin = 160 */
+# define MMIN -5
+# define MMAX 35
+# define dM 0.5
+# define NMBIN 90
+
+int get_luminosity_func (StarData *stars, int N, LumStats *lum) {
+
+  int i, j, Nb;
+  double mbin[NMBIN];
+  double bin[NMBIN], lbin[NMBIN], rbin[NMBIN];
+  double C0, C1;
+
+  lum[0].dNdM = lum[0].Mo = 0;
+
+  bzero (mbin, NMBIN * sizeof (double));
+
+  /* sum histogram */
+  for (i = 0; i < N; i++) {
+    if (stars[i].M < MMIN) continue;
+    if (stars[i].M > MMAX) continue;
+
+    j = (stars[i].M - MMIN) / dM;
+    j = MIN (MAX (j, 0), (NMBIN - 1));
+    mbin[j] ++;
+  }
+
+  /* select filled bins */
+  for (Nb = i = 0; i < NMBIN; i++) {
+    if (mbin[i] > 0) {
+      bin[Nb]  = i * dM + MMIN;
+      lbin[Nb] = log (mbin[i]) / log (10.0);
+      Nb++;
+    }
+  }
+
+  /* find max & min mag bins */
+  lum[0].Mmin = bin[0];
+  lum[0].Mmax = bin[Nb-1];
+
+  if (Nb < 4) { return (FALSE); }
+  fit_lum_bin (bin, lbin, Nb, &C0, &C1);
+  
+  /* find residuals */
+  for (i = 0; i < Nb; i++) {
+    rbin[i] = C0 + C1*bin[i] - lbin[i];
+  }
+
+  /* keep inner 80% */
+  sort_lum (rbin, bin, lbin, Nb);
+  for (j = 0, i = 0.1*Nb; i < 0.9*Nb; i++, j++) {
+    bin[j]  = bin[i];
+    lbin[j] = lbin[i];
+  }    
+  Nb = j;
+
+  if (Nb < 4) { return (FALSE); }
+  fit_lum_bin (bin, lbin, Nb, &C0, &C1);
+
+  lum[0].dNdM = C1;
+  lum[0].Mo   = C0;
+  
+  if (VERBOSE) fprintf (stderr, "lum stats: dNdM = %f, Mo = %f, Mmin = %f, Mmax = %f\n", 
+	   lum[0].dNdM, lum[0].Mo, lum[0].Mmin, lum[0].Mmax);
+
+  return (TRUE);
+
+}
+
+
+void fit_lum_bin (double *x, double *y, int N, double *C0, double *C1) {
+
+  int i;
+  double **c, **b;
+
+  ALLOCATE (c, double *, 2);
+  ALLOCATE (b, double *, 2);
+  ALLOCATE (c[0], double, 2);
+  ALLOCATE (c[1], double, 2);
+  ALLOCATE (b[0], double, 1);
+  ALLOCATE (b[1], double, 1);
+
+  /* fit x, y to line */
+  c[0][0] = 0; c[0][1] = 0;
+  c[1][0] = 0; c[1][1] = 0;
+  b[0][0] = 0; b[1][0] = 0;
+
+  for (i = 0; i < N; i++) {
+    c[0][0] += 1;
+    c[0][1] += x[i];
+    c[1][0] += x[i];
+    c[1][1] += x[i]*x[i];
+    
+    b[0][0] += y[i];
+    b[1][0] += y[i]*x[i];
+  }
+  gaussj (c, 2, b, 1);
+  *C0 = b[0][0];
+  *C1 = b[1][0];
+
+  free (b[0]);
+  free (b[1]);
+  free (c[0]);
+  free (c[1]);
+  free (c);
+  free (b);
+
+}
Index: /tags/start/Ohana/src/gastro2/src/misc.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/misc.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/misc.c	(revision 12606)
@@ -0,0 +1,140 @@
+# include "gastro2.h"
+
+# define SIGN(X)  (((X) == 0) ? 0 : ((fabs((double)(X))) / (X)))
+
+void hh_hms (double hh, int *hr, int *mn, double *sc) {
+
+  int flag;
+
+  flag = SIGN(hh);
+  hh *= flag;
+  hh = 24.0*(hh/24.0 - (int)(hh/24.0));
+  *sc = 60.0*(60.0*hh - (int)(60.0*hh));
+  *mn = 60.0*(hh - (int)hh);
+  *hr = (int) hh;
+  *hr *= flag;
+
+}
+ 
+void hms_format (char *line, double value) {
+
+  int hr, mn;
+  double sc;
+
+  hh_hms (value, &hr, &mn, &sc);
+  hr = (int) value;
+  if (isnan (value))
+    sprintf (line, "xx:xx:xx.xx");
+  else {
+    if (value < 0) {
+      sprintf (line, "-%02d:%02d:%05.2f", abs(hr), mn, sc);
+    } else {
+      sprintf (line, "%02d:%02d:%05.2f", hr, mn, sc);
+    }
+  }      
+}
+
+/***** convert [-]00:00:00 to 0.0000 ****/
+int dms_to_ddd (double *Value, char *string) {
+  
+  int valid, neg, status;
+  double tmp, value;
+  char *p1, *p2, *px;
+
+  valid = FALSE; 
+  neg = FALSE;
+  stripwhite (string);
+  p1 = string;
+  px = string + strlen(string);
+
+  if (string[0] == '-') { 
+    valid = TRUE; 
+    neg = TRUE;
+    p1 = &string[1];
+  }
+  if (string[0] == '+') { 
+    valid = TRUE; 
+    neg = FALSE;
+    p1 = &string[1];
+  }
+  if (isdigit(string[0])) { 
+    valid = TRUE;
+    p1 = &string[0];
+  }
+  if (!valid) { return (FALSE); }
+
+  status = 1;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) return (FALSE); /* entry not a number: +fred */
+  value = tmp;
+  if (p2 == px) goto escape;    /* entry only number: +1.0 */ 
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:fred */
+  status = 2;
+  value += tmp / 60.0;
+  if (p2 == px) goto escape;    /* entry only number: +1:1 */
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:1:fred */
+  value += tmp / 3600.0;
+
+ escape:
+  if (neg) {
+    value *= -1;
+  }
+  *Value = value;
+
+  return (status);
+}
+
+/**********/
+int str_to_radec (double *ra, double *dec, char *str1, char *str2) {
+
+  double Ra, Dec;
+
+  *ra = *dec = 0;
+  switch (dms_to_ddd (&Ra, str1)) {
+  case 0:
+    fprintf (stderr, "syntax error in RA\n");
+    return (FALSE);
+  case 1:
+    break;
+  case 2:
+    Ra = Ra * 15;
+    break;
+  }
+  switch (dms_to_ddd (&Dec, str2)) {
+  case 0:
+    fprintf (stderr, "syntax error in DEC\n");
+    return (FALSE);
+  case 1:
+  case 2:
+    break;
+  }
+  *ra = Ra;
+  *dec = Dec;
+  return (TRUE);
+}
+
+void area_of_region (CatStats *region) {
+  
+  double area;
+
+  area = DEG_RAD*(region[0].RA[1] - region[0].RA[0])*(sin(region[0].DEC[1]*RAD_DEG) - sin(region[0].DEC[0]*RAD_DEG));
+  region[0].Area = area;
+}
+
+void dump_coords (CmpCatalog *Target) {
+  if (VERBOSE) {
+    fprintf (stderr, "%s\n", Target[0].coords.ctype);
+    fprintf (stderr, "%f %f\n", Target[0].coords.crval1, Target[0].coords.crval2);
+    fprintf (stderr, "%f %f\n", Target[0].coords.crpix1, Target[0].coords.crpix2);
+    fprintf (stderr, "%f %f\n", Target[0].coords.pc1_1,  Target[0].coords.pc1_2);
+    fprintf (stderr, "%f %f\n", Target[0].coords.pc2_1,  Target[0].coords.pc2_2);
+    fprintf (stderr, "%f %f\n", Target[0].coords.cdelt1, Target[0].coords.cdelt2);
+    fprintf (stderr, "\n");
+  }
+}
Index: /tags/start/Ohana/src/gastro2/src/plots.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/plots.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/plots.c	(revision 12606)
@@ -0,0 +1,360 @@
+# include "gastro2.h"
+
+int Nv, NV;
+float *xv, *yv;
+Graphdata gv;
+
+void plot_init_gridplot () {
+  
+  NV = 1000;
+  Nv = 0;
+
+  ALLOCATE (xv, float, NV);
+  ALLOCATE (yv, float, NV);
+
+  PlotReset (2);
+
+  gv.xmin = -400;
+  gv.xmax = +400;
+  gv.ymin = -400;
+  gv.ymax = +400;
+
+  gv.style = 2;
+  gv.ltype = 0;
+  gv.etype = 0;
+  gv.ebar  = 0;
+  gv.size = 0.3;
+  gv.lweight = 0;
+  gv.color = 0;
+  gv.ptype = 2;
+
+}
+
+int plot_addpt_gridplot (double x, double y) {
+
+  if (x < gv.xmin) return (0);
+  if (x > gv.xmax) return (0);
+  if (y < gv.ymin) return (0);
+  if (y > gv.ymax) return (0);
+
+  xv[Nv] = x;
+  yv[Nv] = y;
+  Nv ++;
+  
+  if (Nv == NV) {
+    NV += 1000;
+    REALLOCATE (xv, float, NV);
+    REALLOCATE (yv, float, NV);
+  }
+  return (1);
+}
+
+void plot_done_gridplot () {
+
+  char c;
+
+  /* send to Kapa */
+  PrepPlotting (Nv, &gv, 2);
+  PlotVector (Nv, xv, 0, 2);
+  PlotVector (Nv, yv, 1, 2);
+
+  DonePlotting (&gv, 2);
+  fprintf (stderr, "type return to continue");
+  fscanf (stdin, "%c", &c);
+  free (xv);
+  free (yv);
+}
+  
+static double Xm[2];
+static int Xg[2] = {0, 2};
+
+void plot_resid_init (int version, double xmax) {
+
+  if (version > 1) return;
+  if (version < 0) return;
+  
+  Xm[version] = xmax;
+}
+
+
+void plot_resid_plot (int version, float *xvect, float *yvect, int Nvect) {
+ 
+  int i;
+  char c;
+  float xmin, xmax, ymin, ymax;
+  Graphdata graphdata;
+  
+  xmin = xmax = xvect[0];
+  ymin = ymax = yvect[0];
+  for (i = 0; i < Nvect; i++) {
+    xmax = MAX (xvect[i], xmax);
+    xmin = MIN (xvect[i], xmin);
+    ymax = MAX (yvect[i], ymax);
+    ymin = MIN (yvect[i], ymin);
+  }
+    
+  PlotReset (Xg[version]);
+
+  graphdata.xmin = MIN (xmin,   0);
+  graphdata.xmax = MAX (xmax, Xm[version]);
+  graphdata.ymin = MIN (ymin, -10);
+  graphdata.ymax = MAX (ymax, +10);
+
+  graphdata.style = 2;
+  graphdata.ltype = 0;
+  graphdata.etype = 0;
+  graphdata.ebar  = 0;
+  graphdata.size = 0.5;
+  graphdata.lweight = 0;
+  graphdata.color = 0;
+  graphdata.ptype = 2;
+
+  /* send to Kapa */
+  PrepPlotting (Nvect, &graphdata, Xg[version]);
+  PlotVector (Nvect, xvect, 0, Xg[version]);
+  PlotVector (Nvect, yvect, 1, Xg[version]);
+
+  DonePlotting (&graphdata, Xg[version]);
+  fprintf (stderr, "type return to continue");
+  fscanf (stdin, "%c", &c);
+}
+
+void plot_gridpts (double *pts, int Npts) {
+
+  char c;
+  int i;
+  float *xvect, *yvect, ymax;
+  Graphdata graphdata;
+  
+  ymax = 0;
+  ALLOCATE (xvect, float, Npts);
+  ALLOCATE (yvect, float, Npts);
+  for (i = 0; i < Npts; i++) {
+    xvect[i] = i;
+    yvect[i] = pts[i];
+    ymax = MAX (yvect[i], ymax);
+  }
+    
+  PlotReset (0);
+
+  graphdata.xmin = -10;
+  graphdata.xmax = Npts + 10;
+  graphdata.ymin = -1;
+  graphdata.ymax = ymax + 1;
+
+  graphdata.style = 1;
+  graphdata.ltype = 0;
+  graphdata.etype = 0;
+  graphdata.ebar  = 0;
+  graphdata.size = 0.5;
+  graphdata.lweight = 0;
+  graphdata.color = 0;
+  graphdata.ptype = 0;
+
+  /* send to Kapa */
+  PrepPlotting (Npts, &graphdata, 0);
+  PlotVector (Npts, xvect, 0, 0);
+  PlotVector (Npts, yvect, 1, 0);
+  free (xvect);
+  free (yvect);
+
+  DonePlotting (&graphdata, 0);
+  fprintf (stderr, "type return to continue");
+  fscanf (stdin, "%c", &c);
+}
+
+static Graphdata gf;
+
+void plot_fullfield (CmpCatalog *Target, RefCatalog *Ref) {
+
+  int i, Nvect;
+  float *xvect, *yvect, *zvect, M, dM;
+  char c;
+  
+  dM = Target[0].lum.Mmax - Target[0].lum.Mmin;
+
+  PlotReset (1);
+
+  gf.xmin = -100;
+  gf.xmax = Target[0].header.Naxis[0] + 100;
+  gf.ymin = -100;
+  gf.ymax = Target[0].header.Naxis[1] + 100;
+
+  gf.style = 2;
+  gf.ltype = 0;
+  gf.etype = 0;
+  gf.ebar  = 0;
+  gf.size = -1;
+  gf.lweight = 0;
+
+  /* fill in vectors */
+  Nvect = Target[0].N;
+  ALLOCATE (xvect, float, Nvect);
+  ALLOCATE (yvect, float, Nvect);
+  ALLOCATE (zvect, float, Nvect);
+  for (i = 0; i < Nvect; i++) {
+    xvect[i] = Target[0].stars[i].X;
+    yvect[i] = Target[0].stars[i].Y;
+    M = (Target[0].lum.Mmax - Target[0].stars[i].M) / dM;
+    zvect[i] = MIN (1.0, MAX (0.01, M));
+  }
+
+  /* send to Kapa */
+  gf.ptype = 1;
+  gf.color = 0;
+  PrepPlotting (Nvect, &gf, 1);
+  PlotVector (Nvect, xvect, 0, 1);
+  PlotVector (Nvect, yvect, 1, 1);
+  PlotVector (Nvect, zvect, 1, 1);
+  free (xvect);
+  free (yvect);
+  free (zvect);
+
+  /* fill in vectors */
+  Nvect = Ref[0].N;
+  ALLOCATE (xvect, float, Nvect);
+  ALLOCATE (yvect, float, Nvect);
+  ALLOCATE (zvect, float, Nvect);
+  for (i = 0; i < Nvect; i++) {
+    xvect[i] = Ref[0].stars[i].X;
+    yvect[i] = Ref[0].stars[i].Y;
+    M = (Target[0].lum.Mmax - Ref[0].stars[i].M) / dM;
+    zvect[i] = MIN (1.0, MAX (0.01, M));
+  }
+
+  /* send to Kapa */
+  gf.color = 2;
+  gf.ptype = 2;
+  PrepPlotting (Nvect, &gf, 1);
+  PlotVector (Nvect, xvect, 0, 1);
+  PlotVector (Nvect, yvect, 1, 1);
+  PlotVector (Nvect, zvect, 2, 1);
+  free (xvect);
+  free (yvect);
+  free (zvect);
+
+  DonePlotting (&gf, 1);
+  fprintf (stderr, "type return to continue");
+  fscanf (stdin, "%c", &c);
+}
+
+void plot_fullfield_pairs (float *x, float *y, int n) {
+
+  char c;
+
+  /* send to Kapa */
+  gf.color = 6;
+  gf.ptype = 100;
+  gf.size =  1.0;
+  
+  PrepPlotting (n, &gf, 1);
+  PlotVector (n, x, 0, 1);
+  PlotVector (n, y, 1, 1);
+  fprintf (stderr, "type return to continue");
+  fscanf (stdin, "%c", &c);
+}  
+
+/* mag range -5 - 35, dmag = 0.25, Nbin = 160 */
+# define MMIN -5
+# define MMAX 35
+# define dM 0.5
+# define NMBIN 90
+
+void plot_lumfunc (CmpCatalog *Target, RefCatalog *Ref) {
+
+  int i, Nr, Nt;
+  float tbin[NMBIN], tval[NMBIN], rbin[NMBIN], rval[NMBIN];
+  double ymin, ymax;
+  char c;
+  Graphdata graphdata;
+
+  fill_lumfunc (Target[0].stars, Target[0].N, tval, tbin, &Nt);
+  fill_lumfunc (Ref[0].stars, Ref[0].N, rval, rbin, &Nr);
+
+  ymin = 5; ymax = -5;
+  for (i = 0; i < Nt; i++) {
+    tval[i] = tval[i] - log (Target[0].Area) / log (10.0);
+    ymin = MIN (tval[i], ymin);
+    ymax = MAX (tval[i], ymax);
+  }
+
+  for (i = 0; i < Nr; i++) {
+    rval[i] = rval[i] - log (Ref[0].Area) / log (10.0);
+    rbin[i] = rbin[i] + Ref[0].Moff;
+    ymin = MIN (rval[i], ymin);
+    ymax = MAX (rval[i], ymax);
+  }
+
+  graphdata.xmin = MMIN;
+  graphdata.xmax = MMAX;
+  graphdata.ymin = ymin - 0.1;
+  graphdata.ymax = ymax + 0.1;
+
+  graphdata.style = 1;
+  graphdata.ptype = 2;
+  graphdata.ltype = 0;
+  graphdata.etype = 0;
+  graphdata.ebar  = 0;
+  graphdata.color = 0;
+
+  graphdata.lweight = 0;
+  graphdata.size = 0.5;
+
+  PlotReset (0);
+
+  PrepPlotting (Nt, &graphdata, 0);
+  PlotVector (Nt, tbin, 0, 0);
+  PlotVector (Nt, tval, 1, 0);
+
+  graphdata.color = 2;
+  graphdata.style = 1;
+  graphdata.lweight = 0;
+  PrepPlotting (Nr, &graphdata, 0);
+  PlotVector (Nr, rbin, 0, 0);
+  PlotVector (Nr, rval, 1, 0);
+
+  /* plot truncated lum func */
+  for (i = 0; i < Nr; i++) {
+    if (rbin[i] < Target[0].lum.Mmin - 0.5) rval[i] = -1;
+    if (rbin[i] > Target[0].lum.Mmax + 0.5) rval[i] = -1;
+  }
+  graphdata.ltype = 1;
+  PrepPlotting (Nr, &graphdata, 0);
+  PlotVector (Nr, rbin, 0, 0);
+  PlotVector (Nr, rval, 1, 0);
+
+  DonePlotting (&graphdata, 0);
+  fprintf (stderr, "type return to continue");
+  fscanf (stdin, "%c", &c);
+
+}
+
+void fill_lumfunc (StarData *stars, int N, float *lbin, float *bin, int *nb) {
+
+  int i, j, Nb;
+  double mbin[NMBIN];
+
+  bzero (mbin, NMBIN * sizeof (double));
+
+  /* sum histogram */
+  for (i = 0; i < N; i++) {
+    if (stars[i].M < MMIN) continue;
+    if (stars[i].M > MMAX) continue;
+
+    j = (stars[i].M - MMIN) / dM;
+    j = MIN (MAX (j, 0), (NMBIN - 1));
+    mbin[j] ++;
+  }
+
+  /* select filled bins */
+  for (Nb = i = 0; i < NMBIN; i++) {
+    if (mbin[i] > 0) {
+      bin[Nb]  = i * dM + MMIN;
+      lbin[Nb] = log (mbin[i]) / log (10.0);
+      Nb++;
+    }
+  }
+
+  *nb = Nb;
+}
+
Index: /tags/start/Ohana/src/gastro2/src/plotstuff.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/plotstuff.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/plotstuff.c	(revision 12606)
@@ -0,0 +1,166 @@
+# include "gastro2.h"
+# include <signal.h>
+
+static int Xgraph[5] = {0,0,0,0,0};
+static int active;
+
+void XDead () {
+  signal (SIGPIPE, XDead);
+  fprintf (stderr, "kapa is dead, must restart\n");
+  Xgraph[active] = -1;
+}
+
+int open_graph (int N) {
+
+# ifdef ANSI
+#   define F_SETFL      4   
+#   define O_NONBLOCK 0200000  
+#   define       AF_UNIX         1          
+#   define       SOCK_STREAM     1          
+#define ENOENT          2       /* No such file or directory    */
+# endif /* ANSI */
+
+  int InitSocket, status, addreslen;
+  struct sockaddr_un Address;
+  char temp[100];
+  char socket_name[100];
+  
+  active = N;
+  sprintf (socket_name, "/tmp/kapa%d", N);
+  sprintf (temp, "rm -f %s", socket_name);
+  system (temp);
+    
+  strcpy (Address.sun_path, socket_name); 
+  Address.sun_family = AF_UNIX; 
+  InitSocket = socket (AF_UNIX, SOCK_STREAM, 0); 
+  status = bind (InitSocket, (struct sockaddr *) &Address, sizeof (Address));
+  status = listen (InitSocket, 1);
+  
+  sprintf (temp, "kapa %s &", socket_name);
+# ifndef DEBUG
+  system (temp);
+# else  
+  fprintf (stderr, "start kapa, press return: %s\n", temp);
+  fscanf (stdin, "%d", &i);
+# endif
+  
+  addreslen =  sizeof (Address);
+  Xgraph[N] = accept (InitSocket, (struct sockaddr *) &Address, &addreslen);
+  if (Xgraph[N] < 0) {
+    fprintf (stderr, "error starting kapa\n");
+    return (FALSE);
+  }
+  else {
+    return (TRUE);
+  }
+  
+}
+
+void DonePlotting (Graphdata *graphmode, int N) {
+  char buffer[65], buffer2[65];
+
+  write (Xgraph[N], "DBOX", 4);
+  sprintf (buffer, "%f %f %f %f", graphmode[0].xmin, graphmode[0].xmax, graphmode[0].ymin, graphmode[0].ymax);
+  sprintf (buffer2, "NBYTES: %6d", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+
+  sprintf (buffer, "%s %s %s", "2222", "2222", "2222");
+  sprintf (buffer2, "NBYTES: %6d", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+}
+
+void PrepPlotting (int Npts, Graphdata *graphmode, int N) {
+
+  int i, status;
+  char buffer[128], buffer2[128];
+
+  active = N;
+  if (Npts < 1) return;
+
+  /* test Xgraph[N], flush junk from pipe */
+  signal (SIGPIPE, XDead);
+  fcntl (Xgraph[N], F_SETFL,  O_NONBLOCK); 
+  for (i = 0; (read (Xgraph[N], buffer, 64) > 0) && (i < 20); i++);
+  fcntl (Xgraph[N], F_SETFL, !O_NONBLOCK); 
+  
+  if (Xgraph[N] < 1) if (!open_graph(N)) return;
+  
+  /* tell kapa to look for the incoming image */
+  status = write (Xgraph[N], "PLOT", 4); 
+
+  /* send Xgraph[N] the plot details */
+  sprintf (buffer, "%8d %8d %d %d %d %d %d %f %f", 
+	   Npts, graphmode[0].style, 
+	   graphmode[0].ptype, graphmode[0].ltype, 
+	   graphmode[0].etype, graphmode[0].ebar, graphmode[0].color, 
+	   graphmode[0].lweight, graphmode[0].size);
+  sprintf (buffer2, "NBYTES: %6d", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+  
+  sprintf (buffer, "%f %f %f %f", 
+	   graphmode[0].xmin, graphmode[0].xmax, 
+	   graphmode[0].ymin, graphmode[0].ymax);
+  sprintf (buffer2, "NBYTES: %6d", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+
+}
+
+void PlotVector (int Npts, float *vect, int mode, int N) {
+
+  int Nbytes;
+
+  if (Npts < 1) return;
+
+  active = N;
+  Nbytes = Npts * sizeof (float);
+  write (Xgraph[N], vect, Nbytes);
+
+}
+
+void PlotReset (int N) {
+
+  char buffer[128];
+  int i;
+
+  /* test Xgraph[N], flush junk from pipe */
+  signal (SIGPIPE, XDead);
+  fcntl (Xgraph[N], F_SETFL,  O_NONBLOCK); 
+  for (i = 0; (read (Xgraph[N], buffer, 64) > 0) && (i < 20); i++);
+  fcntl (Xgraph[N], F_SETFL, !O_NONBLOCK); 
+  
+  if (Xgraph[N] < 1) if (!open_graph(N)) return;
+  
+  write (Xgraph[N], "ERAS", 4);
+
+}
+/* include these lines to plot a pair of vectors: 
+
+   typedef struct {
+   double xmin, xmax, ymin, ymax;
+   int style, ptype, ltype, etype, color;
+   double lweight, size;
+   } Graphdata;
+   Graphdata graphdata;
+   
+   graphdata.xmin = -200;
+   graphdata.xmax = 4200;
+   graphdata.ymin = -500;
+   graphdata.ymax = 500;
+   graphdata.style = 2;
+   graphdata.ptype = 2;
+   graphdata.ltype = 0;
+   graphdata.etype = 0;
+   graphdata.color = 0;
+   graphdata.lweight = 0;
+   graphdata.size = 0.5;
+   
+   PrepPlotting (N, &graphdata, n);
+   PlotVector (N, Y, 0, n);
+   PlotVector (N, dM, 1, n);
+   DonePlotting (&graphdata, n);
+   
+ */
Index: /tags/start/Ohana/src/gastro2/src/remove_clumps.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/remove_clumps.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/remove_clumps.c	(revision 12606)
@@ -0,0 +1,94 @@
+# include "gastro2.h"
+
+StarData *remove_clumps (StarData *instars, int *nstars, int NX, int NY) {
+
+  int i, j, nx, ny, Npix, nn, x, y, pix, Nstars;
+  double s1, s2, mean, sigma, cutoff;
+  int *hist, *xcld;
+  int nxcld, Nxcld, Nout;
+  
+  StarData *outstars;
+
+  /* create histogram of pixels using coords */
+
+  Nstars = *nstars;
+
+  Npix = 100;
+  nx = (int) (NX / Npix) + 1;
+  ny = (int) (NY / Npix) + 1;
+  nn = nx * ny;
+
+  ALLOCATE (hist, int, nn);
+  ALLOCATE (xcld, int, nn);
+  bzero (hist, nn*sizeof(int));
+
+  for (i = 0; i < Nstars; i++) {
+    
+    x = (int) (instars[i].X / Npix);
+    y = (int) (instars[i].Y / Npix);
+    pix = x + nx * y;
+
+    if ((pix < 0) || (pix >= nn)) { 
+      fprintf (stderr, "! %f %f  %d %d  %d %d\n", instars[i].X, instars[i].Y, x, y, pix, nn);
+      continue;
+    }
+    
+    hist[pix] ++;
+
+  }
+
+  /* find stats on histogram */
+  s1 = s2 = 0;
+  for (i = 0; i < nn; i++) {
+    s1 += hist[i];
+    s2 += hist[i]*hist[i];
+  }
+  mean  = s1 / nn;
+  sigma = 2 + sqrt (s2 / nn - mean*mean);
+  cutoff = mean + 5*sigma;
+
+  /* identify clumps to exclude */
+  Nxcld = 0;
+  for (i = 0; i < nn; i++) {
+    if (hist[i] > cutoff) {
+      y = (int) (i / nx);
+      x = i - y*nx;
+      fprintf (stderr, "cut: %d  %d %d  %d\n", i, x, y, hist[i]);
+      xcld[Nxcld] = i;
+      Nxcld ++;
+    }
+  }
+
+  /* identify stars to exclude (type = -1) */
+  for (i = 0; i < Nxcld; i++) {
+
+    nxcld = 0;
+    for (j = 0; j < Nstars; j++) {
+      
+      x = (int) (instars[j].X / Npix);
+      y = (int) (instars[j].Y / Npix);
+      pix = x + nx * y;
+      if (pix != xcld[i]) continue;
+      nxcld ++;      
+      instars[j].type = -1;
+    }
+    fprintf (stderr, "exclude %d in clump %d\n", nxcld, i);
+  }
+
+  ALLOCATE (outstars, StarData, Nstars);
+  Nout = 0;
+
+  for (i = 0; i < Nstars; i++) {
+    if (instars[i].type == -1) continue;
+    outstars[Nout] = instars[i];
+    Nout ++;
+  } 
+
+  REALLOCATE (outstars, StarData, Nout);
+  *nstars = Nout;
+  fprintf (stderr, "keeping %d of %d stars\n", Nout, Nstars);
+  return (outstars);
+
+}
+  
+     
Index: /tags/start/Ohana/src/gastro2/src/rotate2.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/rotate2.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/rotate2.c	(revision 12606)
@@ -0,0 +1,37 @@
+# include "gastro2.h"
+
+void rotate (RefCatalog *Subset, RefCatalog *Ref, double angle) {
+  
+  int i;
+  double dX, dY, DX, DY, CS, SN;
+  double theta;
+  StarData *in, *out;
+
+  Ref[0] = Subset[0];
+
+  ALLOCATE (Ref[0].stars, StarData, MAX (1, Ref[0].N));
+  bcopy (Subset[0].stars, Ref[0].stars, Ref[0].N*sizeof(StarData));
+
+  if (angle == 0.0) return;
+
+  theta = (angle*RAD_DEG);
+  CS = cos (theta);
+  SN = sin (theta);
+
+  in  = Subset[0].stars;
+  out = Ref[0].stars;
+
+  for (i = 0; i < Ref[0].N; i++) {
+    dX = in[i].X;
+    dY = in[i].Y;
+    
+    DX = dX * CS - dY * SN;
+    DY = dX * SN + dY * CS;
+    
+    out[i].X = DX;
+    out[i].Y = DY;
+  }
+    
+}
+
+/* rotate the star list by an angle ccw from x axis */
Index: /tags/start/Ohana/src/gastro2/src/sort.c
===================================================================
--- /tags/start/Ohana/src/gastro2/src/sort.c	(revision 12606)
+++ /tags/start/Ohana/src/gastro2/src/sort.c	(revision 12606)
@@ -0,0 +1,195 @@
+# include "gastro2.h"
+
+void sort_lum (double *R, double *X, double *Y, int N) {
+
+  int l,j,ir,i;
+  double tX, tY, tR;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tR = R[l];
+    }
+    else {
+      tX    = X[ir];
+      X[ir] = X[0];
+      tY    = Y[ir];
+      Y[ir] = Y[0];
+      tR    = R[ir];
+      R[ir] = R[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	R[0] = tR;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && R[j] < R[j+1]) j++;
+      if (tR < R[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	R[i] = R[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    R[i] = tR;
+  }
+}
+
+void sort_lists (double *X, double *Y, int *S, int N) {
+
+  int l,j,ir,i;
+  double tX, tY, tS;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    S[i] = tS;
+  }
+}
+
+void sort (double *X, int N) {
+
+  int l,j,ir,i;
+  double tmp;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tmp = X[l];
+    }
+    else {
+      tmp = X[ir];
+      X[ir] = X[0];
+      if (--ir == 0) {
+	X[0] = tmp;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tmp < X[j]) {
+	X[i] = X[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tmp;
+  }
+}
+
+void sort_stars_mag (StarData *stars, int N) {
+
+  int l,j,ir,i;
+  StarData tempstar;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      tempstar = stars[--l];
+    }
+    else {
+      tempstar = stars[ir];
+      stars[ir] = stars[0];
+      if (--ir == 0) {
+	stars[0] = tempstar;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && stars[j].M < stars[j+1].M) ++j;
+      if (tempstar.M < stars[j].M) {
+	stars[i] = stars[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    stars[i] = tempstar;
+  }
+}
+
+void sort_stars_X (StarData *stars, int N) {
+
+  int l,j,ir,i;
+  StarData tempstar;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      tempstar = stars[--l];
+    }
+    else {
+      tempstar = stars[ir];
+      stars[ir] = stars[0];
+      if (--ir == 0) {
+	stars[0] = tempstar;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && stars[j].X < stars[j+1].X) ++j;
+      if (tempstar.X < stars[j].X) {
+	stars[i] = stars[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    stars[i] = tempstar;
+  }
+}
+
+
Index: /tags/start/Ohana/src/gcompare/Makefile
===================================================================
--- /tags/start/Ohana/src/gcompare/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/gcompare/Makefile	(revision 12606)
@@ -0,0 +1,68 @@
+include ../../Configure
+HOME 	=	$(ROOT)/src/gcompare
+default: all
+
+BIN	=	$(HOME)/bin
+MAN	=	$(HOME)/doc
+SRC	=	$(HOME)/src
+INC	=	$(HOME)/include
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lFITS -lohana -lm 
+CFLAGS	=	$(INCS) 
+CCFLAGS	=	$(INCS) $(LIBS) 
+LFLAGS	=	$(LIBS)
+
+INSTALL = gcompare
+
+OBJ 	= \
+$(SRC)/input.$(ARCH).o 				$(SRC)/output.$(ARCH).o    		\
+$(SRC)/compare.$(ARCH).o 			$(SRC)/sort.$(ARCH).o      		\
+$(SRC)/count_neighbors.$(ARCH).o                $(SRC)/nextline.$(ARCH).o		\
+$(SRC)/nextword.$(ARCH).o
+
+all: gcompare
+
+# dependancy rules for binary code ##########################
+.PRECIOUS: %.$(ARCH).o
+.PRECIOUS: $(BIN)/%.$(ARCH)
+.PRECIOUS: $(SRC)/%.$(ARCH).o
+
+%.$(ARCH).o : %.c
+	$(CC) $(CFLAGS) -c $^ -o $@
+
+$(BIN)/%.$(ARCH) : $(SRC)/%.$(ARCH).o $(OBJ)
+	$(CC) $^ -o $@ $(LFLAGS)
+
+$(DESTBIN)/%: $(BIN)/%.$(ARCH)
+	mkdir -p $(DESTBIN)
+	rm -f $(DESTBIN)/$*
+	cp $(BIN)/$*.$(ARCH) $(DESTBIN)/$*
+
+%.install:
+	make $(DESTBIN)/$*
+
+$(INSTALL): % : $(BIN)/%.$(ARCH)
+
+# utilities #################################################
+clean:
+	rm -f *~ 
+	rm -f #* 
+	rm -f */*~ 
+	rm -f */#* 
+	rm -f */*.o
+	rm -f $(BIN)/gcompare.$(ARCH)
+
+dist: clean
+	rm -f $(BIN)/gcompare
+
+install:
+	for i in $(INSTALL); do make $$i.install; done
+	mkdir -p $(DESTMAN)
+	rm -f $(DESTMAN)/gcompare.1
+	cp $(MAN)/gcompare.1 $(DESTMAN)/
+
Index: /tags/start/Ohana/src/gcompare/doc/gcompare.1
===================================================================
--- /tags/start/Ohana/src/gcompare/doc/gcompare.1	(revision 12606)
+++ /tags/start/Ohana/src/gcompare/doc/gcompare.1	(revision 12606)
@@ -0,0 +1,52 @@
+.ad l
+.nh
+.TH gcompare 1.0 "Sept 18, 1992" "Version 1.0"
+.SH NAME
+\fIgcompare:\fP  2-D intercomparison between 2 files
+
+.SH SYNOPSIS
+.B gcompare [-d -m -n1 -n2 -s1 N -s2 N -c X Y] file1 X1 Y1 file2 X2 Y2 radius
+
+.SH DESCRIPTION
+\fIgcompare\fP takes two files and compares the entries with one with
+the entries in the second.  Two columns (X and Y) which contain the
+coordinates are given.  Lines in the second file with coordinates
+within the given radius of the first file are selected.  Depending on
+the optional flags, any of the following are printed:  
+1) the coordinate difference for these matched lines,
+2) both matched lines (concatenated into a single line)
+3) \fIunmatched\fP lines from file 1 
+4) \fIunmatched\fP lines from file 2 
+
+.SS OPTIONS
+.TP
+.I "-d"
+Include in the output the coordinate differences for the two files
+.TP
+.I "-m"
+Include in the output the matched lines from the two files
+.TP
+.I "-n1"
+Include in the output the unmatched lines from file 1
+.TP
+.I "-n2"
+Include in the output the unmatched lines from file 2
+.TP
+.I "-s1 N"
+skip the first N lines of file 1
+.TP
+.I "-s2 N"
+skip the first N lines of file 2
+.TP
+.I "-c X Y"
+offset the coordinates of file 2 by (X,Y)
+.TP
+.I "-h, -help"
+print a short help summary
+
+
+.SH COPYRIGHT
+Copyright 1993 Eugene Magnier
+.PP                                                
+.SH AUTHOR
+Eugene Magnier.  MIT - CSR, UvA
Index: /tags/start/Ohana/src/gcompare/include/gcompare.h
===================================================================
--- /tags/start/Ohana/src/gcompare/include/gcompare.h	(revision 12606)
+++ /tags/start/Ohana/src/gcompare/include/gcompare.h	(revision 12606)
@@ -0,0 +1,38 @@
+# include <math.h>
+# include <ohana.h>
+
+typedef struct {
+  double  X, Y;
+  char   *line;
+  int     match;
+} value_type;
+
+typedef struct {
+  value_type *values;
+  char       *buffer;
+  int        Nvalues;
+} data_type;
+
+
+typedef struct {
+  char *line1;
+  char *line2;
+  double dX, dY;
+} match_type;
+
+/******* PROTOTYPES ***********/
+
+void               help              PROTO(());
+data_type          input             PROTO((char *, int, int, int));
+match_type        *compare           PROTO((data_type, data_type, int *, double, double, double, double));
+int                get_argument      PROTO((int, char **, char *));
+int                remove_argument   PROTO((int, int *, char **));
+void               sort              PROTO((data_type));
+void               output            PROTO((data_type, data_type, match_type *, int, int, int, int, int));
+char              *nextword          PROTO((char *));
+int                parse             PROTO((double *, int, char *));
+char              *nextline          PROTO((char *));
+int                scan_line         PROTO((FILE *, char *));
+
+extern double hypot PROTO((double, double));
+/*  this seems to be a problem: is not included from math.h with the -ansi flag */
Index: /tags/start/Ohana/src/gcompare/src/compare.c
===================================================================
--- /tags/start/Ohana/src/gcompare/src/compare.c	(revision 12606)
+++ /tags/start/Ohana/src/gcompare/src/compare.c	(revision 12606)
@@ -0,0 +1,55 @@
+# include "gcompare.h"
+# define D_NMATCH 500;
+
+match_type *compare (data_type data1, data_type data2, int *Nmatches, double radius, double DX, double DY, double noauto) {
+
+  int i, j, first_j, Nmatch, NMATCH;
+  double dX, dY, dR;
+  match_type *match;
+
+  fprintf (stderr, "%f  %f\n", DX, DY);
+  Nmatch = 0;
+  NMATCH = D_NMATCH;
+  ALLOCATE (match, match_type, NMATCH);
+
+  for (i = j = 0;(i < data1.Nvalues) && (j < data2.Nvalues);) {
+    
+    dX = data1.values[i].X - data2.values[j].X - DX;
+
+    if (!(i % 100))
+      fprintf (stderr, ".");
+    
+    if (dX <= -radius)
+      i++;
+    if (dX >= radius)
+      j++;
+
+    if (fabs (dX) < radius) {
+      first_j = j;
+      for (j = first_j; (fabs (dX) < radius) && (j < data2.Nvalues); j++) {
+	dX = data1.values[i].X - data2.values[j].X - DX;
+	dY = data1.values[i].Y - data2.values[j].Y - DY;
+	dR = hypot (dX, dY);
+	if ((dR < radius) && ((noauto == 0) || (dR > noauto))) {
+	  match [Nmatch].line1 = data1.values[i].line;
+	  match [Nmatch].line2 = data2.values[j].line;
+	  match [Nmatch].dX = data1.values[i].X - data2.values[j].X - DX;
+	  match [Nmatch].dY = data1.values[i].Y - data2.values[j].Y - DY;
+	  data1.values[i].match = TRUE;
+	  data2.values[j].match = TRUE;
+	  Nmatch ++;
+	  if (Nmatch == NMATCH - 1) {
+	    NMATCH += D_NMATCH;
+	    REALLOCATE (match, match_type, NMATCH);
+	  }
+	}
+      }
+      j = first_j;
+      i++;
+    }
+
+  }
+  *Nmatches = Nmatch;
+  return (match);
+}
+
Index: /tags/start/Ohana/src/gcompare/src/count_neighbors.c
===================================================================
--- /tags/start/Ohana/src/gcompare/src/count_neighbors.c	(revision 12606)
+++ /tags/start/Ohana/src/gcompare/src/count_neighbors.c	(revision 12606)
@@ -0,0 +1,51 @@
+# include "gcompare.h"
+# define D_NMATCH 500;
+
+int count_neighbors (data, radius, DX, DY)
+data_type  data;
+double     radius;
+double     DX;
+double     DY;
+{
+
+  int i, j, first_j, Nfriends;
+  double dX, dY, dR;
+
+  fprintf (stderr, "%f  %f\n", DX, DY);
+
+  for (i = j = 0; (i < data.Nvalues) && (j < data.Nvalues);) {
+    
+    dX = data.values[i].X - data.values[j].X - DX;
+
+    if (!(i % 100))
+      fprintf (stderr, ".");
+    
+    Nfriends = 0;
+
+    if (dX <= -radius) {
+      fprintf (stdout, "%f %f %d\n", data.values[i].X, data.values[i].Y, Nfriends);
+      i++;
+    }
+    if (dX >= radius)
+      j++;
+
+    if (fabs (dX) < radius) {
+      first_j = j;
+      for (j = first_j; (fabs (dX) < radius) && (j < data.Nvalues); j++) {
+	if (i == j) continue;
+	dX = data.values[i].X - data.values[j].X - DX;
+	dY = data.values[i].Y - data.values[j].Y - DY;
+	dR = hypot (dX, dY);
+	if (dR < radius) {
+	  Nfriends ++;
+	}
+      }
+      j = first_j;
+      fprintf (stdout, "%f %f %d\n", data.values[i].X, data.values[i].Y, Nfriends);
+      i++;
+    }
+
+  }
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/gcompare/src/find_matches.c
===================================================================
--- /tags/start/Ohana/src/gcompare/src/find_matches.c	(revision 12606)
+++ /tags/start/Ohana/src/gcompare/src/find_matches.c	(revision 12606)
@@ -0,0 +1,48 @@
+# include "gcompare.h"
+
+table_type *find_matches (table, values, Nvalues, catalog, Ncatalog, noauto)
+table_type   table[];
+value_type   values[];
+int          Nvalues;
+catalog_type catalog[];
+int          Ncatalog;
+int          noauto;
+{
+
+  int i, j, start, done;
+  double delta_Dec, dRA, dDec, radius;
+
+  delta_Dec = (catalog[Ncatalog - 1].Dec - catalog[0].Dec);
+  for (i = 0; i < Nvalues; i++) {
+    if ((values[i].Dec > catalog[Ncatalog - 1].Dec) || (values[i].Dec < catalog[0].Dec))
+      continue;
+    start = Ncatalog * (values[i].Dec - catalog[0].Dec) / delta_Dec;
+    done = FALSE;
+    while (!done) {
+      if ((catalog[start].Dec > values[i].Dec - values[i].radius) && (start != 0)) {
+	start -= 100;
+	if (start < 0)
+	  start = 0;
+      }
+      else
+	done = TRUE;
+    }
+    for (j = start; ((j < Ncatalog) && 
+		     (catalog[j].Dec < values[i].Dec + values[i].radius)); j++) {
+      dRA = (values[i].RA - catalog[j].RA) / cos (DEG_RAD*values[i].Dec);
+      dDec = values[i].Dec - catalog[j].Dec;
+      
+      radius = hypot (dRA, dDec);
+      if ((radius <= values[i].radius) && (!noauto || (radius > 0))) {
+	ALLOCATE (table[i].match[table[i].Nmatches], char, NBYTES_LINE + 1);
+	bzero (table[i].match[table[i].Nmatches], NBYTES_LINE + 1);
+	strcpy (table[i].match[table[i].Nmatches], catalog[j].line);
+	table[i].Nmatches ++;
+	if (table[i].Nmatches > 500)
+	  fprintf (stderr, "too many objects! \n");
+      }
+    }
+  }
+
+  return (table);
+}
Index: /tags/start/Ohana/src/gcompare/src/gcompare.c
===================================================================
--- /tags/start/Ohana/src/gcompare/src/gcompare.c	(revision 12606)
+++ /tags/start/Ohana/src/gcompare/src/gcompare.c	(revision 12606)
@@ -0,0 +1,101 @@
+# include "gcompare.h"
+
+int main (int argc, char **argv) {
+  
+  /* USAGE:  gcompare file1 X1 Y1 file2 X2 Y2 radius */
+  
+  int Nskip1, Nskip2, Nmatches, N;
+  int X1, X2, Y1, Y2, deltas, match, nomatch1, nomatch2;
+  data_type data1, data2;
+  match_type *matches;
+  double radius, DX, DY, noauto;
+
+  DX = DY = Nskip1 = Nskip2 = 0;
+  noauto = match = nomatch1 = nomatch2 = deltas = FALSE;
+
+  if (remove_argument(get_argument (argc, argv, "-d"), &argc, argv))
+    deltas = TRUE;
+  if (remove_argument(get_argument (argc, argv, "-h"), &argc, argv))
+    help();
+  if (remove_argument(get_argument (argc, argv, "-help"), &argc, argv))
+    help();
+  if (remove_argument(get_argument (argc, argv, "-m"), &argc, argv))
+    match = TRUE;
+  if (remove_argument(get_argument (argc, argv, "-n1"), &argc, argv))
+    nomatch1 = TRUE;
+  if (remove_argument(get_argument (argc, argv, "-n2"), &argc, argv))
+    nomatch2 = TRUE;
+  if (!(match || deltas || nomatch1 || nomatch2)) {
+    fprintf (stderr, "no output mode, use at least one of -d, -m, -n1, or -n2\n");
+    exit (2);
+  }
+  if ((N = get_argument (argc, argv, "-na"))) {
+    remove_argument(N, &argc, argv);
+    noauto = atof(argv[N]);
+    remove_argument(N, &argc, argv);
+  }
+    
+  if ((N = get_argument (argc, argv, "-c")) && (N + 2 < argc)) {
+    DX = atof(argv[N + 1]);
+    DY = atof(argv[N + 2]);
+    remove_argument(N, &argc, argv);
+    remove_argument(N, &argc, argv);
+    remove_argument(N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-s1"))) {
+    Nskip1 = atof(argv[N + 1]);
+    remove_argument(N, &argc, argv);
+    remove_argument(N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-s2")) && (N + 1 < argc)) {
+    Nskip2 = atof(argv[N + 1]);
+    remove_argument(N, &argc, argv);
+    remove_argument(N, &argc, argv);
+  }
+  
+  if (argc != 8) {
+    fprintf (stderr, "gcompare [mode] file1 X1 Y1 file2 X2 Y2 radius\n");
+    exit (2);
+  }
+
+  X1 = atof (argv[2]);
+  Y1 = atof (argv[3]);
+  X2 = atof (argv[5]);
+  Y2 = atof (argv[6]);
+  radius = atof(argv[7]);
+  fprintf (stderr, "radius = %f %s\n", radius, argv[7]);
+
+  data1 = input (argv[1], X1, Y1, Nskip1);
+  fprintf (stderr, "list 1: %d values %d %d\n", data1.Nvalues, X1, Y1);
+  data2 = input (argv[4], X2, Y2, Nskip2);
+  fprintf (stderr, "list 2: %d values %d %d\n", data2.Nvalues, X2, Y2);
+
+  sort (data1); fprintf (stderr, "sorted 1\n");
+  sort (data2); fprintf (stderr, "sorted 2\n");
+
+  fprintf (stderr, "noauto: %e\n", noauto);
+  matches = compare (data1, data2, &Nmatches, radius, DX, DY, noauto);
+
+  output (data1, data2, matches, Nmatches, match, deltas, nomatch1, nomatch2);
+  exit (0);
+}
+
+
+
+void
+help() {
+
+  fprintf (stderr, "gcompare [mode] file1 X1 Y1 file2 X2 Y2 radius\n");
+  fprintf (stderr, " modes:\n");
+  fprintf (stderr, "  -d      return delta coords\n");
+  fprintf (stderr, "  -m      return matched lines\n");
+  fprintf (stderr, "  -n1     return unmatched lines, file 1\n");
+  fprintf (stderr, "  -n2     return unmatched lines, file 2\n");
+  fprintf (stderr, " additional options:\n");
+  fprintf (stderr, "  -c X Y    set offset (file1 - file2)\n");
+  fprintf (stderr, "  -s1 N     skip N lines from file 1\n");
+  fprintf (stderr, "  -s2 N     skip N lines from file 2\n");
+  fprintf (stderr, "  -na X     eliminate auto-matches (radius < X)\n");
+  exit (2);
+}
+
Index: /tags/start/Ohana/src/gcompare/src/input.c
===================================================================
--- /tags/start/Ohana/src/gcompare/src/input.c	(revision 12606)
+++ /tags/start/Ohana/src/gcompare/src/input.c	(revision 12606)
@@ -0,0 +1,65 @@
+# include "gcompare.h"
+# define D_NVALUES 1000
+# define D_NBYTES  10000
+
+data_type input (filename, X, Y, Nskip)
+char *filename;
+int   X;
+int   Y;
+int   Nskip;
+{
+  
+  data_type data;
+  int i, status, n, NVALUES, NBYTES, nbytes;
+  FILE *f;
+  char dummy_line[1000], *next;
+  
+  n = 0;
+
+  if (!strcmp (filename, "-")) {
+    f = stdin;
+  }
+  else {
+    f = fopen (filename, "r");
+    if (f == NULL) {
+      fprintf (stderr, "error opening file %s\n", filename);
+      exit (0);
+    }
+  }
+
+  for (i = 0; i < Nskip; i++) 
+    scan_line (f, dummy_line);
+ 
+  /* read in entire file */
+  NBYTES = D_NBYTES + 1;
+  ALLOCATE (data.buffer, char, NBYTES);
+  for (i = 0, nbytes = D_NBYTES; nbytes == D_NBYTES; i++) {
+    nbytes = fread (&data.buffer[i*D_NBYTES], 1, D_NBYTES, f);
+    NBYTES += D_NBYTES;
+    REALLOCATE (data.buffer, char, NBYTES);
+  }
+  NBYTES -= 2*D_NBYTES - nbytes;
+  data.buffer[NBYTES] = 0;
+  fprintf (stderr, "got %d bytes\n", NBYTES);
+
+  NVALUES = D_NVALUES;
+  ALLOCATE (data.values, value_type, NVALUES);
+  next = data.buffer;
+  for (i = 0; next != (char *) NULL; ) {
+    data.values[i].line  = next;
+    data.values[i].match = FALSE;
+    status  = dparse (&data.values[i].X, X, data.values[i].line);
+    status &= dparse (&data.values[i].Y, Y, data.values[i].line);
+    next = nextline (data.values[i].line);
+    if (status && (data.values[i].line[0] != '#')) {
+      i++;
+    }
+    if (i == NVALUES - 3) {
+      NVALUES += D_NVALUES;
+      REALLOCATE (data.values, value_type, NVALUES);
+    }
+  }
+  data.Nvalues = i;
+  return (data);
+}
+
Index: /tags/start/Ohana/src/gcompare/src/neighbors.c
===================================================================
--- /tags/start/Ohana/src/gcompare/src/neighbors.c	(revision 12606)
+++ /tags/start/Ohana/src/gcompare/src/neighbors.c	(revision 12606)
@@ -0,0 +1,72 @@
+# include "gcompare.h"
+
+void main (argc, argv)
+int    argc;
+char **argv;
+{
+  
+  /* USAGE:  gcompare file1 X1 Y1 file2 X2 Y2 radius */
+  
+  int i, Nskip1, Nskip2, Nmatches, N;
+  int X1, X2, Y1, Y2, deltas, match, nomatch1, nomatch2, noauto;
+  data_type data1, data2;
+  match_type *matches;
+  double radius, DX, DY;
+
+  DX = DY = Nskip1 = Nskip2 = 0;
+
+  if (remove_argument(get_argument (argc, argv, "-h"), &argc, argv))
+    help();
+  if (remove_argument(get_argument (argc, argv, "-help"), &argc, argv))
+    help();
+    
+  if ((N = get_argument (argc, argv, "-c")) && (N + 2 < argc)) {
+    DX = atof(argv[N + 1]);
+    DY = atof(argv[N + 2]);
+    remove_argument(N, &argc, argv);
+    remove_argument(N, &argc, argv);
+    remove_argument(N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-s1")) {
+    Nskip1 = atof(argv[N + 1]);
+    remove_argument(N, &argc, argv);
+    remove_argument(N, &argc, argv);
+  }
+  
+  if (argc != 5) {
+    fprintf (stderr, "neighbors [mode] file X Y radius\n");
+    exit (0);
+  }
+
+  X1 = atof (argv[2]);
+  Y1 = atof (argv[3]);
+  radius = atof(argv[4]);
+
+  data1 = input (argv[1], X1, Y1, Nskip1);
+  fprintf (stderr, "list 1: %d values %d %d\n", data1.Nvalues, X1, Y1);
+
+  sort (data1); fprintf (stderr, "sorted 1\n");
+
+  count_neighbors (data1, radius, DX, DY);
+
+}
+
+
+
+void
+help() {
+
+  fprintf (stderr, "gcompare [mode] file1 X1 Y1 file2 X2 Y2 radius\n");
+  fprintf (stderr, " modes:\n");
+  fprintf (stderr, "  -d      return delta coords\n");
+  fprintf (stderr, "  -m      return matched lines\n");
+  fprintf (stderr, "  -n1     return unmatched lines, file 1\n");
+  fprintf (stderr, "  -n2     return unmatched lines, file 2\n");
+  fprintf (stderr, " additional options:\n");
+  fprintf (stderr, "  -c X Y    set offset (file1 - file2)\n");
+  fprintf (stderr, "  -s1 N     skip N lines from file 1\n");
+  fprintf (stderr, "  -s2 N     skip N lines from file 2\n");
+  fprintf (stderr, "  -na X     eliminate auto-matches (radius < X)\n");
+  exit (0);
+}
+
Index: /tags/start/Ohana/src/gcompare/src/nextline.c
===================================================================
--- /tags/start/Ohana/src/gcompare/src/nextline.c	(revision 12606)
+++ /tags/start/Ohana/src/gcompare/src/nextline.c	(revision 12606)
@@ -0,0 +1,17 @@
+# include "gcompare.h"
+
+char *nextline (line)
+char line[];
+{
+
+  char *ret;
+  
+  ret = strchr (line, '\n');
+  if (ret != NULL) { 
+    *ret = 0;
+    ret += 1;
+  }
+
+  return (ret);
+}
+  
Index: /tags/start/Ohana/src/gcompare/src/nextword.c
===================================================================
--- /tags/start/Ohana/src/gcompare/src/nextword.c	(revision 12606)
+++ /tags/start/Ohana/src/gcompare/src/nextword.c	(revision 12606)
@@ -0,0 +1,12 @@
+# include "gcompare.h"
+
+char *nextword(string)
+char *string;
+{
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (; isspace (*string); string++);
+  for (; (*string != 0) && !isspace (*string); string++);
+  for (; isspace (*string); string++);
+  return (string);
+}
Index: /tags/start/Ohana/src/gcompare/src/output.c
===================================================================
--- /tags/start/Ohana/src/gcompare/src/output.c	(revision 12606)
+++ /tags/start/Ohana/src/gcompare/src/output.c	(revision 12606)
@@ -0,0 +1,57 @@
+# include "gcompare.h"
+
+void output (data1, data2, matches, Nmatches, match, deltas, nomatch1, nomatch2)
+data_type  data1;
+data_type  data2;
+match_type matches[];
+int        Nmatches;
+int        match;
+int        deltas; 
+int        nomatch1;
+int        nomatch2;
+{
+
+  int i, Nmatch1, Nmatch2;
+
+  fprintf (stderr, "This is a Gcompare output list\n");
+  fprintf (stderr, "There are %d matches\n\n", Nmatches);
+  Nmatch1 = Nmatch2 = 0.0;
+
+  if (match || deltas) {
+    for (i = 0; i < Nmatches; i++) {
+      if (deltas)
+	fprintf (stdout, "%15.9f  %15.9f  ", matches[i].dX, matches[i].dY);
+      if (match)
+	fprintf (stdout, "%s  %s", matches[i].line1, matches[i].line2);
+      fprintf (stdout, "\n");
+    }
+  }
+
+  if (match && nomatch1) 
+    fprintf (stdout, "\n non-matces from file 1:\n");
+  
+  if (nomatch1) {
+    for (i = 0; i < data1.Nvalues; i++) {
+      if (!data1.values[i].match) {
+	fprintf (stdout, "%s\n", data1.values[i].line);
+	Nmatch1 ++;
+      }
+    }
+    fprintf (stderr, "no matches in file 1: %d\n", Nmatch1);
+  }
+
+  if ((match || nomatch1) && nomatch2)
+    fprintf (stdout, "\n non-matces from file 2:\n");
+
+  if (nomatch2) {
+    for (i = 0; i < data2.Nvalues; i++) {
+      if (!data2.values[i].match) {
+	fprintf (stdout, "%s\n", data2.values[i].line);
+	Nmatch2++;
+      }
+    }
+    fprintf (stderr, "no matches in file 2: %d\n", Nmatch2);
+  }
+
+
+}
Index: /tags/start/Ohana/src/gcompare/src/sort.c
===================================================================
--- /tags/start/Ohana/src/gcompare/src/sort.c	(revision 12606)
+++ /tags/start/Ohana/src/gcompare/src/sort.c	(revision 12606)
@@ -0,0 +1,40 @@
+# include "gcompare.h"
+
+void sort (data)
+data_type data;
+{
+  int l,j,ir,i, N;
+  value_type temp;
+
+  N = data.Nvalues;
+  if (N == 1)
+    return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      temp = data.values[--l];
+    }
+    else {
+      temp = data.values[ir];
+      data.values[ir] = data.values[0];
+      if (--ir == 0) {
+        data.values[0] = temp;
+        return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && data.values[j].X < data.values[j+1].X) ++j;
+      if (temp.X < data.values[j].X) {
+        data.values[i]=data.values[j];
+        j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    data.values[i] = temp;
+  }
+}
+
Index: /tags/start/Ohana/src/getstar/Makefile
===================================================================
--- /tags/start/Ohana/src/getstar/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/getstar/Makefile	(revision 12606)
@@ -0,0 +1,58 @@
+include ../../Configure
+HOME 	=	$(ROOT)/src/getstar
+PROGRAM =       getstar
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#  
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lFITS -lohana -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS)
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+GETSTAR = \
+$(SRC)/getstar.$(ARCH).o 	$(SRC)/gcatalog.$(ARCH).o 	\
+$(SRC)/gregions.$(ARCH).o 	$(SRC)/gimages.$(ARCH).o        \
+$(SRC)/wstars.$(ARCH).o   	$(SRC)/find_matches.$(ARCH).o 	\
+$(SRC)/sort_lists.$(ARCH).o 	$(SRC)/ConfigInit.$(ARCH).o 	\
+$(SRC)/aregion.$(ARCH).o	$(SRC)/clean_stars.$(ARCH).o	\
+$(SRC)/args.$(ARCH).o
+
+OBJ = $(GETSTAR)
+
+default: $(PROGRAM)
+
+$(GETSTAR): $(INC)/getstar.h
+
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:	
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
+
+
Index: /tags/start/Ohana/src/getstar/doc/database.txt
===================================================================
--- /tags/start/Ohana/src/getstar/doc/database.txt	(revision 12606)
+++ /tags/start/Ohana/src/getstar/doc/database.txt	(revision 12606)
@@ -0,0 +1,91 @@
+
+\begin{verbatim}
+
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm;      /* number of measurements */
+  unsigned short int Xp, Xm;  /* chisq values in tenths */
+  unsigned int offset;        /* offset to first Measure-ment */
+} Average;                    /* = 20 bytes / average */
+
+typedef struct {
+  char dR, dD;                /* tenths of arcsec (-12.7 to +12.7 valid range) */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 -- 0.255 valid range) */
+  float t;                    /* time in seconds (what is reference?) */
+  unsigned int average;       /* reference to corresponding Average entry, 
+				 upper byte of value contains flags.
+				 limit of 16,777,215 stars (Naverage) 
+				 in a file (=0xFFFFFF).
+				 flags = average & 0x1000000 */
+} Measure;                    /* = 13 bytes / measure */
+
+# define BLEND_IMAGE   0X01000000
+# define BLEND_CATALOG 0X02000000
+# define UPPER_LIMIT   0X04000000
+# define CALIBRATED    0X08000000
+
+\end{verbatim}
+
+The above two structures define the entries in the photometry
+database.  The database consists of a large number of files
+representing a small patch on the sky (roughly 1.5 degree$^2$ in most
+places).  These files are organized into directories representing
+bands of Declination.  A reference file determines the coordinate
+boundaries for each of the files so that a given point on the sky can
+unambiguously be associated with a specific file in a specific
+directory.  The sky coordinates for each file is the same as those
+used by the HST Guide Star catalog, except for the region around the
+North celestial pole, for which all stars are included in a single
+file.  
+
+Within a given file, the data are stored in a binary format, with an
+ASCII FITS-like header.  The header is examply in the format of a
+normal FITS header, but with the exception that all files have a fixed
+number of header blocks (for now 3 blocks = 8640 bytes).  This is done
+to speed loading the header and finding the beginning of the binary
+data.  The number of 3 blocks seems quite generous, as currently only
+a few FITS keywords have been defined for each file, basically
+keywords to define the number of stars and the total number of
+measurements stored in the file, as well as values to define the RA
+and DEC range of the file.  
+
+The first section of data following the header blocks consists of
+average measurements for each uniquely observed star.  Each star
+occupies 20 bytes, the size of the Average structure defined above.
+The Average structure contains the average Ra, Dec, and Magnitude for
+the star, as well as the number of measurements, and \chisq\ values
+for the magnitude and position.  Finally, there is a 32 bit integer
+which defines the offset to the first measurement for this star.  This
+offset is defined as the number of Measure records from the start of
+the Measure structure.
+
+The second section of data, following the Average data contains all
+measurements for each star listed in Average.  Each measurement
+occupies 13 bytes, the size of the Measure structure.  This structure
+contains the difference of this position from the average RA and DEC,
+and the instrumental magnitude of this measurement (in the units
+defined by the fstat program, which give m = -2.5*log(cts) + Mo, where
+Mo is currently 24.5 [10/15]).  There is also the magnitude error for
+this measurement, the time of the measurement (in seconds relative to
+a to-be-determined zero point), and a reference to the entry in the
+Average structure so we can relate a given measurement with a given star.
+This last entry also includes a byte of flags, of which only 4 have
+currently been defined.  This means the Average offset can only be as
+large as  16,777,215 (0xffffff), limiting the possible number of stars
+allowed in a given file.  This does not seem like a long term problem,
+though:  aside from the fact that this number is very large and we
+only expect in the vicinity of 20,000 stars per file, the file can
+easily be divided into pieces at a later date if needed.  this last
+step is trivial, consisting of splitting the data up into smaller
+RA,DEC regions, and updating the reference catalog.  With the above
+definitions for the Average and Measure structures, we will typically
+expect 20,000 * 15 measurements per year and 20,000 average entries in
+a given file.  This implies a file size of about 4.3 MB at the end of
+a year.  It is also possible that we will choose to split the files up
+in the future if the number of measurements makes their size
+unweildy.  4.3 MB is sufficiently small that this is not a problem,
+but after only 5 years, the files will be over 21 MB each, getting to
+be fairly significant.  
Index: /tags/start/Ohana/src/getstar/doc/description.txt
===================================================================
--- /tags/start/Ohana/src/getstar/doc/description.txt	(revision 12606)
+++ /tags/start/Ohana/src/getstar/doc/description.txt	(revision 12606)
@@ -0,0 +1,94 @@
+
+ADDSTAR:
+
+This program takes a photometry file, with astrometry, provided by
+earlier routines and incorporates the stellar measurements into the
+photometry database.  This routine does NOT try to calibrate or check
+the photometry, nor does it try to improve the coordinate
+determinations or calculate chisquares for position or photometry -
+those tasks are performed by other routines.
+
+Addstar starts by loading in the photometry file and converting the
+pixel coordinates to sky coordinates using the astrometry information
+in the header of the file.  It also gets the detection limits and
+stores the image astrometry information.
+
+Next, addstar determines which of all the previous images overlaps
+with this image and also which of the catalog regions overlaps with
+this image.
+
+Addstar considers each catalog region in turn, and compares the
+positions of stars in the catalog with stars in the image.  If a
+catalog star is detected, a new measurement is added to the catalog.
+If a catalog star is not detected, but is in the field of view of this
+image, the detection limit for this image is added to the list of
+measurements as an upper limit.  If the image contains a star which is
+not already included in the catalog, the star is added to the catalog,
+and all previous images are checked to see if they included this
+location.  If so, upper limits are added to the list of measurements.
+
+To deal with blended images, we have taken the philosophy that all
+measurements compatible with the coordinates of a given star should be
+included in the list of measurements.  This assumes that programs or people
+downstream will figure out which is the "correct" measurement.  To
+this end, if a catalog star is consistent with multiple measurements,
+they are all added to the catalog measurement and the measurements are
+given a flag to say that there was blending in the catalog (ie, it is
+probably the catalog star which is a blend).  If multiple catalog
+stars are consistent with the same image star, that measurement is
+added to each catalog star, and given a flag to say that there was
+blending on the image.
+
+After all catalogs have been checked, updated, and written to disk,
+the image is added to the database of images.
+
+The format for a catalog region file is as follows:
+
+-- 
+Header
+--
+Averages
+--
+Measurements
+--
+
+The Header follows the format of a FITS header but always stored with
+3 blocks to speed up read time: 2880 x 3 bytes.  Two important
+keywords in the header: NSTARS & NMEAS
+
+All average values are stored consecutively in a single block.  They
+are written as an array with NSTARS elements of the Average structure
+defined below.  The individual measurements follow the averages as a
+block.  To find a measurement for a given star, you need to get the
+value of the offset for the star.  this is the element number for the
+first measurement of this star, and are followed by next measurements
+for this star, until the value Nm is reached.
+
+Here are the structures being used for the average and measurement
+values:
+
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm;      /* number of measurements */
+  unsigned short int Xp, Xm;  /* chisq values in tenths */
+  unsigned int offset;        /* offset to first measurement */
+} Average;                    /* = 20 bytes / average */
+
+typedef struct {
+  char dR, dD;                /* tenths of arcsec (-12.7 to +12.7 valid range) */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 -- 0.255 valid range) */
+  float t;                    /* time in seconds (what is reference?) */
+  unsigned int average;       
+  /* reference to corresponding average entry, upper byte stores flags:
+   limit of 16,777,215 stars (Naverage) in a file (=0xFFFFFF) 
+   flags: average & 0x1000000 */
+} Measure;                    /* = 13 bytes / measure */
+
+/* flags for measurements: */
+# define BLEND_IMAGE   0X01000000
+# define BLEND_CATALOG 0X02000000
+# define UPPER_LIMIT   0X04000000
+# define CALIBRATED    0X08000000
Index: /tags/start/Ohana/src/getstar/etc/phottemp.cat
===================================================================
--- /tags/start/Ohana/src/getstar/etc/phottemp.cat	(revision 12606)
+++ /tags/start/Ohana/src/getstar/etc/phottemp.cat	(revision 12606)
@@ -0,0 +1,296 @@
+SIMPLE  =                    F  / ASTROCAM PHOTOMETRY FILE                    \
+BITPIX  =                   16 /                                              \
+NAXIS   =                    2  / NUMBER OF AXES                              \
+NAXIS1  =                 1106  / NUMBER OF COLUMNS                           \
+NAXIS2  =                 1024  / NUMBER OF ROWS                              \
+BSCALE  =             1.000000 /                                              \
+BZERO   =             0.000000 /                                              \
+DATE    = '19/12/94'            / UT Date of file creation (DD/MM/YY)         \
+ORIGIN  = 'MDM Observatory'     / Michigan-Dartmouth-MIT                      \
+LATITUDE=              31.9500  / Latitude (degrees N)                        \
+LONGITUD=            -111.6150  / Longitude (degrees E)                       \
+OBSERVER= 'Metzger '            / Name of observer                            \
+TELESCOP= '1.3m McGraw-Hill'    / Telescope used for observation              \
+INSTRUME= 'Charlotte Direct'    / Instrument used for observation             \
+DETECTOR= 'Charlotte/Tek 1024^2 CCD'  / Detector used for observation         \
+FRAME   =                   32  / Frame number of observation                 \
+CCDPICNO=                   32  / Frame number of observation                 \
+OBJECT  = 'ocl0327 '            / Name of object                              \
+IMAGETYP= 'OBJECT  '            / Type of observation                         \
+EXPTIME =              250.000  / Integration time (seconds)                  \
+DARKTIME=              250.067  / Dark current time (seconds)                 \
+DATE-OBS= '19/12/94'            / UT Date of observation (DD/MM/YY)           \
+UT      = ' 05:25:44.00'        / Universal time (UTC) at exposure start      \
+JD      =       2449705.726204                                                \
+RA      =           50.700      / Right Ascension                             \
+DEC     =           89.000      / Declination                                 \
+DIRECTN =                 -1    / Moving South                                \
+EQUINOX =             1950.000  / Equinox of RA and DEC                       \
+HA      = ' 02:14:06.72'        / Hour angle at start                         \
+ST      = ' 03:49:36.85'        / Sidereal time at start                      \
+ZD      = ' 36:26:07.17'        / Zenith distance (degrees)                   \
+AIRMASS =                1.243  / Airmass at start                            \
+FILTER  = 'I KP    '            / Filter description                          \
+GAIN    =                3.350  / Nominal gain (e-/ADU)                       \
+SECPIX1 =                0.508  / Arcseconds per pixel in fast dir            \
+SECPIX2 =                0.508  / Arcseconds per pixel in slow dir            \
+CCDBIN1 =                    1  / On-chip column binning (fast dir)           \
+CCDBIN2 =                    1  / On-chip row binning (slow dir)              \
+GPROBE  = '  5000.00   7000.00'  / Guide probe X Y                            \
+DATASEC = '[51:1074,1:1024]'    / Image area of frame                         \
+CCDSEC  = '[1:1074,1:1024]'     / Image area relative to full chip            \
+BIASSEC = '[1080:1106,1:1023]'  / Overscan area of frame                      \
+UNSIGN  =                    T /                                              \
+NSTARS  =                    0  / NUMBER OF stars                             \
+CTYPE1  = 'RA---SIN          ' /                                               
+CTYPE2  = 'DEC--SIN          ' /                                               
+CDELT1  =             0.000733 /                                               
+CDELT2  =             0.000733 /                                               
+CRVAL1  =            50.191418 /                                               
+CRVAL2  =            88.998663 /                                               
+CRPIX1  =          1028.644173 /                                               
+CRPIX2  =           503.129830 /                                               
+PC001001=             0.999906 /                                               
+PC001002=             0.012081 /                                               
+PC002001=            -0.011936 /                                               
+PC002002=             0.999950 /                                               
+END                                                                           \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+ 246.5  352.1 13.000 020 1 3.2
+ 246.5  352.1 14.100 020 1 3.2
+ 279.4  328.9 13.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 436.6  413.5 14.300 020 1 3.2
+   9.3  856.5 13.000 020 1 3.2
+   9.3  856.2 13.600 020 1 3.2
+ 319.7  697.9 12.000 020 1 3.2
+ 319.7  697.7 12.100 020 1 3.2
+ 244.3    9.5 14.100 020 1 3.2
+ 284.7  334.4 14.000 020 1 3.2
+ 127.1  122.8 14.200 020 1 3.2
+ 140.2  791.1 13.700 020 1 3.2
+ 140.2  790.8 14.400 020 1 3.2
+ 131.7  636.3 13.800 020 1 3.2
+ 423.8  700.6 13.800 020 1 3.2
+ 423.7  700.7 12.500 020 1 3.2
+ 266.2  290.7 13.800 020 1 3.2
+ 266.0  290.7 13.100 020 1 3.2
+ 570.7  721.6 13.600 020 1 3.2
+ 570.7  721.6 13.100 020 1 3.2
+ 548.7  673.0 13.700 020 1 3.2
+ 264.2  219.7 12.800 020 1 3.2
+ 264.0  219.7 12.100 020 1 3.2
+ 161.9  797.4 11.900 020 1 3.2
+ 162.0  797.2 12.200 020 1 3.2
+ 505.8  851.8 13.700 020 1 3.2
+  88.2  419.0 11.400 020 1 3.2
+  88.2  419.0 11.800 020 1 3.2
+ 426.9  613.2  9.400 020 1 3.2
+ 427.4  613.5  7.600 020 1 3.2
+ 326.1  595.2 12.100 020 1 3.2
+ 326.2  595.1 12.600 020 1 3.2
+ 444.4  845.2 14.200 020 1 3.2
+ 254.1  916.8 14.500 020 1 3.2
+ 502.6  882.4 14.200 020 1 3.2
+ 128.3  275.7 12.300 020 1 3.2
+ 128.3  275.7 12.900 020 1 3.2
+ 230.9  554.8 13.300 020 1 3.2
+ 230.9  554.7 14.200 020 1 3.2
+  47.5  685.2 13.500 020 1 3.2
+  47.5  684.9 14.200 020 1 3.2
+ 382.6  658.7 14.000 020 1 3.2
+ 182.2  330.3 14.200 020 1 3.2
+ 245.1  548.3 12.600 020 1 3.2
+ 245.3  548.0 13.200 020 1 3.2
+  50.3  849.0 13.700 020 1 3.2
+  50.5  848.8 14.300 020 1 3.2
+  17.9  772.7 14.200 020 1 3.2
+ 499.8  712.8 13.500 020 1 3.2
+ 499.8  712.6 14.400 020 1 3.2
+ 294.5  349.4 14.000 020 1 3.2
+ 497.7  747.8 11.000 020 1 3.2
+ 497.5  747.8 10.900 020 1 3.2
+ 109.7  323.5 14.000 020 1 3.2
+  59.5  917.6 14.300 020 1 3.2
+  59.4  917.8 13.700 020 1 3.2
+  82.2  880.5 13.800 020 1 3.2
+ 145.1  341.2 14.500 020 1 3.2
+ 452.7  592.4 14.400 020 1 3.2
+ 623.4  820.0 13.700 020 1 3.2
+ 609.7  829.3 13.500 020 1 3.2
+ 481.8  938.3 14.400 020 1 3.2
+ 617.0  792.7 13.500 020 1 3.2
+ 183.2  539.7 14.400 020 1 3.2
+ 133.9  679.6 14.400 020 1 3.2
+ 423.7  667.8  6.500 020 1 3.2
+ 434.7  111.9 13.200 020 1 3.2
+ 434.5  111.9 13.200 020 1 3.2
+ 434.6  111.9 14.200 020 1 3.2
+1222.3  684.2 13.900 020 1 3.2
+1077.6  282.5 14.000 020 1 3.2
+1077.8  282.5 13.400 020 1 3.2
+ 720.8  562.1 14.100 020 1 3.2
+ 721.1  561.9 14.400 020 1 3.2
+1182.1  944.4 12.100 020 1 3.2
+1181.9  944.4 11.800 020 1 3.2
+1181.9  944.4 12.300 020 1 3.2
+ 761.2  423.1 14.300 020 1 3.2
+ 761.0  423.1 14.100 020 1 3.2
+ 926.7  436.8 13.400 020 1 3.2
+ 926.6  436.8 14.200 020 1 3.2
+1209.1   45.0 13.200 020 1 3.2
+1209.2   43.6 12.800 020 1 3.2
+1135.2  653.1  8.100 020 1 3.2
+1135.6  653.4  8.200 020 1 3.2
+1123.5  735.8 12.000 020 1 3.2
+1123.6  735.8 11.800 020 1 3.2
+1123.7  735.7 11.600 020 1 3.2
+ 730.7   28.6 12.100 020 1 3.2
+ 730.7   28.6 12.200 020 1 3.2
+ 783.1  267.5 14.200 020 1 3.2
+ 783.2  267.5 13.400 020 1 3.2
+ 876.2  462.7 13.800 020 1 3.2
+ 876.4  462.7 14.200 020 1 3.2
+ 917.2  399.9 13.700 020 1 3.2
+ 917.3  399.9 13.200 020 1 3.2
+1227.5  218.4 10.400 020 1 3.2
+1227.7  218.4 10.500 020 1 3.2
+1022.7  146.0 13.300 020 1 3.2
+1022.5  146.0 14.100 020 1 3.2
+1324.7   72.3 12.900 020 1 3.2
+1324.6   72.3 13.200 020 1 3.2
+ 743.2  379.4 14.300 020 1 3.2
+ 742.9  379.4 13.900 020 1 3.2
+1255.9  544.0 12.600 020 1 3.2
+1256.0  543.9 12.300 020 1 3.2
+ 848.9  251.1 13.200 020 1 3.2
+ 849.0  251.1 12.700 020 1 3.2
+ 495.6  147.4 11.400 020 1 3.2
+ 495.6  147.4 11.300 020 1 3.2
+ 495.5  147.4 11.000 020 1 3.2
+1016.4  735.5 14.200 020 1 3.2
+1016.3  735.7 13.900 020 1 3.2
+ 795.2  675.9 14.400 020 1 3.2
+ 887.2  968.8 10.800 020 1 3.2
+ 626.8  726.9 14.400 020 1 3.2
+ 718.6  800.1  9.700 020 1 3.2
+ 675.4  301.6 14.400 020 1 3.2
+ 801.6  436.8 14.200 020 1 3.2
+1066.4  870.0 13.700 020 1 3.2
+1066.5  869.9 13.800 020 1 3.2
+ 644.5  662.9  9.900 020 1 3.2
+ 639.1  760.4 13.000 020 1 3.2
+ 822.7  663.1 12.800 020 1 3.2
+ 822.7  663.1 13.100 020 1 3.2
+ 677.2  716.2 12.900 020 1 3.2
+ 765.6  641.5 13.200 020 1 3.2
+ 765.7  641.4 13.500 020 1 3.2
+ 998.3  425.8 14.400 020 1 3.2
+ 713.7  716.2 13.800 020 1 3.2
+ 814.7  887.6  2.000 020 1 3.2
+ 808.7  884.1  8.200 020 1 3.2
+1812.3  259.3 14.500 020 1 3.2
+1655.9  655.4 12.200 020 1 3.2
+1655.9  655.4 12.100 020 1 3.2
+1577.2  839.6 11.500 020 1 3.2
+1577.2  839.6 11.400 020 1 3.2
+1643.7  597.0 14.100 020 1 3.2
+1552.8  251.1 10.100 020 1 3.2
+1552.8  251.1 10.300 020 1 3.2
+1410.0  999.9 13.900 020 1 3.2
+1335.6  687.0 13.000 020 1 3.2
+1335.8  686.8 12.700 020 1 3.2
+1471.4  262.0 14.200 020 1 3.2
+1479.6  608.3 14.200 020 1 3.2
+1478.1  211.5 12.000 020 1 3.2
+1478.3  211.5 12.000 020 1 3.2
+1552.5   46.4 14.500 020 1 3.2
+2042.4  548.3 10.800 020 1 3.2
+2042.6  548.3 11.000 020 1 3.2
+1448.0  915.7 14.100 020 1 3.2
+1462.3  989.2 13.000 020 1 3.2
+1462.3  989.0 12.700 020 1 3.2
+1316.9  787.3 14.100 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1677.2  106.4 13.100 020 1 3.2
+1677.0  106.4 13.300 020 1 3.2
+1324.2  429.9  9.200 020 1 3.2
+1324.2  429.9  9.000 020 1 3.2
+1462.8  214.3 13.700 020 1 3.2
+1462.8  214.3 14.200 020 1 3.2
+1405.4   95.5 11.700 020 1 3.2
+1405.2   95.5 11.600 020 1 3.2
+1604.8   90.0 11.200 020 1 3.2
+1604.8   90.0 11.300 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1459.8  473.6 13.400 020 1 3.2
+1459.7  473.6 13.800 020 1 3.2
+1438.7   77.8 12.200 020 1 3.2
+1438.6   77.8 12.200 020 1 3.2
+1355.0  114.6 13.000 020 1 3.2
+1354.9  114.6 13.200 020 1 3.2
+1941.4  940.7 13.000 020 1 3.2
+1941.6  940.7 12.900 020 1 3.2
+1994.0  800.8 13.900 020 1 3.2
+1993.8  800.8 14.000 020 1 3.2
+2024.4  907.0 13.700 020 1 3.2
+2024.4  907.0 13.800 020 1 3.2
+2035.7  881.6 13.900 020 1 3.2
+2035.9  881.6 13.800 020 1 3.2
+1994.0  924.2 12.100 020 1 3.2
+1994.0  924.2 12.000 020 1 3.2
Index: /tags/start/Ohana/src/getstar/etc/template.cat
===================================================================
--- /tags/start/Ohana/src/getstar/etc/template.cat	(revision 12606)
+++ /tags/start/Ohana/src/getstar/etc/template.cat	(revision 12606)
@@ -0,0 +1,296 @@
+SIMPLE  =                    F  / ASTROCAM PHOTOMETRY FILE                    \
+BITPIX  =                   16 /                                              \
+NAXIS   =                    2  / NUMBER OF AXES                              \
+NAXIS1  =                 1106  / NUMBER OF COLUMNS                           \
+NAXIS2  =                 1024  / NUMBER OF ROWS                              \
+BSCALE  =             1.000000 /                                              \
+BZERO   =             0.000000 /                                              \
+DATE    = '19/12/94'            / UT Date of file creation (DD/MM/YY)         \
+ORIGIN  = 'MDM Observatory'     / Michigan-Dartmouth-MIT                      \
+LATITUDE=              31.9500  / Latitude (degrees N)                        \
+LONGITUD=            -111.6150  / Longitude (degrees E)                       \
+OBSERVER= 'Metzger '            / Name of observer                            \
+TELESCOP= '1.3m McGraw-Hill'    / Telescope used for observation              \
+INSTRUME= 'Charlotte Direct'    / Instrument used for observation             \
+DETECTOR= 'Charlotte/Tek 1024^2 CCD'  / Detector used for observation         \
+FRAME   =                   32  / Frame number of observation                 \
+CCDPICNO=                   32  / Frame number of observation                 \
+OBJECT  = 'ocl0327 '            / Name of object                              \
+IMAGETYP= 'OBJECT  '            / Type of observation                         \
+EXPTIME =              250.000  / Integration time (seconds)                  \
+DARKTIME=              250.067  / Dark current time (seconds)                 \
+DATE-OBS= '19/12/94'            / UT Date of observation (DD/MM/YY)           \
+UT      = ' 05:25:44.00'        / Universal time (UTC) at exposure start      \
+JD      =       2449705.726204                                                \
+RA      =           50.700      / Right Ascension                             \
+DEC     =           89.000      / Declination                                 \
+DIRECTN =                 -1    / Moving South                                \
+EQUINOX =             1950.000  / Equinox of RA and DEC                       \
+HA      = ' 02:14:06.72'        / Hour angle at start                         \
+ST      = ' 03:49:36.85'        / Sidereal time at start                      \
+ZD      = ' 36:26:07.17'        / Zenith distance (degrees)                   \
+AIRMASS =                1.243  / Airmass at start                            \
+FILTER  = 'I KP    '            / Filter description                          \
+GAIN    =                3.350  / Nominal gain (e-/ADU)                       \
+SECPIX1 =                0.508  / Arcseconds per pixel in fast dir            \
+SECPIX2 =                0.508  / Arcseconds per pixel in slow dir            \
+CCDBIN1 =                    1  / On-chip column binning (fast dir)           \
+CCDBIN2 =                    1  / On-chip row binning (slow dir)              \
+GPROBE  = '  5000.00   7000.00'  / Guide probe X Y                            \
+DATASEC = '[51:1074,1:1024]'    / Image area of frame                         \
+CCDSEC  = '[1:1074,1:1024]'     / Image area relative to full chip            \
+BIASSEC = '[1080:1106,1:1023]'  / Overscan area of frame                      \
+UNSIGN  =                    T /                                              \
+NSTARS  =                    0  / NUMBER OF stars                             \
+CTYPE1  = 'RA---SIN          ' /                                               
+CTYPE2  = 'DEC--SIN          ' /                                               
+CDELT1  =             0.000733 /                                               
+CDELT2  =             0.000733 /                                               
+CRVAL1  =            50.191418 /                                               
+CRVAL2  =            88.998663 /                                               
+CRPIX1  =          1028.644173 /                                               
+CRPIX2  =           503.129830 /                                               
+PC001001=             0.999906 /                                               
+PC001002=             0.012081 /                                               
+PC002001=            -0.011936 /                                               
+PC002002=             0.999950 /                                               
+END                                                                           \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+ 246.5  352.1 13.000 020 1 3.2
+ 246.5  352.1 14.100 020 1 3.2
+ 279.4  328.9 13.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 436.6  413.5 14.300 020 1 3.2
+   9.3  856.5 13.000 020 1 3.2
+   9.3  856.2 13.600 020 1 3.2
+ 319.7  697.9 12.000 020 1 3.2
+ 319.7  697.7 12.100 020 1 3.2
+ 244.3    9.5 14.100 020 1 3.2
+ 284.7  334.4 14.000 020 1 3.2
+ 127.1  122.8 14.200 020 1 3.2
+ 140.2  791.1 13.700 020 1 3.2
+ 140.2  790.8 14.400 020 1 3.2
+ 131.7  636.3 13.800 020 1 3.2
+ 423.8  700.6 13.800 020 1 3.2
+ 423.7  700.7 12.500 020 1 3.2
+ 266.2  290.7 13.800 020 1 3.2
+ 266.0  290.7 13.100 020 1 3.2
+ 570.7  721.6 13.600 020 1 3.2
+ 570.7  721.6 13.100 020 1 3.2
+ 548.7  673.0 13.700 020 1 3.2
+ 264.2  219.7 12.800 020 1 3.2
+ 264.0  219.7 12.100 020 1 3.2
+ 161.9  797.4 11.900 020 1 3.2
+ 162.0  797.2 12.200 020 1 3.2
+ 505.8  851.8 13.700 020 1 3.2
+  88.2  419.0 11.400 020 1 3.2
+  88.2  419.0 11.800 020 1 3.2
+ 426.9  613.2  9.400 020 1 3.2
+ 427.4  613.5  7.600 020 1 3.2
+ 326.1  595.2 12.100 020 1 3.2
+ 326.2  595.1 12.600 020 1 3.2
+ 444.4  845.2 14.200 020 1 3.2
+ 254.1  916.8 14.500 020 1 3.2
+ 502.6  882.4 14.200 020 1 3.2
+ 128.3  275.7 12.300 020 1 3.2
+ 128.3  275.7 12.900 020 1 3.2
+ 230.9  554.8 13.300 020 1 3.2
+ 230.9  554.7 14.200 020 1 3.2
+  47.5  685.2 13.500 020 1 3.2
+  47.5  684.9 14.200 020 1 3.2
+ 382.6  658.7 14.000 020 1 3.2
+ 182.2  330.3 14.200 020 1 3.2
+ 245.1  548.3 12.600 020 1 3.2
+ 245.3  548.0 13.200 020 1 3.2
+  50.3  849.0 13.700 020 1 3.2
+  50.5  848.8 14.300 020 1 3.2
+  17.9  772.7 14.200 020 1 3.2
+ 499.8  712.8 13.500 020 1 3.2
+ 499.8  712.6 14.400 020 1 3.2
+ 294.5  349.4 14.000 020 1 3.2
+ 497.7  747.8 11.000 020 1 3.2
+ 497.5  747.8 10.900 020 1 3.2
+ 109.7  323.5 14.000 020 1 3.2
+  59.5  917.6 14.300 020 1 3.2
+  59.4  917.8 13.700 020 1 3.2
+  82.2  880.5 13.800 020 1 3.2
+ 145.1  341.2 14.500 020 1 3.2
+ 452.7  592.4 14.400 020 1 3.2
+ 623.4  820.0 13.700 020 1 3.2
+ 609.7  829.3 13.500 020 1 3.2
+ 481.8  938.3 14.400 020 1 3.2
+ 617.0  792.7 13.500 020 1 3.2
+ 183.2  539.7 14.400 020 1 3.2
+ 133.9  679.6 14.400 020 1 3.2
+ 423.7  667.8  6.500 020 1 3.2
+ 434.7  111.9 13.200 020 1 3.2
+ 434.5  111.9 13.200 020 1 3.2
+ 434.6  111.9 14.200 020 1 3.2
+1222.3  684.2 13.900 020 1 3.2
+1077.6  282.5 14.000 020 1 3.2
+1077.8  282.5 13.400 020 1 3.2
+ 720.8  562.1 14.100 020 1 3.2
+ 721.1  561.9 14.400 020 1 3.2
+1182.1  944.4 12.100 020 1 3.2
+1181.9  944.4 11.800 020 1 3.2
+1181.9  944.4 12.300 020 1 3.2
+ 761.2  423.1 14.300 020 1 3.2
+ 761.0  423.1 14.100 020 1 3.2
+ 926.7  436.8 13.400 020 1 3.2
+ 926.6  436.8 14.200 020 1 3.2
+1209.1   45.0 13.200 020 1 3.2
+1209.2   43.6 12.800 020 1 3.2
+1135.2  653.1  8.100 020 1 3.2
+1135.6  653.4  8.200 020 1 3.2
+1123.5  735.8 12.000 020 1 3.2
+1123.6  735.8 11.800 020 1 3.2
+1123.7  735.7 11.600 020 1 3.2
+ 730.7   28.6 12.100 020 1 3.2
+ 730.7   28.6 12.200 020 1 3.2
+ 783.1  267.5 14.200 020 1 3.2
+ 783.2  267.5 13.400 020 1 3.2
+ 876.2  462.7 13.800 020 1 3.2
+ 876.4  462.7 14.200 020 1 3.2
+ 917.2  399.9 13.700 020 1 3.2
+ 917.3  399.9 13.200 020 1 3.2
+1227.5  218.4 10.400 020 1 3.2
+1227.7  218.4 10.500 020 1 3.2
+1022.7  146.0 13.300 020 1 3.2
+1022.5  146.0 14.100 020 1 3.2
+1324.7   72.3 12.900 020 1 3.2
+1324.6   72.3 13.200 020 1 3.2
+ 743.2  379.4 14.300 020 1 3.2
+ 742.9  379.4 13.900 020 1 3.2
+1255.9  544.0 12.600 020 1 3.2
+1256.0  543.9 12.300 020 1 3.2
+ 848.9  251.1 13.200 020 1 3.2
+ 849.0  251.1 12.700 020 1 3.2
+ 495.6  147.4 11.400 020 1 3.2
+ 495.6  147.4 11.300 020 1 3.2
+ 495.5  147.4 11.000 020 1 3.2
+1016.4  735.5 14.200 020 1 3.2
+1016.3  735.7 13.900 020 1 3.2
+ 795.2  675.9 14.400 020 1 3.2
+ 887.2  968.8 10.800 020 1 3.2
+ 626.8  726.9 14.400 020 1 3.2
+ 718.6  800.1  9.700 020 1 3.2
+ 675.4  301.6 14.400 020 1 3.2
+ 801.6  436.8 14.200 020 1 3.2
+1066.4  870.0 13.700 020 1 3.2
+1066.5  869.9 13.800 020 1 3.2
+ 644.5  662.9  9.900 020 1 3.2
+ 639.1  760.4 13.000 020 1 3.2
+ 822.7  663.1 12.800 020 1 3.2
+ 822.7  663.1 13.100 020 1 3.2
+ 677.2  716.2 12.900 020 1 3.2
+ 765.6  641.5 13.200 020 1 3.2
+ 765.7  641.4 13.500 020 1 3.2
+ 998.3  425.8 14.400 020 1 3.2
+ 713.7  716.2 13.800 020 1 3.2
+ 814.7  887.6  2.000 020 1 3.2
+ 808.7  884.1  8.200 020 1 3.2
+1812.3  259.3 14.500 020 1 3.2
+1655.9  655.4 12.200 020 1 3.2
+1655.9  655.4 12.100 020 1 3.2
+1577.2  839.6 11.500 020 1 3.2
+1577.2  839.6 11.400 020 1 3.2
+1643.7  597.0 14.100 020 1 3.2
+1552.8  251.1 10.100 020 1 3.2
+1552.8  251.1 10.300 020 1 3.2
+1410.0  999.9 13.900 020 1 3.2
+1335.6  687.0 13.000 020 1 3.2
+1335.8  686.8 12.700 020 1 3.2
+1471.4  262.0 14.200 020 1 3.2
+1479.6  608.3 14.200 020 1 3.2
+1478.1  211.5 12.000 020 1 3.2
+1478.3  211.5 12.000 020 1 3.2
+1552.5   46.4 14.500 020 1 3.2
+2042.4  548.3 10.800 020 1 3.2
+2042.6  548.3 11.000 020 1 3.2
+1448.0  915.7 14.100 020 1 3.2
+1462.3  989.2 13.000 020 1 3.2
+1462.3  989.0 12.700 020 1 3.2
+1316.9  787.3 14.100 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1677.2  106.4 13.100 020 1 3.2
+1677.0  106.4 13.300 020 1 3.2
+1324.2  429.9  9.200 020 1 3.2
+1324.2  429.9  9.000 020 1 3.2
+1462.8  214.3 13.700 020 1 3.2
+1462.8  214.3 14.200 020 1 3.2
+1405.4   95.5 11.700 020 1 3.2
+1405.2   95.5 11.600 020 1 3.2
+1604.8   90.0 11.200 020 1 3.2
+1604.8   90.0 11.300 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1459.8  473.6 13.400 020 1 3.2
+1459.7  473.6 13.800 020 1 3.2
+1438.7   77.8 12.200 020 1 3.2
+1438.6   77.8 12.200 020 1 3.2
+1355.0  114.6 13.000 020 1 3.2
+1354.9  114.6 13.200 020 1 3.2
+1941.4  940.7 13.000 020 1 3.2
+1941.6  940.7 12.900 020 1 3.2
+1994.0  800.8 13.900 020 1 3.2
+1993.8  800.8 14.000 020 1 3.2
+2024.4  907.0 13.700 020 1 3.2
+2024.4  907.0 13.800 020 1 3.2
+2035.7  881.6 13.900 020 1 3.2
+2035.9  881.6 13.800 020 1 3.2
+1994.0  924.2 12.100 020 1 3.2
+1994.0  924.2 12.000 020 1 3.2
Index: /tags/start/Ohana/src/getstar/include/addstar.h
===================================================================
--- /tags/start/Ohana/src/getstar/include/addstar.h	(revision 12606)
+++ /tags/start/Ohana/src/getstar/include/addstar.h	(revision 12606)
@@ -0,0 +1,47 @@
+# include <ohana.h>
+# include <loneos.h>
+# include <signal.h>
+
+typedef struct {
+  double X;
+  double Y;
+  double R;
+  double D;
+  double M, dM;
+  char   dophot;
+  double sky;
+  double fx, fy, df;
+  double Mgal, Map;
+  int found;
+} Stars;
+
+/* global variables set in parameter file */
+char   ImageCat[256];
+char   ImageTemplate[256];
+char   CatTemplate[256];
+char   GSCFILE[256];
+char   CATDIR[256];
+double DEFAULT_RADIUS, NSIGMA, SNLIMIT;
+double ZeroPt;
+int    VERBOSE;
+int    SKIP_MISSED;
+int    XOVERSCAN, YOVERSCAN;
+int    XMIN, XMAX, YMIN, YMAX;
+int    ACCEPT_ASTROM;
+
+PhotCode *thiscode;
+
+char DateKeyword[64];
+char DateMode[64];
+char UTKeyword[64];
+char MJDKeyword[64];
+char JDKeyword[64];
+char ExptimeKeyword[64];
+char AirmassKeyword[64];
+char CCDNumKeyword[64];
+
+int CalReference;
+int CalColor;
+int CALIBRATE;
+int DUMP_MATCHES;
+int ONLY_IMAGES;
Index: /tags/start/Ohana/src/getstar/include/getstar.h
===================================================================
--- /tags/start/Ohana/src/getstar/include/getstar.h	(revision 12606)
+++ /tags/start/Ohana/src/getstar/include/getstar.h	(revision 12606)
@@ -0,0 +1,47 @@
+# include <ohana.h>
+# include <loneos.h>
+# include <signal.h>
+
+typedef struct {
+  double X;
+  double Y;
+  double R;
+  double D;
+  double M, dM;
+  char   dophot;
+  double sky;
+  double fx, fy, df;
+  double Mgal, Map;
+  int found;
+} Stars;
+
+/* global variables set in parameter file */
+char   ImageCat[256];
+char   ImageTemplate[256];
+char   CatTemplate[256];
+char   GSCFILE[256];
+char   CATDIR[256];
+double DEFAULT_RADIUS, NSIGMA, SNLIMIT;
+double ZeroPt;
+int    VERBOSE;
+int    SKIP_MISSED;
+int    XOVERSCAN, YOVERSCAN;
+int    XMIN, XMAX, YMIN, YMAX;
+int    ACCEPT_ASTROM;
+
+PhotCode *thiscode;
+
+char DateKeyword[64];
+char DateMode[64];
+char UTKeyword[64];
+char MJDKeyword[64];
+char JDKeyword[64];
+char ExptimeKeyword[64];
+char AirmassKeyword[64];
+char CCDNumKeyword[64];
+
+int CalReference;
+int CalColor;
+int CALIBRATE;
+int DUMP_MATCHES;
+int ONLY_IMAGES;
Index: /tags/start/Ohana/src/getstar/src/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/ConfigInit.c	(revision 12606)
@@ -0,0 +1,63 @@
+# include "getstar.h"
+
+ConfigInit (int *argc, char **argv) {
+
+  char *config, *file;
+  char RadiusWord[80];
+  char PhotCodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (1);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  ScanConfig (config, "RADIUS",                 "%s", 0,  RadiusWord);
+  if (!strcasecmp (RadiusWord, "header")) {
+    DEFAULT_RADIUS = 0;
+  } else {
+    DEFAULT_RADIUS = atof (RadiusWord);
+  }
+
+  XMIN = XMAX = YMIN = YMAX = 0;
+  ScanConfig (config, "NSIGMA",                 "%lf", 0, &NSIGMA);
+  ScanConfig (config, "XOVERSCAN",              "%d", 0, &XOVERSCAN);
+  ScanConfig (config, "YOVERSCAN",              "%d", 0, &YOVERSCAN);
+  ScanConfig (config, "ZERO_PT",                "%lf", 0, &ZeroPt);
+
+  ScanConfig (config, "ADDSTAR_XMIN",           "%d", 0, &XMIN);
+  ScanConfig (config, "ADDSTAR_XMAX",           "%d", 0, &XMAX);
+  ScanConfig (config, "ADDSTAR_YMIN",           "%d", 0, &YMIN);
+  ScanConfig (config, "ADDSTAR_YMAX",           "%d", 0, &YMAX);
+
+  ScanConfig (config, "IMAGE_CATALOG",          "%s", 0, ImageCat);
+  ScanConfig (config, "IMAGE_CATALOG_TEMPLATE", "%s", 0, ImageTemplate);
+  ScanConfig (config, "CATALOG_TEMPLATE",       "%s", 0, CatTemplate);
+  ScanConfig (config, "GSCFILE",                "%s", 0, GSCFILE);
+  ScanConfig (config, "CATDIR",                 "%s", 0, CATDIR);
+  ScanConfig (config, "MIN_SN_FSTAT",           "%lf", 0, &SNLIMIT);
+  ScanConfig (config, "PHOTCODE_FILE",          "%s", 0, PhotCodeFile);
+
+  ScanConfig (config, "DATE-KEYWORD",           "%s", 0, DateKeyword);
+  ScanConfig (config, "DATE-MODE",              "%s", 0, DateMode);
+  ScanConfig (config, "UT-KEYWORD",             "%s", 0, UTKeyword);
+  ScanConfig (config, "MJD-KEYWORD",            "%s", 0, MJDKeyword);
+  ScanConfig (config, "JD-KEYWORD",             "%s", 0, JDKeyword);
+
+  ScanConfig (config, "EXPTIME-KEYWORD",        "%s", 0, ExptimeKeyword);
+  ScanConfig (config, "AIRMASS-KEYWORD",        "%s", 0, AirmassKeyword);
+  ScanConfig (config, "CCDNUM-KEYWORD",         "%s", 0, CCDNumKeyword);
+
+  if (!LoadPhotcodes (PhotCodeFile)) {
+    fprintf (stderr, "error loading photcodes\n");
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+
+}
Index: /tags/start/Ohana/src/getstar/src/addstar.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/addstar.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/addstar.c	(revision 12606)
@@ -0,0 +1,223 @@
+# include "addstar.h"
+
+/* these variables are needed by Shutdown */
+static FILE *f = (FILE *) NULL;
+static int Protect = FALSE;
+static int Trapped = FALSE;
+
+/* clean up open / locked ImageCat before shutting down */
+int Shutdown () {  
+  int dbstate;
+
+  Protect = TRUE;
+  fclearlockfile (ImageCat, f, LCK_HARD, &dbstate);
+  fprintf (stderr, "ERROR: addstar halted\n");
+  exit (1);
+}
+
+void TrapSignal (int sig) {
+    fprintf (stderr, "trapped signal %d, exiting gracefully\n", sig);
+    if (sig == 11) {
+      fprintf (stderr, "seg fault\n");
+      exit (1);
+    }
+    if (Protect) {
+      Trapped = TRUE;
+      fprintf (stderr, "blocking until protected sections are clear\n");
+      return;
+    }
+    Shutdown ();
+}    
+
+main (int argc, char **argv) {
+
+  int i, N, mode, dbstate;
+  int Nstars, Nimage, Nregions, Nmissed;
+  Stars *stars, *gstars();
+  Image image, *pimage, *gimages();
+  GSCRegion *region, *gregions();
+  Catalog catalog;
+  struct timeval now, then;  
+  
+  SetSignals ();
+  args (argc, argv);
+
+  /* load the input datafile */
+  stars = gstars (argv[1], &Nstars, &image);
+  if (Nstars == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in data file, skipping\n");
+    fprintf (stderr, "SUCCESS\n");
+    exit (0);
+  }
+
+  /* lock the image catalog */
+  check_permissions (ImageCat);
+  f = fsetlockfile (ImageCat, 3600.0, LCK_HARD, &dbstate);
+  if ((f == (FILE *) NULL) && (dbstate != LCK_EMPTY)) {
+    fprintf (stderr, "ERROR: can't lock image catalog\n");
+    exit (1);
+  }
+  fseek (f, 0, SEEK_SET);
+
+  /* load images */
+  if (dbstate == LCK_EMPTY) {
+    Nimage = 0;
+  } else {
+    pimage = gimages (f, &image, &Nimage);
+  }
+  region = gregions (&image, &Nregions);
+  fprintf (stderr, "region %f %f %f %f\n", region[0].RA[0], region[0].RA[1], region[0].DEC[0], region[0].DEC[1]);
+
+  for (i = 0; i < Nregions; i++) {
+    check_permissions (region[i].filename);
+  }
+
+  if (CALIBRATE) { InitCalibration (); }
+
+  for (i = 0; i < Nregions; i++) {
+    catalog.filename = region[i].filename;  /* don't free region before catalog! */
+    fprintf (stderr, "adding to %s\n", region[i].filename);
+    
+    switch (lock_catalog (&catalog, LCK_XCLD)) {
+    case 0:
+      /* this is a serious error because ImageCat was NOT locked */
+      fprintf (stderr, "ERROR: can't lock file %s\n", catalog.filename);
+      exit (1);
+    case 1:
+      gcatalog (&catalog); /* load from disk */
+      break;
+    case 2:
+      mkcatalog (&region[i], &catalog); /* fills in new header info */
+      break;
+    }
+    find_matches (&region[i], stars, Nstars, &catalog, &image, pimage, Nimage);
+
+    /* protect wcatalog from interrupt signals */
+    Protect = TRUE;
+    if (!DUMP_MATCHES && !ONLY_IMAGES) wcatalog (&catalog);
+    if (Trapped) Shutdown ();
+    Protect = FALSE;
+    unlock_catalog (&catalog);
+  }
+
+  if (CALIBRATE) { FindCalibration (&image); }
+  if (DUMP_MATCHES) Shutdown ();
+
+  for (Nmissed = i = 0; i < Nstars; i++) {
+    if (stars[i].found == -1) {
+      fprintf (stderr, "%d %f %f %f %f\n", i, stars[i].R, stars[i].D, stars[i].M, stars[i].dM);
+      Nmissed ++;
+    }
+  }
+  if (Nmissed) fprintf (stderr, "WARNING: %d stars in image were missed!\n", Nmissed);
+
+  /* protect wimage from interrupt signals */
+  Protect = TRUE;
+  wimage (f, dbstate, &image, Nstars); 
+  if (Trapped) Shutdown ();
+  Protect = FALSE;
+
+  fclearlockfile (ImageCat, f, LCK_HARD, &dbstate);
+
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  chmod (ImageCat, mode);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+
+}
+
+int SetSignals () {
+
+  int i;
+
+  /* disable almost all signal interrupts */
+  for (i = 0; i < 36; i++) {
+    switch (i) {
+      /* can't redirect this signals */
+    case SIGKILL:    /* kill -9: cannot be caught or ignored */
+    case SIGSTOP:    /* SIGSTOP: cannot be caught or ignored */
+      /* ignore these signals */
+    case SIGCHLD:    /* child halted: ignore */
+    case SIGPWR:     /* power failure - why ignore this? */
+    case SIGWINCH:   /* window resized */
+    case SIGCONT:    /* continue - maintain this action */
+    case SIGTSTP:    /* stop signal sent from tty - why ignore? */
+    case SIGURG:     /* socket signal, ignore this */
+      break;
+      
+    default:
+      signal (i, TrapSignal);
+    }
+  }
+
+}
+/*
+
+       Signal     Value     Action   Comment
+       -------------------------------------------------------------------------
+       SIGHUP        1        A      Hangup detected on controlling terminal
+                                     or death of controlling process
+       SIGINT        2        A      Interrupt from keyboard
+       SIGQUIT       3        A      Quit from keyboard
+       SIGILL        4        A      Illegal Instruction
+       SIGABRT       6        C      Abort signal from abort(3)
+       SIGFPE        8        C      Floating point exception
+       SIGKILL       9       AEF     Kill signal
+       SIGSEGV      11        C      Invalid memory reference
+       SIGPIPE      13        A      Broken pipe: write to pipe with no readers
+       SIGALRM      14        A      Timer signal from alarm(2)
+       SIGTERM      15        A      Termination signal
+       SIGUSR1   30,10,16     A      User-defined signal 1
+       SIGUSR2   31,12,17     A      User-defined signal 2
+       SIGCHLD   20,17,18     B      Child stopped or terminated
+       SIGCONT   19,18,25            Continue if stopped
+       SIGSTOP   17,19,23    DEF     Stop process
+       SIGTSTP   18,20,24     D      Stop typed at tty
+       SIGTTIN   21,21,26     D      tty input for background process
+       SIGTTOU   22,22,27     D      tty output for background process
+
+       Next various other signals.
+
+       Signal       Value     Action   Comment
+       ---------------------------------------------------------------------
+       SIGTRAP        5         CG     Trace/breakpoint trap
+       SIGIOT         6         CG     IOT trap. A synonym for SIGABRT
+       SIGEMT       7,-,7       G
+       SIGBUS      10,7,10      AG     Bus error
+       SIGSYS      12,-,12      G      Bad argument to routine (SVID)
+       SIGSTKFLT    -,16,-      AG     Stack fault on coprocessor
+       SIGURG      16,23,21     BG     Urgent condition on socket (4.2 BSD)
+       SIGIO       23,29,22     AG     I/O now possible (4.2 BSD)
+       SIGPOLL                  AG     A synonym for SIGIO (System V)
+       SIGCLD       -,-,18      G      A synonym for SIGCHLD
+       SIGXCPU     24,24,30     AG     CPU time limit exceeded (4.2 BSD)
+       SIGXFSZ     25,25,31     AG     File size limit exceeded (4.2 BSD)
+       SIGVTALRM   26,26,28     AG     Virtual alarm clock (4.2 BSD)
+       SIGPROF     27,27,29     AG     Profile alarm clock
+       SIGPWR      29,30,19     AG     Power failure (System V)
+       SIGINFO      29,-,-      G      A synonym for SIGPWR
+       SIGLOST      -,-,-       AG     File lock lost
+       SIGWINCH    28,28,20     BG     Window resize signal (4.3 BSD, Sun)
+       SIGUNUSED    -,31,-      AG     Unused signal
+       (Here - denotes that a signal is absent; there where three values are given, the first one is usually  valid  for  alpha  and
+       sparc,  the  middle  one  for i386 and ppc, the last one for mips. Signal 29 is SIGINFO / SIGPWR on an alpha but SIGLOST on a
+       sparc.)
+
+       The letters in the "Action" column have the following meanings:
+
+       A      Default action is to terminate the process.
+
+       B      Default action is to ignore the signal.
+
+       C      Default action is to dump core.
+
+       D      Default action is to stop the process.
+
+       E      Signal cannot be caught.
+
+       F      Signal cannot be ignored.
+
+       G      Not a POSIX.1 conformant signal.
+
+*/
Index: /tags/start/Ohana/src/getstar/src/aregion.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/aregion.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/aregion.c	(revision 12606)
@@ -0,0 +1,180 @@
+# include "getstar.h"
+
+double BigDecBounds[] = {0.0, 7.5, 15.0, 22.5, 30.0, 37.5, 45.0, 
+			 52.5, 60.0, 67.5, 75.0, 82.5, 90.0,
+			 0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, 
+			 -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+char *DecSections[] = {"N0000", "N0730", "N1500", "N2230", "N3000", "N3730", "N4500", 
+		       "N5230", "N6000", "N6730", "N7500", "N8230", "weirdness", 
+		       "S0000", "S0730", "S1500", "S2230", "S3000", "S3730", "S4500", 
+		       "S5230", "S6000", "S6730", "S7500", "S8230", "weirdness"};
+
+char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			"n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			"s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			"s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+char *disk[] = {"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", 
+		"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "weirdness", 
+		"disk 1", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", 
+		"disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "weirdness"};
+
+int NBigRASections [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3, 48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3};
+
+int NDecLines[] = {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 24, 
+                   0, 597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48};
+
+# define DEBUG 1
+
+/* find region file which contains ra, dec */
+aregion (region, f, ra, dec) 
+GSCRegion region[];
+FILE *f;
+double ra, dec;
+{
+  
+  
+  char buffer[28800], temp[50], file[256];
+  double dr, dd;
+  double RA0, RA1, DEC0, DEC1;
+  int i, NBigDec, NLINES, done, nregion;
+  
+  while (ra < 0) { ra += 360.0; }
+  while (ra >= 360.0) { ra -= 360.0; }
+
+  if (dec >= 86.25) {
+    sprintf (file, "%s/n8230/pole.cpt\0", CATDIR);
+    region[0].DEC[0] = 86.25;
+    region[0].DEC[1] = 93.75;
+    region[0].RA[0] =  0.0;
+    region[0].RA[1] =  360.0;
+    strcpy (region[0].filename, file);
+    return;
+  }
+    
+  NBigDec = -1;
+  for (i = 0; i < 12; i++) {
+    if ((dec >= BigDecBounds[i]) && (dec < BigDecBounds[i+1])) {
+      NBigDec = i;
+      break;
+    }
+  }
+  if (NBigDec < 0) {
+    for (i = 13; i < 24; i++) {
+      if ((dec < BigDecBounds[i]) && (dec >= BigDecBounds[i+1])) {
+	NBigDec = i;
+	break;
+      }
+    }
+  }
+  if (NBigDec < 0) {
+    fprintf (stderr, "dec out of range: %f\n", dec);
+  }
+    
+  NLINES = 0;
+  for (i = 0; i < NBigDec; i++) {
+    NLINES += NDecLines[i];
+  }
+  fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+      
+  done = FALSE;
+  Fread (buffer, 1, 48*NDecLines[NBigDec], f, "char");
+  for (i = 0; !done && (i < NDecLines[NBigDec]); i++) {
+    strncpy (temp, &buffer[i*48], 48);
+    temp[49] = 0;
+    hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+    if (RA1 < RA0) RA1 += 360.0;
+    if ((dec >= 0) && (dec >= DEC0) && (dec < DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+    if ((dec < 0) && (dec < DEC0) && (dec >= DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+  }
+
+  if (!done) {
+    fprintf (stderr, "error in search: %f %f\n", ra, dec);
+    exit (1);
+  }
+  temp[5] = 0;
+  sprintf (file, "%s/%s/%s.cpt\0", CATDIR, Dec2Sections[NBigDec], &temp[1]);
+  if (DEC0 < DEC1) {
+    region[0].DEC[0] = DEC0;
+    region[0].DEC[1] = DEC1;
+  } else {
+    region[0].DEC[0] = DEC1;
+    region[0].DEC[1] = DEC0;
+  }     
+  region[0].RA[0] = RA0;
+  region[0].RA[1] = RA1;
+  strcpy (region[0].filename, file);
+  return;
+}
+
+
+/**********/
+int hms_to_deg (h0, h1, d0, d1, string) 
+     char *string;
+     double *h0, *h1, *d0, *d1;
+{
+  
+  int flag_d0, flag_d1, flag_h0, flag_h1;
+  double tmp;
+  
+  *d0 = *h0 = *d1 = *h1 = 0;
+
+  flag_h0 = dparse (h0, 1, string);
+  flag_h1 = dparse (h1, 4, string);
+  flag_d0 = dparse (d0, 7, string);
+  flag_d1 = dparse (d1, 9, string);
+  *h0 *= flag_h0;
+  *h1 *= flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  dparse (&tmp, 2, string);
+  *h0 += tmp/60.0;
+  dparse (&tmp, 3, string);
+  *h0 += tmp/3600.0;
+  
+  dparse (&tmp, 5, string);
+  *h1 += tmp/60.0;
+  dparse (&tmp, 6, string);
+  *h1 += tmp/3600.0;
+  
+  dparse (&tmp, 8, string);
+  *d0 += tmp/60.0;
+
+  dparse (&tmp, 10, string);
+  *d1 += tmp/60.0;
+
+  *h0 *= 15*flag_h0;
+  *h1 *= 15*flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  return (TRUE);
+}
+
+
+/*
+      if (buffer[i*48 + 19] == ' ') continue;
+      strncpy (temp, &buffer[i*48 + 19], 20);       temp[20] = 0;
+      hms_to_deg (&RA,  &DEC, temp, ' ', 3);
+
+
+  dBigRA = 360.0 / (int)(0.5 + 48*cos(3.1415927*0.5*(BigDecBounds[NBigDec] + BigDecBounds[NBigDec + 1])/180.0));
+
+  NBigRA = ra / dBigRA;
+
+  NBig = NBigRA;
+  for (i = 0; (i < 12) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+  for (i = 13; (i < 24) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+
+
+  fprintf (stderr, "%d %d %d %d %f %f -> %f %f %f\n", NBigDec, NBigRA, NBigRASections[NBigDec], NBig, ra, dec, BigDecBounds[NBigDec], BigDecBounds[NBigDec + 1], dBigRA);
+*/
Index: /tags/start/Ohana/src/getstar/src/args.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/args.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/args.c	(revision 12606)
@@ -0,0 +1,31 @@
+# include "getstar.h"
+
+void help () {
+  fprintf (stderr, "USAGE: getstar (file) (output)\n");
+  exit (2);
+}
+
+int args (int argc, char **argv) {
+  
+  int N;
+
+  /* check for help request */
+  if (get_argument (argc, argv, "-help") ||
+      get_argument (argc, argv, "-h")) {
+    help ();
+  }
+
+  /* configuration info */
+  ConfigInit (&argc, argv);
+
+  /* check for command line options */
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) help ();
+
+}
+
Index: /tags/start/Ohana/src/getstar/src/calibrate.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/calibrate.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/calibrate.c	(revision 12606)
@@ -0,0 +1,143 @@
+# include "addstar.h"
+
+static int Ncal, NCAL;
+static float *Mobs, *dMobs, *Mref, *Cref, *Airm;
+static float *RA, *DEC, *X, *Y;
+int *Nstar;
+
+InitCalibration () {
+
+    fprintf (stderr, "calibrating the image...  %d\n", CalReference);
+    Ncal = 0;
+    NCAL = 1000;
+    ALLOCATE (Mobs,  float,  NCAL);
+    ALLOCATE (dMobs, float, NCAL);
+    ALLOCATE (Mref,  float,  NCAL);
+    ALLOCATE (Cref,  float,  NCAL);
+    ALLOCATE (Airm,  float,  NCAL);
+    ALLOCATE (Nstar, int, NCAL);
+    ALLOCATE (RA, float, NCAL);
+    ALLOCATE (DEC, float, NCAL);
+    ALLOCATE (X, float, NCAL);
+    ALLOCATE (Y, float, NCAL);
+}
+  
+SaveCalibration (float M, float dM, float Mr, float Mc, float A, int N, float ra, float dec, float x, float y) {
+
+  Mobs[Ncal] = M;
+  dMobs[Ncal] = dM;
+  Mref[Ncal] = Mr;
+  Cref[Ncal] = Mc;
+  Airm[Ncal] = A;
+  Nstar[Ncal] = N;
+
+  RA[Ncal] = ra;
+  DEC[Ncal] = dec;
+  X[Ncal] = x;
+  Y[Ncal] = y;
+  Ncal ++;
+
+  if (Ncal == NCAL) {
+    NCAL += 1000;
+    REALLOCATE (dMobs, float, NCAL);
+    REALLOCATE (Mobs,  float, NCAL);
+    REALLOCATE (Mref,  float, NCAL);
+    REALLOCATE (Cref,  float, NCAL);
+    REALLOCATE (Airm,  float, NCAL);
+    REALLOCATE (Nstar, int,   NCAL);
+    REALLOCATE (RA, float, NCAL);
+    REALLOCATE (DEC, float, NCAL);
+    REALLOCATE (X, float, NCAL);
+    REALLOCATE (Y, float, NCAL);
+  }
+}
+
+FindCalibration (Image *image) {
+
+  int i, MaxN, *Nlist, Nkeep;
+  float N, M1, M2, Klam, Clam, Xlam, Mabs, dM, dm, *Dmag;
+  float dAs, dMs, dYs;
+  
+  /* reject multiple matched-stars */
+  /* find maximum value of Nstar[] */
+  MaxN = -1;
+  for (i = 0; i < Ncal; i++) {
+    MaxN = MAX (Nstar[i], MaxN);
+  }
+  if (MaxN == -1) {
+    fprintf (stderr, "no clean stars\n");
+    image[0].Mcal = 10000;
+    image[0].dMcal = 10000;
+    return;
+  }
+  /* create a hash array from Nstar[] entries */
+  ALLOCATE (Nlist, int, MAX (1, MaxN + 1));
+  bzero (Nlist, MAX (0, MaxN*sizeof(int)));
+  for (i = 0; i < Ncal; i++) {
+    Nlist[Nstar[i]] ++;
+  }
+  
+  /* accumulate delta mags */
+  ALLOCATE (Dmag, float, Ncal);
+  Nkeep = 0;
+  Klam = thiscode[0].K;
+  Clam = thiscode[0].C;
+  Xlam = thiscode[0].X;
+  for (i = 0; i < Ncal; i++) {
+    /* if this entry has too many (or two few?) matches, skip it */
+    if (Nlist[Nstar[i]] != 1) continue;
+    Mabs = 0.001*(Mobs[i] + Klam*(Airm[i] - 1000) + Clam + Xlam*(Mref[i] - Cref[i])) - ZeroPt;
+
+    /* subpix correction : make parameters global! */
+    dAs = 0;
+    if (Y[i] < 400) dAs = 0.06 - 0.00015*Y[i];
+    dYs = Y[i] - (int) (Y[i]) + 0.55;
+    dMs = dAs * sin (6.28*dYs);
+    /* Mabs -= dMs; */
+
+    if (DUMP_MATCHES) 
+      fprintf (stdout, "%d  %6.3f %6.3f %6.3f  %10.6f %10.6f  %7.2f %7.2f\n", 
+	       i, Mabs, 0.001*Mref[i], 0.001*Cref[i], RA[i], DEC[i], X[i], Y[i]);
+
+    /* skip stars brighter than 8.0 */
+    /* if (Mabs < 8.0) continue; */
+    
+    Dmag[Nkeep] = (Mabs - 0.001*Mref[i]);
+    Nkeep ++;
+  }
+
+  if (Nkeep < 3) {
+    fprintf (stderr, "too few stars\n");
+    image[0].Mcal = 10000;
+    image[0].dMcal = 10000;
+    return;
+  }
+  fsort (Dmag, Nkeep);
+
+  /* accumulate delta mags (25% - 75% of list) */
+  M1 = 0.0;
+  M2 = 0.0;
+  N  = 0.0;
+  for (i = 0.25*Nkeep; i <= 0.75*Nkeep; i++) {
+
+    /* a straight mean works better, given the bad photometry of skyprobe */
+    M1 += Dmag[i];
+    M2 += SQ (Dmag[i]);
+    N  += 1.0; 
+
+  }
+
+  if (N > 1) {
+    M1 = M1 / N;
+    M2 = sqrt (fabs(M2/N - M1*M1));
+    fprintf (stderr, "N: %.0f, mean: %f, stdev: %f, precision: %f\n", N, M1, M2, M2 / sqrt (N));
+    image[0].Mcal = 1000 * M1;
+    image[0].dMcal = 1000 * M2 / sqrt (N);
+  } else {
+    fprintf (stderr, "too few stars\n");
+    image[0].Mcal = 10000;
+    image[0].dMcal = 10000;
+  }
+}
+
+
Index: /tags/start/Ohana/src/getstar/src/check_permissions.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/check_permissions.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/check_permissions.c	(revision 12606)
@@ -0,0 +1,91 @@
+# include "addstar.h"
+
+check_permissions (char *basefile) {
+  
+  FILE *f;
+  char *c, dir[256], filename[256];
+  struct stat filestat;
+  uid_t fuid, uid;
+  gid_t fgid, gid;
+  int status, cmode;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to write to directory */
+  sprintf (filename, "%s\0", basefile);
+  c = strrchr (filename, '/');
+  if (c == (char *) NULL) {
+    strcpy (dir, ".");
+  } else {
+    *c = 0;
+    strcpy (dir, filename);
+  }
+  status = stat (dir, &filestat);
+  if (status == -1) {
+    fprintf (stderr, "directory %s does not exist, creating...\n", dir);
+    cmode = S_IRWXU | S_IRWXG | S_IRWXO;
+    status = mkdir (dir, cmode);
+    if (status == -1) {
+      fprintf (stderr, "ERROR: can't create %s\n", dir);
+      exit (1);
+    }
+  } 
+  status = stat (dir, &filestat);
+  if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRWXU)) ||
+      ((gid == filestat.st_gid) && (filestat.st_mode & S_IRWXG)) || 
+      (filestat.st_mode & S_IRWXO)) {
+  } else {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (1);
+  }
+  
+  /* check permission to write to file */
+  sprintf (filename, "%s\0", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (1);
+    }
+  }
+  
+  /* check permission to write to backup file */
+  sprintf (filename, "%s~\0", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (1);
+    }
+  }
+  
+}
+
+/* uses cp only */
+make_backup (char *filename) {
+
+  int status, cmode;
+  struct stat filestat;
+  char line [256];
+
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, make backup copy */
+    sprintf (line, "cp %s %s~\0", filename, filename);
+    status = system (line);
+    if (status) {
+      fprintf (stderr, "ERROR: unable to create %s~, exiting\n", filename);
+      exit (1);
+    }
+    cmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    sprintf (line, "%s~\0", filename);
+    chmod (line, cmode);
+  }
+  
+}
Index: /tags/start/Ohana/src/getstar/src/clean_stars.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/clean_stars.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/clean_stars.c	(revision 12606)
@@ -0,0 +1,63 @@
+# include "getstar.h"
+
+int clean_stars (Stars *stars, int *nstars, Image *image) {
+
+  int i, j, Nsubset, *subset, *skip, *found, Nstars, check, Nskip;
+  double Xo, Yo, Xt, Yt, radius;
+  double Mo, Mt, dM;
+
+  Nstars = *nstars;
+  ALLOCATE (found,  int, Nstars);
+  ALLOCATE (subset, int, Nstars);
+  ALLOCATE (skip,   int, Nstars);
+  bzero (skip, Nstars*sizeof(int));
+
+  Nskip = 0;
+  Nsubset = 0;
+  for (i = 0; i < Nstars; i++) {
+    RD_to_XY (&stars[i].X, &stars[i].Y, stars[i].R, stars[i].D, &image[0].coords);
+    check = (stars[i].found & BLEND_IMAGE) || (stars[i].found & BLEND_IMAGE_NEIGHBOR) || (stars[i].found & BLEND_CATALOG);
+    if (check) {
+      subset[Nsubset] = i;
+      found[Nsubset] = FALSE;
+      Nsubset ++;
+    }
+  }
+
+  if (Nsubset > 1) {
+    for (i = 0; i < Nsubset; i++) {
+      if (found[i]) continue;
+      Xo = stars[subset[i]].X;
+      Yo = stars[subset[i]].Y;
+      Mo = stars[subset[i]].M;
+      for (j = 0; j < Nsubset; j++) {
+	if (j == i) continue;
+	if (found[j]) continue;
+	Xt = stars[subset[j]].X;
+	Yt = stars[subset[j]].Y;
+	Mt = stars[subset[j]].M;
+	radius = hypot ((Xo-Xt), (Yo-Yt));
+	dM = fabs (Mo-Mt);
+	if ((radius < 5.0) && (dM < 0.005)) {
+	  skip[subset[j]] = TRUE;
+	  found[j] = TRUE;
+	  Nskip ++;
+	}
+      }
+      found[i] = TRUE;
+    }
+ 
+    for (i = j = 0; i < Nstars; i++) {
+      if (skip[i]) continue;
+      if (i == j) { 
+	j++;
+	continue;
+      }
+      stars[j] = stars[i];
+      j++;
+    }
+    *nstars = j;
+  }
+  fprintf (stderr, "%d skipped\n", Nskip);
+}
+
Index: /tags/start/Ohana/src/getstar/src/coordops.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/coordops.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/coordops.c	(revision 12606)
@@ -0,0 +1,342 @@
+# include "addstar.h"
+
+XY_to_RD (ra, dec, x, y, coords)
+double *ra, *dec;
+double  x, y;
+Coords coords[];
+{
+
+  double L, M, X, Y, T;
+  double R, sphi, cphi, stht, ctht;
+  double alpha, delta, salp, calp, sdel, sdp, cdp;
+  
+  *ra  = 0;
+  *dec = 0;
+
+# if 1
+  if (!strcmp(&coords[0].ctype[4], "-PLY")) {
+    X = coords[0].cdelt1*(x - coords[0].crpix1 + x*x*coords[0].polyterms[0][0] + x*y*coords[0].polyterms[1][0] + y*y*coords[0].polyterms[2][0]
+			  + x*x*x*coords[0].polyterms[3][0] + x*x*y*coords[0].polyterms[4][0] + x*y*y*coords[0].polyterms[5][0] + y*y*y*coords[0].polyterms[6][0]);
+    Y = coords[0].cdelt2*(y - coords[0].crpix2 + x*x*coords[0].polyterms[0][1] + x*y*coords[0].polyterms[1][1] + y*y*coords[0].polyterms[2][1]
+			  + x*x*x*coords[0].polyterms[3][1] + x*x*y*coords[0].polyterms[4][1] + x*y*y*coords[0].polyterms[5][1] + y*y*y*coords[0].polyterms[6][1]);
+  } else {
+# else
+  {
+# endif
+    X = coords[0].cdelt1*(x - coords[0].crpix1);
+    Y = coords[0].cdelt2*(y - coords[0].crpix2);
+  }    
+
+  L = (X*coords[0].pc1_1 + Y*coords[0].pc1_2);
+  M = (X*coords[0].pc2_1 + Y*coords[0].pc2_2);
+
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    R = hypot (L,M);
+    if ((L == 0) && (M == 0)) {
+      sphi = 0;
+      cphi = 1;
+    }
+    else {
+      sphi =  L / R;
+      cphi = -M / R;
+    }
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN")) {
+      if (R == 0) {
+	stht = 1.0;
+	ctht = 0.0;
+      }
+      else {
+	T = DEG_RAD / R;
+	stht =   T / sqrt ( 1.0 + T*T);
+	ctht = 1.0 / sqrt ( 1.0 + T*T);
+      }
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      ctht = RAD_DEG * R;
+      stht = sqrt (1 - ctht*ctht);
+    }
+
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    
+    sdel = stht*sdp - ctht*cphi*cdp;
+    salp = ctht*sphi;
+    calp = stht*cdp + ctht*cphi*sdp;
+    alpha = atan2 (salp, calp);
+    delta = asin (sdel);
+    
+    *ra  = DEG_RAD*alpha + coords[0].crval1;
+    *dec = DEG_RAD*delta;
+  }
+  if (!strcmp(&coords[0].ctype[4], "-LIN") || !strcmp(&coords[0].ctype[0], "GENE")) {
+    *ra  = L + coords[0].crval1;
+    *dec = M + coords[0].crval2;
+  }
+
+}
+
+
+fXY_to_RD (ra, dec, x, y, coords)
+float *ra, *dec;
+double  x, y;
+Coords coords[];
+{
+
+  double L, M, X, Y, T;
+  double R, sphi, cphi, stht, ctht;
+  double alpha, delta, salp, calp, sdel, sdp, cdp;
+  
+  *ra  = 0;
+  *dec = 0;
+
+  if (!strcmp(&coords[0].ctype[4], "-PLY")) {
+    X = coords[0].cdelt1*(x - coords[0].crpix1 + x*x*coords[0].polyterms[0][0] + x*y*coords[0].polyterms[1][0] + y*y*coords[0].polyterms[2][0]
+			  + x*x*x*coords[0].polyterms[3][0] + x*x*y*coords[0].polyterms[4][0] + x*y*y*coords[0].polyterms[5][0] + y*y*y*coords[0].polyterms[6][0]);
+    Y = coords[0].cdelt2*(y - coords[0].crpix2 + x*x*coords[0].polyterms[0][1] + x*y*coords[0].polyterms[1][1] + y*y*coords[0].polyterms[2][1]
+			  + x*x*x*coords[0].polyterms[3][1] + x*x*y*coords[0].polyterms[4][1] + x*y*y*coords[0].polyterms[5][1] + y*y*y*coords[0].polyterms[6][1]);
+  } else {
+    X = coords[0].cdelt1*(x - coords[0].crpix1);
+    Y = coords[0].cdelt2*(y - coords[0].crpix2);
+  }    
+  L = (X*coords[0].pc1_1 + Y*coords[0].pc1_2);
+  M = (X*coords[0].pc2_1 + Y*coords[0].pc2_2);
+
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    R = hypot (L,M);
+    if ((L == 0) && (M == 0)) {
+      sphi = 0;
+      cphi = 1;
+    }
+    else {
+      sphi =  L / R;
+      cphi = -M / R;
+    }
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") ) {
+      if (R == 0) {
+	stht = 1.0;
+	ctht = 0.0;
+      }
+      else {
+	T = DEG_RAD / R;
+	stht =   T / sqrt ( 1.0 + T*T);
+	ctht = 1.0 / sqrt ( 1.0 + T*T);
+      }
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      ctht = RAD_DEG * R;
+      stht = sqrt (1 - ctht*ctht);
+    }
+
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    
+    sdel = stht*sdp - ctht*cphi*cdp;
+    salp = ctht*sphi;
+    calp = stht*cdp + ctht*cphi*sdp;
+    alpha = atan2 (salp, calp);
+    delta = asin (sdel);
+    
+    *ra  = DEG_RAD*alpha + coords[0].crval1;
+    *dec = DEG_RAD*delta;
+  }
+  if (!strcmp(&coords[0].ctype[4], "-LIN") || !strcmp(&coords[0].ctype[0], "GENE")) {
+    *ra  = L + coords[0].crval1;
+    *dec = M + coords[0].crval2;
+  }
+
+}
+
+
+RD_to_XY (x, y, ra, dec, coords)
+double *x, *y;
+double  ra, dec;
+Coords coords[];
+{
+
+  double tmp_d;
+  double X, Y, sphi, cphi, stht;
+  double salp, calp, sdel, cdel, sdp, cdp;
+
+  if (!strcmp(&coords[0].ctype[4], "-PLY")) {
+    /* fprintf (stderr, "approximate to polynomial TAN plane fit\n");  */
+  }
+
+  *x = 0;
+  *y = 0;
+  if (!strcmp(&coords[0].ctype[0], "GENE") || !strcmp(&coords[0].ctype[4], "-LIN")) {
+    X = (ra  - coords[0].crval1);
+    Y = (dec - coords[0].crval2);
+  }
+  
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    salp = sin(RAD_DEG*(ra - coords[0].crval1));
+    calp = cos(RAD_DEG*(ra - coords[0].crval1));
+    sdel = sin(RAD_DEG*dec);
+    cdel = cos(RAD_DEG*dec);
+
+    stht = sdel*sdp + cdel*cdp*calp;  /* sin(theta) */
+    sphi = cdel*salp;  /* = cos(theta)*sin(phi) */
+    cphi = cdel*sdp*calp - sdel*cdp; /* = cos(theta)*cos(phi) */
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") ) {
+      X =  DEG_RAD * sphi / stht;
+      Y = -DEG_RAD * cphi / stht;
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      X =  DEG_RAD * sphi;
+      Y = -DEG_RAD * cphi;
+    }
+    X = X;
+    Y = Y;
+  }
+  
+  tmp_d = 1.0 / (coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1);
+  *x = tmp_d * (coords[0].pc2_2*X - coords[0].pc1_2*Y) / coords[0].cdelt1 + coords[0].crpix1;
+  *y = tmp_d * (coords[0].pc1_1*Y - coords[0].pc2_1*X) / coords[0].cdelt2 + coords[0].crpix2;
+ 
+}
+
+
+fRD_to_XY (x, y, ra, dec, coords)
+float *x, *y;
+double  ra, dec;
+Coords coords[];
+{
+
+  double tmp_d;
+  double X, Y, sphi, cphi, stht;
+  double salp, calp, sdel, cdel, sdp, cdp;
+
+  *x = 0;
+  *y = 0;
+  if (!strcmp(&coords[0].ctype[0], "GENE") || !strcmp(&coords[0].ctype[4], "-LIN")) {
+    X = (ra  - coords[0].crval1);
+    Y = (dec - coords[0].crval2);
+  }
+  
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    salp = sin(RAD_DEG*(ra - coords[0].crval1));
+    calp = cos(RAD_DEG*(ra - coords[0].crval1));
+    sdel = sin(RAD_DEG*dec);
+    cdel = cos(RAD_DEG*dec);
+
+    stht = sdel*sdp + cdel*cdp*calp;  /* sin(theta) */
+    sphi = cdel*salp;  /* = cos(theta)*sin(phi) */
+    cphi = cdel*sdp*calp - sdel*cdp; /* = cos(theta)*cos(phi) */
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") ) {
+      X =  DEG_RAD * sphi / stht;
+      Y = -DEG_RAD * cphi / stht;
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      X =  DEG_RAD * sphi;
+      Y = -DEG_RAD * cphi;
+    }
+    X = X;
+    Y = Y;
+  }
+  
+  tmp_d = 1.0 / (coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1);
+  *x = tmp_d * (coords[0].pc2_2*X - coords[0].pc1_2*Y) / coords[0].cdelt1 + coords[0].crpix1;
+  *y = tmp_d * (coords[0].pc1_1*Y - coords[0].pc2_1*X) / coords[0].cdelt2 + coords[0].crpix2;
+ 
+}
+
+
+
+GetCoords (coords, header) 
+Coords coords[];
+Header header[];
+{
+
+  int status;
+  double rotate;
+
+  rotate = 0.0;
+  coords[0].crval1 = coords[0].crpix1 = coords[0].cdelt1 = 0.0;
+  coords[0].crval2 = coords[0].crpix2 = coords[0].cdelt2 = 0.0;
+  coords[0].pc1_1 = coords[0].pc2_2 = 1.0;
+  coords[0].pc2_1 = coords[0].pc1_2 = 0.0;
+  strcpy (coords[0].ctype, "NONE");
+
+  status = TRUE; 
+  if (fits_scan (header, "CTYPE2", "%s", 1, coords[0].ctype)) {
+    status  = fits_scan (header, "CRVAL1", "%lf", 1, &coords[0].crval1);
+    status &= fits_scan (header, "CRPIX1", "%lf", 1, &coords[0].crpix1);
+    status &= fits_scan (header, "CRVAL2", "%lf", 1, &coords[0].crval2);  
+    status &= fits_scan (header, "CRPIX2", "%lf", 1, &coords[0].crpix2);
+    if (fits_scan (header, "CDELT1", "%lf", 1, &coords[0].cdelt1)) {
+      status &= fits_scan (header, "CDELT2", "%lf", 1, &coords[0].cdelt2);
+      if (fits_scan (header, "CROTA2", "%lf", 1, &rotate)) {
+	coords[0].pc1_1 =  cos(rotate*RAD_DEG);
+	coords[0].pc1_2 = -sin(rotate*RAD_DEG);
+	coords[0].pc2_1 =  sin(rotate*RAD_DEG);
+	coords[0].pc2_2 =  cos(rotate*RAD_DEG);
+      }
+      if (fits_scan (header, "PC001001", "%lf", 1, &coords[0].pc1_1)) {
+	status &= fits_scan (header, "PC001002", "%lf", 1, &coords[0].pc1_2);
+	status &= fits_scan (header, "PC002001", "%lf", 1, &coords[0].pc2_1);
+	status &= fits_scan (header, "PC002002", "%lf", 1, &coords[0].pc2_2);
+      }
+    }
+    else {
+      if (fits_scan (header, "CD1_1", "%lf", 1, &coords[0].pc1_1)) {
+	status &= fits_scan (header, "CD1_2", "%lf", 1, &coords[0].pc1_2);
+	status &= fits_scan (header, "CD2_1", "%lf", 1, &coords[0].pc2_1);
+	status &= fits_scan (header, "CD2_2", "%lf", 1, &coords[0].pc2_2);
+	coords[0].cdelt1 = coords[0].cdelt2 = 1.0;
+      }
+      else {
+	status = FALSE;
+      }
+    }
+  }
+  else {
+    if (fits_scan (header, "RA_O", "%lf", 1, &coords[0].crval1)) {
+      status  = fits_scan (header, "RA_X", "%lf", 1, &coords[0].pc1_1);
+      status &= fits_scan (header, "RA_Y", "%lf", 1, &coords[0].pc1_2);
+      status &= fits_scan (header, "DEC_O", "%lf", 1, &coords[0].crval2);  
+      status &= fits_scan (header, "DEC_X", "%lf", 1, &coords[0].pc2_1);
+      status &= fits_scan (header, "DEC_Y", "%lf", 1, &coords[0].pc2_2);
+      coords[0].crpix1 = coords[0].crpix2 = 0.0;
+      coords[0].cdelt1 = coords[0].cdelt2 = 1.0;
+      strcpy (coords[0].ctype, "GENE");
+    }
+  }
+  if (!status) {
+    fprintf (stderr, "error getting all elements for coordinate mode %d\n", coords[0].ctype);
+    coords[0].crval1 = coords[0].crpix1 = coords[0].cdelt1 = 0.0;
+    coords[0].crval2 = coords[0].crpix2 = coords[0].cdelt2 = 0.0;
+    coords[0].pc1_1 = coords[0].pc2_2 = 1.0;
+    coords[0].pc2_1 = coords[0].pc1_2 = 0.0;
+    strcpy (coords[0].ctype, "NONE");
+  }
+}
+
+
+  /* -PLY projection is an extrapolation of the -TAN projection. 
+     In addition to the usual linear terms of CRPIXi, PC00i00j, there are 
+     higher order polynomial terms (up to 3rd order):
+     Axis 1 terms:
+     PCA1X2Y0 = coords.polyterm[0][0] = x^2                                             
+     PCA1X1Y1 = coords.polyterm[1][0] = xy                                          
+     PCA1X0Y2 = coords.polyterm[2][0] = y^2                                             
+     PCA1X3Y0 = coords.polyterm[3][0] = x^3                                             
+     PCA1X2Y1 = coords.polyterm[4][0] = x^2 y                                             
+     PCA1X1Y2 = coords.polyterm[5][0] = x y^2                                             
+     PCA1X0Y3 = coords.polyterm[6][0] = y^2                                              
+     Axis 2 terms:
+     PCA2X2Y0 = coords.polyterm[0][1] = x^2                                               
+     PCA2X1Y1 = coords.polyterm[1][1] = xy                                                
+     PCA2X0Y2 = coords.polyterm[2][1] = y^2                                               
+     PCA2X3Y0 = coords.polyterm[3][1] = x^3                                               
+     PCA2X2Y1 = coords.polyterm[4][1] = x^2 y                                             
+     PCA2X1Y2 = coords.polyterm[5][1] = x y^2                                             
+     PCA2X0Y3 = coords.polyterm[6][1] = y^2                                               
+  */
Index: /tags/start/Ohana/src/getstar/src/find_matches.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/find_matches.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/find_matches.c	(revision 12606)
@@ -0,0 +1,57 @@
+# include "getstar.h"
+
+Stars *find_matches (Catalog *catalog, Image *image, int start, int end, Stars *stars, int *Nstar) {
+
+  int i, n, N, NSTARS;
+  int photcode;
+
+  if (stars == (Stars *) NULL) {
+    N = 0;
+    NSTARS = 1000;
+    ALLOCATE (stars, Stars, NSTARS);
+  } else {
+    N = *Nstar;
+    NSTARS = N + 1000;
+    REALLOCATE (stars, Stars, NSTARS);
+  }    
+
+  /* identify selection criteria */
+  photcode = -1;
+  if ((start == 0) && (end == 0)) {
+    start = image[0].tzero;
+    end   = image[0].tzero + 1e-4*image[0].NY*image[0].trate;  /* trate is in 0.1 msec / row */
+    photcode = image[0].source;
+  }
+  if (VERBOSE) fprintf (stderr, "extracting for range %d to %d (photcode %s)\n", start, end, photcode);
+
+  for (i = 0; (i < catalog[0].Nmeasure); i++) {
+    if ((i % 10000) == 0) fprintf (stderr, ". ");
+    if ((catalog[0].measure[i].t >= start) && (catalog[0].measure[i].t <= end) && (photcode == catalog[0].measure[i].source)) { 
+      n = catalog[0].measure[i].averef;
+      stars[N].R      = catalog[0].average[n].R - catalog[0].measure[i].dR / 360000.0;
+      stars[N].D      = catalog[0].average[n].D - catalog[0].measure[i].dD / 360000.0;
+
+      stars[N].M      = 0.001*(catalog[0].measure[i].M - catalog[0].measure[i].dt);
+      stars[N].dM     = catalog[0].measure[i].dM;
+      stars[N].dophot = catalog[0].measure[i].dophot;  
+
+      stars[N].Mgal   = 0.001*(catalog[0].measure[i].Mgal - catalog[0].measure[i].dt);
+
+      stars[N].fx     = 0.01*catalog[0].measure[i].FWx;
+      stars[N].fy     = stars[N].fx * 0.01*catalog[0].measure[i].fwy;
+      stars[N].df     = (360.0/255.0)*catalog[0].measure[i].theta;
+      stars[N].found  = catalog[0].measure[i].flags;
+
+      N ++;
+      if (N == NSTARS) {
+	NSTARS += 1000;
+	REALLOCATE (stars, Stars, NSTARS);
+      }    
+
+    } 
+  }
+  fprintf (stderr, "found %d meas\n", N);
+  *Nstar = N;
+  return (stars);
+}
+
Index: /tags/start/Ohana/src/getstar/src/gcatalog.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/gcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/gcatalog.c	(revision 12606)
@@ -0,0 +1,45 @@
+# include "getstar.h"
+
+int gcatalog (Catalog *catalog) {
+  
+  int Nsecfilt;
+  char mode;
+
+  /* read catalog header */
+  mode = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+  if (!load_catalog (catalog, mode, VERBOSE)) {
+    fprintf (stderr, "ERROR: failure loading catalog\n");
+    exit (1);
+  }
+
+  /* check Nsecfile value, update if needed */
+  Nsecfilt = GetPhotcodeNsecfilt ();
+  if (catalog[0].Nsecfilt < Nsecfilt) {
+
+    int i, j, Nextra, in, out;
+    SecFilt *insec, *outsec;
+
+    Nextra = Nsecfilt - catalog[0].Nsecfilt;
+    insec = catalog[0].secfilt;
+    ALLOCATE (outsec, SecFilt, catalog[0].Naverage * Nsecfilt);
+    for (in = out = i = 0; i < catalog[0].Naverage; i++) {
+      for (j = 0; j < catalog[0].Nsecfilt; j++, in++, out++) {
+	outsec[out].M = insec[in].M;
+	outsec[out].Xm = insec[in].Xm;
+      }
+      for (j = 0; j < Nextra; j++, out++) {
+	outsec[out].M = NO_MAG;
+	outsec[out].Xm = NO_MAG;
+      }
+    }
+    free (catalog[0].secfilt);
+    catalog[0].secfilt = outsec;
+    catalog[0].Nsecfilt = Nsecfilt;
+  }
+
+  if (catalog[0].Nsecfilt > Nsecfilt) {
+    fprintf (stderr, "ERROR: can't reduce number of secondary filters\n");
+    exit (1);
+  }
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/getstar/src/getstar.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/getstar.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/getstar.c	(revision 12606)
@@ -0,0 +1,49 @@
+# include "getstar.h"
+
+main (int argc, char **argv) {
+
+  int i, Nstars, Nregions;
+  Image *image, *gimages(), *gtimes(), *find_images();
+  Catalog catalog;
+  GSCRegion *region, *tregion, *gregions();
+  Stars *stars;
+  
+  args (argc, argv);
+
+  image = gimages (argv[1]);
+
+  region = gregions (&image[0], &Nregions);
+
+  stars = (Stars *) NULL;
+  Nstars = 0;
+
+  for (i = 0; i < Nregions; i++) {
+    if (VERBOSE) fprintf (stderr, "extracting from %s\n", region[i].filename);
+    catalog.filename = region[i].filename;  /* don't free region before catalog! */
+    switch (lock_catalog (&catalog, LCK_SOFT)) {
+    case 0:
+      fprintf (stderr, "ERROR: can't lock file\n");
+      exit (1);
+    case 1:
+      gcatalog (&catalog);
+      break;
+    case 2:
+      fprintf (stderr, "no data in %s, skipping\n", catalog.filename);
+      catalog.Naverage = 0;
+      catalog.Nmeasure = 0;
+      break;
+    default:
+      fprintf (stderr, "weird lock_catalog exit state\n");
+      exit (1);
+    }
+    unlock_catalog (&catalog);
+    stars = find_matches (&catalog, &image[0], 0, 0, stars, &Nstars);
+  }
+
+  /* write out the selected stars */
+  clean_stars (stars, &Nstars, image);
+  wstars (argv[2], stars, Nstars, image);
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+
+}
Index: /tags/start/Ohana/src/getstar/src/gimages.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/gimages.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/gimages.c	(revision 12606)
@@ -0,0 +1,63 @@
+# include "getstar.h"
+
+Image *gimages (char *filename) {
+  
+  int i, size, Nimage, nimage;
+  double zeropt;
+  struct stat filestatus;
+  FILE *f;
+  Image *timage, *image;
+  Header header;
+  
+  f = fopen (ImageCat, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "error opening image cat %s\n", ImageCat);
+    exit (1);
+  }
+
+  /* read header */
+  if (!fits_load_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "ERROR: can't read image catalog %s\n", ImageCat);
+    exit (1);
+  }
+
+  fits_scan (&header, "ZERO_PT", "%lf", 1, &zeropt);
+  if (fabs (ZeroPt - zeropt) > 1e-4) {
+    fprintf (stderr, "ERROR: zero point in image table (%f:%s) inconsistent with zero point in image header (%f:%s)\n",
+	     zeropt, ImageCat, ZeroPt, filename);
+    exit (1);
+  }
+
+  /* advance to data segment */ 
+  fseek (f, header.size, SEEK_SET); 
+
+  Nimage = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+  /* check that file size makes sense */
+  if (stat (ImageCat, &filestatus) == -1) {
+    fprintf (stderr, "ERROR: failed to get status of image catalog\n");
+    exit (1);
+  }
+  size = Nimage*sizeof(Image) + header.size;
+  if (size != filestatus.st_size) {
+    fprintf (stderr, "ERROR: image catalog has inconsistent size\n");
+    exit (1);
+  } 
+
+  ALLOCATE (timage, Image, Nimage);
+  nimage = Fread (timage, sizeof(Image), Nimage, f, "image");
+  if (nimage != Nimage) {
+    fprintf (stderr, "error reading images from table\n");
+    exit (1);
+  }
+
+  ALLOCATE (image, Image, 1);
+  for (i = 0; i < Nimage; i++) {
+    if (strcmp (timage[i].name, filename)) continue;
+    memcpy (image, &timage[i], sizeof(Image));
+    return (image);
+  }
+
+  fprintf (stderr, "error: failed to find desired image\n");
+  exit (1);
+}
Index: /tags/start/Ohana/src/getstar/src/gregions.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/gregions.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/gregions.c	(revision 12606)
@@ -0,0 +1,56 @@
+# include "getstar.h"
+
+GSCRegion *gregions (image, Nregions)
+Image *image;
+int *Nregions;
+{
+  
+  GSCRegion *region;
+  FILE *f;
+  double x, y;
+  double dr, dd, dec, ra;
+  int i, j, done, nregion, NREGION;
+  
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find GSC region file %s\n", GSCFILE);
+    exit (1);
+  }
+  
+  /* find regions at image corners */
+  NREGION = 10;
+  ALLOCATE (region, GSCRegion, NREGION);
+  nregion = 0;
+
+  /* look for new regions on grid across image */ 
+  for (x = 0.0; x <= 1.0; x+=0.25) {
+    for (y = 0.0; y <= 1.0; y+=0.25) {
+      XY_to_RD (&ra, &dec, image[0].NX*(1.1*x - 0.05), image[0].NY*(1.1*y - 0.05), &image[0].coords);
+      aregion (&region[nregion], f, ra, dec);
+      done = FALSE;
+      for (j = 0; (j < nregion) && !done; j++) {
+	if (!strcmp (region[nregion].filename, region[j].filename)) {
+	  nregion --;
+	  done = TRUE;
+	}
+      }
+      nregion ++;
+      if (nregion == NREGION) {
+	NREGION += 10;
+	REALLOCATE (region, GSCRegion, NREGION);
+      }
+    }
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "found %d region files:\n", nregion);
+    for (i = 0; i < nregion; i++) {
+      fprintf (stderr, "  %d %s\n", i, region[i].filename);
+    }
+  }
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (region);
+  
+}
Index: /tags/start/Ohana/src/getstar/src/gstars.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/gstars.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/gstars.c	(revision 12606)
@@ -0,0 +1,276 @@
+# include "addstar.h"
+# define D_NSTARS 1000
+# define BYTES_STAR 66
+# define BLOCK 1000
+#include <sys/time.h>
+#include <time.h>
+
+Stars *gstars (file, NSTARS, image) 
+char file[];
+int *NSTARS;
+Image *image;
+{
+
+  FILE *f;
+  Header header;
+  int j, N, Ninstar;
+  int nbytes, Nbytes;
+  Stars *stars;
+  char *buffer, *c, *c2, photcode[64];
+  double tmp;
+  int done, doneread, Nskip, Nextra, itmp;
+  unsigned short int Nc;
+
+  if (!fits_read_header (file, &header)) {
+    fprintf (stderr, "ERROR: can't read header for %s\n", file);
+    exit (1);
+  }
+
+  /* open file */
+  f = fopen (file, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't read data from %s\n", file);
+    exit (1);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* find image rootname */
+  c = strrchr (file, 0x2f);
+  if (c == (char *) NULL) {
+    strcpy (image[0].name, file);
+  } else { 
+    strcpy (image[0].name, (c+1));
+  }
+
+  /* get astrometry information */
+  if (!GetCoords (&image[0].coords, &header)) {
+    fprintf (stderr, "ERROR: no astrometric solution in header\n");
+    exit (1);
+  }
+  while (image[0].coords.crval1 < 0) image[0].coords.crval1 += 360.0;
+  while (image[0].coords.crval1 > 360.0) image[0].coords.crval1 -= 360.0;
+  itmp = 0;
+  fits_scan (&header, "NASTRO",   "%d", 1, &itmp);
+  if ((itmp == 0) && !ACCEPT_ASTROM) {
+    fprintf (stderr, "ERROR: bad astrometric solution in header\n");
+    exit (1);
+  }
+    
+  /* CERROR in data file is in arcsec */
+  if (!fits_scan (&header, "CERROR",   "%lf", 1, &tmp)) tmp = 1.0;
+  image[0].cerror = tmp * 50.0;
+  fits_scan (&header, "NAXIS1",   "%hd", 1, &image[0].NX); 
+  fits_scan (&header, "NAXIS2",   "%hd", 1, &image[0].NY);
+ 
+  /* get photcode from header */
+  if (thiscode == NULL) {
+    fits_scan (&header, "PHOTCODE", "%s", 1, photcode);
+    thiscode = GetPhotcodebyName (photcode);
+  }
+  if (thiscode == NULL) {
+    fprintf (stderr, "ERROR: photcode %s not found in photcode table\n", photcode);
+    exit (1);
+  }
+  image[0].source = thiscode[0].code;
+
+  image[0].NX -= XOVERSCAN;
+  image[0].NY -= YOVERSCAN;
+  fits_scan (&header, ExptimeKeyword,  "%lf", 1, &tmp);
+  image[0].exptime = tmp;
+  
+  tmp = 0;
+  /* fits_scan (&header, "APMIFIT",  "%lf", 1, &tmp); */
+  image[0].apmifit = tmp * 1000.0;
+
+  tmp = 0;
+  /* fits_scan (&header, "dAPMIFIT", "%lf", 1, &tmp); */
+  image[0].dapmifit = tmp * 1000.0;
+
+  tmp = 0;
+  fits_scan (&header, "FLIMIT",   "%lf", 1, &tmp);
+  image[0].detection_limit = tmp * 10.0;
+
+  tmp = 0;
+  fits_scan (&header, "FSATUR",   "%lf", 1, &tmp);
+  image[0].saturation_limit = tmp * 10.0;
+
+  tmp = 0;
+  fits_scan (&header, "FWHM_X",   "%lf", 1, &tmp);
+  image[0].fwhm_x = tmp * 25.0 * image[0].coords.cdelt1 * 3600.0;
+
+  tmp = 0;
+  fits_scan (&header, "FWHM_Y",   "%lf", 1, &tmp);
+  image[0].fwhm_y = tmp * 25.0 * image[0].coords.cdelt1 * 3600.0;
+
+  if (!fits_scan (&header, "TZERO",   "%d",  1, &image[0].tzero)) {
+    image[0].tzero = parse_time (&header);
+  }
+
+  tmp = 0;
+  fits_scan (&header, "TRATE",   "%lf", 1, &tmp);
+  image[0].trate = 10000 * tmp;
+
+  tmp = 0;
+  fits_scan (&header, AirmassKeyword, "%lf", 1, &tmp);
+  image[0].secz = MIN (NO_MAG, 1000*tmp);
+
+  if (!fits_scan (&header, CCDNumKeyword, "%d", 1, &itmp)) {
+    image[0].ccdnum = 0xff;
+  } else {
+    image[0].ccdnum = itmp;
+  }
+
+  fits_scan (&header, "ZERO_PT", "%lf", 1, &ZeroPt);
+
+  /* secz is in units milli-airmass */
+  image[0].Mcal = 0.0;
+  image[0].code = 0;
+  image[0].Xm   = NO_MAG;
+  bzero (image[0].dummy, sizeof(image[0].dummy));
+
+  /* find expected number of stars */
+  fits_scan (&header, "NSTARS", "%d", 1, &image[0].nstar);
+  if (image[0].nstar == 0) {
+    fprintf (stderr, "ERROR: can't get NSTARS from header\n");
+    exit (1);
+  }
+  ALLOCATE (stars, Stars, image[0].nstar);
+
+  /* load in stars by blocks of 1000 */
+  N = 0;
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR) + 1);
+  buffer[BLOCK*BYTES_STAR] = 0;
+  Nextra = 0;
+  doneread = FALSE;
+  while (!doneread) {
+    Nbytes = BYTES_STAR * BLOCK - Nextra;
+    nbytes = Fread (&buffer[Nextra], 1, Nbytes, f, "char");
+    if (nbytes == 0) {
+      doneread = TRUE;
+      continue;
+    }
+    nbytes += Nextra;
+    /* check line-by-line integrity */
+    c = buffer;
+    done = FALSE;
+    while ((c < buffer + nbytes) && (!done)) { 
+      for (c2 = c; *c2 == '\n'; c2++);
+      if (c2 > c) { /* extra return chars */
+	memmove (c, c2, (int)(buffer + nbytes - c2));
+	Nskip = c2 - c;
+	nbytes -= Nskip;
+	bzero (buffer + nbytes, Nskip);
+	if (VERBOSE) fprintf (stderr, "deleted %d extra return chars\n", Nskip);
+      }
+      c2 = strchr (c, '\n');
+      if (c2 == (char *) NULL) {
+	done = TRUE;	
+	continue;
+      }
+      c2++;
+      if ((c2 - c) != BYTES_STAR) { /* bad line, delete it */
+	memmove (c, c2, (int)(buffer + nbytes - c2));
+	Nskip = c2 - c;
+	nbytes -= Nskip;
+	bzero (buffer + nbytes, Nskip);
+	if (VERBOSE) fprintf (stderr, "deleted line, %d extra chars\n", Nskip);
+      } else {
+	c = c2;
+      }
+    }
+    Ninstar = nbytes / BYTES_STAR;
+    Nextra = nbytes % BYTES_STAR;
+    for (j = 0; j < Ninstar; j++, N++) {
+      dparse (&stars[N].X,  1, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].Y,  2, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].M,  3, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].dM, 4, &buffer[j*BYTES_STAR]);
+      /* allow for some dynamic filtering of star list */
+      if (stars[N].dM > 1000.0 / SNLIMIT) { N--; continue; }
+      if (XMAX && (stars[N].X > XMAX))    { N--; continue; }
+      if (XMIN && (stars[N].X < XMIN))    { N--; continue; }
+      if (YMAX && (stars[N].Y > YMAX))    { N--; continue; }
+      if (YMIN && (stars[N].Y < YMIN))    { N--; continue; }
+
+      dparse (&tmp,         5, &buffer[j*BYTES_STAR]);
+      stars[N].dophot = tmp;
+      dparse (&stars[N].Mgal, 7, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].Map,  8, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].fx,   9, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].fy,  10, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].df,  11, &buffer[j*BYTES_STAR]);
+
+      XY_to_RD (&stars[N].R, &stars[N].D, stars[N].X, stars[N].Y, &image[0].coords);
+      while (stars[N].R < 0.0) stars[N].R += 360.0;
+      while (stars[N].R >= 360.0) stars[N].R -= 360.0;
+      stars[N].found = -1;
+    }
+  }
+
+  image[0].nstar = N;
+  REALLOCATE (stars, Stars, image[0].nstar);
+  if (VERBOSE) fprintf (stderr, "read %d stars from target file\n", image[0].nstar);
+  *NSTARS = image[0].nstar;
+
+  return (stars);
+}
+
+
+
+
+# if (0)
+  /* left over fraction of a block */
+  nbytes = Fread (buffer, 1, (Nbytes % (BLOCK*BYTES_STAR)), f, "char");
+  if (nbytes != (Nbytes % (BLOCK*BYTES_STAR))) {
+    fprintf (stderr, "ERROR: failed to read in stars (2)\n");
+    exit (1);
+  }
+  /* check line-by-line integrity */
+  Nnew = 0;
+  c = buffer;
+  done = FALSE;
+  while ((c < buffer + nbytes) && (!done)) { 
+    for (c2 = c; *c2 == '\n'; c2++);
+    if (c2 > c) { /* extra return chars */
+      memmove (c, c2, (int)(buffer + nbytes - c2));
+      Nnew += c2 - c;
+      fprintf (stderr, "deleting %d extra return chars\n", (int)(c2-c));
+    }
+    c2 = strchr (c, '\n');
+    if (c2 == (char *) NULL) {
+      if (Nnew > 0) {
+	nnew = Fread (&buffer[nbytes-Nnew], 1, Nnew, f, "char");
+	if (nnew != Nnew) {
+	  fprintf (stderr, "ERROR: failed to read in stars (1)\n");
+	  exit (1);
+	}
+      } else {
+	done = TRUE;	
+      }
+      continue;
+    }
+    c2++;
+    if ((c2 - c) != BYTES_STAR) {
+      /* this is a bad line, delete it, adjust data in buffer, 
+	 and be ready to read the rest of the last line */
+      memmove (c, c2, (int)(buffer + nbytes - c2));
+      Nnew += c2 - c;
+      fprintf (stderr, "deleting bad line with %d chars\n", (int)(c2-c));
+    } else {
+      c = c2;
+    }
+  }
+  for (j = 0; j < nbytes / BYTES_STAR; j++, nstar++, N++) {
+    dparse (&stars[N].X, 1, &buffer[j*BYTES_STAR]);
+    dparse (&stars[N].Y, 2, &buffer[j*BYTES_STAR]);
+    dparse (&stars[N].M, 3, &buffer[j*BYTES_STAR]);
+    dparse (&stars[N].dM, 4, &buffer[j*BYTES_STAR]);
+    XY_to_RD (&stars[N].R, &stars[N].D, stars[N].X, stars[N].Y, &image[0].coords);
+    while (stars[N].R < 0.0) stars[N].R += 360.0;
+    while (stars[N].R >= 360.0) stars[N].R -= 360.0;
+    dparse (&tmp, 5, &buffer[j*BYTES_STAR]);
+    stars[N].dophot = tmp;
+    stars[N].found = -1;
+  }
+
+# endif
Index: /tags/start/Ohana/src/getstar/src/misc.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/misc.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/misc.c	(revision 12606)
@@ -0,0 +1,398 @@
+# include "getstar.h"
+
+/***** convert [-]00:00:00 to 0.0000 ****/
+int dms_to_ddd (double *Value, char *string) {
+  
+  int valid, neg, status;
+  double tmp, value;
+  char *p1, *p2, *px;
+
+  valid = FALSE; 
+  neg = FALSE;
+  stripwhite (string);
+  p1 = string;
+  px = string + strlen(string);
+
+  if (string[0] == '-') { 
+    valid = TRUE; 
+    neg = TRUE;
+    p1 = &string[1];
+  }
+  if (string[0] == '+') { 
+    valid = TRUE; 
+    neg = FALSE;
+    p1 = &string[1];
+  }
+  if (isdigit(string[0])) { 
+    valid = TRUE;
+    p1 = &string[0];
+  }
+  if (!valid) { return (FALSE); }
+
+  status = 1;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) return (FALSE); /* entry not a number: +fred */
+  value = tmp;
+  if (p2 == px) goto escape;    /* entry only number: +1.0 */ 
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:fred */
+  status = 2;
+  value += tmp / 60.0;
+  if (p2 == px) goto escape;    /* entry only number: +1:1 */
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:1:fred */
+  value += tmp / 3600.0;
+
+ escape:
+  if (neg) {
+    value *= -1;
+  }
+  *Value = value;
+
+  return (status);
+}
+
+/**********/
+int str_to_radec (double *ra, double *dec, char *str1, char *str2) {
+
+  double Ra, Dec;
+
+  *ra = *dec = 0;
+  switch (dms_to_ddd (&Ra, str1)) {
+  case 0:
+    fprintf (stderr, "syntax error in RA\n");
+    return (FALSE);
+  case 1:
+    break;
+  case 2:
+    Ra = Ra * 15;
+    break;
+  }
+  switch (dms_to_ddd (&Dec, str2)) {
+  case 0:
+    fprintf (stderr, "syntax error in DEC\n");
+    return (FALSE);
+  case 1:
+  case 2:
+    break;
+  }
+  *ra = Ra;
+  *dec = Dec;
+  return (TRUE);
+}
+
+# define FORMAT_DAYS    1
+# define FORMAT_HOURS   2
+# define FORMAT_MINUTES 3
+# define FORMAT_SECONDS 4
+# define FORMAT_JD      5
+# define FORMAT_DATE    6
+
+/**********/
+int chk_time (char *line) {
+
+  char *p1, *p2;
+  double tmp;
+  int mode;
+
+  p1 = line;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1 + strlen (p1) - 1) {
+    if (*p2 == 'd') {
+      mode = FORMAT_DAYS;
+    }
+    if (*p2 == 'h') {
+      mode = FORMAT_HOURS;
+    }
+    if (*p2 == 'm') {
+      mode = FORMAT_MINUTES;
+    }
+    if (*p2 == 's') {
+      mode = FORMAT_SECONDS;
+    }
+    if (*p2 == 'j') {
+      mode = FORMAT_JD;
+    }
+  } else { 
+    mode = FORMAT_DATE;
+  }
+  return (mode);
+}
+
+/**********/
+int str_to_time (char *line, unsigned int *second) {
+  
+  char *tmpline;
+  struct tm *gmt;
+  struct timeval now;
+  double jd;
+  unsigned long tsec;
+
+  if (!strcasecmp (line, "NOW")) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    *second = now.tv_sec;
+    return (TRUE);
+  }
+    
+  if (!strncasecmp (line, "TODAY", 5)) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    if (line[5]) { /* line has extra data (ie, hh:mm:ss) */
+      tsec = now.tv_sec;
+      ALLOCATE (tmpline, char, 64);
+      gmt   = gmtime (&tsec);
+      sprintf (tmpline, "%04d/%02d/%02d,%s", 
+	       1900 + gmt[0].tm_year, gmt[0].tm_mon+1, gmt[0].tm_mday, &line[6]);
+      *second = date_to_sec (tmpline);
+      free (tmpline);
+      return (TRUE);
+    } else {
+      *second = 86400 * ((int)(now.tv_sec / 86400));
+      return (TRUE); 
+    }
+  }
+    
+  switch (chk_time (line)) {
+  case 0:
+    return (FALSE);
+  case FORMAT_DAYS:
+    *second = strtod (line, 0) * 86400.0;
+    return (TRUE);
+  case FORMAT_HOURS:
+    *second = strtod (line, 0) * 3600.0;
+    return (TRUE);
+  case FORMAT_MINUTES:
+    *second = strtod (line, 0) * 60.0;
+    return (TRUE);
+  case FORMAT_SECONDS:
+    *second = strtod (line, 0);
+    return (TRUE);
+  case FORMAT_JD:
+    jd = strtod (line, 0);
+    *second = jd_to_sec (jd);
+    return (TRUE);
+  case FORMAT_DATE:
+    *second = date_to_sec (line);
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+
+/**********/
+int str_to_dtime (char *line, double *second) {
+  
+  switch (chk_time (line)) {
+  case 0:
+  case FORMAT_JD:
+  case FORMAT_DATE:
+    return (FALSE);
+  case FORMAT_DAYS:
+    *second = strtod (line, 0) * 86400.0;
+    return (TRUE);
+  case FORMAT_HOURS:
+    *second = strtod (line, 0) * 3600.0;
+    return (TRUE);
+  case FORMAT_MINUTES:
+    *second = strtod (line, 0) * 60.0;
+    return (TRUE);
+  case FORMAT_SECONDS:
+    *second = strtod (line, 0);
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+/**********/
+double sec_to_jd (unsigned long second) {
+
+  double jd;
+  
+  jd = second/86400.0 + 2440587.5;
+  return (jd);
+}
+
+/**********/
+unsigned long int jd_to_sec (double jd) {
+
+  unsigned long int second;
+
+  second = (jd - 2440587.5)*86400;
+  return (second);
+}
+
+/**********/
+char *sec_to_date (unsigned long second) {
+  
+  struct tm *gmt;
+  char *line;
+  
+  ALLOCATE (line, char, 64);
+  gmt   = gmtime (&second);
+  sprintf (line, "%04d/%02d/%02d,%02d:%02d:%02d", 
+	   1900 + gmt[0].tm_year, gmt[0].tm_mon+1, gmt[0].tm_mday, 
+	   gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+  return (line);
+
+}
+
+/***** date in format yyyy/mm/dd,hh:mm:ss *****/
+unsigned long date_to_sec (char *date) {
+  
+  unsigned long second;
+  double tmp, jd;
+  struct tm now;
+  char *p1, *p2, *px;
+  
+  p1 = date;
+  px = date + strlen(date);
+  bzero (&now, sizeof(now));
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_year = tmp;
+  if (now.tm_year > 1000) now.tm_year -= 1900;
+  if (now.tm_year <   50) now.tm_year += 100;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mon = tmp - 1; /* mon runs from 0 - 11 */
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mday = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  p1 = p2 + 1;
+  now.tm_hour = tmp;
+  if (p2 == px) goto escape;  
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_min = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_sec = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+ escape:
+  jd = now.tm_mday - 32075 + (int)(1461*(1900 + now.tm_year + 4800 + (int)(((now.tm_mon+1)-14)/12))/4)
+    + (int)(367*((now.tm_mon+1) - 2 - (int)(((now.tm_mon+1) - 14)/12)*12)/12)
+    - (int)(3*(int)((1900 + now.tm_year + 4900 + (int)(((now.tm_mon+1) - 14)/12))/100)/4) - 0.5;
+  
+  second = (jd - 2440587.5)*86400 + 3600.0*now.tm_hour + now.tm_min*60.0 + now.tm_sec;
+
+  return (second);
+}
+
+
+
+/* times may be in forms as:
+   20040200450s (N seconds since 1970.0)
+   2440900.232j (julian date)
+   99/02/23,03:22:18 (date string)
+   (separators may be anything except space, +, -)
+   99:02:15:12:23:30
+   99:02:15:12h23m30s
+   */
+
+
+int GetTimeFormat (unsigned int *TimeReference, int *TimeFormat) {
+
+  char *p;
+
+  *TimeReference = 0;
+  if ((p = get_variable ("TIMEREF")) != (char *) NULL) {
+    if (!str_to_time (p, TimeReference)) {
+      fprintf (stderr, "error in TIME_REF format\n");
+      return (FALSE);
+    }
+    free (p);
+  }
+  *TimeFormat = FALSE;
+  if ((p = get_variable ("TIMEFORMAT")) != (char *) NULL) {
+    if (!strcasecmp (p, "date")) *TimeFormat   = TIME_DATE;
+    if (!strcasecmp (p, "hours")) *TimeFormat  = TIME_HOURS;
+    if (!strcasecmp (p, "days")) *TimeFormat   = TIME_DAYS;
+    if (!strcasecmp (p, "JD")) *TimeFormat     = TIME_JD;
+    if (!strcasecmp (p, "MJD")) *TimeFormat    = TIME_MJD;
+    if (!strcasecmp (p, "sec")) *TimeFormat    = TIME_SEC;
+    if (!*TimeFormat) fprintf (stderr, "unknown TIME_FORMAT\n");
+    free (p);
+    return (FALSE);
+  }
+  if (!*TimeFormat) *TimeFormat = TIME_SEC;
+  return (TRUE);
+}
+  
+/* convert UNIX time to a value referenced to the TimeReference in the given unit */
+double TimeValue (unsigned int time, unsigned int TimeReference, int TimeFormat) {
+
+  double value, dt;
+
+  dt = (time > TimeReference) ? (time - TimeReference) : -1 * (double)(TimeReference - time);
+  switch (TimeFormat) {
+  case TIME_HOURS:
+    value = dt / 3600.0;
+    break;
+  case TIME_DAYS:
+    value = dt / 86400.0;
+    break;
+  case TIME_JD:
+    value = time / 86400.0 + 2440587.5;
+    break;
+  case TIME_MJD:
+    value = time / 86400.0 + 40587.0;
+    break;
+  case TIME_SEC:
+  default:
+    value = dt;
+    break;
+  }
+  return (value);
+}
+  
+/* convert time value referenced to the TimeReference in the given unit to UNIX time */
+unsigned int TimeRef (double value, unsigned int TimeReference, int TimeFormat) {
+
+  int dt;
+  unsigned int time;
+
+  switch (TimeFormat) {
+  case TIME_HOURS:
+    dt = value * 3600.0;
+    break;
+  case TIME_DAYS:
+    dt = value * 86400.0;
+    break;
+  case TIME_JD:
+    time = (value -  2440587.5) * 86400.0;
+    return (time);
+    break;
+  case TIME_MJD:
+    time = (value -  40587.0) * 86400.0;
+    return (time);
+    break;
+  case TIME_SEC:
+  default:
+    dt = value;
+    break;
+  }
+
+  time = TimeReference + dt;
+  return (time);
+}
Index: /tags/start/Ohana/src/getstar/src/mkcatalog.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/mkcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/mkcatalog.c	(revision 12606)
@@ -0,0 +1,42 @@
+# include "addstar.h"
+# include <time.h>
+
+mkcatalog (GSCRegion *region, Catalog *catalog) {
+  
+  char filename[64], line[64];
+  int i, Nmeas, Nmiss;
+  struct tm *local;
+  struct timeval now;
+  char mode;
+  int status, Nextra, in, out, j;
+  SecFilt *insec, *outsec;
+
+  if (VERBOSE) fprintf (stderr, "new catalog file: %s\n", region[0].filename);
+  if (!fits_read_header (CatTemplate, &catalog[0].header)) {
+    fprintf (stderr, "ERROR: can't find template header %s\n", CatTemplate);
+    exit (1);
+  }
+  
+  /* assign header values for RA, DEC, DATE, etc */
+  fits_modify (&catalog[0].header, "RA0", "%lf", 1, region[0].RA[0]);
+  fits_modify (&catalog[0].header, "DEC0", "%lf", 1, region[0].DEC[0]);
+  fits_modify (&catalog[0].header, "RA1", "%lf", 1, region[0].RA[1]);
+  fits_modify (&catalog[0].header, "DEC1", "%lf", 1, region[0].DEC[1]);
+  gettimeofday (&now, NULL);
+  local = localtime (&now.tv_sec);
+  sprintf (line, "%02d/%02d/%02d\0", local[0].tm_year, local[0].tm_mon + 1, local[0].tm_mday); 
+  fits_modify (&catalog[0].header, "DATE", "%s", 1, line);
+  strcpy (filename, CatTemplate);
+  ALLOCATE (catalog[0].average, Average, 1);
+  ALLOCATE (catalog[0].measure, Measure, 1);
+  ALLOCATE (catalog[0].missing, Missing, 1);
+  catalog[0].Naverage = catalog[0].Nmeasure = catalog[0].Nmissing = 0;
+
+  /* setup secondary filters to match photcodes */
+  ALLOCATE (catalog[0].secfilt, SecFilt, 1);
+  catalog[0].Nsecfilt = GetPhotcodeNsecfilt ();
+
+  /* Nsecfilt is number of filters.  Number of entries in array is
+     Nsecfilt * Naverage.  At this point, N entries == 0 */
+
+}
Index: /tags/start/Ohana/src/getstar/src/old/ForkToServer.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/old/ForkToServer.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/old/ForkToServer.c	(revision 12606)
@@ -0,0 +1,77 @@
+# include <ohana.h>
+
+int ForkToServer (int argc, char **argv, char *database, char *server) {
+
+  int i, fd, N, pid, status;
+  char **arglist, *p;
+  char hostname[1025];
+  struct timeval now, then;  
+  double dtime;
+
+  /* get local hostname */
+  if (gethostname (hostname, 1024)) {
+    fprintf (stderr, "ERROR: can't get hostname\n");
+    exit (1);
+  }
+
+  /* lock database file */
+  fd = setlockfile (database, 60.0, TRUE);
+  if (fd == -1) {
+    fprintf (stderr, "ERROR: can't set lock on %s\n", database);
+    exit (1);
+  }
+
+  if ((p = strchr (server, '.')) != (char *) NULL) *p = 0;
+  if ((p = strchr (hostname, '.')) != (char *) NULL) *p = 0;
+
+  if (!strcasecmp (hostname, server)) return (fd);
+
+  if (!strlen (server)) {
+    fprintf (stderr, "ERROR: no Database Server defined\n");
+    clearlockfile (database, fd, TRUE);
+    exit (1);
+  }
+
+  /* get start of fork time */
+  gettimeofday (&then, (void *) NULL);
+  pid = fork ();
+  if (!pid) { 
+    /* must be child process, fork to remote machine */
+
+    /* create argument list */
+    N = argc + 4;
+    ALLOCATE (arglist, char *, N);
+
+    arglist[0] = strcreate ("rsh");
+    arglist[1] = strcreate (server);
+    arglist[2] = strcreate (argv[0]);
+    arglist[3] = strcreate ("-remote");
+    for (i = 4; i < N; i++) {
+      arglist[i] = strcreate (argv[i-3]);
+    }
+    fprintf (stderr, "starting remote process on %s\n", server);
+    status = execvp ("rsh", arglist);
+    fprintf (stderr, "ERROR: can't start remote shell process\n");
+    exit (1);
+  }
+  /* it would be good to put rsh in the config file */
+
+  /* block until child exits */
+  wait (0);
+  
+  /*****  
+       inetd has a maximum connection rate of 40 / 60 seconds it will
+       block for 10 min if this rate is exceeded.  this is here because
+       we have to hold the lock long enough that the connection rate does
+       not get exceeded.  We actually use 3.0 seconds to avoid stealing
+       too many rsh slots. 
+  *****/
+  
+  gettimeofday (&now, (void *) NULL);
+  dtime = 1e6*(3.0 - DTIME(now,then));
+  if (dtime > 0) usleep (dtime);
+  
+  clearlockfile (database, fd, TRUE);
+  exit (0);
+  
+}
Index: /tags/start/Ohana/src/getstar/src/old/add_unfound.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/old/add_unfound.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/old/add_unfound.c	(revision 12606)
@@ -0,0 +1,35 @@
+  /* incorporate unmatched image stars -- after all catalogs searched... */
+  for (i = 0; i < Nstars; i++) {
+    if (!found[i]) {
+      catalog[0].average[Nave].R = stars[N1[i]].R;
+      catalog[0].average[Nave].D = stars[N1[i]].D;
+      catalog[0].average[Nave].M = 1000.0*stars[N1[i]].M;
+      catalog[0].average[Nave].Nm = 1;
+      catalog[0].average[Nave].Xp = catalog[0].average[Nave].Xm = 0.0;
+      catalog[0].average[Nave].offset = Nmeas;
+      catalog[0].measure[Nmeas].dR  = 0.0;
+      catalog[0].measure[Nmeas].dD  = 0.0;
+      catalog[0].measure[Nmeas].M   = 1000.0*stars[N1[i]].M;
+      catalog[0].measure[Nmeas].dM  = stars[N1[i]].dM;
+      catalog[0].measure[Nmeas].t  = 3600.0 + stars[N1[i]].Y*0.1;
+      catalog[0].measure[Nmeas].average = (0x00ffffff & Nave);
+      /* time of star = time of image + offset + Y*rate */
+      Nave ++;
+      if (Nave == 0x1000000) {
+	fprintf (stderr, "too many stars in catalog\n");
+	clear_lockfile ();
+	exit (0);
+      }
+      if (Nave == NAVE) {
+	NAVE = Nave + 1000;
+	REALLOCATE (next, int, NAVE);
+	REALLOCATE (catalog[0].average, Average, NAVE);
+      }
+      Nmeas ++;
+      if (Nmeas == NMEAS) {
+	NMEAS = Nmeas + 1000;
+	REALLOCATE (next, int, NMEAS);
+	REALLOCATE (catalog[0].measure, Measure, NMEAS);
+      }
+    }
+  }
Index: /tags/start/Ohana/src/getstar/src/old/check_lockfile.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/old/check_lockfile.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/old/check_lockfile.c	(revision 12606)
@@ -0,0 +1,46 @@
+# include "addstar.h"
+
+check_lockfile ()
+{
+  
+  FILE *f;
+  char filename[128];
+  struct stat filestat;
+
+  sprintf (filename, "%s/lock\0", CATDIR);
+  if (stat (filename, &filestat) != -1) {
+    fprintf (stderr, "ERROR: catalog %s is locked, try again later\n", CATDIR);
+    sprintf (filename, "%s/kill\0", CATDIR);
+    f = fopen (filename, "w");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't set kill file %s\n", filename);
+      exit (0);
+    }
+    fclose (f);
+    exit (0);
+  }
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't set lock file %s\n", filename);
+    exit (0);
+  }
+  fclose (f);
+
+}
+
+clear_lockfile ()
+{
+  
+  char filename[128], line[256];
+  struct stat filestat;
+
+  sprintf (filename, "%s/lock\0", CATDIR);
+  if (stat (filename, &filestat) != -1) {
+    sprintf (line, "rm %s\0", filename);
+    system (line);
+  } else {
+    fprintf (stderr, "can't remove lockfile, why not?\n");
+  }
+
+}
Index: /tags/start/Ohana/src/getstar/src/old/config.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/old/config.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/old/config.c	(revision 12606)
@@ -0,0 +1,110 @@
+# include <ohana.h>
+# define D_NBYTES 4096
+
+char *LoadConfigFile (filename) 
+char *filename; 
+{
+  
+  FILE *f;
+  int i, done, Nbytes, NBYTES, size;
+  char *config;
+  
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "couldn't find %s\n", filename);
+    return ((char *) NULL);
+  }
+ 
+  NBYTES = D_NBYTES;
+  ALLOCATE (config, char, NBYTES);
+ 
+  size = 0;
+  done = FALSE;
+  for (i = 0; !done; i++) {
+    Nbytes = Fread (&config[i*D_NBYTES], sizeof(char), D_NBYTES, f, "char");
+    size += Nbytes;
+    if (Nbytes < D_NBYTES) 
+      done = TRUE;
+    else {
+      NBYTES += D_NBYTES;
+      REALLOCATE (config, char, NBYTES);
+    }
+  }
+  
+  config[size] = '\n';
+  config[size+1] = 0;
+  REALLOCATE (config, char, size + 2);
+ 
+  fclose (f);
+
+  return (config);
+}
+
+int ScanConfig /* we expect one more field: the pointer to the value requested */
+# ifndef ANSI
+(config, field, mode, va_alist) 
+ char *config; char *field, *mode; va_dcl
+# else
+(char       config[],
+ char       field[],
+ char       mode[],...)
+# endif
+{
+ 
+  int i, j;
+  char *p, *p2, tmp[256];
+  va_list argp;
+  double value;
+  
+# ifndef ANSI
+  va_start (argp);
+# else
+  va_start (argp, N);
+# endif
+  
+  /* find the correct line with field */
+  p2 = config;
+  for (i = 0; ; i++) {
+    if (!strncmp (field, p2, strlen(field))) {
+      p = p2 + strlen (field);
+      break;
+    }
+    else {
+      p2 = strchr (p2, '\n');
+      if (p2 == (char *) NULL) {
+	fprintf (stderr, "entry %s not found in config file\n", field);
+	return (FALSE);
+      }
+      else p2++;
+    }
+  }
+  if (!strcmp (mode, "%s")) {
+    p2 = strchr (p, '\n');
+    if (p2 == (char *) NULL)
+      p2 = config + strlen(config);
+    bcopy (p, tmp, (p2-p));
+    tmp[(p2-p)] = 0;
+    stripwhite (tmp);
+    p2 = va_arg (argp, char *);
+    strcpy (p2, tmp);
+  }
+  else {
+ 
+    /* try to get a numerical value from the field */
+    value = strtod (p, &p2);
+    if ((*p2 == 'd') || (*p2 == 'D')) 
+      value *= pow (10.0, atof (p2 + 1));
+    
+    if (!strcmp (mode, "%d"))  *va_arg (argp, int *)       = value;
+    if (!strcmp (mode, "%u"))  *va_arg (argp, unsigned *)  = value;
+    if (!strcmp (mode, "%ld")) *va_arg (argp, long *)      = value;
+    if (!strcmp (mode, "%hd")) *va_arg (argp, short *)     = value;
+    if (!strcmp (mode, "%f"))  *va_arg (argp, float *)     = value;
+    if (!strcmp (mode, "%lf")) *va_arg (argp, double *)    = value;
+    
+  }
+ 
+  va_end (argp);
+  return (TRUE);
+  
+}
Index: /tags/start/Ohana/src/getstar/src/old/dumpcat.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/old/dumpcat.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/old/dumpcat.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include "addstar.h"
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  int i, j, Nstars, Nimage, Nregions;
+  Average *average;
+  Measure *measure;
+  Missing *missing;
+  Catalog catalog;
+  GSCRegion region;
+  FILE *f;
+  
+  if (argc < 4) {
+    fprintf (stderr, "USAGE: dumpcat catalog output mode(0,1,2,3)\n");
+    clear_lockfile ();
+    exit (0);
+  }
+
+  strcpy (region.filename, argv[1]);
+
+  gcatalog (&region, &catalog);
+
+  f = fopen (argv[2], "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "failed to open file %s for write\n", argv[2]);
+    clear_lockfile ();
+    exit (0);
+  }
+
+  average = catalog.average;
+  for (i = 0; i < catalog.Naverage; i++) {
+    fprintf (f, "%10.6f %10.6f %7.3f %3d %3d %8d %d\n", average[i].R, average[i].D, 
+	     0.001*average[i].M, average[i].Nm, average[i].Nn, average[i].offset, catalog.measure[average[i].offset].t);
+    if ((atof(argv[3]) == 1) || (atof(argv[3]) == 3)) {
+      measure = &catalog.measure[average[i].offset];
+      for (j = 0; j < average[i].Nm; j++) {
+	fprintf (f, "  %d %d %f %f %d\n", measure[j].dR, measure[j].dD, 0.001*measure[j].M, 
+		  measure[j].t, measure[j].average);
+      }
+    }
+    if ((atof(argv[3]) == 2) || (atof(argv[3]) == 3)) {
+      if (average[i].Nn > 0) {
+	missing = &catalog.missing[average[i].missing];
+	for (j = 0; j < average[i].Nn; j++) {
+	  fprintf (f, "  %f\n", missing[j].t);
+	}
+      } else { 
+	fprintf (f, "no missing obs\n");
+      }
+    }
+  }
+
+    
+
+  fclose (f);
+    
+
+}
Index: /tags/start/Ohana/src/getstar/src/old/gstars1.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/old/gstars1.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/old/gstars1.c	(revision 12606)
@@ -0,0 +1,273 @@
+# include "addstar.h"
+# define D_NSTARS 1000
+# define BYTES_STAR 31
+# define BLOCK 1000
+#include <sys/time.h>
+#include <time.h>
+
+Stars *gstars (file, NSTARS, image) 
+char file[];
+int *NSTARS;
+Image *image;
+{
+
+  FILE *f;
+  Header header;
+  int j, N, Ninstar;
+  int nbytes, Nbytes;
+  Stars *stars;
+  char *buffer;
+  double tmp;
+  int done, doneread, Nskip, Nextra, itmp;
+  char  *c, *c2;
+  unsigned short int Nc;
+
+  if (!fits_read_header (file, &header)) {
+    fprintf (stderr, "ERROR: can't read header for %s\n", file);
+    clearlockfile (ImageCat, -1);
+    exit(0);
+  }
+
+  /* open file */
+  f = fopen (file, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't read data from %s\n", file);
+    clearlockfile (ImageCat, -1);
+    exit(0);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* find image rootname */
+  c = strrchr (file, 0x2f);
+  if (c == (char *) NULL) {
+    strcpy (image[0].name, file);
+  } else { 
+    strcpy (image[0].name, (c+1));
+  }
+
+  /* get astrometry information */
+  if (!GetCoords (&image[0].coords, &header)) {
+    fprintf (stderr, "ERROR: no astrometric solution in header\n");
+    clearlockfile (ImageCat, -1);
+    exit (0);
+  }
+  while (image[0].coords.crval1 < 0) image[0].coords.crval1 += 360.0;
+  while (image[0].coords.crval1 > 360.0) image[0].coords.crval1 -= 360.0;
+  itmp = 0;
+  fits_scan (&header, "NASTRO",   "%d", 1, &itmp);
+  if (itmp == 0) {
+    fprintf (stderr, "ERROR: bad astrometric solution in header\n");
+    clearlockfile (ImageCat, -1);
+    exit (0);
+  }
+    
+  /* CERROR in data file is in arcsec */
+  fits_scan (&header, "CERROR",   "%lf", 1, &tmp);
+  image[0].cerror = tmp * 50.0;
+  fits_scan (&header, "NAXIS1",   "%hd", 1, &image[0].NX); 
+  fits_scan (&header, "NAXIS2",   "%hd", 1, &image[0].NY);
+  fits_scan (&header, "PHOTCODE", "%hd", 1, &image[0].source);
+  if (NEWPHOTCODE) {
+    image[0].source = PHOTCODE;
+  }
+  if ((image[0].source < 0) || (image[0].source > 0xffff)) {
+    fprintf (stderr, "error: invalid photcode\n");
+    exit (0);
+  }
+  Nc = photcodes.hashcode[image[0].source];
+  if (Nc < 0) {
+    fprintf (stderr, "ERROR: image has invalid photcode value\n");
+    exit (0);
+  }
+  thiscode = &photcodes.code[Nc];
+
+  image[0].NX -= XOVERSCAN;
+  image[0].NY -= YOVERSCAN;
+  fits_scan (&header, "EXPTIME",  "%lf", 1, &tmp);
+  image[0].exptime = tmp;
+  
+  tmp = 0;
+  fits_scan (&header, "APMIFIT",  "%lf", 1, &tmp);
+  image[0].apmifit = tmp * 1000.0;
+
+  tmp = 0;
+  fits_scan (&header, "dAPMIFIT", "%lf", 1, &tmp);
+  image[0].dapmifit = tmp * 1000.0;
+
+  tmp = 0;
+  fits_scan (&header, "FLIMIT",   "%lf", 1, &tmp);
+  image[0].detection_limit = tmp * 10.0;
+
+  tmp = 0;
+  fits_scan (&header, "FSATUR",   "%lf", 1, &tmp);
+  image[0].saturation_limit = tmp * 10.0;
+
+  tmp = 0;
+  fits_scan (&header, "FWHM_X",   "%lf", 1, &tmp);
+  image[0].fwhm_x = tmp * 25.0 * image[0].coords.cdelt1 * 3600.0;
+
+  tmp = 0;
+  fits_scan (&header, "FWHM_Y",   "%lf", 1, &tmp);
+  image[0].fwhm_y = tmp * 25.0 * image[0].coords.cdelt1 * 3600.0;
+
+  if (!fits_scan (&header, "TZERO",   "%d",  1, &image[0].tzero)) {
+    image[0].tzero = parse_time (&header);
+  }
+
+  tmp = 0;
+  fits_scan (&header, "TRATE",   "%lf", 1, &tmp);
+  image[0].trate = 10000 * tmp;
+
+  tmp = 0;
+  fits_scan (&header, "AIRMASS", "%lf", 1, &tmp);
+  image[0].secz = 1000*tmp;
+
+  if (!fits_scan (&header, "IMAGEID", "%d", 1, &itmp)) {
+    image[0].ccdnum = 0xff;
+  } else {
+    image[0].ccdnum = itmp;
+  }
+
+  fits_scan (&header, "ZERO_PT", "%lf", 1, &ZeroPt);
+
+  /* secz is in units milli-airmass */
+  image[0].Mcal =  ALPHA*(image[0].secz - 1000);
+  image[0].Xm   = 30.0;
+  image[0].code = 0;
+  bzero (image[0].dummy, sizeof(image[0].dummy));
+
+  /* find expected number of stars */
+  fits_scan (&header, "NSTARS", "%d", 1, &image[0].nstar);
+  if (image[0].nstar == 0) {
+    fprintf (stderr, "ERROR: can't get NSTARS from header\n");
+    clearlockfile (ImageCat, -1);
+    exit (0);
+  }
+  ALLOCATE (stars, Stars, image[0].nstar);
+
+  /* load in stars by blocks of 1000 */
+  N = 0;
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR) + 1);
+  buffer[BLOCK*BYTES_STAR] = 0;
+  Nextra = 0;
+  doneread = FALSE;
+  while (!doneread) {
+    Nbytes = BYTES_STAR * BLOCK - Nextra;
+    nbytes = Fread (&buffer[Nextra], 1, Nbytes, f, "char");
+    if (nbytes == 0) {
+      doneread = TRUE;
+      continue;
+    }
+    nbytes += Nextra;
+    /* check line-by-line integrity */
+    c = buffer;
+    done = FALSE;
+    while ((c < buffer + nbytes) && (!done)) { 
+      for (c2 = c; *c2 == '\n'; c2++);
+      if (c2 > c) { /* extra return chars */
+	memmove (c, c2, (int)(buffer + nbytes - c2));
+	Nskip = c2 - c;
+	nbytes -= Nskip;
+	bzero (buffer + nbytes, Nskip);
+	if (VERBOSE) fprintf (stderr, "deleted %d extra return chars\n", Nskip);
+      }
+      c2 = strchr (c, '\n');
+      if (c2 == (char *) NULL) {
+	done = TRUE;	
+	continue;
+      }
+      c2++;
+      if ((c2 - c) != BYTES_STAR) { /* bad line, delete it */
+	memmove (c, c2, (int)(buffer + nbytes - c2));
+	Nskip = c2 - c;
+	nbytes -= Nskip;
+	bzero (buffer + nbytes, Nskip);
+	if (VERBOSE) fprintf (stderr, "deleted line, %d extra chars\n", Nskip);
+      } else {
+	c = c2;
+      }
+    }
+    Ninstar = nbytes / BYTES_STAR;
+    Nextra = nbytes % BYTES_STAR;
+    for (j = 0; j < Ninstar; j++, N++) {
+      dparse (&stars[N].X,  1, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].Y,  2, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].M,  3, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].dM, 4, &buffer[j*BYTES_STAR]);
+      XY_to_RD (&stars[N].R, &stars[N].D, stars[N].X, stars[N].Y, &image[0].coords);
+      while (stars[N].R < 0.0) stars[N].R += 360.0;
+      while (stars[N].R >= 360.0) stars[N].R -= 360.0;
+      dparse (&tmp, 5, &buffer[j*BYTES_STAR]);
+      stars[N].dophot = tmp;
+      stars[N].found = -1;
+    }
+  }
+
+  image[0].nstar = N;
+  REALLOCATE (stars, Stars, image[0].nstar);
+  if (VERBOSE) fprintf (stderr, "read %d stars from target file\n", image[0].nstar);
+  *NSTARS = image[0].nstar;
+
+  return (stars);
+}
+
+
+
+
+# if (0)
+  /* left over fraction of a block */
+  nbytes = Fread (buffer, 1, (Nbytes % (BLOCK*BYTES_STAR)), f, "char");
+  if (nbytes != (Nbytes % (BLOCK*BYTES_STAR))) {
+    fprintf (stderr, "ERROR: failed to read in stars (2)\n");
+    clearlockfile (ImageCat, -1);
+    exit (0);
+  }
+  /* check line-by-line integrity */
+  Nnew = 0;
+  c = buffer;
+  done = FALSE;
+  while ((c < buffer + nbytes) && (!done)) { 
+    for (c2 = c; *c2 == '\n'; c2++);
+    if (c2 > c) { /* extra return chars */
+      memmove (c, c2, (int)(buffer + nbytes - c2));
+      Nnew += c2 - c;
+      fprintf (stderr, "deleting %d extra return chars\n", (int)(c2-c));
+    }
+    c2 = strchr (c, '\n');
+    if (c2 == (char *) NULL) {
+      if (Nnew > 0) {
+	nnew = Fread (&buffer[nbytes-Nnew], 1, Nnew, f, "char");
+	if (nnew != Nnew) {
+	  fprintf (stderr, "ERROR: failed to read in stars (1)\n");
+	  exit (0);
+	}
+      } else {
+	done = TRUE;	
+      }
+      continue;
+    }
+    c2++;
+    if ((c2 - c) != BYTES_STAR) {
+      /* this is a bad line, delete it, adjust data in buffer, 
+	 and be ready to read the rest of the last line */
+      memmove (c, c2, (int)(buffer + nbytes - c2));
+      Nnew += c2 - c;
+      fprintf (stderr, "deleting bad line with %d chars\n", (int)(c2-c));
+    } else {
+      c = c2;
+    }
+  }
+  for (j = 0; j < nbytes / BYTES_STAR; j++, nstar++, N++) {
+    dparse (&stars[N].X, 1, &buffer[j*BYTES_STAR]);
+    dparse (&stars[N].Y, 2, &buffer[j*BYTES_STAR]);
+    dparse (&stars[N].M, 3, &buffer[j*BYTES_STAR]);
+    dparse (&stars[N].dM, 4, &buffer[j*BYTES_STAR]);
+    XY_to_RD (&stars[N].R, &stars[N].D, stars[N].X, stars[N].Y, &image[0].coords);
+    while (stars[N].R < 0.0) stars[N].R += 360.0;
+    while (stars[N].R >= 360.0) stars[N].R -= 360.0;
+    dparse (&tmp, 5, &buffer[j*BYTES_STAR]);
+    stars[N].dophot = tmp;
+    stars[N].found = -1;
+  }
+
+# endif
Index: /tags/start/Ohana/src/getstar/src/old/sort_stars.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/old/sort_stars.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/old/sort_stars.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include "relphot.h"
+
+void sort_stars (radec, stars, Nstars)
+int  **radec;
+Star  *stars;
+int    Nstars;
+{
+  
+  int i;
+  double *RAs;
+
+  ALLOCATE (radec[0], int, Nstars);
+  ALLOCATE (RAs, double, Nstars);
+  for (i = 0; i < Nstars; i++) {
+    radec[0][i] = i;
+    RAs[i] = stars[i].RA;
+  }
+
+  sort_seq (radec[0], RAs, Nstars);
+  free (RAs);
+
+}
+
+
+void sort_seq (seq, value, N) 
+int *seq;
+double *value;
+int N;
+{
+  int l,j,ir,i;
+  int temp;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      temp = seq[--l];
+    }
+    else {
+      temp = seq[ir];
+      seq[ir] = seq[0];
+      if (--ir == 0) {
+	seq[0] = temp;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && value[seq[j]] < value[seq[j+1]]) ++j;
+      if (value[temp] < value[seq[j]]) {
+	seq[i]=seq[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    seq[i] = temp;
+  }
+}
+
+
Index: /tags/start/Ohana/src/getstar/src/old/string.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/old/string.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/old/string.c	(revision 12606)
@@ -0,0 +1,64 @@
+# include <stdio.h>
+# include <math.h>
+# define TRUE  1
+# define FALSE 0
+
+int scan_line (f, line) 
+FILE *f;
+char line[];
+{
+
+  int i, status;
+  char c;
+  
+  status = EOF + 1;
+  
+  for (i = 0, c = 0; (c != '\n') && (status != EOF); i++) {
+    status = fscanf (f, "%c", &c);
+    line[i] = c;
+  }
+  line[i - 1] = 0;  /* this could make things crash! */
+
+  if (i > 1) {
+    status = EOF + 1;
+  }
+
+  return (status);
+
+}
+
+char *_parse_nextword(string)
+char *string;
+{
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (; isspace (*string); string++);
+  for (; (*string != 0) && !isspace (*string); string++);
+  for (; isspace (*string); string++);
+  return (string);
+}
+
+int dparse (X, NX, line)
+double *X;
+int NX;
+char *line;
+{
+
+  int i;
+  char *word;
+  char *ptr;
+
+  word = line;
+  for (i = 0; i < NX - 1; i++)
+    word = _parse_nextword (word);
+
+  *X = strtod (word, &ptr);
+  if (ptr == word)
+    return (FALSE);
+  else {
+    if (word[0] == '-') 
+      return (-1);
+    else
+      return (1);
+  }
+}
Index: /tags/start/Ohana/src/getstar/src/parse_time.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/parse_time.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/parse_time.c	(revision 12606)
@@ -0,0 +1,126 @@
+# include "addstar.h"
+
+parse_time (Header *header) {
+
+  double jd;
+  int Ny, Nf, mode;
+  int Nsec, hour, min, sec, year, month, day;
+  char *py, *pm, *pd, *c;
+  char line[256];
+
+  /* we want to find JD or MJD to get Nsec (seconds since 01/01/1970) */
+
+  /* try JD first */
+  if (strcasecmp (JDKeyword, "NONE")) {
+    uppercase (JDKeyword);
+    fits_scan (header, JDKeyword, "%lf", 1, &jd);
+    Nsec = (jd - 2440587.5)*86400;
+    return (Nsec);
+  }
+
+  /* try MJD next */
+  if (strcasecmp (MJDKeyword, "NONE")) {
+    uppercase (MJDKeyword);
+    fits_scan (header, MJDKeyword, "%lf", 1, &jd);
+    Nsec = (jd - 40587.0)*86400;
+    return (Nsec);
+  }
+    
+  /* get UT and DATE */
+  uppercase (UTKeyword);
+  fits_scan (header, UTKeyword, "%s", 1, line);
+  /* remove ':' characters */
+  for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
+  sscanf (line, "%d %d %d", &hour, &min, &sec);
+
+  /* parse mode line */
+  uppercase (DateMode);
+  for (Ny = 0, c = strchr (DateMode, 'Y'); c != (char ) NULL; c = strchr (c + 1, 'Y'), Ny++);
+  if ((Ny != 2) && (Ny != 4)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  py = strchr (DateMode, 'Y');
+  pm = strchr (DateMode, 'M');
+  pd = strchr (DateMode, 'D');
+  if ((py == (char *) NULL) || (pm == (char *) NULL) || (pd == (char *) NULL)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  if ((py > pm) && (py < pd)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  if ((py > pd) && (py < pm)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  mode = 0;
+  if ((py < pm) && (pm < pd)) { mode = 1; }  /* yyyy-mm-dd */
+  if ((py < pm) && (pm > pd)) { mode = 2; }  /* yyyy-dd-mm */
+  if ((py > pm) && (pm < pd)) { mode = 3; }  /* mm-dd-yyyy */
+  if ((py > pm) && (pm > pd)) { mode = 4; }  /* dd-mm-yyyy */
+  if (!mode) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+
+  /* parse date entry */
+  uppercase (DateKeyword);
+  fits_scan (header, DateKeyword, "%s",  1, line);
+  /* remove possible separators: ':', '/' '.', '-' */
+  for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
+  for (c = strchr (line, 0x2f); c != (char *) NULL; c = strchr (line, 0x2f)) { *c = ' '; }
+  for (c = strchr (line, 0x2e); c != (char *) NULL; c = strchr (line, 0x2e)) { *c = ' '; }
+  for (c = strchr (line, 0x2d); c != (char *) NULL; c = strchr (line, 0x2d)) { *c = ' '; }
+
+  switch (mode) {
+  case 1:
+    Nf = sscanf (line, "%d %d %d", &year, &month, &day);
+    break;
+  case 2:
+    Nf = sscanf (line, "%d %d %d", &year, &day, &month);
+    break;
+  case 3:
+    Nf = sscanf (line, "%d %d %d", &month, &day, &year);
+    break;
+  case 4:
+    Nf = sscanf (line, "%d %d %d", &day, &month, &year);
+    break;
+  }
+  if (Nf != 3) {
+    fprintf (stderr, "error in date entry (%s) or DATE-MODE format (%s)\n", line, DateMode);
+    exit (1);
+  }
+
+  if (year > 1000) {
+    if (Ny == 2) {
+      fprintf (stderr, "warning: mode line claims 2 digit year, but 4 digit year found\n");
+    }
+  } else {
+    if (Ny == 4) {
+      fprintf (stderr, "warning: mode line claims 4 digit year, but 2 digit year found\n");
+    }
+    if (year < 50) year += 100;
+    year += 1900;
+  }    
+
+  /* convert yy.mm.dd hh.mm.ss to Nsec since 1970 (jd = 2440587.5) */
+  /* note that in this section, tm_mon has range 1-12, unlike for gmtime () */
+  jd = day - 32075 + (int)(1461*(year + 4800 + (int)(((month)-14)/12))/4)
+    + (int)(367*((month) - 2 - (int)(((month) - 14)/12)*12)/12)
+    - (int)(3*(int)((year + 4900 + (int)(((month) - 14)/12))/100)/4) - 0.5;
+  /* jd is the julian day of the whole day only not the time */
+  Nsec = (jd - 2440587.5)*86400 + 3600.0*hour + min*60.0 + sec;
+  
+  return (Nsec);
+
+}
+
+uppercase (char *string) {
+
+  int i;
+    
+  for (i = 0; i < strlen (string); i++) string[i] = toupper (string[i]);
+
+}
Index: /tags/start/Ohana/src/getstar/src/sort_lists.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/sort_lists.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/sort_lists.c	(revision 12606)
@@ -0,0 +1,82 @@
+
+sort_lists (X, Y, S, N) 
+float *X, *Y;
+int *S, N;
+{
+  int l,j,ir,i;
+  double tX, tY, tS;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    S[i] = tS;
+  }
+}
+
+fsort (float *X, int N) {
+
+  int l,j,ir,i;
+  float tX;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+  }
+}
Index: /tags/start/Ohana/src/getstar/src/wcatalog.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/wcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/wcatalog.c	(revision 12606)
@@ -0,0 +1,37 @@
+# include "addstar.h"
+
+wcatalog (Catalog *catalog) {
+  
+  int status;
+
+  /* we'll leave these for now, but they are LONEOS specific */
+  fits_modify (&catalog[0].header, "MARKSTAR", "%t", 1, FALSE);
+  fits_modify (&catalog[0].header, "ADDUSNO", "%t", 1, FALSE);
+  fits_modify (&catalog[0].header, "MARKROCK", "%t", 1, FALSE);
+
+  if (!save_catalog (catalog, VERBOSE)) {
+    fprintf (stderr, "ERROR: failure saving catalog\n");
+    exit (1);
+  }
+
+  /* free, initialize data structures */
+
+  if (catalog[0].Naverage) {
+    free (catalog[0].average); 
+    catalog[0].Naverage = 0;
+  }
+  if (catalog[0].Nmeasure) {
+    free (catalog[0].measure); 
+    catalog[0].Nmeasure = 0;
+  }
+  if (catalog[0].Nmissing) {
+    free (catalog[0].missing); 
+    catalog[0].Nmissing = 0;
+  }
+  if (catalog[0].Nsecfilt) {
+    free (catalog[0].secfilt); 
+    catalog[0].Nsecfilt = 0;
+  }
+  fits_free_header (&catalog[0].header);
+}
+
Index: /tags/start/Ohana/src/getstar/src/wimage.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/wimage.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/wimage.c	(revision 12606)
@@ -0,0 +1,52 @@
+# include "getstar.h"
+
+wimage (FILE *f, int dbstate, Image *image, int Nstars) {
+  
+  int Nimages, status, mode;
+  Header header;
+
+  /* place file pointer at beginning of file */
+  fseek (f, 0, SEEK_SET);
+
+  if (dbstate == LCK_EMPTY) {
+    if (VERBOSE) fprintf (stderr, "can't find %s, creating a new one\n", ImageCat);
+    if (!fits_read_header (ImageTemplate, &header)) {
+      fprintf (stderr, "ERROR: can't find template header %s\n", ImageTemplate);
+      exit (1);
+    }
+    /* assign Zero Point provided by first image in dB */
+    fits_modify (&header, "ZERO_PT", "%lf", 1, ZeroPt);
+  } else {
+    if (!fits_load_header (f, &header)) {
+      fprintf (stderr, "ERROR: can't read image header %s\n", ImageCat);
+      exit (1);
+    }
+  }
+  
+  Nimages = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimages);
+  Nimages ++;
+  fits_modify (&header, "NIMAGES", "%d", 1, Nimages);
+
+  /* position to begining of file to write header */
+  fseek (f, 0, SEEK_SET);
+  status = Fwrite (header.buffer, 1, header.size, f, "char");
+  if (status != header.size) {
+    fprintf (stderr, "ERROR: failed writing data to image header\n");
+    exit (1);
+  }
+
+  /* position to end of file for new image data */
+  fseek (f, 0, SEEK_END);
+  status = Fwrite (image, sizeof(Image), 1, f, "image");
+  if (status != 1) {
+    fprintf (stderr, "ERROR: failed writing data to image catalog\n");
+    exit (1);
+  }
+}
+
+/* the image we add in this routine is always a new image.  
+   We only need to do two things:
+     1) append the data for the image to the end of the file
+     2) update the NIMAGES field in the header (which means, read in header, re-write)
+ */
Index: /tags/start/Ohana/src/getstar/src/wstars.c
===================================================================
--- /tags/start/Ohana/src/getstar/src/wstars.c	(revision 12606)
+++ /tags/start/Ohana/src/getstar/src/wstars.c	(revision 12606)
@@ -0,0 +1,146 @@
+# include "getstar.h"
+# define NCHAR 66 /* 65 char EXCLUDING return */
+
+int wstars (char *filename, Stars *stars, int Nstars, Image *image) {
+
+  /* construct a header from the image structure */
+  /* write out header */
+  /* write out data lines */
+
+  int i, Nchar, Ny, mode;
+  double scale;
+  char *photcode, *c, *py, *pm, *pd, datestr[64], timestr[64];
+  struct tm *gmt;
+  Header header;
+  FILE *f;
+  char line[NCHAR];
+
+  fits_init_header (&header);
+  header.Naxis[0] = image[0].NX + XOVERSCAN;
+  header.Naxis[1] = image[0].NY + YOVERSCAN;
+  header.bitpix   = 16;
+  header.Naxes    = 2;
+  fits_create_header (&header);
+
+  /* astrometric data */
+  fits_print (&header, "CTYPE1",  "%s", 1, "RA---SIN");
+  fits_print (&header, "CTYPE2",  "%s", 1, "DEC--SIN");
+
+  fits_print (&header, "CRVAL1", "%f", 1, image[0].coords.crval1);
+  fits_print (&header, "CRVAL2", "%f", 1, image[0].coords.crval2);
+
+  fits_print (&header, "CRPIX1", "%f", 1, image[0].coords.crpix1);
+  fits_print (&header, "CRPIX2", "%f", 1, image[0].coords.crpix2);
+
+  fits_print (&header, "PC001001",  "%f", 1, image[0].coords.pc1_1);
+  fits_print (&header, "PC001002",  "%f", 1, image[0].coords.pc1_2);
+  fits_print (&header, "PC002001",  "%f", 1, image[0].coords.pc2_1);
+  fits_print (&header, "PC002002",  "%f", 1, image[0].coords.pc2_2);
+
+  fits_print (&header, "CDELT1",  "%f", 1, image[0].coords.cdelt1);
+  fits_print (&header, "CDELT2",  "%f", 1, image[0].coords.cdelt2);
+  
+  fits_print (&header, "NASTRO", "%d", 1, 1); /* TBD */
+  fits_print (&header, "EQUINOX", "%f", 1, 2000.0); /* TBD */
+  
+  fits_print (&header, "CERROR", "%f", 1, 0.02*image[0].cerror);
+
+  photcode = GetPhotcodeNamebyCode (image[0].source);
+  fits_print (&header, "PHOTCODE", "%s", 1, photcode);
+
+  fits_print (&header, ExptimeKeyword, "%f", 1, image[0].exptime);
+  
+  fits_print (&header, "FLIMIT",   "%lf", 1, 0.1*image[0].detection_limit);
+  fits_print (&header, "FSATUR",   "%lf", 1, 0.1*image[0].saturation_limit);
+
+  scale = image[0].coords.cdelt1*25.0*3600.0;
+  fits_print (&header, "FWHM_X",   "%lf", 1, image[0].fwhm_x / scale);
+  fits_print (&header, "FWHM_Y",   "%lf", 1, image[0].fwhm_y / scale);
+	      
+  fits_print (&header, "TRATE",   "%lf", 1, image[0].trate/10000.0);
+  fits_print (&header, AirmassKeyword, "%lf", 1, 0.001*image[0].secz);
+
+  if (image[0].ccdnum != 0xff) {
+    fits_print (&header, CCDNumKeyword, "%d", 1, image[0].ccdnum);
+  }
+
+  /* parse date-mode line */
+  uppercase (DateMode);
+  for (Ny = 0, c = strchr (DateMode, 'Y'); c != (char ) NULL; c = strchr (c + 1, 'Y'), Ny++);
+  if ((Ny != 2) && (Ny != 4)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  py = strchr (DateMode, 'Y');
+  pm = strchr (DateMode, 'M');
+  pd = strchr (DateMode, 'D');
+  if ((py == (char *) NULL) || (pm == (char *) NULL) || (pd == (char *) NULL)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  if ((py > pm) && (py < pd)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  if ((py > pd) && (py < pm)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  mode = 0;
+  if ((py < pm) && (pm < pd)) { mode = 1; }  /* yyyy-mm-dd */
+  if ((py < pm) && (pm > pd)) { mode = 2; }  /* yyyy-dd-mm */
+  if ((py > pm) && (pm < pd)) { mode = 3; }  /* mm-dd-yyyy */
+  if ((py > pm) && (pm > pd)) { mode = 4; }  /* dd-mm-yyyy */
+  if (!mode) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+
+  gmt = gmtime ((unsigned long *)&image[0].tzero);
+
+  switch (mode) {
+  case 1:
+    sprintf (datestr, "%04d/%02d/%02d", 1900 + gmt[0].tm_year, gmt[0].tm_mon+1, gmt[0].tm_mday);
+    break;
+  case 2:
+    sprintf (datestr, "%04d/%02d/%02d", 1900 + gmt[0].tm_year, gmt[0].tm_mday, gmt[0].tm_mon+1);
+    break;
+  case 3:
+    sprintf (datestr, "%02d/%02d/%04d", gmt[0].tm_mon+1, gmt[0].tm_mday, 1900 + gmt[0].tm_year);
+    break;
+  case 4:
+    sprintf (datestr, "%02d/%02d/%04d", gmt[0].tm_mday, gmt[0].tm_mon+1, 1900 + gmt[0].tm_year);
+    break;
+  }
+  sprintf (timestr, "%02d:%02d:%02d", gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+  fits_print (&header, UTKeyword, "%s", 1, timestr);
+  fits_print (&header, DateKeyword, "%s", 1, datestr);
+
+  fits_print (&header, "ZERO_PT", "%lf", 1, ZeroPt);
+  fits_print (&header, "NSTARS", "%d", 1, Nstars);
+  
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't create output file %s\n", filename);
+    exit (1);
+  }
+
+  fwrite (header.buffer, 1, header.size, f);
+
+  for (i = 0; i < Nstars; i++) {
+    Nchar = snprintf (line, NCHAR, "%6.1f %6.1f %6.3f %03d %2d %3.1f %6.3f %6.3f %6.2f %6.2f %5.1f", 
+		      stars[i].X, stars[i].Y, stars[i].M, 
+		      (int)(stars[i].dM), stars[i].dophot, stars[i].sky, 
+		      stars[i].Mgal, stars[i].Map, stars[i].fx, stars[i].fy, stars[i].df);
+    fprintf (f, "%s\n", line);
+  }
+  fclose (f);
+}
+
+uppercase (char *string) {
+
+  int i;
+    
+  for (i = 0; i < strlen (string); i++) string[i] = toupper (string[i]);
+
+}
Index: /tags/start/Ohana/src/gophot/Makefile
===================================================================
--- /tags/start/Ohana/src/gophot/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/gophot/Makefile	(revision 12606)
@@ -0,0 +1,68 @@
+include ../../Configure
+HOME    =       $(ROOT)/src/gophot
+PROGRAM =       gophot
+
+CC      =       gcc -g
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#  
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lFITS -lohana -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS) 
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+default: $(PROGRAM)
+
+OBJ = \
+           $(SRC)/gophot.$(ARCH).o 	   $(SRC)/ConfigInit.$(ARCH).o \
+	   $(SRC)/message.$(ARCH).o	   $(SRC)/dophot.$(ARCH).o \
+	   $(SRC)/makenoise.$(ARCH).o      $(SRC)/findsky.$(ARCH).o \
+           $(SRC)/makemask.$(ARCH).o       $(SRC)/paravg.$(ARCH).o \
+           $(SRC)/objout.$(ARCH).o         $(SRC)/addstar.$(ARCH).o \
+	   $(SRC)/ellipse.$(ARCH).o        $(SRC)/improve.$(ARCH).o \
+           $(SRC)/fillerup.$(ARCH).o       $(SRC)/parinterp.$(ARCH).o \
+           $(SRC)/guess.$(ARCH).o          $(SRC)/offpic.$(ARCH).o \
+           $(SRC)/addlims.$(ARCH).o        $(SRC)/parupd.$(ARCH).o \
+           $(SRC)/toofaint.$(ARCH).o       $(SRC)/isearch.$(ARCH).o \
+           $(SRC)/shape.$(ARCH).o          $(SRC)/galaxy.$(ARCH).o \
+           $(SRC)/transmask.$(ARCH).o      $(SRC)/cosmic.$(ARCH).o \
+           $(SRC)/impaper2.$(ARCH).o       $(SRC)/sort.$(ARCH).o \
+           $(SRC)/oblit.$(ARCH).o          $(SRC)/toobright.$(ARCH).o \
+           $(SRC)/Chisq.$(ARCH).o          $(SRC)/oblims.$(ARCH).o \
+           $(SRC)/ludcmp.$(ARCH).o         $(SRC)/lubksb.$(ARCH).o \
+           $(SRC)/pseud2d.$(ARCH).o        $(SRC)/twofit.$(ARCH).o \
+           $(SRC)/skyfun_plane.$(ARCH).o   $(SRC)/pseud4d.$(ARCH).o \
+	   $(SRC)/large_features.$(ARCH).o $(SRC)/set_thresholds.$(ARCH).o \
+           $(SRC)/outline.$(ARCH).o        $(SRC)/delete_ellipse.$(ARCH).o \
+	   $(SRC)/feature_fluxes.$(ARCH).o $(SRC)/mediansky.$(ARCH).o
+
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:	
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
Index: /tags/start/Ohana/src/gophot/doc/Notes
===================================================================
--- /tags/start/Ohana/src/gophot/doc/Notes	(revision 12606)
+++ /tags/start/Ohana/src/gophot/doc/Notes	(revision 12606)
@@ -0,0 +1,144 @@
+
+Converting dophot to C: (I use dophot.f and dophot.c to refer to the
+fortran and C versions of dophot).
+
+some rules and goals for the first pass:
+
+1) I am maintaining the fortran dophot variable names as much as
+   possible, at least for now. 
+
+2) I am avoiding making proceedural changes / method changes, but I am
+willing to make minor modifications of things like looping strategies
+and if-statement order to clean the code a bit.
+
+3) I have placed all of the common-block variables in a single include
+file, gophot.h, with some attempt to define the names.  I've also placed the
+image data and noise matricies in gophot.h, along with nfast, nslow,
+so these are not passed endlessly back and forth among functions.
+
+4) My (sort-of) working fortran f2c dophot used an external loop,
+getfits.c which enclosed dophot.f and performed the image loading,
+big matrix allocation stuff.  I have renamed that gophot.c and cleaned
+it somewhat.  
+
+5) The biggest structural change so far is the infamous tuneup.f.  I
+have replaced it with my own ConfigInit function, based on my ohana
+config functions.  These have a much cleaner syntax for reading
+configuration values.  I have also placed the ConfigInit function much
+earlier, in gophot.c at the very beginning.  this means that config
+values can be overridden by image header values, if the fits_scan
+lines are coded.  currently, itop is read from the header (SATVALUE).
+
+For the moment, I am only making those changes needed to get a working
+dophot version, not a complete version.  Thus, I am skipping:
+warmstart, autothresh, median sky, hubble sky. 
+
+some function with significant adjustments, other than getfits.c and
+tuneup.f:
+
+message.c: actually this didn't exist in dophot.f - I have created a
+function mprint, which conditionally prints a message based on the
+verbosity level and an associated threshold.  the verbosity is
+registered with set_verbosity (level) and is stored static in
+message.c (not visible to the rest of dophot.c).  the prototype is:
+mprint (int level, char format, ...), with a format and argument
+syntax identical to printf.  all messages go to stderr, for now.
+
+makenoise.c: I am using pointers to do the loops. this should speed
+life alot.
+
+findsky.c: a new addition of mine to determine skyvalue from median of
+image.  this is implemented in the most recent dophot.f, but only
+since March 2000.
+
+There are some typical coding structures in the fortran that I am
+changing to make more legible:
+
+1) a = a + 1, a = a + b --> I'm using C inc args: a++, a+=b
+
+2) nested logic:
+
+{ /* some block */
+
+ code, code, code;
+
+ if (condition) then 
+
+   big block;
+
+ endif
+
+} /* end block */  
+
+there are many of these structures which conditionally perform a large
+operation, and otherwise do nothing or almost nothing.  I'm inverting
+these like this:
+
+{ /* some block */
+
+ code, code, code;
+
+ if (!condition) continue
+
+ big block;
+
+} /* end block */  
+
+data hard.soft.mat 
+read m1 4 m2 15
+set dm = m1 - m2
+lim -17 -7 -1 1; clear; box; plot m1 dm
+
+I have been making some significant changes to the dophot strategy for
+finding stars.  The goal is to handle saturated stars more
+effectively.  The strategy should not really change for faint stars.
+There are a few problems with the old strategy.  
+
+First, we were using an image array and a noise array.  To inhibit
+finding fake stars in the wings of bright stars, the noise array was
+enhanced when the stars were subtracted.  But for each loop, we were
+fitting and re-fitting each star several times.  As a result, we were
+adding, subtracting, adding, and subtracting the noise, which was of
+the order Nstar^2, many times.  Round off errors eventually made the
+noise array useless in the vicinity of bright stars.  Second, bright
+stars likely have many bad pixels, either low from sagging counts at
+or near saturation or high from bleeding.  Since these all have quite
+high flux, they highly discrepant points drive the fits
+significantly.  Finally, the initial guess location used the peak of
+the flux in a box around the trigger pixel.  This was problematic for
+bright stars because bleeding and saturation meant the peak was
+frequently far from the centroid.  I am addressing each of these
+problems separately.
+
+First, for the fits, we are now softening the errors by the residual
+from the initial guess fit.  This is a fitting method called 'robust
+fitting', and it allows significantly discrepant points to be part of
+the data without dominating or driving the fit to funny places.  This
+means the saturated stars are less biased by the few pixels in the
+core which are saturated and discrepant from the fit for the other
+pixels.
+
+Second, for the noise problem, I have made several related changes.
+First, I am now converting the image from DN to electrons (and
+re-scaling all relevant parameters to match).  This means the Poisson
+noise in the original image is now simply sqrt(Ncts).  I am putting
+only the square of the read noise in the noise array.  When I subtract
+a star, I move the counts from the image array to the noise array.
+Thus, the noise per pixel is always (Icts + Ncts) [where Icts = image
+array counts and Ncts = noise array counts] before or after the star
+subtraction.  I now have two tests for bump significance:  1) the
+signal-to-noise must be above a threshold: 
+
+sq(sum[image-sky]) > sum[noise + image] * ratio
+
+and the image counts must be significant:
+
+sub[image-sky] > sum[noise - readnoise^2] * ratio
+
+Finally, the initial guess will use a centroid in fillerup if the flux
+is high enough.
+
+
+
+
+
Index: /tags/start/Ohana/src/gophot/include/fit.h
===================================================================
--- /tags/start/Ohana/src/gophot/include/fit.h	(revision 12606)
+++ /tags/start/Ohana/src/gophot/include/fit.h	(revision 12606)
@@ -0,0 +1,27 @@
+
+# ifndef ALLOCATE
+# define ALLOCATE(X,T,S)  \
+  X=(T *)malloc((unsigned) (MAX(((S)*sizeof(T)),1)));\
+  if(X==NULL) \
+    { \
+      fprintf(stderr,"failed to malloc X\n");\
+        exit (10);\
+    } 
+# define REALLOCATE(X,T,S) \
+  X=(T *)realloc(X,(unsigned) (MAX(((S)*sizeof(T)),1))); \
+  if(X==NULL) \
+    { \
+       fprintf(stderr,"failed to realloc X\n"); \
+       exit (10); \
+    }
+# endif /* ALLOCATE */
+
+float mrq2dinit (int *, int *, float *, float *, int, float *, int, float (funcs)(int *, int *, float *, float *)); 
+float mrq2dmin (int *, int *, float *, float *, int, float *, int, float (funcs)(int *, int *, float *, float *)); 
+float **mrq2dcovar (int);
+
+# define NPARS 8
+# define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+# define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+# define SQ(X)    (double) (((double)(X))*((double)(X)))
+# define SWAP(X,Y) {double tmp=(X); (X) = (Y); (Y) = tmp;}
Index: /tags/start/Ohana/src/gophot/include/gophot.h
===================================================================
--- /tags/start/Ohana/src/gophot/include/gophot.h	(revision 12606)
+++ /tags/start/Ohana/src/gophot/include/gophot.h	(revision 12606)
@@ -0,0 +1,128 @@
+/* includes */
+
+# include <ohana.h>
+
+typedef char bool;
+
+# define TRUE (1)
+# define FALSE (0)
+# define SIGN(X)  (((X) == 0) ? 0 : ((fabs((double)(X))) / (X)))
+# define ROUND(X) ((int) ((X) + 0.5*SIGN(X)))
+# define SQ(X)    (double) (((double)(X))*((double)(X)))
+# define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+# define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+# define SWAP(X,Y) {double tmp=(X); (X) = (Y); (Y) = tmp;}
+
+/* constants */
+
+# define NRMAX 1024 /* max Ny, deprecated */
+# define NCMAX 1024 /* max Nx, deprecated */
+
+# define CHIPAR 0.9 /* used by chisq.f */
+# define NSMAX 100000 /* max number of stars */
+# define NPMAX 8    /* max number of parameters */
+# define NPAR  8    /* max number of parameters used */
+# define NPSKY 8    /* max sky fit parameters */
+# define NSKYFIT 3  /* max sky fit parameters used */
+# define NFF   20   /* max number of files / flags */
+# define NAPPLE 5   /* number of aper data somethings? */
+# define NAPMAX 30  /* number of correction apertures in file? */
+# define NFIT0  2   /* N par in fit 0 */
+# define NFIT1  4   /* N par in fit 1 */
+# define NFIT2  7   /* N par in fit 2 */
+# define NFIT3  8   /* N par in fit 3 */
+
+# define MAXFIL 5000 /* max size of subraster vector */
+# define NMASK 17    /* max mask size */
+# define MAGIC HUGE_VAL  /* sentinel for bad pixels */
+/* # define MAGICSET 2e30 old value for sentinel */
+
+# define ADD +1
+# define SUB -1
+
+/* global variables */
+
+/* int   lverb;     * verbosity - no longer global */
+float chipar;       /* unknown chisq scale factor */
+float ufactor;      /* star scaling factor */
+
+/* float b[2*NPMAX];   * two-star fit array */
+/* float fb[2*NPMAX];  * two-star fit error array */
+
+bool test7; 
+bool needit;        /* deprecated? */
+
+int xs[MAXFIL], ys[MAXFIL], nrect[3];        /* subraster vectors */
+float zs[MAXFIL], dzs[MAXFIL];   /* subraster vectors */
+float ts[MAXFIL];
+
+float starmask[NMASK][NMASK];
+float parms[NPMAX];
+
+/* float a[NPMAX], fa[NPMAX], c[NPMAX][NPMAX];  fit param arrays */
+float chiimp, apertime, filltime, addtime;   /* deprecated? */
+
+float sum0, sum1, sum2, maxval, xmax, ymax, xmax2, ymax2;  /* crude star statistics */
+int   npt;
+
+float chi[5]; /* almost deprecated, but still in galaxy & shape */
+
+/* tuneup parameters */
+
+enum {NONE1, PGAUSS};
+enum {NONE2, PLANE, HUBBLE, MEDIAN};
+enum {NONE3, COMPLETE, INCOMPLETE, INTERNAL, OLDSTYLE};
+
+char flags[NFF];
+char files[64][NFF];
+bool fixpos;
+
+float  skyguess, tmin, tmax, tfac;
+float  fac, xpnd, ctpersat, widobl, cmax;
+float  stograt, discrim, sig[4], arect[3];
+float  chicrit, xtra, crit7, snlim, bumpcrit, sn2cos;
+float  enuff4, enuff7;
+float  eperdn, rnoise;
+float  acc[NPMAX], parlim[NPMAX], ava[NPMAX];
+float  beta4, beta64;
+float  pixthresh;
+float  apmagmaxerr;
+float  nphsub, nphob, apmax, apskymin, apskymax, aperrmax;
+
+int irect[3], krect[3], ibot, itop, nit, grect[3];
+int icrit, ixby2, iyby2;
+int n0left, n0right, nthpix, nbadleft, nbadright, nbadtop, nbadbot;
+int jhxwid, jhywid, mprec, napertures;
+      
+/* image data */
+float *big, *noise;
+int nfast, nslow;   /* NAXIS1, NAXIS2 of image */
+
+/* star data */
+float starpar[NSMAX][NPMAX];
+float galpar[NSMAX][NPMAX];
+float shadow[NSMAX][NPMAX];
+float shaderr[NSMAX][NPMAX];
+float apple[NSMAX][NAPPLE];
+int   imtype[NSMAX];
+int   nstot;
+float thresh;
+float probgal[NSMAX]; /* deprecated */
+float rchisq[NSMAX]; /* deprecated */
+bool  fixxy;
+
+int nregion;
+float region[100][8];
+
+/* sky data */
+float skypar[NPSKY];
+
+/* image data */
+Header header;
+Matrix matrix;
+
+float (*onestar)(int, int, float *, float *);
+float (*twostar)(int, int, float *, float *);
+float (*skyfun)(int, int, float *, float *);
+
+# include "prototypes.h"
Index: /tags/start/Ohana/src/gophot/include/prototypes.h
===================================================================
--- /tags/start/Ohana/src/gophot/include/prototypes.h	(revision 12606)
+++ /tags/start/Ohana/src/gophot/include/prototypes.h	(revision 12606)
@@ -0,0 +1,46 @@
+float pseud2d (int ix, int iy, float *a, float *fa);
+float pseud4d (int ix, int iy, float *a, float *fa);
+float skyfun_plane (int ix, int iy, float *a, float *fa);
+float chisq (float (function)(int, int, float *, float *), int *, int *, float *, float *, int, float *, float*, int, float *, float *, int);
+int ConfigInit (int *argc, char **argv);
+int addlims (float *star, int *jrect);
+int addstar (float *instar, int iadd, int type);
+char *SelectConfigFile (int *argc, char **argv, char *progname);
+char *LoadConfigFile (char *filename);
+char *ScanConfig (char *config, char *field, char *mode, int Nentry, ...);
+char *expandline (char *line, char *config);
+bool cosmic (float *star);
+int dophot ();
+int ellipse (float, float, float, float *, float *, float *, float *);
+int errupd (float *, int);
+int fillerup (int, int, int);
+float findsky ();
+bool galaxy (float *, float *, float *);
+float guess1 (float *, float *, int, int);
+float guess2 (float *, float *, int *, int *);
+float guess3 (float *, float *, int *, int *);
+int impaper2 (int);
+int improve (int);
+int isearch ();
+void lubksb (float **, int, int *, float *);
+void ludcmp (float **, int, int *, float *);
+int makemask ();
+int makenoise ();
+int mprint (int, char *, ...);
+int set_verbosity (int);
+int completeout ();
+int oblims (float *, int *);
+bool oblit (float *);
+bool oblit (float *);
+int paravg ();
+float parinterp (float, float, float *);
+int parupd (float *, float *, int, int);
+int shape ();
+int sort (float *, int);
+bool toobright (float *);
+bool toofaint (float *, float *);
+bool transmask (int, int, float);
+float twofit (float *, float *, float *, float *);
+int variparplane ();
+bool offpic (float *, int, int, float *, float *);
+float newguess (float *, float *, int, int);
Index: /tags/start/Ohana/src/gophot/src/Chisq.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/Chisq.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/Chisq.c	(revision 12606)
@@ -0,0 +1,202 @@
+# include "gophot.h"
+
+float chisq (function, ix, iy, z, dz, npts, pars, dpars, npars, Acc, Parlim, niter) 
+     float (function)(int, int, float *, float *);
+     int *ix;
+     int *iy;
+     float *z, *dz;
+     float *pars, *dpars, *Acc, *Parlim;
+     int npts, npars, niter;
+{
+
+  float **covmatr, **tmpmatr;
+  float *v, *tmpvec, *fpars;
+  int *indx;
+  bool conv, marq, limit, islimit;
+  int i, j, k, jj, kk;
+  float ifact, fact, chinew, chiold, f, dz1, fakk, d, tmpval, value;
+  float perdeg, save;
+
+  if (npars >= NPMAX) return (MAGIC);
+
+  ALLOCATE (v, float, npars);
+  ALLOCATE (indx, int, npars);
+  ALLOCATE (fpars, float, NPMAX);
+  ALLOCATE (tmpvec, float, npars);
+  ALLOCATE (covmatr, float *, npars);
+  ALLOCATE (tmpmatr, float *, npars);
+  for (i = 0; i < npars; i++) {
+    ALLOCATE (covmatr[i], float, npars);
+    ALLOCATE (tmpmatr[i], float, npars + 1);
+  }
+
+  conv = FALSE;
+  limit = FALSE;
+
+  /* check if parameters exceeds limits at the start. */
+  for (j = 0; j < npars; j++) {
+    if (Parlim[j] < 0.0) {
+      limit = fabs(pars[j]) > fabs(Parlim[j]);
+      if (limit) mprint (4, "self-deception has occured: initial limits\n");
+    }
+  }
+
+  /*
+  for (j = 0; j < npars; j++) {
+    mprint (3, "%d %f %f\n", j, pars[j], fpars[j]);
+  }
+  */
+
+  ifact = 0;
+
+  for (i = 0; (i < niter) && !conv && !limit; i++) {
+    chinew = 0.0;
+    for (j = 0; j < npars; j++) {
+      for (kk = 0; kk < npars + 1; kk++) {
+	tmpmatr[j][kk] = 0;
+      }
+    }
+
+    for (j = 0; j < npts; j++) {
+      f = function (ix[j], iy[j], pars, fpars) - z[j];
+      /* fprintf (stderr, "%d  %d %d  %f %f %f\n", j, ix[j], iy[j], f, z[j], dz[j]); */
+      dz1 = 1.0 / dz[j];
+      chinew += SQ(f)*dz1;
+      for (kk = 0; kk < npars; kk++) {
+	if (fabs(fpars[kk]) > 1e-12) {
+	  fakk = fpars[kk]*dz1;
+	  tmpmatr[kk][npars] += fakk*f;
+	  for (jj = 0; jj <= kk; jj++) {
+	    if (fabs(fpars[kk]) > 1e-12) tmpmatr[kk][jj] += fakk*fpars[jj];	
+	  }
+	}
+      }
+    } 
+
+    chiold = chinew;
+    marq = FALSE;
+    for (k = 1; (k <= 10) && !marq && !limit; k++) {
+      conv = (k == 1);
+      fact = (k == 1) ? 0.0 : pow (2.0, ifact);
+      for (j = 0; j < npars; j++) {
+	for (jj = 0; jj < j; jj++) {
+	  covmatr[j][jj] = tmpmatr[j][jj];
+	  covmatr[jj][j] = tmpmatr[j][jj];
+	}
+	covmatr[j][j] = (1+fact)*tmpmatr[j][j];
+	v[j] = tmpmatr[j][npars];
+      }
+      ludcmp (covmatr, npars, indx, &d);
+
+      /* if d = 0, the matrix was singular; no convergence. */
+      if (d == 0) {
+	mprint (4, "singular matrix!\n");
+	/* need to free arrays */
+	return (MAGIC);
+      }
+      lubksb (covmatr, npars, indx, v);
+
+      /* 
+	 check if change in parameters exceeds limits.  if Parlim(j) > 0, then
+	 consider fractional changes.  if Parlim(j) < 0, consider absolute
+	 changes.  if Parlim(j) = 0, ignore this test.
+      */
+      for (j = 0; j < npars; j++) {
+	pars[j] -= chipar*v[j];
+	if (Parlim[j] > 0.0) {
+	  tmpval = fabs (v[j]/pars[j]);
+	  islimit = (tmpval > Parlim[j]);
+	  limit = limit || islimit;
+	  if (islimit) mprint (4, "self-deception has occured: frac limits: %d  %f %f %f\n", j, pars[j], v[j], Parlim[j]);
+	}
+	if (Parlim[j] < 0.0) {
+	  islimit = (fabs (pars[j]) > fabs (Parlim[j]));
+	  limit = limit || islimit;
+	  if (islimit) mprint (4, "self-deception has occured: abs limits: %d  %f %f %f\n", j, pars[j], v[j], Parlim[j]);
+	}
+	/* check convergence */
+	if (Acc[j] > 0) {
+	  tmpval = fabs (v[j]/pars[j]);
+	  conv = conv && (tmpval <= Acc[j]);
+	} else {
+	  conv = conv && (fabs (v[j]) <= fabs (Acc[j]));
+	}
+      }
+
+      if (conv) {
+	marq = TRUE;
+      } else {
+	if (!limit) {
+	  chinew = 0.0;
+	  for (j = 0; j < npts; j++) {
+	    f = function(ix[j], iy[j], pars, (float *) NULL) - z[j];
+	    chinew += SQ(f)/dz[j];
+	  }
+	  if (k == 2) ifact --;
+	  if (chinew < 1.0001*chiold) {
+	    marq = TRUE;
+	  } else {
+	    if (k == 2) ifact += 2;
+	    if (k > 2)  ifact ++;
+	    if (ifact > 10) goto escape;
+	    for (j = 0; j < npars; j++) pars[j] += chipar*v[j];
+	  }
+	}
+      }
+
+      mprint (4, "%d, %d, ", i, k);
+      for (kk = 0; kk < npars; kk++) mprint (4, "%f ", pars[kk]);
+      mprint (4, "  %f\n", chinew);
+
+    }
+  }
+  escape:
+      
+  if (!limit) {
+    for (j = 0; j < npars; j++) {
+      for (i = 0; i < npars; i++) tmpvec[i] = 0;
+      tmpvec[j] = 1;
+      lubksb (covmatr, npars, indx, tmpvec);
+      for (i = 0; i < npars; i++) tmpmatr[i][j] = tmpvec[i];
+    }
+  }
+      
+  if (conv && !limit) {
+    perdeg = sqrt (chinew / MAX (npts - npars, 1));
+    for (i = 0; i < npars; i++) {
+      if (tmpmatr[i][i] > 0) {
+	save = sqrt (tmpmatr[i][i]);
+      } else {
+	mprint (4, "trouble: negative autovariance for tmpmatr[%d][%d] = %f\n", i, i, tmpmatr[i][i]);
+	save = 1e10;
+      }
+      for (j = 0; j < npars; j++) {
+	covmatr[i][j] = tmpmatr[i][j]/save;
+	covmatr[j][i] = tmpmatr[j][i]/save;
+      }
+      covmatr[i][i] = save*perdeg;
+    }
+    value = chiold;
+  } else {
+    value = MAGIC;
+  }
+  
+  for (i = 0; i < npars; i++) dpars[i] = SQ(covmatr[i][i]);
+
+  for (kk = 0; kk < npars; kk++) mprint (4, "%f ", pars[kk]);
+  mprint (4, "     %f\n", chiold);
+  
+  for (i = 0; i < npars; i++) {
+    free (covmatr[i]);
+    free (tmpmatr[i]);
+  }
+  free (v);
+  free (indx);
+  free (fpars);
+  free (tmpvec);
+  free (covmatr);
+  free (tmpmatr);
+
+  return (value);
+
+}
Index: /tags/start/Ohana/src/gophot/src/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/ConfigInit.c	(revision 12606)
@@ -0,0 +1,264 @@
+# include "gophot.h"
+
+# define TestConfig(A,B,C,D,E) { if (!ScanConfig (A,B,C,D,E)) { fprintf (stderr, B); exit (1); }}
+
+ConfigInit (int *argc, char **argv) {
+
+  char *config, *file;
+  float fwhm, ar, tilt;
+  char line[128];
+  int level;
+  float gmajwid, gxwid, gywid, fwhmx, fwhmy;
+  float scalefb, fbmin, scaleab, abmin, scalemb, ambmin;
+
+  /*** load configuration info ***/
+  file = argv[3];
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    exit (0);
+  }
+
+  set_verbosity (0);  /* initializes function data */
+
+  /* flags -- OK for now, not really used much */
+  flags[1] =  PGAUSS;  /* psf type */
+  flags[2] =  NONE2;   /* sky type */
+  flags[3] =  NONE3;   /* objtype_out */
+  flags[4] =  FALSE;   /* output shadow file? */
+  flags[5] =  FALSE;   /* image out? */
+  flags[6] =  FALSE;   /* warmstart? */
+  flags[7] =  FALSE;   /* load input shadow file? */
+  flags[8] =  FALSE;   /* objtype_in */
+  flags[10] = FALSE;   /* aperture correction file? */
+
+  onestar = pseud2d;
+  twostar = pseud4d;
+  skyfun  = skyfun_plane;
+
+  /* files:
+     files[2] - image_out 
+     files[3] - objects_in      - UNUSED
+     files[5] - shadowfile_out  - UNUSED
+     files[7] - shadowfile_in   - UNUSED
+     files[6] - logfile         - UNUSED
+     files[8] - apcorrfile      - UNUSED
+  */
+  
+  /** legacy - delete? */
+  n0left = 0;
+  n0right = 0;
+  nthpix = 0;
+
+  TestConfig (config, "FWHM",                   "%f", 0,    &fwhm);               /* Approx FWHM of objects (pixels) along major axis. */
+  TestConfig (config, "AXIS_RATIO",             "%f", 0,    &ar);                 /* For star objects.  AR=b/a; b=minor axis. */
+  TestConfig (config, "TILT",                   "%f", 0,    &tilt);               /* Angle of major axis in degrees; +x=0; +y=90. */
+  TestConfig (config, "SKY",                    "%f", 0,    &skyguess);           /* Approximate mean sky value in data numbers. */
+
+  /* convert to internal values */
+  fwhm *= 1.2; /* is this really necessary? */
+  tilt = tilt/57.29578;
+  gmajwid = SQ(fwhm/2.3548);
+  gxwid = gmajwid*(SQ(cos(tilt)) + SQ(ar*sin(tilt)));
+  gywid = gmajwid*(SQ(ar*cos(tilt)) + SQ(sin(tilt)));
+  fwhmx = 2.3548*sqrt(gxwid);
+  fwhmy = 2.3548*sqrt(gywid);
+  mprint (1, "fwhm x & y: %f, %f\n", fwhmx, fwhmy);
+
+  /* no longer use ava[0-3] */
+  ava[4] = gxwid;
+  ava[6] = gywid;
+  ava[5] = 0.01/sqrt(gxwid*gywid);
+  
+  TestConfig (config, "NFITBOX_X",              "%d", 0,    &irect[1]);           /* Size of fit box in the x-direction. */
+  TestConfig (config, "NFITBOX_Y",              "%d", 0,    &irect[2]);           /* Size of fit box in the y-direction. */
+  TestConfig (config, "MASKBOX_X",              "%d", 0,    &ixby2);              /* Size of mask box size in x. */
+  TestConfig (config, "MASKBOX_Y",              "%d", 0,    &iyby2);              /* Size of mask box size in y. */
+  TestConfig (config, "APBOX_X",                "%f", 0,    &arect[1]);           /* Size of aperture photometry box in x. */
+  TestConfig (config, "APBOX_Y",                "%f", 0,    &arect[2]);           /* Size of aperture photometry box in y. */
+  TestConfig (config, "NGALBOX_X",              "%d", 0,    &grect[1]);           /* Size of fit box in the x-direction. */
+  TestConfig (config, "NGALBOX_Y",              "%d", 0,    &grect[2]);           /* Size of fit box in the y-direction. */
+
+  TestConfig (config, "IBOTTOM",                "%d", 0,    &ibot);               /* Lowest allowed data value in data numbers. */
+  TestConfig (config, "ITOP",                   "%d", 0,    &itop);               /* Level where Saturation begins. */
+  TestConfig (config, "THRESHMIN",              "%f", 0,    &tmin);               /* Sigmas above sky for min threshold */
+  TestConfig (config, "THRESHMAX",              "%f", 0,    &tmax);               /* Value of maximum threshold. */
+  TestConfig (config, "THRESHDEC",              "%f", 0,    &tfac);               /* Threshold decrement in powers-of-2. */
+  TestConfig (config, "EPERDN",                 "%f", 0,    &eperdn);             /* Electrons per data number. */
+  TestConfig (config, "RDNOISE",                "%f", 0,    &rnoise);             /* Readout noise in electrons. */
+  rnoise = SQ (rnoise);  /* we will store SQ(rnoise) since this is always needed */
+
+  /* I don't like AUTOSCALE because it is not dynamic - 
+     it sets the values once here for the run, so FWHM better be right */
+  TestConfig (config, "AUTOSCALE",              "%s", 0,    line);                /* Auto-scaling of sizes by FWHM. */
+  if (!strncasecmp (line, "y", 1)) {
+    ScanConfig (config, "SCALEFITBOX",          "%f", 0,    &scalefb);          /* Size of fit box in units of FWHM. */
+    ScanConfig (config, "FITBOXMIN",            "%f", 0,    &fbmin);            /* Smallest allowed fit box size. */
+    ScanConfig (config, "SCALEAPBOX",           "%f", 0,    &scaleab);          /* Size of aperture phot box in units of FWHM. */
+    ScanConfig (config, "APBOXMIN",             "%f", 0,    &abmin);            /* Smallest allowed aperture phot box size. */
+    ScanConfig (config, "SCALEMASKBOX",         "%f", 0,    &scalemb);          /* Size of mask box in units of FWHM. */
+    ScanConfig (config, "AMASKBOXMIN",          "%f", 0,    &ambmin);           /* Smallest allowed mask box size. */
+    irect[1] = MAX (fwhmx*scalefb, fbmin);
+    irect[2] = MAX (fwhmy*scalefb, fbmin);
+    arect[1] = MAX (fwhmx*scaleab, abmin);
+    arect[2] = MAX (fwhmy*scaleab, abmin);
+    ixby2 = MAX(fwhmx*scalemb, ambmin);
+    ixby2 = MAX(fwhmy*scalemb, ambmin);
+  }
+  /* force boxes to have odd sizes */
+  if (((int)arect[1]) % 2 == 0) arect[1]++;
+  if (((int)arect[2]) % 2 == 0) arect[2]++;
+  if (irect[1] % 2 == 0) irect[1]++;
+  if (irect[2] % 2 == 0) irect[2]++;
+  if (ixby2 % 2 == 0) ixby2 ++;
+  if (iyby2 % 2 == 0) iyby2 ++;
+  ixby2 = (ixby2 - 1)/2;
+  iyby2 = (iyby2 - 1)/2;
+
+  fixpos = FALSE;
+  TestConfig (config, "FIXPOS", "%s", 0, line);                 /* Fix star positions? */
+  if (!strncasecmp (line, "y", 1)) fixpos = TRUE;
+
+  if (ScanConfig (config, "IMAGE_OUT", "%s", 0, files[2])) flags[5] = TRUE;    /* Output image name. */
+
+  TestConfig (config, "OBJTYPE_OUT", "%s", 0, &line);                /* Output format: (COMPLETE, INCOMPLETE, INTERNAL) */
+  if (!strcasecmp (line, "complete"))   flags[3] = COMPLETE;
+  if (!strcasecmp (line, "incomplete")) flags[3] = INCOMPLETE;
+  if (!strcasecmp (line, "internal"))   flags[3] = INTERNAL;
+  if (!strcasecmp (line, "oldstyle"))   flags[3] = OLDSTYLE;
+  if (flags[3] == NONE3) {
+    fprintf (stderr, "invalid OBJTYPE_OUT: %s\n", line);
+    exit (1);
+  }
+  
+  TestConfig (config, "LOGVERBOSITY",           "%d", 0,    &level);               /* Verbosity of log file; (0-4). */
+  set_verbosity (level);
+  TestConfig (config, "RESIDNOISE",             "%f", 0,    &fac);                 /* Fraction of noise to ADD to noise file. */
+  TestConfig (config, "FOOTPRINT_NOISE",        "%f", 0,    &xpnd);                /* Expand stars in noise file by this amount. */
+  TestConfig (config, "NPHSUB",                 "%f", 0,    &nphsub);              /* Limiting surface brightness for subtractions. */
+  TestConfig (config, "NPHOB",                  "%f", 0,    &nphob);               /* Limiting surface brightness for obliterations. */
+  TestConfig (config, "ICRIT",                  "%d", 0,    &icrit);               /* Obliterate if # of pixels > ITOP exceeds this. */
+  TestConfig (config, "CENTINTMAX",             "%f", 0,    &cmax);                /* Obliterate if central intensity exceeds this. */
+  TestConfig (config, "CTPERSAT",               "%f", 0,    &ctpersat);            /* Assumed intensity for saturated pixels. */
+
+  TestConfig (config, "STARGALKNOB",            "%f", 0,    &stograt);             /* Star/galaxy discriminator: bigger number, more stars */
+  TestConfig (config, "STARCOSKNOB",            "%f", 0,    &discrim);             /* Object/cosmic-ray discriminator: bigger number, more cosmics */
+  TestConfig (config, "SNLIM7",                 "%f", 0,    &crit7);               /* Minimum S/N for 7-parameter fit. */
+  crit7 = SQ(crit7);
+  TestConfig (config, "SNLIM",                  "%f", 0,    &snlim);               /* Minimum S/N for a pixel to be in fit subraster. */
+  TestConfig (config, "SNLIMMASK",              "%f", 0,    &bumpcrit);            /* Minimum S/N through mask to identify an object. */
+  TestConfig (config, "SNLIMCOS",               "%f", 0,    &sn2cos);              /* Minimum S/N to be called a cosmic ray. */
+  sn2cos = SQ(sn2cos);
+  TestConfig (config, "NBADLEFT",               "%d", 0,    &nbadleft);            /* Ignore pixels closer to the left edge than this. */
+  TestConfig (config, "NBADRIGHT",              "%d", 0,    &nbadright);           /* Ignore pixels closer to the right edge than this. */
+  TestConfig (config, "NBADTOP",                "%d", 0,    &nbadtop);             /* Ignore pixels closer to the top edge than this. */
+  TestConfig (config, "NBADBOT",                "%d", 0,    &nbadbot);             /* Ignore pixels closer to the bottom edge than this. */
+
+  TestConfig (config, "SKYTYPE",                "%s", 0,    line);                 /* SKY type: (PLANE, HUBBLE, MEDIAN) */
+  if (!strcasecmp (line, "plane")) flags[2] =  PLANE;
+  /* if (!strcasecmp (line, "hubble")) flags[2] = HUBBLE; */
+  /* if (!strcasecmp (line, "median")) flags[2] = MEDIAN; */
+  if (flags[2] == NONE2) {
+    fprintf (stderr, "invalid SKYTYPE: %s\n", line);
+    exit (1);
+  }
+
+  TestConfig (config, "NFITITER",               "%d", 0,    &nit);                 /* Maximum number of iterations. */
+  TestConfig (config, "NFITBOXFIRST_X",         "%d", 0,    &krect[1]);            /* Size of fit box in x for first pass. */
+  TestConfig (config, "NFITBOXFIRST_Y",         "%d", 0,    &krect[2]);            /* Size of fit box in y for first pass. */
+  TestConfig (config, "CHI2MINBIG",             "%f", 0,    &chicrit);             /* Critical CHI-squared for a large object. */
+  TestConfig (config, "XTRA",                   "%f", 0,    &xtra);                /* We need more S/N if some pixels are missing. */
+  TestConfig (config, "SIGMA1",                 "%f", 0,    &sig[1]);              /* Max. frac. scatter in sigma_x for stars. */
+  TestConfig (config, "SIGMA2",                 "%f", 0,    &sig[2]);              /* Max. scatter in xy cross term for stars. */
+  TestConfig (config, "SIGMA3",                 "%f", 0,    &sig[3]);              /* Max. frac. scatter in sigma_y for stars. */
+  TestConfig (config, "ENUFF4",                 "%f", 0,    &enuff4);              /* Fraction of pixels needed for 4-param fit. */
+  TestConfig (config, "ENUFF7",                 "%f", 0,    &enuff7);              /* Fraction of pixels needed for 7-param fit. */
+  TestConfig (config, "COSOBLSIZE",             "%f", 0,    &widobl);              /* Size of obliteration box for a cosmic ray. */
+  TestConfig (config, "APMAG_MAXERR",           "%f", 0,    &apmagmaxerr);         /* Max anticipated error for aperture phot report. */
+  TestConfig (config, "PIXTHRESH",              "%f", 0,    &pixthresh);           /* Trigger on pixels higher than noise*PIXTHRESH. */
+  TestConfig (config, "BETA4",                  "%f", 0,    &beta4);               /* R**4 coefficient modifier. */
+  TestConfig (config, "BETA6",                  "%f", 0,    &beta64);              /* R**6 coefficient modifier. */
+  beta4 = 1.0;
+  beta64 = 1.0;
+
+  TestConfig (config, "RELACC1",                "%f", 0,    &acc[0]);              /* Convergence criterion for sky. */
+  TestConfig (config, "RELACC2",                "%f", 0,    &acc[1]);              /* Convergence criterion for for central intensity. */
+  TestConfig (config, "RELACC3",                "%f", 0,    &acc[2]);              /* Convergence criterion for x-position. */
+  TestConfig (config, "RELACC4",                "%f", 0,    &acc[3]);              /* Convergence criterion for y-position. */
+  TestConfig (config, "RELACC5",                "%f", 0,    &acc[4]);              /* Convergence criterion for sigma-x. */
+  TestConfig (config, "RELACC6",                "%f", 0,    &acc[5]);              /* Convergence criterion for sigma-xy. */
+  TestConfig (config, "RELACC7",                "%f", 0,    &acc[6]);              /* Convergence criterion for sigma-y. */
+  TestConfig (config, "PARLIM1",                "%f", 0,    &parlim[0]);           /* Allowed change for sky value. */
+  TestConfig (config, "PARLIM2",                "%f", 0,    &parlim[1]);           /* Allowed change for central intensity. */
+  TestConfig (config, "PARLIM3",                "%f", 0,    &parlim[2]);           /* Allowed change for x-position. */
+  TestConfig (config, "PARLIM4",                "%f", 0,    &parlim[3]);           /* Allowed change for y-position. */
+  TestConfig (config, "PARLIM5",                "%f", 0,    &parlim[4]);           /* Allowed change for sigma-x. */
+  TestConfig (config, "PARLIM6",                "%f", 0,    &parlim[5]);           /* Allowed change for sigma-xy. */
+  TestConfig (config, "PARLIM7",                "%f", 0,    &parlim[6]);           /* Allowed change for sigma-y. */
+
+  /* other initial values for parameters */
+  needit = TRUE;
+  fixxy = FALSE;
+  test7 = FALSE;
+  ufactor = 100;
+  chipar = 0.9;
+
+  free (config);
+  /* free (file); */
+
+}
+
+
+# if (0) /* things used by MEDIAN sky, disabled */
+  /* only if 'median' */
+  ScanConfig (config, "JHXWID",                 "%f", 0,    &jhxwid);                 /* X Half-size of median box (.le. 0 -> autoscale) */
+  ScanConfig (config, "JHYWID",                 "%f", 0,    &jhywid);                 /* Y (same as above) */
+  ScanConfig (config, "MPREC",                  "%f", 0,    &mprec);                 /* Median precision in DN (use .le. 0 for autocalc) */
+  ScanConfig (config, "NTHPIX",                 "%f", 0,    &nthpix);                 /* Frequency of sky updates in pixels for 1st pass */
+
+  /* log is now going to stderr, up to user to redirect */
+  ScanConfig (config, "LOGFILE",                "%s", 0,    &A);                 /* Log file name.  TERM for screen. */
+  ScanConfig (config, "IMAGE_IN",               "%s", 0,    &A);                 /* Input image name.  */
+  ScanConfig (config, "OBJECTS_OUT",            "%s", 0,    &A);                 /* Output object list file name. */
+  ScanConfig (config, "PARAMS_DEFAULT",         "%s", 0,    &A);                 /* Default parameters file name. */
+  ScanConfig (config, "PARAMS_OUT",             "%s", 0,    &A);                 /* Output parameters file name. */
+  ScanConfig (config, "SHADOWFILE_OUT",         "%s", 0,    &A);                 /* Output shadow file name. */
+  ScanConfig (config, "SHADOWFILE_IN",          "%s", 0,    &A);                 /* Input shadow file name. */
+  
+  ScanConfig (config, "ABSLIM1",                "%f", 0,    &A);                 /* Allowed range for sky value. */
+  ScanConfig (config, "ABSLIM2",                "%f", 0,    &A);                 /* Allowed range for central intensity. */
+  ScanConfig (config, "ABSLIM3",                "%f", 0,    &A);                 /* Allowed range for x-position. */
+  ScanConfig (config, "ABSLIM4",                "%f", 0,    &A);                 /* Allowed range for y-position. */
+  ScanConfig (config, "ABSLIM5",                "%f", 0,    &A);                 /* Allowed range for sigma-x. */
+  ScanConfig (config, "ABSLIM6",                "%f", 0,    &A);                 /* Allowed range for sigma-xy. */
+  ScanConfig (config, "ABSLIM7",                "%f", 0,    &A);                 /* Allowed range for sigma-y. */
+  ScanConfig (config, "ABSLIM8",                "%f", 0,    &A);                 /* Allowed range for sigma-y. */
+  
+  ScanConfig (config, "NPARAM",                 "%f", 0,    &A);                 /* Maximum number of PSF fit parameters. */
+  ScanConfig (config, "NFITMAG",                "%f", 0,    &A);                 /* No. of PSF parameters to get magnitudes. */
+  ScanConfig (config, "NFITSHAPE",              "%f", 0,    &A);                 /* No. of PSF parameters to get shape and mags. */
+  
+  ScanConfig (config, "MAXSTARS",               "%f", 0,    &A);                 /* Ignore pixels closer to the bottom edge than this. */
+  ScanConfig (config, "PSFTYPE",                "%s", 0,    &A);                 /* PSF type: (PGAUSS) */
+# endif
+
+# if (0) /* autothresh eliminated: we are using threshmin = Nsigma above sky always */
+  Autothresh = FALSE;
+  ScanConfig (config, "AUTOTHRESH",             "%s", 0,    line);                 /* Auto-scaling of thresholds. */
+  if (!strncasecmp (line, "y")) Autothresh = TRUE;
+  /* only if 'autothresh' */
+  ScanConfig (config, "SIGMAIBOTTOM",           "%f", 0,    &sigbot);                 /* Level of IBOTTOM below sky in units of noise. */
+  ScanConfig (config, "SIGMATHRESHMIN",         "%f", 0,    &sigthresh);                 /* Level of THRESHMIN above sky in units of noise. */
+# endif
+
+# if (0) /* warmstart code */  
+  status = ScanConfig (config, "OBJECTS_IN",             "%s", 0,    &A);                 /* Input object list file name. */
+  if (status) {
+    flags[6] = TRUE;
+    ScanConfig (config, "OBJTYPE_IN",             "%s", 0,    &A);                 /* Input format: (COMPLETE, INTERNAL) */
+  }
+# endif
+
+# if (0) /* aperture correction file - there are several other parameters, see tuneup.f */ 
+    ScanConfig (config, "APCORRFILE",             "%s", 0,    &A);                 /* Aperture correction file name. */
+# endif
Index: /tags/start/Ohana/src/gophot/src/addlims.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/addlims.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/addlims.c	(revision 12606)
@@ -0,0 +1,34 @@
+# include "gophot.h"
+
+addlims (float *star, int *jrect) {
+
+  float temp, fudgex, fudgey;
+	
+  if (star[1] > 0) {
+    if (beta4 < 0.1) {
+      temp = star[1]/nphsub - 1.0;
+    } else {
+      temp = pow (6*star[1]/nphsub, 0.33333);
+    }
+    if (star[4] > 0) {
+      fudgex = sqrt(temp*star[4]*2);
+    } else {
+      fudgex = 1.5*irect[1]/2;
+    }
+    if (star[6] > 0) {
+      fudgey = sqrt(temp*star[6]*2);
+    } else {
+      fudgey = 1.5*irect[2]/2;
+    }
+  } else {
+    fudgex = 1.5*irect[1]/2;
+    fudgey = 1.5*irect[2]/2;
+  }
+  /* don't extrapolate beyond 2*fit box */
+  fudgex = MIN (irect[1], fudgex);
+  fudgey = MIN (irect[2], fudgex);
+  jrect[1] = star[2] - fudgex;
+  jrect[2] = star[2] + fudgex;
+  jrect[3] = star[3] - fudgey;
+  jrect[4] = star[3] + fudgey;
+}
Index: /tags/start/Ohana/src/gophot/src/addstar.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/addstar.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/addstar.c	(revision 12606)
@@ -0,0 +1,60 @@
+# include "gophot.h"
+
+addstar (float *instar, int iadd, int type) {
+
+  float star0[NPMAX], star1[NPMAX], *bigval, *noiseval;
+  float sky, bfactor, bsky, cfactor, csky, val;
+  int ix, iy, jrect[5];
+  int i, j, ihi, ilo, jhi, jlo, ixin, iyin;
+	
+  if (type == 12) beta4 = 0.01;
+
+  needit = FALSE;
+	
+  sky = guess2 (star0, instar, &ixin, &iyin);
+  sky = guess2 (star1, instar, &ixin, &iyin) / ufactor;
+	
+  addlims (instar, jrect);
+  star1[4] = star0[4]*SQ(xpnd);
+  star1[5] = star0[5]/SQ(xpnd);			
+  star1[6] = star0[6]*SQ(xpnd);
+	
+  bfactor = ufactor*iadd;
+  bsky = iadd*(0.5 - sky);  /* why the 0.5? */
+  cfactor = fac*ufactor;
+  csky = 0.5 - fac*sky;
+
+  ilo = MAX (jrect[1], 0);
+  ihi = MIN (jrect[2], nfast-1);
+  jlo = MAX (jrect[3], 0);
+  jhi = MIN (jrect[4], nslow-1);
+	
+  for (j = jlo; j <= jhi; j++) {
+    iy = j - iyin;
+    bigval = &big[ilo + j*nfast];
+    noiseval = &noise[ilo + j*nfast];
+    for (i = ilo; i <= ihi; i++, bigval++, noiseval++) {
+      if (!finite (*noiseval)) continue;
+      ix = i - ixin;
+      /* shouldn't bfactor multiply both onestar and bsky? */
+      val = ufactor*(onestar (ix, iy, star0, (float *) NULL) - sky);
+      *bigval += iadd*val;
+
+      val = fac*ufactor*fabs(onestar (ix, iy, star1, (float *) NULL) - sky);
+      *noiseval -= iadd*val;
+
+      if (*noiseval <= -1000) {
+	mprint (2, "i,j,noise = %d, %d, %f, %f %f %f %d, negative noise! obliterating\n", i, j, *noiseval, val, *bigval, cfactor, iadd);
+	/*
+	*bigval = MAGIC;
+	*noiseval = MAGIC;
+	*/
+      }
+    }
+  }
+  needit = TRUE;
+  beta4 = 1.0;
+}
+
+/* star0 is the nominial star region, star1 is the expanded are for the noise array */
+
Index: /tags/start/Ohana/src/gophot/src/cosmic.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/cosmic.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/cosmic.c	(revision 12606)
@@ -0,0 +1,84 @@
+# include "gophot.h"
+
+bool cosmic (float *star) {
+
+  float dummy[NPMAX];
+  float obs, maxob, sky, chistar, chicos, pred, temp;
+  float sn2, tnoise, *Bval, *Nval;
+  int ix, iy, I, J, ii, jj, npix, imax, jmax;
+  bool pointy;
+
+  pointy = FALSE;
+
+  sky = guess2 (dummy, star, &ix, &iy);
+  temp = big[ix + iy*nfast] / ufactor - dummy[0];
+  if (finite (temp)) dummy[1] = temp;
+  maxob = -HUGE_VAL;
+  chistar = 0;
+  chicos  = 0;
+  npix = 0;
+  
+  for (J = -1; J <= 1; J++) {
+    jj = iy + J;
+    if (jj < 0) continue;
+    if (jj > nslow - 1) continue;
+    
+    Bval = &big[ix - 1 + jj*nfast];
+    Nval = &noise[ix - 1 + jj*nfast];
+    
+    for (I = -1; I <= 1; I++, Bval++, Nval++) {
+      ii = ix + I;
+      if (ii < 0) continue;
+      if (ii > nfast - 1) continue;
+      if (!finite (*Nval)) continue;
+      npix ++;
+      pred = ufactor*onestar (I, J, dummy, (float *) NULL);
+      obs = *Bval;
+      temp = 1.0 / (*Nval + *Bval);
+      chistar += SQ (obs - pred) * temp;
+      sn2 = SQ (obs - sky) * temp;
+      chicos += sn2;
+      if ((obs > maxob) && (sn2 >= sn2cos)) {
+	imax = ii;
+	jmax = jj;
+	maxob = obs;
+	tnoise = temp;
+      }
+    }
+  }
+
+  /* this is meant to test if the object is mostly a single pixel event.
+     doesn't do a good job of distinguishing a single pixel event from a
+     generally poor fit to the top of the star. */
+  if ((npix >= 7) && (maxob > -HUGE_VAL)) {
+    chicos -= SQ (maxob - sky) * tnoise;
+    pointy = (chicos/chistar < discrim);
+    mprint (3, "location %d, %d,  chi-star & chi-cosmic = %f, %f\n", ix, iy, chistar, chicos);
+  }
+
+  if (pointy) {
+    mprint (2, "cosmic ray intensity, x, y: %f %d %d\n", maxob, imax, jmax);
+    star[0] = sky;
+    star[1] = maxob;
+    star[2] = imax;
+    star[3] = jmax;
+    star[4] = widobl;
+    star[5] = -1;
+    star[6] = widobl;
+  }
+  return (pointy);
+}
+
+/* We are basically comparing if the object is more like a stellar
+   object, or if it is compatible with a single high point over a
+   general sky-like region.  
+
+   we have a danger here that a wide object will boost Io
+   significantly, which in turn makes the fit to the object
+   particularly poor in the center areas.  This in turn makes the
+   object seem comparable to the sky, and therefore a cosmic.  Since
+   we really only care if the inner 9 pixels are comparable to the
+   star shape, vaguely, we can fudge this by temporarily setting Io to
+   the central pixel value.  We don't bother if that pixel is bad (NaN).
+
+*/
Index: /tags/start/Ohana/src/gophot/src/delete_ellipse.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/delete_ellipse.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/delete_ellipse.c	(revision 12606)
@@ -0,0 +1,81 @@
+# include "gophot.h"
+
+float delete_ellipse (float *par, float sky) {
+
+  int i, j, npix;
+  float theta, phi;
+  float xp, yp, x, y, dx, dy, Dx, Dy;
+  float Chi, dv, Dv, R2, F2, r1, r2;
+  float flux, mean;
+
+  npix = flux = 0;
+
+  dx = MAX (par[2], par[3]) + 2;
+  dy = MAX (par[2], par[3]) + 2;
+
+  for (j = par[1] - dy; j < par[1] + dy; j++) {
+    if (j < 0) continue;
+    if (j >= nslow) continue;
+    for (i = par[0] - dx; i < par[0] + dx; i++) {
+      if (i < 0) continue;
+      if (i >= nfast) continue;
+    
+      Dx = i - par[0];
+      Dy = j - par[1];
+      phi = atan2 (Dy, Dx) - RAD_DEG * par[4];
+      theta = atan2 (par[2]*sin(phi), par[3]*cos(phi));
+      
+      /* this is the point on the ellipse at the same angle as ref point */
+      xp = par[2] * cos (theta);
+      yp = par[3] * sin (theta);
+    
+      x = xp * cos (par[4] * RAD_DEG) - yp * sin (par[4] * RAD_DEG);
+      y = xp * sin (par[4] * RAD_DEG) + yp * cos (par[4] * RAD_DEG);
+      
+      r1 = hypot (Dx, Dy);
+      r2 = hypot (x, y);
+      
+      if (r1 < r2) {
+	flux += big[i + nfast*j] - sky;
+	npix ++;
+      }
+
+    }
+  }
+  mean = flux / npix;
+  fprintf (stderr, "flux: %f, mag: %f, mean: %f\n", flux, -2.5*log10(flux), flux / npix);
+
+  for (j = par[1] - dy; j < par[1] + dy; j++) {
+    if (j < 0) continue;
+    if (j >= nslow) continue;
+    for (i = par[0] - dx; i < par[0] + dx; i++) {
+      if (i < 0) continue;
+      if (i >= nfast) continue;
+    
+      Dx = i - par[0];
+      Dy = j - par[1];
+      phi = atan2 (Dy, Dx) - RAD_DEG * par[4];
+      theta = atan2 (par[2]*sin(phi), par[3]*cos(phi));
+      
+      /* this is the point on the ellipse at the same angle as ref point */
+      xp = par[2] * cos (theta);
+      yp = par[3] * sin (theta);
+    
+      x = xp * cos (par[4] * RAD_DEG) - yp * sin (par[4] * RAD_DEG);
+      y = xp * sin (par[4] * RAD_DEG) + yp * cos (par[4] * RAD_DEG);
+      
+      r1 = hypot (Dx, Dy);
+      r2 = hypot (x, y);
+      
+      if (r1 < r2) {
+	big[i + nfast*j] -= mean;
+      }
+      if (r1 < 1.2*r2) {
+	noise[i + nfast*j] += fac*(mean + sky);
+      }
+
+    }
+  }
+  fprintf (stderr, "flux: %f, mag: %f, mean: %f\n", flux, -2.5*log10(flux), flux / npix);
+  return (flux);
+}
Index: /tags/start/Ohana/src/gophot/src/dophot.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/dophot.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/dophot.c	(revision 12606)
@@ -0,0 +1,94 @@
+# include "gophot.h"
+float set_thresholds (float, float, float *, int *);
+void large_features (float, float);
+int fix_mediansky  (float);
+float get_mediansky (int, int);
+
+dophot () {
+
+  bool first, lastround;
+  float factor, sky, dsky;
+  int nstar, Nit, i, j;
+  char c;
+  int xtest, ytest;
+  struct timeval now, then;  
+  
+  makenoise ();
+  make_mediansky ();
+  get_skystats (&sky, &dsky);
+  fix_mediansky (sky);
+
+  /*
+  gettimeofday (&then, (void *) NULL);
+  for (i = 0; i < nfast; i++) {
+    for (j = 0; j < nslow; j++) {
+      sky = get_mediansky (i, j);
+      big[j*nfast + i] -= sky;
+    }
+  }
+  gettimeofday (&now, (void *) NULL);
+  fprintf (stderr, "elapsed time = %.2f sec\n", 
+	   (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec));
+
+  fits_write_header ("test.sub", &header);
+  fits_write_matrix ("test.sub", &matrix);
+  exit (0);
+  */
+
+  thresh = set_thresholds (sky, dsky, &factor, &Nit);
+
+  /* large_features (sky, dsky); */
+
+  first = TRUE;
+  lastround = FALSE;
+
+  for (i = 0; i < Nit + 1; i++) {
+    mprint (0, "starting loop at threshold level %f\n", thresh);
+	   
+    if (i == Nit) lastround = TRUE;
+
+    makemask ();
+
+    /* fix pos needs to be defined correctly */
+    if (fixpos && first) improve (FALSE);
+	   
+    nstar = isearch (first);
+    shape ();
+    paravg ();
+
+    improve (lastround);
+	   
+    mprint (1, " ending loop at threshold level %f\n", thresh); 
+    mprint (1, " number of new objects found on this threshold = %f\n", nstar); 
+    mprint (1, " total number of objects found so far = %d\n", nstot); 
+    
+    thresh /= factor;
+
+    first = FALSE;
+
+# if (0)
+    fits_write_header ("test.sub", &header);
+    fits_write_matrix ("test.sub", &matrix);
+
+    completeout (nstot);
+    fprintf (stderr, "type return to continue:  ");
+    fscanf (stdin, "%c", &c);
+# endif
+
+  }
+
+  feature_fluxes ();
+
+  if (lastround) {
+    if (flags[3] == COMPLETE) completeout (nstot);
+  }
+	   
+    /* 
+    fits_write_header ("test.sub", &header);
+    fits_write_matrix ("test.sub", &matrix);
+    completeout (nstot);
+    fprintf (stderr, "type return to continue:  ");
+    fscanf (stdin, "%c", &c);
+    */
+
+}
Index: /tags/start/Ohana/src/gophot/src/ellipse.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/ellipse.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/ellipse.c	(revision 12606)
@@ -0,0 +1,57 @@
+# include <math.h>
+# include <stdio.h>
+# define SQ(X)    (double) (((double)(X))*((double)(X)))
+
+int ellipse (float Sx, float Sxy, float Sy,
+	     float *area, float *amaj, float *amin, float *angle) {
+
+  float A1, A2, A3, R, root1, root2;
+
+  if (fabs(Sxy) >= 1.0 / sqrt(fabs(Sx*Sy))) {
+    *area = 0.0;
+    *amaj = 0.0;
+    *amin = 0.0;
+    *angle = 0.0;
+    /* this is a poor fit - not an ellipse but a hyperbola */
+    return (0);
+  }
+
+  A1 = 1/(2*Sx);
+  A2 = 1/(2*Sy);
+  A3 = Sxy;
+  
+  *angle = atan2(-A3, A2 - A1) / 2.0;
+  R = sqrt( SQ(A2 - A1) + SQ(A3));
+  root1 = (A1 + A2 + R);
+  root2 = (A1 + A2 - R);
+
+  *area = 2.0*M_PI/sqrt(root1*root2);
+  *amaj = 2.35482*sqrt(1.0/root2);
+  *amin = 2.35482*sqrt(1.0/root1);
+
+  return (1);
+
+}
+
+
+/* In this function, Sx & Sy represent sx^2, sy^2 
+
+   given an elliptical Gaussian of the form:
+
+   exp (-z); z = x^2 / 2 sx^2 + y^2 / 2 sy^2 + xy Sxy
+
+   Sa, Sb, and angle can be found by:
+
+   A1 = 1/(2 Sx)
+   A2 = 1/(2 Sy)
+   A3 = Sxy
+   
+   R = sqrt ((A2 - A1)^2 + A3^2)
+   root1 = (A1 + A2 + R)
+   root2 = (A1 + A2 - R)
+   
+   angle = atan2 (-A3, A2 - A1) / 2.0
+   Sa = sqrt (1.0/root2)
+   Sb = sqrt (1.0/root1)
+   
+*/
Index: /tags/start/Ohana/src/gophot/src/feature_fluxes.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/feature_fluxes.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/feature_fluxes.c	(revision 12606)
@@ -0,0 +1,56 @@
+# include "gophot.h"
+
+float feature_fluxes () {
+
+  int i, j, npix, n;
+  float theta, phi, cs, sn;
+  float xp, yp, x, y, dx, dy, Dx, Dy;
+  float r1, r2;
+  float flux, mean, sky;
+
+  for (n = 0; n < nregion; n++) {
+
+    npix = flux = 0;
+    
+    dx = MAX (region[n][4], region[n][5]) + 2;
+    dy = MAX (region[n][4], region[n][5]) + 2;
+    cs = cos (region[n][6] * RAD_DEG);
+    sn = sin (region[n][6] * RAD_DEG);
+    sky = region[n][0];      
+
+    for (j = region[n][3] - dy; j < region[n][3] + dy; j++) {
+      if (j < 0) continue;
+      if (j >= nslow) continue;
+      for (i = region[n][2] - dx; i < region[n][2] + dx; i++) {
+	if (i < 0) continue;
+	if (i >= nfast) continue;
+	
+	Dx = i - region[n][2];
+	Dy = j - region[n][3];
+	phi = atan2 (Dy, Dx) - RAD_DEG * region[n][6];
+	theta = atan2 (region[n][4]*sin(phi), region[n][5]*cos(phi));
+	
+	/* this is the point on the ellipse at the same angle as ref point */
+	xp = region[n][4] * cos (theta);
+	yp = region[n][5] * sin (theta);
+	
+	x = xp * cs - yp * sn;
+	y = xp * sn + yp * cs;
+	
+	r1 = hypot (Dx, Dy);
+	r2 = hypot (x, y);
+	
+	if (r1 < r2) {
+	  flux += big[i + nfast*j] - sky;
+	  npix ++;
+	}
+	
+      }
+    }
+    /* existing image has mean subtracted = flux*Npix */
+    flux += region[n][1];
+    mean = flux / npix;
+    fprintf (stderr, "sub flux: %f, mag: %f, mean: %f\n", flux, -2.5*log10(flux), flux / npix);
+    region[n][7] = flux;
+  }
+}
Index: /tags/start/Ohana/src/gophot/src/fillerup.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/fillerup.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/fillerup.c	(revision 12606)
@@ -0,0 +1,169 @@
+# include "gophot.h"
+
+fillerup (int xo, int yo, int findstats) {
+
+  float *bigval, *noiseval, ufactor2, snlim2;
+  int i, j, ilo, ihi, jlo, jhi, ix, iy, idist, nsky, maxnpt, outer;
+  int *x, *y;
+  float *z, *d;
+  float N, S, F, Sx, Sy, Sx2, Sy2, xv, yv;
+  float value, SNR, sky;
+
+  ufactor2 = SQ(ufactor);
+  snlim2 = SQ(snlim);
+  npt = 0;
+  nsky = 0;
+
+  ilo = MAX (xo - nrect[1]/2, 0);
+  ihi = MIN (xo + nrect[1]/2, nfast-1);
+  jlo = MAX (yo - nrect[2]/2, 0);
+  jhi = MIN (yo + nrect[2]/2, nslow-1);
+  
+  outer = MIN (nrect[1]/3, nrect[2]/3);
+  
+  for (j = jlo; j <= jhi; j++) {
+    bigval = &big[ilo + j*nfast];
+    noiseval = &noise[ilo + j*nfast];
+    for (i = ilo; i <= ihi; i++, bigval++, noiseval++) {
+      if (!finite (*bigval)) continue;
+      if (!finite (*noiseval)) continue;
+      if (SQ(*bigval) < (*bigval + *noiseval) * snlim2) continue;
+      if (*bigval < (*noiseval - rnoise)) continue;
+      ix = i - xo;
+      iy = j - yo;
+      xs[npt] = ix;
+      ys[npt] = iy;
+      zs[npt] = *bigval/ufactor;
+      dzs[npt] = (*bigval + *noiseval) / ufactor2;
+      idist = MAX (abs(ix), abs(iy));
+      if (idist > outer) {
+	ts[nsky] = zs[npt];
+	nsky ++;
+      }
+      npt ++;
+    }
+  }
+  
+  if (npt == 0) return (FALSE);
+  if (!findstats) return (TRUE);
+
+  if (nsky == 0) return (FALSE);
+
+  sort (ts, nsky);
+  sky = ts[(int)(0.5*nsky)];
+  sum2 = sky;
+
+  z = zs;
+  d = dzs;
+  S = N = 0;
+  for (i = 0; i < npt; i++, z++, d++) {
+    if (*z < sky) continue;
+    N += *d;
+    S += *z - sky;
+  }
+
+  if (S < 0) return (FALSE);
+  SNR = S*S / N;
+  if (SNR < SQ(bumpcrit)) return (FALSE);
+
+  if (SNR > 49) {
+    x = xs;
+    y = ys;
+    z = zs;
+    d = dzs;
+    N = S = Sx = Sy = Sx2 = Sy2 = 0;
+    for (i = 0; i < npt; i++, x++, y++, z++, d++) {
+      idist = MAX (abs(*x), abs(*y));
+      if (idist > outer) continue;
+      if (*z < sky) continue;
+      value = *z - sky;
+      xv = *x * value;
+      yv = *y * value;
+      N += *d;
+      S += value;
+      Sx += xv;
+      Sx2 += *x * xv;
+      Sy += yv;
+      Sy2 += *y * yv;
+    }
+    xmax = Sx / S;
+    ymax = Sy / S;
+    xmax2 = fabs(Sx2 / S - xmax*xmax);
+    ymax2 = fabs(Sy2 / S - ymax*ymax);
+    maxval = S / sqrt (xmax2*ymax2);
+  } else {
+    z = zs;
+    maxval = *z;
+    maxnpt = 0;
+    for (i = 0; i < npt; i++, z++) {
+      if (*z > maxval) {
+	maxnpt = i;
+	maxval = *z;
+      }
+    }
+    xmax = xs[maxnpt];
+    ymax = ys[maxnpt];
+    xmax2 = ava[4];
+    ymax2 = ava[6];
+    maxval -= sum2; 
+ }
+
+  maxval *= ufactor;
+  sum2 *= ufactor;
+
+  if (!finite (maxval)) return (FALSE);
+  return (TRUE);
+  
+}
+
+/* adjust the errors by the deviation from the guess fit */
+filladjust (float *star) {
+
+  int i;
+  float f, df;
+
+  return (0);
+  if (star[1] < cmax/(ufactor*10)) return (0); 
+
+  for (i = 0; i < npt; i++) {
+
+    f = onestar ((int)xs[i], (int)ys[i], star, (float *) NULL);
+    
+    df = 10 * fabs(f - zs[i]);
+    dzs[i] += df/ufactor;
+  }
+
+}
+
+/* check if weighted center is in OK location 
+   weighted center is based on useable pixels, not
+   on entire box */
+centertest (float *star, int *x, int *y) {
+
+  int i;
+  float f, df, Sf, Sx, Sy, dx, dy;
+
+  Sf = Sx = Sy = 0;
+
+  for (i = 0; i < npt; i++) {
+
+    f = onestar ((int)xs[i], (int)ys[i], star, (float *) NULL);
+    
+    Sf += f;
+    Sx += f*xs[i];
+    Sy += f*ys[i];
+
+  }
+
+  dx = star[2] - Sx/Sf;
+  dy = star[3] - Sy/Sf;
+
+  if ((fabs(dx) > 0.25*nrect[1]) || (fabs(dy) > 0.25*nrect[2])) {
+    mprint (3, "center %f %f %f\n", dx, dy, Sf);
+    return (TRUE);
+  }
+
+  return (FALSE);
+
+}
+
Index: /tags/start/Ohana/src/gophot/src/findsky.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/findsky.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/findsky.c	(revision 12606)
@@ -0,0 +1,36 @@
+# include "gophot.h"
+
+float findsky () {
+
+  int i, skip, nsky, bin;
+  int zvalue[0x10000], nvalue;
+  float median, *valB;
+  
+  skip = 100;
+  valB = big;
+
+  for (i = 0; i < nfast*nslow; i+=skip, valB+=skip) {
+    bin = *valB;
+    if ((bin >= 0) && (bin < 0x10000)) {
+      nvalue ++;
+      zvalue[bin] ++;
+    }
+  }
+  
+  nsky = 0;
+  for (i = 0; (i < 0x10000) && (nsky < nvalue / 2); i++) {
+    nsky += zvalue[i];
+  }
+  if (nsky < nvalue / 2) {
+    mprint (1, "weird situation: no median found\n");
+    exit (1);
+  }
+  median = i;
+  mprint (1, "median = %f\n", median);
+
+  return (median);
+}
+
+/* arguments OK */
+
+/* this median method assumes 64k data range */
Index: /tags/start/Ohana/src/gophot/src/galaxy.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/galaxy.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/galaxy.c	(revision 12606)
@@ -0,0 +1,58 @@
+# include "gophot.h"
+
+/* this is kind of stupid:  this function takes two 
+   lists of the parameters for the object because 
+   star1 has x, y, relative to 0, */
+
+bool galaxy (float *star1, float *err, float *star2) {
+
+  float dummy[NPMAX], tot[4], temp, nsigma;
+  int i;
+  bool value;
+
+  value = FALSE;
+
+  for (i = 0; i < 4; i++) chi[i] = 0;
+	
+  parinterp (star2[2], star2[3], dummy);
+
+  /* if errors on sigma x or y are so large, call it a galaxy */
+  if (dummy[4] < 3*sqrt(err[4])) return (TRUE);
+  if (dummy[6] < 3*sqrt(err[6])) return (TRUE);
+
+  /* too weak a measurement to be called galaxy */
+  if (star1[4] < 2*sqrt(err[4])) return (FALSE);
+  if (star1[6] < 2*sqrt(err[6])) return (FALSE);
+  if (star1[1] < 2*sqrt(err[1])) return (FALSE); 
+
+  /*************************************************************
+   I'm rather concerned about 'parsm' where did it come from? 
+  parms[] is set in varipar_plane.c  */							
+  temp = SQ (sig[1]*dummy[4]);
+  tot[1] = MAX (parms[4], temp);
+  temp = SQ (sig[2])/(dummy[4]*dummy[6]);
+  tot[2] = MAX (parms[5], temp);
+  temp = SQ (sig[3]*dummy[6]);
+  tot[3] = MAX (parms[6], temp);
+  chi[1] = SQ (star1[4] - dummy[4]) / (tot[1] + err[4]);
+  chi[2] = SQ (star1[5] - dummy[5]) / (tot[2] + err[5]);
+  chi[3] = SQ (star1[6] - dummy[6]) / (tot[3] + err[6]);
+
+  if (star1[4] < dummy[4]) chi[1] = 0;
+  if (star1[6] < dummy[6]) chi[3] = 0;
+  chi[4] = chi[1] + chi[2] + chi[3];
+
+  mprint (2, "galaxy test, object at %f %f  %f\n", star2[2], star2[3], star2[1]);
+  mprint (2, "chisqs: %f %f %f %f\n", chi[1], chi[2], chi[3], chi[4]);
+
+  nsigma = MIN (sqrt(chi[4]), 1.0e8);
+  mprint (2, "nsigma = %f\n", nsigma);
+
+  value = chi[4] >= chicrit;
+
+  return (value);
+
+}
+
+/* this function uses C 0,N-1 for a[], fa[] */
+
Index: /tags/start/Ohana/src/gophot/src/gophot.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/gophot.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/gophot.c	(revision 12606)
@@ -0,0 +1,54 @@
+# include "gophot.h"
+
+main (int argc, char **argv) {
+
+  float tmp;
+
+  if (argc < 4) {
+    fprintf (stderr, "ERROR: usage: dophot imagename outfile paramfile\n");
+    exit (0);
+  }
+  ConfigInit (&argc, argv);
+
+  fprintf (stderr, "reading from %s, writing to %s, %s param file\n", argv[1], argv[2], argv[3]);
+
+  FT_UNSIGN_MODE = FALSE;
+  strcpy (files[4], argv[2]);
+
+  /* load image header and data */
+  if (!fits_read_header (argv[1], &header)) {
+    fprintf (stderr, "ERROR: can't open FITS header %s\n", argv[1]);
+    exit (1);
+  }
+  if (!fits_read_matrix (argv[1], &matrix)) {
+    fprintf (stderr, "ERROR: can't open FITS matrix %s\n", argv[1]);
+    exit (1);
+  }
+  /* convert to float, set up noise array and axes */
+  fits_convert_format (&header, &matrix, -32, 1.0, 0.0, 0);
+  ALLOCATE (noise, float, matrix.size);
+  big = (float *) matrix.buffer;
+  nfast = matrix.Naxis[0];
+  nslow = matrix.Naxis[1];
+ 
+  /* override config values with header values */ 
+  if (fits_scan (&header, "SATVALUE", "%f", 1, &tmp)) itop = tmp;
+  if (fits_scan (&header, "GAIN", "%f", 1, &tmp)) eperdn = tmp;
+  if (fits_scan (&header, "NEWGAIN", "%f", 1, &tmp)) eperdn = tmp;
+
+  /* we are scaling the image to electrons, must also scale parameters */
+  itop *= eperdn;
+  ibot *= eperdn;
+  tmax *= eperdn;
+  cmax *= eperdn;
+  ctpersat *= eperdn;
+
+  dophot (); 
+
+  fprintf (stderr, "SUCCESS\n");
+}
+
+/* in the rest of the program:
+   NFAST = matrix.Naxis[0]  -- # of X-axis pixels 
+   NSLOW = matrix.Naxis[1]  -- # of Y-axis pixels 
+*/
Index: /tags/start/Ohana/src/gophot/src/guess.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/guess.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/guess.c	(revision 12606)
@@ -0,0 +1,72 @@
+# include "gophot.h"
+
+/* fill in values for star[NPMAX] based on rough stats and sky model */
+float guess1 (float *star, float *dummy, int ix, int iy) {
+
+  /* parinterp fills in star[4,5,6] from averages */
+  parinterp (ix, iy, star);
+
+  star[0] = sum2/ufactor;
+  star[1] = maxval/ufactor;
+  star[2] = xmax;
+  star[3] = ymax;
+
+  return (0.0);
+
+}
+
+/* fill in values for star[NPMAX] based on rough stats and sky model */
+/* use sigma_x, sigma_y from fillerup */
+float newguess (float *star, float *dummy, int ix, int iy) {
+
+  star[0] = sum2 / ufactor;
+  star[1] = maxval / ufactor;
+  star[2] = xmax;
+  star[3] = ymax;
+  star[4] = xmax2;
+  star[5] = 0;
+  star[6] = ymax2;
+  
+  return (0.0);
+}
+
+/* fill in values for star from instar, rescaling */
+float guess2 (float *star, float *instar, int *ix, int *iy) {
+
+  /* i'm concerned that the ix, iy values need to be passed back. */
+  float value;
+
+  *ix = (int) (instar[2] + 0.5);
+  *iy = (int) (instar[3] + 0.5);
+
+  star[0] = instar[0]/ufactor;
+  star[1] = instar[1]/ufactor;
+  star[2] = instar[2] - *ix;
+  star[3] = instar[3] - *iy;
+  star[4] = instar[4];
+  star[5] = instar[5];
+  star[6] = instar[6];
+
+  value = instar[0];				
+  return (value);
+}
+
+
+/* fill in values for star from instar, rescaling */
+float guess3 (float *star, float *instar, int *ix, int *iy) {
+
+  float value;
+
+  *ix = (int) (instar[2] + 0.5);
+  *iy = (int) (instar[3] + 0.5);
+
+  parinterp (instar[2], instar[3], star);
+
+  star[0] = instar[0]/ufactor;
+  star[1] = instar[1]/ufactor;
+  star[2] = instar[2] - *ix;
+  star[3] = instar[3] - *iy;
+
+  value = instar[0];				
+  return (value);
+}
Index: /tags/start/Ohana/src/gophot/src/impaper2.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/impaper2.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/impaper2.c	(revision 12606)
@@ -0,0 +1,42 @@
+# include "gophot.h"
+
+impaper2 (int k) {
+
+  int i, nsky, nsort;
+  float sky, sum, r, dr, zsort[MAXFIL];
+
+  /* find median sky outside inner radius */
+
+  dr = 0.5*(SQ (0.5*arect[1]) + SQ (0.5*arect[2]));
+  nsort = 0;
+  for (i = 0; i < npt; i++) {
+    r = SQ (xs[i]) + SQ (ys[i]);
+    if (r >= dr) {
+      zsort[nsort] = zs[i];
+      nsort ++;
+    }
+  }
+  
+  if (nsort < 1) return (0);
+
+  sort (zsort, nsort);
+        
+  sky = 0;
+  nsky = 0;
+  for (i = 0.25*nsort; i < 0.75*nsort; i++) {
+    sky += zsort[i];
+    nsky ++;
+  }
+  sky /= nsky;
+
+  sum = 0;
+  for (i = 0; i < npt; i++) {
+    sum += (zs[i] - sky);
+  }
+        
+  apple[k][1] = sum*ufactor;
+
+  return (1);
+
+}
+
Index: /tags/start/Ohana/src/gophot/src/improve.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/improve.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/improve.c	(revision 12606)
@@ -0,0 +1,117 @@
+# include "gophot.h"
+
+# define ADD +1
+# define SUB -1
+
+improve (int last) {
+
+  float err[NPMAX], star[NPMAX], sky, dx, dy, starchi;
+  int i, k, ix, iy, jmtype, niter, nfit;
+  bool skip, snok;
+
+  /* imtype may be 1-9 for regular objects, 101-109 for fixed objects */
+
+  for (i = 0; i < nstot; i++) {
+
+    /* set up flags for fixed objects */
+    fixxy = fixpos && (imtype[i] >= 100);
+    jmtype = fixxy ? imtype[i] - 100 : imtype[i];
+    /* inverse: imtype[i] = fixxy ? jmtype + 100 : jmtype; */
+
+    if (jmtype == 0) continue;
+    if (jmtype == 6) continue;
+    if (jmtype == 16) continue;
+    if (jmtype == 8) continue;
+    if (jmtype == 18) continue;
+
+    /* if (jmtype == 3) continue; */
+    if (jmtype == 2) continue;
+    if (jmtype == 12) continue;
+    if (jmtype == 10) continue;
+	   
+    /* add star back to frame, get sky, get subraster */
+    addstar (starpar[i], ADD, jmtype);
+    sky = guess3 (star, starpar[i], &ix, &iy);
+    mprint (3, " improving star %d at %d, %d\n", i, ix, iy);
+    nrect[1] = irect[1];
+    nrect[2] = irect[2];
+    fillerup (ix, iy, FALSE);  /* we don't use the center information here */
+
+    /* skip star if off picture, has negative flux, or if s/n too low for non-fixed objects */
+    skip = offpic (star, ix, iy, &dx, &dy);
+    if (star[1] <= 0) {
+      skip = TRUE;
+      starpar[i][1] = 0;
+    }
+    if (!skip && !fixxy) {
+      snok = transmask (ix,iy,sky);
+      skip = skip && !snok;
+    }
+    if (skip) {
+      jmtype = 6;
+      mprint (3, " deactivating star %d at %d, %d\n", i, ix, iy);
+      imtype[i] = fixxy ? jmtype + 100 : jmtype;
+      continue;
+    }
+
+    /* fixed objects only vary x,y */
+    if (fixxy) {
+      nfit = NFIT0;
+      niter = 2;
+    } else {
+      nfit = NFIT1;
+      niter = nit;
+    }
+
+    filladjust (star); 
+
+    /* fit for magnitudes -- 4 param fit (or 2 for fixed obj) (initial guesses in are the previous fits) */
+    starchi = chisq (onestar, xs, ys, zs, dzs, npt, star, err, nfit, acc, parlim, niter);
+
+    /* set non-converge objects to type 4, don't bother with other calcs */
+    if (!finite(starchi)) {
+      if (jmtype != 3) jmtype = 4;
+      for (k = 0; k < NPMAX; k++) galpar[i][k] = starpar[i][k];
+      for (k = 0; k < NPMAX; k++) shadow[i][k] = starpar[i][k];
+      apple[i][4] = MIN (1.086*sqrt(err[1])/star[1], 1);
+      addstar (starpar[i], SUB, jmtype);
+      imtype[i] = fixxy ? jmtype + 100 : jmtype;
+      continue;
+    }
+
+    /* things which get negative flux, turn in to type 6 and skip */
+    if (star[1] <= 0) {
+      starpar[i][1] = 0;
+      jmtype = 6;
+      mprint (3, " deactivating star %d at %d, %d\n", i, ix, iy);
+      imtype[i] = fixxy ? jmtype + 100 : jmtype;
+      continue;
+    }
+
+    /* this section applies to type 1 3 5 7 */
+    if ((jmtype != 2) && (jmtype != 10)) {
+      /* store the fitted values */
+      parupd (star, starpar[i], ix, iy);
+    }
+
+    if ((jmtype != 2) && (jmtype != 3) && toofaint(starpar[i], err)) jmtype = 7;
+	   
+    apple[i][4] = MIN (1, 1.086*sqrt(err[1])/star[1]);
+
+    if (last) {
+      nrect[1] = arect[1];
+      nrect[2] = arect[2];
+      fillerup (ix, iy, FALSE);
+      impaper2 (i);
+    }
+	      
+    addstar (starpar[i], SUB, jmtype);
+    imtype[i] = fixxy ? jmtype + 100 : jmtype;
+
+  }
+
+  return (0);
+
+}
+
+/* this function uses C 0,N-1 for a[], fa[] */
Index: /tags/start/Ohana/src/gophot/src/isearch.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/isearch.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/isearch.c	(revision 12606)
@@ -0,0 +1,170 @@
+# include "gophot.h"
+
+int isearch (int first) {
+  
+  int jrect[3];
+  int i, j, nsprev, nfound, nnew, ngoodpts, ngoodmask, ngoodfit, nfit;
+  float dummy[2*NPMAX], star[2*NPMAX], err[NPMAX], pixt2, bestsky;
+  float tthresh, thresh2, highsky, highthresh, tmp;
+  float sky, Chi, dx, dy, rdnoise2;
+  float *Bval, *Nval;
+  bool iscosmic, isbright, isfaint, hole;
+  float get_mediansky ();
+  FILE *f;
+
+  bzero (dummy, NPMAX*sizeof(float));
+  
+  pixt2 = SQ(pixthresh);
+
+  /* use jrect as temp in isearch.c */
+  for (i = 1; i < 3; i++) {
+    jrect[i] = (first) ? krect[i] : irect[i]; 
+  }
+	
+  nsprev = nstot;
+  nnew = 0;
+  ngoodpts = 0;
+  ngoodmask = 0;
+  ngoodfit = 0;
+  thresh2 = SQ(thresh);
+  nfit = (first) ? NFIT2 : NFIT1;
+  /* on first pass or so, we use 7 par fit, not 4 par fit */
+
+  Bval = big;
+  Nval = noise;
+  for (i = 0; i < nslow; i++) {
+    for (j = 0; j < nfast; j++, Bval++, Nval++) {
+
+      /* occasionally update sky guess based on median sky image */
+      if (!(j % nthpix)) {
+	sky = get_mediansky (j, i); 
+	tthresh = sky + thresh;
+      }
+
+      imtype[nstot] = 1;
+
+      /* skip bad pixels */
+      if (*Bval < tthresh) continue;
+      if (!finite (*Nval)) continue;
+      if (*Bval < *Nval - rnoise) continue;
+
+      /* test for significant peak */
+      if (!transmask (j, i, sky)) continue;
+      nnew ++;
+
+      /* nrect is passed globally to fillerup or through - rather obscure */ 
+      nrect[1] = jrect[1];
+      nrect[2] = jrect[2];
+
+      /* fills the vectors xs, ys, zs, dzs */
+      if (!fillerup (j, i, TRUE)) continue;
+      if ((fabs(xmax) > 0.33*nrect[1]) || (fabs(ymax) > 0.33*nrect[2])) {
+	mprint (3, "centroid moved: %d %d  %f %f\n", j, i, xmax, ymax);
+      }
+
+      tmp = enuff4*jrect[1]*jrect[2];
+      if (npt < tmp) {
+	mprint (3, "skipping: npt = %d\n", npt);
+	continue;
+      }
+      ngoodpts ++;
+
+      /* if sky guess has changed significantly, retest for significant peak */
+      if (fabs(sum2 - sky) / maxval > 0.2) {
+	if (!transmask (j, i, sum2)) {
+	  mprint (3, "failed transmask on local sky, %f\n", sum2);
+	  continue;
+	}
+      }
+      ngoodmask ++;
+
+      /* fill in guess for this object */
+      if (first) {
+	newguess (star, dummy, j, i); 
+      } else {
+	guess1 (star, dummy, j, i);
+      }
+      filladjust (star); 
+
+      /* fit star using 4 parameterfit */
+      Chi = chisq (onestar, xs, ys, zs, dzs, npt, star, err, nfit, acc, parlim, nit);
+
+      /* if (finite(Chi) && ((err[2] > 0.1) || (err[3] > 0.1))) fprintf (stderr, "errors: %d %d  %f %f   %f %f   %f\n", j, i, err[2], err[3], err[4], err[6], Chi/npt); */
+      if (!finite(Chi)) {
+	mprint (3, "failed to converge:  no entry in starlist\n");
+	continue;
+      }
+      if ((fabs(star[2]) > 0.33*nrect[1]) || (fabs(star[3]) > 0.33*nrect[2])) {
+	mprint (3, "fit center moved: %d %d  %f %f\n", j, i, star[2], star[3]);
+	continue;
+      }
+      if (centertest (star, xs, ys, npt)) {
+	mprint (3, "star %d at %d %d moved\n", nstot, j, i);
+	continue;
+      }
+      if (offpic (star, j, i, &dx, &dy)) {
+	mprint (3, "fitted star off image\n");
+	continue;
+      }
+
+      /* save fit parameters */
+      parupd (star, starpar[nstot], j, i);
+      parupd (star, shadow[nstot], j, i);
+      rchisq[nstot] = Chi / npt;
+      apple[nstot][4] = MIN (1, 1.086*sqrt(err[1])/star[1]);
+      mprint (2, "star %d: %f, %f  peak: %f chisq: %f\n", nstot, starpar[nstot][2], starpar[nstot][3], maxval, rchisq[nstot]);
+      ngoodfit ++;
+
+      if (verybright (starpar[nstot])) {
+	imtype[nstot] = 10;
+	goto finish;
+      }	
+      if (cosmic (starpar[nstot])) {
+	imtype[nstot] = 8;
+	hole = oblit (starpar[nstot]);
+	goto finish_noadd;
+      }	
+      if (toofaint (starpar[nstot], err)) {
+	imtype[nstot] = 7;
+	mprint (3, "faint imtype %d\n", imtype[nstot]);
+	goto finish;
+      }
+
+    finish:
+      addstar (starpar[nstot], SUB, imtype[nstot]);
+
+    finish_noadd:
+      nstot ++;
+      if (nstot >= NSMAX) {
+	mprint (0, "too many stars!\n");
+	return (0);
+      }
+
+    }
+  }
+  nfound = nstot - nsprev;
+  mprint (0, "stars found %d, stars tested %d\n", nfound, nnew);
+  mprint (0, "ngoodpts: %d, ngoodfit: %d, ngoodmask: %d\n", ngoodpts, ngoodfit, ngoodmask);
+
+  return (nfound);
+}
+
+
+/* this function uses C 0,N-1 for a[], fa[] */
+
+      /* before star subtraction:
+
+       Nval contains just sq(RN) (e) 
+       Bval contains counts (e)
+       dBval = sqrt(Bval + Nval)
+
+       after star subtraction:
+       
+       Nval contains fit + sq(RN)
+       Bval contains (obs-fit)
+       dBval = sqrt(Bval + Nval) [Bval' + Nval' = Bval + Nval] 
+      */       
+
+      /* note that the coordinates used in the fit are relative to j, i
+	 and are adjusted back in parupd */
+
Index: /tags/start/Ohana/src/gophot/src/large_features.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/large_features.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/large_features.c	(revision 12606)
@@ -0,0 +1,161 @@
+# include "gophot.h"
+
+/* these don't need to be 'static' unless we intend to call these 
+   functions outside of this file... */
+   
+static int *x;
+static int *y;
+static int Npts = 0;
+static int NPTS = 0;
+
+static int dx[] = {-1, 1, 0, 0};
+static int dy[] = {0, 0, -1, 1};
+static int Ntry = 4;
+
+static float *mediansky;
+static int Nx, Ny;
+static float fx, fy;
+
+float *copy_mediansky (int *, int *, float *, float *);
+int set_value (int, int, float);
+void large_features (float, float);
+void get_neighbors (int, int, float);
+float get_value (int, int);
+int outline (float, float, float, float, float, float, float *);
+float delete_ellipse (float *, float);
+
+void large_features (float sky, float dsky) {
+
+  int i, j, k;
+  float min, flux, dSky;
+  float Xo, Yo, dX, dY;
+  float Xmin, Xmax, Ymin, Ymax;
+  float fitpars[5];
+
+  nregion = 0;
+
+  /* use a copy to protect original */
+  mediansky = copy_mediansky (&Nx, &Ny, &fx, &fy);
+
+  dSky = sqrt(sky + rnoise);
+  dsky = MAX (dsky, dSky);
+
+  min = sky + 3*dsky;
+  fprintf (stderr, "sky %f, %f, %f\n", sky, dsky, min);
+  /* find pixels which stand above threshold */
+
+  for (j = 0; j < Ny; j++) {
+    for (i = 0; i < Nx; i++) {
+      if (mediansky [i + j*Nx] > min) {
+	/* this is always the first point in the group */
+	/* init the storage arrays */
+	Npts = 0;
+	NPTS = 100;
+	ALLOCATE (x, int, NPTS);
+	ALLOCATE (y, int, NPTS);
+	x[Npts] = i;
+	y[Npts] = j;
+	Npts ++;
+	get_neighbors (i, j, min);
+	/* we now have a list x, y, Npts */
+	Xmin = Xmax = x[0];
+	Ymin = Ymax = y[0];
+	for (k = 0; k < Npts; k++) {
+	  Xmin = MIN (Xmin, x[k]);
+	  Ymin = MIN (Ymin, y[k]);
+	  Xmax = MAX (Xmax, x[k]);
+	  Ymax = MAX (Ymax, y[k]);
+	}
+	Xo = 0.5*(Xmax + 1 + Xmin);
+	Yo = 0.5*(Ymax + 1 + Ymin);
+	dX = (Xmax + 1 - Xmin);
+	dY = (Ymax + 1 - Ymin);
+	convert_coords (&Xo, &Yo, &dX, &dY);
+	fprintf (stderr, "large feature: %f %f  %f %f\n", Xo, Yo, dX, dY);
+	outline (Xo, Yo, 0.4*dX, 0.4*dY, sky + 7*dsky, 2*dsky, fitpars);
+	flux = delete_ellipse (fitpars, sky);
+	fprintf (stderr, " flux: %f  %f\n", flux, sky);
+	region[nregion][0] = sky;
+	region[nregion][1] = flux;
+	region[nregion][2] = fitpars[0];
+	region[nregion][3] = fitpars[1];
+	region[nregion][4] = fitpars[2];
+	region[nregion][5] = fitpars[3];
+	region[nregion][6] = fitpars[4];
+	region[nregion][7] = flux;
+	nregion ++;
+	if (nregion == 100) {
+	  fprintf (stderr, "too many regions!\n");
+	  exit (0);
+	}
+      }
+    }
+  }
+}
+
+void get_neighbors (int ix, int iy, float min) {
+
+  int i, Ix, Iy;
+
+  for (i = 0; i < Ntry; i++) {
+    
+    Ix = ix + dx[i];
+    Iy = iy + dy[i];
+
+    if (get_value(Ix, Iy) > min) {
+      
+      x[Npts] = Ix;
+      y[Npts] = Iy;
+      Npts ++;
+      if (Npts == NPTS) {
+	NPTS += 100;
+	REALLOCATE (x, int, NPTS);
+	REALLOCATE (y, int, NPTS);
+      } 
+      
+      set_value (Ix, Iy, 0);
+      
+      get_neighbors (Ix, Iy, min);
+      
+    }
+  }
+}
+
+float get_value (int i, int j) {
+
+  float value;
+
+  if (i < 0) return (0);
+  if (i >= Nx) return (0);
+
+  if (j < 0) return (0);
+  if (j >= Ny) return (0);
+
+  value = mediansky[i + Nx*j];
+
+  return (value);
+
+}
+
+int set_value (int i, int j, float value) {
+
+  if (i < 0) return (0);
+  if (i >= Nx) return (0);
+
+  if (j < 0) return (0);
+  if (j >= Ny) return (0);
+
+  mediansky[i + Nx*j] = value;;
+
+  return (1);
+
+}
+
+convert_coords (float *X, float *Y, float *dX, float *dY) {
+
+  *X /= fx;
+  *dX /= fx;
+  *Y /= fy;
+  *dY /= fy;
+
+}
Index: /tags/start/Ohana/src/gophot/src/lubksb.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/lubksb.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/lubksb.c	(revision 12606)
@@ -0,0 +1,31 @@
+void lubksb (float **a, int n, int *indx, float *b) {
+
+  int i, j, ii, kk;
+  float sum;
+
+  ii = -1;
+  for (i = 0; i < n; i++) {
+    kk = indx[i];
+    sum = b[kk];
+    b[kk] = b[i];
+    if (ii != -1) {
+      for (j = ii; j < i; j++) {
+	sum -= a[i][j]*b[j];
+      }
+    } else {
+      if (sum != 0) ii = i;
+    }
+    b[i] = sum;
+  }
+
+  for (i = n-1; i >= 0; i--) {
+    sum=b[i];
+    if (i < n-1) {
+      for (j = i+1; j < n; j++) {
+	sum -= a[i][j]*b[j];
+      }
+    }
+    b[i] = sum/a[i][i];
+  }
+
+}
Index: /tags/start/Ohana/src/gophot/src/ludcmp.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/ludcmp.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/ludcmp.c	(revision 12606)
@@ -0,0 +1,71 @@
+# include <ohana.h>
+
+# define TINY 1.0e-20
+
+void ludcmp (float **a, int n, int *indx, float *D) {
+
+  float *vv;
+  int i, j, k, imax;
+  float aamax, sum, dum, d;
+
+  ALLOCATE (vv, float, n);
+
+  d = 1.0;
+  for (i = 0; i < n; i++) {
+    aamax = 0.0;
+    for (j = 0; j < n; j++) {
+      if (fabs (a[i][j]) > aamax) aamax = fabs (a[i][j]);
+    }
+    if (aamax == 0.0) {
+      *D = 0;
+      free (vv);
+      return;
+    }
+    vv[i] = 1.0/aamax;
+  }
+
+  for (j = 0; j < n; j++) {
+    for (i = 0; i < j; i++) {
+      sum = a[i][j];
+      for (k = 0; k < i; k++) {
+	sum -= a[i][k]*a[k][j];
+      }
+      a[i][j] = sum;
+    }
+    aamax = 0.0;
+    for (i = j; i < n; i++) {
+      sum = a[i][j];
+      for (k = 0; k < j; k++) {
+	sum -= a[i][k]*a[k][j];
+      }
+      a[i][j] = sum;
+      dum = vv[i]*fabs(sum);
+      if (dum >= aamax) {
+	imax = i;
+	aamax = dum;
+      }
+    }
+    if (j != imax) {
+      for (k = 0; k < n; k++) {
+	dum = a[imax][k];
+	a[imax][k] = a[j][k];
+	a[j][k] = dum;
+      }
+      d = -d;
+      vv[imax] = vv[j];
+    }
+    indx[j] = imax;
+    if (j != n-1) {
+      if (a[j][j] == 0.0) a[j][j] = TINY;
+      dum = 1.0 / a[j][j];
+      for (i = j+1; i < n; i++) {
+	a[i][j] = a[i][j]*dum;
+      }
+    }
+  }
+  if (a[n-1][n-1] == 0.0) a[n-1][n-1] = TINY;
+  free (vv);
+
+  *D = d;
+  return;
+}
Index: /tags/start/Ohana/src/gophot/src/makemask.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/makemask.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/makemask.c	(revision 12606)
@@ -0,0 +1,26 @@
+# include "gophot.h"
+
+makemask () {
+
+  int i, j, ii, jj;
+  float value;
+  float dumx, dumy, dummy, star[NPMAX];
+
+  dumx = 0;
+  dumy = 0;
+  dummy = parinterp (dumx, dumy, star);
+  
+  star[0] = 0;			
+  star[1] = 1;			
+  star[2] = 0;			
+  star[3] = 0;	
+  
+  for (j = 0, jj = -iyby2; j < 2*iyby2 + 1; j++, jj++) {
+    for (i = 0, ii = -ixby2; i < 2*ixby2 + 1; i++, ii++) {
+      starmask[i][j] = value = onestar (ii, jj, star, (float *) NULL);
+      mprint (2, "starmask[%d][%d]: %f\n", ii, jj, value);
+    }
+  }
+}
+
+/* this function uses C 0,N-1 for a[], fa[] */
Index: /tags/start/Ohana/src/gophot/src/makenoise.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/makenoise.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/makenoise.c	(revision 12606)
@@ -0,0 +1,47 @@
+# include "gophot.h"
+
+makenoise () {
+
+  int i, j;
+  float *valN, *valB;
+
+  valN = noise;
+  valB = big;
+
+  for (i = 0; i < nslow; i++) {
+    if ((i < nbadbot) || (i > nslow - nbadtop - 1)) {
+      for (j = 0; j < nfast; j++, valN++, valB++) *valN = MAGIC;
+      continue;
+    }      
+    for (j = 0; j < nfast; j++, valN++, valB++) {
+      if (j < nbadleft) {
+	*valN = MAGIC;
+	continue;
+      }
+      if (j > nfast - nbadright - 1) {
+	*valN = MAGIC;
+	continue;
+      }
+      *valB *= eperdn;
+      if (*valB > itop) {
+	*valN = MAGIC;
+	continue;
+      }
+      if (*valB <= ibot) {
+	*valN = MAGIC;
+	continue;
+      }
+      *valN = rnoise;
+    }
+  }
+}
+
+/* arguments OK */
+
+
+/* NEW CHOICES FOR NOISE AND BIG:
+
+   'big' is converted to electrons - this is the Poisson component of the error
+   'noise' will contain just the SQ(read-noise) - this is added to when a star is subtracted
+
+*/
Index: /tags/start/Ohana/src/gophot/src/mediansky.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/mediansky.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/mediansky.c	(revision 12606)
@@ -0,0 +1,197 @@
+# include "gophot.h"
+
+static float *mediansky;
+static int Nx, Ny;
+static float fx, fy;
+sort (float *, int);
+
+int make_mediansky () {
+
+  /* we have an image of nfast x nslow pix.  
+     make a new image of size sqrt(nfast) x sqrt(nslow)
+     (2k x 4k -> 45 x 63)
+  */
+
+  float *temp;
+  int i, j, I0, I1, J0, J1, I, J, n;
+  int nx, ny;
+  float Mv, Nv, Mv2, value;
+
+  Nx = sqrt (nfast);
+  Ny = sqrt (nslow);
+
+  /* nthpix is used in isearch.c to update sky guess */
+  nthpix = Nx;
+
+  fx = (float) Nx / nfast;
+  fy = (float) Ny / nslow;
+
+  ALLOCATE (mediansky, float, Nx*Ny);
+
+  nx = 1 + 1/fx;
+  ny = 1 + 1/fy;
+
+  ALLOCATE (temp, float, 2*nx*ny);
+
+  Nv = Mv = Mv2 = 0.0;
+
+  for (j = 0; j < Ny; j++) {
+    for (i = 0; i < Nx; i++) {
+      
+      I0 = i / fx;
+      J0 = j / fy;
+
+      I1 = (i + 1) / fx;
+      J1 = (j + 1) / fy;
+
+      n = 0;
+      temp[0] = 0;
+      
+      for (J = J0; J < J1; J++) {
+	if (J < nbadbot) continue;
+	if (J > nslow - nbadtop - 1) continue;
+	for (I = I0; I < I1; I++) {
+	  if (I < nbadleft) continue;
+	  if (I > nfast - nbadright - 1) continue;
+	  temp[n] = big[J*nfast + I];
+	  n++;
+	}
+      }
+
+      sort (temp, n);
+      value = temp[(int)(0.5*n)];
+
+      if (n < 2) {
+	mediansky[j*Nx + i] = MAGIC;
+      } else {
+	mediansky[j*Nx + i] = value;
+      }
+    }
+  }
+  return (0);
+}
+
+/* take array which is the median sky, copy to a separate vector, 
+   sort, find median and sigma in 50% interval around median */
+
+get_skystats (float *sky, float *dsky) {
+
+  float *temp, sky2;
+  int i, Npix, Nsky;
+
+  Npix = Nx*Ny;
+
+  ALLOCATE (temp, float, Npix);
+
+  memcpy (temp, mediansky, Npix*sizeof(float));
+
+  sort (temp, Npix);
+
+  *sky = temp[(int)(0.5*Npix)];
+
+  Nsky = 0;
+  sky2 = 0;
+  for (i = 0.25*Npix; i < 0.75*Npix; i++) {
+    if (!finite(temp[i])) continue;
+    sky2 += SQ(temp[i] - *sky);
+    Nsky ++;
+  }
+  
+  *dsky = sqrt (sky2/Nsky);
+
+  free (temp);
+
+  mprint (0, "median sky: %f %f\n", *sky, *dsky);
+
+  return (1);
+
+}
+
+fix_mediansky (float sky) {
+
+  int i;
+
+  for (i = 0; i < Nx*Ny; i++) {
+    if (!finite (mediansky[i])) {
+      mediansky[i] = sky;
+    }
+  }
+}
+
+/* this version is fast and has no edge problems. */
+
+# if (1) 
+float get_mediansky (int i, int j) {
+
+  float value;
+  int I, J;
+
+  I = i * fx;
+  J = j * fy;
+
+  value = mediansky[J*Nx + I];
+
+  return (value);
+
+}
+# endif
+
+/* this version is slow, but more accurate.
+   on the other hand, it needs to be fixed for
+   edge problems. */
+
+# if (0) 
+float get_mediansky (int i, int j) {
+
+  float Fx, Fy, Vo, Vm, Vx, Vy;
+  float value;
+  int I, J, dx, dy;
+
+  I = i * fx;
+  J = j * fy;
+
+  Vo = mediansky[J*Nx + I];
+
+  Fx = i * fx - I;
+  if (Fx < 0.5) {
+    dx = -1;
+  } else {
+    dx = +1;
+    Fx = 1.0 - Fx;
+  }
+  Vm = mediansky[J*Nx + I + dx];
+  Vx = (Vo*(0.5+Fx) + Vm*(0.5-Fx));
+
+  Fy = j * fy - J;
+  if (Fy < 0.5) {
+    dy = -1;
+  } else {
+    dy = +1;
+    Fy = 1.0 - Fy;
+  }
+  Vm = mediansky[J*Nx + I + dy*Nx];
+  Vy = (Vo*(0.5+Fy) + Vm*(0.5-Fy));
+
+  value = 0.5*(Vx + Vy);
+
+  return (value);
+
+}
+# endif
+
+float *copy_mediansky (int *nx, int *ny, float *Fx, float *Fy) {
+
+  float *temp;
+
+  ALLOCATE (temp, float, Nx*Ny);
+  memcpy (temp, mediansky, Nx*Ny*sizeof(float));
+  
+  *nx = Nx;
+  *ny = Ny;
+  *Fx = fx;
+  *Fy = fy;
+
+  return (temp);
+
+}
+
Index: /tags/start/Ohana/src/gophot/src/message.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/message.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/message.c	(revision 12606)
@@ -0,0 +1,29 @@
+# include <stdio.h>
+# include <stdarg.h>
+
+static FILE *f;
+static int verbosity = 0;
+
+int mprint (int level, char *mode, ...) {
+
+  int status;
+  va_list argp;
+  
+  if (level > verbosity) return (0);
+
+  va_start (argp, mode);
+  
+  status = vfprintf (f, mode, argp);
+
+  va_end (argp);
+
+  return (status);
+
+}
+
+set_verbosity (int level) {
+
+  f = stderr;
+  verbosity = level;
+
+}
Index: /tags/start/Ohana/src/gophot/src/objout.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/objout.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/objout.c	(revision 12606)
@@ -0,0 +1,88 @@
+# include "gophot.h"
+# define NCHAR 104
+
+completeout () {
+
+  FILE *f;
+  int i, Nchar;
+  float gcorr, gmag;
+  float area, amajor, aminor, tilt, fmag, xc, yc, apmag, tmp;
+  char line[NCHAR];
+	
+  f = fopen (files[4], "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "error, can't save data in file %s\n", files[4]);
+    exit (1);
+  }
+
+  ellipse (ava[4], ava[5], ava[6], &area, &amajor, &aminor, &tilt);
+  fprintf (f, "# Average Star: %f %f %f\n", amajor, aminor, tilt);
+
+  for (i = 0; i < nregion; i++) {
+    
+    fmag = -2.5*log10 (region[i][1]);
+    gmag = -2.5*log10 (region[i][7]);
+    apmag = 99.999;
+
+    Nchar = snprintf (line, NCHAR, "%3d %8.2f %8.2f %8.3f %6.3f %9.2f %9.3f %9.3f %7.2f %8.3f %8.3f  %8.2f",
+		      20, region[i][2], region[i][3], fmag, 0.01, region[i][0], region[i][4], region[i][5], region[i][6], 
+		      gmag, apmag, 10.0);
+    fprintf (f, "%s\n", line);
+  }
+
+  for (i = 0; i < nstot; i++) {
+         
+    fmag = 99.999;
+    gmag = 99.999;
+    apmag = 99.999;
+
+    if (imtype[i] != 8) {
+      /* pure gaussian fit mags */
+      ellipse (starpar[i][4], starpar[i][5], starpar[i][6], &area, &amajor, &aminor, &tilt);
+      tmp = area*starpar[i][1]/eperdn;
+      if (tmp > 0.0) fmag = -2.5 * log10 (tmp);
+      /* galaxy-non-gauss fit mags */
+      ellipse (shadow[i][4], shadow[i][5], shadow[i][6], &area, &amajor, &aminor, &tilt);
+      gcorr = 1.0;
+      tmp = area*gcorr*shadow[i][1]/eperdn;
+      if (tmp > 0.0) gmag = -2.5 * log10 (tmp);
+      tilt = 57.29578 * tilt;
+    } else {
+      /* get correct orientation for oblit boxes */
+      if (starpar[i][5] != -1) fmag = -99.999;
+      if (starpar[i][4] >= starpar[i][6]) {
+	amajor = starpar[i][4];
+	aminor = starpar[i][6];
+	tilt = 0.0;
+      } else {
+	amajor = starpar[i][6];
+	aminor = starpar[i][4];
+	tilt = 90.0;
+      }
+    }
+         
+    /* what is the value of the center of a pixel? */
+    /* this assumes the pixel center is at 0,0, not 0.5, 0.5 */
+    xc = starpar[i][2];
+    yc = starpar[i][3];
+
+    if (apple[i][1] > 0.0) apmag = -2.5 * log10 (apple[i][1]/eperdn);
+         
+    Nchar = snprintf (line, NCHAR, "%3d %8.2f %8.2f %8.3f %6.3f %9.2f %9.3f %9.3f %7.2f %8.3f %8.3f  %8.2f",
+	     imtype[i], xc, yc, fmag, apple[i][4], shadow[i][0], amajor, aminor, tilt, 
+	     gmag, apmag, rchisq[i]);
+    if (Nchar != NCHAR - 1) {
+      mprint (1, "funny line %d\n", i);
+    }
+    fprintf (f, "%s\n", line);
+  }         
+
+  /*
+  1    37.51  1193.91  -15.246   .034    594.48     6.657     5.654   -7.06  -15.611  -15.822
+  */  
+  fclose (f);
+
+  return (0);
+}
+
+/* this function uses C 0,N-1 for a[], fa[] */
Index: /tags/start/Ohana/src/gophot/src/oblims.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/oblims.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/oblims.c	(revision 12606)
@@ -0,0 +1,31 @@
+# include "gophot.h"
+
+oblims (float *star, int *jrect) {
+
+  float temp, fudgex, fudgey;
+
+  if (star[1] > 0) {
+    /* think about this line: */
+    temp = pow ((6*star[1]/nphob), 0.33333333);
+    if (star[4] > 0) {
+      fudgex = sqrt(temp*star[4]*2);
+    } else {
+      fudgex = 10;
+    }
+    if (star[6] > 0) {
+      fudgey = sqrt(temp*star[6]*2);
+    } else {
+      fudgey = 10;
+    }
+  } else {
+    fudgex = 10;
+    fudgey = 10;
+  }
+
+  mprint (3, "fudge size: %f %f\n", fudgex, fudgey);
+  jrect[1] = star[2] - fudgex;
+  jrect[2] = star[2] + fudgex;
+  jrect[3] = star[3] - fudgey;
+  jrect[4] = star[3] + fudgey;
+
+}
Index: /tags/start/Ohana/src/gophot/src/oblit.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/oblit.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/oblit.c	(revision 12606)
@@ -0,0 +1,34 @@
+# include "gophot.h"
+
+bool oblit (float *star) {
+
+  bool value;
+	
+  float wx, wy, dum, duma[NPMAX];
+  int ix, iy, ixhi, ixlo, iyhi, iylo, jx, jy;
+	
+  dum = guess2 (duma, star, &ix, &iy);
+  wx = star[4];				
+  wy = star[6];
+
+  ixhi = MIN ((int)(ix + 0.5*wx + 0.5), nfast-1);
+  ixlo = MAX ((int)(ix - 0.5*wx + 0.5), 0);
+  iyhi = MIN ((int)(iy + 0.5*wy + 0.5), nslow-1);
+  iylo = MAX ((int)(iy - 0.5*wy + 0.5), 0);
+
+  mprint (3, "obliterating following region : %d - %d, %d - %d\n", ixlo, ixhi, iylo, iyhi);
+  for (jy = iylo; jy <= iyhi; jy++) {
+    for (jx = ixlo; jx <= ixhi; jx++) {
+      big[jx+jy*nfast] = MAGIC;
+      noise[jx+jy*nfast] = MAGIC;
+    }
+  }
+
+  mprint (2, "obliteration: %d, %d (%f x %f)\n", ix, iy, wx, wy);
+
+  return (TRUE);
+
+}
+
+	
+	
Index: /tags/start/Ohana/src/gophot/src/offpic.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/offpic.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/offpic.c	(revision 12606)
@@ -0,0 +1,24 @@
+# include "gophot.h"
+
+bool offpic (float *star, int ix, int iy, float *dx, float *dy) {
+
+  bool nogood;
+  float x, y;
+
+  x = ix + star[2];
+  y = iy + star[3];
+  
+  *dx = 0;
+  if (x < 0) *dx = -x;
+  if (x > nfast) *dx = x - nfast;
+	
+  *dy = 0;
+  if (y < 0) *dy = -y;
+  if (y > nslow) *dy = y - nslow;
+	
+  nogood = (*dx != 0) || (*dy != 0);
+
+  if (!fixpos) nogood = nogood || (star[1] < 0);
+
+  return (nogood);
+}
Index: /tags/start/Ohana/src/gophot/src/outline.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/outline.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/outline.c	(revision 12606)
@@ -0,0 +1,188 @@
+# include "gophot.h"
+
+int Npts;
+float *xv, *yv, *zv;
+float par[5];
+float dpar[5];
+float outline_chi (float);
+
+/* fit pars[5] to ellipse at Xo, Yo, dX, dY */
+int outline (float Xo, float Yo, float dX, float dY, float Io, float dIo, float *pars) {
+  
+  int i, j, k, Nx, Ny, NPTS, BigChange, ABigChange;
+  float oChi, dchi, Chi, Chi_p, Chi_m, dp, tmp_par, nChi, tmp1, tmp2;
+  float curve, frac, value;
+
+  par[0] = Xo;
+  par[1] = Yo;
+  par[2] = dX;
+  par[3] = dY;
+  par[4] = 0.0;
+
+  dpar[0] = 10;
+  dpar[1] = 10;
+  dpar[2] = 10;
+  dpar[3] = 10;
+  dpar[4] = 10;
+
+  /* find all pixels within range Io-dIo : Io+dIo, in region about center guess */
+
+  Npts = 0;
+  NPTS = 1000;
+  ALLOCATE (xv, float, NPTS);
+  ALLOCATE (yv, float, NPTS);
+  ALLOCATE (zv, float, NPTS);
+  for (j = par[1]-2*par[3]; j < par[1]+2*par[3]; j++) {
+    if (j < 0) continue;
+    if (j >= nslow) continue;
+    for (i = par[0]-2*par[2]; i < par[0]+2*par[2]; i++) {
+      if (i < 0) continue;
+      if (i >= nfast) continue;
+      value = big[i + nfast*j];
+      if (fabs (value - Io) < dIo) {
+	xv[Npts] = i;
+	yv[Npts] = j;
+	zv[Npts] = value;
+	Npts ++;
+	if (Npts == NPTS) {
+	  NPTS += 1000;
+	  REALLOCATE (xv, float, NPTS);
+	  REALLOCATE (yv, float, NPTS);
+	  REALLOCATE (zv, float, NPTS);
+	}
+      }
+    }
+  }
+
+  if (Npts == 0) {
+    fprintf (stderr, "no valid points in box, try again\n");
+    free (xv);
+    free (yv);
+    free (zv);
+    return (FALSE);
+  }
+
+  Chi = outline_chi (Io);
+  for (j = 0; j < 15; j++) {
+    
+    oChi = Chi;
+    for (i = 0; i < 5; i++) {
+      /* find +Chi, -Chi for this par & adjust par as needed */
+
+      for (k = 0, BigChange = TRUE; (k < 3) && BigChange; k++) {
+	tmp_par = par[i];
+	par[i] = tmp_par + dpar[i];
+	Chi_p = outline_chi (Io);
+	par[i] = tmp_par - dpar[i];
+	Chi_m = outline_chi (Io);
+	
+	/* have we braketted a minimum? (curve < 0) */
+	curve = (Chi_p - Chi) * (Chi - Chi_m);
+	if (curve > 0) {
+	  dp = 2*dpar[i];
+	} else {
+	  dp = 0.5 * dpar[i] * (Chi_m - Chi_p) / (Chi_m + Chi_p - 2*Chi);
+	}      
+	if (Chi_m + Chi_p - 2*Chi == 0) dp = 0;
+	/* don't let extrapolation go too far */
+	if (fabs (dp) > 2*fabs(dpar[i])) { dp = SIGN(dp) * fabs (2*dpar[i]); }
+	
+	par[i] = tmp_par + dp;
+	Chi = outline_chi (Io);
+	
+	BigChange = FALSE;
+	if (Chi <= 1.001*oChi) {
+	  /* got better */
+	  dchi = (oChi - Chi) / oChi; 
+	  if ((dchi > 0.03) || (curve > 0)) BigChange = TRUE;
+	} else {
+	  par[i] = tmp_par;
+	  Chi = oChi;
+	  if (Chi_m < Chi) {
+	    Chi = Chi_m;
+	    par[i] = tmp_par - dpar[i];
+	  }	
+	  if (Chi_p < Chi) {
+	    Chi = Chi_p;
+	    par[i] = tmp_par + dpar[i];
+	  }	
+	}	
+	oChi = Chi;
+      }
+      if (!BigChange) dpar[i] *= 0.8;
+    }
+
+    mprint (0, "try: %d  %f   ", j, Chi);
+    for (i = 0; i < 5; i++) {
+      mprint (0, "%f ", par[i]);
+    }
+    mprint (0, "\n");
+    for (i = 0; i < 5; i++) {
+      mprint (2, "%f ", dpar[i]);
+    }
+    mprint (2, "\n");
+    dchi -= Chi;
+
+  }
+
+  free (xv);
+  free (yv);
+  free (zv);
+  
+  pars[0] = par[0];
+  pars[1] = par[1];
+  pars[2] = par[2];
+  pars[3] = par[3];
+  pars[4] = par[4];
+  return (TRUE);
+
+}
+
+/* par[0] = x
+   par[1] = y
+   par[2] = dx
+   par[3] = dy
+   par[4] = dxy
+   
+    xp = par[2] * cos (t);
+    yp = par[3] * sin (t);
+    
+    x = xp * cos (par[4] * RAD_DEG) - yp * sin (par[4] * RAD_DEG) + par[0];
+    y = xp * sin (par[4] * RAD_DEG) + yp * cos (par[4] * RAD_DEG) + par[1];
+
+*/
+
+float outline_chi (float Io) {
+
+  int i;
+  float theta, phi;
+  float xp, yp, x, y;
+  float Chi, dv, Dv, R2, F2;
+  float cs, sn;
+
+  Chi = 0;
+
+  cs = cos (par[4] * RAD_DEG);
+  sn = sin (par[4] * RAD_DEG);
+
+  for (i = 0; i < Npts; i++) {
+    
+    phi = atan2 (yv[i] - par[1], xv[i] - par[0]) - RAD_DEG * par[4];
+    theta = atan2 (par[2]*sin(phi), par[3]*cos(phi));
+
+    /* this is the point on the ellipse at the same angle as ref point */
+    xp = par[2] * cos (theta);
+    yp = par[3] * sin (theta);
+    
+    x = xp * cs - yp * sn + par[0];
+    y = xp * sn + yp * cs + par[1];
+
+    R2 = sqrt (SQ (x - xv[i]) + SQ (y - yv[i]));
+    Chi += R2;
+
+  }
+
+  Chi = Chi / Npts;
+  return (Chi);
+
+}
Index: /tags/start/Ohana/src/gophot/src/paravg.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/paravg.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/paravg.c	(revision 12606)
@@ -0,0 +1,98 @@
+# include "gophot.h"
+
+paravg () {
+
+  float sum[NPMAX][2];
+  int i, j, n;
+  FILE *f;
+  char c;
+  float *ave4, *ave5, *ave6, *key;
+  int Ngood, NGOOD, *index, *idx;
+  int Nave;
+  float a4, a5, a6;
+
+  for (j = 0; j < NPAR; j++) {
+    sum[j][0] = 0;
+    sum[j][1] = 0;
+  }
+  
+  if (nstot < 1) return (0);
+
+  NGOOD = 100;
+  Ngood = 0;
+  ALLOCATE (index, int, NGOOD);
+
+  /* find good stars, store index */
+  for (i = 0; i < nstot; i++) {
+    if (starpar[i][1] < 100) continue;
+    if ((imtype[i] == 1) || (imtype[i] == 101)) {
+      index[Ngood] = i;
+      Ngood ++;
+      if (Ngood == NGOOD) {
+	NGOOD += 100;
+	REALLOCATE (index, int, NGOOD);
+      }
+    }
+  }
+  for (i = 0; i < Ngood; i++) {
+    fprintf (stderr, "S: %d %d %d  %f %f   %f %f\n", i, index[i], imtype[index[i]], starpar[index[i]][1], shaderr[index[i]][1], starpar[index[i]][4], shadow[index[i]][4]);
+  }
+
+  /* find good stars, store index */
+  if (Ngood < 10) { /* accept type 2 as well... */
+    for (i = 0; i < nstot; i++) {
+      if ((imtype[i] == 2) || (imtype[i] == 102)) {
+	index[Ngood] = i;
+	Ngood ++;
+	if (Ngood == NGOOD) {
+	  NGOOD += 100;
+	  REALLOCATE (index, int, NGOOD);
+	}
+      }
+    }
+  }
+
+  if (Ngood > 10) { /* don't change if not enough 'stars' */
+    
+    ALLOCATE (ave4, float, Ngood);
+    ALLOCATE (ave5, float, Ngood);
+    ALLOCATE (ave6, float, Ngood);
+    ALLOCATE (key,  float, Ngood);
+    ALLOCATE (idx,  int, Ngood);
+    
+    for (i = 0; i < Ngood; i++) {
+      idx[i] = i;
+      key[i] = shadow[index[i]][4];
+      ave4[i] = shadow[index[i]][4];
+      ave5[i] = shadow[index[i]][5];
+      ave6[i] = shadow[index[i]][6];
+    }
+    sortkey (idx, key, Ngood);
+
+    a4 = a5 = a6 = Nave = 0;
+    for (i = 0.4*Ngood; i < 0.6*Ngood; i++) {
+      a4 += ave4[idx[i]];
+      a5 += ave5[idx[i]];
+      a6 += ave6[idx[i]];
+      Nave ++;
+    }
+    ava[4] = a4/Nave;
+    ava[5] = a5/Nave;
+    ava[6] = a6/Nave;
+
+    free (key);
+    free (idx);
+    free (ave4);
+    free (ave5);
+    free (ave6);
+  }
+  free (index);
+  
+
+  mprint (1, "%d stars used to find parameter averages\n", Ngood);
+  mprint (1, "average values so far of shape parameters for stars: \n");
+  for (j = 4; j < NPAR; j++) mprint (1, "%f ", ava[j]);
+  mprint (1, "\n");
+
+}
+/* this function uses C 0,N-1 for a[], fa[] */
Index: /tags/start/Ohana/src/gophot/src/parinterp.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/parinterp.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/parinterp.c	(revision 12606)
@@ -0,0 +1,10 @@
+# include "gophot.h"
+
+float parinterp (float x, float y, float *star) {
+
+  star[4] = ava[4];
+  star[5] = ava[5];
+  star[6] = ava[6];
+  
+  return (star[0]);
+}
Index: /tags/start/Ohana/src/gophot/src/parupd.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/parupd.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/parupd.c	(revision 12606)
@@ -0,0 +1,25 @@
+# include "gophot.h"
+
+parupd (float *instar, float *outstar, int ix, int iy) {
+
+	outstar[0] = instar[0]*ufactor;
+	outstar[1] = instar[1]*ufactor;
+	outstar[2] = instar[2] + ix;
+	outstar[3] = instar[3] + iy;
+	outstar[4] = instar[4];
+	outstar[5] = instar[5];
+	outstar[6] = instar[6];
+}
+
+/* a legacy function 
+twoupd (float *instar, float *outstar, int ix, int iy) {
+
+	outstar[0] = instar[0];
+	outstar[1] = instar[1];
+	outstar[2] = instar[2] + ix;
+	outstar[3] = instar[3] + iy;
+	outstar[4] = instar[4];
+	outstar[5] = instar[5] + ix;
+	outstar[6] = instar[6] + iy;
+}
+*/
Index: /tags/start/Ohana/src/gophot/src/pseud2d.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/pseud2d.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/pseud2d.c	(revision 12606)
@@ -0,0 +1,84 @@
+# include "gophot.h"
+
+# define HALF 0.5
+# define THIRD 0.333
+# define EXPMIN -15.0
+
+float pseud2d (int ix, int iy, float *a, float *fa) {
+
+  double x, y, t5, t6, t7, T;
+  double denom, dt, pexp, R;
+  double Q;
+  float value;
+  int i;
+
+  x = ix - a[2];
+  y = iy - a[3];
+       
+  t6 = a[5]*y;
+  t5 = x/a[4];
+  t7 = y/a[6];
+
+  T = 0.5*((t5 + 2.0*t6)*x + t7*y);
+  
+  if (!finite (a[1])) fprintf (stderr, "bad star!\n");
+
+  if (T >= 0) { 
+    denom = 1.0 + T*(beta4 + HALF*beta64*T*(1.0 + THIRD*T));
+    pexp = 1.0 / denom; 
+    dt = beta4 + beta64*T*(1.0 + HALF*T);
+    if (!finite (pexp)) {
+      fprintf (stderr, "error in pseud2d: %f %f %f %d %d\n", T, denom, pexp, ix, iy); 
+      denom = 1.0 + T + HALF*beta4*T*T + THIRD*beta64*T*T*T;
+      pexp = 1.0 / denom;
+      if (!finite (pexp)) { 
+	fprintf (stderr, "error in pseud2d: %f %f %f %d %d\n", T, denom, pexp, ix, iy);
+	fprintf (stderr, "%f %f   %f %f %f\n", x, y, t5, t6, t7); 
+	fprintf (stderr, "%f %f %f\n", T, T*HALF*beta4*T, T*HALF*beta4*T*THIRD*beta64*T);
+	for (i = 0; i < 7; i++) fprintf (stderr, "%d %f\n", i, a[i]);
+	fprintf (stderr, "nstot: %d\n", nstot);
+	fprintf (stderr, "invalid value!\n");
+	exit (1);
+      } 
+    }
+   } else {
+    denom = MAX (T, EXPMIN);
+    denom = fabs (denom);
+    pexp = exp (denom);
+    denom = 1.0;
+    dt = 1.0;
+  }
+
+  value = a[1]*pexp;
+
+  if (fa != (float *) NULL) {
+    R = value*dt/denom;
+    fa[1] = pexp;
+    fa[2] = R*(t5 + t6);
+    fa[3] = R*(a[5]*x + t7);
+    fa[4] = R*t5*t5*0.5;
+    fa[6] = R*t7*t7*0.5;
+    
+    fa[5] = -R*x*y;
+    fa[0] = 1.0;
+  }
+
+  value += + a[0];
+
+  if (!finite(value)) {
+    fprintf (stderr, "error in pseud2d: %f %f %f %f\n", T, denom, pexp, a[1]);
+    exit (1);
+  }
+
+  return (value);
+
+}
+
+/* this function uses C 0,N-1 for a[], fa[] */
+
+/* a[0] - sky
+   a[1] - Io
+   a[2], a[3] - X, Y
+   a[4], a[5], a[6] - shape
+*/
+
Index: /tags/start/Ohana/src/gophot/src/pseud4d.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/pseud4d.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/pseud4d.c	(revision 12606)
@@ -0,0 +1,73 @@
+# include "gophot.h"
+
+# define HALF 0.5
+# define THIRD 0.33333333333333
+# define EXPMIN -15
+
+float pseud4d (int ix, int iy, float *a, float *fa) {
+
+  int i, ioff;
+  float x, y;
+  float denom, T, dt, pexp[2];
+  float a2, a5, a6, a7, t5, t6, t7, value;
+	
+  a5 = 1.0/a[7];
+  a7 = 1.0/a[9];
+  a6 = a[8];
+  
+  for (i = 0; i < 2; i++) {
+
+    ioff = 3*i;
+    x = ix - a[2 + ioff];
+    y = iy - a[3 + ioff];
+       
+    t5 = a5*x;
+    t6 = a6*y;
+    t7 = a7*y;
+    T = HALF*((t5 + 2*t6)*x + t7*y);
+	   
+    if (T > 0) {
+      denom = 1.0 + T*(1.0 + HALF*beta4*T*(1.0 + THIRD*beta64*T));
+      pexp[i] = 1./denom;
+    } else {
+      denom = MAX (T, EXPMIN);
+      denom = fabs (denom);
+      pexp[i] = exp (denom);
+      denom = 1.0;
+    }
+
+    a2 = exp(a[1 + ioff]);
+    value = a2*pexp[i];
+    pexp[i] = value;
+    
+    if (fa != (float *) NULL) {
+      if (T > 0) {
+	dt = 1.0 + beta4*T*(1.0 + HALF*beta64*T);
+      } else {
+      	dt = 1.0;
+      }
+      fa[1 + ioff] = value;
+      T = pexp[i]*dt/denom;
+      fa[2 + ioff] = (a5*x + a6*y)*T;
+      fa[3 + ioff] = (a6*x + a7*y)*T;
+      
+      fa[0] = 1;
+    }      
+  }
+
+  value = pexp[0] + pexp[1] + a[0];
+
+  return (value);
+
+}
+
+/* this function uses C 0,N-1 for a[], fa[] */
+
+/* a[0] - sky
+   a[1] - I1
+   a[2], a[3] - X1, Y1
+   a[4] - I2
+   a[5], a[6] - X2, Y2
+   a[7], a[8], a[9] - shape
+*/
+
Index: /tags/start/Ohana/src/gophot/src/set_thresholds.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/set_thresholds.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/set_thresholds.c	(revision 12606)
@@ -0,0 +1,33 @@
+# include "gophot.h"
+
+float set_thresholds (float sky, float dSky, float *factor, int *Nit) {
+
+  float dsky, tmp;
+
+  /* tmin starts with Nsigma above sky */
+
+  dsky = sqrt(sky + rnoise);
+  fprintf (stderr, "dsky: %f %f %f %f\n", rnoise, sky, dsky, dSky);
+  dsky = MAX (dsky, dSky);
+  tmin = tmin * dsky;
+
+  mprint (0, "gain is %f, median sky is %f, min threshold is %f\n",
+	  eperdn, sky, tmin);
+
+  /* set starting threshold */
+  tmp = pow (2.0, tfac);
+  tmax = 0.5*itop;
+  *Nit  = log (tmax / tmin) / log (tmp);
+  *factor = pow ((tmax / tmin), (1.0 / *Nit));
+
+  return (tmax);
+
+}
+
+/* we are going to evenly divide the range from 
+   sky + tmin*dsky to 0.5*itop in slices with ratios 
+   close to tfac */
+
+/* images with very messy backgrounds should not be pushed to the 
+   absolute minimum.  We let the sky sigma be the max of the 
+   formal and the measured sigmas */
Index: /tags/start/Ohana/src/gophot/src/shape.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/shape.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/shape.c	(revision 12606)
@@ -0,0 +1,267 @@
+# include "gophot.h"
+
+# define ZERO_SHADOW {shadow[i][0] = 0; \
+	              shadow[i][1] = 0; \
+	              shadow[i][4] = 1; \
+                      shadow[i][5] = 0; \
+                      shadow[i][6] = 1; }
+
+/* try 7 par fit for each object, decide on object types */
+shape () {
+
+  bool notnuff, gotfaint, verybig, offp, converge;
+
+  /* watch twofpar - i think we only need 2 entries, for storage in this loop */
+  float star[NPMAX], err[NPMAX], star1[NPMAX], star2[NPMAX];
+  float sky, galchi, dx, dy, starchi;
+  int i, j, n, k, ix, iy, jmtype, nsprev;
+
+  test7 = TRUE;
+  nsprev = nstot;
+
+  for (i = 0; i < nsprev; i++) {
+    mprint (3, " determining shape for object no. %d\n", i);
+
+    gotfaint = FALSE;
+    fixxy = imtype[i] >= 100;
+    jmtype = (fixxy) ? imtype[i] - 100 : imtype[i];
+	   
+    switch (jmtype) {
+    case 7:
+      mprint (3, "too faint, skipping object %d at %f, %f\n", i, starpar[i][2], starpar[i][3]);
+      continue;
+      break;
+    case 4:
+    case 9:
+      mprint (3, "nonconverge, skipping object %d at %f, %f\n", i, starpar[i][2], starpar[i][3]);
+      continue;
+      break;
+    case 8:
+    case 18:
+    case 6:
+    case 16:
+      mprint (3, "poor obj, skipping object %d at %f, %f\n", i, starpar[i][2], starpar[i][3]);
+      ZERO_SHADOW;
+      continue;
+      break;
+    }
+
+    if (shadow[i][0] == 0) {
+      sky = guess2 (star, starpar[i], &ix, &iy);
+    } else {
+      sky = guess2 (star, shadow[i], &ix, &iy);
+    }
+
+    addstar (starpar[i], ADD, jmtype);
+
+    nrect[1] = irect[1];
+    nrect[2] = irect[2];
+    fillerup (ix, iy, FALSE);
+    notnuff = (npt < enuff7*irect[1]*irect[2]);
+
+    if (notnuff) {
+      mprint (3, "obj %d, npts %d, %d & %d - skipping star: not enough pixels for 7-parm fit \n", i, npt, ix, iy);
+      if (jmtype != 2) jmtype = 5;
+      if (jmtype == 12) beta4 = 0.01;
+      addstar (starpar[i], SUB, jmtype);
+      beta4 = 1.0;
+      imtype[i] = fixxy ? jmtype + 100 : jmtype;
+      continue;
+    }
+
+    if (fixxy) {
+      gotfaint = !transmask (ix, iy, sky);
+      if (gotfaint) { 
+	if (jmtype != 3) jmtype = 7;
+	mprint (3, "obj %d, npts %d, %d & %d - skipping star: too faint for 7 par fit\n", i, npt, ix, iy);
+	addstar (starpar[i], SUB, jmtype);
+	imtype[i] = fixxy ? jmtype + 100 : jmtype;
+	continue;
+      }
+    }
+
+    filladjust (star); 
+    mprint (2, "obj %d, npts %d, %d & %d\n", i, npt, ix, iy);
+
+    /* fit 'extended' to star (7 parameter fit) */
+    galchi = chisq (onestar, xs, ys, zs, dzs, npt, star, err, NFIT2, acc, parlim, nit);
+    /*
+    if (finite(galchi) && ((err[4] > 0.25) || (err[6] > 0.25))) {
+      fprintf (stderr, "7 errors: %d %d  %f %f   %f %f   %f\n", ix, iy, err[2], err[3], err[4], err[6], galchi/npt);
+      fprintf (stderr, "                 %f %f   %f %f\n", star[2], star[3], star[4], star[6]);
+    }
+    */
+    if (fabs(star[5]) >= 1.0 / sqrt(fabs(star[4]*star[6]))) {
+      mprint (3, "hyperbola!  problem with %d at %f %f\n", i, starpar[i][2], starpar[i][3]);
+      /* just a warning... */
+    }
+    if ((star[4] > SQ(0.25*nrect[1])) || (star[6] > SQ(0.25*nrect[1]))) {
+     mprint (3, "warning - dubious fit for %d at %f %f\n", i, starpar[i][2], starpar[i][3]);
+      /* just a warning... */
+    } 
+    if (!finite (galchi)) {
+      /* shadow, starpar keep 4-par fit */
+      mprint (3, "non-converge object %d at %f %f\n", i, starpar[i][2], starpar[i][3]);
+      if (jmtype != 3) jmtype = 9;
+      mprint (3, "obj %d, npts %d, %d & %d .... failed to converge\n", i, npt, ix, iy);
+      addstar (starpar[i], SUB, jmtype);
+      imtype[i] = fixxy ? jmtype + 100 : jmtype;
+      continue;
+    }
+    
+    /* is new fit position reasonable? */
+    if (centertest (star, xs, ys, npt) || (fabs(star[2]) > 0.33*nrect[1]) || (fabs(star[3]) > 0.33*nrect[2])) {
+      mprint (3, "fit center moved 2: %f %f  %f %f\n", starpar[i][2], starpar[i][3], star[2], star[3]);
+      jmtype = 16;
+      /* shadow, starpar keep 4-par fit */
+      addstar (starpar[i], SUB, jmtype);
+      imtype[i] = fixxy ? jmtype + 100 : jmtype;
+      continue;
+    }
+      
+    /* calculate error here for type 2, 10. redone in improve for 1, 3, 5, 7 */
+    apple[i][4] = MIN (1, 1.086*sqrt(err[1])/star[1]);
+    rchisq[i] = galchi / npt;
+
+    /* save 7-par fit in shadow */
+    parupd (star, shadow[i], ix, iy);
+    for (j = 0; j < NPAR; j++) shaderr[i][j] = err[j];
+	
+    /* allow type 10 to go back to 1 and vice-versa */
+    if ((jmtype == 10) && !verybright (starpar[i])) jmtype = 1;
+    if (verybright (starpar[i])) jmtype = 10;
+
+    if (jmtype == 10) {
+      mprint (3, " very bright, keep 7 par fit only\n");
+
+      if ((thresh < tmax / 4) && (thresh > tmax/16)) {
+	/* test if type 10 can be safely split in two */
+	starchi = twofit (star, starpar[i], star1, star2);
+	/* has to be a really significant improvement */
+	if (finite(starchi) && (starchi/galchi < 10*stograt) && (starchi < 10*npt)) {
+	  mprint (3, " result-> a split star: gal-chi: %f, star-chi: %f\n", galchi, starchi);
+	  jmtype = 3;
+	  parupd (star1, shadow[i], ix, iy);
+	  parupd (star1, starpar[i], ix, iy);
+	  addstar (starpar[i], SUB, jmtype);
+	  imtype[nstot] = 3;
+	  parupd (star2, starpar[nstot], ix, iy);
+	  parupd (star2, shadow[nstot], ix, iy);	
+	  addstar (starpar[nstot], SUB, jmtype);
+	  nstot ++;
+	  continue;
+	}
+      }
+      parupd (star, starpar[i], ix, iy);
+
+      if ((thresh < tmax / 4) && (thresh > tmax/16)) {
+
+	float err2[NPMAX], galchi2;
+
+	beta4 = 0.01;
+	for (n = 0; n < NPMAX; n++) star2[n] = star[n];
+	galchi2 = chisq (onestar, xs, ys, zs, dzs, npt, star2, err2, NFIT2, acc, parlim, nit);
+	if (1.2*galchi2 < galchi) {
+	  jmtype = 12;
+	  parupd (star2, starpar[i], ix, iy);
+	  mprint (3, "extended: %f vs %f  %f %f  %f -   %d\n", galchi/npt, galchi2/npt, starpar[i][2], starpar[i][3], star[1], jmtype);
+	}
+	beta4 = 1.0;
+      }
+
+      addstar (starpar[i], SUB, jmtype);
+      imtype[i] = fixxy ? jmtype + 100 : jmtype;
+      continue;
+    }
+      
+    verybig = galaxy (star, shaderr[i], starpar[i]);
+    if (jmtype == 3) verybig = verybig && (chi[4] > xtra);
+
+    /* shouldn't this test come earlier? */
+    converge = finite(galchi);
+    offp = offpic (star, ix, iy, &dx, &dy);
+    verybig = verybig && !offp && converge;;
+
+    if (!verybig || fixxy) {
+      if (jmtype != 3) jmtype = 1;
+      if (!converge) {
+	if (jmtype != 3) jmtype = 9;
+	mprint (3, "obj %d, npts %d, %d & %d .... failed to converge\n", i, npt, ix, iy);
+	addstar (starpar[i], SUB, jmtype);
+	imtype[i] = fixxy ? jmtype + 100 : jmtype;
+	continue;
+      }
+      if (offp) {
+	jmtype = 9;
+	imtype[i] = fixxy ? jmtype + 100 : jmtype;
+	mprint (3, "obj %d, npts %d, %d & %d .... fit center outside fit subraster\n", i, npt, ix, iy);
+      }
+      addstar (starpar[i], SUB, jmtype);
+      imtype[i] = fixxy ? jmtype + 100 : jmtype;
+      continue;
+    }
+	   
+    mprint (3, "obj %d, npts %d, %d & %d .... is very big....\n", i, npt, ix, iy);
+    mprint (3, ".... testing galaxy vs. double-star \n");
+    
+    starchi = twofit (star, starpar[i], star1, star2);
+
+    if (finite(starchi) && (starchi/galchi < stograt)) {
+      mprint (3, " result-> a split star: gal-chi: %f, star-chi: %f\n", galchi, starchi);
+      jmtype = 3;
+      parupd (star1, shadow[i], ix, iy);
+      parupd (star1, starpar[i], ix, iy);
+      addstar (starpar[i], SUB, jmtype);
+      imtype[nstot] = 3;
+      parupd (star2, starpar[nstot], ix, iy);
+      parupd (star2, shadow[nstot], ix, iy);	
+      addstar (starpar[nstot], SUB, jmtype);
+      nstot ++;
+    } else {
+      mprint (3, " result-> a galaxy: gal-chi: %f, star-chi: %f\n", galchi, starchi);
+      jmtype = 2;
+      parupd (star, starpar[i], ix, iy);
+      if (star[1]*star[4]*star[6]*ufactor > 20000) {
+	float err2[NPMAX], galchi2;
+
+	beta4 = 0.01;
+	for (n = 0; n < NPMAX; n++) star2[n] = star[n];
+	galchi2 = chisq (onestar, xs, ys, zs, dzs, npt, star2, err2, NFIT2, acc, parlim, nit);
+	if (1.2*galchi2 < galchi) {
+	  jmtype = 12;
+	  parupd (star2, starpar[i], ix, iy);
+	}
+	/* fprintf (stderr, "extended: %f vs %f  %f %f  %f -   %d\n", galchi/npt, galchi2/npt, starpar[i][2], starpar[i][3], star[1], jmtype);
+	 */
+	beta4 = 1.0;
+      }
+      addstar (starpar[i], SUB, jmtype);
+    }
+    imtype[i] = fixxy ? jmtype + 100 : jmtype;
+  }
+  test7 = FALSE;
+}
+
+
+
+/*****************
+
+  This routine seems really poorly written.  there is too much obfuscation.
+
+  we just need to do a few things:
+
+  1) do we try this object with 7-par fit? (if no, continue)
+
+  2) fit the object with 7-par fit
+
+  3) did it succeed? (if no, set some types)
+
+  4) should it be a type 10? (ie, very bright)
+
+  5) should it be a type 2? (ie, significantly extended)
+
+  6) should if be a type 3? (ie, split in two)
+
+  7) should it be a type 12? (ie, hubble fit)
+
+******************/
Index: /tags/start/Ohana/src/gophot/src/skyfun_plane.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/skyfun_plane.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/skyfun_plane.c	(revision 12606)
@@ -0,0 +1,22 @@
+# include "gophot.h"
+
+# define HALF 0.5
+
+float skyfun_plane (int ix, int iy, float *a, float *fa) {
+	
+  int i;
+  float value;
+
+  fa[0] = 1.0;
+  fa[1] = HALF*(ix - HALF*nfast)/(HALF*nfast);
+  fa[2] = HALF*(iy - HALF*nslow)/(HALF*nslow);
+
+  value = 0;
+  for (i = 0; i < 1; i++) {
+    value += a[i]*fa[i];
+  }
+
+  return (value);
+}
+
+/* this function uses C 0,N-1 for a[], fa[] */
Index: /tags/start/Ohana/src/gophot/src/sort.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/sort.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/sort.c	(revision 12606)
@@ -0,0 +1,77 @@
+
+sort (float *value, int N) {
+
+  int l,j,ir,i;
+  float temp;
+  
+  if (N < 2) return;
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      temp = value[--l];
+    }
+    else {
+      temp = value[ir];
+      value[ir] = value[0];
+      if (--ir == 0) {
+	value[0] = temp;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && value[j] < value[j+1]) ++j;
+      if (temp < value[j]) {
+	value[i]=value[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    value[i] = temp;
+  }
+}
+
+sortkey (int *index, float *key, int N) {
+
+  int l,j,ir,i;
+  float ktmp;
+  int  itmp;
+  
+  if (N < 2) return;
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      ktmp = key[l];
+      itmp = index[l];
+    }
+    else {
+      ktmp    = key[ir];
+      key[ir] = key[0];
+      itmp      = index[ir];
+      index[ir] = index[0];
+      ir--;
+      if (ir == 0) {
+	key[0] = ktmp;
+	index[0] = itmp;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && key[j] < key[j+1]) ++j;
+      if (ktmp < key[j]) {
+	key[i] = key[j];
+	index[i] = index[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    key[i] = ktmp;
+    index[i] = itmp;
+  }
+}
Index: /tags/start/Ohana/src/gophot/src/toobright.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/toobright.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/toobright.c	(revision 12606)
@@ -0,0 +1,64 @@
+# include "gophot.h"
+
+bool toobright (float *star) {
+
+  bool value;
+  bool flag;
+  int jrect[5];
+  int nsat, nbad, ix, iy, ixhi, ixlo, iyhi, iylo, jx, jy;
+  float dum, duma[NPMAX];
+
+  value = FALSE;
+	
+  if (star[1] < itop/4) return (FALSE);
+
+  nsat = 0;
+  nbad = 0;
+  dum = guess2 (duma, star, &ix, &iy);
+  ixhi = MIN ((int)(ix + krect[1]/2 + 0.5), nfast - 1);
+  ixlo = MAX ((int)(ix - krect[1]/2 + 0.5), 0);
+  iyhi = MIN ((int)(iy + krect[2]/2 + 0.5), nslow - 1);
+  iylo = MAX ((int)(iy - krect[2]/2 + 0.5), 0);
+
+  for (jy = iylo; jy <= iyhi; jy++) {
+    for (jx = ixlo; jx <= ixhi; jx++) {
+      if (!finite (noise[jx+jy*nfast])) nbad ++;
+      if (big[jx+jy*nfast] >= itop) nsat ++;
+    }
+  }
+
+  value = (star[1] > cmax) || (nsat >= icrit) || (nbad >= icrit);
+
+  mprint (3, "object at: %d, %d - %d:  %d %d %f %f %f\n", ix,iy, value, nsat, nbad, star[1], big[ix+iy*nfast], noise[ix+iy*nfast]);
+
+  if (value) {
+    if (nsat >= icrit)  star[1] = ctpersat*nsat;
+    
+    oblims(star,jrect);
+    
+    star[4] = jrect[2] - jrect[1];
+    star[5] = nsat;
+    star[6] = jrect[4] - jrect[3];
+    
+    mprint (0, "%d, %d funny pixels in object at %d, %d (%f peak)\n", nsat, nbad, ix, iy, star[1]);
+  }
+
+  return (value);
+}
+
+bool verybright (float *star) {
+
+  float flux;
+
+  /* rough scaling to compare fits with different scale */
+
+  flux = star[1]*sqrt((star[4]*star[6])/(ava[4]*ava[6]));;
+
+  if (flux > cmax) {
+    return (TRUE);
+  } else {
+    return (FALSE);
+  }
+
+}
+
Index: /tags/start/Ohana/src/gophot/src/toofaint.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/toofaint.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/toofaint.c	(revision 12606)
@@ -0,0 +1,22 @@
+# include "gophot.h"
+
+bool toofaint (float *star, float *err) {
+
+  bool value;
+  float cmin, sig2;
+
+  cmin = 1.0;
+  value = (star[1] < cmin);
+
+  if (err[1] > 0) {
+    sig2 = SQ(star[1]/ufactor) / err[1];
+    value = value || (sig2 < crit7);
+    mprint (3, "sig2 = %f (%f %f %f)\n", sig2, star[1], ufactor, err[1]);
+    mprint (3, "value, crit7: %d, %f\n", value, crit7);
+  }
+
+  return (value);
+
+}
+
+/* this function uses C 0,N-1 for a[], fa[] */
Index: /tags/start/Ohana/src/gophot/src/transmask.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/transmask.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/transmask.c	(revision 12606)
@@ -0,0 +1,94 @@
+# include "gophot.h"
+
+bool transmask (int ix, int iy, float sky) {
+
+  bool value;
+  int i, j, ii, jj;
+  float tmp, tmp0, tmp1, tmp2, ratio, hump2;
+  float tmpB, tmpN, df;
+  float *Bval, *Nval, cval, tmp3;
+
+  value = FALSE;
+
+  if (test7) 
+    hump2 = crit7;
+  else
+    hump2 = SQ (bumpcrit);
+
+  tmp0 = tmp1 = tmp2 = 0;
+  tmpB = tmpN = tmp3 = 0;
+
+  cval = big[ix + iy*nfast];
+
+  jj = iy - iyby2;
+  for (j = 0; j < 2*iyby2 + 1; j++, jj++) {
+    if (jj < 0) continue;
+    if (jj > nslow - 1) continue;
+    
+    ii = ix - ixby2;
+    Bval = &big[ii + jj*nfast];
+    Nval = &noise[ii + jj*nfast];
+    for (i = 0; i < 2*ixby2 + 1; i++, ii++, Bval++, Nval++) {
+      if (ii < 0) continue;
+      if (ii > nfast - 1) continue;
+      if (!finite (*Nval)) continue;
+
+# if (1)
+      tmp0 ++;
+      tmp = starmask[i][j] / (*Nval + *Bval);
+      tmp1 += tmp*starmask[i][j];
+      tmp2 += tmp*(*Bval-sky);
+      
+# else
+
+      tmp0 ++;
+      tmp1 += (*Nval + *Bval);
+      tmp2 += (*Bval - sky);
+
+      df = (cval - *Bval);
+      tmp3 +=  df * fabs(df) / (*Nval + *Bval);
+
+# endif
+
+      tmpB += (*Bval - sky);
+      tmpN += (*Nval - rnoise);
+    }
+  }
+
+  if (tmp0 == 0) return (FALSE);
+
+  if (tmpB < tmpN) return (FALSE);  
+
+  if (tmp2 > 0) {
+    ratio = tmp2*tmp2/tmp1;
+
+# if (1)
+    if (ratio > hump2) {
+      value = TRUE;
+      mprint (3, " trigger 1 on new object: %d, %d,  %f %f   %f %f %f\n", ix, iy, ratio, tmp3, sky, tmp2, tmp1);
+      if (ratio < 1.1*hump2) mprint (3, "marginal: (s/n)**2 through mask = %f\n", ratio);
+    }
+# else
+    if ((ratio > hump2) && (tmp3 > 0.25*ratio)) {
+      value = TRUE;
+      mprint (3, " trigger 1 on new object: %d, %d,  %f %f   %f %f %f\n", ix, iy, ratio, tmp3, sky, tmp2, tmp1);
+      if (ratio < 1.1*hump2) mprint (3, "marginal: (s/n)**2 through mask = %f\n", ratio);
+    }
+# endif
+
+  }
+
+  if (value) mprint (3, " trigger 2 on new object: %d, %d\n", ix, iy);
+
+  return (value);
+
+}
+
+
+  /* t1 = 1/N
+     t2 = d/N
+     rat = N d^2 / N^2 = d^2 / N
+  */
+
+/* does not check if bump is significant in region, 
+   only if mask region is significant over sky */
Index: /tags/start/Ohana/src/gophot/src/twofit.c
===================================================================
--- /tags/start/Ohana/src/gophot/src/twofit.c	(revision 12606)
+++ /tags/start/Ohana/src/gophot/src/twofit.c	(revision 12606)
@@ -0,0 +1,127 @@
+# include "gophot.h"
+
+/****************************************
+ there are big problems here with the values of b and probably 
+ other things.  fix please! */
+
+/* we are fitting two stars at the location of the input star */
+/* starraw has the real X,Y coords, star is relative to centroid */
+
+float twofit (float *star, float *starraw, float *star1, float *star2) {
+
+  int i;
+  float b[2*NPMAX], err[2*NPMAX], bacc[2*NPMAX], bparlim[2*NPMAX], tstar[NPMAX];
+  bool badfit, conv;
+  float a5, a7, angle, root, root1, root2, dx2, dy2, dx, dy, value;
+  float garea, sarea, dx74, dy74, dot, fac1, fac2, dxmax, dymax;
+
+  badfit = FALSE;
+  conv = TRUE;
+
+  /* fills in values 1, 5, 6, 7, 8 */
+  parinterp (starraw[2], starraw[3], tstar);
+
+  /* this all seems way too obtuse. */
+  a5 = 1.0/star[4];
+  a7 = 1.0/star[6];
+  angle = atan2 (-2*star[5], a7 - a5)/2.0;
+  root = sqrt (SQ(a5 - a7) + 4*SQ(star[5]));
+  root1 = (a5 + a7 + root)/2.0;
+  root2 = root1 - root;
+  dx2 = star[4] - tstar[4];
+  dy2 = star[6] - tstar[6];
+  dx = sqrt (MAX (dx2, 0.0)) / 2.0;
+  dy = sqrt (MAX (dy2, 0.0)) / 2.0;
+  badfit = (MAX (dx, dy) == 0);
+  /* we can use these since dx & dy are always >= 0 */
+  dx = (cos(angle) < 0) ? -dx : dx;
+  dy = (sin(angle) < 0) ? -dy : dy;
+  garea = 1.0 / sqrt (fabs (root1*root2));
+  sarea = sqrt (fabs (tstar[4]*tstar[6]));
+  dx74 = starraw[2] - star[2];	
+  dy74 = starraw[3] - star[3];		
+  dot = dx74*dx + dy74*dy;
+  if (dot > 0) {
+    fac1 = 0.6666666;
+    fac2 = 1.3333333;
+  } else {
+    fac1 = 1.3333333;
+    fac2 = 0.6666666;
+  }
+	   
+  /* 
+     b[0] - sky
+     b[1] - I1
+     b[2], b[3] - X1, Y1
+     b[4] - I2
+     b[5], b[6] - X2, Y2
+     b[7], b[8], b[9] - shape 
+  */
+
+  b[0] = star[0];
+  b[1] = (star[1]*garea*fac2 / (sarea*2));
+  b[2] = star[2] - dx*fac1;
+  b[3] = star[3] - dy*fac1;
+  b[4] = (star[1]*garea*fac1 / (sarea*2));		
+  b[5] = star[2] + dx*fac2;
+  b[6] = star[3] + dy*fac2;
+
+  /* for reasons unclear, the fit is done in ln(Io), not Io */
+  b[1] = log(b[1]);
+  b[4] = log(b[4]); 
+
+  b[7] = tstar[4];
+  b[8] = tstar[5];
+  b[9] = tstar[6];
+
+  bacc[0] = acc[0];
+  bacc[1] = bacc[4] = acc[1];
+  bacc[2] = bacc[5] = acc[2];
+  bacc[3] = bacc[6] = acc[3];
+
+  bparlim[0] = parlim[0];
+  bparlim[1] = bparlim[4] = parlim[1];
+  bparlim[2] = bparlim[5] = parlim[2];
+  bparlim[3] = bparlim[6] = parlim[3];
+
+  dxmax = MAX (fabs(b[2]), fabs(b[5]));
+  dymax = MAX (fabs(b[3]), fabs(b[6]));
+  badfit = badfit || (dxmax > irect[1]/2.0);
+  badfit = badfit || (dymax > irect[2]/2.0);
+
+  if (!badfit) {
+    value = chisq (twostar, xs, ys, zs, dzs, npt, b, err, NFIT2, bacc, bparlim, 2*nit);
+    conv = finite (value);
+  }
+	
+  dxmax = MAX (fabs(b[2]), fabs(b[5]));
+  dymax = MAX (fabs(b[3]), fabs(b[6]));
+  badfit = badfit || (dxmax > 0.4*irect[1]);
+  badfit = badfit || (dymax > 0.4*irect[2]);
+
+  if (conv) {
+    if (b[1] < b[4]) {
+      SWAP (b[1], b[4]);
+      SWAP (b[2], b[5]);
+      SWAP (b[3], b[6]);
+    }
+    
+    star1[0] = star2[0] = b[0];
+    star1[4] = star2[4] = b[7];
+    star1[5] = star2[5] = b[8];
+    star1[6] = star2[6] = b[9];
+    star1[1] = exp(b[1]);
+    star1[2] = b[2];
+    star1[3] = b[3];
+    star2[1] = exp(b[4]);
+    star2[2] = b[5];
+    star2[3] = b[6];
+  }
+
+  badfit = badfit || centertest (star1, xs, ys);
+  badfit = badfit || centertest (star2, xs, ys);
+  if (!conv || badfit) value = MAGIC;
+
+  return (value);
+}
+/* this function uses C 0,N-1 for a[], fa[] */
Index: /tags/start/Ohana/src/imclean/Makefile
===================================================================
--- /tags/start/Ohana/src/imclean/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/imclean/Makefile	(revision 12606)
@@ -0,0 +1,56 @@
+include ../../Configure
+HOME    =       $(ROOT)/src/imclean
+PROGRAM =       imclean
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#  
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lFITS -lohana -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS)
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+OBJ = \
+$(SRC)/imclean.$(ARCH).o	$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/args.$(ARCH).o		$(SRC)/sort_stars.$(ARCH).o \
+$(SRC)/AdjustHeader.$(ARCH).o	$(SRC)/find_group.$(ARCH).o \
+$(SRC)/find_trails.$(ARCH).o	$(SRC)/find_line.$(ARCH).o \
+$(SRC)/LoadStarsDophot.$(ARCH).o $(SRC)/wstars.$(ARCH).o	\
+$(SRC)/LoadStarsSex.$(ARCH).o	$(SRC)/LoadStarsChad.$(ARCH).o	
+
+default: $(PROGRAM)
+
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:	
+	rm -f *~
+	rm -f #*
+	rm -f */*~
+	rm -f */#*
+	rm -f $(SRC)/*.o
+	rm -f $(BIN)/*.$(ARCH)
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
+
+
Index: /tags/start/Ohana/src/imclean/include/imclean.h
===================================================================
--- /tags/start/Ohana/src/imclean/include/imclean.h	(revision 12606)
+++ /tags/start/Ohana/src/imclean/include/imclean.h	(revision 12606)
@@ -0,0 +1,62 @@
+# include <ohana.h>
+# include <loneos.h>
+
+enum {DOPHOT, CHAD, SEXTRACT};
+
+int    MODE;
+int    VERBOSE;
+int    RESET;
+int    FORCE_RUN;
+int    PROVIDE_ASTROM;
+int    NEWPHOTCODE;
+
+/* global variables set in parameter file */
+char   *PHOTCODE;
+char   PhotCodeFile[256];
+char   AstromFile[256];
+
+double DEFAULT_ERROR;
+double RADIUS;
+double TRAIL_WIDTH;
+int    NBINS;
+int    NPTSINLINE;
+double MIN_DENSITY;
+double NSIGMA;
+
+double RA, DEC, ZERO_POINT, MIN_SN_FSTAT;
+int CHAR_LINE, TYPE_FIELD, AP_FIELD, PSF_FIELD, HEADER_COORDS;
+
+int FIX_KEYWORD;
+char **KEYWORD, **KEYVALU, **KEYFMT;
+
+typedef struct {
+  double X;
+  double Y;
+  double M, dM;
+  char   dophot;
+  double sky;
+  double fx, fy, df;
+  double Mgal, Map;
+} Stars;
+
+Stars *LoadStars ();
+Stars *LoadStarsChad ();
+Stars *LoadStarsSex ();
+
+Stars *LoadStarsDophot (char *filename, int *nstars, Header *header);
+Stars *LoadStarsChad (char *filename, int *nstars, Header *header);
+Stars *LoadStarsSex (char *filename, int *nstars, Header *header);
+
+void ConfigInit (int *argc, char **argv);
+void AdjustHeader (Header *header);
+void sort_stars (Stars *X, int N);
+void find_trails (Stars *stars, int Nstars);
+int find_group (Stars *stars, char *mark, int Npts, int i, double *ANGLE);
+void wstars (char *filename, Stars *stars, int Nstars, Header *header);
+
+void fix_total (Stars *stars, int Nstars, Header *header);
+int find_line (Stars *stars, char *mark, int Npts, int i, double *M, double *B, double Angle);
+void find_better_line (Stars *stars, char *mark, int Npts, int i, double *M, double *B, int axis);
+
+void help ();
+void args (int argc, char **argv);
Index: /tags/start/Ohana/src/imclean/src/AdjustHeader.c
===================================================================
--- /tags/start/Ohana/src/imclean/src/AdjustHeader.c	(revision 12606)
+++ /tags/start/Ohana/src/imclean/src/AdjustHeader.c	(revision 12606)
@@ -0,0 +1,109 @@
+# include "imclean.h"
+
+void AdjustHeader (Header *header) {
+
+  int i;
+  double value;
+  char line[256];
+
+  if (FIX_KEYWORD) {
+    for (i = 0; i < FIX_KEYWORD; i++) {
+      if (!strcmp (KEYFMT[i], "%f")) {
+	value = atof (KEYVALU[i]);
+	fits_modify (header, KEYWORD[i], "%le", 1, value);
+      } else {
+	fits_modify (header, KEYWORD[i], "%s", 1, KEYVALU[i]);
+      }
+    }
+  }
+
+  if (NEWPHOTCODE) {
+    /* we are going to write the photcode into the header
+       here we are just checking that the photcode provided
+       is a valid code */
+    if (!LoadPhotcodes (PhotCodeFile)) {
+      fprintf (stderr, "ERROR: can't load photcodes\n");
+      exit (1);
+    }
+    if (!GetPhotcodebyName (PHOTCODE)) {
+      fprintf (stderr, "ERROR: photcode not found in photcode table\n");
+      exit (1);
+    }
+    fits_modify (header, "PHOTCODE", "%s", 1, PHOTCODE);
+  }    
+
+  if (!HEADER_COORDS) {
+    int rh, rm, dd, dm;
+    float rs, ds;
+    RA = RA / 15.0;
+    rh = RA; /* rh is int */
+    rm = 60.0 * (RA - rh);
+    rs = 3600 * (RA - rh - rm / 60.0);
+    sprintf (line, "%02d:%02d:%05.2f", rh, rm, rs);
+    fits_modify (header, "RA", "%s", 1, line);
+    dd = DEC;
+    dm = 60.0 * (DEC - dd);
+    ds = 3600 * (DEC - dd - dm / 60.0);
+    sprintf (line, "%02d:%02d:%05.2f", dd, dm, ds);
+    fits_modify (header, "DEC", "%s", 1, line);
+  }
+ 
+  if (PROVIDE_ASTROM) {
+
+    Header astrom_header;
+    Coords coords;
+
+    if (!fits_read_header (AstromFile, &astrom_header)) {
+      fprintf (stderr, "ERROR: can't get astrometry from %s\n", AstromFile);
+      exit (1);
+    }
+    if (!GetCoords (&coords, &astrom_header)) {
+      fprintf (stderr, "ERROR: no astrometric solution in header\n");
+      exit (1);
+    }
+    if (coords.Npolyterms > 1) {
+      fits_modify (header, "CTYPE1",   "%s",  1, "RA---PLY");
+      fits_modify (header, "CTYPE2",   "%s",  1, "DEC--PLY");
+    } else {
+      fits_modify (header, "CTYPE1",   "%s",  1, "RA---TAN");
+      fits_modify (header, "CTYPE2",   "%s",  1, "DEC--TAN");
+    }    
+    fits_modify (header, "NASTRO",   "%d", 1, 1); 
+
+    fits_modify (header, "CDELT1",   "%le", 1, coords.cdelt1); 
+    fits_modify (header, "CDELT2",   "%le", 1, coords.cdelt2);
+    fits_modify (header, "CRVAL1",   "%lf", 1, coords.crval1);
+    fits_modify (header, "CRVAL2",   "%lf", 1, coords.crval2);  
+    fits_modify (header, "CRPIX1",   "%lf", 1, coords.crpix1);
+    fits_modify (header, "CRPIX2",   "%lf", 1, coords.crpix2);
+    fits_modify (header, "PC001001", "%le", 1, coords.pc1_1);
+    fits_modify (header, "PC001002", "%le", 1, coords.pc1_2);
+    fits_modify (header, "PC002001", "%le", 1, coords.pc2_1);
+    fits_modify (header, "PC002002", "%le", 1, coords.pc2_2);
+    fits_modify (header, "NPLYTERM", "%d", 1, coords.Npolyterms);
+    if (coords.Npolyterms > 1) {
+      /* RA Terms */
+      fits_modify (header, "PCA1X2Y0", "%le", 1, coords.polyterms[0][0]);   /* polyterms[0]); */
+      fits_modify (header, "PCA1X1Y1", "%le", 1, coords.polyterms[1][0]);   /* polyterms[1]); */
+      fits_modify (header, "PCA1X0Y2", "%le", 1, coords.polyterms[2][0]);   /* polyterms[2]); */
+      
+      if (coords.Npolyterms > 2) {
+	fits_modify (header, "PCA1X3Y0", "%le", 1, coords.polyterms[3][0]);   /* polyterms[3]); */
+	fits_modify (header, "PCA1X2Y1", "%le", 1, coords.polyterms[4][0]);   /* polyterms[4]); */
+	fits_modify (header, "PCA1X1Y2", "%le", 1, coords.polyterms[5][0]);   /* polyterms[5]); */
+	fits_modify (header, "PCA1X0Y3", "%le", 1, coords.polyterms[6][0]);   /* polyterms[6]); */
+      }
+      /* Dec Terms */
+      fits_modify (header, "PCA2X2Y0", "%le", 1, coords.polyterms[0][1]);   /* polyterms[7]); */
+      fits_modify (header, "PCA2X1Y1", "%le", 1, coords.polyterms[1][1]);   /* polyterms[8]); */
+      fits_modify (header, "PCA2X0Y2", "%le", 1, coords.polyterms[2][1]);   /* polyterms[9]); */
+      
+      if (coords.Npolyterms > 2) {
+	fits_modify (header, "PCA2X3Y0", "%le", 1, coords.polyterms[3][1]);   /* polyterms[10]); */
+	fits_modify (header, "PCA2X2Y1", "%le", 1, coords.polyterms[4][1]);   /* polyterms[11]); */
+	fits_modify (header, "PCA2X1Y2", "%le", 1, coords.polyterms[5][1]);   /* polyterms[12]); */
+	fits_modify (header, "PCA2X0Y3", "%le", 1, coords.polyterms[6][1]);   /* polyterms[13]); */
+      }
+    }
+  }
+}
Index: /tags/start/Ohana/src/imclean/src/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/imclean/src/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/imclean/src/ConfigInit.c	(revision 12606)
@@ -0,0 +1,36 @@
+# include "imclean.h"
+
+void ConfigInit (int *argc, char **argv) {
+  
+  char *config, *file;
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (1);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  ScanConfig (config, "ZERO_PT",           "%lf", 0, &ZERO_POINT);
+  ScanConfig (config, "MIN_SN_FSTAT",      "%lf", 0, &MIN_SN_FSTAT);
+  ScanConfig (config, "DEFAULT_ERROR_FSTAT", "%lf", 0, &DEFAULT_ERROR);
+  ScanConfig (config, "DOPHOT_CHAR_LINE",  "%d", 0, &CHAR_LINE);
+  ScanConfig (config, "DOPHOT_TYPE_FIELD", "%d", 0, &TYPE_FIELD);
+  ScanConfig (config, "DOPHOT_PSF_FIELD",  "%d", 0, &PSF_FIELD);
+  ScanConfig (config, "DOPHOT_AP_FIELD",   "%d", 0, &AP_FIELD);
+  ScanConfig (config, "PHOTCODE_FILE",     "%s", 0, PhotCodeFile);
+
+  /* unique to markstar */
+  ScanConfig (config, "SEARCH_RADIUS",   "%lf", 0, &RADIUS);
+  ScanConfig (config, "TRAIL_WIDTH",     "%lf", 0, &TRAIL_WIDTH);
+  ScanConfig (config, "NANGLE_BINS",     "%d",  0, &NBINS);
+  ScanConfig (config, "NPTSINLINE",      "%d",  0, &NPTSINLINE);
+  ScanConfig (config, "MIN_DENSITY",     "%lf", 0, &MIN_DENSITY);
+  ScanConfig (config, "SPACE_SIGMA",     "%lf", 0, &NSIGMA); 
+
+  free (config);
+  free (file);
+}
Index: /tags/start/Ohana/src/imclean/src/LoadStarsChad.c
===================================================================
--- /tags/start/Ohana/src/imclean/src/LoadStarsChad.c	(revision 12606)
+++ /tags/start/Ohana/src/imclean/src/LoadStarsChad.c	(revision 12606)
@@ -0,0 +1,131 @@
+# include "imclean.h"
+# define NBLOCK 100
+# define HIST_BINS 150
+
+Stars *LoadStarsChad (char *filename, int *nstars, Header *header) {
+
+  FILE *f;
+  Stars *stars;
+  int NSTARS, Nstars, i, N;
+  int status;
+  double x, y, m, sky, lsky;
+  char *buffer;
+  int Mhist[HIST_BINS], Shist[HIST_BINS], bin, sum;
+  double FWHMx, FWHMy, angle, flux;
+  int satfound, done;
+  double saturate, complete;
+  char line[256];
+
+  ALLOCATE (buffer, char, CHAR_LINE*NBLOCK);
+
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't find object file %s\n", filename);
+    exit (1);
+  }
+
+  /* zero things that will sum */
+  for (i = 0; i < HIST_BINS; i++) { Mhist[i] = Shist[i] = 0; }
+
+  Nstars = 0;
+  NSTARS = 500;
+  ALLOCATE (stars, Stars, NSTARS);
+
+  /* for now assume file 'header' is fixed-format */
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+  if (strncasecmp (line, "#seeing", 7)) {
+    fprintf (stderr, "error in header, skipping\n");
+    exit (1);
+  }
+  sscanf (line, "%*s %lf", &FWHMx);
+  FWHMy = FWHMx;
+  angle = 0;
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+
+  /* read in data from obj file */
+  /* data is not fixed format for lines, read each line one-at-a-time */
+  for (i = 0; (status = fscanf (f, "%lf %lf %*f %*f %lf %lf %*f", &x, &y, &sky, &flux)) != EOF; i++) {
+
+    if (status != 4) {
+      fprintf (stderr, "format error in file %s, line %d\n", filename, i);
+      continue;
+    }
+
+    if (flux <= 0) continue;
+    m = -2.5*log10 (flux);
+
+    if (sky < 1.0) {
+      lsky = 0.0;
+    } else {
+      lsky = log10(sky);
+    }
+
+    bin = MAX (0.0, MIN (HIST_BINS, 10.0 * (m + 15.0)));  /* stick in 0.1 mag bins */
+    Mhist[bin] ++;
+
+    m = MIN (50.0, m);
+    m = MAX (-24.0, m);
+
+    stars[Nstars].fx = 0;
+    stars[Nstars].fy = 0;
+    stars[Nstars].df = 0;
+    stars[Nstars].Mgal = 50.0;;
+    stars[Nstars].Map = 50.0;
+    stars[Nstars].X = x;
+    stars[Nstars].Y = y;
+    stars[Nstars].M = m;
+    stars[Nstars].dM = 0.01;
+    stars[Nstars].dophot = 1;
+    stars[Nstars].sky = lsky;
+    Nstars++;
+    if (Nstars == NSTARS - 1) {
+      NSTARS += 500;
+      REALLOCATE (stars, Stars, NSTARS);
+    }
+  }
+
+  /* look at histogram, find saturation and completion limits */
+  sum = 0;
+  for (i = 0; i < HIST_BINS; i++) {
+    sum += Mhist[i];
+    Shist[i] = sum;
+  }
+  satfound = done = FALSE;
+  for (i = 0; (i < HIST_BINS) && !done; i++) {
+    if ((!satfound) && (Mhist[i] > 0)) {
+      saturate = 0.1*(i-1) - 15.0;
+      satfound = TRUE;
+    }
+    if (Shist[i] > 0.9*Shist[HIST_BINS - 1]) {
+      complete = 0.1*i - 15.0;
+      done = TRUE;
+    }
+  }
+  
+  fits_modify (header, "ZERO_PT", "%lf", 1, ZERO_POINT);
+  fits_modify (header, "FWHM_X", "%lf", 1, FWHMx);
+  fits_modify (header, "FWHM_Y", "%lf", 1, FWHMy);
+  fits_modify (header, "ANGLE", "%lf", 1, angle);
+  fits_modify (header, "FSATUR", "%lf", 1, (saturate + ZERO_POINT));
+  fits_modify (header, "FLIMIT", "%lf", 1, (complete + ZERO_POINT));
+  fits_modify (header, "NSTARS", "%d", 1, N);
+  for (i = 1; i <= 9; i++) {
+    sprintf (line, "TDOPHOT%1d", i);
+    fits_modify (header, line, "%d", 1, 0);
+  }
+
+  *nstars = Nstars;
+  return (stars);
+
+}
Index: /tags/start/Ohana/src/imclean/src/LoadStarsDophot.c
===================================================================
--- /tags/start/Ohana/src/imclean/src/LoadStarsDophot.c	(revision 12606)
+++ /tags/start/Ohana/src/imclean/src/LoadStarsDophot.c	(revision 12606)
@@ -0,0 +1,175 @@
+# include "imclean.h"
+# define NBLOCK 100
+# define HIST_BINS 300 
+/* the mag histogram has range 0.0 to 30.0 */
+/* m = 0.1*Mhist[i] */
+
+Stars *LoadStarsDophot (char *filename, int *nstars, Header *header) {
+
+  FILE *f;
+  Stars *stars;
+  int NSTARS, Nstars, i, Nline, N;
+  int type, status;
+  double x, y, m, dm, sky, lsky, fx, fy, df, Mgal, Map;
+  char *buffer;
+  int Mhist[HIST_BINS], Shist[HIST_BINS], n[20], bin, sum;
+  double FWHMx, FWHMy, angle;
+  int satfound, done;
+  double saturate, complete;
+  char line[256];
+  int MedHist[2002], NMedHist;
+  double SMedHist, dMed;
+
+  NMedHist = 0;
+  bzero (MedHist, 2002*sizeof(int));
+
+  ALLOCATE (buffer, char, CHAR_LINE*NBLOCK);
+
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't find object file %s\n", filename);
+    exit (1);
+  }
+
+  /* zero things that will sum */
+  for (i = 0; i < HIST_BINS; i++) { Mhist[i] = Shist[i] = 0; }
+  for (i = 1; i <= 9; i++) { n[i] = 0; }
+
+  Nstars = 0;
+  NSTARS = 500;
+  ALLOCATE (stars, Stars, NSTARS);
+
+  /* read average values from first line */
+  scan_line (f, line);
+  sscanf (line, "%*s %*s %*s %lf %lf %lf", &FWHMx, &FWHMy, &angle);
+
+  /* read in data from obj file */
+  while ((Nline = fread (buffer, CHAR_LINE, NBLOCK, f)) > 0) {
+    for (i = 0; i < Nline; i++) {
+      /* we are now using all entries on the *.obj line */
+      status = sscanf (&buffer[i*CHAR_LINE], "%d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf", 
+		       &type, &x, &y, &m, &dm, &sky, &fx, &fy, &df, &Mgal, &Map);
+      if (status != 11) {
+	fprintf (stderr, "format error in file %s, line %d\n", filename, i);
+	continue;
+      }
+
+      /* dophot magnitudes can range from 99.999 to -99.999 
+	 realistic numbers are between -20 and 0
+	 outside, we should set the value to 50.0 to force saturation */
+      
+      n[type] ++;
+      if (type == 6) continue;
+      if (type == 9) continue;
+      if (type == 8) continue;
+      if (type == 16) continue;
+      
+      if (m > 0) continue;                /* skip stars which totally fail on fit */
+      if (dm == 0.0) dm = DEFAULT_ERROR;  /* stars with poor errors, get 25.5% errors */
+      dm = MIN (0.999, MAX (0.0, dm));    /* truncate dm to fit in range 0 - 999 on output */
+
+      /* need to accumulate the median histogram thingy */
+      dMed = Map - m;
+      if ((fabs(m) < 90) && (fabs(Map) < 90) && (fabs(dMed) < 1)) {
+	bin = 1000 * (dMed + 1);
+	MedHist[bin] ++;
+	NMedHist ++;
+      }
+      
+      /* dophot provides values which are -2.5*log(counts) */
+      m    = ((m    > -25) && (m    < 0)) ? m + ZERO_POINT    : 50.0;
+      Mgal = ((Mgal > -25) && (Mgal < 0)) ? Mgal + ZERO_POINT : 50.0;
+      Map  = ((Map  > -25) && (Map  < 0)) ? Map + ZERO_POINT  : 50.0;
+
+      if (sky < 1.0) {
+	lsky = 0.0;
+      } else {
+	lsky = log10(sky);
+      }
+
+      if (MIN_SN_FSTAT*dm > 1.0) continue;  /* skip stars with errors too large */
+          
+      switch (type) {
+      case 1:
+      case 4:
+      case 7:
+	bin = MAX (0, MIN (HIST_BINS - 1, 10.0 * m));  /* stick in 0.1 mag bins */
+	Mhist[bin] ++;
+      default:
+	if (df < 0.0) df += 360.0;
+	stars[Nstars].X      = x;
+	stars[Nstars].Y      = y;
+	stars[Nstars].M      = m;
+	stars[Nstars].Mgal   = Mgal;
+	stars[Nstars].Map    = Map;
+	stars[Nstars].dM     = dm;
+	stars[Nstars].dophot = type;
+	stars[Nstars].sky    = lsky;
+	stars[Nstars].fx     = fx;
+	stars[Nstars].fy     = fy;
+	stars[Nstars].df     = df;
+	Nstars++;
+	if (Nstars == NSTARS - 1) {
+	  NSTARS += 500;
+	  REALLOCATE (stars, Stars, NSTARS);
+	}
+      }
+    }
+
+  }    
+
+  /* look at histogram, find saturation and completion limits */
+  sum = 0;
+  for (i = 0; i < HIST_BINS; i++) {
+    sum += Mhist[i];
+    Shist[i] = sum;
+  }
+  satfound = done = FALSE;
+  for (i = 0; (i < HIST_BINS) && !done; i++) {
+    if ((!satfound) && (Mhist[i] > 0)) {
+      saturate = 0.1*(i-1);
+      satfound = TRUE;
+    }
+    if (Shist[i] > 0.9*Shist[HIST_BINS - 1]) {
+      complete = 0.1*i;
+      done = TRUE;
+    }
+  }
+  
+  SMedHist = 0;
+  for (i = 0; (i < 2002) && (SMedHist < NMedHist / 2); i++) {
+    SMedHist += MedHist[i];
+  }
+  if (i == 2002) {
+    fprintf (stderr, "error finding (Ap - Fit) median\n");
+    SMedHist = 0;
+  } else {
+    SMedHist = 0.001*i - 1;
+    fprintf (stderr, "(Ap - Fit) median = %f\n", SMedHist);
+  }
+
+  for (i = 0; i < Nstars; i++) {
+    stars[i].Mgal += SMedHist;
+    stars[i].M += SMedHist;
+  }    
+
+  fits_modify (header, "ZERO_PT", "%lf", 1, ZERO_POINT);
+  fits_modify (header, "FWHM_X", "%lf", 1, FWHMx);
+  fits_modify (header, "FWHM_Y", "%lf", 1, FWHMy);
+  fits_modify (header, "ANGLE", "%lf", 1, angle);
+  fits_modify (header, "FSATUR", "%lf", 1, saturate);
+  fits_modify (header, "FLIMIT", "%lf", 1, complete);
+  fits_modify (header, "APMIFIT", "%lf", 1, SMedHist);
+  fits_modify (header, "NSTARS", "%d", 1, N);
+  for (i = 1; i <= 9; i++) {
+    sprintf (line, "TDOPHOT%1d", i);
+    fits_modify (header, line, "%d", 1, n[i]);
+  }
+
+  *nstars = Nstars;
+  return (stars);
+
+}
+
+/* this function should load the stars and immediately convert them to
+   have the ZERO_PT zero point */
Index: /tags/start/Ohana/src/imclean/src/LoadStarsSex.c
===================================================================
--- /tags/start/Ohana/src/imclean/src/LoadStarsSex.c	(revision 12606)
+++ /tags/start/Ohana/src/imclean/src/LoadStarsSex.c	(revision 12606)
@@ -0,0 +1,141 @@
+# include "imclean.h"
+# define NBLOCK 100
+# define HIST_BINS 300 
+
+/* good for sextractor */
+
+Stars *LoadStarsSex (char *filename, int *nstars, Header *header) {
+
+  FILE *f;
+  Stars *stars;
+  int NSTARS, Nstars, i, Nline, N;
+  int type, status;
+  double x, y, m, dm, sky, lsky, ftype;
+  char *buffer;
+  int Mhist[HIST_BINS], Shist[HIST_BINS], n[10], bin, sum, flags;
+  double A, A2, S2, FWHMx, FWHMy, angle, Mgal, Map;
+  int gotFWHM, satfound, done;
+  double saturate, complete;
+
+  CHAR_LINE = 105;
+  TYPE_FIELD = 0;
+  
+  ALLOCATE (buffer, char, CHAR_LINE*NBLOCK);
+
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't find object file %s\n", filename);
+    exit (1);
+  }
+
+  /* zero things that will sum */
+  A = A2 = S2 = 0;
+  gotFWHM = FALSE;
+  for (i = 0; i < HIST_BINS; i++) { Mhist[i] = Shist[i] = 0; }
+  for (i = 1; i <= 9; i++) { n[i] = 0; }
+
+  Nstars = 0;
+  NSTARS = 500;
+  ALLOCATE (stars, Stars, NSTARS);
+
+  /* read in data from obj file */
+  while ((Nline = fread (buffer, CHAR_LINE, NBLOCK, f)) > 0) {
+    for (i = 0; i < Nline; i++) {
+      status = sscanf (&buffer[i*CHAR_LINE + TYPE_FIELD], "%lf %lf %lf %lf %lf   %lf %lf %lf %lf %lf  %lf %d", 
+		       &ftype, &x, &y, &m, &dm, &sky, &FWHMx, &FWHMy, &angle, &Mgal, &Map, &flags);
+      if (status != 12) {
+	fprintf (stderr, "ERROR: format error in file %s, line %d\n", filename, i);
+	continue;
+      } 
+
+      if (flags > 7) continue;
+      /* if (m > 0) continue; skip stars which totally fail on fit */
+      if (dm == 0.0) dm = DEFAULT_ERROR;  
+
+      /* sextract can provide values which are -2.5*log(counts) */
+      m    += ZERO_POINT;
+      Mgal += ZERO_POINT;
+      Map  += ZERO_POINT;
+      m    = MIN (32.767, MAX (-32.767, m));
+      Mgal = MIN (32.767, MAX (-32.767, Mgal));
+      Map  = MIN (32.767, MAX (-32.767, Map));
+
+      if (sky < 1) {
+	lsky = 0.0;
+      } else {
+	lsky = log10(sky);
+      }
+
+      /* type = MAX (0, MIN (9, 5*log10(ftype) + 10)); */
+      switch (flags) {
+      case 4:
+      case 5:
+      case 6:
+      case 7:
+	type = 10;
+	break;
+      case 1:
+      case 2:
+      case 3:
+	type = 3;
+	break;
+      default:
+	type = 1;
+      }
+
+      if (MIN_SN_FSTAT*dm > 1.0) continue;
+      
+      bin = MAX (0, MIN (HIST_BINS - 1, 10.0 * m));  /* stick in 0.1 mag bins */
+      Mhist[bin] ++;
+      
+      stars[Nstars].X = x;
+      stars[Nstars].Y = y;
+      stars[Nstars].M = m;
+      stars[Nstars].dM = dm;
+      stars[Nstars].dophot = type;
+      stars[Nstars].sky = lsky;
+      
+      stars[Nstars].fx = FWHMx;
+      stars[Nstars].fy = FWHMx * (FWHMy/FWHMx);
+      stars[Nstars].df = angle;
+      stars[Nstars].Mgal = Mgal;
+      stars[Nstars].Map = Map;
+
+      Nstars++;
+      if (Nstars == NSTARS - 1) {
+	NSTARS += 500;
+	REALLOCATE (stars, Stars, NSTARS);
+      }
+    }
+
+  }    
+
+  sum = 0;
+  for (i = 0; i < HIST_BINS; i++) {
+    sum += Mhist[i];
+    Shist[i] = sum;
+  }
+  satfound = done = FALSE;
+  for (i = 0; (i < HIST_BINS) && !done; i++) {
+    if ((!satfound) && (Mhist[i] > 0)) {
+      saturate = 0.1*(i-1);
+      satfound = TRUE;
+    }
+    if (Shist[i] > 0.9*Shist[HIST_BINS - 1]) {
+      complete = 0.1*i;
+      done = TRUE;
+    }
+  }
+  
+  fits_modify (header, "ZERO_PT", "%lf", 1, ZERO_POINT);
+  fits_modify (header, "FWHM_X", "%lf", 1, FWHMx);
+  fits_modify (header, "FWHM_Y", "%lf", 1, FWHMy);
+  fits_modify (header, "ANGLE", "%lf", 1, angle);
+  fits_modify (header, "FSATUR", "%lf", 1, saturate);
+  fits_modify (header, "FLIMIT", "%lf", 1, complete);
+  fits_modify (header, "NSTARS", "%d", 1, N);
+
+  *nstars = Nstars;
+  return (stars);
+
+}
Index: /tags/start/Ohana/src/imclean/src/addastro.c
===================================================================
--- /tags/start/Ohana/src/imclean/src/addastro.c	(revision 12606)
+++ /tags/start/Ohana/src/imclean/src/addastro.c	(revision 12606)
@@ -0,0 +1,56 @@
+# include <ohana.
+
+main (int argc, char **argv) {
+
+  Header header;
+  Stars *stars;
+  int Nstars;
+
+  ConfigInit (&argc, argv);
+
+  args (argc, argv);
+
+  /* load in FITS header from image */
+  if (!fits_read_header (argv[1], &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s\n", argv[1]);
+    exit (1);
+  }
+
+  AdjustHeader (&header);
+  
+  switch (MODE) {
+  case DOPHOT:
+    stars = LoadStarsDophot (argv[2], &Nstars, &header);
+    break;
+  case CHAD:
+    stars = LoadStarsChad (argv[2], &Nstars, &header);
+    break;
+  case SEXTRACT:
+    stars = LoadStarsSex (argv[2], &Nstars, &header);
+    break;
+  default: 
+    fprintf (stderr, "unknown mode: %d\n", MODE);
+    exit (1);
+  }
+
+  sort_stars (stars, Nstars);
+  find_trails (stars, Nstars);  
+  fix_total (stars, Nstars, &header);
+
+  wstars (argv[3], stars, Nstars, &header); 
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+
+}
+
+/* based on fstat and markstar:
+
+   0) load config data, global parameters 
+   1) load header
+   2) load data from *.obj file
+   3) eliminate bad star types: 6, 8
+   4) identify trails
+   5) get statistics on remaining stars
+
+*/
Index: /tags/start/Ohana/src/imclean/src/args.c
===================================================================
--- /tags/start/Ohana/src/imclean/src/args.c	(revision 12606)
+++ /tags/start/Ohana/src/imclean/src/args.c	(revision 12606)
@@ -0,0 +1,82 @@
+# include "imclean.h"
+# define NARGS 2  /* minimum is: addstar (filename) */
+
+void help () {
+
+  fprintf (stderr, "USAGE: imclean (file.fits) (file.obj) (file.cmp)\n");
+  exit (2);
+
+}
+
+void args (int argc, char **argv) {
+  
+  int i, N;
+
+  if (get_argument (argc, argv, "-help") ||
+      get_argument (argc, argv, "-h")) {
+    help ();
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  HEADER_COORDS = TRUE;
+  if ((N = get_argument (argc, argv, "-coords"))) {
+    remove_argument (N, &argc, argv);
+    RA = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    DEC = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    HEADER_COORDS = FALSE;
+  }
+
+  NEWPHOTCODE = FALSE;
+  if ((N = get_argument (argc, argv, "-p"))) {
+    NEWPHOTCODE = TRUE;
+    remove_argument (N, &argc, argv);
+    PHOTCODE = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  PROVIDE_ASTROM = FALSE;
+  if ((N = get_argument (argc, argv, "-astrom"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (AstromFile, argv[N]);
+    remove_argument (N, &argc, argv);
+    PROVIDE_ASTROM = TRUE;
+  }
+
+  MODE = DOPHOT;
+  if ((N = get_argument (argc, argv, "-chad"))) {
+    MODE = CHAD;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-sex"))) {
+    MODE = SEXTRACT;
+    remove_argument (N, &argc, argv);
+  }
+
+  ALLOCATE (KEYWORD, char *, 64);
+  ALLOCATE (KEYVALU, char *, 64);
+  ALLOCATE (KEYFMT, char *, 64);
+  FIX_KEYWORD = 0;
+  while ((N = get_argument (argc, argv, "-key"))) {
+    i = FIX_KEYWORD;
+    remove_argument (N, &argc, argv);
+    KEYWORD[i] = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    KEYFMT[i] = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    KEYVALU[i] = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    FIX_KEYWORD ++;
+    if (FIX_KEYWORD == 64) break;
+  }
+
+
+  if (argc != 4) help ();
+
+}
+
Index: /tags/start/Ohana/src/imclean/src/find_group.c
===================================================================
--- /tags/start/Ohana/src/imclean/src/find_group.c	(revision 12606)
+++ /tags/start/Ohana/src/imclean/src/find_group.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include "imclean.h"
+
+int find_group (Stars *stars, char *mark, int Npts, int i, double *ANGLE) {
+ 
+  int j, N, bin, Ndegbin;
+  unsigned short int *A;
+  double Xo, Yo, dX, dY, angle, limit;
+
+   /* assign some parameter values */
+  if (mark[i]) return (FALSE);
+
+  Ndegbin = NBINS / 180.0;
+  ALLOCATE (A, unsigned short int, NBINS + 1)
+  bzero (A, (NBINS+1)*sizeof(short));
+
+  /* look for points concentrated in an angle bin */
+  Xo = stars[i].X;
+  Yo = stars[i].Y;
+  N = 0;
+  /* points east */
+  for (j = i + 1; (j < Npts) && ((dX = stars[j].X - Xo) < RADIUS); j++) {
+    dY = stars[j].Y - Yo;
+    if (fabs(dY) < RADIUS) {
+      angle = atan2 (dY,dX);
+      if (!finite(angle)) continue;  /* only NaN if dD = dR = 0 */
+      if (angle < 0) angle += M_PI;
+      bin = angle*DEG_RAD*Ndegbin;
+      A[bin] ++;
+      N ++;
+    }
+  }
+  /* points west */
+  for (j = i - 1; (j >= 0) && ((dX = Xo - stars[j].X) < RADIUS); j--) {
+    if (mark[j]) continue;
+    dY = stars[j].Y - Yo;
+    if (fabs(dY) < RADIUS) {
+      angle = atan2 (dY,dX);
+      if (!finite(angle)) continue;
+      if (angle < 0) angle += M_PI;
+      bin = angle*DEG_RAD*Ndegbin;
+      A[bin] ++;	
+      N ++;
+    }
+  }
+  if (N < 5) {
+    free (A);
+    return (FALSE);
+  }
+  limit = MAX (5, NSIGMA*sqrt((double)(N)/(double)(NBINS)));
+  for (j = 0; j < NBINS; j++) {
+    if (A[j] > limit) {
+      *ANGLE = j / (DEG_RAD*Ndegbin);
+      fprintf (stderr, "group: %f (%f %f)\n", *ANGLE, Xo, Yo);
+      free (A);
+      return (TRUE);
+    }
+  }
+  free (A);
+  return (FALSE);
+}
+  
Index: /tags/start/Ohana/src/imclean/src/find_line.c
===================================================================
--- /tags/start/Ohana/src/imclean/src/find_line.c	(revision 12606)
+++ /tags/start/Ohana/src/imclean/src/find_line.c	(revision 12606)
@@ -0,0 +1,164 @@
+# include "imclean.h"
+
+int find_line (Stars *stars, char *mark, int Npts, int i, double *M, double *B, double Angle) {
+  
+  int j, N;
+  double X, Y, X2, Y2, XY, m, b, det;
+  double dX, dY, Xo, Yo, angle;
+  char Flipped;
+  
+  Xo = stars[i].X;
+  Yo = stars[i].Y;
+  X = Xo;
+  Y = Yo;
+  X2 = Xo*Xo;
+  Y2 = Yo*Yo;
+  XY = Xo*Yo;
+  N = 1;
+  /* points to the right */
+  for (j = i + 1; (j < Npts) && ((dX = stars[j].X - Xo) < RADIUS); j++) {
+    if (mark[j]) continue;
+    dY = stars[j].Y - Yo;
+    if (fabs(dY) < RADIUS) {
+      angle = atan2 (dY,dX);
+      if (!finite(angle)) continue;
+      if (angle < 0) angle += M_PI;
+      if (fabs(angle - Angle) < 2*RAD_DEG) {
+	X += stars[j].X;
+	Y += stars[j].Y;
+	X2 += stars[j].X*stars[j].X;
+	Y2 += stars[j].Y*stars[j].Y;
+	N ++;
+	XY += stars[j].X*stars[j].Y;
+      }
+    }
+  }
+  /* points to the left */
+  for (j = i - 1; (j >= 0) && ((dX = Xo - stars[j].X) < RADIUS); j--) {
+    if (mark[j]) continue;
+    dY = stars[j].Y - Yo;
+    if (fabs(dY) < RADIUS) {
+      angle = atan2 (dY,dX);
+      if (!finite(angle)) continue;
+      if (angle < 0) angle += M_PI;
+      if (fabs(angle - Angle) < 2*RAD_DEG) {
+	X += stars[j].X;
+	Y += stars[j].Y;
+	X2 += stars[j].X*stars[j].X;
+	Y2 += stars[j].Y*stars[j].Y;
+	N ++;
+	XY += stars[j].X*stars[j].Y;
+      }
+    }
+  }
+  /* determine coeffs */
+  Flipped = 0;
+  det = 1.0 / (X2*N - X*X);
+  m = det * (XY*N - X*Y);
+  b = det * (X2*Y - XY*X);
+  if (fabs(m) > 1.1) { /* use a line of R = m*D + b instead */
+    /* fprintf (stderr, "high slope object: %f %f  -> ", m, b); */
+    det = 1.0 / (Y2*N - Y*Y);
+    m = det * (XY*N - X*Y);
+    b = det * (Y2*X - XY*Y);
+    Flipped = 1;
+    /* fprintf (stderr, "%f %f\n", m, b); */
+  }
+
+  *M = m;
+  *B = b;
+  return (Flipped);
+
+}
+
+
+void find_better_line (Stars *stars, char *mark, int Npts, int i, double *M, double *B, int axis) {
+  
+  int j, N;
+  double X, Y, X2, Y2, XY, m, b, det, dist;
+  double delta, *path;
+  int NLINE, *line;
+
+  NLINE = 50;
+  ALLOCATE (line, int, NLINE);
+  ALLOCATE (path, double, NLINE);
+  
+  /* fit a line to points near line */
+  X = Y = X2 = Y2 = XY = N = 0;
+  m = *M;  b = *B;
+  for (j = 0; (j < Npts); j++) {
+    if (axis == 1) 
+      delta = stars[j].X - m*stars[j].Y - b;
+    else
+      delta = stars[j].Y - m*stars[j].X - b;
+    if (fabs(delta) < 2*TRAIL_WIDTH) {
+      X += stars[j].X;
+      Y += stars[j].Y;
+      X2 += stars[j].X*stars[j].X;
+      Y2 += stars[j].Y*stars[j].Y;
+      XY += stars[j].X*stars[j].Y;
+      line[N] = j;
+      path[N] = hypot (stars[j].X - stars[line[0]].X, stars[j].Y - stars[line[0]].Y);
+      N ++;
+      if (N == NLINE - 1) {
+	NLINE += 50;
+	REALLOCATE (line, int, NLINE);
+	REALLOCATE (path, double, NLINE);
+      }
+    }
+  }
+
+  if (N < NPTSINLINE) {
+    free (line);
+    return;
+  }
+
+  for (i = 0; i < N - NPTSINLINE + 1; i++) {
+    j = i + NPTSINLINE - 1;
+    dist = fabs (path[j] - path[i]);
+    if ((j - i) / dist < MIN_DENSITY) continue;
+    for (; (j < N) && (((j - i) / dist) > MIN_DENSITY); j++) {
+      dist = fabs (path[j] - path[i]);
+    }
+    if ((j == N) && (((j - i) / dist) > MIN_DENSITY)) j++;
+    j--;
+    for (; i < j; i++) {
+      mark[line[i]] = TRUE;
+      stars[line[i]].dophot = 0;
+    }
+    i--;
+  }
+  free (line);
+  free (path);
+
+  /* determine coeffs */
+  if (axis == 0) {
+    det = 1.0 / (X2*N - X*X);
+    m = det * (XY*N - X*Y);
+    b = det * (X2*Y - XY*X);
+  } else {
+    det = 1.0 / (Y2*N - Y*Y);
+    m = det * (XY*N - X*Y);
+    b = det * (Y2*X - XY*Y);
+  }
+
+  fprintf (stderr, "%f %f %d\n", m, b, N);
+
+  *M = m;
+  *B = b;
+
+}
+
+void fix_total (Stars *stars, int Nstars, Header *header) {
+  
+  int Ngood, i;
+
+  Ngood = 0;
+  for (i = 0; i < Nstars; i++) {
+    if (stars[i].dophot != 0) Ngood ++;
+  }
+
+  fits_modify (header, "NSTARS", "%d", 1, Ngood);
+  
+}
+  
Index: /tags/start/Ohana/src/imclean/src/find_trails.c
===================================================================
--- /tags/start/Ohana/src/imclean/src/find_trails.c	(revision 12606)
+++ /tags/start/Ohana/src/imclean/src/find_trails.c	(revision 12606)
@@ -0,0 +1,23 @@
+# include "imclean.h"
+
+void find_trails (Stars *stars, int Nstars) {
+
+  int i;
+  char *mark;
+  double Angle, axis, m, b;
+  
+  ALLOCATE (mark, char, Nstars);
+  bzero (mark, Nstars);
+  
+  for (i = 0; i < Nstars; i++) {
+    /* already marked, ignore */
+    if (mark[i]) continue;
+    if (find_group (stars, mark, Nstars, i, &Angle)) {
+      /* this point has an excess nearby concentration, find the line */
+      axis = find_line (stars, mark, Nstars, i, &m, &b, Angle);
+      find_better_line (stars, mark, Nstars, i, &m, &b, axis);
+      /* mark_trail (stars, mark, Nstars, i, m, b, axis); */
+    }
+  }
+}
+
Index: /tags/start/Ohana/src/imclean/src/imclean.c
===================================================================
--- /tags/start/Ohana/src/imclean/src/imclean.c	(revision 12606)
+++ /tags/start/Ohana/src/imclean/src/imclean.c	(revision 12606)
@@ -0,0 +1,71 @@
+# include "imclean.h"
+
+int main (int argc, char **argv) {
+
+  Header header;
+  Stars *stars;
+  int Nstars;
+
+  ConfigInit (&argc, argv);
+
+  args (argc, argv);
+
+  /* load in FITS header from image */
+  if (!fits_read_header (argv[1], &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s\n", argv[1]);
+    exit (1);
+  }
+
+  AdjustHeader (&header);
+  
+  switch (MODE) {
+  case DOPHOT:
+    stars = LoadStarsDophot (argv[2], &Nstars, &header);
+    break;
+  case CHAD:
+    stars = LoadStarsChad (argv[2], &Nstars, &header);
+    break;
+  case SEXTRACT:
+    stars = LoadStarsSex (argv[2], &Nstars, &header);
+    break;
+  default: 
+    fprintf (stderr, "unknown mode: %d\n", MODE);
+    exit (1);
+  }
+
+  sort_stars (stars, Nstars);
+  find_trails (stars, Nstars);  
+  fix_total (stars, Nstars, &header);
+
+  wstars (argv[3], stars, Nstars, &header); 
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+
+}
+
+/* based on fstat and markstar:
+
+   0) load config data, global parameters 
+   1) load header
+   2) load data from *.obj file
+   3) eliminate bad star types: 6, 8
+   4) identify trails
+   5) get statistics on remaining stars
+
+*/
+
+/* 
+imclean (file.fits) (file.obj) (file.cmp) 
+
+ [-p photcode]
+ [-chad]
+ [-sex]
+ [-coords RA DEC] 
+ [-astrom file]
+ [-v]
+ [-key name %f value]
+ [-key name %s value]
+ (maximum of 64 keywords can be changed)
+
+*/
Index: /tags/start/Ohana/src/imclean/src/sort_stars.c
===================================================================
--- /tags/start/Ohana/src/imclean/src/sort_stars.c	(revision 12606)
+++ /tags/start/Ohana/src/imclean/src/sort_stars.c	(revision 12606)
@@ -0,0 +1,36 @@
+# include "imclean.h"
+
+void sort_stars (Stars *X, int N) {
+
+  int l,j,ir,i;
+  Stars tX;
+  
+  if (N < 1) return;
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j].X < X[j+1].X) j++;
+      if (tX.X < X[j].X) {
+	X[i] = X[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+  }
+}
Index: /tags/start/Ohana/src/imclean/src/star_stats.c
===================================================================
--- /tags/start/Ohana/src/imclean/src/star_stats.c	(revision 12606)
+++ /tags/start/Ohana/src/imclean/src/star_stats.c	(revision 12606)
@@ -0,0 +1,76 @@
+# include "imclean.h"
+
+star_stats (Header *header, Stars *stars, int Nstars) {
+
+  int i;
+  
+  /* zero things that will sum */
+  N = A = A2 = S2 = 0;
+  gotFWHM = FALSE;
+
+  for (i = 0; i < HIST_BINS; i++) { Mhist[i] = Shist[i] = 0; }
+  for (i = 1; i <= 9; i++) { n[i] = 0; }
+
+  for (i = 0; i < Nstars; i++) {
+    n[type] ++;
+    switch (type) {
+    case 6:  /* just throw these ones out */
+    case 8:
+    case 9:
+      break;
+    case 1:
+      sscanf (&buffer[i*CHAR_LINE + AP_FIELD], "%lf", &ap);
+      if (ap < 99) {
+	apmifit = ap - m;
+	A += apmifit / SQ(df);
+	A2 += SQ(apmifit) / SQ(df);
+	S2 += 1.0 / SQ(df);
+      } 
+      if (!gotFWHM) {
+	sscanf (&buffer[i*CHAR_LINE + PSF_FIELD], "%lf %lf %lf ", &FWHMx, &FWHMy, &angle);
+	gotFWHM = TRUE;
+      }
+    case 4:
+    case 7:
+      bin = MAX (0.0, MIN (HIST_BINS, 10.0 * (m + 15.0)));  /* stick in 0.1 mag bins */
+      Mhist[bin] ++;
+    case 2:
+    case 3:
+    case 5:
+      fprintf (g, "%6.1f %6.1f %6.3f %03d %1d %3.1f\n", x, y, m+ZERO_POINT, (int)(1000*df), type, lsky);
+      N ++; 
+    }
+  }
+
+  Ap = A / S2;
+  Ap2 = sqrt(A2 / (S2) - Ap*Ap);
+  sum = 0.0;
+  for (i = 0; i < HIST_BINS; i++) {
+    sum += Mhist[i];
+    Shist[i] = sum;
+  }
+  satfound = done = FALSE;
+  for (i = 0; (i < HIST_BINS) && !done; i++) {
+    if ((!satfound) && (Mhist[i] > 0)) {
+      saturate = 0.1*(i-1) - 15.0;
+      satfound = TRUE;
+    }
+    if (Shist[i] > 0.9*Shist[HIST_BINS - 1]) {
+      complete = 0.1*i - 15.0;
+      done = TRUE;
+    }
+  }
+  
+  fits_modify (&header, "ZERO_PT", "%lf", 1, ZERO_POINT);
+  fits_modify (&header, "FWHM_X", "%lf", 1, FWHMx);
+  fits_modify (&header, "FWHM_Y", "%lf", 1, FWHMy);
+  fits_modify (&header, "ANGLE", "%lf", 1, angle);
+  fits_modify (&header, "APMIFIT", "%lf", 1, Ap);
+  fits_modify (&header, "dAPMIFIT", "%lf", 1, Ap2);
+  fits_modify (&header, "FSATUR", "%lf", 1, (saturate + ZERO_POINT));
+  fits_modify (&header, "FLIMIT", "%lf", 1, (complete + ZERO_POINT));
+  fits_modify (&header, "NSTARS", "%d", 1, N);
+  for (i = 1; i <= 9; i++) {
+    sprintf (line, "TDOPHOT%1d\0", i);
+    fits_modify (&header, line, "%d", 1, n[i]);
+  }
Index: /tags/start/Ohana/src/imclean/src/wstars.c
===================================================================
--- /tags/start/Ohana/src/imclean/src/wstars.c	(revision 12606)
+++ /tags/start/Ohana/src/imclean/src/wstars.c	(revision 12606)
@@ -0,0 +1,43 @@
+# include "imclean.h"
+# define NCHAR 66 /* 65 char EXCLUDING return */
+
+void wstars (char *filename, Stars *stars, int Nstars, Header *header) {
+  
+  int i, Nchar;
+  FILE *g;
+  char line[NCHAR + 3];
+
+  g = fopen (filename, "w");
+  if (g == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't create output file %s\n", filename);
+    exit (1);
+  }
+
+  fwrite (header[0].buffer, 1, header[0].size, g);
+
+  for (i = 0; i < Nstars; i++) {
+    if (stars[i].dophot == 0) continue;
+    Nchar = snprintf (line, NCHAR, "%6.1f %6.1f %6.3f %03d %2d %3.1f %6.3f %6.3f %6.2f %6.2f %5.1f", 
+		      stars[i].X, stars[i].Y, stars[i].M, 
+		      (int)(1000*stars[i].dM), stars[i].dophot, stars[i].sky, 
+		      stars[i].Mgal, stars[i].Map, stars[i].fx, stars[i].fy, stars[i].df);
+    
+    /* this is just a little funny.  NCHAR (in) includes the trailing NULL, Nchar (out) excludes it */
+    if (Nchar != NCHAR - 1) {
+      fprintf (stderr, "funny line %d (%d)\n%s\n", i, Nchar, line);
+    } else {
+      fprintf (g, "%s\n", line);
+    }
+  }
+
+  fclose (g);
+
+}
+
+/*
+
+  63.6 2869.5 17.568 157 17.568 17.568 25.01 25.00 360.0 7 2.9
+
+  63.6 2869.5 17.568 157 7 2.9
+
+*/
Index: /tags/start/Ohana/src/imregister/Makefile
===================================================================
--- /tags/start/Ohana/src/imregister/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/imregister/Makefile	(revision 12606)
@@ -0,0 +1,173 @@
+include ../../Configure
+HOME    =       $(ROOT)/src/imregister
+
+default: all
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+BASEDIR =	$(HOME)/base
+DETREND =	$(HOME)/detrend
+PHOTREG =	$(HOME)/photreg
+IMREG   =	$(HOME)/imreg
+SPREG   =	$(HOME)/spreg
+
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH) -Wunused
+LIBS	= 	-L$(LLIB) -lFITS -lohana -lm 
+# CFLAGS	=	$(INCS) -Wall -Wunused
+CFLAGS	=	$(INCS)
+LFLAGS	=	$(LIBS)
+
+# programs which should be installed
+INSTALL = \
+detregister  detsearch    \
+imregister   imstatreg    \
+imsort       imsearch     \
+showiminfo   convertimreg \
+imregtable   photcode	  \
+photsearch   photreg      \
+cameraconfig filtnames    \
+imphotsearch imphotmerge  \
+imphotset	          
+
+# spregister   spsearch
+
+# program under development, not installed
+DEVEL = 
+
+IMOBJ  = \
+$(IMREG)/db.$(ARCH).o     \
+$(IMREG)/delete.$(ARCH).o \
+$(IMREG)/define.$(ARCH).o \
+$(IMREG)/iminfo.$(ARCH).o \
+$(IMREG)/load_probes.$(ARCH).o  \
+$(IMREG)/match.$(ARCH).o  \
+$(IMREG)/modify.$(ARCH).o \
+$(IMREG)/output.$(ARCH).o \
+$(IMREG)/unique.$(ARCH).o \
+$(IMREG)/cadc.$(ARCH).o   \
+$(IMREG)/mosaics.$(ARCH).o   \
+$(IMREG)/ConfigPID.$(ARCH).o   \
+$(IMREG)/SetSignals.$(ARCH).o   \
+$(IMREG)/imregclient.$(ARCH).o   \
+$(IMREG)/rconnect.$(ARCH).o   \
+$(IMREG)/FifoOps.$(ARCH).o   \
+$(IMREG)/SockScan.$(ARCH).o   \
+$(IMREG)/submit.$(ARCH).o 
+
+SPOBJ  = \
+$(SPREG)/db.$(ARCH).o     \
+$(SPREG)/delete.$(ARCH).o \
+$(SPREG)/define.$(ARCH).o \
+$(SPREG)/spinfo.$(ARCH).o \
+$(SPREG)/match.$(ARCH).o  \
+$(SPREG)/modify.$(ARCH).o \
+$(SPREG)/fits_scan_nchar.$(ARCH).o \
+$(SPREG)/output.$(ARCH).o \
+$(SPREG)/unique.$(ARCH).o \
+$(SPREG)/ConfigInit.$(ARCH).o    \
+$(BASEDIR)/misc.$(ARCH).o        \
+$(BASEDIR)/parse_time.$(ARCH).o  \
+$(BASEDIR)/sort.$(ARCH).o
+
+PHOTOBJ  = \
+$(PHOTREG)/db.$(ARCH).o     \
+$(PHOTREG)/delete.$(ARCH).o \
+$(PHOTREG)/match.$(ARCH).o  \
+$(PHOTREG)/define.$(ARCH).o  \
+$(PHOTREG)/getImageData.$(ARCH).o  \
+$(PHOTREG)/output.$(ARCH).o 
+
+DETOBJ  = \
+$(DETREND)/db.$(ARCH).o        \
+$(DETREND)/define.$(ARCH).o    \
+$(DETREND)/criteria.$(ARCH).o  \
+$(DETREND)/define.$(ARCH).o    \
+$(DETREND)/delete.$(ARCH).o    \
+$(DETREND)/entry.$(ARCH).o     \
+$(DETREND)/image.$(ARCH).o     \
+$(DETREND)/imdef.$(ARCH).o     \
+$(DETREND)/match.$(ARCH).o     \
+$(DETREND)/modify.$(ARCH).o    \
+$(DETREND)/mosaic.$(ARCH).o    \
+$(DETREND)/output.$(ARCH).o    \
+$(DETREND)/recipe.$(ARCH).o    \
+$(DETREND)/select.$(ARCH).o    \
+$(DETREND)/unique.$(ARCH).o    \
+$(DETREND)/altpath.$(ARCH).o   \
+$(DETREND)/usage.$(ARCH).o
+
+BASEOBJ = \
+$(BASEDIR)/ConfigCamera.$(ARCH).o \
+$(BASEDIR)/ConfigFilter.$(ARCH).o \
+$(BASEDIR)/ConfigInit.$(ARCH).o   \
+$(BASEDIR)/WriteFIFO.$(ARCH).o    \
+$(BASEDIR)/get_fwhm.$(ARCH).o     \
+$(BASEDIR)/misc.$(ARCH).o         \
+$(BASEDIR)/parse_time.$(ARCH).o   \
+$(BASEDIR)/sort.$(ARCH).o
+
+all: $(INSTALL) $(DEVEL)
+
+IR = $(IMREG)/args.imregister.$(ARCH).o    $(IMOBJ)  $(BASEOBJ)
+IS = $(IMREG)/args.imsearch.$(ARCH).o      $(IMOBJ)  $(BASEOBJ)
+DR = $(DETREND)/args.detregister.$(ARCH).o $(DETOBJ) $(BASEOBJ)
+DS = $(DETREND)/args.detsearch.$(ARCH).o   $(DETOBJ) $(BASEOBJ)
+PS = $(PHOTREG)/args.photsearch.$(ARCH).o  $(PHOTOBJ) $(BASEOBJ)
+PR = $(PHOTREG)/args.photreg.$(ARCH).o     $(PHOTOBJ) $(BASEOBJ)
+SR = $(SPREG)/args.spregister.$(ARCH).o    $(SPOBJ)  
+SS = $(SPREG)/args.spsearch.$(ARCH).o      $(SPOBJ)  
+
+# special rules:
+$(BIN)/photreg.$(ARCH)      : $(SRC)/photreg.$(ARCH).o      $(PR) ; $(CC) $^ -o $@ $(LFLAGS)
+$(BIN)/photsearch.$(ARCH)   : $(SRC)/photsearch.$(ARCH).o   $(PS) ; $(CC) $^ -o $@ $(LFLAGS)
+$(BIN)/imsearch.$(ARCH)     : $(SRC)/imsearch.$(ARCH).o     $(IS) ; $(CC) $^ -o $@ $(LFLAGS)
+$(BIN)/imregister.$(ARCH)   : $(SRC)/imregister.$(ARCH).o   $(IR) ; $(CC) $^ -o $@ $(LFLAGS)
+$(BIN)/imstatreg.$(ARCH)    : $(SRC)/imstatreg.$(ARCH).o    $(IR) ; $(CC) $^ -o $@ $(LFLAGS)
+$(BIN)/showiminfo.$(ARCH)   : $(SRC)/showiminfo.$(ARCH).o   $(IR) ; $(CC) $^ -o $@ $(LFLAGS)
+$(BIN)/imregtable.$(ARCH)   : $(SRC)/imregtable.$(ARCH).o   $(IR) ; $(CC) $^ -o $@ $(LFLAGS)
+$(BIN)/convertimreg.$(ARCH) : $(SRC)/convertimreg.$(ARCH).o $(IR) ; $(CC) $^ -o $@ $(LFLAGS)
+$(BIN)/detregister.$(ARCH)  : $(SRC)/detregister.$(ARCH).o  $(DR) ; $(CC) $^ -o $@ $(LFLAGS)
+$(BIN)/detsearch.$(ARCH)    : $(SRC)/detsearch.$(ARCH).o    $(DS) ; $(CC) $^ -o $@ $(LFLAGS)
+
+$(BIN)/imsort.$(ARCH)       : $(BIN)/imregister.$(ARCH) ; rm -f $(BIN)/imsort.$(ARCH) ; ln $(BIN)/imregister.$(ARCH) $(BIN)/imsort.$(ARCH) 
+
+$(BIN)/spsearch.$(ARCH)     : $(SRC)/spsearch.$(ARCH).o     $(SS) ; $(CC) $^ -o $@ $(LFLAGS)
+$(BIN)/spregister.$(ARCH)   : $(SRC)/spregister.$(ARCH).o   $(SR) ; $(CC) $^ -o $@ $(LFLAGS)
+
+# dependancy rules for binary code #########################
+.PRECIOUS: %.$(ARCH).o
+.PRECIOUS: $(BIN)/%.$(ARCH)
+
+%.$(ARCH).o : %.c
+	$(CC) $(CFLAGS) -c $^ -o $@
+
+$(BIN)/%.$(ARCH) : $(SRC)/%.$(ARCH).o $(BASEOBJ)
+	$(CC) $^ -o $@ $(LFLAGS)
+
+$(DESTBIN)/%: $(BIN)/%.$(ARCH)
+	rm -f $(DESTBIN)/$*
+	cp $(BIN)/$*.$(ARCH) $(DESTBIN)/$*
+
+$(INSTALL) $(DEVEL): % : $(BIN)/%.$(ARCH)
+
+%.clean :
+	rm -f $(BIN)/$*.$(ARCH)
+
+%.install:
+	make $(DESTBIN)/$*
+
+# utilities #################################################
+
+install:
+	for i in $(INSTALL); do make $$i.install; done
+
+clean:
+	rm -f */*.o
+	rm -f */*~
Index: /tags/start/Ohana/src/imregister/base/convert.c
===================================================================
--- /tags/start/Ohana/src/imregister/base/convert.c	(revision 12606)
+++ /tags/start/Ohana/src/imregister/base/convert.c	(revision 12606)
@@ -0,0 +1,2 @@
+# include "imregister.h"
+
Index: /tags/start/Ohana/src/imregister/doc/Change.log
===================================================================
--- /tags/start/Ohana/src/imregister/doc/Change.log	(revision 12606)
+++ /tags/start/Ohana/src/imregister/doc/Change.log	(revision 12606)
@@ -0,0 +1,8 @@
+
+imregister-3.0 represents a completely new organization of these
+programs, with the twin goals of making the FITS table handling more
+cleanly encapsulated and of easing the addition of a mysql database
+engine in place of the FITS tables.  As programs from imregister-1.0
+are adapted to match this structure, they will be moved into the
+imregister-3.0 directory.  
+
Index: /tags/start/Ohana/src/imregister/doc/Compatibility
===================================================================
--- /tags/start/Ohana/src/imregister/doc/Compatibility	(revision 12606)
+++ /tags/start/Ohana/src/imregister/doc/Compatibility	(revision 12606)
@@ -0,0 +1,58 @@
+
+transearch-1.0: 
+  v1: ok
+  v2: ok
+
+transearch-2.0: 
+  v1: not compatible, exits gracefully
+  v2: ok
+
+transreg-1.0:
+  v1: ok
+  v2: not compatible, exits gracefully
+
+transreg-1.0:
+  v1: not compatible, exits gracefully
+  v2: ok
+
+photsearch-1.0:
+  v1: ok
+  v2: ok
+
+photsearch-2.0:
+  v1: not compatible, exits gracefully
+  v2: ok
+
+photreg-1.0:
+  v1: ok
+  v2: ok [creates v1]
+
+photreg-2.0:
+  v1: not compatible, exits gracefully
+  v2: ok
+
+imsearch-1.0:
+  v1, v2: ok
+  v3: not compatible, exits gracefully
+
+imregister-1.0:
+  v1, v2: ok
+  v3: not compatible ****
+
+imregister-2.0:
+  v1, v2: ok
+  v3: not compatible, exits gracefully
+
+imsort-1.0:
+  v1, v2: ok
+  v3: not compatible ****
+
+imsort-2.0:
+  v1, v2: ok
+  v3: not compatible ***
+
+imregtable-3.0:
+  v1, v2: not compatibe, exits gracefully
+  v3: ok
+
+
Index: /tags/start/Ohana/src/imregister/doc/dbtools.txt
===================================================================
--- /tags/start/Ohana/src/imregister/doc/dbtools.txt	(revision 12606)
+++ /tags/start/Ohana/src/imregister/doc/dbtools.txt	(revision 12606)
@@ -0,0 +1,41 @@
+
+Elixir uses several databases to store a variety of information.
+One of these databases is the photometry database, with several
+interface tools (status, nrphot, addstar, etc).  The other databases
+are manipulated with the tools found in this directory.  In addition,
+tools used to abstract the camera description, photcodes, and filters
+are included here.
+
+imregister   : add images to the image registration database (imreg.db)
+
+imsearch     : find images in imreg.db
+
+imsort       : add images to imreg.db and pass to elixir systems
+
+imstatreg    : update stats to imreg.db (fwhm, flux, bias)
+
+detregister  : add images to the detrend database
+
+detsearch    : find images in the detrend database
+
+photreg      : add photometry datapoints to zeropoint db (phot.db)
+
+photsearch   : search phot.db
+
+transreg     : add transparency points to database (trans.db)
+
+transsearch  : search trans.db
+
+photcode     : find photcode for given image
+
+filtnames    : filter name lookups
+
+cameraconfig : get configuration information for camera
+
+As in all Elixir programs, a reference to a specific CCD in a MEF
+image can be done with (file) (ccd) MEF, where the value of 'ccd' is
+one of the valid extension names, associated in the header with the
+keyword defined by CCDNUM-KEYWORD.  In addition, searches (imsearch,
+detsearch) may be restricted to specific ccds with the -ccd flag,
+which also takes the extension name ID.
+
Index: /tags/start/Ohana/src/imregister/doc/det.txt
===================================================================
--- /tags/start/Ohana/src/imregister/doc/det.txt	(revision 12606)
+++ /tags/start/Ohana/src/imregister/doc/det.txt	(revision 12606)
@@ -0,0 +1,46 @@
+
+detregister:
+-time")) {
+-label")) {
+-ID")) {
+-order")) {
+-type")) {
+-ccd")) {
+-exptime")) {
+-filter")) {
+
+detsearch:
+--help		: ok
+-ccd		: ok
+-close		: ok
+-exptime	: ok
+-filter		: ok
+-h		: ok
+-image		: ok
+-label		: ok
+-mosaic		: ok
+-recipe		: ok
+-select		: ok
+-time		: ok
+-trange		: ok
+-treg		: ok
+-tstop		: ok
+-type		: ok
+-ve		: ok
+-quiet		: ok
+
+-match		: ?
+-entry		: ok
+
+-fits		: ok
+-binfits	: ok
+-del		: ok
+-delete		: ok
+-modify		: ok
+
+--help : clean up usage statement
+
+option behavior: 
+
+-close implies -time or -trange
+-select returns best for all detrend base selection
Index: /tags/start/Ohana/src/imregister/doc/detsearch.txt
===================================================================
--- /tags/start/Ohana/src/imregister/doc/detsearch.txt	(revision 12606)
+++ /tags/start/Ohana/src/imregister/doc/detsearch.txt	(revision 12606)
@@ -0,0 +1,74 @@
+
+detregister / detsearch MEF support:
+
+issue of database image format:
+
+filename			type	CCD  mode
+modes/2001A.modes.R.12.00.fits  modes   12   modes
+flat/R/02Bk06.flat.R.00.00.fits flat    00   split
+flat/R/03Ak01.flat.R.00.fits    flat    12   mef
+
+detsearch / detregister concepts:
+
+selection rules:
+
+ match all simple filters 
+
+ -image foo.fits[ccd 08] matches (split 08) or (mef NCCD)
+ 
+ if CCD is defined, return foo.fits[ext] if foo.fits is MEF
+
+simple filters:
+
+ -ccd (N)                       : match ccd
+ -time yyyy/mm/dd,HH:MM:SS      : match time
+ -trange (start) (stop)         : match time range
+ -entry (value)                 : match entry (entry == version number)
+ -label (word)                  : match this label
+ -filter (name)                 : match filter
+ -exptime (value)               : match exposure time
+
+complex rules:
+ -image (filename) (ccd) (mode) : determine filters from image
+
+ -mosaic (filename)		: determine filters from image
+
+ -recipe			: determine filters from image
+
+ -type (type)                   : match type, limit valid filters
+
+ -match (value)                 : only list the Nth matched entry ???
+
+ -close                         : allow non-perfect matches
+
+ -select                        : select 'best' match
+
+display rules:
+ -tstop                         : display end of valid time range
+ -treg                          : display time of image registration
+ -ve                            : Elixir verbose (SUCCESS / ERROR) 
+ -quiet                         : Elixir quiet (no SUCCESS / ERROR) 
+
+
+behaviour rules:
+ -modify (entry) (value)        : change entry for matched images to value
+  [possible -modify entries: label, order, tstart, tstop]
+
+ -del    : delete the matched entries
+ -delete : delete the matched entries
+
+
+-image sets:  -filter, -ccd, -time, -exptime
+-mosaic sets: -filter, -time, -exptime, (-ccds?)
+-recipe sets -type, for each type, sets -
+
+possible values for -type:  mask, bias, dark, flat, fringe, scatter, modes
+
+valid filters for type selections:
+  mask:    -ccd, -label, -entry, -time || -trange
+  bias:    -ccd, -label, -entry, -time || -trange
+  dark:    -ccd, -label, -entry, -time || -trange, -exptime
+  flat:    -ccd, -label, -entry, -time || -trange, -filter
+  fringe:  -ccd, -label, -entry, -time || -trange, -filter
+  scatter: -ccd, -label, -entry, -time || -trange, -filter
+  modes:   -ccd, -label, -entry, -time || -trange, -filter
Index: /tags/start/Ohana/src/imregister/doc/imreg.txt
===================================================================
--- /tags/start/Ohana/src/imregister/doc/imreg.txt	(revision 12606)
+++ /tags/start/Ohana/src/imregister/doc/imreg.txt	(revision 12606)
@@ -0,0 +1,25 @@
+
+command-line options from imregister:
+-split	     - OK
+-noreg	     - OK
+
+command-line options from imsearch:
+-type	     - ok
+-etime	     - ok
+-mode	     - ok
+-ccd	     - ok
+-filter	     - ok
+-name	     - ok
+
+-treg	     -ok
+-seq	     -ok
+-pt	     -ok
+-table	     -ok
+-bintable    -ok
+-del	     -ok
+-delete	     -ok
+-newpath     -ok
+-mef2split   -ok 
+-split2mef   -ok
+
+
Index: /tags/start/Ohana/src/imregister/doc/imregister.txt
===================================================================
--- /tags/start/Ohana/src/imregister/doc/imregister.txt	(revision 12606)
+++ /tags/start/Ohana/src/imregister/doc/imregister.txt	(revision 12606)
@@ -0,0 +1,63 @@
+
+This directory contains several routines which are related to
+maintaining a small, elixir-internal databases about the images which
+have been obtained.
+
+This database can be used to find the location on disk of the images
+which we have analysed, or to display various statistics about images,
+or to find types of images which have been obtained.  
+
+The basic program is 'imregister', which places the basic information
+about an image in the database, as determined from the header.  The
+program is invoked with: {\tt imregister (filename) [-split]}.  The
+optional flag is used to tell the program to distinguish the
+individual (SPLIT) frames of a mosaic CCD from an individual CCD which
+should be treated as an isolated image.  
+
+The second program is 'imsort', which does the same task as
+'imregister', but it also sends a trigger to the IMSTAT elixir and if
+needed to the PTOLEMY elixir.  For this program, the -split flag makes
+a difference in how these images are treated in the elixir processes.
+The basic point is that a SINGLE image /fullpath/filename.fits
+produces analysis files of the form /newpath/filename.ext while a
+SPLIT image will have the form /fullpath/word/wordNN.fits and output
+files of the form /newpath/word/wordNN.ext.  
+
+May 11, 2000
+
+I have been working to clean up some of the details of the Elixir
+system.  There are three big issues I have been attempting to address.
+First, I have wanted to create a single set of Elixirs for both MEF
+and SPLIT (and even SINGLE) images.  I also want to minimize the
+number of programs are required to know something special about our
+system, our camera, or our method of naming files.  Finally, I have
+been trying to automate the selection of the appropriate detrend data.
+These are connected problems, in many ways.
+
+Here, in order, are the programs (and scripts) needed to run the
+Elixir system for which these issues are relevant:
+
+elixir.fork:  this program is launched by the camera to introduce a
+	      new image to the system.  It must understand the
+	      difference between SPLIT and MEF, and also the naming
+	      convention.
+
+imsort:	      this program adds the image to the database and passes a
+	      trigger to the elixirs ptolemy and imstats.  imsort
+	      needs to distinguish SPLIT, MEF, and SINGLE images, and
+	      it must know the naming convention.  
+
+elixir (ptolemy): this script is now independent of the mode and
+		  naming issues
+
+elixir (imstats): this script is now independent of the mode and
+		  naming issues
+
+flatten:	  this script needs to distinguish SPLIT and MEF
+		  images (it is told the mode by the input line), but
+		  it does not know the naming convention.
+
+imstats:	  this script needs to distinguish SPLIT and MEF
+		  images (it is told the mode by the input line), but
+		  it does not know the naming convention.
+
Index: /tags/start/Ohana/src/imregister/doc/imtable.txt
===================================================================
--- /tags/start/Ohana/src/imregister/doc/imtable.txt	(revision 12606)
+++ /tags/start/Ohana/src/imregister/doc/imtable.txt	(revision 12606)
@@ -0,0 +1,22 @@
+
+Image Table: run @ 6 AM in ert
+
+- for given time period:
+
+* are all images in database? (compare archive db & elixir db)
+* have all images passed imstats?
+
+- complete images should be extracted into a table, sent to CADC
+- missing images should be registered or a warning sent on failure
+  (relink on /data/kapu/elixir/cfh12k)
+
+- nostat images should be sent to imstats
+  (launch imstats to process)
+ 
+* imsearch output format CADC: 
+
+  fits_define_table_column (&theader, "A64",   "FILE",       "filename in db",        "",                              1.0, 0.0);
+  fits_define_table_column (&theader, "F7.1",  "SKY",        "background level",     "counts / pixel",                 1.0, 0.0); 
+  fits_define_table_column (&theader, "F6.1",  "BIAS",       "bias level",           "counts / pixel",                 1.0, 0.0); 
+  fits_define_table_column (&theader, "F5.2",  "FWHM",       "image quality",        "pixels",                         1.0, 0.0); 
+
Index: /tags/start/Ohana/src/imregister/doc/notes.2.txt
===================================================================
--- /tags/start/Ohana/src/imregister/doc/notes.2.txt	(revision 12606)
+++ /tags/start/Ohana/src/imregister/doc/notes.2.txt	(revision 12606)
@@ -0,0 +1,63 @@
+
+problem:  imstatreg is too slow because of network I/O
+
+option 1: add mysql db to imstats system
+
+option 2: create client / server pair for imregister / imstatreg
+
+option 3: create buffer file for network I/O, local daemon for update
+
+1: best soln but will take a while
+2: ok option, but significant programming effort (worse than 1)
+3: easy programming, acceptable
+
+for imstatreg update, we need the only following data:
+
+obstime (unsigned int)
+ccd     (char or int)
+fwhm
+bias
+sky
+ra
+dec
+
+imstatreg -client:
+
+ read image info
+ load temp db
+ append data
+ close
+
+imstatreg -daemon:
+
+ load temp db
+ load main db
+ match images
+ update db
+ close db
+ empty temp db
+
+------------------------------------------------------
+
+detsearch needs optional alternative detrend.db paths
+
+- add column ALTPATH : true / false
+- add option -altpath :
+  - select images
+  - select ALTPATH images
+  - find subset 'add'
+  - find subset 'remove'
+  - 'remove': unlink files & unset ALTPATH
+  - 'add'   : copy files & set ALTPATH
+  
+
+if (ADD)    : all images in match are 'add', no images are 'delete'
+if (DELETE) : all images in match are 'delete', no images are 'add'
+if (UPDATE) : ??
+
+-----------------------------------------------------
+
+photreg / photsearch 
+
+- need to define the target photometry system in the output table.
+
Index: /tags/start/Ohana/src/imregister/doc/notes.old.txt
===================================================================
--- /tags/start/Ohana/src/imregister/doc/notes.old.txt	(revision 12606)
+++ /tags/start/Ohana/src/imregister/doc/notes.old.txt	(revision 12606)
@@ -0,0 +1,12 @@
+
+there are some issues with the imregister database that should get
+addressed eventually.  currently, I am loading and saving the entire
+file each time I make a change.  this seems like a bad plan.  when we
+get a few hundred nights of images in there, we will have several
+megabytes to load, change, and save each time.  two things could
+change.  first, imregister (imsort) could only add a record at the end
+of the file.  second, the imstatreg function could find the right
+image and write over the few needed bytes.
+
+should I uses mmap to do the I/O?
+
Index: /tags/start/Ohana/src/imregister/doc/notes.txt
===================================================================
--- /tags/start/Ohana/src/imregister/doc/notes.txt	(revision 12606)
+++ /tags/start/Ohana/src/imregister/doc/notes.txt	(revision 12606)
@@ -0,0 +1,101 @@
+
+imsearch & CADC distribution:
+
+i need to create raw image tables for the CADC for only those images
+which have been processed (-proc t) and for which a distribution table
+has not been created.
+
+imsearch -modify help
+imsearch -modify path /oldpath /newpath
+imsearch -modify mode [mef/split] 
+imsearch -modify dist [t/f]
+
+history:
+
+v1 : < 2002.09 
+
+ - FITS table interface had errors, incorrect TFORM values
+ - imreg db used pseudo FITS table
+
+v2 : 2002.09 
+
+ - FITS table interface repaired
+ - imreg db uses pseudo FITS table
+ - unwieldy files which contain many functions (esp detsearch /
+   imsearch)
+
+v3 : 2002.11
+
+ - FITS table interface repaired
+ - imreg db converted to read FITS tables
+ - use of vtable interface introduced
+ - db interactions abstracted to allow for SQL
+ - reorganization of files
+
+v3: functions & dependancies
+
+function             : external : globals               : structs
+
+WriteFIFO            : ohana    :		        :
+LoadCameraConfig     : ohana    : ccd data, keywords	:
+MatchCCDName         : ohana    : ccd data, keywords	:
+ConfigCamera         : ohana    : ccd data, keywords	:
+LoadFilterList       : ohana    : filt data, keywords	:
+MatchFilterList      : ohana    : filt data             :
+ConfigInit           : ohana    : keywords  
+get_fwhm	     : ohana
+load_probes	     : ohana
+parse_time	     : ohana    : keywords
+get_trange_arguments : ohana
+make_backup	     : ohana
+uppercase	     : 
+check_unixtime	     : UNUSED
+sort (various)	     : 
+
+(why aren't these in libohana?)
+dms_to_ddd
+str_to_radec
+chk_time
+str_to_time
+str_to_dtime
+sec_to_jd
+jd_to_sec
+date_to_sec
+Fseek - allow for timeout...
+
+problems:
+
+ imregister2.c: args
+ imsort2.c: args, SubmitImages
+ imstatreg2.c: args
+ photcode.c: ConfigSystem (ConfigCamera ConfigFilters)
+ photreg2.c: make_backup
+ photsearch2.c: DumpFitsTable
+ showiminfo.c: args
+ transearch2: LoadFilters, DumpFitsTable
+ transreg2: make_backup
+
+main programs:
+
+cameraconfig
+convertimreg
+filtnames
+imphotsearch
+imregister2
+imsearch2
+imsort2
+imstatreg2
+photcode
+photreg2
+photsearch2
+showiminfo
+transearch
+transreg
+
+
+dependency types:
+
+external libraries
+local library
+group 
+program-specific functions
Index: /tags/start/Ohana/src/imregister/doc/photdb.dat
===================================================================
--- /tags/start/Ohana/src/imregister/doc/photdb.dat	(revision 12606)
+++ /tags/start/Ohana/src/imregister/doc/photdb.dat	(revision 12606)
@@ -0,0 +1,349 @@
+u 2003/02/10,13:00:46  25.3434 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/10,13:27:24  25.3435 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/10,13:33:10  25.3496 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/10,13:38:47  25.3583 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/10,13:56:21  25.3455 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/24,12:36:34  25.2875 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/24,12:37:43  25.2855 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/09,13:01:29  25.3035 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/09,13:05:05  25.3034 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/09,13:06:14  25.3004 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/24,12:39:01  25.3197 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+g 2003/02/23,10:10:59  26.4664 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/02/23,10:11:59  26.4654 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/02/23,10:13:00  26.4604 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/02/24,12:00:51  26.4463 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/02/24,12:01:43  26.4393 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/02/24,12:02:35  26.4343 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/02/09,12:47:05  26.4692 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/02/09,12:47:48  26.4642 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/02/09,12:48:40  26.4624 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/02/23,10:17:28  25.9736 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/23,10:20:12  25.9708 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/23,10:20:55  25.9648 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/08,13:30:08  25.9878 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/08,13:30:51  25.9862 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/08,13:31:43  25.9816 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/24,12:07:20  25.9939 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/24,12:10:39  25.9897 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/24,12:09:47  25.9722 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/09,12:26:03  25.9581 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/09,12:26:55  25.9529 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/09,12:27:38  25.9617 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/12,15:18:51  26.0073 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/02/23,10:25:32  25.7384 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/23,10:28:07  25.7415 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/23,10:28:59  25.7465 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/08,13:18:37  25.7317 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/08,13:19:29  25.7307 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/08,13:20:12  25.7289 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/24,12:15:24  25.7579 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/24,12:18:51  25.7489 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/09,13:22:04  25.7434 25.7430  0.0000    3   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/09,13:23:39  25.7397 25.7430  0.0000    3   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/24,12:18:00  25.7399 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/09,13:22:56  25.7318 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/02/23,10:33:44  24.7826 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/02/23,10:36:54  24.7967 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/02/24,12:26:47  24.7562 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/02/09,13:12:43  24.7879 24.8000  0.0000    3   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/02/09,13:13:26  24.7888 24.8000  0.0000    3   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/02/24,12:23:19  24.7178 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/02/24,12:25:46  24.7117 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/02/09,13:11:51  24.7789 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+g 2003/03/24,15:07:46  26.4566 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/03/30,13:12:34  26.4501 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+i 2003/03/25,15:12:48  25.7633 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+r 2003/03/24,15:10:56  25.9917 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/03/25,15:21:27  26.0231 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+u 2003/03/22,15:11:13  25.4630 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/03/23,15:12:14  25.3056 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+z 2003/03/24,14:59:16  24.8271 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/03/30,13:20:55  24.7152 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+g 2003/04/25,09:06:28  26.4030 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/04/26,12:38:26  25.9774 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/26,13:14:35  25.9455 25.9780  0.0046    6   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/25,08:55:23  25.9287 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/27,08:44:44  25.9646 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/26,10:44:32  25.9647 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/26,13:05:05  26.0053 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/27,08:47:28  25.9676 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/26,13:06:05  25.9697 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/27,09:57:10  25.7930 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/04/25,08:58:07  25.7034 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/04/25,09:00:43  24.7533 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+u 2003/06/09,14:36:14  25.2311 25.2800  0.0071    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/05/30,14:21:41  25.2892 25.2800  0.0150    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+r 2003/06/08,14:43:35  25.9302 25.9780  0.0000    3   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/06/02,07:20:29  25.7291 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/04,06:40:27  25.7566 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/05,06:21:27  25.5921 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/06,05:58:59  25.7441 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/08,14:48:20  25.6812 25.7430  0.0000    3   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/06/02,07:23:22  24.8465 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/09,14:42:25  24.7583 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+u 2003/06/24,14:36:40  25.2756 25.2800  0.0361    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/06/29,14:36:40  25.2756 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/07/01,13:04:48  25.2674 25.2800  0.0365    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/07/05,14:51:04  25.2739 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/06/27,14:43:26  25.2580 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/06/30,14:44:00  25.1926 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+g 2003/06/23,10:19:29  26.4170 26.4600  0.0112    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/24,10:28:33  26.4245 26.4600  0.0086    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/26,11:56:32  26.4183 26.4600  0.0130    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/27,10:17:02  26.4285 26.4600  0.0113    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/29,09:53:25  26.4350 26.4600  0.0274    6   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/28,12:25:29  26.4477 26.4600  0.0251    6   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/01,09:52:16  26.4206 26.4600  0.0130    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/04,10:25:06  26.4018 26.4600  0.0143    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/05,10:25:14  26.4114 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/22,14:27:01  26.4249 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/29,14:33:38  26.4104 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/01,13:01:55  26.4169 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/24,14:39:24  26.4019 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/30,14:40:59  26.3187 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/06/22,12:56:00  25.9895 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/23,10:13:35  25.9652 25.9780  0.0047    6   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/24,10:19:55  25.9644 25.9780  0.0033    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/26,12:02:09  25.9610 25.9780  0.0073    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/27,10:19:46  25.9708 25.9780  0.0008    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/29,09:56:18  25.9528 25.9780  0.0089    6   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/28,12:28:22  25.9663 25.9780  0.0058    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/01,09:55:00  25.9672 25.9780  0.0073    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/04,10:29:42  25.9544 25.9780  0.0103    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/05,10:16:36  25.9552 25.9780  0.0067    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/05,14:48:46  25.9320 25.9780  0.0000    3   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/22,14:29:45  25.9493 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/24,14:42:17  25.9354 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/27,14:49:29  25.9371 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/29,14:45:27  25.9172 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/30,14:52:30  25.9221 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/01,13:07:49  25.9294 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/07,07:42:14  25.8036 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/06/22,12:58:53  25.7312 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/24,10:25:49  25.7261 25.7430  0.0095    4   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/26,11:59:16  25.7120 25.7430  0.0099    4   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/27,10:22:39  25.7250 25.7430  0.0103    4   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/29,09:59:02  25.7016 25.7430  0.0193    6   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/28,12:30:57  25.7047 25.7430  0.0152    6   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/04,10:33:53  25.7089 25.7430  0.0085    4   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/05,10:21:04  25.7078 25.7430  0.0080    4   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/01,09:57:53  25.7179 25.7430  0.0000    3   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/22,14:22:42  25.7170 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/24,14:45:01  25.7069 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/27,14:46:36  25.7100 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/29,14:39:33  25.6881 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/30,14:46:45  25.6658 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/06/23,10:16:27  24.8045 24.8000  0.0426    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/24,10:22:47  24.8213 24.8000  0.0363    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/27,10:25:23  24.8190 24.8000  0.0415    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/29,10:01:55  24.7694 24.8000  0.0431    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/28,12:33:41  24.7714 24.8000  0.0408    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/01,10:00:28  24.8012 24.8000  0.0394    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/04,10:31:43  24.7981 24.8000  0.0419    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/05,10:23:05  24.7617 24.8000  0.0311    4   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/24,14:33:30  24.7644 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/27,14:52:13  24.7629 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/29,14:42:34  24.7233 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/30,14:49:37  24.7408 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+g 2003/05/25,08:16:48  26.4408 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/05/25,14:02:24  26.4275 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/05/25,14:03:59  26.4430 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/05/26,14:50:55  26.4043 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/05/26,07:54:11  26.4084 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/05/25,08:18:23  26.3957 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/05/27,10:26:41  25.9994 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/27,10:27:41  25.9876 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/25,14:06:51  25.9703 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/27,14:38:23  25.9785 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/26,14:47:54  25.9553 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/25,14:08:26  25.9845 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/27,14:40:16  25.9925 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/26,07:58:30  25.9474 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/25,08:23:08  25.9621 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/27,06:04:10  25.9786 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/27,10:29:16  25.9440 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/05/27,06:06:54  25.7535 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/27,10:31:52  25.7376 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/25,14:11:19  25.7157 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/27,14:43:26  25.7314 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/26,14:45:01  25.7264 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/25,14:12:54  25.7356 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/27,14:44:52  25.7485 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/26,08:02:41  25.7276 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/25,08:27:35  25.6939 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/27,06:08:29  25.6955 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/27,10:33:27  25.6919 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/05/25,08:30:28  24.8014 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/25,14:15:38  24.7352 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/25,14:17:13  24.7520 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/25,14:39:50  24.7505 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/25,14:42:25  24.7538 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/25,14:44:52  24.7559 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/25,14:50:55  24.7465 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/26,08:08:00  24.6889 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/26,08:09:44  24.7414 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/25,08:32:03  24.7488 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+u 2003/07/22,13:40:22  25.3017 25.2800  0.0209    6   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/07/31,10:28:33  25.2284 25.2800  0.0319    7   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/01,11:32:47  25.2627 25.2800  0.0124    5   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/07/22,11:26:35  25.2747 25.2800  0.0072    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+g 2003/07/30,12:30:05  26.3704 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:31:32  26.3815 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:32:24  26.4011 26.4600  0.0175    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:33:15  26.3942 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:34:07  26.3715 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:34:59  26.3837 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:36:43  26.3226 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:38:26  26.3463 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:39:18  26.3810 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:12:46  26.4141 26.4600  0.0199    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:14:38  26.2761 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:44:18  26.4026 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:45:10  26.3946 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:46:10  26.4046 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:47:02  26.3942 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:47:54  26.4032 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:48:46  26.4307 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:49:37  26.4329 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/01,14:30:46  26.4302 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:35:51  26.3759 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:37:35  26.3472 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:13:46  26.3669 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:40:19  26.4117 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:41:19  26.4284 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:42:20  26.4288 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:43:11  26.3882 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:44:21  26.4019 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:45:21  26.4233 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:46:22  26.3867 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:47:13  26.4394 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:48:23  26.4528 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:49:23  26.4335 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:15:30  26.2898 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:16:22  26.2841 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:28:01  26.3029 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:32:12  26.2736 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:33:12  26.3506 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:34:22  26.3716 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:35:22  26.3566 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:36:14  26.3866 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:37:23  26.3626 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:38:23  26.3926 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:39:24  26.3606 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:40:16  26.3566 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:41:25  26.3863 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:42:25  26.3973 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:50:29  26.4281 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:51:21  26.4151 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/22,11:20:06  26.4140 26.4600  0.0058    6   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:36:02  26.3875 26.4600  0.0082    6   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:36:54  26.3962 26.4600  0.0061    6   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:38:47  26.3939 26.4600  0.0048    6   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:39:38  26.3879 26.4600  0.0071    6   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/01,11:24:17  26.4161 26.4600  0.0192    7   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/22,13:42:40  26.4298 26.4600  0.0089    5   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:23:57  26.3996 26.4600  0.0087    5   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:35:02  26.3865 26.4600  0.0082    5   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:37:55  26.3802 26.4600  0.0061    5   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:40:30  26.3766 26.4600  0.0064    5   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:41:22  26.3746 26.4600  0.0090    5   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:42:31  26.3733 26.4600  0.0090    5   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:43:23  26.3783 26.4600  0.0086    5   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/07/30,12:28:04  25.9364 25.9780  0.0140    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/01,14:28:45  25.9363 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/01,11:28:27  25.9590 25.9780  0.0195    7   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/22,11:22:16  25.9475 25.9780  0.0000    3   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/22,13:38:03  25.9685 25.9780  0.0152    5   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/31,10:30:43  25.9386 25.9780  0.0138    5   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/08/01,14:35:13  25.7086 25.7430  0.0000    3   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/01,11:30:28  25.7165 25.7430  0.0193    5   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/22,11:17:57  25.7288 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/22,13:44:49  25.7200 25.7430  0.0187    5   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/31,10:32:52  25.6899 25.7430  0.0179    5   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/08/01,14:37:06  24.7903 24.8000  0.0000    3   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/22,11:24:17  24.7831 24.8000  0.0416    7   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/22,13:46:50  24.7811 24.8000  0.0401    7   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/31,10:26:15  24.7419 24.8000  0.0384    7   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/21,06:16:07  24.8628 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+u 2003/08/21,09:56:35  25.3331 25.2800  0.0357    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/22,06:16:24  25.4472 25.2800  0.0382    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/22,09:13:32  25.3878 25.2800  0.0050    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/25,12:39:10  25.4175 25.2800  0.0310    5   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/28,10:14:35  25.3980 25.2800  0.0296    5   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/29,08:14:38  25.3912 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/29,08:15:38  25.3885 25.2800  0.0373    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/30,09:59:02  25.3895 25.2800  0.0318    5   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/31,07:15:10  25.4075 25.2800  0.0273    5   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/09/04,08:31:03  25.3510 25.2800  0.0058    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/25,05:52:39  25.3050 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/30,07:13:00  25.4598 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+g 2003/08/27,15:09:21  26.5096 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/09/03,15:00:34  26.5288 26.4600  0.0205    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/23,14:57:24  26.5457 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/30,14:25:00  26.5669 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/09/04,15:11:05  26.4714 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/28,07:13:09  26.5061 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/21,10:07:58  26.4956 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/22,06:24:46  26.5343 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/25,12:36:51  26.5242 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/28,10:18:54  26.5111 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/29,08:22:24  26.5010 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/30,09:56:44  26.5113 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/31,07:19:37  26.5286 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/09/04,08:28:53  26.4813 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/23,07:09:15  26.5158 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/25,05:50:21  26.4298 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/30,07:10:33  26.5390 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/09/03,05:49:29  26.4413 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/08/23,14:50:55  26.0223 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/30,14:27:10  26.0383 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/09/03,15:02:35  26.0080 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/09/04,15:13:14  25.9757 25.9780  0.0000    3   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/30,09:52:24  25.9954 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/21,09:59:36  25.9575 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/22,06:18:25  26.0393 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/22,09:15:50  26.0112 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/25,12:34:50  26.0245 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/29,08:17:57  25.9944 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/31,07:21:47  26.0173 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/23,07:05:13  26.0000 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/30,07:06:23  26.0434 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/09/03,05:45:10  25.9892 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/09/03,15:04:45  25.7557 25.7430  0.0000    3   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/23,14:52:56  25.7570 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/30,14:29:02  25.7823 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/09/04,15:06:20  25.7414 25.7430  0.0000    3   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/28,07:18:20  25.7614 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/22,06:20:35  25.7676 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/22,09:17:42  25.7562 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/30,09:50:24  25.7790 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/21,10:02:21  25.7279 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/25,12:41:36  25.7803 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/28,10:20:55  25.7747 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/29,08:24:25  25.7721 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/31,07:13:00  25.7795 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/09/04,08:33:30  25.7536 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/23,07:07:23  25.7556 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/30,07:08:32  25.7745 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/09/03,05:47:19  25.7456 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/08/27,15:18:00  24.7928 24.8000  0.0000    3   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/28,15:15:24  24.8363 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/09/03,15:09:21  24.8027 24.8000  0.0193    4   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/23,14:59:42  24.7762 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/30,14:33:38  24.8063 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/09/04,15:15:15  24.7638 24.8000  0.0355    5   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/28,07:21:12  24.8333 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/21,10:05:13  24.7669 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/22,09:11:13  24.7917 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/25,12:43:46  24.7967 24.8000  0.0000    3   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/28,10:22:56  24.8075 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/29,08:20:06  24.7902 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/30,09:54:25  24.8141 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/31,07:17:28  24.8038 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/09/04,08:35:31  24.7788 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/22,06:22:36  24.8321 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/23,07:03:04  24.7013 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/25,05:44:00  24.7611 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/30,07:04:13  24.8370 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/09/03,05:43:00  24.7850 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
Index: /tags/start/Ohana/src/imregister/doc/photdb.src
===================================================================
--- /tags/start/Ohana/src/imregister/doc/photdb.src	(revision 12606)
+++ /tags/start/Ohana/src/imregister/doc/photdb.src	(revision 12606)
@@ -0,0 +1,349 @@
+photreg -photcode i -trange 2003/02/08,13:18:37 1s -zp 25.7317 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/08,13:19:29 1s -zp 25.7307 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/08,13:20:12 1s -zp 25.7289 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/08,13:30:08 1s -zp 25.9878 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/08,13:30:51 1s -zp 25.9862 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/08,13:31:43 1s -zp 25.9816 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/09,12:26:03 1s -zp 25.9581 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/09,12:26:55 1s -zp 25.9529 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/09,12:27:38 1s -zp 25.9617 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/02/09,12:47:05 1s -zp 26.4692 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/02/09,12:47:48 1s -zp 26.4642 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/02/09,12:48:40 1s -zp 26.4624 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/09,13:01:29 1s -zp 25.3035 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/09,13:05:05 1s -zp 25.3034 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/09,13:06:14 1s -zp 25.3004 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/02/09,13:11:51 1s -zp 24.7789 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/02/09,13:12:43 1s -zp 24.7879 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/02/09,13:13:26 1s -zp 24.7888 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/09,13:22:04 1s -zp 25.7434 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/09,13:22:56 1s -zp 25.7318 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/09,13:23:39 1s -zp 25.7397 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/10,13:00:46 1s -zp 25.3434 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/10,13:27:24 1s -zp 25.3435 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/10,13:33:10 1s -zp 25.3496 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/10,13:38:47 1s -zp 25.3583 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/10,13:56:21 1s -zp 25.3455 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/12,15:18:51 1s -zp 26.0073 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/02/23,10:10:59 1s -zp 26.4664 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/02/23,10:11:59 1s -zp 26.4654 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/02/23,10:13:00 1s -zp 26.4604 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/23,10:17:28 1s -zp 25.9736 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/23,10:20:12 1s -zp 25.9708 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/23,10:20:55 1s -zp 25.9648 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/23,10:25:32 1s -zp 25.7384 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/23,10:28:07 1s -zp 25.7415 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/23,10:28:59 1s -zp 25.7465 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/02/23,10:33:44 1s -zp 24.7826 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/02/23,10:36:54 1s -zp 24.7967 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/02/24,12:00:51 1s -zp 26.4463 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/02/24,12:01:43 1s -zp 26.4393 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/02/24,12:02:35 1s -zp 26.4343 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/24,12:07:20 1s -zp 25.9939 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/24,12:09:47 1s -zp 25.9722 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/24,12:10:39 1s -zp 25.9897 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/24,12:15:24 1s -zp 25.7579 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/24,12:18:00 1s -zp 25.7399 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/24,12:18:51 1s -zp 25.7489 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/02/24,12:23:19 1s -zp 24.7178 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/02/24,12:25:46 1s -zp 24.7117 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/02/24,12:26:47 1s -zp 24.7562 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/24,12:36:34 1s -zp 25.2875 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/24,12:37:43 1s -zp 25.2855 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/24,12:39:01 1s -zp 25.3197 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/03/22,15:11:13 1s -zp 25.4630 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/03/23,15:12:14 1s -zp 25.3056 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/03/24,14:59:16 1s -zp 24.8271 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/03/24,15:07:46 1s -zp 26.4566 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/03/24,15:10:56 1s -zp 25.9917 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/03/25,15:12:48 1s -zp 25.7633 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/03/25,15:21:27 1s -zp 26.0231 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/03/30,13:12:34 1s -zp 26.4501 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/03/30,13:20:55 1s -zp 24.7152 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/04/25,08:55:23 1s -zp 25.9287 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/04/25,08:58:07 1s -zp 25.7034 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/04/25,09:00:43 1s -zp 24.7533 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/04/25,09:06:28 1s -zp 26.4030 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/04/26,10:44:32 1s -zp 25.9647 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/04/26,12:38:26 1s -zp 25.9774 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/04/26,13:05:05 1s -zp 26.0053 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/04/26,13:06:05 1s -zp 25.9697 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/04/26,13:14:35 1s -zp 25.9455 -dzp 0.0046 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/04/27,08:44:44 1s -zp 25.9646 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/04/27,08:47:28 1s -zp 25.9676 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/04/27,09:57:10 1s -zp 25.7930 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/05/25,08:16:48 1s -zp 26.4408 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/05/25,08:18:23 1s -zp 26.3957 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/25,08:23:08 1s -zp 25.9621 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/25,08:27:35 1s -zp 25.6939 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/25,08:30:28 1s -zp 24.8014 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/25,08:32:03 1s -zp 24.7488 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/05/25,14:02:24 1s -zp 26.4275 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/05/25,14:03:59 1s -zp 26.4430 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/25,14:06:51 1s -zp 25.9703 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/25,14:08:26 1s -zp 25.9845 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/25,14:11:19 1s -zp 25.7157 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/25,14:12:54 1s -zp 25.7356 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/25,14:15:38 1s -zp 24.7352 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/25,14:17:13 1s -zp 24.7520 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/25,14:39:50 1s -zp 24.7505 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/25,14:42:25 1s -zp 24.7538 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/25,14:44:52 1s -zp 24.7559 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/25,14:50:55 1s -zp 24.7465 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/05/26,07:54:11 1s -zp 26.4084 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/26,07:58:30 1s -zp 25.9474 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/26,08:02:41 1s -zp 25.7276 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/26,08:08:00 1s -zp 24.6889 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/26,08:09:44 1s -zp 24.7414 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/26,14:45:01 1s -zp 25.7264 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/26,14:47:54 1s -zp 25.9553 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/05/26,14:50:55 1s -zp 26.4043 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/27,06:04:10 1s -zp 25.9786 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/27,06:06:54 1s -zp 25.7535 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/27,06:08:29 1s -zp 25.6955 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/27,10:26:41 1s -zp 25.9994 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/27,10:27:41 1s -zp 25.9876 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/27,10:29:16 1s -zp 25.9440 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/27,10:31:52 1s -zp 25.7376 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/27,10:33:27 1s -zp 25.6919 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/27,14:38:23 1s -zp 25.9785 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/27,14:40:16 1s -zp 25.9925 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/27,14:43:26 1s -zp 25.7314 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/27,14:44:52 1s -zp 25.7485 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/05/30,14:21:41 1s -zp 25.2892 -dzp 0.0150 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/02,07:20:29 1s -zp 25.7291 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/02,07:23:22 1s -zp 24.8465 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/04,06:40:27 1s -zp 25.7566 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/05,06:21:27 1s -zp 25.5921 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/06,05:58:59 1s -zp 25.7441 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/08,14:43:35 1s -zp 25.9302 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/08,14:48:20 1s -zp 25.6812 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/06/09,14:36:14 1s -zp 25.2311 -dzp 0.0071 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/09,14:42:25 1s -zp 24.7583 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/22,12:56:00 1s -zp 25.9895 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/22,12:58:53 1s -zp 25.7312 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/22,14:22:42 1s -zp 25.7170 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/22,14:27:01 1s -zp 26.4249 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/22,14:29:45 1s -zp 25.9493 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/23,10:13:35 1s -zp 25.9652 -dzp 0.0047 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/23,10:16:27 1s -zp 24.8045 -dzp 0.0426 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/23,10:19:29 1s -zp 26.4170 -dzp 0.0112 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/24,10:19:55 1s -zp 25.9644 -dzp 0.0033 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/24,10:22:47 1s -zp 24.8213 -dzp 0.0363 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/24,10:25:49 1s -zp 25.7261 -dzp 0.0095 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/24,10:28:33 1s -zp 26.4245 -dzp 0.0086 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/24,14:33:30 1s -zp 24.7644 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/06/24,14:36:40 1s -zp 25.2756 -dzp 0.0361 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/24,14:39:24 1s -zp 26.4019 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/24,14:42:17 1s -zp 25.9354 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/24,14:45:01 1s -zp 25.7069 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/26,11:56:32 1s -zp 26.4183 -dzp 0.0130 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/26,11:59:16 1s -zp 25.7120 -dzp 0.0099 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/26,12:02:09 1s -zp 25.9610 -dzp 0.0073 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/27,10:17:02 1s -zp 26.4285 -dzp 0.0113 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/27,10:19:46 1s -zp 25.9708 -dzp 0.0008 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/27,10:22:39 1s -zp 25.7250 -dzp 0.0103 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/27,10:25:23 1s -zp 24.8190 -dzp 0.0415 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/06/27,14:43:26 1s -zp 25.2580 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/27,14:46:36 1s -zp 25.7100 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/27,14:49:29 1s -zp 25.9371 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/27,14:52:13 1s -zp 24.7629 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/28,12:25:29 1s -zp 26.4477 -dzp 0.0251 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/28,12:28:22 1s -zp 25.9663 -dzp 0.0058 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/28,12:30:57 1s -zp 25.7047 -dzp 0.0152 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/28,12:33:41 1s -zp 24.7714 -dzp 0.0408 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/29,09:53:25 1s -zp 26.4350 -dzp 0.0274 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/29,09:56:18 1s -zp 25.9528 -dzp 0.0089 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/29,09:59:02 1s -zp 25.7016 -dzp 0.0193 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/29,10:01:55 1s -zp 24.7694 -dzp 0.0431 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/29,14:33:38 1s -zp 26.4104 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/06/29,14:36:40 1s -zp 25.2756 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/29,14:39:33 1s -zp 25.6881 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/29,14:42:34 1s -zp 24.7233 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/29,14:45:27 1s -zp 25.9172 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/30,14:40:59 1s -zp 26.3187 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/06/30,14:44:00 1s -zp 25.1926 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/30,14:46:45 1s -zp 25.6658 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/30,14:49:37 1s -zp 24.7408 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/30,14:52:30 1s -zp 25.9221 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/01,09:52:16 1s -zp 26.4206 -dzp 0.0130 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/01,09:55:00 1s -zp 25.9672 -dzp 0.0073 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/07/01,09:57:53 1s -zp 25.7179 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/07/01,10:00:28 1s -zp 24.8012 -dzp 0.0394 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/01,13:01:55 1s -zp 26.4169 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/07/01,13:04:48 1s -zp 25.2674 -dzp 0.0365 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/01,13:07:49 1s -zp 25.9294 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/04,10:25:06 1s -zp 26.4018 -dzp 0.0143 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/04,10:29:42 1s -zp 25.9544 -dzp 0.0103 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/07/04,10:31:43 1s -zp 24.7981 -dzp 0.0419 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/07/04,10:33:53 1s -zp 25.7089 -dzp 0.0085 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/05,10:16:36 1s -zp 25.9552 -dzp 0.0067 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/07/05,10:21:04 1s -zp 25.7078 -dzp 0.0080 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/07/05,10:23:05 1s -zp 24.7617 -dzp 0.0311 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/05,10:25:14 1s -zp 26.4114 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/05,14:48:46 1s -zp 25.9320 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/07/05,14:51:04 1s -zp 25.2739 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/07,07:42:14 1s -zp 25.8036 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/07/21,06:16:07 1s -zp 24.8628 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/07/22,11:17:57 1s -zp 25.7288 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/22,11:20:06 1s -zp 26.4140 -dzp 0.0058 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/22,11:22:16 1s -zp 25.9475 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/07/22,11:24:17 1s -zp 24.7831 -dzp 0.0416 -Nmeas 7 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/07/22,11:26:35 1s -zp 25.2747 -dzp 0.0072 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/22,13:38:03 1s -zp 25.9685 -dzp 0.0152 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/07/22,13:40:22 1s -zp 25.3017 -dzp 0.0209 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/22,13:42:40 1s -zp 26.4298 -dzp 0.0089 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/07/22,13:44:49 1s -zp 25.7200 -dzp 0.0187 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/07/22,13:46:50 1s -zp 24.7811 -dzp 0.0401 -Nmeas 7 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/30,12:28:04 1s -zp 25.9364 -dzp 0.0140 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:30:05 1s -zp 26.3704 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:31:32 1s -zp 26.3815 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:32:24 1s -zp 26.4011 -dzp 0.0175 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:33:15 1s -zp 26.3942 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:34:07 1s -zp 26.3715 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:34:59 1s -zp 26.3837 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:35:51 1s -zp 26.3759 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:36:43 1s -zp 26.3226 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:37:35 1s -zp 26.3472 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:38:26 1s -zp 26.3463 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:39:18 1s -zp 26.3810 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:40:19 1s -zp 26.4117 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:41:19 1s -zp 26.4284 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:42:20 1s -zp 26.4288 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:43:11 1s -zp 26.3882 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:44:21 1s -zp 26.4019 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:45:21 1s -zp 26.4233 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:46:22 1s -zp 26.3867 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:47:13 1s -zp 26.4394 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:48:23 1s -zp 26.4528 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:49:23 1s -zp 26.4335 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:12:46 1s -zp 26.4141 -dzp 0.0199 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:13:46 1s -zp 26.3669 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:14:38 1s -zp 26.2761 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:15:30 1s -zp 26.2898 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:16:22 1s -zp 26.2841 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:28:01 1s -zp 26.3029 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:32:12 1s -zp 26.2736 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:33:12 1s -zp 26.3506 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:34:22 1s -zp 26.3716 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:35:22 1s -zp 26.3566 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:36:14 1s -zp 26.3866 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:37:23 1s -zp 26.3626 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:38:23 1s -zp 26.3926 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:39:24 1s -zp 26.3606 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:40:16 1s -zp 26.3566 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:41:25 1s -zp 26.3863 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:42:25 1s -zp 26.3973 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:44:18 1s -zp 26.4026 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:45:10 1s -zp 26.3946 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:46:10 1s -zp 26.4046 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:47:02 1s -zp 26.3942 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:47:54 1s -zp 26.4032 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:48:46 1s -zp 26.4307 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:49:37 1s -zp 26.4329 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:50:29 1s -zp 26.4281 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:51:21 1s -zp 26.4151 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:23:57 1s -zp 26.3996 -dzp 0.0087 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/07/31,10:26:15 1s -zp 24.7419 -dzp 0.0384 -Nmeas 7 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/07/31,10:28:33 1s -zp 25.2284 -dzp 0.0319 -Nmeas 7 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/31,10:30:43 1s -zp 25.9386 -dzp 0.0138 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/07/31,10:32:52 1s -zp 25.6899 -dzp 0.0179 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:35:02 1s -zp 26.3865 -dzp 0.0082 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:36:02 1s -zp 26.3875 -dzp 0.0082 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:36:54 1s -zp 26.3962 -dzp 0.0061 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:37:55 1s -zp 26.3802 -dzp 0.0061 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:38:47 1s -zp 26.3939 -dzp 0.0048 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:39:38 1s -zp 26.3879 -dzp 0.0071 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:40:30 1s -zp 26.3766 -dzp 0.0064 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:41:22 1s -zp 26.3746 -dzp 0.0090 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:42:31 1s -zp 26.3733 -dzp 0.0090 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:43:23 1s -zp 26.3783 -dzp 0.0086 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/01,11:24:17 1s -zp 26.4161 -dzp 0.0192 -Nmeas 7 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/01,11:28:27 1s -zp 25.9590 -dzp 0.0195 -Nmeas 7 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/01,11:30:28 1s -zp 25.7165 -dzp 0.0193 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/01,11:32:47 1s -zp 25.2627 -dzp 0.0124 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/01,14:28:45 1s -zp 25.9363 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/01,14:30:46 1s -zp 26.4302 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/01,14:35:13 1s -zp 25.7086 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/01,14:37:06 1s -zp 24.7903 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/21,09:56:35 1s -zp 25.3331 -dzp 0.0357 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/21,09:59:36 1s -zp 25.9575 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/21,10:02:21 1s -zp 25.7279 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/21,10:05:13 1s -zp 24.7669 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/21,10:07:58 1s -zp 26.4956 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/22,06:16:24 1s -zp 25.4472 -dzp 0.0382 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/22,06:18:25 1s -zp 26.0393 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/22,06:20:35 1s -zp 25.7676 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/22,06:22:36 1s -zp 24.8321 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/22,06:24:46 1s -zp 26.5343 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/22,09:11:13 1s -zp 24.7917 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/22,09:13:32 1s -zp 25.3878 -dzp 0.0050 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/22,09:15:50 1s -zp 26.0112 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/22,09:17:42 1s -zp 25.7562 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/23,07:03:04 1s -zp 24.7013 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/23,07:05:13 1s -zp 26.0000 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/23,07:07:23 1s -zp 25.7556 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/23,07:09:15 1s -zp 26.5158 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/23,14:50:55 1s -zp 26.0223 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/23,14:52:56 1s -zp 25.7570 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/23,14:57:24 1s -zp 26.5457 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/23,14:59:42 1s -zp 24.7762 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/25,05:44:00 1s -zp 24.7611 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/25,05:50:21 1s -zp 26.4298 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/25,05:52:39 1s -zp 25.3050 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/25,12:34:50 1s -zp 26.0245 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/25,12:36:51 1s -zp 26.5242 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/25,12:39:10 1s -zp 25.4175 -dzp 0.0310 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/25,12:41:36 1s -zp 25.7803 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/25,12:43:46 1s -zp 24.7967 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/27,15:09:21 1s -zp 26.5096 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/27,15:18:00 1s -zp 24.7928 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/28,07:13:09 1s -zp 26.5061 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/28,07:18:20 1s -zp 25.7614 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/28,07:21:12 1s -zp 24.8333 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/28,10:14:35 1s -zp 25.3980 -dzp 0.0296 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/28,10:18:54 1s -zp 26.5111 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/28,10:20:55 1s -zp 25.7747 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/28,10:22:56 1s -zp 24.8075 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/28,15:15:24 1s -zp 24.8363 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/29,08:14:38 1s -zp 25.3912 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/29,08:15:38 1s -zp 25.3885 -dzp 0.0373 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/29,08:17:57 1s -zp 25.9944 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/29,08:20:06 1s -zp 24.7902 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/29,08:22:24 1s -zp 26.5010 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/29,08:24:25 1s -zp 25.7721 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/30,07:04:13 1s -zp 24.8370 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/30,07:06:23 1s -zp 26.0434 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/30,07:08:32 1s -zp 25.7745 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/30,07:10:33 1s -zp 26.5390 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/30,07:13:00 1s -zp 25.4598 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/30,09:50:24 1s -zp 25.7790 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/30,09:52:24 1s -zp 25.9954 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/30,09:54:25 1s -zp 24.8141 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/30,09:56:44 1s -zp 26.5113 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/30,09:59:02 1s -zp 25.3895 -dzp 0.0318 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/30,14:25:00 1s -zp 26.5669 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/30,14:27:10 1s -zp 26.0383 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/30,14:29:02 1s -zp 25.7823 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/30,14:33:38 1s -zp 24.8063 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/31,07:13:00 1s -zp 25.7795 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/31,07:15:10 1s -zp 25.4075 -dzp 0.0273 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/31,07:17:28 1s -zp 24.8038 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/31,07:19:37 1s -zp 26.5286 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/31,07:21:47 1s -zp 26.0173 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/09/03,05:43:00 1s -zp 24.7850 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/09/03,05:45:10 1s -zp 25.9892 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/09/03,05:47:19 1s -zp 25.7456 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/09/03,05:49:29 1s -zp 26.4413 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/09/03,15:00:34 1s -zp 26.5288 -dzp 0.0205 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/09/03,15:02:35 1s -zp 26.0080 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/09/03,15:04:45 1s -zp 25.7557 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/09/03,15:09:21 1s -zp 24.8027 -dzp 0.0193 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/09/04,08:28:53 1s -zp 26.4813 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/09/04,08:31:03 1s -zp 25.3510 -dzp 0.0058 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/09/04,08:33:30 1s -zp 25.7536 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/09/04,08:35:31 1s -zp 24.7788 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/09/04,15:06:20 1s -zp 25.7414 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/09/04,15:11:05 1s -zp 26.4714 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/09/04,15:13:14 1s -zp 25.9757 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/09/04,15:15:15 1s -zp 24.7638 -dzp 0.0355 -Nmeas 5 -Ntime 1 -label elixir
Index: /tags/start/Ohana/src/imregister/doc/spdb.txt
===================================================================
--- /tags/start/Ohana/src/imregister/doc/spdb.txt	(revision 12606)
+++ /tags/start/Ohana/src/imregister/doc/spdb.txt	(revision 12606)
@@ -0,0 +1,58 @@
+
+plan - use imregister / imsearch framework for spectra.db
+
+relevant database usages:
+
+use this for spectra.db ref ?
+  average.code or average.Xg
+
+
+spectra in spectra.db will have RA,DEC: join between tables using position
+
+example queries:
+
+spsearch 
+
+/* structure for Spectra Registration Database */
+typedef struct {
+  char filename[64];
+  char pathname[128];
+  char telescope[32];
+  char instrument[32];
+ 
+  char objname[64];
+
+  char mode (MEF?)
+  
+  float ra, dec;
+  float exptime;
+  float airmass;
+
+  /* spectral range representation */
+  float W0, W1, dW; 
+
+  /* spectral range start, end; average value for nm / pixel */
+
+  float sky;
+  float bias;
+  float fwhm;
+
+  float telfocus;
+  float xprobe, yprobe, zprobe;
+  float dettemp;
+  float teltemp[4];
+  float rotangle;
+
+  unsigned long int obstime;
+  unsigned long int regtime;
+} RegImage;  /* 360 bytes / image */
+
+
+outstanding questions:
+
+- convert spectral file to standard format on db insertion?
+  - uniform keywords for wavelength calibration?
+  - need header WCS
+  - single FITS file
+  - how to store discontiguous spectra? (MEF?)
+  - 
Index: /tags/start/Ohana/src/imregister/doc/transdb.dat
===================================================================
--- /tags/start/Ohana/src/imregister/doc/transdb.dat	(revision 12606)
+++ /tags/start/Ohana/src/imregister/doc/transdb.dat	(revision 12606)
@@ -0,0 +1,159 @@
+u 2003/02/24,00:00:00  25.2980 25.2800  0.0157    7   3   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+g 2003/02/23,00:00:00  26.4640 26.4600  0.0026    3   3   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/02/24,00:00:00  26.4400 26.4600  0.0049    6   3   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/02/23,00:00:00  25.9700 25.9780  0.0037    3   3   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/24,00:00:00  25.9850 25.9780  0.0094    5   3   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/02/23,00:00:00  25.7420 25.7430  0.0033    3   3   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/24,00:00:00  25.7490 25.7430  0.0073    6   3   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/02/23,00:00:00  24.7900 24.8000  0.0070    2   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/02/24,00:00:00  24.7290 24.8000  0.0197    4   3   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+u 2003/03/22,00:00:00  25.4630 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/03/23,00:00:00  25.3060 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+g 2003/03/24,00:00:00  26.4570 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/03/30,00:00:00  26.4500 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/03/24,00:00:00  25.9920 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/03/25,00:00:00  26.0230 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/03/25,00:00:00  25.7630 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/03/24,00:00:00  24.8270 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/03/30,00:00:00  24.7150 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+g 2003/04/25,00:00:00  26.4030 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/04/25,00:00:00  25.9290 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/26,00:00:00  25.9730 25.9780  0.0195   11   5   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/27,00:00:00  25.9080 25.9780  0.0816    5   3   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/04/25,00:00:00  25.7030 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/04/25,00:00:00  24.7530 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+u 2003/05/30,00:00:00  25.2890 25.2800  0.0000    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/06/09,00:00:00  25.2310 25.2800  0.0000    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+r 2003/06/08,00:00:00  25.9300 25.9780  0.0000    3   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/06/02,00:00:00  25.7290 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/04,00:00:00  25.7570 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/05,00:00:00  25.5920 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/06,00:00:00  25.7440 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/08,00:00:00  25.6810 25.7430  0.0000    3   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/06/02,00:00:00  24.8460 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/09,00:00:00  24.7580 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+u 2003/06/24,00:00:00  25.2760 25.2800  0.0000    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/06/27,00:00:00  25.2580 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/06/29,00:00:00  25.2760 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/06/30,00:00:00  25.1930 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/07/01,00:00:00  25.2670 25.2800  0.0000    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/07/05,00:00:00  25.2740 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+g 2003/06/22,00:00:00  26.4250 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/23,00:00:00  26.4170 26.4600  0.0000    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/24,00:00:00  26.4130 26.4600  0.0113    5   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/26,00:00:00  26.4180 26.4600  0.0000    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/27,00:00:00  26.4280 26.4600  0.0000    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/28,00:00:00  26.4480 26.4600  0.0000    6   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/29,00:00:00  26.4230 26.4600  0.0123    8   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/30,00:00:00  26.3190 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/01,00:00:00  26.4190 26.4600  0.0019    6   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/04,00:00:00  26.4020 26.4600  0.0000    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/05,00:00:00  26.4110 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/06/22,00:00:00  25.9690 25.9780  0.0201    4   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/23,00:00:00  25.9650 25.9780  0.0000    6   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/24,00:00:00  25.9500 25.9780  0.0145    6   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/26,00:00:00  25.9610 25.9780  0.0000    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/27,00:00:00  25.9540 25.9780  0.0169    6   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/28,00:00:00  25.9660 25.9780  0.0000    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/29,00:00:00  25.9350 25.9780  0.0178    8   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/30,00:00:00  25.9220 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/01,00:00:00  25.9480 25.9780  0.0189    6   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/04,00:00:00  25.9540 25.9780  0.0000    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/05,00:00:00  25.9440 25.9780  0.0116    7   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/07,00:00:00  25.8040 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/06/22,00:00:00  25.7240 25.7430  0.0071    4   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/24,00:00:00  25.7160 25.7430  0.0096    6   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/26,00:00:00  25.7120 25.7430  0.0000    4   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/27,00:00:00  25.7180 25.7430  0.0075    6   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/28,00:00:00  25.7050 25.7430  0.0000    6   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/29,00:00:00  25.6950 25.7430  0.0067    8   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/30,00:00:00  25.6660 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/01,00:00:00  25.7180 25.7430  0.0000    3   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/04,00:00:00  25.7090 25.7430  0.0000    4   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/05,00:00:00  25.7080 25.7430  0.0000    4   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/06/23,00:00:00  24.8050 24.8000  0.0000    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/24,00:00:00  24.7930 24.8000  0.0284    8   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/27,00:00:00  24.7910 24.8000  0.0280    8   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/28,00:00:00  24.7710 24.8000  0.0000    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/29,00:00:00  24.7460 24.8000  0.0231    8   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/30,00:00:00  24.7410 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/01,00:00:00  24.8010 24.8000  0.0000    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/04,00:00:00  24.7980 24.8000  0.0000    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/05,00:00:00  24.7620 24.8000  0.0000    4   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+g 2003/05/25,00:00:00  26.4270 26.4600  0.0189    5   4   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/05/26,00:00:00  26.4060 26.4600  0.0021    2   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/05/25,00:00:00  25.9720 25.9780  0.0093    4   3   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/26,00:00:00  25.9510 25.9780  0.0040    3   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/27,00:00:00  25.9800 25.9780  0.0178    7   6   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/05/25,00:00:00  25.7150 25.7430  0.0170    3   3   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/26,00:00:00  25.7270 25.7430  0.0006    3   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/27,00:00:00  25.7260 25.7430  0.0242    6   6   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/05/25,00:00:00  24.7560 24.8000  0.0183    9   8   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/26,00:00:00  24.7150 24.8000  0.0262    3   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+u 2003/07/22,00:00:00  25.2880 25.2800  0.0135   10   2   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/07/31,00:00:00  25.2280 25.2800  0.0000    7   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/01,00:00:00  25.2630 25.2800  0.0000    5   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+g 2003/07/22,00:00:00  26.4220 26.4600  0.0079   11   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,00:00:00  26.3810 26.4600  0.0431   78  47   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,00:00:00  26.3850 26.4600  0.0086   59  11   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/01,00:00:00  26.4230 26.4600  0.0070    9   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/07/22,00:00:00  25.9580 25.9780  0.0105    8   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/30,00:00:00  25.9360 25.9780  0.0000    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/31,00:00:00  25.9390 25.9780  0.0000    5   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/01,00:00:00  25.9480 25.9780  0.0113    9   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/07/22,00:00:00  25.7240 25.7430  0.0044    6   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/31,00:00:00  25.6900 25.7430  0.0000    5   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/01,00:00:00  25.7130 25.7430  0.0039    8   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/07/21,00:00:00  24.8630 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/22,00:00:00  24.7820 24.8000  0.0010   14   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/31,00:00:00  24.7420 24.8000  0.0000    7   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/01,00:00:00  24.7900 24.8000  0.0000    3   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+u 2003/08/21,00:00:00  25.3330 25.2800  0.0000    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/22,00:00:00  25.4170 25.2800  0.0297    8   2   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/25,00:00:00  25.3610 25.2800  0.0563    6   2   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/28,00:00:00  25.3980 25.2800  0.0000    5   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/29,00:00:00  25.3900 25.2800  0.0013    7   2   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/30,00:00:00  25.4250 25.2800  0.0351    6   2   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/31,00:00:00  25.4070 25.2800  0.0000    5   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/09/04,00:00:00  25.3510 25.2800  0.0000    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+g 2003/08/21,00:00:00  26.4960 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/22,00:00:00  26.5340 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/23,00:00:00  26.5310 26.4600  0.0150    2   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/25,00:00:00  26.4770 26.4600  0.0472    3   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/27,00:00:00  26.5100 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/28,00:00:00  26.5090 26.4600  0.0025    4   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/29,00:00:00  26.5010 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/30,00:00:00  26.5390 26.4600  0.0227    5   3   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/31,00:00:00  26.5290 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/09/03,00:00:00  26.4850 26.4600  0.0437    5   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/09/04,00:00:00  26.4760 26.4600  0.0049    4   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/08/21,00:00:00  25.9570 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/22,00:00:00  26.0250 25.9780  0.0141    2   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/23,00:00:00  26.0110 25.9780  0.0112    2   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/25,00:00:00  26.0240 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/29,00:00:00  25.9940 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/30,00:00:00  26.0260 25.9780  0.0215    3   3   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/31,00:00:00  26.0170 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/09/03,00:00:00  25.9990 25.9780  0.0094    2   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/09/04,00:00:00  25.9760 25.9780  0.0000    3   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/08/21,00:00:00  25.7280 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/22,00:00:00  25.7620 25.7430  0.0057    4   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/23,00:00:00  25.7560 25.7430  0.0007    2   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/25,00:00:00  25.7800 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/28,00:00:00  25.7680 25.7430  0.0067    2   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/29,00:00:00  25.7720 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/30,00:00:00  25.7790 25.7430  0.0032    4   3   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/31,00:00:00  25.7790 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/09/03,00:00:00  25.7510 25.7430  0.0050    4   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/09/04,00:00:00  25.7470 25.7430  0.0061    4   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/08/21,00:00:00  24.7670 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/22,00:00:00  24.8120 24.8000  0.0202    3   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/23,00:00:00  24.7390 24.8000  0.0374    2   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/25,00:00:00  24.7790 24.8000  0.0178    4   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/27,00:00:00  24.7930 24.8000  0.0000    3   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/28,00:00:00  24.8260 24.8000  0.0129    5   3   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/29,00:00:00  24.7900 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/30,00:00:00  24.8190 24.8000  0.0130    4   3   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/31,00:00:00  24.8040 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/09/03,00:00:00  24.7940 24.8000  0.0089    5   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/09/04,00:00:00  24.7710 24.8000  0.0075    7   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
Index: /tags/start/Ohana/src/imregister/doc/transdb.src
===================================================================
--- /tags/start/Ohana/src/imregister/doc/transdb.src	(revision 12606)
+++ /tags/start/Ohana/src/imregister/doc/transdb.src	(revision 12606)
@@ -0,0 +1,159 @@
+photreg -trans -photcode z -trange 2003/02/23,00:00:00 1s -zp 24.7900 -dzp 0.0070 -Nmeas 2 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/02/23,00:00:00 1s -zp 25.7420 -dzp 0.0033 -Nmeas 3 -Ntime 3 -label elixir
+photreg -trans -photcode r -trange 2003/02/23,00:00:00 1s -zp 25.9700 -dzp 0.0037 -Nmeas 3 -Ntime 3 -label elixir
+photreg -trans -photcode g -trange 2003/02/23,00:00:00 1s -zp 26.4640 -dzp 0.0026 -Nmeas 3 -Ntime 3 -label elixir
+photreg -trans -photcode z -trange 2003/02/24,00:00:00 1s -zp 24.7290 -dzp 0.0197 -Nmeas 4 -Ntime 3 -label elixir
+photreg -trans -photcode u -trange 2003/02/24,00:00:00 1s -zp 25.2980 -dzp 0.0157 -Nmeas 7 -Ntime 3 -label elixir
+photreg -trans -photcode i -trange 2003/02/24,00:00:00 1s -zp 25.7490 -dzp 0.0073 -Nmeas 6 -Ntime 3 -label elixir
+photreg -trans -photcode r -trange 2003/02/24,00:00:00 1s -zp 25.9850 -dzp 0.0094 -Nmeas 5 -Ntime 3 -label elixir
+photreg -trans -photcode g -trange 2003/02/24,00:00:00 1s -zp 26.4400 -dzp 0.0049 -Nmeas 6 -Ntime 3 -label elixir
+photreg -trans -photcode u -trange 2003/03/22,00:00:00 1s -zp 25.4630 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/03/23,00:00:00 1s -zp 25.3060 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/03/24,00:00:00 1s -zp 24.8270 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/03/24,00:00:00 1s -zp 25.9920 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/03/24,00:00:00 1s -zp 26.4570 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/03/25,00:00:00 1s -zp 25.7630 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/03/25,00:00:00 1s -zp 26.0230 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/03/30,00:00:00 1s -zp 24.7150 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/03/30,00:00:00 1s -zp 26.4500 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/04/25,00:00:00 1s -zp 24.7530 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/04/25,00:00:00 1s -zp 25.7030 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/04/25,00:00:00 1s -zp 25.9290 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/04/25,00:00:00 1s -zp 26.4030 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/04/26,00:00:00 1s -zp 25.9730 -dzp 0.0195 -Nmeas 11 -Ntime 5 -label elixir
+photreg -trans -photcode r -trange 2003/04/27,00:00:00 1s -zp 25.9080 -dzp 0.0816 -Nmeas 5 -Ntime 3 -label elixir
+photreg -trans -photcode z -trange 2003/05/25,00:00:00 1s -zp 24.7560 -dzp 0.0183 -Nmeas 9 -Ntime 8 -label elixir
+photreg -trans -photcode i -trange 2003/05/25,00:00:00 1s -zp 25.7150 -dzp 0.0170 -Nmeas 3 -Ntime 3 -label elixir
+photreg -trans -photcode r -trange 2003/05/25,00:00:00 1s -zp 25.9720 -dzp 0.0093 -Nmeas 4 -Ntime 3 -label elixir
+photreg -trans -photcode g -trange 2003/05/25,00:00:00 1s -zp 26.4270 -dzp 0.0189 -Nmeas 5 -Ntime 4 -label elixir
+photreg -trans -photcode z -trange 2003/05/26,00:00:00 1s -zp 24.7150 -dzp 0.0262 -Nmeas 3 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/05/26,00:00:00 1s -zp 25.7270 -dzp 0.0006 -Nmeas 3 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/05/26,00:00:00 1s -zp 25.9510 -dzp 0.0040 -Nmeas 3 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/05/26,00:00:00 1s -zp 26.4060 -dzp 0.0021 -Nmeas 2 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/05/27,00:00:00 1s -zp 25.7260 -dzp 0.0242 -Nmeas 6 -Ntime 6 -label elixir
+photreg -trans -photcode r -trange 2003/05/27,00:00:00 1s -zp 25.9800 -dzp 0.0178 -Nmeas 7 -Ntime 6 -label elixir
+photreg -trans -photcode u -trange 2003/05/30,00:00:00 1s -zp 25.2890 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/06/02,00:00:00 1s -zp 24.8460 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/02,00:00:00 1s -zp 25.7290 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/04,00:00:00 1s -zp 25.7570 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/05,00:00:00 1s -zp 25.5920 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/06,00:00:00 1s -zp 25.7440 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/08,00:00:00 1s -zp 25.6810 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/06/08,00:00:00 1s -zp 25.9300 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/06/09,00:00:00 1s -zp 24.7580 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/06/09,00:00:00 1s -zp 25.2310 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/22,00:00:00 1s -zp 25.7240 -dzp 0.0071 -Nmeas 4 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/06/22,00:00:00 1s -zp 25.9690 -dzp 0.0201 -Nmeas 4 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/06/22,00:00:00 1s -zp 26.4250 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/06/23,00:00:00 1s -zp 24.8050 -dzp 0.0000 -Nmeas 6 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/06/23,00:00:00 1s -zp 25.9650 -dzp 0.0000 -Nmeas 6 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/06/23,00:00:00 1s -zp 26.4170 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/06/24,00:00:00 1s -zp 24.7930 -dzp 0.0284 -Nmeas 8 -Ntime 2 -label elixir
+photreg -trans -photcode u -trange 2003/06/24,00:00:00 1s -zp 25.2760 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/24,00:00:00 1s -zp 25.7160 -dzp 0.0096 -Nmeas 6 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/06/24,00:00:00 1s -zp 25.9500 -dzp 0.0145 -Nmeas 6 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/06/24,00:00:00 1s -zp 26.4130 -dzp 0.0113 -Nmeas 5 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/06/26,00:00:00 1s -zp 25.7120 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/06/26,00:00:00 1s -zp 25.9610 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/06/26,00:00:00 1s -zp 26.4180 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/06/27,00:00:00 1s -zp 24.7910 -dzp 0.0280 -Nmeas 8 -Ntime 2 -label elixir
+photreg -trans -photcode u -trange 2003/06/27,00:00:00 1s -zp 25.2580 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/27,00:00:00 1s -zp 25.7180 -dzp 0.0075 -Nmeas 6 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/06/27,00:00:00 1s -zp 25.9540 -dzp 0.0169 -Nmeas 6 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/06/27,00:00:00 1s -zp 26.4280 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/06/28,00:00:00 1s -zp 24.7710 -dzp 0.0000 -Nmeas 6 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/28,00:00:00 1s -zp 25.7050 -dzp 0.0000 -Nmeas 6 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/06/28,00:00:00 1s -zp 25.9660 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/06/28,00:00:00 1s -zp 26.4480 -dzp 0.0000 -Nmeas 6 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/06/29,00:00:00 1s -zp 24.7460 -dzp 0.0231 -Nmeas 8 -Ntime 2 -label elixir
+photreg -trans -photcode u -trange 2003/06/29,00:00:00 1s -zp 25.2760 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/29,00:00:00 1s -zp 25.6950 -dzp 0.0067 -Nmeas 8 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/06/29,00:00:00 1s -zp 25.9350 -dzp 0.0178 -Nmeas 8 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/06/29,00:00:00 1s -zp 26.4230 -dzp 0.0123 -Nmeas 8 -Ntime 2 -label elixir
+photreg -trans -photcode z -trange 2003/06/30,00:00:00 1s -zp 24.7410 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/06/30,00:00:00 1s -zp 25.1930 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/30,00:00:00 1s -zp 25.6660 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/06/30,00:00:00 1s -zp 25.9220 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/06/30,00:00:00 1s -zp 26.3190 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/07/01,00:00:00 1s -zp 24.8010 -dzp 0.0000 -Nmeas 6 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/07/01,00:00:00 1s -zp 25.2670 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/07/01,00:00:00 1s -zp 25.7180 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/07/01,00:00:00 1s -zp 25.9480 -dzp 0.0189 -Nmeas 6 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/07/01,00:00:00 1s -zp 26.4190 -dzp 0.0019 -Nmeas 6 -Ntime 2 -label elixir
+photreg -trans -photcode z -trange 2003/07/04,00:00:00 1s -zp 24.7980 -dzp 0.0000 -Nmeas 6 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/07/04,00:00:00 1s -zp 25.7090 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/07/04,00:00:00 1s -zp 25.9540 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/07/04,00:00:00 1s -zp 26.4020 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/07/05,00:00:00 1s -zp 24.7620 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/07/05,00:00:00 1s -zp 25.2740 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/07/05,00:00:00 1s -zp 25.7080 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/07/05,00:00:00 1s -zp 25.9440 -dzp 0.0116 -Nmeas 7 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/07/05,00:00:00 1s -zp 26.4110 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/07/07,00:00:00 1s -zp 25.8040 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/07/21,00:00:00 1s -zp 24.8630 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/07/22,00:00:00 1s -zp 24.7820 -dzp 0.0010 -Nmeas 14 -Ntime 2 -label elixir
+photreg -trans -photcode u -trange 2003/07/22,00:00:00 1s -zp 25.2880 -dzp 0.0135 -Nmeas 10 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/07/22,00:00:00 1s -zp 25.7240 -dzp 0.0044 -Nmeas 6 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/07/22,00:00:00 1s -zp 25.9580 -dzp 0.0105 -Nmeas 8 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/07/22,00:00:00 1s -zp 26.4220 -dzp 0.0079 -Nmeas 11 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/07/30,00:00:00 1s -zp 25.9360 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/07/30,00:00:00 1s -zp 26.3810 -dzp 0.0431 -Nmeas 78 -Ntime 47 -label elixir
+photreg -trans -photcode z -trange 2003/07/31,00:00:00 1s -zp 24.7420 -dzp 0.0000 -Nmeas 7 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/07/31,00:00:00 1s -zp 25.2280 -dzp 0.0000 -Nmeas 7 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/07/31,00:00:00 1s -zp 25.6900 -dzp 0.0000 -Nmeas 5 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/07/31,00:00:00 1s -zp 25.9390 -dzp 0.0000 -Nmeas 5 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/07/31,00:00:00 1s -zp 26.3850 -dzp 0.0086 -Nmeas 59 -Ntime 11 -label elixir
+photreg -trans -photcode z -trange 2003/08/01,00:00:00 1s -zp 24.7900 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/08/01,00:00:00 1s -zp 25.2630 -dzp 0.0000 -Nmeas 5 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/08/01,00:00:00 1s -zp 25.7130 -dzp 0.0039 -Nmeas 8 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/08/01,00:00:00 1s -zp 25.9480 -dzp 0.0113 -Nmeas 9 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/08/01,00:00:00 1s -zp 26.4230 -dzp 0.0070 -Nmeas 9 -Ntime 2 -label elixir
+photreg -trans -photcode z -trange 2003/08/21,00:00:00 1s -zp 24.7670 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/08/21,00:00:00 1s -zp 25.3330 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/08/21,00:00:00 1s -zp 25.7280 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/08/21,00:00:00 1s -zp 25.9570 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/08/21,00:00:00 1s -zp 26.4960 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/08/22,00:00:00 1s -zp 24.8120 -dzp 0.0202 -Nmeas 3 -Ntime 2 -label elixir
+photreg -trans -photcode u -trange 2003/08/22,00:00:00 1s -zp 25.4170 -dzp 0.0297 -Nmeas 8 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/08/22,00:00:00 1s -zp 25.7620 -dzp 0.0057 -Nmeas 4 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/08/22,00:00:00 1s -zp 26.0250 -dzp 0.0141 -Nmeas 2 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/08/22,00:00:00 1s -zp 26.5340 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/08/23,00:00:00 1s -zp 24.7390 -dzp 0.0374 -Nmeas 2 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/08/23,00:00:00 1s -zp 25.7560 -dzp 0.0007 -Nmeas 2 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/08/23,00:00:00 1s -zp 26.0110 -dzp 0.0112 -Nmeas 2 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/08/23,00:00:00 1s -zp 26.5310 -dzp 0.0150 -Nmeas 2 -Ntime 2 -label elixir
+photreg -trans -photcode z -trange 2003/08/25,00:00:00 1s -zp 24.7790 -dzp 0.0178 -Nmeas 4 -Ntime 2 -label elixir
+photreg -trans -photcode u -trange 2003/08/25,00:00:00 1s -zp 25.3610 -dzp 0.0563 -Nmeas 6 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/08/25,00:00:00 1s -zp 25.7800 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/08/25,00:00:00 1s -zp 26.0240 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/08/25,00:00:00 1s -zp 26.4770 -dzp 0.0472 -Nmeas 3 -Ntime 2 -label elixir
+photreg -trans -photcode z -trange 2003/08/27,00:00:00 1s -zp 24.7930 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/08/27,00:00:00 1s -zp 26.5100 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/08/28,00:00:00 1s -zp 24.8260 -dzp 0.0129 -Nmeas 5 -Ntime 3 -label elixir
+photreg -trans -photcode u -trange 2003/08/28,00:00:00 1s -zp 25.3980 -dzp 0.0000 -Nmeas 5 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/08/28,00:00:00 1s -zp 25.7680 -dzp 0.0067 -Nmeas 2 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/08/28,00:00:00 1s -zp 26.5090 -dzp 0.0025 -Nmeas 4 -Ntime 2 -label elixir
+photreg -trans -photcode z -trange 2003/08/29,00:00:00 1s -zp 24.7900 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/08/29,00:00:00 1s -zp 25.3900 -dzp 0.0013 -Nmeas 7 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/08/29,00:00:00 1s -zp 25.7720 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/08/29,00:00:00 1s -zp 25.9940 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/08/29,00:00:00 1s -zp 26.5010 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/08/30,00:00:00 1s -zp 24.8190 -dzp 0.0130 -Nmeas 4 -Ntime 3 -label elixir
+photreg -trans -photcode u -trange 2003/08/30,00:00:00 1s -zp 25.4250 -dzp 0.0351 -Nmeas 6 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/08/30,00:00:00 1s -zp 25.7790 -dzp 0.0032 -Nmeas 4 -Ntime 3 -label elixir
+photreg -trans -photcode r -trange 2003/08/30,00:00:00 1s -zp 26.0260 -dzp 0.0215 -Nmeas 3 -Ntime 3 -label elixir
+photreg -trans -photcode g -trange 2003/08/30,00:00:00 1s -zp 26.5390 -dzp 0.0227 -Nmeas 5 -Ntime 3 -label elixir
+photreg -trans -photcode z -trange 2003/08/31,00:00:00 1s -zp 24.8040 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/08/31,00:00:00 1s -zp 25.4070 -dzp 0.0000 -Nmeas 5 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/08/31,00:00:00 1s -zp 25.7790 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/08/31,00:00:00 1s -zp 26.0170 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/08/31,00:00:00 1s -zp 26.5290 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/09/03,00:00:00 1s -zp 24.7940 -dzp 0.0089 -Nmeas 5 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/09/03,00:00:00 1s -zp 25.7510 -dzp 0.0050 -Nmeas 4 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/09/03,00:00:00 1s -zp 25.9990 -dzp 0.0094 -Nmeas 2 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/09/03,00:00:00 1s -zp 26.4850 -dzp 0.0437 -Nmeas 5 -Ntime 2 -label elixir
+photreg -trans -photcode z -trange 2003/09/04,00:00:00 1s -zp 24.7710 -dzp 0.0075 -Nmeas 7 -Ntime 2 -label elixir
+photreg -trans -photcode u -trange 2003/09/04,00:00:00 1s -zp 25.3510 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/09/04,00:00:00 1s -zp 25.7470 -dzp 0.0061 -Nmeas 4 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/09/04,00:00:00 1s -zp 25.9760 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/09/04,00:00:00 1s -zp 26.4760 -dzp 0.0049 -Nmeas 4 -Ntime 2 -label elixir
Index: /tags/start/Ohana/src/imregister/include/photreg.h
===================================================================
--- /tags/start/Ohana/src/imregister/include/photreg.h	(revision 12606)
+++ /tags/start/Ohana/src/imregister/include/photreg.h	(revision 12606)
@@ -0,0 +1,47 @@
+# include <signal.h>
+
+struct {
+  int Ntimes;         unsigned long *tstart, *tstop;
+  int PhotCodeSelect; int photcode;
+  int LabelSelect;    char *Label;
+} criteria;
+
+struct {
+  int delete;
+  int modify;
+
+  int HST;
+  int verbose;
+  int convert;
+  char *table;
+  char *bintable;
+  char *cadctable;
+
+  int equiv;
+  int offset;
+  char *db;
+} output;
+
+enum {UNLOCK, LOCK, IGNORE};
+
+int args (int argc, char **argv);
+int regargs (int argc, char **argv, PhotPars *);
+PhotPars *get_images (int *N);
+int set_images (PhotPars *new, int Nnew);
+int load_db ();
+int save_db ();
+int update_db (int *match, int Nmatch);
+int append_db (PhotPars *new, int Nnew);
+int create_db ();
+int close_db ();
+void DeleteSubset (int *match, int Nmatch);
+int *match_criteria (int *Nmatch);
+int *match_images (PhotPars *subset, int Nsubset, int *Nmatch);
+void ModifySubset (int *match, int Nmatch);
+void OutputSubset (int *match, int Nmatch);
+void DumpFitsBintable (char *filename, PhotPars *image, int *match, int Nmatch);
+void DumpFitsTable (char *filename, PhotPars *image, int *match, int Nmatch);
+int PrintSubset (PhotPars *image, int *match, int Nmatch);
+int define_table (Header *header, Matrix *matrix, Header *theader, FTable *table);
+void set_timezone (double dt);
+void DumpCADCTable (char *filename, PhotPars *image, int *match, int Nmatch);
Index: /tags/start/Ohana/src/imregister/include/spreg.h
===================================================================
--- /tags/start/Ohana/src/imregister/include/spreg.h	(revision 12606)
+++ /tags/start/Ohana/src/imregister/include/spreg.h	(revision 12606)
@@ -0,0 +1,113 @@
+# include <signal.h>
+
+enum {
+  SPMODE_UKN,				/* unknown mode */
+  SPMODE_PHU,				/* one spectrum, primary header unit */
+  SPMODE_MEF,				/* spectrum group, extensions */
+  SPMODE_EXT,				/* one of a spectrum group, extension */
+  SPMODE_N
+};
+
+enum {
+  SPSTATE_UKN,				/* unknown state */
+  SPSTATE_RAW,				/* raw image counts */
+  SPSTATE_FLT,				/* flattened image counts */
+  SPSTATE_CLN,				/* clean extraction */
+  SPSTATE_WAV,				/* wavelength calibrated */
+  SPSTATE_FLX,				/* flux calibrated (implies WAV) */
+  SPSTATE_N
+};
+
+struct {
+  int Ntimes;           unsigned long *tstart, *tstop;
+  int ModeSelect;       int Mode;
+  int StateSelect;      int State;
+  int ExptimeSelect;    float Exptime;
+  int FilenameSelect;   char *Filename;
+  int ObjectSelect;     char *Object;
+  int TelescopeSelect;  char *Telescope;
+  int InstrumentSelect; char *Instrument;
+  int MatchNumber;
+} criteria;
+
+struct {
+  int delete;
+  int modify;
+
+  int unique;
+  int modify_path;
+  char *oldpath, *newpath;
+
+  int modify_mode, mode;
+  int modify_state, state;
+
+  int HST;
+  int verbose;
+  char *table;
+  char *bintable;
+} output;
+
+typedef struct {
+  int *ccd;
+  int Nccd;
+  char name[64];
+} MosaicRegion;
+
+typedef struct {
+  MosaicRegion center;
+  MosaicRegion outer;
+  MosaicRegion top;
+  MosaicRegion bottom;
+  MosaicRegion left;
+  MosaicRegion right;
+} MosaicLayout;
+
+enum {UNLOCK, LOCK, IGNORE};
+
+int SingleIsSplit;
+int NeedType;
+int NoReg;
+int IMSORT;
+int CLIENT;
+char *PIDFILE;
+int LOOP_DELAY;
+
+char SpectrumDB[64];
+char ObjectKeyword[64];
+char TelescopeKeyword[64];
+
+
+int args (int argc, char **argv);
+Spectrum *get_spectrums (int *N);
+int set_spectrums (Spectrum *new, int Nnew);
+int load_db ();
+int save_db ();
+int update_db (int *match, int Nmatch);
+int append_db (Spectrum *new, int Nnew);
+int create_db ();
+int close_db ();
+void DeleteSubset (int *match, int Nmatch);
+Spectrum *spinfo (char *filename);
+int *match_criteria (int *Nmatch);
+int *match_spectrums (Spectrum *subset, int Nsubset, int *Nmatch);
+void ModifySubset (int *match, int Nmatch);
+void SetOutputMode (char *mode);
+void OutputSubset (int *match, int Nmatch);
+void DumpFitsBintable (char *filename, Spectrum *spectrum, int *match, int Nmatch);
+void DumpFitsTable (char *filename, Spectrum *spectrum, int *match, int Nmatch);
+int PrintSubset (Spectrum *spectrum, int *match, int Nmatch);
+int dump_data (Spectrum *spectrum, int Nspectrum);
+int SubmitSpectrums (Spectrum *spectrum);
+int load_probes (char *filename, unsigned long tzero, int *wantprobe, double *values, int Nprobe);
+int define_table (Header *header, Matrix *matrix, Header *theader, FTable *table);
+void set_timezone (double dt);
+
+void DumpCADCTable (char *filename, Spectrum *spectrum, int *match, int Nmatch);
+int *GetObsIDSubset (Spectrum *spectrum, int start, int *index, int *entry, int Nindex, int *Nsubset);
+int *GetUniqueObsID (Spectrum *spectrum, int *index, int *entry, int Nindex, int *Nmatch);
+void GetObsIDIndex (Spectrum *spectrum, int *match, int Nmatch, int **Index, int **Entry);
+double SigmaClipList (double *list, int N);
+double MosaicIQStats (Spectrum *spectrum, int *match, int Nmatch, MosaicRegion *region);
+MosaicLayout *CreateCFH12K ();
+MosaicLayout *CreateMegaCam ();
+int GetREFCCD (Spectrum *spectrum, int *index, int *entry, int Nindex, int start);
Index: /tags/start/Ohana/src/imregister/spreg/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/imregister/spreg/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/imregister/spreg/ConfigInit.c	(revision 12606)
@@ -0,0 +1,63 @@
+# include "imregister.h"
+# include "spreg.h"
+
+int success;
+
+void ConfigInit (int *argc, char **argv) {
+
+  int i, NDB;
+  char *config, *file, ElixirBase[80];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (0);
+  }
+
+  success = TRUE;
+
+  WarnConfig (config, "SPECTRUM_DATABASE",       "%s", 0, SpectrumDB);
+
+  /* keyword abstractions for parse_time */	   
+  WarnConfig (config, "DATE-KEYWORD",                "%s", 0, DateKeyword);
+  WarnConfig (config, "DATE-MODE",                   "%s", 0, DateMode);
+  WarnConfig (config, "UT-KEYWORD",                  "%s", 0, UTKeyword);
+  WarnConfig (config, "MJD-KEYWORD",                 "%s", 0, MJDKeyword);
+  WarnConfig (config, "JD-KEYWORD",                  "%s", 0, JDKeyword);
+						   
+  /* keyword abstractions for spinfo */		   
+  WarnConfig (config, "EXPTIME-KEYWORD",             "%s", 0, ExptimeKeyword);
+  WarnConfig (config, "AIRMASS-KEYWORD",             "%s", 0, AirmassKeyword);
+  WarnConfig (config, "CAMERA-KEYWORD",              "%s", 0, CameraKeyword);
+  WarnConfig (config, "OBJECT-KEYWORD",              "%s", 0, ObjectKeyword);
+  WarnConfig (config, "TELESCOPE-KEYWORD",           "%s", 0, TelescopeKeyword);
+
+  /* semi-optional values */
+  ScanConfig (config, "RA-DDD-KEYWORD",              "%s", 0, RADecDegKeyword);
+  ScanConfig (config, "DEC-DDD-KEYWORD",             "%s", 0, DECDecDegKeyword);
+  ScanConfig (config, "RA-HMS-KEYWORD",              "%s", 0, RASexigKeyword);
+  ScanConfig (config, "DEC-DMS-KEYWORD",             "%s", 0, DECSexigKeyword);
+  if (!RADecDegKeyword[0] & !DECDecDegKeyword[0] && !RASexigKeyword[0] && !DECSexigKeyword[0]) {
+    fprintf (stderr, "missing astrometry configuration information\n");
+    success = FALSE;
+  }
+
+  if (! success) {
+    fprintf (stderr, "ERROR: problem with elixir configuration\n");
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+
+}
+
+void WarnConfig (char *config, char *key, char * mode, int N, void *var) {
+  if (!ScanConfig (config, key, mode, N, var)) {
+    fprintf (stderr, "missing config variable %s\n", key);
+    success = FALSE;
+  }
+}
Index: /tags/start/Ohana/src/imregister/spreg/args.spregister.c
===================================================================
--- /tags/start/Ohana/src/imregister/spreg/args.spregister.c	(revision 12606)
+++ /tags/start/Ohana/src/imregister/spreg/args.spregister.c	(revision 12606)
@@ -0,0 +1,47 @@
+# include "imregister.h"
+# include "spreg.h"
+
+int args (int argc, char **argv) {
+
+  int N;
+
+  ConfigInit (&argc, argv); /* load elixir config data */
+
+  NoReg = FALSE;
+  if (N = get_argument (argc, argv, "-noreg")) {
+    remove_argument (N, &argc, argv);
+    NoReg = TRUE;
+  }
+
+  output.verbose = FALSE;
+  if (N = get_argument (argc, argv, "-v")) {
+    remove_argument (N, &argc, argv);
+    output.verbose = TRUE;
+  }
+
+  NeedType = FALSE;
+  if (N = get_argument (argc, argv, "-needtype")) {
+    remove_argument (N, &argc, argv);
+    NeedType = TRUE;
+  }
+
+  /* all imregister programs are implicitly modifying the db */
+  output.modify = TRUE;
+  IMSORT = FALSE;
+
+  if (strstr (argv[0], "spregister") != (char *) NULL) {
+    if (argc != 2) {
+      fprintf (stderr, "ERROR: Usage: spregister (filename) [-noreg]\n");
+      exit (1);
+    }
+    return (TRUE);
+  }
+  if (strstr (argv[0], "showspinfo") != (char *) NULL) {
+    if (argc != 2) {
+      fprintf (stderr, "ERROR: Usage: showspinfo (filename)\n");
+      exit (1);
+    }
+    return (TRUE);
+  }
+  return (FALSE);
+}
Index: /tags/start/Ohana/src/imregister/spreg/args.spsearch.c
===================================================================
--- /tags/start/Ohana/src/imregister/spreg/args.spsearch.c	(revision 12606)
+++ /tags/start/Ohana/src/imregister/spreg/args.spsearch.c	(revision 12606)
@@ -0,0 +1,178 @@
+# include "imregister.h" 
+# include "spreg.h"
+
+/* criteria struct is global */
+int args (int argc, char **argv) {
+
+  double dt;
+  int N, i;
+
+  ConfigInit (&argc, argv); /* load elixir config data */
+
+  /* set timezone (set static in misc.c) */
+  if (N = get_argument (argc, argv, "-tz")) {
+    remove_argument (N, &argc, argv);
+    dt = atof (argv[N]);
+    set_timezone (dt);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* define time range */
+  criteria.Ntimes = 0;
+  if (!get_trange_arguments (&argc, argv, &criteria.tstart, &criteria.tstop, &criteria.Ntimes)) {
+    fprintf (stderr, "ERROR: syntax error\n");
+    exit (1);
+  }
+
+  /* exposure time */
+  criteria.ExptimeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-etime")) {
+    remove_argument (N, &argc, argv);
+    criteria.Exptime = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    criteria.ExptimeSelect = TRUE;
+  }
+ 
+  /* image type (dark, flat, bias, etc) */
+  criteria.StateSelect = FALSE;
+
+ 
+  /* image mode (split, mef, single) */
+  criteria.ModeSelect = FALSE;
+  /*
+  criteria.Mode = M_NONE;
+  if (N = get_argument (argc, argv, "-mode")) {
+    remove_argument (N, &argc, argv);
+    for (i = 0; (i < NMODE) && (criteria.Mode == M_NONE); i++) {
+      if (!strncasecmp (argv[N], modename[i], strlen(argv[N]))) criteria.Mode = i;
+    }
+    if (criteria.Mode == M_NONE) {
+      fprintf (stderr, "ERROR: invalid image mode %s\n", argv[N]);
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    criteria.ModeSelect = TRUE;
+  }
+  */
+
+  /* string in image name */
+  criteria.FilenameSelect = FALSE;
+  if (N = get_argument (argc, argv, "-filename")) {
+    remove_argument (N, &argc, argv);
+    criteria.Filename = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    criteria.FilenameSelect = TRUE;
+  }
+
+  /* string in image name */
+  criteria.ObjectSelect = FALSE;
+  if (N = get_argument (argc, argv, "-object")) {
+    remove_argument (N, &argc, argv);
+    criteria.Object = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    criteria.ObjectSelect = TRUE;
+  }
+
+  /* string in image name */
+  criteria.TelescopeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-tel")) {
+    remove_argument (N, &argc, argv);
+    criteria.Telescope = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    criteria.TelescopeSelect = TRUE;
+  }
+
+  /* string in image name */
+  criteria.InstrumentSelect = FALSE;
+  if (N = get_argument (argc, argv, "-inst")) {
+    remove_argument (N, &argc, argv);
+    criteria.Instrument = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    criteria.InstrumentSelect = TRUE;
+  }
+
+  /*** command-line options which modify the output list */
+  if (N = get_argument (argc, argv, "-treg")) {
+    remove_argument (N, &argc, argv);
+    SetOutputMode ("RegTimeMode");
+  }
+  output.table = (char *) NULL;
+  if (N = get_argument (argc, argv, "-table")) {
+    remove_argument (N, &argc, argv);
+    output.table = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  output.bintable = (char *) NULL;
+  if (N = get_argument (argc, argv, "-bintable")) {
+    remove_argument (N, &argc, argv);
+    output.bintable = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /*** command-line options which modify behavior (delete, modify, newpath, mef2split split2mef */
+  output.delete = FALSE;
+  output.modify = FALSE;
+  output.modify_path = FALSE; 
+  output.unique = FALSE;
+
+  if (N = get_argument (argc, argv, "-delete")) {
+    remove_argument (N, &argc, argv);
+    output.delete = TRUE;
+  }
+
+  if (N = get_argument (argc, argv, "-unique")) {
+    remove_argument (N, &argc, argv);
+    output.unique = TRUE;
+  }
+
+  if (N = get_argument (argc, argv, "-modify")) {
+    if (output.delete) { 
+      fprintf (stderr, "can't specify more than one modifier at a time\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    output.modify = TRUE;
+    
+    /* modify part of the path */
+    if (!strcasecmp (argv[N], "path")) {
+      output.modify_path = TRUE;
+      remove_argument (N, &argc, argv);
+      output.oldpath = strcreate (argv[N]);
+      remove_argument (N, &argc, argv);
+      output.newpath = strcreate (argv[N]);
+      remove_argument (N, &argc, argv);
+      goto valid_modify;
+    }
+
+    /* modify distributed status */
+    if (!strcasecmp (argv[N], "mode")) {
+      output.modify_mode = TRUE;
+      remove_argument (N, &argc, argv);
+      output.mode = atoi(argv[N]);
+      remove_argument (N, &argc, argv);
+      goto valid_modify;
+    }
+
+    if (!strcasecmp (argv[N], "help")) {
+      fprintf (stderr, "-modify option: \n");
+      fprintf (stderr, "  -modify path (oldpath) (newpath)\n"); 
+      fprintf (stderr, "  -modify mode (mef | split)\n"); 
+      exit (2);
+    }
+
+    fprintf (stderr, "invalid -modify option, try -modify help\n");
+    exit (1);
+  }
+ valid_modify:
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: imsearch [config ops] \n");
+    fprintf (stderr, "  [-type type] [-mode mode] [-trange start range] [-ccd N]\n");
+    fprintf (stderr, "  [-etime exptime] [-filter name] [-name string] [-proc t/f]\n");
+    fprintf (stderr, "  [-treg] [-seq] [-pt] [-table] [-cadctable] [-bintable]\n");
+    fprintf (stderr, "  [-delete] [-modify (options)]\n");
+    exit (1);
+  }
+
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/imregister/spreg/db.c
===================================================================
--- /tags/start/Ohana/src/imregister/spreg/db.c	(revision 12606)
+++ /tags/start/Ohana/src/imregister/spreg/db.c	(revision 12606)
@@ -0,0 +1,250 @@
+# include "imregister.h"
+# include "spreg.h"
+
+/* variables which describe the db */
+char *dBFile = (char *) NULL;
+FILE *f;
+Header header;
+Header theader;
+Matrix matrix;
+FTable table;
+Spectrum *spectrum;
+int Nspectrum;
+int lockstate;
+int dbstate = LCK_UNLOCK;
+
+/* set the name of the currently active database table 
+   be careful: don't change db without closing old db */
+int set_db (char *filename) {
+  dBFile = filename;
+  return (TRUE);
+}
+
+/* load the complete db table into memory */
+int load_db () {
+
+  int Nx, Ny;
+
+  /* database name must be set first */
+  if (dBFile == (char *) NULL) {
+    fprintf (stderr, "ERROR: db file is not set\n");
+    exit (1);
+  }
+
+  /* set locking state */
+  lockstate = (output.modify || output.delete) ? LCK_HARD : LCK_SOFT;
+  header.buffer = matrix.buffer = theader.buffer = table.buffer = (char *) NULL;
+
+  /* lock & open database */
+  f = fsetlockfile (dBFile, 300.0, lockstate, &dbstate);
+  if (dbstate == LCK_EMPTY) return (0);
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't set lock on %s\n", dBFile);
+    exit (1);
+  }
+
+  /* init & load in FITS table data */
+  table.header = &theader;
+  if (!fits_fread_header (f, &header))                     escape (UNLOCK, "ERROR: can't read primary header"); 
+  if (!fits_fread_matrix (f, &matrix, &header))            escape (UNLOCK, "ERROR: can't read primary matrix");
+  if (!fits_fread_ftable (f, &table, "SPECTRUM_DATABASE")) escape (UNLOCK, "ERROR: can't read table SPECTRUM_DATABASE");
+
+  /* convert to internal format */
+  spectrum = (Spectrum *) table.buffer;
+  fits_scan (table.header, "NAXIS1", "%d", 1, &Nx);
+  fits_scan (table.header, "NAXIS2", "%d", 1, &Ny);
+  Nspectrum = Ny;
+
+  if (!ConvertStruct ((char *) spectrum, sizeof (Spectrum), Nspectrum, "spectrum")) escape (UNLOCK, "ERROR: can't convert to internal format"); 
+  return (TRUE);
+}
+
+/* save complete db file */
+int save_db () {
+
+  if (!ConvertStruct ((char *) spectrum, sizeof (Spectrum), Nspectrum, "spectrum")) escape (UNLOCK, "ERROR: can't convert from native format");
+
+  /* write all spectra to file */
+  make_backup (dBFile);
+  Fseek (f, 0, SEEK_SET);
+  if (!fits_fwrite_header  (f, &header))  escape (LOCK, "ERROR: can't write primary header");
+  if (!fits_fwrite_matrix  (f, &matrix))  escape (LOCK, "ERROR: can't write primary matrix");
+  if (!fits_fwrite_Theader (f, &theader)) escape (LOCK, "ERROR: can't write table header");
+  if (!fits_fwrite_table   (f, &table))   escape (LOCK, "ERROR: can't write table data");
+
+  fits_free_header (&header);
+  fits_free_matrix (&matrix);
+  fits_free_header (&theader);
+  fits_free_table  (&table);
+
+  fclearlockfile (dBFile, f, lockstate, &dbstate);
+  return (TRUE);
+}
+
+/* write selected rows to db file 
+   complete db must already be loaded in memory (table) */
+int update_db (int *match, int Nmatch) {
+
+  int i, N, Nx, Ny;
+  VTable vtable;
+
+  fits_scan (table.header, "NAXIS1", "%d", 1, &Nx);
+  fits_scan (table.header, "NAXIS2", "%d", 1, &Ny);
+
+  /* make empty vtable from table */
+  vtable.header = table.header;
+  vtable.size = table.size;
+  vtable.Nrow = Ny;
+  vtable.pad = vtable.size - Nx*Ny;
+
+  /* insert selected rows in vtable */ 
+  ALLOCATE (vtable.row, int, Nmatch);
+  ALLOCATE (vtable.buffer, char *, Nmatch);
+  for (N = i = 0; i < Nmatch; i++) {
+    if (match[i] == -1) continue;
+    vtable.row[N] = match[i];
+    ALLOCATE (vtable.buffer[N], char, Nx);
+    memcpy (vtable.buffer[N], &spectrum[match[i]], sizeof (Spectrum));
+    ConvertStruct ((char *) vtable.buffer[N], sizeof (Spectrum), 1, "spectrum");
+    N++;
+  }
+  vtable.Nrow = N;
+
+  /* write subset to file */
+  make_backup (dBFile);
+  Fseek (f, 0, SEEK_SET);
+  if (!fits_fwrite_header (f, &header))   escape (LOCK, "ERROR: can't update primary header");
+  if (!fits_fwrite_matrix (f, &matrix))   escape (LOCK, "ERROR: can't update primary matrix");
+  if (!fits_fwrite_Theader (f, &theader)) escape (LOCK, "ERROR: can't update table header");
+  if (!fits_fwrite_vtable   (f, &vtable)) escape (LOCK, "ERROR: can't update table data");
+
+  fits_free_header (&header);
+  fits_free_matrix (&matrix);
+  fits_free_header (&theader);
+  fits_free_vtable (&vtable);
+  fits_free_table  (&table);
+
+  fclearlockfile (dBFile, f, lockstate, &dbstate);
+  return (TRUE);
+}
+
+/* write a row to the end of the existing table 
+   file must be open, but need not be in memory */
+int append_db (Spectrum *new, int Nnew) {
+
+  VTable vtable;
+
+  /* add error checks! */
+  fits_table_to_vtable (&table, &vtable, 0, 0);
+
+  ConvertStruct ((char *) new, sizeof (Spectrum), Nnew, "spectrum");
+  fits_vadd_rows (&vtable, new, Nnew, sizeof(Spectrum));
+
+  /* write subset to file */
+  Fseek (f, 0, SEEK_SET);
+  if (!fits_fwrite_header (f, &header))   escape (LOCK, "ERROR: can't append to db");
+  if (!fits_fwrite_matrix (f, &matrix))   escape (LOCK, "ERROR: can't append to db");
+  if (!fits_fwrite_Theader (f, &theader)) escape (LOCK, "ERROR: can't append to db");
+  if (!fits_fwrite_vtable   (f, &vtable)) escape (LOCK, "ERROR: can't append to db");
+
+  fits_free_header (&header);
+  fits_free_matrix (&matrix);
+  fits_free_header (&theader);
+  fits_free_vtable (&vtable);
+
+  fclearlockfile (dBFile, f, lockstate, &dbstate);
+  return (TRUE);
+}
+
+/* create a new (empty) db table in memory. 
+   dBFile already set with set_db (filename);
+   f already set with load_db () */
+int create_db () {
+
+  /* define table layout */
+  define_table (&header, &matrix, &theader, &table);
+
+  /* convert to internal format */
+  spectrum = (Spectrum *) table.buffer;
+  Nspectrum = 0;
+
+  return (TRUE);
+}
+
+/* close the db files, free header data
+   table data remains alloc'ed */
+int close_db () {
+
+  fits_free_header (&header);
+  fits_free_matrix (&matrix);
+  fits_free_header (&theader);
+
+  if (dbstate == LCK_UNLOCK) return (TRUE);
+  fclearlockfile (dBFile, f, lockstate, &dbstate);
+  return (TRUE);
+}  
+
+/* close the db files, free header data
+   table data remains alloc'ed 
+   clear soft/xcld locks, but keep a hard lock on the db, if it exists */
+int close_lock_db () {
+
+  fits_free_header (&header);
+  fits_free_matrix (&matrix);
+  fits_free_header (&theader);
+
+  if (dbstate == LCK_UNLOCK) return (TRUE);
+  fclearlockfile (dBFile, f, LCK_XCLD, &dbstate);
+  return (TRUE);
+}  
+
+int print_db_status (char *message) {
+
+  int fd;
+
+  if (!output.verbose) return (0);
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "%s - db: %s - fd: %d\n", message, "null", -1);
+    return (0);
+  }
+  fd = fileno (f);
+  fprintf (stderr, "%s - db: %s - fd: %d\n", message, dBFile, fd);
+  return (TRUE);
+}
+
+int escape (int mode, char *message) {
+  
+  if (mode == UNLOCK) close_db ();
+  fprintf (stderr, "%s\n", message);
+  exit (1);
+}
+
+/* return the current table data */
+Spectrum *get_spectra (int *N) {
+  *N = Nspectrum;
+  return (spectrum);
+}
+
+/* set the table to the specified data */
+int set_spectra (Spectrum *new, int Nnew) {
+
+  int Nbytes;
+
+  /* assign pointers to new data block */
+  free (spectrum);
+  Nspectrum = Nnew;
+  spectrum = new;
+
+  /* update header, table structures */
+  fits_modify (table.header, "NAXIS2", "%d", 1, Nnew);
+  table.header[0].Naxis[1] = Nnew;
+  Nbytes = fits_matrix_size (table.header);
+
+  /* add padding space to buffer */
+  REALLOCATE ((char *) spectrum, char, Nbytes);
+  table.buffer = (char *) spectrum;
+  table.size = Nbytes;
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/imregister/spreg/define.c
===================================================================
--- /tags/start/Ohana/src/imregister/spreg/define.c	(revision 12606)
+++ /tags/start/Ohana/src/imregister/spreg/define.c	(revision 12606)
@@ -0,0 +1,44 @@
+# include "imregister.h"
+# include "spreg.h"
+
+int define_table (Header *header, Matrix *matrix, Header *theader, FTable *table) {
+
+  /* create primary header */
+  fits_init_header (header);    
+  header[0].extend = TRUE;
+  fits_create_header (header);
+  fits_create_matrix (header, matrix);
+  fits_print (header, "NEXTEND", "%d", 1, 1);
+    
+  /* define bintable header  layout */
+  fits_create_table_header (theader, "BINTABLE", "SPECTRUM_DATABASE");
+
+  fits_define_bintable_column (theader, "32A",  "FILENAME",   "filename in db",        "",                              1.0, 0.0);
+  fits_define_bintable_column (theader, "64A",  "PATHNAME",   "fullpath in db",        "",                              1.0, 0.0);
+  fits_define_bintable_column (theader, "16A",  "INSTRUMENT", "instrument",            "",                              1.0, 0.0);
+  fits_define_bintable_column (theader, "16A",  "TELESCOPE",  "telescope",             "",                              1.0, 0.0);
+  fits_define_bintable_column (theader, "16A",  "OBJNAME",    "object name",           "",                              1.0, 0.0);
+  fits_define_bintable_column (theader, "16A",  "EXTNAME",    "extname in file",       "",                              1.0, 0.0);
+
+  fits_define_bintable_column (theader, "E",    "RA",         "ra",                    "degrees",                       1.0, 0.0); 
+  fits_define_bintable_column (theader, "E",    "DEC",        "dec",                   "degrees",                       1.0, 0.0); 
+  fits_define_bintable_column (theader, "E",    "EXPTIME",    "exposure time",         "seconds",                       1.0, 0.0); 
+  fits_define_bintable_column (theader, "E",    "AIRMASS",    "airmass",               "",                              1.0, 0.0); 
+  fits_define_bintable_column (theader, "E",    "Ws",         "spectral range start",  "Angstrom",                 	1.0, 0.0); 
+  fits_define_bintable_column (theader, "E",    "We",         "spectral range end",    "Angstrom",                 	1.0, 0.0); 
+  fits_define_bintable_column (theader, "E",    "dW",         "spectral resolution",   "Angstrom / pix",                1.0, 0.0); 
+
+  fits_define_bintable_column (theader, "J",    "NSPECTRA",   "number of spectra",     "",                              1.0, 0.0); 
+  fits_define_bintable_column (theader, "J",    "OBS_TIME",   "time of measurement",   "seconds since Jan 1, 1970 UT",  1.0, 0.0);
+  fits_define_bintable_column (theader, "J",    "REG_TIME",   "time of registration",  "seconds since Jan 1, 1970 UT",  1.0, 0.0);
+
+  fits_define_bintable_column (theader, "A",    "MODE",       "phu/mef/ext",           "",                              1.0, 0.0);
+  fits_define_bintable_column (theader, "A",    "STATE",      "raw/wav/flx/etc",       "",                              1.0, 0.0);
+  fits_define_bintable_column (theader, "A",    "FLAG",       "status flags",          "",                              1.0, 0.0);
+  fits_define_bintable_column (theader, "13A",  "EXTRA",      "room for expansion",    "",                              1.0, 0.0);
+
+  /* create table, add data values */
+  fits_create_table (theader, table);
+
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/imregister/spreg/delete.c
===================================================================
--- /tags/start/Ohana/src/imregister/spreg/delete.c	(revision 12606)
+++ /tags/start/Ohana/src/imregister/spreg/delete.c	(revision 12606)
@@ -0,0 +1,40 @@
+# include "imregister.h"
+# include "spreg.h"
+
+void DeleteSubset (int *match, int Nmatch) {
+
+  int i, j;
+  int *keep, Nbad, Nspectrum, Nsubset;
+  Spectrum *spectrum, *subset;
+
+  spectrum = get_spectra (&Nspectrum);
+
+  ALLOCATE (keep, int, MAX (Nspectrum, 1));
+  for (i = 0; i < Nspectrum; i++) keep[i] = TRUE;
+  fprintf (stderr, "total of %d spectra\n", Nspectrum);
+
+  Nbad = 0;
+  for (i = 0; i < Nmatch; i++) {
+    j = match[i];
+    if (j == -1) continue;
+    keep[j] = FALSE;
+    Nbad ++;
+  }
+  fprintf (stderr, "delete %d spectra\n", Nbad);
+
+  Nsubset = Nspectrum - Nbad;
+  ALLOCATE (subset, Spectrum, MAX (1, Nsubset));
+  fprintf (stderr, "keeping %d spectra\n", Nsubset);
+  for (j = i = 0; i < Nspectrum; i++) {
+    if (!keep[i]) continue;
+    subset[j] = spectrum[i];
+    j++;
+  }
+
+  free (keep);
+  set_spectra (subset, Nsubset);
+
+  save_db ();
+  exit (0);
+
+}
Index: /tags/start/Ohana/src/imregister/spreg/fits_scan_nchar.c
===================================================================
--- /tags/start/Ohana/src/imregister/spreg/fits_scan_nchar.c	(revision 12606)
+++ /tags/start/Ohana/src/imregister/spreg/fits_scan_nchar.c	(revision 12606)
@@ -0,0 +1,23 @@
+# include "imregister.h"
+# include "imreg.h"
+
+/* scan from header into a string of fixed length */
+int fits_scan_nchar (Header *header, int size, char *field, int N,...) {
+
+  char *tmpstr, *outstr; 
+  va_list argp;
+  int status;
+  
+  va_start (argp, N);
+  outstr = va_arg (argp, char *);
+  va_end (argp);
+
+  ALLOCATE (tmpstr, char, size); 
+  status = fits_scan (header, field, "%s", N, tmpstr); 
+  strncpy (outstr, tmpstr, size - 1);
+  outstr[size-1] = 0; 
+
+  free (tmpstr); 
+  return (status);
+} 
+     
Index: /tags/start/Ohana/src/imregister/spreg/match.c
===================================================================
--- /tags/start/Ohana/src/imregister/spreg/match.c	(revision 12606)
+++ /tags/start/Ohana/src/imregister/spreg/match.c	(revision 12606)
@@ -0,0 +1,84 @@
+# include "imregister.h"
+# include "spreg.h"
+
+int *match_criteria (int *Nmatch) {
+
+  int i, j, Nspectrum;
+  int N, NMATCH;
+  int *match;
+  int reject;
+  int Nfilename, Nobject, Ntelescope, Ninstrument;
+  Spectrum *spectrum;
+
+  /* create selection index */
+  N = 0;
+  NMATCH = 1000;
+  ALLOCATE (match, int, NMATCH);
+
+  if (criteria.FilenameSelect) Nfilename     = strlen (criteria.Filename);
+  if (criteria.ObjectSelect) Nobject         = strlen (criteria.Object);
+  if (criteria.TelescopeSelect) Ntelescope   = strlen (criteria.Telescope);
+  if (criteria.InstrumentSelect) Ninstrument = strlen (criteria.Instrument);
+
+  spectrum = get_spectra (&Nspectrum);
+
+  /* find entries that matches criteria */
+  for (i = 0; i < Nspectrum; i++) {
+    for (j = 0, reject = TRUE; reject && (j < criteria.Ntimes); j++) {
+      reject = (spectrum[i].obstime + spectrum[i].exptime < criteria.tstart[j]) || (spectrum[i].obstime > criteria.tstop[j]);
+    }
+    if (criteria.Ntimes && reject) continue;
+    if (criteria.ModeSelect    && (spectrum[i].mode  != criteria.Mode)) continue;
+    if (criteria.StateSelect   && (spectrum[i].state != criteria.State)) continue;
+
+    if (criteria.ExptimeSelect && (fabs (spectrum[i].exptime - criteria.Exptime) > 5.0)) continue;
+
+    if (criteria.FilenameSelect   && (strncasecmp (spectrum[i].filename, criteria.Filename, Nfilename))) continue;
+    if (criteria.ObjectSelect     && (strncasecmp (spectrum[i].objname, criteria.Object, Nobject))) continue;
+    if (criteria.TelescopeSelect  && (strncasecmp (spectrum[i].telescope, criteria.Telescope, Ntelescope))) continue;
+    if (criteria.InstrumentSelect && (strncasecmp (spectrum[i].instrument, criteria.Instrument, Ninstrument))) continue;
+
+    match[N] = i;
+    N ++;
+    if (N == NMATCH) {
+      NMATCH += 1000;
+      REALLOCATE (match, int, NMATCH);
+    }
+  }
+  *Nmatch = N;
+  return (match);
+}
+
+int *match_spectra (Spectrum *subset, int Nsubset, int *Nmatch) {
+  
+  int i, j, N, Nspectrum, Nfound;
+  int *match;
+  Spectrum *spectrum;
+
+  spectrum = get_spectra (&Nspectrum);
+
+  /* find matching spectra - very inefficient : sort by obstime, find those first? */
+  ALLOCATE (match, int, Nsubset);
+  for (j = 0; j < Nsubset; j++) {
+    match[j] = -1;
+    for (i = 0; (match[j] == -1) && (i < Nspectrum); i++) {
+      if (spectrum[i].obstime > subset[j].obstime + 1) continue;
+      if (spectrum[i].obstime < subset[j].obstime - 1) continue;
+      match[j] = i;
+    }
+  }
+  
+  Nfound = 0;
+  for (i = 0; i < Nsubset; i++) {
+    /* set the new values for this spectrum */
+    N = match[i];
+    if (N == -1) continue;
+    spectrum[N].ra   = subset[i].ra; 
+    spectrum[N].dec  = subset[i].dec; 
+    /* if the spectrum is MEF, these were not correctly assigned by imsort.
+       this step uses the values from the split ccd spectrum */
+    Nfound ++;
+  }
+  *Nmatch = Nfound;
+  return (match);
+}
Index: /tags/start/Ohana/src/imregister/spreg/modify.c
===================================================================
--- /tags/start/Ohana/src/imregister/spreg/modify.c	(revision 12606)
+++ /tags/start/Ohana/src/imregister/spreg/modify.c	(revision 12606)
@@ -0,0 +1,45 @@
+# include "imregister.h"
+# include "spreg.h"
+
+void ModifySubset (int *match, int Nmatch) {
+
+  int i, j, Nold;
+  char *tmppath;
+  char *ext, *root, *path;
+  int Nspectrum;
+  Spectrum *spectrum;
+
+  spectrum = get_spectra (&Nspectrum);
+
+  /* create some necessary variables */
+  if (output.modify_path) { 
+    Nold = strlen (output.oldpath);
+    ALLOCATE (tmppath, char, 128);
+  }
+
+  /* modify the selected entries */
+  for (j = 0; j < Nmatch; j++) {
+
+    i = match[j];
+
+    if (output.modify_path) {
+      if (!strncmp (spectrum[i].pathname, output.oldpath, Nold)) {
+	strcpy (tmppath, &spectrum[i].pathname[Nold]);
+	snprintf (spectrum[i].pathname, 128, "%s%s", output.newpath, tmppath);
+      }
+    }
+
+    if (output.modify_mode) {
+      spectrum[i].mode = output.mode;
+    }
+
+    if (output.modify_state) {
+      spectrum[i].state = output.state;
+    }
+  }
+
+  update_db (match, Nmatch);
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+
+}
Index: /tags/start/Ohana/src/imregister/spreg/output.c
===================================================================
--- /tags/start/Ohana/src/imregister/spreg/output.c	(revision 12606)
+++ /tags/start/Ohana/src/imregister/spreg/output.c	(revision 12606)
@@ -0,0 +1,182 @@
+# include "imregister.h"
+# include "spreg.h"
+
+static int RegTimeMode = FALSE;
+static int PTstyle = FALSE;
+
+void SetOutputMode (char *mode) {
+
+  if (!strcmp (mode, "RegTimeMode")) {
+    RegTimeMode = TRUE;
+    return;
+  }
+  if (!strcmp (mode, "PTstyle")) {
+    PTstyle = TRUE;
+    return;
+  }
+
+}
+
+/* given a subset list, write out the selected spectra, if desired */
+void OutputSubset (int *match, int Nmatch) {
+
+  int Nspectrum;
+  Spectrum *spectrum;
+
+  spectrum = get_spectra (&Nspectrum);
+
+  if (output.table != (char *) NULL) {
+    DumpFitsTable (output.table, spectrum, match, Nmatch);
+  } 
+
+  if (output.bintable != (char *) NULL) {
+    DumpFitsBintable (output.bintable, spectrum, match, Nmatch);
+  } 
+
+  PrintSubset (spectrum, match, Nmatch);
+  exit (0);
+}
+
+/* write out complete binary FITS table in format of db */
+void DumpFitsBintable (char *filename, Spectrum *spectrum, int *match, int Nmatch) {
+
+  int i, j, Nx;
+  Header header, theader;
+  Matrix matrix;
+  FTable table;
+  Spectrum *subset;
+
+  /* define table layout */
+  define_table (&header, &matrix, &theader, &table);
+
+  ALLOCATE (subset, Spectrum, MAX (1, Nmatch));
+  for (i = 0; i < Nmatch; i++){
+    j = match[i];
+    memcpy (&subset[i], &spectrum[j], sizeof (Spectrum));
+  }
+  ConvertStruct ((char *) subset, sizeof (Spectrum), Nmatch, "spectrum");
+  fits_add_rows (&table, subset, Nmatch, sizeof (Spectrum));
+
+  fits_write_header  (filename, &header);
+  fits_write_matrix  (filename, &matrix);
+  fits_write_Theader (filename, &theader);
+  fits_write_table   (filename, &table);
+  exit (0);
+}
+
+void DumpFitsTable (char *filename, Spectrum *spectrum, int *match, int Nmatch) {
+  
+  int i;
+  char *obsstr, *regstr, *line, dummy[64];
+  char *modestr, *typestr, *ccdstr, *datestr;
+  unsigned long tsecond;
+  Header header, theader;
+  Matrix matrix;
+  FTable table;
+  Spectrum *subset;
+
+  bzero (dummy, 64);
+  memset (dummy, ' ', 63);
+
+  /* create primary header */
+  fits_init_header (&header);    
+  header.extend = TRUE;
+  fits_create_header (&header);
+  fits_create_matrix (&header, &matrix);
+  fits_print (&header, "NEXTEND", "%d", 1, 1);
+  
+  /* create table header */
+  fits_create_table_header (&theader, "TABLE", "SPECTRUM_DATABASE");
+      
+  /* add current date/time to header */
+  str_to_time ("now", &tsecond);
+  datestr = sec_to_date (tsecond);
+  fits_modify (&header,  "DATE", "%s", 1, datestr);
+  fits_modify (&theader, "DATE", "%s", 1, datestr);
+
+  /* define table layout */
+  fits_define_table_column (&theader, "A32",  "FILENAME",   "filename in db",        "",                              1.0, 0.0);
+  fits_define_table_column (&theader, "A64",  "PATHNAME",   "fullpath in db",        "",                              1.0, 0.0);
+  fits_define_table_column (&theader, "A16",  "INSTRUMENT", "instrument",            "",                              1.0, 0.0);
+  fits_define_table_column (&theader, "A16",  "TELESCOPE",  "telescope",             "",                              1.0, 0.0);
+  fits_define_table_column (&theader, "A16",  "OBJNAME",    "object name",           "",                              1.0, 0.0);
+  fits_define_table_column (&theader, "A16",  "EXTNAME",    "extname in file",       "",                              1.0, 0.0);
+
+  fits_define_table_column (&theader, "F10.6","RA",         "ra",                    "degrees",                       1.0, 0.0); 
+  fits_define_table_column (&theader, "F10.6","DEC",        "dec",                   "degrees",                       1.0, 0.0); 
+  fits_define_table_column (&theader, "F6.1", "EXPTIME",    "exposure time",         "seconds",                       1.0, 0.0); 
+  fits_define_table_column (&theader, "F5.3", "AIRMASS",    "airmass",               "",                              1.0, 0.0); 
+  fits_define_table_column (&theader, "F7.2", "Ws",         "spectral range start",  "Angstrom",                      1.0, 0.0); 
+  fits_define_table_column (&theader, "F7.2", "We",         "spectral range end",    "Angstrom",                      1.0, 0.0); 
+  fits_define_table_column (&theader, "F7.2", "dW",         "spectral resolution",   "Angstrom / pix",                1.0, 0.0); 
+
+  fits_define_table_column (&theader, "I3",   "NSPECTRA",   "number of spectra",     "",                              1.0, 0.0); 
+  fits_define_table_column (&theader, "A20",  "OBS_TIME",   "time of observation",   "yyyy/mm/dd,hh:mm:ss");
+  fits_define_table_column (&theader, "A20",  "REG_TIME",   "time of registration",  "yyyy/mm/dd,hh:mm:ss");
+
+  fits_define_table_column (&theader, "I2",   "MODE",       "phu/mef/ext",           "",                              1.0, 0.0);
+  fits_define_table_column (&theader, "I2",   "STATE",      "raw/wav/flx/etc",       "",                              1.0, 0.0);
+  fits_define_table_column (&theader, "I3",   "FLAG",       "status flags",          "",                              1.0, 0.0);
+
+  /* create table, add data values */
+  fits_create_table (&theader, &table);
+  
+  /* add data to table */
+  for (i = 0; i < Nmatch; i++) {
+    subset = &spectrum[match[i]];
+    obsstr   = sec_to_date (subset[0].obstime);
+    regstr   = sec_to_date (subset[0].regtime);
+
+    line = fits_table_print (&table, subset[0].filename, subset[0].pathname, subset[0].instrument, 
+			     subset[0].telescope, subset[0].objname, subset[0].extname, 
+			     subset[0].ra, subset[0].dec, subset[0].exptime, subset[0].airmass, 
+			     subset[0].Ws, subset[0].We, subset[0].dW, 
+			     subset[0].Nspec, obsstr, regstr,
+			     subset[0].mode, subset[0].state, subset[0].flag);
+
+    fits_add_rows (&table, line, 1, strlen(line));
+    free (line);
+    free (obsstr);
+    free (regstr);
+  }
+
+  fits_write_header  (filename, &header);
+  fits_write_matrix  (filename, &matrix);
+  fits_write_Theader (filename, &theader);
+  fits_write_table   (filename, &table);
+  exit (0);
+}
+
+/* Select, TimeMode are global */
+int PrintSubset (Spectrum *spectrum, int *match, int Nmatch) {
+  
+  int i, j;
+  char *timestr;
+
+  /* print the selected entries */
+  for (j = 0; j < Nmatch; j++) {
+    i = match[j];
+    
+    timestr = RegTimeMode ? sec_to_date (spectrum[i].regtime) : sec_to_date (spectrum[i].obstime);
+
+    /* predefined subset of values */
+    fprintf (stdout, "%5d %20s %s %s %s %s ", i, timestr, spectrum[i].pathname, spectrum[i].filename, spectrum[i].objname, spectrum[i].telescope);
+    fprintf (stdout, "%5.1f %5.3f %.1f %.1f %.2f\n", spectrum[i].exptime, spectrum[i].airmass, spectrum[i].Ws, spectrum[i].We, spectrum[i].dW);
+
+    free (timestr);
+  }
+  return (TRUE);
+}
+
+int dump_data (Spectrum *spectrum, int Nspectrum) {
+
+  int i;
+
+  for (i = 0; i < Nspectrum; i++) {
+    fprintf (stdout, "%s %s %f %f %f %f\n", spectrum[i].filename, spectrum[i].objname, spectrum[i].exptime, spectrum[i].airmass, spectrum[i].Ws, spectrum[i].We);
+  }
+
+  fprintf (stdout, "SUCCESS\n");
+  exit (0);
+
+}
Index: /tags/start/Ohana/src/imregister/spreg/spinfo.c
===================================================================
--- /tags/start/Ohana/src/imregister/spreg/spinfo.c	(revision 12606)
+++ /tags/start/Ohana/src/imregister/spreg/spinfo.c	(revision 12606)
@@ -0,0 +1,99 @@
+# include "imregister.h"
+# include "spreg.h"
+
+Spectrum *spinfo (char *filename) {
+
+  Spectrum *spectrum;
+  Header header;
+  int Naxes, Nextend;
+  char Imagetype[80], line[80];
+  struct timeval now;
+  char *name, *cwd, *tempname;
+  double tmp;
+  float *dtime;
+
+  ALLOCATE (spectrum, Spectrum, 1);
+  bzero (spectrum, sizeof (Spectrum));
+
+  /* load in FITS header from image */
+  if (!fits_read_header (filename, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s\n", filename);
+    exit (1);
+  }
+
+  /* get filename */
+  name = filebasename (filename);
+  snprintf (spectrum[0].filename, 32, "%s", name);
+  free (name);
+
+  /* get pathname (add cwd if not absolute) */
+  name = pathname (filename);
+  if (name[0] != '/') {
+    cwd = getcwd (NULL, 64 - strlen(name) - 2);
+    if (cwd == (char *) NULL) {
+      cwd = strcreate ("longpath");
+      /* pathname is limited to 64 chars.  if it is toolong, 
+	 we put in the word 'longpath'.  no other useful solution. */
+    }
+    ALLOCATE (tempname, char, strlen (cwd) + strlen (name) + 2);
+    if (!strcmp (name, ".")) {
+      sprintf (tempname, "%s", cwd);
+    } else {
+      sprintf (tempname, "%s/%s", cwd, name);
+    }      
+    free (name);
+    free (cwd);
+    name = tempname;
+  }    
+  snprintf (spectrum[0].pathname, 64, "%s", name);
+  free (name);
+
+  /* find the important header keyword values */
+  spectrum[0].obstime = parse_time (&header);
+
+  gettimeofday (&now, (void *) NULL);
+  spectrum[0].regtime = now.tv_sec;
+
+  fits_scan_nchar (&header, 15, ObjectKeyword,    1, spectrum[0].objname);
+  fits_scan_nchar (&header, 15, CameraKeyword,    1, spectrum[0].instrument);
+  fits_scan_nchar (&header, 15, TelescopeKeyword, 1, spectrum[0].telescope);
+
+  fits_scan (&header, ExptimeKeyword,    "%f", 1, &spectrum[0].exptime);
+  fits_scan (&header, AirmassKeyword,    "%f", 1, &spectrum[0].airmass);
+
+  /* grab coordinates from header */
+  if (RADecDegKeyword[0] & DECDecDegKeyword[0]) {
+    /* expect RA & DEC in decimal degrees */
+    fits_scan (&header, RADecDegKeyword,  "%f", 1, &spectrum[0].ra);
+    fits_scan (&header, DECDecDegKeyword, "%f", 1, &spectrum[0].dec);
+  } else {
+    if (RASexigKeyword[0] & DECSexigKeyword[0]) {
+      /* expect RA & DEC in hh:mm:ss, dd:mm:ss */
+      fits_scan (&header, RASexigKeyword,  "%s", 1, line);
+      dms_to_ddd (&tmp, line);
+      spectrum[0].ra = 15*tmp;
+      fits_scan (&header, DECSexigKeyword, "%s", 1, &line);
+      dms_to_ddd (&tmp, line);
+      spectrum[0].dec = tmp;
+    }
+  }
+
+  /* for now we will not try to determine the mode, state, or 
+     wavelength ranges from the header.  set these with -modify
+     or on the command line on insert.  later on, we can add the logic */
+  
+  spectrum[0].mode  = SPMODE_UKN;
+  spectrum[0].state = SPSTATE_UKN;
+  spectrum[0].Nspec = 1;
+  spectrum[0].flag  = 0;
+  
+  spectrum[0].Ws = 0;
+  spectrum[0].We = 0;
+  spectrum[0].dW = 0;
+  
+  strcpy (spectrum[0].extname, "PHU");
+  
+  return (spectrum);
+
+}
+
Index: /tags/start/Ohana/src/imregister/spreg/submit.c
===================================================================
--- /tags/start/Ohana/src/imregister/spreg/submit.c	(revision 12606)
+++ /tags/start/Ohana/src/imregister/spreg/submit.c	(revision 12606)
@@ -0,0 +1,64 @@
+# include "imregister.h"
+# include "spreg.h"
+
+int SubmitImages (RegImage *image) {
+
+  int i;
+  char line[1024], *root, *path;
+
+  /* send these images to FIFOs for imstat and ptolemy */ 
+
+  /* image[0].ccd contains:
+     MEF    : Nccd
+     SPLIT  : ccd number
+     CUBE   : Nslice
+     SLICE  : slice number
+     SINGLE : 0
+  */
+
+  if (image[0].mode == M_MEF) {
+    for (i = 0; i < image[0].ccd; i++) {
+      root = filerootname (image[0].filename);
+      if (i < Nccd) {
+	sprintf (line, "%s/%s %s/%s%s %s %s", image[0].pathname, image[0].filename, root, root, ccdn[i], ccds[i], "MEF");
+      } else {
+	sprintf (line, "%s/%s %s/%sxx none %s", image[0].pathname, image[0].filename, root, root, "MEF");
+      }
+      if (!WriteFIFO (ImstatFifo, line)) return (FALSE);
+      if (image[0].type == T_OBJECT) {
+	if (!WriteFIFO (PtolemyFifo, line)) return (FALSE);
+      }
+    }
+  } 
+
+  if (image[0].mode == M_SINGLE) {
+    root = filerootname (image[0].filename);
+    sprintf (line, "%s/%s %s %02d %s", image[0].pathname, image[0].filename, root, 0, "SINGLE");
+    if (!WriteFIFO (ImstatFifo, line)) return (FALSE);
+    if (image[0].type == T_OBJECT) {
+      if (!WriteFIFO (PtolemyFifo, line)) return (FALSE);
+    }
+  } 
+
+  if (image[0].mode == M_CUBE) {
+    root = filerootname (image[0].filename);
+    sprintf (line, "%s/%s %s %02d %s", image[0].pathname, image[0].filename, root, 0, "CUBE");
+    if (!WriteFIFO (ImstatFifo, line)) return (FALSE);
+    if (image[0].type == T_OBJECT) {
+      if (!WriteFIFO (PtolemyFifo, line)) return (FALSE);
+    }
+  } 
+
+  if (image[0].mode == M_SPLIT) {
+    path = basename (image[0].pathname);
+    root = filerootname (image[0].filename);
+    sprintf (line, "%s/%s %s/%s %02d %s", image[0].pathname, image[0].filename, path, root, image[0].ccd, "SPLIT");
+    if (!WriteFIFO (ImstatFifo, line)) return (FALSE);
+    if (image[0].type == T_OBJECT) {
+      if (!WriteFIFO (PtolemyFifo, line)) return (FALSE);
+    }
+  }    
+
+  return (TRUE);
+}
+  
Index: /tags/start/Ohana/src/imregister/spreg/unique.c
===================================================================
--- /tags/start/Ohana/src/imregister/spreg/unique.c	(revision 12606)
+++ /tags/start/Ohana/src/imregister/spreg/unique.c	(revision 12606)
@@ -0,0 +1,60 @@
+# include "imregister.h"
+# include "spreg.h"
+
+/* input is a subset index of spectrum list, output is a new subset */
+int *unique_entries (int *subset, int *Nmatch) {
+
+  int i, j, k, m, Nspectrum, Nsubset;
+  int N, NMATCH;
+  int *match, *entry;
+  int reject;
+  Spectrum *spectrum;
+  char idxline[128];
+  char **index;
+
+  if (!output.unique) return (subset);
+
+  /* create output index */
+  N = 0;
+  NMATCH = 1000;
+  ALLOCATE (match, int, NMATCH);
+
+  Nsubset = *Nmatch;
+  spectrum = get_spectra (&Nspectrum);
+
+  /* index = filename */
+  ALLOCATE (index, char *, Nsubset);
+  ALLOCATE (entry, int, Nsubset);
+  for (i = 0; i < Nsubset; i++) {
+    sprintf (idxline, "%s", spectrum[subset[i]].filename);
+    index[i] = strcreate (idxline);
+    entry[i] = subset[i];
+  }
+  sortstr (index, entry, Nsubset);
+
+  /* find unique sequences */
+  for (i = 0; i < Nsubset; ) {
+    for (j = i + 1; (j < Nsubset) && (!strcmp (index[i], index[j])); j++);
+    m = i;
+    
+    /* add unique entry to output list */
+    match[N] = entry[m];
+    N ++;
+    if (N == NMATCH) {
+      NMATCH += 1000;
+      REALLOCATE (match, int, NMATCH);
+    }
+
+    /* j always points to the next entry */
+    i = j;
+  }
+
+  for (i = 0; i < Nsubset; i++) free (index[i]);
+  free (index);
+  free (entry);
+  free (subset);
+
+  *Nmatch = N;
+  return (match);
+}
+
Index: /tags/start/Ohana/src/imregister/src/notes.txt
===================================================================
--- /tags/start/Ohana/src/imregister/src/notes.txt	(revision 12606)
+++ /tags/start/Ohana/src/imregister/src/notes.txt	(revision 12606)
@@ -0,0 +1,58 @@
+
+metadata to extract:
+
+typedef struct {
+  char filename[64];
+  char pathname[128];
+  char instrument[32];
+  char telescope[32];
+  char objname[64];
+  char extname[64];
+
+  float ra, dec;
+  float exptime;
+  float airmass;
+
+  float W0, W1, dW;
+  int Nspec;				/* number of spectra associated with entry */
+
+  char mode;			/* PHU, MEF, EXT */
+  char state;			/* image state: raw, flx, etc */
+  char flag;			/* image status flags */
+  char junk[9];
+
+  unsigned long int obstime;
+  unsigned long int regtime;
+} Spectrum;
+
+
+FITS Keywords for metadata
+
+case 1:
+NAXIS  = 1
+NAXIS1 = Nw
+
+case 2:
+NAXIS  = 2
+NAXIS1 = Nw
+NAXIS2 = 1
+
+case 3:
+NAXIS  = 2
+NAXIS1 = 1
+NAXIS2 = Nw
+
+case 4:
+NAXIS  = 2
+NAXIS1 = Nw
+NAXIS2 = n   (flux, dflux, etc)
+
+case 5:
+NAXIS  = 3
+NAXIS1 = Nw
+NAXIS2 = 1
+NAXIS3 = n   (flux, dflux, etc)
+
+0         1         2         3         4         5         6         7         8
+012345678901234567890123456789012345678901234567890123456789012345678901234567890
+/data/elixir2/datdir/megacam/03Am02/taurus/L1551/VLT/spectra/2002.04.01
Index: /tags/start/Ohana/src/imregister/src/spregister.c
===================================================================
--- /tags/start/Ohana/src/imregister/src/spregister.c	(revision 12606)
+++ /tags/start/Ohana/src/imregister/src/spregister.c	(revision 12606)
@@ -0,0 +1,32 @@
+# include "imregister.h"
+# include "spreg.h"
+static char *version = "spregister $Revision: 1.1.1.1 $";
+
+int main (int argc, char **argv) {
+ 
+  Spectrum *spectrum, *pspectrum;
+  int i, status, Nnew;
+  float *dtime;
+
+  get_version (argc, argv, version);
+  args (argc, argv);
+  spectrum = spinfo (argv[1]);
+
+  Nnew = 1;
+  pspectrum = &spectrum[0];
+
+  if (NoReg) exit (0);
+
+  set_db (SpectrumDB);
+  status = load_db ();
+  if (!status) {
+    create_db ();
+  }
+  append_db (pspectrum, Nnew);
+}
+
+
+/* notes:
+   SpectrumDB set in args:ConfigInit by config variable SPECTRUM_DB
+
+*/
Index: /tags/start/Ohana/src/imregister/src/spsearch.c
===================================================================
--- /tags/start/Ohana/src/imregister/src/spsearch.c	(revision 12606)
+++ /tags/start/Ohana/src/imregister/src/spsearch.c	(revision 12606)
@@ -0,0 +1,63 @@
+# include "imregister.h"
+# include "spreg.h"
+static char *version = "imsearch $Revision: 1.1.1.1 $";
+
+int main (int argc, char **argv) {
+ 
+  int status, Nmatch;
+  int *match;
+
+  get_version (argc, argv, version);
+  args (argc, argv);
+
+  set_db (SpectrumDB);
+
+  status = load_db ();
+  if (!status) {
+    close_db ();
+    exit (0);
+  }
+  if (!output.modify && !output.delete) close_db ();
+  
+  match = match_criteria (&Nmatch);
+  match = unique_entries (match, &Nmatch);
+
+  if (output.modify) ModifySubset (match, Nmatch);
+  if (output.delete) DeleteSubset (match, Nmatch);
+
+  OutputSubset (match, Nmatch);
+
+  exit (0);
+}
+
+/* 
+
+FITS table version:
+
+   load_db - open, read in database, store as RegImage structure
+   match   - return index 'match' to matched images
+   modify  - change value of selected images
+             write out subset of rows
+   delete  - remove selected images from image structure
+             write out entire table
+   output  - write out subset in various formats
+
+   get_images returns pointer to complete image structure
+
+
+SQL version:
+
+   load_db - set up connection
+   match   - convert criteria to SQL where clause and do:
+             'select from images [where clause]'
+             images structure is filled with result from query
+   modify  - change value of subset selection (identical)
+             update selected rows
+   delete  - user where clause and do 
+             'delete from images where clause'
+   output  - (identical)
+
+   get_images returns pointer to image subset from query
+   match[i] = i
+
+*/
Index: /tags/start/Ohana/src/kapa/Makefile
===================================================================
--- /tags/start/Ohana/src/kapa/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/kapa/Makefile	(revision 12606)
@@ -0,0 +1,109 @@
+include ../../Configure
+HOME 	=	$(ROOT)/src/kapa
+PROGRAM =       kapa
+
+default: $(PROGRAM)
+CC      =       gcc -g
+
+INC	=	$(HOME)/include
+BIN	=	$(HOME)/bin
+BDIR	=	$(HOME)/button
+CDIR	=	$(HOME)/colorbar
+EDIR	=	$(HOME)/event
+MDIR	=	$(HOME)/misc
+ODIR	=	$(HOME)/overlay
+PDIR	=	$(HOME)/picture
+GDIR	=	$(HOME)/graph
+SDIR	=	$(HOME)/setup
+ZDIR	=	$(HOME)/zoom
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+#
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+#LIBS	= 	-L$(LLIB) $(XLIB) -lFITS -lohana -lX11 -lm
+LIBS	= 	-L$(LLIB) $(XLIB) -lFITS -lohana -lX11 -lsocket -lnsl -lpng -lz -lm
+CFLAGS  =	-o $*.$(ARCH).o $(INCS) 
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+# local source / object files ########################
+BOBJ = \
+$(BDIR)/ButtonFunctions.$(ARCH).o         $(BDIR)/InButton.$(ARCH).o           \
+$(BDIR)/CheckButtons.$(ARCH).o     	  $(BDIR)/InPicture.$(ARCH).o          \
+$(BDIR)/DrawButton.$(ARCH).o       	  $(BDIR)/InvertButton.$(ARCH).o       \
+$(BDIR)/FlashButton.$(ARCH).o      	  $(BDIR)/PSit.$(ARCH).o               \
+$(SDIR)/DrawBitmap.$(ARCH).o               
+
+EOBJ = \
+$(EDIR)/CheckPipe.$(ARCH).o               $(EDIR)/Stop.$(ARCH).o               \
+$(EDIR)/EventLoop.$(ARCH).o         	  $(EDIR)/Reconfig.$(ARCH).o           \
+$(EDIR)/SetFont.$(ARCH).o           	  $(EDIR)/PositionPicture.$(ARCH).o\
+$(EDIR)/InterpretKeys.$(ARCH).o     	  $(EDIR)/Refresh.$(ARCH).o		\
+$(EDIR)/SetSection.$(ARCH).o		  $(EDIR)/FlushDisplay.$(ARCH).o	\
+$(EDIR)/Resize.$(ARCH).o
+
+GOBJ = \
+$(GDIR)/DrawObjects.$(ARCH).o             $(GDIR)/DrawFrame.$(ARCH).o       	\
+$(GDIR)/DrawText.$(ARCH).o		  $(GDIR)/LoadObject.$(ARCH).o		\
+$(GDIR)/ErasePlot.$(ARCH).o		  $(GDIR)/LoadBox.$(ARCH).o		\
+$(GDIR)/SetLimits.$(ARCH).o               $(GDIR)/PSObjects.$(ARCH).o		\
+$(GDIR)/DrawLabels.$(ARCH).o              $(GDIR)/LoadLabels.$(ARCH).o		\
+$(GDIR)/cursor.$(ARCH).o 		  $(GDIR)/PSFrame.$(ARCH).o		\
+$(GDIR)/LoadPtext.$(ARCH).o		  $(GDIR)/DrawPtext.$(ARCH).o		\
+$(GDIR)/PSLabels.$(ARCH).o		  $(GDIR)/PSPtext.$(ARCH).o		\
+$(GDIR)/DrawRotString.$(ARCH).o        	  $(GDIR)/PNGit.$(ARCH).o \
+$(GDIR)/PPMit.$(ARCH).o
+
+SOBJ = \
+$(SDIR)/CheckColors.$(ARCH).o             $(SDIR)/MakeGC.$(ARCH).o             \
+$(SDIR)/CheckDisplayName.$(ARCH).o  	  $(SDIR)/MapWindow.$(ARCH).o          \
+$(SDIR)/CheckFontName.$(ARCH).o     	  $(SDIR)/NameWindow.$(ARCH).o         \
+$(SDIR)/CheckGeometry.$(ARCH).o     	  $(SDIR)/OpenDisplay.$(ARCH).o        \
+$(SDIR)/CloseDisplay.$(ARCH).o      	  $(SDIR)/QuitX.$(ARCH).o              \
+$(SDIR)/CreateWindow.$(ARCH).o      	  $(SDIR)/SetNormalHints.$(ARCH).o     \
+$(SDIR)/DefineLayout.$(ARCH).o      	  $(SDIR)/SetUpDisplay.$(ARCH).o       \
+$(SDIR)/SetUpWindow.$(ARCH).o        						\
+$(SDIR)/GetColor.$(ARCH).o          	  $(SDIR)/SetWMHints.$(ARCH).o         \
+$(SDIR)/LoadFont.$(ARCH).o          	  $(SDIR)/TopWindow.$(ARCH).o          \
+$(SDIR)/MakeColormap.$(ARCH).o      	  $(SDIR)/Ximage.$(ARCH).o             \
+$(SDIR)/MakeCursor.$(ARCH).o
+
+OBJ  =  $(EOBJ) $(GOBJ) $(MOBJ) $(SOBJ) 
+
+# dependancy rules for include files ########################
+$(OBJ): $(INC)/Ximage.h \
+	$(INC)/constants.h \
+	$(INC)/structures.h \
+	$(INC)/prototypes.h
+
+#### nothing program-dependant below ####
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+dist: clean
+	rm -f */*.*.o
+	rm -f $(BIN)/$(PROGRAM).*
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
+
+
Index: /tags/start/Ohana/src/kapa/event/CheckPipe.c
===================================================================
--- /tags/start/Ohana/src/kapa/event/CheckPipe.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/event/CheckPipe.c	(revision 12606)
@@ -0,0 +1,145 @@
+# include "Ximage.h"
+# define STRCONST(A) ((int)(0x1000000*A[0] + 0x10000*A[1] + 0x100*A[2] + 0x1*A[3]))
+
+int CheckPipe () {
+
+  int status;
+  char buffer[32];
+
+  /***** read (4 byte) message word from socket ****/
+  status = read (sock, buffer, 4);
+  buffer[4] = 0;
+  switch (status) {
+  case -1:                          /* no input from pipe: continue */
+    return (TRUE);
+    break;
+
+  case 0:
+    fprintf (stderr, "pipe has died!\n");
+    return (FALSE);
+    break;
+
+  case 4:
+    break;
+
+  default:
+    fprintf (stderr, "weird signal: too many or few bytes!  %d\n", status);
+    return (TRUE);
+    break;
+  }
+  
+  /***** handle different messages ****/
+  if (!strcmp (buffer, "QUIT")) return (FALSE);
+  
+  if (!strcmp (buffer, "PSIT")) {
+    status = PSit (SCALE);
+    write (sock, "DONE", 4);
+    return (status);
+  }
+  
+  if (!strcmp (buffer, "PSRW")) {
+    status = PSit (RAW);
+    write (sock, "DONE", 4);
+    return (status);
+  }
+  
+  if (!strcmp (buffer, "PSNS")) {
+    status = PSit (NOSCALE);
+    write (sock, "DONE", 4);
+    return (status);
+  }
+  
+  if (!strcmp (buffer, "PNGF")) {
+    status = PNGit ();
+    write (sock, "DONE", 4);
+    return (status);
+  }
+  
+  if (!strcmp (buffer, "PPMF")) {
+    status = PPMit ();
+    write (sock, "DONE", 4);
+    return (status);
+  }
+  
+  if (!strcmp (buffer, "RSIZ")) {
+    status = Resize ();
+    return (status);
+  }
+
+  if (!strcmp (buffer, "PLOT")) {
+    status = LoadObject ();
+    return (status);
+  }
+  
+  if (!strcmp (buffer, "LIMS")) {
+    sprintf (buffer, "LIMS: %8.1f %8.1f \0", 
+	     section[TheSection].axis[0].dfx, section[TheSection].axis[1].dfy);
+    write (sock, buffer, 30);
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "SLIM")) {
+    status = SetLimits ();
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "LABL")) {
+    status = LoadLabels ();
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "LSEC")) {
+    status = ListSection ();
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "DSEC")) {
+    status = SetSection (FALSE);
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "SSEC")) {
+    status = SetSection (TRUE);
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "PTXT")) {
+    status = LoadPtext ();
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "FONT")) {
+    status = SetFont ();
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "CURS")) {
+    cursor ();
+    return (TRUE);
+  }
+  
+  /* Erase Section */
+  if (!strcmp (buffer, "ERAS")) {
+    status = ErasePlot (TRUE);
+    return (status);
+  }
+  
+  /* Don't Erase Section */
+  if (!strcmp (buffer, "ERSS")) {
+    status = ErasePlot (FALSE);
+    return (status);
+  }
+  
+  if (!strcmp (buffer, "DBOX")) {
+    status = LoadBox ();
+    return (status);
+  }
+  
+  fprintf (stderr, "unknown signal %s\n", buffer);
+
+  return (TRUE);
+
+}
+
+
+    
Index: /tags/start/Ohana/src/kapa/event/EventLoop.c
===================================================================
--- /tags/start/Ohana/src/kapa/event/EventLoop.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/event/EventLoop.c	(revision 12606)
@@ -0,0 +1,62 @@
+# include "Ximage.h"
+# define EventMask (long) (KeyPressMask | ExposureMask | StructureNotifyMask)
+# define EMask (long) (KeyPressMask | ExposureMask | StructureNotifyMask | PointerMotionMask)
+
+int EventLoop () {
+  
+  XEvent          event, reconfig_event;
+  int             status, Ne;
+  int  NeedRefresh, NeedReconfig;
+  
+  Refresh (1);
+
+  NeedReconfig = FALSE;
+  NeedRefresh = FALSE;
+  status = TRUE;
+  while (status) {
+
+    if (!CheckPipe ()) return (FALSE);
+
+    if (XEventsQueued (graphic.display, QueuedAfterFlush) < 1) {
+      if (NeedReconfig) status = Reconfig (&reconfig_event);
+      if (NeedRefresh && !NeedReconfig) Refresh (1);
+      NeedRefresh = FALSE;
+      NeedReconfig = FALSE;
+      usleep (10000);
+      continue;
+    }
+
+    if (XCheckMaskEvent (graphic.display, EVENT_MASK, &event)) {
+
+      switch (event.type)  {
+
+      case MotionNotify:
+	break;
+
+      case Expose:
+	if (HAVE_BACKING) continue;
+	NeedRefresh = TRUE;
+	break;
+	
+      case ConfigureNotify:
+	/* Ne = XEventsQueued (graphic.display, QueuedAlready); */
+	reconfig_event = event;
+	NeedReconfig = TRUE;
+	break;
+	
+      case KeyPress:
+	status = InterpretKeys (&event);
+	break;
+
+      case MappingNotify:
+	if (XEventsQueued (graphic.display, QueuedAlready) < 2) {
+	  XRefreshKeyboardMapping ((XMappingEvent *) &event);
+	}
+	break;
+	
+      }
+    }
+  }
+  return (status);
+}
+
Index: /tags/start/Ohana/src/kapa/event/FlushDisplay.c
===================================================================
--- /tags/start/Ohana/src/kapa/event/FlushDisplay.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/event/FlushDisplay.c	(revision 12606)
@@ -0,0 +1,32 @@
+# include "Ximage.h"
+
+static struct timeval reftime; 
+static char reftimeset = FALSE;
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+
+void FlushDisplay () {
+
+  struct timeval now;
+  int flush;
+  double dtime;
+
+  flush = FALSE;
+  if (!reftimeset) {
+    flush = TRUE;
+    gettimeofday (&reftime, (struct timeval *) NULL);
+  } 
+
+  gettimeofday (&now, (struct timeval *) NULL);
+  dtime = DTIME (now, reftime);
+
+  if (dtime > 0.1) {
+    flush = TRUE;
+  }
+
+  if (flush) {
+    XFlush (graphic.display);
+    reftime = now;
+  }
+
+}
+
Index: /tags/start/Ohana/src/kapa/event/InterpretKeys.c
===================================================================
--- /tags/start/Ohana/src/kapa/event/InterpretKeys.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/event/InterpretKeys.c	(revision 12606)
@@ -0,0 +1,20 @@
+# include "Ximage.h"
+
+int InterpretKeys (XEvent *event) {
+
+  int    status;
+  KeySym keysym;
+  char            string[10];
+  XComposeStatus  composestatus;
+
+  XLookupString ((XKeyEvent *)event, string, 9, &keysym, &composestatus);
+
+  switch (keysym) {
+
+  default:
+    status = TRUE;
+  }
+
+  return (status);
+
+}
Index: /tags/start/Ohana/src/kapa/event/InterpretPresses.c
===================================================================
--- /tags/start/Ohana/src/kapa/event/InterpretPresses.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/event/InterpretPresses.c	(revision 12606)
@@ -0,0 +1,57 @@
+# include "Ximage.h"
+
+int 
+InterpretPresses (graphic, layout, event)
+Graphic        graphic[];
+Layout         layout[];
+XButtonEvent   event[];
+{
+
+  int             status, done, this_button, x, y, old_cursor;
+  KeySym          keysym;
+  Button         *button;
+
+  status = TRUE;
+  this_button = event[0].button;
+  
+  if ((event[0].type == ButtonPress) && InPicture (event, &layout[0].picture)) {
+    Reorient (graphic, layout, event);
+  }
+
+  if ((event[0].type == ButtonPress) && InPicture (event, &layout[0].cmapbar)) {
+    DragColorbar (graphic, layout, event);
+  }
+
+  /* if on an exisiting button, Invert, wait for release, then go (or not) */
+  if ((button = CheckButtons (event, layout)) != (Button *) NULL) {
+    InvertButton (graphic, button); 
+    done = FALSE;
+    while (!done) { /* wait for release of this button */
+      XNextEvent (graphic[0].display, (XEvent *) event);
+      if ((event[0].type == ButtonRelease) && (event[0].button == this_button)) {
+	done = TRUE;
+      }
+    }
+    DrawButton (graphic, button);
+    if (InButton (event, button)) {
+      switch (event[0].button) {
+      case 1:
+	status = button[0].function_1(graphic, layout);
+	break;
+      case 2:
+	status = button[0].function_2(graphic, layout);
+	break;
+      case 3:
+	status = button[0].function_3(graphic, layout);
+	break;
+      }
+    }
+    else {
+      return (status);
+    }
+  }
+
+  return (status);
+
+}
+
Index: /tags/start/Ohana/src/kapa/event/PositionPicture.c
===================================================================
--- /tags/start/Ohana/src/kapa/event/PositionPicture.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/event/PositionPicture.c	(revision 12606)
@@ -0,0 +1,95 @@
+# include "Ximage.h"
+
+void PositionPicture (Layout *layout) {
+
+  int fontsize, bump, Nc;
+  double PADx, PADy, Dx, Dy, dPx, dPy;
+  double PXm, PXp, PYm, PYp;
+  double X0, Y0, dX, dY;
+  char string[64], *fontname;
+
+  fontname = GetRotFont (&fontsize);
+
+  /* window has outer bounding box with margins Wx, Wy 
+     section commands subdivide the internal box (Dx,Dy)
+   */
+
+  PADx = MAX (graphic.dx / 20.0, fontsize);
+  PADy = MAX (graphic.dy / 20.0, fontsize);
+  Dx = graphic.dx - 2*PADx;
+  Dy = graphic.dy - 2*PADy;
+
+  /* each graph has a padding PXm, PXp, PYm, PYp */
+  PXm = (layout[0].axis[1].islabel) ? 4*fontsize : 0;
+  PXp = (layout[0].axis[3].islabel) ? 4*fontsize : 0;
+  PYm = (layout[0].axis[0].islabel) ? 4*fontsize : 0;
+  PYp = (layout[0].axis[2].islabel) ? 4*fontsize : 0;
+ 
+  X0 = PADx + PXm + (Dx * layout[0].x);
+  Y0 = PADy + PYm + (Dy * layout[0].y);
+  dX = (Dx * layout[0].dx) - PXp - PXm;
+  dY = (Dy * layout[0].dy) - PYp - PYm;
+
+  /* define locations of coordinate axes */
+  layout[0].axis[0].fx  = X0;
+  layout[0].axis[0].fy  = graphic.dy - Y0;
+  layout[0].axis[0].dfx = dX;
+  layout[0].axis[0].dfy = 0;
+  
+  layout[0].axis[1].fx  = X0;
+  layout[0].axis[1].fy  = graphic.dy - Y0;
+  layout[0].axis[1].dfx = 0;
+  layout[0].axis[1].dfy = -dY;
+
+  layout[0].axis[2].fx  = X0;
+  layout[0].axis[2].fy  = graphic.dy - Y0 - dY;
+  layout[0].axis[2].dfx = dX;
+  layout[0].axis[2].dfy = 0;
+
+  layout[0].axis[3].fx  = X0 + dX;
+  layout[0].axis[3].fy  = graphic.dy - Y0;
+  layout[0].axis[3].dfx = 0;
+  layout[0].axis[3].dfy = -dY;
+
+  PADx = 0.8*fontsize + 2;
+  PADy = 3.0*fontsize + 4;
+
+  /* define locations of axis labels */
+  layout[0].label[LABELX0].x = layout[0].axis[0].fx + 0.5*layout[0].axis[0].dfx;
+  bump = (layout[0].axis[0].islabel) ? PADy : PADx;
+  layout[0].label[LABELX0].y = layout[0].axis[0].fy + bump;
+
+  layout[0].label[LABELX1].x = layout[0].axis[2].fx + 0.5*layout[0].axis[2].dfx;
+  bump = (layout[0].axis[2].islabel) ? PADy : PADx;
+  layout[0].label[LABELX1].y = layout[0].axis[2].fy - bump;
+
+  sprintf (string, "%4g\0", layout[0].axis[1].min);
+  Nc = strlen (string);
+  sprintf (string, "%4g\0", layout[0].axis[1].max);
+  Nc = MAX (Nc, strlen (string));
+
+  layout[0].label[LABELY0].y = layout[0].axis[1].fy + 0.5*layout[0].axis[1].dfy;
+  bump = (layout[0].axis[1].islabel) ? (0.8*Nc*fontsize + 1) : PADx;
+  layout[0].label[LABELY0].x = layout[0].axis[1].fx - bump;
+
+  sprintf (string, "%4g\0", layout[0].axis[1].min);
+  Nc = strlen (string);
+  sprintf (string, "%4g\0", layout[0].axis[1].max);
+  Nc = MAX (Nc, strlen (string));
+
+  layout[0].label[LABELY1].y = layout[0].axis[3].fy + 0.5*layout[0].axis[3].dfy;
+  bump = (layout[0].axis[3].islabel) ? (0.8*Nc*fontsize + 1) : PADx;
+  layout[0].label[LABELY1].x = layout[0].axis[3].fx + bump;
+  
+  /* these are wrong and have to be adjusted to sit in the corners */
+
+  layout[0].label[LABELUL].x = layout[0].axis[2].fx - PADx;
+  layout[0].label[LABELUL].y = layout[0].axis[2].fy - PADx;
+  layout[0].label[LABELUR].x = layout[0].axis[2].fx + layout[0].axis[2].dfx + PADx;
+  layout[0].label[LABELUR].y = layout[0].axis[2].fy - PADx;
+  layout[0].label[LABELLL].x = layout[0].axis[0].fx - PADx;
+  layout[0].label[LABELLL].y = layout[0].axis[0].fy + PADx;
+  layout[0].label[LABELLR].x = layout[0].axis[0].fx + layout[0].axis[0].dfx + PADx;
+  layout[0].label[LABELLR].y = layout[0].axis[0].fy + PADx;
+
+}
Index: /tags/start/Ohana/src/kapa/event/Reconfig.c
===================================================================
--- /tags/start/Ohana/src/kapa/event/Reconfig.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/event/Reconfig.c	(revision 12606)
@@ -0,0 +1,24 @@
+# include "Ximage.h"
+
+int Reconfig (XEvent *event) {
+
+  int i;
+
+  if ((graphic.dx == event[0].xconfigure.width) &&
+      (graphic.dy == event[0].xconfigure.height)) 
+    return (TRUE);
+
+  graphic.dx = MAX(event[0].xconfigure.width,  MIN_WIDTH); 
+  graphic.dy = MAX(event[0].xconfigure.height, MIN_HEIGHT);
+
+  for (i = 0; i < Nsection; i++) {
+    PositionPicture (&section[i]);
+  }
+
+  XClearWindow (graphic.display, graphic.window);
+
+  Refresh (1);
+
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/kapa/event/Refresh.c
===================================================================
--- /tags/start/Ohana/src/kapa/event/Refresh.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/event/Refresh.c	(revision 12606)
@@ -0,0 +1,23 @@
+# include "Ximage.h"
+
+void Refresh (int mode) {
+
+  int i;
+
+  
+  /* XClearWindow   (graphic.display, graphic.window); */
+  XSetForeground (graphic.display, graphic.gc, graphic.back);
+  XFillRectangle (graphic.display, graphic.window, graphic.gc, 0, 0, graphic.dx, graphic.dy);
+  XSetForeground (graphic.display, graphic.gc, graphic.fore);
+  
+  for (i = 0; i < Nsection; i++) {
+    DrawFrame   (&section[i]);
+    DrawObjects (&section[i]);
+    DrawLabels  (&section[i]);
+    DrawPtext   (&section[i]);
+  }
+
+  FlushDisplay ();
+ 
+}
+
Index: /tags/start/Ohana/src/kapa/event/Resize.c
===================================================================
--- /tags/start/Ohana/src/kapa/event/Resize.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/event/Resize.c	(revision 12606)
@@ -0,0 +1,36 @@
+# include "Ximage.h"
+# define SCAN \
+  status = read (sock, buffer, 16); \
+  buffer[16] = 0; \
+  sscanf (buffer, "%*s %d", &Nbytes); \
+  status = read (sock, buffer, Nbytes); \
+  buffer[status] = 0; /* make the string easy to parse */ \
+  (DEBUG) && fprintf (stderr, "buffer: <%s>\n", buffer); \
+
+
+int Resize () {
+ 
+  int i, status, Nbytes;
+  unsigned int NX, NY;
+  char buffer[128];
+
+  SCAN;
+  sscanf (buffer, "%d %d", &NX, &NY);
+
+  if ((graphic.dx == NX) && (graphic.dy == NY)) 
+    return (TRUE);
+
+  graphic.dx = MAX(NX, 50); 
+  graphic.dy = MAX(NY, 50); 
+
+  XResizeWindow (graphic.display, graphic.window, NX, NY);
+
+  for (i = 0; i < Nsection; i++) {
+    PositionPicture (&section[i]);
+  }
+
+  XClearWindow (graphic.display, graphic.window);
+  Refresh (1);
+
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/kapa/event/SetFont.c
===================================================================
--- /tags/start/Ohana/src/kapa/event/SetFont.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/event/SetFont.c	(revision 12606)
@@ -0,0 +1,30 @@
+# include "Ximage.h"
+
+int SetFont () {
+  
+  char buffer[256], name[64];
+  int status, size;
+  
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+  status = read (sock, buffer, 16); 
+  buffer[16] = 0; 
+  sscanf (buffer, "%s", name);
+  
+  status = read (sock, buffer, 16); 
+  buffer[16] = 0; 
+  sscanf (buffer, "%d", &size);
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+  
+  SetRotFont (name, size);
+  
+  return (TRUE);
+  
+}
+
+/*
+  layout[0].X = 0;
+  layout[0].Y = 0;
+  layout[0].expand = 1;
+  */
+
+
Index: /tags/start/Ohana/src/kapa/event/SetSection.c
===================================================================
--- /tags/start/Ohana/src/kapa/event/SetSection.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/event/SetSection.c	(revision 12606)
@@ -0,0 +1,127 @@
+# include "Ximage.h"
+# define SCAN \
+status = read (sock, buffer, 16); \
+buffer[16] = 0; \
+sscanf (buffer, "%*s %d", &Nbytes); \
+status = read (sock, buffer, Nbytes); \
+buffer[status] = 0;
+
+int SetSection (int SwitchSection) {
+  
+  int i, status, Nbytes, NewSection, ThisSection, MoveSection;
+  char buffer[128], name[128];
+  double x, y, dx, dy;
+
+  SCAN;
+
+  if (SwitchSection) {
+    sscanf (buffer, "%s", name);
+  } else {
+    sscanf (buffer, "%s %lf %lf %lf %lf", 
+	    name, &x, &y, &dx, &dy);
+  }    
+
+  NewSection = FALSE;
+  MoveSection = FALSE;
+  ThisSection = -1;
+  for (i = 0; i < Nsection; i++) {
+    if (!strcmp (name, section[i].name)) {
+      ThisSection = i;
+      break;
+    }
+  }
+
+  if (ThisSection == -1) {
+    if (SwitchSection) {
+      fprintf (stderr, "section %s not found\n", name);
+      return (TRUE);
+    }
+    NewSection = TRUE;
+    Nsection ++;
+    REALLOCATE (section, Layout, Nsection);
+    ThisSection = Nsection - 1;
+    strcpy (section[ThisSection].name, name);
+    section[ThisSection].Nobjects = 0;
+    section[ThisSection].Nptext = 0;
+    ALLOCATE (section[ThisSection].objects, Gobjects, 1);  /* allocate so later free will not crash! */
+    section[ThisSection].objects[0].x   = section[ThisSection].objects[0].y   = section[ThisSection].objects[0].z = (float *) NULL;
+    section[ThisSection].objects[0].dxm = section[ThisSection].objects[0].dxp = (float *) NULL;
+    section[ThisSection].objects[0].dym = section[ThisSection].objects[0].dyp = (float *) NULL;
+    ALLOCATE (section[ThisSection].ptext, Label, 1);       /* allocate so later free will not crash! */
+    for (i = 0; i < 4; i++) {
+      section[ThisSection].axis[i].min = 0;
+      section[ThisSection].axis[i].max = 1;
+      section[ThisSection].axis[i].isaxis = FALSE;
+      section[ThisSection].axis[i].areticks = FALSE;
+      section[ThisSection].axis[i].islabel = FALSE;
+      strcpy (section[ThisSection].axis[i].label, "");
+    }    
+    for (i = 0; i < 8; i++) {
+      strcpy (section[ThisSection].label[i].text, "");
+    }
+  }
+
+  if (!SwitchSection) {
+    if (!NewSection && (section[ThisSection].x != x)) MoveSection = TRUE;
+    section[ThisSection].x = x;
+    if (!NewSection && (section[ThisSection].y != y)) MoveSection = TRUE;
+    section[ThisSection].y = y;
+    if (!NewSection && (section[ThisSection].dx != dx)) MoveSection = TRUE;
+    section[ThisSection].dx = dx;
+    if (!NewSection && (section[ThisSection].dy != dy)) MoveSection = TRUE;
+    section[ThisSection].dy = dy;
+
+    if (NewSection || MoveSection) {
+      PositionPicture (&section[ThisSection]);
+    }
+
+    if (MoveSection) {
+      XClearWindow (graphic.display, graphic.window);
+      Refresh (1);
+    } 
+    if (NewSection) {
+    }      
+  }
+
+  TheSection = ThisSection;
+
+  return (TRUE);
+  
+}
+
+int ListSection () {
+  
+  int i, status, Nbytes, NewSection, ThisSection, MoveSection;
+  char buffer[128], name[128];
+  double x, y, dx, dy;
+
+  SCAN;
+
+  sscanf (buffer, "%s", name);
+
+  if (!strcmp (name, "*")) {
+    for (i = 0; i < Nsection; i++) {
+      fprintf (stderr, "%s: %6.3f %6.3f %6.3f %6.3f\n", 
+	       section[i].name, section[i].x, section[i].y, section[i].dx, section[i].dy);
+    }
+    return (TRUE);
+  }
+
+  ThisSection = -1;
+  for (i = 0; i < Nsection; i++) {
+    if (!strcmp (name, section[i].name)) {
+      ThisSection = i;
+      break;
+    }
+  }
+  if (ThisSection == -1) {
+    fprintf (stderr, "section %s not found\n", name);
+    return (TRUE);
+  }
+
+  fprintf (stderr, "%s: %6.3f %6.3f %6.3f %6.3f\n", 
+	   section[ThisSection].name, 
+	   section[ThisSection].x, section[ThisSection].y, 
+	   section[ThisSection].dx, section[ThisSection].dy);
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/kapa/event/Stop.c
===================================================================
--- /tags/start/Ohana/src/kapa/event/Stop.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/event/Stop.c	(revision 12606)
@@ -0,0 +1,8 @@
+# include "Ximage.h"
+
+int Stop () {
+  return (FALSE);
+}
+
+/******  this function looks stupid, but it has to be like this:
+  it is called as a pointer to function **/
Index: /tags/start/Ohana/src/kapa/graph/DrawFrame.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/DrawFrame.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/DrawFrame.c	(revision 12606)
@@ -0,0 +1,159 @@
+# include "Ximage.h"
+# define DrawLine(X,Y,DX,DY) (XDrawLine (graphic.display, graphic.window, graphic.gc, (int)(X), (int)(Y), (int)(X+DX), (int)(Y+DY)))
+  
+void DrawFrame (Layout *layout) {
+  
+  int i, fx, fy, dfx, dfy, P, IsLabel;
+  double range, major, minor, first, next;
+
+  /* each axis is drawn independently, but ticks and labels are placed according to
+     perpendicular distance. */
+  for (i = 0; i < 4; i++) {
+    fx = layout[0].axis[i].fx;
+    fy = layout[0].axis[i].fy;
+    dfx = layout[0].axis[i].dfx;
+    dfy = layout[0].axis[i].dfy;
+    P = hypot ((double)layout[0].axis[(i+1)%2].dfx, (double)layout[0].axis[(i+1)%2].dfy);
+
+    if (layout[0].axis[i].isaxis) {
+      DrawLine (fx, fy, dfx, dfy);
+    }
+    
+    if (layout[0].axis[i].areticks) {
+      range = layout[0].axis[i].max - layout[0].axis[i].min;
+      AxisTickScale (&layout[0].axis[i], &major, &minor);
+
+      first = minor*((int)(layout[0].axis[i].min/minor));
+      if ((range > 0) && (first < layout[0].axis[i].min)) {
+	first += minor;
+      }
+      if ((range < 0) && (first > layout[0].axis[i].min)) {
+	first -= minor;
+      }
+      for (next = first; ((range > 0) && (next <= layout[0].axis[i].max)) || ((range < 0) && (next >= layout[0].axis[i].max));) {
+	IsLabel = FALSE;
+	if ((fabs((int)(next/major) - (next/major)) < 0.5*(minor/major)) || 
+	    (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)) ||
+	    (fabs ((int)((next - 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)))
+	  IsLabel = layout[0].axis[i].islabel;
+	DrawTick (fx, fy, dfx, dfy, P, layout[0].axis[i].min, layout[0].axis[i].max, next, IsLabel, i);
+	if (range > 0) 
+	  next += minor;
+	else 
+	  next -= minor;
+      }
+    }
+  }
+}
+
+DrawTick (int fx, int fy, int dfx, int dfy, 
+	  int P, double min, double max, 
+	  double value, int mode, int naxis) {
+  
+  int x, y, dx, dy, pos, dir, fontsize;
+  double tmp, size, n;
+  char string[64], *fontname;
+
+  if (mode) { 
+    size = MAX (0.02, 7.0 / P); 
+  } else {
+    size = MAX (0.01, 4.0 / P); 
+  }
+  
+  n = P / sqrt ((double)(dfx*dfx + dfy*dfy));
+  x = fx + (value-min)*dfx/(max - min);
+  y = fy + (value-min)*dfy/(max - min);
+
+  dir = 1;
+  if ((naxis == 0) || (naxis == 1)) dir = -1;
+
+  dx = dir*size*dfy*n;	
+  dy = dir*size*dfx*n;
+  
+  DrawLine (x, y, dx, dy);
+
+# ifdef IN_AND_OUT_TICKS
+# define GAP 0.03
+# else
+# define GAP 0.01
+# endif
+
+  if (mode == 1) {
+    fontname = GetRotFont (&fontsize);
+    
+    /* temporarily assume rectilinear axes */
+    if (naxis == 0) { dx = 0; dy = +(0.8*fontsize + 1); pos = 1; }
+    if (naxis == 2) { dx = 0; dy = -(0.8*fontsize + 1); pos = 7; }
+
+    if (naxis == 1) { dy = 0; dx = -(0.8*fontsize + 1); pos = 3; }
+    if (naxis == 3) { dy = 0; dx = +(0.8*fontsize + 1); pos = 5; }
+
+    x = fx + (value-min)*dfx/(max - min) + dx;
+    y = fy + (value-min)*dfy/(max - min) + dy;
+    if (fabs(value/(max-min)) < 0.001) { value = 0.0; }
+    sprintf (string, "%4g\0", value);
+    DrawRotText (x, y, string, pos, 0.0);
+  }
+  
+}
+
+
+AxisTickScale (Axis *axis, double *major, double *minor) {
+
+  double range, lrange, factor, mantis, fmantis, power;
+
+  range = axis[0].max - axis[0].min;
+
+  lrange = log10(MAX(fabs(range), 1e-30));
+  mantis = modf (lrange, &factor);
+  if (mantis < 0.0) {
+    mantis += 1.0;
+    factor -= 1.0;
+  }
+  
+  power = pow(10.0, factor);
+  fmantis = pow(10.0, mantis);
+  *major = 0.5 * power;
+  *minor = 0.1 * power;
+  
+  if ((fmantis >= 1.0) && (fmantis <  1.999)) {
+    *major = 0.5 * power;
+    *minor = 0.1 * power;
+    if (axis[0].areticks == 1) {
+      *major = 1.0 * power;
+      *minor = 0.2 * power;
+    }	  
+  }
+  if ((fmantis >= 1.999) && (fmantis <  3.999)) {
+    *major = 1.0 * power;
+    *minor = 0.2 * power;
+    if (axis[0].areticks == 1) {
+      *major = 2.0 * power;
+      *minor = 0.5 * power;
+    }	  
+  }
+  if ((fmantis >= 3.999) && (fmantis <  5.999)) {
+    *major = 1.0 * power;
+    *minor = 0.5 * power;
+    if (axis[0].areticks == 1) {
+      *major = 2.0 * power;
+      *minor = 0.5 * power;
+    }	  
+  }
+  if ((fmantis >= 5.999) && (fmantis <   7.999)) {
+    *major = 2.0 * power;
+    *minor = 0.5 * power;
+    if (axis[0].areticks == 1) {
+      *major = 2.5 * power;
+      *minor = 0.5 * power;
+    }	  
+  }
+  if ((fmantis >= 7.999) && (fmantis <  10.000)) {
+    *major = 2.5 * power;
+    *minor = 0.5 * power;
+    if (axis[0].areticks == 1) {
+      *major = 5.0 * power;
+      *minor = 1.0 * power;
+    }	  
+  }
+}
Index: /tags/start/Ohana/src/kapa/graph/DrawLabels.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/DrawLabels.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/DrawLabels.c	(revision 12606)
@@ -0,0 +1,55 @@
+# include "Ximage.h"
+  
+void DrawLabels (Layout *layout) {
+  
+  int i, pos, x, y, size;
+  double angle;
+  char *fontname;
+
+  fontname = GetRotFont (&size);
+  XSetForeground (graphic.display, graphic.gc, graphic.fore);
+
+  /* each label is drawn independently */
+  for (i = 0; i < 8; i++) {
+    if (strcmp (layout[0].label[i].text, "")) {
+      angle = 0;
+      switch (i) {
+      case 0: pos = 7; break;
+      case 1: pos = 1; angle = -90; break;
+      case 2: pos = 1; break;
+      case 3: pos = 1; angle =  90; break;
+      case 4: pos = 2; break;
+      case 5: pos = 0; break;
+      case 6: pos = 8; break;
+      case 7: pos = 6; break;
+      }	
+      x = layout[0].label[i].x;
+      y = layout[0].label[i].y;
+      SetRotFont (layout[0].label[i].font, layout[0].label[i].size);
+      DrawRotText (x, y, layout[0].label[i].text, pos, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+  /*
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|       |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+          
+ 6____7___8 
+  |       | 
+  |       | 
+ 3|   4   |5
+  |       |
+  |       |
+  ---------
+  0   1   2
+
+  */
Index: /tags/start/Ohana/src/kapa/graph/DrawObjects.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/DrawObjects.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/DrawObjects.c	(revision 12606)
@@ -0,0 +1,616 @@
+# include "Ximage.h"
+# define DrawLine(X1,Y1,X2,Y2) (XDrawLine (graphic.display, graphic.window, graphic.gc, (int)(X1+0.5), (int)(Y1+0.5), (int)(X2+0.5), (int)(Y2+0.5)))
+# define DrawRectangle(X1,Y1,X2,Y2) (XDrawRectangle (graphic.display, graphic.window, graphic.gc, (int)(X1+0.5), (int)(Y1+0.5), (int)(X2+0.5), (int)(Y2+0.5)))
+# define FillRectangle(X1,Y1,X2,Y2) (XFillRectangle (graphic.display, graphic.window, graphic.gc, (int)(X1+0.5), (int)(Y1+0.5), (int)(X2+0.5), (int)(Y2+0.5)))
+# define DrawCircle(X,Y,R) (XDrawArc (graphic.display, graphic.window, graphic.gc, (int)(X-R+0.5), (int)(Y-R+0.5), abs(2*R+0.5), abs(2*R+0.5), 0, 23040))
+
+# define CONNECT 0
+# define HISTOGRAM 1
+# define POINTS 2
+
+void ClipLine (double x0, double y0, double x1, double y1, double X0, double Y0, double X1, double Y1);
+
+/* draw all objects for this Layout */
+int DrawObjects (Layout *layout) {
+  
+  int i;
+  
+  for (i = 0; i < layout[0].Nobjects; i++) {
+    if (DEBUG) fprintf (stderr, "object: %d\n", i);
+    if (DEBUG) fprintf (stderr, "Npts: %d\n", layout[0].objects[i].Npts);
+    DrawObjectN (layout, &layout[0].objects[i]);
+  }    
+
+}
+
+/* Draw a specific object in the layout */
+int DrawObjectN (Layout *layout, Gobjects *object) {
+  
+  static unsigned char dash[2] = {5,10};
+  static unsigned char dot[2] = {3,3};
+  int ltype, lweight;
+  
+  lweight = MAX (0, MIN (10, object[0].lweight));
+
+  /* set line type */
+  switch (object[0].ltype) {
+  case 0:
+    XSetLineAttributes (graphic.display, graphic.gc, lweight, LineSolid, CapNotLast, JoinMiter);
+    break;
+  case 1:
+    XSetDashes (graphic.display, graphic.gc, 100, dash, 2);
+    XSetLineAttributes (graphic.display, graphic.gc, lweight, LineOnOffDash, CapNotLast, JoinMiter);
+    break;
+  case 2:
+    XSetDashes (graphic.display, graphic.gc, 10, dot, 2);
+    XSetLineAttributes (graphic.display, graphic.gc, lweight, LineOnOffDash, CapNotLast, JoinMiter);
+    break;
+  default:
+    XSetLineAttributes (graphic.display, graphic.gc, lweight, LineSolid, CapNotLast, JoinMiter);
+    break;
+  }
+
+  XSetForeground (graphic.display, graphic.gc, graphic.color[object[0].color]);
+
+  switch (object[0].style) {
+  case CONNECT: 
+    DrawConnect (layout, object);
+    break;
+  case HISTOGRAM:
+    DrawHistogram (layout, object);
+    break;
+  case POINTS:
+    DrawPoints (layout, object);
+    break;
+  }
+    
+  if (object[0].etype & 0x01) {
+    DrawYErrors (layout, object);
+  }
+  if (object[0].etype & 0x02) {
+    DrawXErrors (layout, object);
+  }
+
+  XSetLineAttributes (graphic.display, graphic.gc, 0, LineSolid, CapNotLast, JoinMiter);
+  XSetForeground (graphic.display, graphic.gc, graphic.fore);
+}
+
+/******/
+void DrawConnect (Layout *layout, Gobjects *object) {
+  
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1;
+  double X0, X1, Y0, Y1;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = layout[0].axis[0].fx;
+  X1 = layout[0].axis[0].fx + layout[0].axis[0].dfx;
+  Y0 = layout[0].axis[1].fy;
+  Y1 = layout[0].axis[1].fy + layout[0].axis[1].dfy;
+
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    
+    ClipLine (sx0, sy0, sx1, sy1, X0, Y0, X1, Y1);
+    /* DrawLine (sx0, sy0, sx1, sy1); */
+    sx0 = sx1; sy0 = sy1;
+  }
+  
+}
+
+void ClipLine (double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0) {
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x0,y0 if outside box */
+  if ((x0 < X0) && (x1 >= X0)) {
+    y0 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X0;
+  }
+  if ((x0 > X1) && (x1 <= X1)) {
+    y0 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X1;
+  }
+  if ((y0 < Y0) && (y1 >= Y0)) {
+    x0 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y0;
+  }
+  if ((y0 > Y1) && (y1 <= Y1)) {
+    x0 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y1;
+  }
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x1,y1 if outside box */
+  if ((x1 < X0) && (x0 >= X0)) {
+    y1 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X0;
+  }
+  if ((x1 > X1) && (x0 <= X1)) {
+    y1 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X1;
+  }
+  if ((y1 < Y0) && (y0 >= Y0)) {
+    x1 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y0;
+  }
+  if ((y1 > Y1) && (y0 <= Y1)) {
+    x1 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y1;
+  }
+  DrawLine (x0, y0, x1, y1);
+}
+  
+
+/******/
+void DrawHistogram (Layout *layout, Gobjects *object) {
+
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sxa;
+  double X0, X1, Y0, Y1;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = layout[0].axis[0].fx;
+  X1 = layout[0].axis[0].fx + layout[0].axis[0].dfx;
+  Y0 = layout[0].axis[1].fy;
+  Y1 = layout[0].axis[1].fy + layout[0].axis[1].dfy;
+
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+  sx0 = MIN (MAX (sx0, X0), X1);
+  sy0 = MAX (MIN (sy0, Y0), Y1);
+  
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    sx1 = MIN (MAX (sx1, X0), X1);
+    sy1 = MAX (MIN (sy1, Y0), Y1);
+    sxa = 0.5*(sx0 + sx1);
+    DrawLine (sx0, sy0, sxa, sy0);
+    DrawLine (sxa, sy0, sxa, sy1);
+    DrawLine (sxa, sy1, sx1, sy1);
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+/******/
+void DrawPoints (Layout *layout, Gobjects *object) {
+
+  int i;
+  float *x, *y, *z;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx, sy, d, sx1, sy1, sx2, sy2;
+  
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  /**** points are scaled by object.z ***/
+  if (object[0].size < 0) {
+    d = 0.5 * (graphic.dx + graphic.dy) * 0.01;
+    x = object[0].x; y = object[0].y; z = object[0].z;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx - d*z[i], sy - d*z[i], 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {	/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx - d*z[i], sy - d*z[i], 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy, sx + d*z[i] + 1, sy);
+	    DrawLine (sx, sy - d*z[i], sx, sy + d*z[i] + 1);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {	/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx + d*z[i] + 1, sy - d*z[i] - 1, sx - d*z[i], sy + d*z[i]);
+	    DrawLine (sx - d*z[i], sy - d*z[i], sx + d*z[i] + 1, sy + d*z[i] + 1);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      XPoint points[4];
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    points[0].x = sx - d*z[i];  points[0].y = sy + 0.58*d*z[i];  
+	    points[1].x = sx + d*z[i];  points[1].y = sy + 0.58*d*z[i];  
+	    points[2].x = sx;           points[2].y = sy - 1.15*d*z[i];  
+	    points[3].x = sx - d*z[i];  points[3].y = sy + 0.58*d*z[i];  
+	    XFillPolygon (graphic.display, graphic.window, graphic.gc, points, 4, Convex, CoordModeOrigin);
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy + 0.58*d*z[i], sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx + d*z[i], sy + 0.58*d*z[i], sx,          sy - 1.15*d*z[i]);
+	    DrawLine (sx,          sy - 1.15*d*z[i], sx - d*z[i], sy + 0.58*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx,          sy - 1.15*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	/* connect a pair of points */
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	if (!(finite(x[i+1]) && finite(y[i+1]))) continue;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  } 
+  /**** points are not scaled by object.z ***/
+  else {
+    d = object[0].size * 0.5 * (graphic.dx + graphic.dy) * 0.003;
+    x = object[0].x; y = object[0].y;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx - d, sy - d, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {		/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+   	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx - d, sy - d, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy, sx + d + 1, sy);
+	    DrawLine (sx, sy - d, sx, sy + d + 1);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {		/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    /* XDrawLine is a little funny, this is needed to fix endpost errors */
+	    DrawLine (sx + d + 1, sy - d - 1, sx - d, sy + d);
+	    DrawLine (sx - d, sy - d, sx + d + 1, sy + d + 1);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      XPoint points[4];
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    points[0].x = sx - d;  points[0].y = sy + 0.58*d;  
+	    points[1].x = sx + d;  points[1].y = sy + 0.58*d;  
+	    points[2].x = sx;      points[2].y = sy - 1.15*d;  
+	    points[3].x = sx - d;  points[3].y = sy + 0.58*d;  
+	    XFillPolygon (graphic.display, graphic.window, graphic.gc, points, 4, Convex, CoordModeOrigin);
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy + 0.58*d, sx + d, sy + 0.58*d);
+	    DrawLine (sx + d, sy + 0.58*d, sx,     sy - 1.15*d);
+	    DrawLine (sx,     sy - 1.15*d, sx - d, sy + 0.58*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d, sy + 0.58*d);
+	    DrawLine (sx, sy, sx + d, sy + 0.58*d);
+	    DrawLine (sx, sy, sx,     sy - 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  }
+}
+    
+/******/
+void DrawXErrors (Layout *layout, Gobjects *object) {
+  
+  int i, bar;
+  float *x, *y, *dxm, *dxp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dxp = object[0].dxp; dxm = object[0].dxm; 
+  bar = object[0].ebar; sz = object[0].size*layout[0].axis[1].dfy*0.03;
+  
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] + dxp[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] + dxp[i])*myi + y[i]*myj + by;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy))) 
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxm[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] - dxm[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] - dxm[i])*myi + y[i]*myj + by;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+  }
+}
+    
+/******/
+void DrawYErrors (Layout *layout, Gobjects *object) {
+
+  int i, bar;
+  float *x, *y, *dym, *dyp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dyp = object[0].dyp; dym = object[0].dym; 
+  bar = object[0].ebar; sz = object[0].size*layout[0].axis[0].dfx*0.03;
+  
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dyp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = sx0 + dyp[i]*mxj;
+    sy1 = sy0 + dyp[i]*myj;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dym[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = x[i]*mxi + (y[i] - dym[i])*mxj + bx;
+    sy1 = x[i]*myi + (y[i] - dym[i])*myj + by;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+  }
+}
Index: /tags/start/Ohana/src/kapa/graph/DrawPtext.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/DrawPtext.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/DrawPtext.c	(revision 12606)
@@ -0,0 +1,35 @@
+# include "Ximage.h"
+  
+void DrawPtext (Layout *layout) {
+  
+  int i, width, pos, x, y, size;
+  double angle;
+  char *fontname;
+
+  fontname = GetRotFont (&size);
+  XSetForeground (graphic.display, graphic.gc, graphic.fore);
+
+  for (i = 0; i < layout[0].Nptext; i++) {
+    if (strcmp (layout[0].ptext[i].text, "")) {
+      angle = layout[0].ptext[i].angle;
+      x = layout[0].ptext[i].x;
+      y = layout[0].ptext[i].y;
+      SetRotFont (layout[0].ptext[i].font, layout[0].ptext[i].size);
+      DrawRotText (x, y, layout[0].ptext[i].text, 5, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+  /* pos values
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|   8   |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+
+  */
Index: /tags/start/Ohana/src/kapa/graph/DrawRotString.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/DrawRotString.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/DrawRotString.c	(revision 12606)
@@ -0,0 +1,472 @@
+# include "Ximage.h"
+# include "alphabet.h"
+
+# define NROT 256
+# define XPROC(x,y) (scale*(cs*((x) - x0) - sn*((y) - y0)) + X0)
+# define YPROC(x,y) (scale*(cs*((y) - y0) + sn*((x) - x0)) + Y0)
+# define NEARINT(x) ((x < 0) ? ((int)(x - 0.5)) : ((int)(x + 0.5)))
+  
+int DrawRotText (int x, int y, char *string, int pos, double angle) {
+
+  char *c, *bitmap, basefont[64];
+  int i, dy, dx, N, X, Y, X1, Y1, code;
+  int dX, Xoff, dY, Yoff, YoffBase, basesize;
+  double cs, sn;
+
+  /* strip leading whitespace */
+  for (c = string; (*c == ' ') || (*c == '\t'); c++);
+  if (*c == 0) return;
+  
+  /* compute string length */
+  cs = cos(angle*RAD_DEG);
+  sn = sin(angle*RAD_DEG);
+  dX = RotStrlen (c);
+  dY = activefont[65].ascent;
+
+  /* apply appropriate offset */
+  switch (pos) {
+  case 0: Xoff =     -dX; Yoff = dY; break;
+  case 1: Xoff = -0.5*dX; Yoff = dY; break;
+  case 2: Xoff =       0; Yoff = dY; break;
+  case 3: Xoff =     -dX; Yoff = 0.5*dY; break;
+  case 4: Xoff = -0.5*dX; Yoff = 0.5*dY; break;
+  case 5: Xoff =       0; Yoff = 0.5*dY; break;
+  case 6: Xoff =     -dX; Yoff = 0; break;
+  case 7: Xoff = -0.5*dX; Yoff = 0; break;
+  case 8: Xoff =       0; Yoff = 0; break;
+  }
+
+  code = FALSE;
+
+  strcpy (basefont, currentname);
+  basesize = currentsize;
+
+  YoffBase = Yoff;
+  /* draw characters one-by-one */
+  for (i = 0; i < strlen(c); i++) {
+    N = (int)(c[i]);
+    if ((N < 0) || (N >= NROT)) continue;
+
+    /* check for special characters */
+    if (!code) {
+      if (N == 94) {
+	SetRotFont (currentname, (int)(0.8*currentsize));
+	Yoff -= 0.5*activescale*dY;
+	continue;
+      }
+      if (N == 95) { 
+	SetRotFont (currentname, (int)(0.8*currentsize));
+	Yoff += 0.5*activescale*dY;
+	continue;
+      }
+      if (N == 124) {
+	SetRotFont (currentname, basesize);
+	Yoff = YoffBase;
+	continue;
+      }
+      if (N == 92) {
+	code = TRUE;
+	continue;
+      } 
+      if (N == 38) {
+	if (c[i+1] == 'h') {
+	  SetRotFont ("helvetica", currentsize);
+	}
+	if (c[i+1] == 't') {
+	  SetRotFont ("times", currentsize);
+	}
+	if (c[i+1] == 'c') {
+	  SetRotFont ("courier", currentsize);
+	}
+	if (c[i+1] == 's') {
+	  SetRotFont ("symbol", currentsize);
+	}
+	i++;
+	continue;
+      }
+    }
+    code = FALSE;
+
+    bitmap = activefont[N].bits;
+    dx = activefont[N].dx;
+    dy = activefont[N].dy;
+    X = x + (int)(Xoff*cs - Yoff*sn) + (int)(activescale*activefont[N].ascent*sn);
+    Y = y + (int)(Xoff*sn + Yoff*cs) - (int)(activescale*activefont[N].ascent*cs);
+    DrawRotBitmap (X, Y, dx, dy, bitmap, TRUE, angle, activescale);
+    Xoff += 1 + (int)(activescale*dx + 0.5);
+  }
+  SetRotFont (basefont, basesize);
+}
+
+int DrawRotBitmap (x, y, dx, dy, bitmap, mode, angle, scale)
+int         x, y, dx, dy;
+char        bitmap[];
+int         mode;
+double      angle, scale;
+{
+
+  int ii, jj, byte_line, byte, bit, flag;
+  unsigned long int fore, back;
+  double i, j, cs, sn, rscale, tmp;
+  int Xt, Yt, X, Y, X0, X1, X2, Y0, Y1, Y2, x0, y0;
+
+  if (mode) {
+    fore = graphic.fore;
+    back = graphic.back;
+  } else {
+    fore = graphic.back;
+    back = graphic.fore;
+  } 
+    
+  byte_line = (int) ((dx + 7) / 8);
+
+  cs = cos(angle*RAD_DEG);  sn = sin(angle*RAD_DEG);
+  rscale = 1.0 / scale;
+
+  X0 = 0;
+  Y0 = 0;
+  x0 = 0;
+  y0 = 0;
+
+  X2 = X1 = XPROC (0,0);
+  Y2 = Y1 = YPROC (0,0);
+
+  X = XPROC (dx,0);
+  Y = YPROC (dx,0);
+# ifdef DRAWBOXES
+  XDrawLine (graphic.display, graphic.window, graphic.gc, x+X, y+Y, x+X1, y+Y1);
+  Xt = X;
+  Yt = Y;
+# endif
+  X1 = MIN (X, X1);
+  X2 = MAX (X, X2);
+  Y1 = MIN (Y, Y1);
+  Y2 = MAX (Y, Y2);
+
+  X = XPROC (dx,dy);
+  Y = YPROC (dx,dy);
+# ifdef DRAWBOXES
+  XDrawLine (graphic.display, graphic.window, graphic.gc, x+X, y+Y, x+Xt, y+Yt);
+  Xt = X;
+  Yt = Y;
+# endif
+  Y1 = MIN (Y, Y1);
+  Y2 = MAX (Y, Y2);
+  X1 = MIN (X, X1);
+  X2 = MAX (X, X2);
+
+  X = XPROC (0,dy);
+  Y = YPROC (0,dy);
+# ifdef DRAWBOXES
+  XDrawLine (graphic.display, graphic.window, graphic.gc, x+X, y+Y, x+Xt, y+Yt);
+  Xt = X;
+  Yt = Y;
+# endif
+  Y1 = MIN (Y, Y1);
+  Y2 = MAX (Y, Y2);
+  X1 = MIN (X, X1);
+  X2 = MAX (X, X2);
+
+  XSetForeground (graphic.display, graphic.gc, fore);
+  if (scale > 1) {
+    for (i = X1; i <= X2; i+=1) {
+      for (j = Y1; j <= Y2; j+=1) {
+	tmp = rscale*(cs*(i - X0) + sn*(j - Y0)) + x0;  ii = NEARINT (tmp);
+	tmp = rscale*(cs*(j - Y0) - sn*(i - X0)) + y0;  jj = NEARINT (tmp);
+	/* fprintf (stderr, "%d %d  %d %d\n", i, j, ii, jj);  */
+	if ((ii < 0) || (ii >= dx) || (jj < 0) || (jj >= dy)) continue;
+	byte = byte_line * jj + (ii / 8);
+	bit = ii % 8;
+	flag = 0x01 & (bitmap[byte] >> bit);
+	if (flag) XDrawPoint (graphic.display, graphic.window, graphic.gc, x + i, y + j);
+      }
+    }
+  } else {
+    for (i = X1; i <= X2; i+=scale) {
+      for (j = Y1; j <= Y2; j+=scale) {
+	tmp = rscale*(cs*(i - X0) + sn*(j - Y0)) + x0;  ii = NEARINT (tmp);
+	tmp = rscale*(cs*(j - Y0) - sn*(i - X0)) + y0;  jj = NEARINT (tmp);
+	/* fprintf (stderr, "%d %d  %d %d\n", i, j, ii, jj);  */
+	if ((ii < 0) || (ii >= dx) || (jj < 0) || (jj >= dy)) continue;
+	byte = byte_line * jj + (ii / 8);
+	bit = ii % 8;
+	flag = 0x01 & (bitmap[byte] >> bit);
+	/* fprintf (stderr, "%2d %2d  %3d %3d  %1d  %f  %f\n", i, j, ii, jj, flag,
+	   rscale*(cs*(i - X0) + sn*(j - Y0)) + x0, rscale*(cs*(j - Y0) - sn*(i - X0)) + y0);  */
+	if (flag) XDrawPoint (graphic.display, graphic.window, graphic.gc, x + i, y + j);
+      }
+    }
+# if (0)
+    for (i = 0; i < dx; i++) {
+      for (j = 0; j < dy; j++) {
+	tmp = scale*(cs*(i - x0) - sn*(j - y0)) + X0; ii = NEARINT (tmp);
+	tmp = scale*(cs*(j - y0) + sn*(i - x0)) + Y0; jj = NEARINT (tmp);
+	/* if ((ii < 0) || (ii >= dx) || (jj < 0) || (jj >= dy)) continue; */
+	byte = byte_line * j + (i / 8);
+	bit = i % 8;
+	flag = 0x01 & (bitmap[byte] >> bit);
+	fprintf (stderr, "%2d %2d  %3d %3d  %1d  %f  %f\n", i, j, ii, jj, flag, 
+		 scale*(cs*(i - x0) - sn*(j - y0)) + X0, scale*(cs*(j - y0) + sn*(i - x0)) + Y0); 
+	if (flag) XDrawPoint (graphic.display, graphic.window, graphic.gc, x + ii, y + jj);
+      }
+    }
+# endif
+  }
+  XSetForeground (graphic.display, graphic.gc, graphic.fore);
+}
+
+InitRotFonts () {
+
+  int i, Nhardwired;
+
+  Nhardwired = sizeof (HardwiredFonts) / sizeof (FontSet);
+  
+  Nallfonts = Nhardwired;
+  ALLOCATE (AllFonts, FontSet, Nallfonts);
+  
+  for (i = 0; i < Nhardwired; i++) {
+    AllFonts[i] = HardwiredFonts[i];
+  }
+
+  activefont = AllFonts[DEFFONT].font;
+  activescale = 1.0;
+  strcpy (currentname, AllFonts[DEFFONT].name);
+  currentsize = AllFonts[DEFFONT].size;
+}
+
+int SetRotFont (char *name, int size) {
+  
+  int i, nsize, msize, bsize, bigger, dsize, match, good;
+
+  bigger = good = match = -1;
+  dsize = 10000;
+  bsize = 10000;
+  for (i = 0; i < Nallfonts; i++) {
+    if (!strcasecmp (AllFonts[i].name, name)) {
+      good = i;
+      nsize = abs (AllFonts[i].size - size);
+      if (nsize < dsize) {
+	match = i;
+	dsize = nsize;
+      }
+      msize = AllFonts[i].size - size;
+      if ((msize < bsize) && (msize >= 0)) {
+	bigger = i;
+	bsize = msize;
+      }
+    }
+  }
+  
+  if ((match == -1) && (good != -1)) match = good;
+  if (bigger != -1) match = bigger;
+  if (match != -1) {
+    activefont = AllFonts[match].font;
+    activescale = (double) size / AllFonts[match].size;
+    currentsize = size;
+    strcpy (currentname, name);
+    return (TRUE);
+  } else {
+    fprintf (stderr, "no matching font\n");
+    return (FALSE);
+  }
+
+}
+  
+char *GetRotFont (int *size) {
+
+  *size = currentsize;
+  return (currentname);
+
+}
+
+int RotStrlen (char *c) {
+
+  int i, N, dX, code;
+  double scale; 
+  
+  scale = activescale;
+
+  /* find string length */
+  dX = 0;
+
+  code = FALSE;
+  for (i = 0; i < strlen (c); i++) {
+    N = (int)(c[i]);
+    /* skip non-printing characters */
+    if ((N < 0) || (N >= NROT)) continue;
+
+    /* check for special characters */
+    if (!code) {
+      if (N == 94) { /* super-script */
+	scale *= 0.8;
+	continue;
+      }
+      if (N == 95) { /* sub-script */
+	scale *= 0.8;
+	continue;
+      }
+      if (N == 124) { /* normal-script */
+	scale = activescale;
+	continue;
+      }
+      if (N == 92) { /* backslash */
+	code = TRUE;
+	continue;
+      } 
+      if (N == 38) { /* font-code */
+	i++;
+	continue;
+      }
+    }
+    code = FALSE;
+    dX += scale*activefont[N].dx + 1;
+  }
+  return (dX);
+}
+
+/* writes commands to print string at location and angle using
+   currently set font and size */
+void PSRotText (FILE *f, int x, int y, char *string, int pos, double angle) {
+
+  char *c, *segment, basefont[64];
+  int i, N, code;
+  int dX, dY, Xoff, Yoff, X, Y, Nseg, YoffBase;
+  double cs, sn, fscale;
+  int basesize;
+    
+  /* strip off leading whitespace */
+  for (c = string; (*c == ' ') || (*c == '\t'); c++);
+  if (*c == 0) return;
+  
+  /* compute string length */
+  /* PS fonts are somewhat different scales from bitmap font equivalents */
+  if (!strcmp (currentname, "times")) fscale = 1.07;
+  if (!strcmp (currentname, "courier")) fscale = 1.5;
+  if (!strcmp (currentname, "helvetica")) fscale = 0.9;
+  if (!strcmp (currentname, "symbol")) fscale = 1.2;
+  dX = fscale*RotStrlen (c);
+  dY = activefont[65].ascent;
+  
+  /* apply appropriate offset */
+  switch (pos) {
+  case 0: Xoff =     -dX; Yoff = -dY; break;
+  case 1: Xoff = -0.5*dX; Yoff = -dY; break;
+  case 2: Xoff =       0; Yoff = -dY; break;
+  case 3: Xoff =     -dX; Yoff = -0.5*dY; break;
+  case 4: Xoff = -0.5*dX; Yoff = -0.5*dY; break;
+  case 5: Xoff =       0; Yoff = -0.5*dY; break;
+  case 6: Xoff =     -dX; Yoff = 0; break;
+  case 7: Xoff = -0.5*dX; Yoff = 0; break;
+  case 8: Xoff =       0; Yoff = 0; break;
+  }
+  cs = cos(angle*RAD_DEG);
+  sn = sin(angle*RAD_DEG);
+  X = x + Xoff*cs + Yoff*sn;
+  Y = y - Xoff*sn + Yoff*cs;
+
+  basesize = currentsize;
+  strcpy (basefont, currentname);
+
+  PSSetFont (f, currentsize);
+  fprintf (f, "gsave\n");
+  fprintf (f, " %d %d moveto %f rotate\n", X, Y, -angle);
+
+  ALLOCATE (segment, char, strlen (c)+2);
+  bzero (segment, strlen (c)+2);
+  Nseg = 0;
+
+  code = FALSE;
+  YoffBase = 0;
+  /* accumulate string segments with common state */
+  for (i = 0; i < strlen (c); i++) {
+    N = (int)(c[i]);
+    if ((N < 0) || (N >= NROT)) continue;
+
+    /* check for special characters */
+    if (!code) {
+      if (N == 94) {
+	PSDumpRotSegment (f, segment, &Nseg);
+	SetRotFont (currentname, (int)(0.8*currentsize));
+	Yoff = 0.75*activescale*dY;
+	fprintf (f, "0 %d rmoveto\n", Yoff);
+	YoffBase += Yoff;
+	PSSetFont (f, currentsize);
+	continue;
+      }
+      if (N == 95) { 
+	PSDumpRotSegment (f, segment, &Nseg);
+	SetRotFont (currentname, (int)(0.8*currentsize));
+	Yoff = -0.5*activescale*dY;
+	fprintf (f, "0 %d rmoveto\n", Yoff);
+	YoffBase += Yoff;
+	PSSetFont (f, currentsize);
+	continue;
+      }
+      if (N == 124) {
+	PSDumpRotSegment (f, segment, &Nseg);
+	SetRotFont (currentname, basesize);
+	fprintf (f, "0 %d rmoveto\n", -YoffBase);
+	YoffBase = 0;
+	PSSetFont (f, currentsize);
+	continue;
+      }
+      if (N == 92) {
+	code = TRUE;
+	continue;
+      } 
+      if (N == 38) {
+	PSDumpRotSegment (f, segment, &Nseg);
+	if (c[i+1] == 'h') {
+	  SetRotFont ("helvetica", currentsize);
+	  PSSetFont (f, currentsize);
+	}
+	if (c[i+1] == 't') {
+	  SetRotFont ("times", currentsize);
+	  PSSetFont (f, currentsize);
+	}
+	if (c[i+1] == 'c') {
+	  SetRotFont ("courier", currentsize);
+	  PSSetFont (f, currentsize);
+	}
+	if (c[i+1] == 's') {
+	  SetRotFont ("symbol", currentsize);
+	  PSSetFont (f, currentsize);
+	}
+	i++;
+	continue;
+      }
+    }
+    code = FALSE;
+    segment[Nseg] = N;
+    Nseg ++;
+  }
+  PSDumpRotSegment (f, segment, &Nseg);
+  fprintf (f, "stroke grestore\n");
+  free (segment);
+  SetRotFont (basefont, basesize);
+}
+
+
+PSDumpRotSegment (FILE *f, char *segment, int *Nseg) {
+  fprintf (f, "(%s) show\n", segment);
+  bzero (segment, *Nseg);
+  *Nseg = 0;
+}
+
+PSSetFont (FILE *f, int size) {
+  if (!strcmp (currentname, "times")) 
+    fprintf (f, "/Times-Roman findfont %d scalefont setfont\n", size);
+  if (!strcmp (currentname, "helvetica")) 
+    fprintf (f, "/Helvetica findfont %d scalefont setfont\n", size);
+  if (!strcmp (currentname, "courier")) 
+    fprintf (f, "/Courier findfont %d scalefont setfont\n", size);
+  if (!strcmp (currentname, "symbol")) 
+    fprintf (f, "/Symbol findfont %d scalefont setfont\n", size);
+}
+
+
+
+  /* test cross hair
+  fprintf (f, "%d %d %d %d L\n", x-10, y, x+10, y);
+  fprintf (f, "%d %d %d %d L\n", x, y-10, x, y+10);
+  */
Index: /tags/start/Ohana/src/kapa/graph/DrawText.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/DrawText.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/DrawText.c	(revision 12606)
@@ -0,0 +1,39 @@
+# include "Ximage.h"
+  
+/* Draw text centered at x,y */
+
+void DrawText (int x, int y, char *string, int pos) {
+
+  char *c;
+  int dx, dy;
+
+  for (c = string; (*c == ' ') || (*c == '\t'); c++);
+  if (*c == 0) return;
+  
+  dx  = XTextWidth (graphic.font, c, strlen(c));
+  dy  = graphic.font[0].ascent;
+  switch (pos) {
+  case 0: XDrawString (graphic.display, graphic.window, graphic.gc, x - dx,   y + dy,   c, strlen(c)); break;
+  case 1: XDrawString (graphic.display, graphic.window, graphic.gc, x - dx/2, y + dy,   c, strlen(c)); break;
+  case 2: XDrawString (graphic.display, graphic.window, graphic.gc, x,        y + dy,   c, strlen(c)); break;
+  case 3: XDrawString (graphic.display, graphic.window, graphic.gc, x - dx,   y + dy/2, c, strlen(c)); break;
+  case 4: XDrawString (graphic.display, graphic.window, graphic.gc, x - dx/2, y + dy/2, c, strlen(c)); break;
+  case 5: XDrawString (graphic.display, graphic.window, graphic.gc, x,        y + dy/2, c, strlen(c)); break;
+  case 6: XDrawString (graphic.display, graphic.window, graphic.gc, x - dx,   y,        c, strlen(c)); break;
+  case 7: XDrawString (graphic.display, graphic.window, graphic.gc, x - dx/2, y,        c, strlen(c)); break;
+  case 8: XDrawString (graphic.display, graphic.window, graphic.gc, x,        y,        c, strlen(c)); break;
+  }
+}
+
+/*
+            
+ 6____7___8
+  |       | 
+  |       | 
+ 3|   4   |5
+  |       |
+  |       |
+  ---------
+ 0    1   2
+
+*/
Index: /tags/start/Ohana/src/kapa/graph/ErasePlot.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/ErasePlot.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/ErasePlot.c	(revision 12606)
@@ -0,0 +1,60 @@
+# include "Ximage.h"
+# define TESTFREE(a) { if ((a) != (float *) NULL) free (a);}
+
+int ErasePlot (int ClearSection) {
+  
+  int i, j;
+
+  for (j = 0; j < Nsection; j++) {
+
+    /* free data objects, then re-alloc those needed */
+    for (i = 0; i < section[j].Nobjects; i++) {
+      TESTFREE (section[j].objects[i].x);
+      TESTFREE (section[j].objects[i].y);
+      TESTFREE (section[j].objects[i].z);
+      TESTFREE (section[j].objects[i].dxm);
+      TESTFREE (section[j].objects[i].dxp);
+      TESTFREE (section[j].objects[i].dym);
+      TESTFREE (section[j].objects[i].dyp);
+    }
+    
+    /* reset axes and labels */
+    for (i = 0; i < 4; i++) {
+      section[j].axis[i].isaxis = FALSE;
+      section[j].axis[i].islabel = FALSE;
+      section[j].axis[i].areticks = FALSE;
+    }
+    for (i = 0; i < 8; i++) {
+      strcpy (section[j].label[i].text, "");
+    }
+    
+    /* free objects and text entries, or re-zero */
+    if (ClearSection && (j != 0)) {
+      free (section[j].objects);
+      free (section[j].ptext);
+    } else {
+      section[j].Nobjects = 0;
+      REALLOCATE (section[j].objects, Gobjects, 1);
+      section[j].Nptext = 0;
+      REALLOCATE (section[j].ptext, Label, 1);
+    }
+  }
+
+  if (ClearSection) {
+    Nsection = 1;
+    TheSection = 0;
+    REALLOCATE (section, Layout, Nsection);
+  }
+
+  XClearWindow (graphic.display, graphic.window);
+  Refresh (1);
+
+  return (TRUE);
+  
+}
+
+
+/** note that 'section' is the global variable
+    of type 'Layout' which carries data and info 
+    about each graph section 
+**/
Index: /tags/start/Ohana/src/kapa/graph/LoadBox.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/LoadBox.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/LoadBox.c	(revision 12606)
@@ -0,0 +1,87 @@
+# include "Ximage.h"
+# define SCAN \
+status = read (sock, buffer, 16); \
+buffer[16] = 0; \
+sscanf (buffer, "%*s %d", &Nbytes); \
+status = read (sock, buffer, Nbytes); \
+buffer[status] = 0;
+
+int LoadBox () {
+  
+  int i, status, Nbytes;
+  char buffer[128], Axis[16], Labels[16], Ticks[16];
+  Layout *layout;
+  
+  layout = &section[TheSection];
+
+  SCAN;
+  sscanf (buffer, "%lf %lf %lf %lf", 
+	  &layout[0].axis[0].min, &layout[0].axis[0].max, 
+	  &layout[0].axis[1].min, &layout[0].axis[1].max);
+
+  layout[0].axis[3].min = layout[0].axis[1].min;
+  layout[0].axis[3].max = layout[0].axis[1].max;
+  layout[0].axis[2].min = layout[0].axis[0].min;
+  layout[0].axis[2].max = layout[0].axis[0].max;
+  
+  SCAN;
+  sscanf (buffer, "%s %s %s", Axis, Labels, Ticks);
+
+  for (i = 0; i < 4; i++) {
+    switch (Axis[i]) {
+    case '0':
+      layout[0].axis[i].isaxis = FALSE;
+      break;
+    case '1':
+      layout[0].axis[i].isaxis = TRUE;
+      break;
+    case '2':
+      layout[0].axis[i].isaxis = TRUE;
+      break;
+    }
+    switch (Ticks[i]) {
+    case '0':
+      layout[0].axis[i].areticks = FALSE;
+      break;
+    case '1':
+      layout[0].axis[i].areticks = TRUE;
+      break;
+    case '2':
+      layout[0].axis[i].areticks = 2;
+      break;
+    }
+    switch (Labels[i]) {
+    case '0':
+      layout[0].axis[i].islabel = FALSE;
+      break;
+    case '1':
+      layout[0].axis[i].islabel = TRUE;
+      break;
+    case '2':
+      layout[0].axis[i].islabel = (i < 2);
+      break;
+    }
+  }
+
+  DrawFrame (layout);
+  status = TRUE;
+  if (status) {
+    for (i = 0; i < Nsection; i++) {
+      PositionPicture (&section[i]);
+    }
+    XClearWindow (graphic.display, graphic.window);
+    Refresh (1);
+  } else {
+    FlushDisplay ();
+  } 
+
+  return (TRUE);
+  
+}
+
+/*
+  layout[0].X = 0;
+  layout[0].Y = 0;
+   layout[0].expand = 1;
+*/
+  
Index: /tags/start/Ohana/src/kapa/graph/LoadLabels.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/LoadLabels.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/LoadLabels.c	(revision 12606)
@@ -0,0 +1,42 @@
+# include "Ximage.h"
+
+int LoadLabels () {
+  
+  char buffer[256], *c;
+  int status, Nbytes, mode, size;
+  Layout *layout;
+  
+  layout = &section[TheSection];
+  
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+  
+  status = read (sock, buffer, 16); 
+  buffer[16] = 0; 
+  sscanf (buffer, "%d %d", &Nbytes, &mode); 
+
+  status = read (sock, buffer, Nbytes); 
+  buffer[status] = 0; 
+
+  strncpy (layout[0].label[mode].text, buffer, Nbytes);
+  layout[0].label[mode].text[Nbytes] = 0;
+
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+  
+  c = GetRotFont (&size);
+  layout[0].label[mode].size = size;
+  strcpy (layout[0].label[mode].font, c);
+  DrawLabels (layout);
+  
+  FlushDisplay ();
+  
+  return (TRUE);
+  
+}
+
+/*
+  layout[0].X = 0;
+  layout[0].Y = 0;
+  layout[0].expand = 1;
+  */
+
+
Index: /tags/start/Ohana/src/kapa/graph/LoadObject.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/LoadObject.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/LoadObject.c	(revision 12606)
@@ -0,0 +1,195 @@
+# include "Ximage.h"
+# include <unistd.h>
+# include <errno.h>
+
+# define SCAN \
+status = read (sock, buffer, 16); \
+buffer[16] = 0; \
+sscanf (buffer, "%*s %d", &Nbytes); \
+status = read (sock, buffer, Nbytes); \
+buffer[status] = 0;
+
+int LoadObject () {
+  
+  char buffer[1024];
+  int status, N, Nbytes;
+  Layout *layout;
+
+  layout = &section[TheSection];
+  
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+  
+  N = layout[0].Nobjects;
+  layout[0].Nobjects ++;
+  REALLOCATE (layout[0].objects, Gobjects, layout[0].Nobjects);
+  layout[0].objects[N].x = layout[0].objects[N].y = layout[0].objects[N].z = (float *) NULL;
+  layout[0].objects[N].dxm = layout[0].objects[N].dxp = (float *) NULL;
+  layout[0].objects[N].dym = layout[0].objects[N].dyp = (float *) NULL;
+  
+  SCAN;
+  sscanf (buffer, "%d %d %d %d %d %d %d %lf %lf",
+	  &layout[0].objects[N].Npts, &layout[0].objects[N].style, 
+	  &layout[0].objects[N].ptype, &layout[0].objects[N].ltype, 
+	  &layout[0].objects[N].etype, &layout[0].objects[N].ebar, 
+	  &layout[0].objects[N].color, 
+	  &layout[0].objects[N].lweight, &layout[0].objects[N].size);
+  
+  if (DEBUG) fprintf (stderr, "%d %d %d %d %d %d %d %lf %lf\n",
+	  layout[0].objects[N].Npts, layout[0].objects[N].style, 
+	  layout[0].objects[N].ptype, layout[0].objects[N].ltype, 
+	  layout[0].objects[N].etype, layout[0].objects[N].ebar, 
+	  layout[0].objects[N].color, 
+	  layout[0].objects[N].lweight, layout[0].objects[N].size);
+  
+  /* force valid ranges */
+  if ((layout[0].objects[N].color > NGRAPHCOLORS) || (layout[0].objects[N].color < 0))
+    layout[0].objects[N].color = 0;
+
+  SCAN;
+  sscanf (buffer, "%lf %lf %lf %lf",
+	  &layout[0].objects[N].x0, &layout[0].objects[N].x1, 
+	  &layout[0].objects[N].y0, &layout[0].objects[N].y1);
+  
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+  
+  if (!LoadVectorData (layout, N, "x")) {
+    FreeObjectData (&layout[0].objects[N]);
+    layout[0].Nobjects --;
+    REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
+  }
+    
+  if (!LoadVectorData (layout, N, "y")) {
+    FreeObjectData (&layout[0].objects[N]);
+    layout[0].Nobjects --;
+    REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
+  }
+  if (layout[0].objects[N].size < 0.0) {
+    if (!LoadVectorData (layout, N, "z")) {
+      FreeObjectData (&layout[0].objects[N]);
+      layout[0].Nobjects --;
+      REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
+    }
+  }
+  if (layout[0].objects[N].etype & 0x01) {
+    if (!LoadVectorData (layout, N, "dym")) {
+      FreeObjectData (&layout[0].objects[N]);
+      layout[0].Nobjects --;
+      REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
+    }
+    if (!LoadVectorData (layout, N, "dyp")) {
+      FreeObjectData (&layout[0].objects[N]);
+      layout[0].Nobjects --;
+      REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
+    }
+  }
+  if (layout[0].objects[N].etype & 0x02) {
+    if (!LoadVectorData (layout, N, "dxm")) {
+      FreeObjectData (&layout[0].objects[N]);
+      layout[0].Nobjects --;
+      REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
+    }
+    if (!LoadVectorData (layout, N, "dxp")) {
+      FreeObjectData (&layout[0].objects[N]);
+      layout[0].Nobjects --;
+      REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
+    }
+  }
+
+  if (DEBUG) fprintf (stderr, "loaded %d objects, using object %d\n", layout[0].objects[N].Npts, N);
+
+  DrawObjectN (layout, &layout[0].objects[layout[0].Nobjects-1]);
+  FlushDisplay ();
+
+  return (TRUE);
+  
+}
+
+/* load data for the named component */
+int LoadVectorData (Layout *layout, int N, char *type) {
+  
+  int Npts, Ninpts, status, Ntry;
+  int bytes_left;
+  char *buff;
+
+  Npts = layout[0].objects[N].Npts;
+  status = 1;
+  if (!strcmp (type, "x")) {
+    ALLOCATE (layout[0].objects[N].x, float, MAX (1, Npts));
+    buff = (char *) layout[0].objects[N].x;
+  }
+  if (!strcmp (type, "y")) {
+    ALLOCATE (layout[0].objects[N].y, float, MAX (1, Npts));
+    buff = (char *) layout[0].objects[N].y;
+  }
+  if (!strcmp (type, "z")) {
+    ALLOCATE (layout[0].objects[N].z, float, MAX (1, Npts));
+    buff = (char *) layout[0].objects[N].z;
+  }
+  if (!strcmp (type, "dxm")) {
+    ALLOCATE (layout[0].objects[N].dxm, float, MAX (1, Npts));
+    buff = (char *) layout[0].objects[N].dxm;
+  }
+  if (!strcmp (type, "dxp")) {
+    ALLOCATE (layout[0].objects[N].dxp, float, MAX (1, Npts));
+    buff = (char *) layout[0].objects[N].dxp;
+  }
+  if (!strcmp (type, "dym")) {
+    ALLOCATE (layout[0].objects[N].dym, float, MAX (1, Npts));
+    buff = (char *) layout[0].objects[N].dym;
+  }
+  if (!strcmp (type, "dyp")) {
+    ALLOCATE (layout[0].objects[N].dyp, float, MAX (1, Npts));
+    buff = (char *) layout[0].objects[N].dyp;
+  }
+
+  bytes_left = Npts*sizeof (float);
+
+  Ntry = 0;
+  if (DEBUG) fprintf (stderr, "starting vector load\n");
+  Ninpts = 0;
+  while (bytes_left > 0) {
+    status = read (sock, buff, bytes_left);
+    if (DEBUG) fprintf (stderr, "status: %d, %d\n", status, bytes_left);
+    if (status == 0) {  /* No more pipe */
+      fprintf (stderr, "error: pipe closed\n");
+      return (FALSE);
+    }
+    if (status != -1) { /* pipe has data */
+      Ninpts += status;
+      bytes_left -= status;
+      buff = (char *)(buff + status);
+      Ntry = 0;
+      continue;
+    }
+    if (errno == EAGAIN) {
+      Ntry ++;
+      if (Ntry > 100) {
+	fprintf (stderr, "kapa communication error\n");
+	return (FALSE);
+      }
+      usleep (10000);
+      continue;
+    }
+    perror ("kapa load");
+  }
+  if (Ninpts != Npts*sizeof(float)) {  
+    fprintf (stderr, "error: expected %d bytes, but got only %d\n", Ninpts, Npts*sizeof(float));
+    return (FALSE);
+  }
+  if (DEBUG) fprintf (stderr, "done vector load\n");
+  return (TRUE);
+
+}
+
+FreeObjectData (Gobjects *object) {
+
+  if (object[0].x != (float *) NULL) free (object[0].x);
+  if (object[0].y != (float *) NULL) free (object[0].y);
+  if (object[0].z != (float *) NULL) free (object[0].z);
+
+  if (object[0].dxm != (float *) NULL) free (object[0].dxm);
+  if (object[0].dxp != (float *) NULL) free (object[0].dxp);
+  if (object[0].dym != (float *) NULL) free (object[0].dym);
+  if (object[0].dyp != (float *) NULL) free (object[0].dyp);
+}
+
Index: /tags/start/Ohana/src/kapa/graph/LoadPtext.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/LoadPtext.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/LoadPtext.c	(revision 12606)
@@ -0,0 +1,51 @@
+# include "Ximage.h"
+
+int LoadPtext () {
+  
+  char buffer[256], *c;
+  int N, status, Nbytes, mode, size;
+  double tmp, L;
+  Layout *layout;
+  
+  layout = &section[TheSection];
+  
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+  
+  layout[0].Nptext = MAX (layout[0].Nptext, 0);
+  N = layout[0].Nptext;
+  layout[0].Nptext++;
+  REALLOCATE (layout[0].ptext, Label, layout[0].Nptext);
+
+  status = read (sock, buffer, 16); 
+  buffer[16] = 0; 
+  sscanf (buffer, "%lf", &tmp); 
+  L = layout[0].axis[0].dfx;
+  layout[0].ptext[N].x = L * (tmp - layout[0].axis[0].min) / (layout[0].axis[0].max - layout[0].axis[0].min) + layout[0].axis[0].fx;
+
+  status = read (sock, buffer, 16); 
+  buffer[16] = 0; 
+  sscanf (buffer, "%lf", &tmp); 
+  L = layout[0].axis[1].dfy;
+  layout[0].ptext[N].y = L * (tmp - layout[0].axis[1].min) / (layout[0].axis[1].max - layout[0].axis[1].min) + layout[0].axis[1].fy;
+
+  status = read (sock, buffer, 16); 
+  buffer[16] = 0; 
+  sscanf (buffer, "%lf", &layout[0].ptext[N].angle); 
+
+  status = read (sock, buffer, 128); 
+  buffer[status] = 0; 
+  strcpy (layout[0].ptext[N].text, buffer);
+
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+  
+  c = GetRotFont (&size);
+  layout[0].ptext[N].size = size;
+  strcpy (layout[0].ptext[N].font, c);
+
+  DrawPtext (layout);
+  
+  FlushDisplay ();
+  
+  return (TRUE);
+  
+}
Index: /tags/start/Ohana/src/kapa/graph/PNGit.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/PNGit.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/PNGit.c	(revision 12606)
@@ -0,0 +1,137 @@
+# include "Ximage.h"
+# include <png.h>
+# define NPALETTE NGRAPHCOLORS
+
+int PNGit () {
+
+  FILE *f;
+  png_structp png_ptr;
+  png_infop info_ptr;
+  png_color palette[NPALETTE];
+  int pchoice[NPALETTE];
+  XColor color;
+  png_byte **rows;
+  int dx, dy;
+  int i, j, k, found;
+  XImage *tmpimage;
+  unsigned long pixel;
+  char filename[1024];
+  int Nbytes, status;
+
+  dx = graphic.dx;
+  dy = graphic.dy;
+  
+  /* expect a line telling the number of bytes and a filename */
+  status = read (sock, filename, 16);
+  filename[16] = 0;
+  sscanf (filename, "%*s %d", &Nbytes);
+  status = read (sock, filename, Nbytes);
+  filename[status] = 0; /* make the string easy to parse */
+
+  ALLOCATE (rows, png_byte *, dy);
+  for (i = 0; i < dy; i++) {
+    ALLOCATE (rows[i], png_byte, 3*dx);
+  }
+
+  /* define the palette */
+  for (i = 0; i < NPALETTE; i++) {
+    color.pixel = graphic.color[i];
+    XQueryColor (graphic.display, graphic.colormap, &color);
+    palette[i].red = (0x100 * color.red / 0x10000);
+    palette[i].green = (0x100 * color.green / 0x10000);
+    palette[i].blue = (0x100 * color.blue / 0x10000);
+    pchoice[i] = color.pixel;
+  }
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open output file %s\n", "Xgraph.png");
+    return (TRUE);  /* true because otherwise it quits kapa! */
+  }
+
+  png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, (png_voidp) NULL, (png_voidp) NULL, (png_voidp) NULL);
+  if (!png_ptr) {
+    fclose (f);
+    fprintf (stderr, "can't get png structure\n");
+    return (TRUE);
+  }
+
+  info_ptr = png_create_info_struct (png_ptr);
+  if (!info_ptr) {
+    png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
+    fclose (f);
+    fprintf (stderr, "can't get png info structure\n");
+    return (TRUE);
+  }
+
+  if (setjmp (png_ptr[0].jmpbuf)) {
+    png_destroy_write_struct (&png_ptr, &info_ptr);
+    fclose (f);
+    fprintf (stderr, "can't get png return\n");
+    return (TRUE);
+  }
+
+  png_init_io (png_ptr, f);
+
+  /* see docs for write-row-callback to provide progress info */
+
+  png_set_IHDR (png_ptr, info_ptr, dx, dy, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 
+
+  /* png_set_IHDR (png_ptr, info_ptr, dx, dy, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); */
+
+  png_set_PLTE (png_ptr, info_ptr, palette, NPALETTE); 
+ 
+  png_write_info (png_ptr, info_ptr);
+
+  /* a new attempt... */
+
+  {
+    XWindowAttributes WindowAttributes;
+    Pixmap tmp_pixmap;
+    Window tmp_window;
+    
+    XGetWindowAttributes (graphic.display, graphic.window, &WindowAttributes);
+    
+    tmp_pixmap = XCreatePixmap (graphic.display, graphic.window, dx, dy, WindowAttributes.depth);
+
+    tmp_window = graphic.window;
+    graphic.window = tmp_pixmap;
+
+    Refresh (1);
+
+    tmpimage = XGetImage (graphic.display, graphic.window, 0, 0, dx, dy, 0xffffffff, ZPixmap);
+    for (j = 0; j < dy; j++) {
+      for (i = 0; i < dx; i++) {
+	pixel = XGetPixel (tmpimage, i, j);
+	for (found = k = 0; (k < NPALETTE) && !found; k++) {
+	  if (pixel == pchoice[k]) {
+	    found = TRUE;
+	    rows[j][i] = k;
+	    /*
+	      rows[j][3*i+0] = palette[k].red;
+	      rows[j][3*i+1] = palette[k].green;
+	      rows[j][3*i+2] = palette[k].blue;
+	    */
+	  }
+	}
+      }
+    }
+    graphic.window = tmp_window;
+    XFreePixmap (graphic.display, tmp_pixmap);
+  }
+
+  png_write_image (png_ptr, rows);
+  png_write_end (png_ptr, info_ptr);
+  png_destroy_write_struct (&png_ptr, &info_ptr);
+
+  for (i = 0; i < dy; i++) {
+    free (rows[i]);
+  }
+  free (rows);
+
+  XDestroyImage (tmpimage);
+
+  fclose (f);
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/kapa/graph/PPMit.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/PPMit.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/PPMit.c	(revision 12606)
@@ -0,0 +1,86 @@
+# include "Ximage.h"
+# define NPALETTE 9
+
+int PPMit () {
+
+  FILE *f;
+  int pixval[NPALETTE], red[NPALETTE], blue[NPALETTE], green[NPALETTE];
+  XColor color;
+  int dx, dy;
+  int i, j, k, m, found;
+  XImage *tmpimage;
+  unsigned long pixel;
+  char filename[1024];
+  int Nbytes, status;
+  char *buffer;
+
+  XWindowAttributes WindowAttributes;
+  Pixmap tmp_pixmap;
+  Window tmp_window;
+  
+  dx = graphic.dx;
+  dy = graphic.dy;
+  
+  /* expect a line telling the number of bytes and a filename */
+  status = read (sock, filename, 16);
+  filename[16] = 0;
+  sscanf (filename, "%*s %d", &Nbytes);
+  status = read (sock, filename, Nbytes);
+  filename[status] = 0; /* make the string easy to parse */
+
+  ALLOCATE (buffer, char, 3*dx*dy);
+
+  /* define the palette */
+  for (i = 0; i < NPALETTE; i++) {
+    color.pixel = graphic.color[i];
+    XQueryColor (graphic.display, graphic.colormap, &color);
+    red[i]     = (color.red >> 8);
+    green[i]   = (color.green >> 8);
+    blue[i]    = (color.blue >> 8);
+    pixval[i]  = color.pixel;
+  }
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open output file %s\n", filename);
+    return (TRUE);  /* true because otherwise it quits kapa! */
+  }
+  
+  fprintf (f, "P6\n");
+  fprintf (f, "%d %d\n", dx, dy);
+  fprintf (f, "255\n");
+
+  XGetWindowAttributes (graphic.display, graphic.window, &WindowAttributes);
+  
+  tmp_pixmap = XCreatePixmap (graphic.display, graphic.window, dx, dy, WindowAttributes.depth);
+  
+  tmp_window = graphic.window;
+  graphic.window = tmp_pixmap;
+  
+  Refresh (1);
+  
+  tmpimage = XGetImage (graphic.display, graphic.window, 0, 0, dx, dy, 0xffffffff, ZPixmap);
+  for (m = j = 0; j < dy; j++) {
+    for (i = 0; i < dx; i++, m+=3) {
+      pixel = XGetPixel (tmpimage, i, j);
+      for (found = k = 0; (k < NPALETTE) && !found; k++) {
+	if (pixel == pixval[k]) {
+	  found = TRUE;
+	  buffer[m+0] = red[k];
+	  buffer[m+1] = green[k];
+	  buffer[m+2] = blue[k];
+	}
+      }
+    }
+  }
+  graphic.window = tmp_window;
+  XFreePixmap (graphic.display, tmp_pixmap);
+
+  fwrite (buffer, 3, dx*dy, f);
+
+  XDestroyImage (tmpimage);
+
+  fclose (f);
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/kapa/graph/PSFrame.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/PSFrame.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/PSFrame.c	(revision 12606)
@@ -0,0 +1,104 @@
+# include "Ximage.h"
+# define DrawLine(X1,Y1,DX,DY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f L\n", X1, Y1, X1+DX, Y1+DY))
+
+int PSFrame (Layout *layout, FILE *f) {
+  
+  int i, j, P, IsLabel, fontsize;
+  double fx, fy, dfx, dfy, range, major, minor, first, next;
+  char *fontname;
+
+  /* each axis is drawn independently */
+  fontname = GetRotFont (&fontsize);
+  fprintf (f, "1 setlinewidth\n");
+  for (i = 0; i < 4; i++) {
+    fx = layout[0].axis[i].fx;
+    fy = graphic.dy - layout[0].axis[i].fy;
+    dfx = layout[0].axis[i].dfx;
+    dfy = -layout[0].axis[i].dfy;
+    P = hypot ((double)layout[0].axis[(i+1)%2].dfx, (double)layout[0].axis[(i+1)%2].dfy);
+
+    if (layout[0].axis[i].isaxis) { DrawLine (fx, fy, dfx, dfy); }
+    
+    if (layout[0].axis[i].areticks) {
+      range = layout[0].axis[i].max - layout[0].axis[i].min;
+
+      AxisTickScale (&layout[0].axis[i], &major, &minor);
+
+      first = minor*((int)(layout[0].axis[i].min/minor));
+      if ((range > 0) && (first < layout[0].axis[i].min)) {
+	first += minor;
+      }
+      if ((range < 0) && (first > layout[0].axis[i].min)) {
+	first -= minor;
+      }
+      for (next = first; ((range > 0) && (next <= layout[0].axis[i].max)) || ((range < 0) && (next >= layout[0].axis[i].max));) {
+	IsLabel = FALSE;
+	if ((fabs((int)(next/major) - (next/major)) < 0.5*(minor/major)) || 
+	    (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)) ||
+	    (fabs ((int)((next - 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)))
+	  IsLabel = layout[0].axis[i].islabel;
+	PSTick (f, fx, fy, dfx, dfy, P, layout[0].axis[i].min, layout[0].axis[i].max, next, IsLabel, i);
+	if (range > 0) 
+	  next += minor;
+	else 
+	  next -= minor;
+      }
+    }
+  }
+}
+
+PSTick (FILE *f, double fx, double fy, double dfx, double dfy, int P, double min, double max, double value, int mode, int naxis) {
+  
+  int pos, dir, fontsize;
+  double size, n, x, y, dx, dy;
+  char string[64], *fontname;
+
+  if (mode == 1) { size = MAX (0.02, 7.0 / P); }
+  if (mode == 0) { size = MAX (0.01, 4.0 / P); }
+  
+  n = P / sqrt ((double)(dfx*dfx + dfy*dfy));
+  x = fx + (value-min)*dfx/(max - min);
+  y = fy + (value-min)*dfy/(max - min);
+
+  dir = -1;
+  if ((naxis == 0) || (naxis == 1)) dir = 1;
+  dx = dir*size*dfy*n;	
+  dy = dir*size*dfx*n;
+  
+  DrawLine (x, y, dx, dy);
+
+# ifdef IN_AND_OUT_TICKS
+# define SPACE 0.03
+# else
+# define SPACE 0.01
+# endif
+
+  if (mode == 1) {
+    fontname = GetRotFont (&fontsize);
+
+    /* temporarily assume rectilinear axes */
+    if (naxis == 0) { dx = 0; dy = -(0.8*fontsize + 1); pos = 1; }
+    if (naxis == 2) { dx = 0; dy = +(0.8*fontsize + 1); pos = 7; }
+
+    if (naxis == 1) { dy = 0; dx = -(0.8*fontsize + 1); pos = 3; }
+    if (naxis == 3) { dy = 0; dx = +(0.8*fontsize + 1); pos = 5; }
+
+    x = fx + (value-min)*dfx/(max - min) + dx;
+    y = fy + (value-min)*dfy/(max - min) + dy;
+    if (fabs(value) < 1e-14) { value = 0.0; }
+    sprintf (string, "%g\0", value);
+    PSRotText (f, (int)x, (int)y, string, pos, 0.0);
+  }
+  
+}
+
+  /* 
+  dx = size*dfy*n;	
+  dy = size*dfx*n;
+  DrawLine (x, y, dx, dy);
+  
+  dx = -size*dfy*n;	
+  dy = -size*dfx*n;
+  DrawLine (x, y, dx, dy);
+  */
+  
Index: /tags/start/Ohana/src/kapa/graph/PSLabels.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/PSLabels.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/PSLabels.c	(revision 12606)
@@ -0,0 +1,47 @@
+# include "Ximage.h"
+  
+void PSLabels (Layout *layout, FILE *f) {
+  
+  int dX, dY, Xoff;
+  int i, width, pos, x, y, size;
+  double angle;
+  char *fontname;
+  double cs, sn;
+
+  fontname = GetRotFont (&size);
+  for (i = 0; i < 8; i++) {
+    if (strcmp (layout[0].label[i].text, "")) {
+      angle = 0;
+      switch (i) {
+      case 0: pos = 7; break;
+      case 1: pos = 1; angle = -90; break;
+      case 2: pos = 1; break;
+      case 3: pos = 1; angle =  90; break;
+      case 4: pos = 2; break;
+      case 5: pos = 0; break;
+      case 6: pos = 8; break;
+      case 7: pos = 6; break;
+      }	
+      x = layout[0].label[i].x;
+      y = graphic.dy - layout[0].label[i].y;
+      SetRotFont (layout[0].label[i].font, layout[0].label[i].size); 
+      PSRotText (f, x, y, layout[0].label[i].text, pos, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+  /*
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|       |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+
+  */
+
+
Index: /tags/start/Ohana/src/kapa/graph/PSObjects.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/PSObjects.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/PSObjects.c	(revision 12606)
@@ -0,0 +1,671 @@
+# include "Ximage.h"
+# define XOFFSET 60
+# define YOFFSET 60
+
+void ClipLinePS (double, double, double, double, double, double, double, double, FILE *);
+
+int PSit (int mode) {
+
+  int i;
+  double scale;
+  FILE *f;
+  char filename[1024];
+  int Nbytes, status;
+
+  /* expect a line telling the number of bytes and a filename */
+  status = read (sock, filename, 16);
+  filename[16] = 0;
+  sscanf (filename, "%*s %d", &Nbytes);
+  status = read (sock, filename, Nbytes);
+  filename[status] = 0; /* make the string easy to parse */
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open output file %s\n", filename);
+    return (TRUE);  /* true because otherwise it quits kapa! */
+  }
+
+  /* two scaling options: expand to fit page / keep absolute size */ 
+  scale = 1;
+  if (mode == SCALE) {
+    scale = MIN (fabs(500.0 / graphic.dx), fabs (700.0 / graphic.dy));
+  } else {
+    scale = 72.0 / 96.0; /* ratio of screen pixels to points */
+  }
+
+  if (mode != RAW) {
+    fprintf (f, "%%!PS-Adobe-2.0 EPSF-2.0\n");
+    fprintf (f, "%%%%Title: Kapa Plot\n");
+    fprintf (f, "%%%%Creator: Kapa (0.95)\n");
+    fprintf (f, "%%%%BoundingBox: %d %d %.0f %.0f\n", 
+	     XOFFSET, YOFFSET, XOFFSET + scale*graphic.dx, YOFFSET + scale*graphic.dy);
+    fprintf (f, "%%%%Pages: 1\n");
+    fprintf (f, "%%%%DocumentFonts:\n");
+    fprintf (f, "%%%%EndComments\n");
+    fprintf (f, "%%%%EndProlog\n");
+    fprintf (f, "%%%%Page: 1 1\n\n");
+  } 
+  fprintf (f, "gsave %% encloses picture\n");
+  fprintf (f, "%% local abbreviations\n");
+  fprintf (f, "/Times-Roman findfont 14 scalefont setfont\n");
+  fprintf (f, "/T {moveto show stroke} def\n");
+  fprintf (f, "/B { newpath moveto dup 0 exch rlineto exch dup 0 rlineto exch -1 mul\n");
+  fprintf (f, " 0 exch rlineto -1 mul 0 rlineto closepath stroke } def\n");
+  fprintf (f, "/F { newpath moveto dup 0 exch rlineto exch dup 0 rlineto exch -1 mul\n");
+  fprintf (f, " 0 exch rlineto -1 mul 0 rlineto closepath fill stroke } def\n");
+  fprintf (f, "/C {0 360 arc stroke} def\n");
+  fprintf (f, "/L {newpath moveto lineto stroke} def\n\n");
+  fprintf (f, "/TF {newpath moveto lineto lineto fill stroke} def\n\n");
+
+  if (mode != RAW) {
+    fprintf (f, " %d %d translate\n", XOFFSET, YOFFSET);
+    fprintf (f, "  %f  %f scale\n", scale, scale);
+  }
+
+  for (i = 0; i < Nsection; i++) {
+    PSFrame (&section[i], f); 
+    PSObjects (&section[i], f);
+    PSLabels (&section[i], f);
+    PSPtext (&section[i], f);
+  }
+  
+  fprintf (f, "grestore %% end of picture\n");
+
+  if (mode != RAW) fprintf (f, "showpage\n");
+
+  fclose (f);
+  return (TRUE);
+
+}
+
+# define DrawLine(X1,Y1,X2,Y2) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f L\n", X1, graphic.dy - Y1, X2, graphic.dy - Y2))
+# define DrawCircle(X1,Y1,R) (fprintf (f, " %6.2f %6.2f %6.2f C\n", (X1), (graphic.dy - Y1), (R)))
+# define DrawRectangle(X,Y,dX,dY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f B\n", (dX), (dY), (X-0.5*dX), (graphic.dy-Y-0.5*dY)))
+# define FillRectangle(X,Y,dX,dY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f F\n", (dX), (dY), (X-0.5*dX), (graphic.dy-Y-0.5*dY)))
+# define FillTriangle(X1,Y1,X2,Y2, X3, Y3) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f TF\n", (X1), (graphic.dy-Y1), (X2), (graphic.dy-Y2), (X3), (graphic.dy-Y3)))
+# define CONNECT 0
+# define HISTOGRAM 1
+# define POINTS 2
+
+int PSObjects (Layout *layout, FILE *f) {
+  
+  int i, ltype;
+  double lweight;
+  static char dash[] = "5";
+  static char dot[] = "3";
+  
+  for (i = 0; i < layout[0].Nobjects; i++) {
+    switch (layout[0].objects[i].ltype) {
+    case 0:
+      break;
+    case 1:
+      fprintf (f, "[%s] 0 setdash\n", dash);
+      break;
+    case 2:
+      fprintf (f, "[%s] 0 setdash\n", dot);
+      break;
+    default:
+      break;
+    }
+    
+    lweight = MAX (0, MIN (10, layout[0].objects[i].lweight));
+    fprintf (f, "%.1f setlinewidth\n", lweight);
+    fprintf (f, "%s setrgbcolor\n", GRAPHCOLORS[layout[0].objects[i].color][1]);
+
+    switch (layout[0].objects[i].style) {
+    case CONNECT: 
+      PSConnect (layout, &layout[0].objects[i], f);
+      break;
+    case HISTOGRAM:
+      PSHistogram (layout, &layout[0].objects[i], f);
+      break;
+    case POINTS:
+      PSPoints (layout, &layout[0].objects[i], f);
+      break;
+    }
+
+    if (layout[0].objects[i].etype & 0x01) {
+      PSYErrors (layout, &layout[0].objects[i], f);
+    }
+    if (layout[0].objects[i].etype & 0x02) {
+      PSXErrors (layout, &layout[0].objects[i], f);
+    }
+    fprintf (f, "[] 0 setdash\n");
+    fprintf (f, "0.00 0.00 0.00 setrgbcolor\n");
+  }
+}
+
+/*******/
+void PSConnect (Layout *layout, Gobjects *object, FILE *f) {
+  
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1;
+  double X0, X1, Y0, Y1;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0); 
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0); 
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = layout[0].axis[0].fx;
+  X1 = layout[0].axis[0].fx + layout[0].axis[0].dfx;
+  Y0 = layout[0].axis[1].fy;
+  Y1 = layout[0].axis[1].fy + layout[0].axis[1].dfy;
+
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+  
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    ClipLinePS (sx0, sy0, sx1, sy1, X0, Y0, X1, Y1, f);
+    /* DrawLine (sx0, sy0, sx1, sy1); */
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+void ClipLinePS (double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0, FILE *f) {
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x0,y0 if outside box */
+  if ((x0 < X0) && (x1 >= X0)) {
+    y0 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X0;
+  }
+  if ((x0 > X1) && (x1 <= X1)) {
+    y0 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X1;
+  }
+  if ((y0 < Y0) && (y1 >= Y0)) {
+    x0 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y0;
+  }
+  if ((y0 > Y1) && (y1 <= Y1)) {
+    x0 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y1;
+  }
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x1,y1 if outside box */
+  if ((x1 < X0) && (x0 >= X0)) {
+    y1 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X0;
+  }
+  if ((x1 > X1) && (x0 <= X1)) {
+    y1 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X1;
+  }
+  if ((y1 < Y0) && (y0 >= Y0)) {
+    x1 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y0;
+  }
+  if ((y1 > Y1) && (y0 <= Y1)) {
+    x1 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y1;
+  }
+  DrawLine (x0, y0, x1, y1);
+}
+
+/*******/
+void PSHistogram (Layout *layout, Gobjects *object, FILE *f) {
+
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sxa;
+  double X0, X1, Y0, Y1;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0); 
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0); 
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = layout[0].axis[0].fx;
+  X1 = layout[0].axis[0].fx + layout[0].axis[0].dfx;
+  Y0 = layout[0].axis[1].fy;
+  Y1 = layout[0].axis[1].fy + layout[0].axis[1].dfy;
+
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[0]*mxi + y[0]*mxj + bx;
+  sy0 = x[0]*myi + y[0]*myj + by;
+  sx0 = MIN (MAX (sx0, X0), X1);
+  sy0 = MAX (MIN (sy0, Y0), Y1);
+  
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    sx1 = MIN (MAX (sx1, X0), X1);
+    sy1 = MAX (MIN (sy1, Y0), Y1);
+    sxa = 0.5*(sx0 + sx1);
+    DrawLine (sx0, sy0, sxa, sy0);
+    DrawLine (sxa, sy0, sxa, sy1);
+    DrawLine (sxa, sy1, sx1, sy1);
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+/*******/
+void PSPoints (Layout *layout, Gobjects *object, FILE *f) {
+ 
+  int i;
+  float *x, *y, *z;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx, sy, d, sx1, sy1, sx2, sy2;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);  
+ 
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);  
+
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  /* below here, code is identical with DrawObjects */
+  /**** points are scaled by object.z ***/
+  if (object[0].size < 0) {
+    d = 0.5 * (graphic.dx + graphic.dy) * 0.01;
+    x = object[0].x; y = object[0].y; z = object[0].z;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx, sy, 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {	/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx, sy, 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy, sx + d*z[i], sy);
+	    DrawLine (sx, sy - d*z[i], sx, sy + d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {	/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx + d*z[i], sy - d*z[i], sx - d*z[i], sy + d*z[i]);
+	    DrawLine (sx - d*z[i], sy - d*z[i], sx + d*z[i], sy + d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    FillTriangle (sx - d*z[i], sy - 0.58*d*z[i], sx + d*z[i], sy - 0.58*d*z[i], sx, sy + 1.15*d*z[i]);
+	    /*
+	    DrawLine (sx - d*z[i], sy + 0.58*d*z[i], sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx + d*z[i], sy + 0.58*d*z[i], sx,          sy - 1.15*d*z[i]);
+	    DrawLine (sx,          sy - 1.15*d*z[i], sx - d*z[i], sy + 0.58*d*z[i]);
+	    */
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy + 0.58*d*z[i], sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx + d*z[i], sy + 0.58*d*z[i], sx,          sy - 1.15*d*z[i]);
+	    DrawLine (sx,          sy - 1.15*d*z[i], sx - d*z[i], sy + 0.58*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx,          sy - 1.15*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	/* connect a pair of points */
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  } else {
+    d = object[0].size * 0.5 * (graphic.dx + graphic.dy) * 0.003;
+    x = object[0].x; y = object[0].y;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx, sy, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {		/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+   	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx, sy, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy, sx + d, sy);
+	    DrawLine (sx, sy - d, sx, sy + d);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {		/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx + d, sy - d, sx - d, sy + d);
+	    DrawLine (sx - d, sy - d, sx + d, sy + d);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    /*
+	    DrawLine (sx - d, sy + 0.58*d, sx + d, sy + 0.58*d);
+	    DrawLine (sx + d, sy + 0.58*d, sx,     sy - 1.15*d);
+	    DrawLine (sx,     sy - 1.15*d, sx - d, sy + 0.58*d);
+	    */
+	    FillTriangle (sx - d, sy - 0.58*d, sx + d, sy - 0.58*d, sx, sy + 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy - 0.58*d, sx + d, sy - 0.58*d);
+	    DrawLine (sx + d, sy - 0.58*d, sx,     sy + 1.15*d);
+	    DrawLine (sx,     sy + 1.15*d, sx - d, sy - 0.58*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d, sy - 0.58*d);
+	    DrawLine (sx, sy, sx + d, sy - 0.58*d);
+	    DrawLine (sx, sy, sx,     sy + 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  }
+}
+    
+/*******/
+void PSXErrors (Layout *layout, Gobjects *object, FILE *f) {
+  
+  int i, bar;
+  float *x, *y, *dxm, *dxp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dxp = object[0].dxp; dxm = object[0].dxm; 
+  bar = object[0].ebar; sz = object[0].size*layout[0].axis[1].dfy*0.03;
+   
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] + dxp[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] + dxp[i])*myi + y[i]*myj + by;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxm[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] - dxm[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] - dxm[i])*myi + y[i]*myj + by;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+  }
+}
+
+    
+/*******/
+void PSYErrors (Layout *layout, Gobjects *object, FILE *f) {
+  
+  int i, bar;
+  float *x, *y, *dym, *dyp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+  
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dyp = object[0].dyp; dym = object[0].dym; 
+  bar = object[0].ebar; sz = object[0].size*layout[0].axis[0].dfx*0.03;
+  
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dyp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = x[i]*mxi + (y[i] + dyp[i])*mxj + bx;
+    sy1 = x[i]*myi + (y[i] + dyp[i])*myj + by;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dym[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = x[i]*mxi + (y[i] - dym[i])*mxj + bx;
+    sy1 = x[i]*myi + (y[i] - dym[i])*myj + by;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+  }
+}
Index: /tags/start/Ohana/src/kapa/graph/PSPtext.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/PSPtext.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/PSPtext.c	(revision 12606)
@@ -0,0 +1,33 @@
+# include "Ximage.h"
+  
+void PSPtext (Layout *layout, FILE *f) {
+
+  int i, width, pos, x, y, size;
+  double angle;
+  char *fontname;
+
+  fontname = GetRotFont (&size);
+  for (i = 0; i < layout[0].Nptext; i++) {
+    if (strcmp (layout[0].ptext[i].text, "")) {
+      angle = layout[0].ptext[i].angle;
+      x = layout[0].ptext[i].x;
+      y = graphic.dy - layout[0].ptext[i].y;
+      SetRotFont (layout[0].ptext[i].font, layout[0].ptext[i].size);
+      PSRotText (f, x, y, layout[0].ptext[i].text, 5, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+  /* pos values
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|   8   |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+
+  */
Index: /tags/start/Ohana/src/kapa/graph/SetLimits.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/SetLimits.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/SetLimits.c	(revision 12606)
@@ -0,0 +1,38 @@
+# include "Ximage.h"
+# define SCAN \
+status = read (sock, buffer, 16); \
+buffer[16] = 0; \
+sscanf (buffer, "%*s %d", &Nbytes); \
+status = read (sock, buffer, Nbytes); \
+buffer[status] = 0;
+
+int SetLimits () {
+  
+  int i, status, Nbytes;
+  char buffer[128];
+  double xmin, xmax, ymin, ymax;
+  Layout *layout;
+
+  layout = &section[TheSection];
+
+  SCAN;
+  sscanf (buffer, "%lf %lf %lf %lf", &xmin, &xmax, &ymin, &ymax);
+
+  layout[0].axis[2].min = layout[0].axis[0].min = xmin;
+  layout[0].axis[2].max = layout[0].axis[0].max = xmax;
+  layout[0].axis[3].min = layout[0].axis[1].min = ymin; 
+  layout[0].axis[3].max = layout[0].axis[1].max = ymax;
+  
+  for (i = 0; i < layout[0].Nobjects; i++) {
+    layout[0].objects[i].x0 = xmin;
+    layout[0].objects[i].x1 = xmax;
+    layout[0].objects[i].y0 = ymin;
+    layout[0].objects[i].y1 = ymax;
+  }
+
+  XClearWindow (graphic.display, graphic.window);
+  Refresh (1);
+
+  return (TRUE);
+  
+}
Index: /tags/start/Ohana/src/kapa/graph/cursor.c
===================================================================
--- /tags/start/Ohana/src/kapa/graph/cursor.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/graph/cursor.c	(revision 12606)
@@ -0,0 +1,88 @@
+# include "Ximage.h"
+# define EventMask (long) (KeyPressMask | ExposureMask | StructureNotifyMask)
+
+int cursor () {
+
+  XEvent          event;
+  KeySym          keysym;
+  int             status, xstatus, value;
+  XComposeStatus  composestatus;
+  char            string[10], line[35];
+  double          x, y;
+  char            buffer[10];
+  Layout         *layout;
+  
+  layout = &section[TheSection];
+
+  while (1) {
+    
+    /* check the pipe for messages */
+    status = read (sock, buffer, 4);
+    buffer[4] = 0;
+    
+    switch (status) {
+    case -1:
+      /* no input from pipe: continue */
+      break;
+      
+    case 0:
+      fprintf (stderr, "pipe has died!\n");
+      return (FALSE);
+      break;
+
+    case 4:
+      if (!strcmp (buffer, "NCUR")) {  /* stop reading cursor */
+	return (TRUE);
+      }
+      break;
+
+    default:
+      fprintf (stderr, "weird signal: too many or few bytes!  %d\n", status);
+      return (TRUE);
+      break;
+    }
+
+    if (XEventsQueued (graphic.display, QueuedAfterFlush) < 1){
+      usleep (10000);
+      continue;
+    }
+
+    /* check for x events */
+    if (XCheckMaskEvent (graphic.display, EVENT_MASK, &event)) {
+      
+      switch (event.type)  {
+
+      case MotionNotify:
+	break;
+
+      case Expose:
+	if (HAVE_BACKING) {
+	  continue;
+	}
+	if (XEventsQueued (graphic.display, QueuedAlready) < 2) {
+	  Refresh (1);
+	}
+	break;
+	
+      case ConfigureNotify:
+	status = Reconfig (&event);
+	break;
+	
+      case MappingNotify:
+	XRefreshKeyboardMapping ((XMappingEvent *) &event);
+	break;
+	
+      case KeyPress:
+	string[0] = 0;
+	value = XLookupString ((XKeyEvent *) &event, string, 9, &keysym, &composestatus);
+	x = (event.xkey.x - layout[0].axis[0].fx)*(layout[0].axis[0].max - layout[0].axis[0].min)/layout[0].axis[0].dfx + layout[0].axis[0].min;
+	y = (event.xkey.y - layout[0].axis[1].fy)*(layout[0].axis[1].max - layout[0].axis[1].min)/layout[0].axis[1].dfy + layout[0].axis[1].min;
+	if ((value > 0) && (isdigit(string[0]) || isalpha(string[0]))) {
+	  sprintf (line, "%c %12.6f %12.6f \0", string[0], x, y);
+	  write (sock, line, 32);
+	}
+	break;
+      }
+    }
+  }
+}
Index: /tags/start/Ohana/src/kapa/include/Ximage.h
===================================================================
--- /tags/start/Ohana/src/kapa/include/Ximage.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/include/Ximage.h	(revision 12606)
@@ -0,0 +1,5 @@
+# include <Xohana.h>
+# include "constants.h"
+# include "structures.h"
+# include "prototypes.h"
+# include "globals.h"
Index: /tags/start/Ohana/src/kapa/include/alphabet.h
===================================================================
--- /tags/start/Ohana/src/kapa/include/alphabet.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/include/alphabet.h	(revision 12606)
@@ -0,0 +1,69 @@
+typedef struct {
+  int dx, dy, ascent;
+  char *bits;
+} RotFont;
+
+typedef struct {
+  RotFont *font;
+  char name[64];
+  int size;
+} FontSet;
+
+# include "../rotfont/times8.h"
+# include "../rotfont/times12.h"
+# include "../rotfont/times14.h"
+# include "../rotfont/times18.h"
+# include "../rotfont/times24.h"
+
+# include "../rotfont/courier8.h"
+# include "../rotfont/courier12.h"
+# include "../rotfont/courier14.h"
+# include "../rotfont/courier18.h"
+# include "../rotfont/courier24.h"
+
+# include "../rotfont/helvetica8.h"
+# include "../rotfont/helvetica12.h"
+# include "../rotfont/helvetica14.h"
+# include "../rotfont/helvetica18.h"
+# include "../rotfont/helvetica24.h"
+
+# include "../rotfont/symbol8.h"
+# include "../rotfont/symbol12.h"
+# include "../rotfont/symbol14.h"
+# include "../rotfont/symbol18.h"
+# include "../rotfont/symbol24.h"
+
+# define DEFFONT 1
+static FontSet HardwiredFonts[] = {
+  {times8font,  "times", 8},
+  {times12font, "times", 12},
+  {times14font, "times", 14},
+  {times18font, "times", 18},
+  {times24font, "times", 24},
+  
+  {courier8font,  "courier", 8},
+  {courier12font, "courier", 12},
+  {courier14font, "courier", 14},
+  {courier18font, "courier", 18},
+  {courier24font, "courier", 24},
+  
+  {helvetica8font,  "helvetica", 8},
+  {helvetica12font, "helvetica", 12},
+  {helvetica14font, "helvetica", 14},
+  {helvetica18font, "helvetica", 18},
+  {helvetica24font, "helvetica", 24},
+  
+  {symbol8font,  "symbol", 8},
+  {symbol12font, "symbol", 12},
+  {symbol14font, "symbol", 14},
+  {symbol18font, "symbol", 18},
+  {symbol24font, "symbol", 24}
+};
+
+int Nallfonts;
+FontSet *AllFonts;
+RotFont *activefont;
+double activescale;
+
+char currentname[64];
+int  currentsize;
Index: /tags/start/Ohana/src/kapa/include/buttons.h
===================================================================
--- /tags/start/Ohana/src/kapa/include/buttons.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/include/buttons.h	(revision 12606)
@@ -0,0 +1,120 @@
+#define PS_width 25
+#define PS_height 25
+static char PS_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x81, 0x3f, 0x00,
+   0x82, 0x67, 0x60, 0x00, 0x02, 0x26, 0x40, 0x00, 0x02, 0x24, 0x40, 0x00,
+   0x02, 0x24, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00,
+   0x02, 0x24, 0x00, 0x00, 0x02, 0x64, 0x00, 0x00, 0x02, 0xc6, 0x00, 0x00,
+   0x82, 0x07, 0x07, 0x00, 0xfe, 0x01, 0x0c, 0x00, 0x02, 0x00, 0x18, 0x00,
+   0x02, 0x00, 0x20, 0x00, 0x02, 0x00, 0x60, 0x00, 0x02, 0x00, 0x40, 0x00,
+   0x02, 0x00, 0xc0, 0x00, 0x02, 0x10, 0x80, 0x00, 0x02, 0x10, 0xc0, 0x00,
+   0x02, 0x60, 0x60, 0x00, 0x02, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00}; 
+#define grey_width 25
+#define grey_height 25
+static char grey_bits[] = {
+   0x90, 0x40, 0xf7, 0x01, 0x04, 0xaa, 0xad, 0x01, 0x68, 0xd5, 0xfe, 0x01,
+   0x82, 0x28, 0xdb, 0x01, 0x10, 0xd2, 0x75, 0x01, 0x40, 0xad, 0xee, 0x01,
+   0xac, 0x50, 0xbf, 0x01, 0x00, 0xaa, 0xf9, 0x01, 0x52, 0xd5, 0xd6, 0x01,
+   0x80, 0x28, 0x6f, 0x01, 0x28, 0xd2, 0xfd, 0x01, 0x44, 0xad, 0xba, 0x01,
+   0x90, 0x50, 0xf7, 0x01, 0x02, 0xaa, 0xcd, 0x01, 0x68, 0xd5, 0x7e, 0x01,
+   0x80, 0x28, 0xfb, 0x01, 0x14, 0xd2, 0xb5, 0x01, 0x40, 0xad, 0xee, 0x01,
+   0xaa, 0x50, 0xdf, 0x01, 0x00, 0xaa, 0x79, 0x01, 0x50, 0xd5, 0xf6, 0x01,
+   0x84, 0x28, 0xaf, 0x01, 0x28, 0xd2, 0xfd, 0x01, 0x40, 0xad, 0xda, 0x01,
+   0x90, 0x50, 0x77, 0x01};
+#define rainbow_width 25
+#define rainbow_height 25
+static char rainbow_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x80, 0xff, 0x00, 0x00, 0x70, 0x00, 0x01, 0x00, 0x0c, 0x7f, 0x00,
+   0x00, 0xe3, 0x80, 0x01, 0xc0, 0x9c, 0xff, 0x00, 0x20, 0x62, 0x00, 0x01,
+   0x90, 0x99, 0xff, 0x00, 0x48, 0x76, 0x00, 0x01, 0x24, 0x09, 0x00, 0x00,
+   0x94, 0x06, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00,
+   0xa5, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+   0x2a, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+   0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
+   0x15, 0x00, 0x00, 0x00};
+#define recenter_width 25
+#define recenter_height 25
+static char recenter_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00,
+   0x80, 0xef, 0x03, 0x00, 0xe0, 0x00, 0x0e, 0x00, 0x30, 0x00, 0x18, 0x00,
+   0x10, 0x00, 0x10, 0x00, 0x18, 0x00, 0x30, 0x00, 0x08, 0x00, 0x20, 0x00,
+   0x0c, 0x00, 0x60, 0x00, 0x0c, 0x38, 0x60, 0x00, 0x0c, 0x7c, 0x60, 0x00,
+   0x04, 0x7c, 0x40, 0x00, 0x0c, 0x7c, 0x60, 0x00, 0x0c, 0x38, 0x60, 0x00,
+   0x0c, 0x00, 0x60, 0x00, 0x08, 0x00, 0x20, 0x00, 0x18, 0x00, 0x30, 0x00,
+   0x10, 0x00, 0x10, 0x00, 0x30, 0x00, 0x18, 0x00, 0xe0, 0x00, 0x0e, 0x00,
+   0x80, 0xef, 0x03, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define puns_width 25
+#define puns_height 25
+static char puns_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0xd8, 0x01,
+   0x00, 0x0c, 0x37, 0x00, 0xf8, 0xc9, 0x6f, 0x00, 0x0c, 0xde, 0xf0, 0x00,
+   0x06, 0x5b, 0x1f, 0x00, 0x7b, 0xd9, 0x0c, 0x00, 0xc9, 0x70, 0x06, 0x00,
+   0x81, 0x71, 0x03, 0x00, 0x78, 0xb9, 0x39, 0x00, 0xc8, 0xdb, 0x0f, 0x00,
+   0x84, 0xf7, 0x7f, 0x00, 0x04, 0xff, 0xc3, 0x00, 0xe6, 0xfe, 0x8e, 0x00,
+   0x9a, 0x7d, 0x0b, 0x00, 0x08, 0xbc, 0x01, 0x00, 0x08, 0xfc, 0x3f, 0x00,
+   0x0c, 0xff, 0x78, 0x00, 0x84, 0x39, 0x60, 0x00, 0x40, 0x38, 0x40, 0x00,
+   0x60, 0x38, 0x40, 0x00, 0x20, 0x38, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00,
+   0x00, 0xd6, 0x00, 0x00};
+#define red_width 25
+#define red_height 25
+static char red_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xfc, 0x03, 0x00,
+   0x20, 0x07, 0x06, 0x00, 0xe0, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x08, 0x00,
+   0x20, 0x00, 0x08, 0x00, 0x20, 0x00, 0x08, 0x00, 0x20, 0x00, 0x08, 0x00,
+   0x20, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x06, 0x00, 0x20, 0x80, 0x01, 0x00,
+   0x20, 0xe0, 0x00, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xe0, 0xc3, 0x00, 0x00,
+   0x20, 0xc0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x20, 0x80, 0x01, 0x00,
+   0x20, 0x00, 0x01, 0x00, 0x20, 0x00, 0x01, 0x00, 0x20, 0x00, 0x03, 0x00,
+   0x20, 0x00, 0x06, 0x00, 0x20, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x18, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define green_width 25
+#define green_height 25
+static char green_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00,
+   0x00, 0x06, 0x04, 0x00, 0x80, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0x40, 0x80, 0x0f, 0x00, 0x40, 0xc0, 0x30, 0x00,
+   0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x08, 0x00,
+   0x00, 0x03, 0x08, 0x00, 0x00, 0x7e, 0x0e, 0x00, 0x00, 0xc0, 0x03, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define blue_width 25
+#define blue_height 25
+static char blue_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xfe, 0x00, 0x00,
+   0xc0, 0x83, 0x07, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x08, 0x00,
+   0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00,
+   0x40, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x04, 0x00, 0x40, 0x00, 0x02, 0x00,
+   0x40, 0x80, 0x07, 0x00, 0x40, 0xe0, 0x0c, 0x00, 0xc0, 0x3f, 0x08, 0x00,
+   0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00,
+   0x40, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x06, 0x00, 0x40, 0x00, 0x02, 0x00,
+   0xc0, 0x80, 0x03, 0x00, 0x40, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define yellow_width 25
+#define yellow_height 25
+static char yellow_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00,
+   0x80, 0x01, 0x0c, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x02, 0x02, 0x00,
+   0x00, 0x84, 0x01, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00,
+   0x00, 0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+   0x00, 0x30, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define hms_width 25
+#define hms_height 25
+static char hms_bits[] = {
+   0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+   0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0xf0, 0x00, 0x1e, 0xef, 0x89, 0x00,
+   0x22, 0x11, 0x09, 0x00, 0x22, 0x11, 0x71, 0x00, 0x22, 0x11, 0x81, 0x00,
+   0x22, 0x11, 0x89, 0x00, 0x22, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x1e, 0xc7, 0xf1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x80, 0x00,
+   0x40, 0x80, 0x80, 0x00, 0x40, 0x80, 0x80, 0x00, 0x40, 0x80, 0x80, 0x00,
+   0x40, 0x80, 0x80, 0x00, 0x5c, 0xb8, 0xb8, 0x00, 0x62, 0xc4, 0xc4, 0x00,
+   0x42, 0x84, 0x84, 0x00, 0x42, 0x84, 0x84, 0x00, 0x62, 0xc4, 0xc4, 0x00,
+   0x5c, 0xb9, 0xb8, 0x00};
Index: /tags/start/Ohana/src/kapa/include/constants.h
===================================================================
--- /tags/start/Ohana/src/kapa/include/constants.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/include/constants.h	(revision 12606)
@@ -0,0 +1,19 @@
+/* hardwired values for some window parameters */
+# define EVENT_MASK (long) (ButtonPressMask | ClientMessage | ButtonReleaseMask | KeyPressMask | ExposureMask | StructureNotifyMask | PointerMotionMask)
+# define DEFAULT_CURSOR XC_crosshair
+# define BORDER_WIDTH 2
+# define MIN_WIDTH 250
+# define MIN_HEIGHT 250
+
+/* label names */
+# define LABELX0 0
+# define LABELY0 1
+# define LABELX1 2
+# define LABELY1 3
+# define LABELUL 4
+# define LABELUR 5
+# define LABELLL 6
+# define LABELLR 7
+
+enum {SCALE, NOSCALE, RAW};
+
Index: /tags/start/Ohana/src/kapa/include/globals.h
===================================================================
--- /tags/start/Ohana/src/kapa/include/globals.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/include/globals.h	(revision 12606)
@@ -0,0 +1,17 @@
+
+int HAVE_BACKING;
+int DEBUG;
+
+/* file descriptor for socket connection to mana */
+int sock; 
+
+/* each layout / section defines one of the active portions of the graphics window
+   there may be an arbitrary number of sections, and each section may fill an arbitrary
+   rectangle in the X window.  The startup configuration assumes 1 section filling the 
+   entire X window. */
+
+Layout *section;
+int    Nsection, TheSection;
+
+/* graphic defines the basic details of the X window */
+Graphic graphic;
Index: /tags/start/Ohana/src/kapa/include/icons/arrow.h
===================================================================
--- /tags/start/Ohana/src/kapa/include/icons/arrow.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/include/icons/arrow.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define arrow_width 6
+#define arrow_height 9
+static char arrow_bits[] = {
+   0x00, 0x02, 0x06, 0x0e, 0x1e, 0x0e, 0x06, 0x02, 0x00};
Index: /tags/start/Ohana/src/kapa/include/icons/back.h
===================================================================
--- /tags/start/Ohana/src/kapa/include/icons/back.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/include/icons/back.h	(revision 12606)
@@ -0,0 +1,6 @@
+#define back_width 16
+#define back_height 16
+static char back_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x3c, 0x00, 0x3f, 0xc0, 0x3f,
+   0xf0, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xf0, 0x3f, 0xc0, 0x3f, 0x00, 0x3f,
+   0x00, 0x3c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00};
Index: /tags/start/Ohana/src/kapa/include/icons/down.h
===================================================================
--- /tags/start/Ohana/src/kapa/include/icons/down.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/include/icons/down.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define down_width 9
+#define down_height 6
+static char down_bits[] = {
+   0x00, 0x00, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00};
Index: /tags/start/Ohana/src/kapa/include/icons/fore.h
===================================================================
--- /tags/start/Ohana/src/kapa/include/icons/fore.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/include/icons/fore.h	(revision 12606)
@@ -0,0 +1,6 @@
+#define fore_width 16
+#define fore_height 16
+static char fore_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x3c, 0x00, 0xfc, 0x00, 0xfc, 0x03,
+   0xfc, 0x0f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x0f, 0xfc, 0x03, 0xfc, 0x00,
+   0x3c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00};
Index: /tags/start/Ohana/src/kapa/include/icons/icon.h
===================================================================
--- /tags/start/Ohana/src/kapa/include/icons/icon.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/include/icons/icon.h	(revision 12606)
@@ -0,0 +1,13 @@
+#define icon_width 29
+#define icon_height 29
+static unsigned char icon_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x07,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0xfc, 0xff, 0xff, 0x07,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0xfc, 0xff, 0xff, 0x07,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0xfc, 0xff, 0xff, 0x07,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0xfc, 0xff, 0xff, 0x07,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Index: /tags/start/Ohana/src/kapa/include/icons/stop.h
===================================================================
--- /tags/start/Ohana/src/kapa/include/icons/stop.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/include/icons/stop.h	(revision 12606)
@@ -0,0 +1,6 @@
+#define stop_width 16
+#define stop_height 16
+static char stop_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f,
+   0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f,
+   0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Index: /tags/start/Ohana/src/kapa/include/prototypes.h
===================================================================
--- /tags/start/Ohana/src/kapa/include/prototypes.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/include/prototypes.h	(revision 12606)
@@ -0,0 +1,131 @@
+
+# if (OLDPROTO) 
+/***** Prototypes for image ***************/
+
+void          PositionPictures    PROTO((Layout *, Graphic *));
+void          CreateColorbar      PROTO((Layout *, Graphic *));
+void          CreatePicture       PROTO((Layout *, Graphic *));
+void          CreateZoom          PROTO((Layout *, Graphic *, double, double));
+void          Remap               PROTO((Layout *, Matrix  *));
+int           NewPicture          PROTO((Graphic *, Layout *));
+void          Reorient            PROTO((Graphic *, Layout *, XButtonEvent *));
+int           UpdatePointer       PROTO((Graphic *, Layout *, XMotionEvent *));
+void          CrossHairs          PROTO((Graphic *, Layout *));
+int           LoadOverlay         PROTO((Graphic *, Layout *));
+int           SaveOverlay         PROTO((Graphic *, Layout *));
+int           CSaveOverlay         PROTO((Graphic *, Layout *));
+int           EraseOverlay        PROTO((Graphic *, Layout *));
+void          StatusBox           PROTO((Graphic *, Layout *));
+void          PaintOverlay        PROTO((Graphic *, Layout *, int));
+
+/***** Prototypes for action ***************/
+
+int           CheckPipe           PROTO((Graphic *, Layout *));
+void          DefineLayout        PROTO((Layout *, Graphic *, int, char **));
+int           EventLoop           PROTO((Graphic *, Layout *));
+int           InPicture           PROTO((XButtonEvent *, Picture *));
+int           InterpretKeys       PROTO((Graphic *, Layout *, XEvent *));
+int           InterpretPresses    PROTO((Graphic *, Layout *, XButtonEvent *));
+int           Reconfig            PROTO((Graphic *, Layout *, XEvent *));
+void          Refresh             PROTO((Graphic *, Layout *, int));
+int           Stop                PROTO((Graphic *, Layout *));
+int           PSit                PROTO((Graphic *, Layout *));
+int           get_argument        PROTO((int, char **, char *));
+int           remove_argument     PROTO((int, int *, char **));
+void          DragColorbar        PROTO((Graphic *, Layout *, XButtonEvent *));
+void          ResetColorbar       PROTO((Graphic *, Layout *, double, double));
+void          MakeColormap        PROTO((Graphic *, Layout *, int, char **));
+
+/***** Prototypes for button ***************/
+
+Button       *CheckButtons        PROTO((XButtonEvent *, Layout *));
+void          DrawButton          PROTO((Graphic *, Button *));
+void          FlashButton         PROTO((Graphic *, Button *));
+int           InButton            PROTO((XButtonEvent *, Button *));
+void          InvertButton        PROTO((Graphic *, Button *));
+int           greycolors          PROTO((Graphic *, Layout *));
+int           rainbow             PROTO((Graphic *, Layout *));
+int           puns                PROTO((Graphic *, Layout *));
+int           Recenter            PROTO((Graphic *, Layout *));
+int           RecenterRescale     PROTO((Graphic *, Layout *));
+int           Rescale             PROTO((Graphic *, Layout *));
+int           ToggleDEG           PROTO((Graphic *, Layout *));
+int           Overlay0            PROTO((Graphic *, Layout *));
+int           Overlay1            PROTO((Graphic *, Layout *));
+int           Overlay2            PROTO((Graphic *, Layout *));
+int           Overlay3            PROTO((Graphic *, Layout *));
+
+/***** Prototypes for xtools ***************/
+
+void          CheckColors         PROTO((Graphic *, int *, char **));
+void          CheckDisplayName    PROTO((int *, char **, char *));
+void          CheckFontName       PROTO((int *, char **, char *));
+void          CheckGeometry       PROTO((int *, char **, Graphic *));
+void          CloseDisplay        PROTO((Graphic *));
+void          CreateWindow        PROTO((Graphic *, Window, int, long));
+void          DrawBitmap          PROTO((Graphic *, int, int, int, int, char *, int));
+unsigned long GetColor            PROTO((Display *, char *, Colormap, unsigned long));
+void          LoadFont            PROTO((Graphic *, int *, char **, char *));
+void          MakeCursor          PROTO((Graphic *, unsigned int));
+void          MakeGC              PROTO((Graphic *));
+void          MapWindow           PROTO((Graphic *));
+void          NameWindow          PROTO((Graphic *, char *));
+Display      *OpenDisplay         PROTO((char *, int *));
+void          QuitX               PROTO((Display *, char *, char *));
+void          SetNormalHints      PROTO((Graphic *));
+Display      *SetUpDisplay        PROTO((Graphic *, int *, char **));
+void          SetUpWindow         PROTO((Graphic *, int *, char **));
+void          SetWMHints          PROTO((Graphic *, Icon *));
+void          TopWindow           PROTO((Graphic *, Icon *));
+
+void          hh_hms              PROTO((char *, double, double, char));
+# endif 
+
+Display *SetUpDisplay (int *, char **);
+Display *OpenDisplay (char *, int *);
+void CheckDisplayName (int *, char **, char *);
+void CheckColors (int *, char **);
+void SetUpWindow (int *, char **);
+void CheckGeometry (int *, char **);
+void TopWindow (Icon *);
+void QuitX (Display *, char *, char *);
+void CreateWindow (Window, int, long);
+void MakeCursor (unsigned int);
+void CheckFontName (int *, char **, char *);
+void LoadFont (int *, char **, char *);
+void SetNormalHints ();
+void SetWMHints (Icon *);
+void NameWindow (char *);
+void MapWindow ();
+void MakeColormap (int, char **);
+void DefineLayout (int, char **);
+void PositionPicture (Layout *);
+void DrawFrame (Layout *);
+int DrawObjects (Layout *);
+int DrawObjectN (Layout *, Gobjects *);
+void DrawConnect (Layout *, Gobjects *);
+void DrawHistogram (Layout *, Gobjects *);
+void DrawPoints (Layout *, Gobjects *);
+void DrawXErrors (Layout *, Gobjects *);
+void DrawYErrors (Layout *, Gobjects *);
+void DrawLabels (Layout *);
+void Refresh (int);
+int CheckPipe ();
+int PSit (int);
+int PSObjects (Layout *, FILE *);
+void PSConnect (Layout *, Gobjects *, FILE *);
+void PSHistogram (Layout *, Gobjects *, FILE *);
+void PSPoints (Layout *, Gobjects *, FILE *);
+void PSXErrors (Layout *, Gobjects *, FILE *);
+void PSYErrors (Layout *, Gobjects *, FILE *);
+int LoadObject ();
+int LoadVectorData (Layout *, int, char *);
+int SetLimits ();
+int LoadLabels ();
+int SetFont ();
+int cursor ();
+int ErasePlot ();
+int Reconfig (XEvent *);
+int LoadBox ();
+int PSFrame (Layout *, FILE *);
+void PSLabels (Layout *, FILE *);
Index: /tags/start/Ohana/src/kapa/include/structures.h
===================================================================
--- /tags/start/Ohana/src/kapa/include/structures.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/include/structures.h	(revision 12606)
@@ -0,0 +1,156 @@
+/** this list must match the one in mana/include/package.h, and equiv */
+# define NGRAPHCOLORS 23
+static char GRAPHCOLORS[NGRAPHCOLORS][2][15] = {
+"black",    "0.00 0.00 0.00", 
+"white",    "1.00 1.00 1.00", 
+"red",      "1.00 0.00 0.00", 
+"pink",     "1.00 0.75 0.80", 
+"orange",   "1.00 0.65 0.00", 
+"yellow",   "1.00 1.00 0.00", 
+"wheat",    "0.96 0.87 0.70", 
+"gold",     "1.00 0.84 0.00", 
+"green",    "0.00 1.00 0.00", 
+"darkgreen","0.00 0.40 0.00", 
+"blue",     "0.00 0.00 1.00", 
+"skyblue",  "0.53 0.81 0.92", 
+"indigo",   "0.56 0.16 0.87", 
+"violet",   "1.00 0.00 0.00",
+"grey10",   "0.10 0.10 0.10",
+"grey20",   "0.20 0.20 0.20",
+"grey30",   "0.30 0.30 0.30",
+"grey40",   "0.40 0.40 0.40",
+"grey50",   "0.50 0.50 0.50",
+"grey60",   "0.60 0.60 0.60",
+"grey70",   "0.70 0.70 0.70",
+"grey80",   "0.80 0.80 0.80",
+"grey90",   "0.90 0.90 0.90"};
+
+/**************** Graphic carries X info around ****************/
+typedef struct {
+  Display       *display;
+  int            screen;
+  int            depth;
+  Window         window;
+  GC             gc;
+  XFontStruct   *font;
+  Cursor         cursor;
+  int            x,  y;
+  int            dx, dy;
+  Colormap       colormap;
+  unsigned long  fore;
+  unsigned long  back;
+  unsigned long  color[NGRAPHCOLORS];
+} Graphic;
+
+/**************** X related "widget" structures ****************/
+typedef struct {
+  int      x, y, dx, dy;      /* position and size */
+  int      text;              /* does this have a picture or text? */
+  int      width, height;
+  char    *bitmap;          /* picture on button */
+  int    (*function_1) ();  /* mouse_button 1 function */
+  int    (*function_2) ();  /* mouse_button 2 function */
+  int    (*function_3) ();  /* mouse_button 3 function */
+} Button;
+
+typedef struct {
+  int      x, y, dx, dy;   /* position and size */
+  char    *label;          /* label on TextLine */
+  char     text[1024];     /* words of TextLine */
+  char     old_text[1024]; /* words of TextLine */
+  int      outline;        /* draw an outline?  */ 
+  int      cursor;         /* location of cursor (if selected) */
+  int    (*function) ();   /* textline function */
+} TextLine;
+
+typedef char STRING[1024];
+
+typedef struct {
+  int      x, y, dx, dy;   /* position and size */
+  STRING  *text;           /* words of TextLine */
+  int      Nlines;
+  int      outline;        /* draw an outline?  */ 
+  int      cursor_line;    /* cursor line */
+  int      cursor_x;       /* location of cursor (if selected) */
+  int      cursor_y;       /* location of cursor (if selected) */
+  int    (*function) ();   /* textline function */
+} TextBox;
+
+/**************** general structures ****************/
+typedef struct {
+  Pixmap pixmap;
+  int    width;
+  int    height;
+  char  *bits;
+} Icon;
+
+typedef struct {
+  int      dx, dy, x, y;
+  XImage  *pix;
+  char    *data;
+} Picture;
+
+typedef struct {
+  char type[10];
+  double x, y;
+  double dx, dy;
+  double angle;
+  char  *text;
+} Object;
+
+typedef struct {
+  int x, y;
+  int dx, dy;
+  double angle;
+  int  size;
+  char font[64]; 
+  char text[128];
+} Label;
+
+typedef struct {
+  int Nobjects;
+  unsigned long color;
+  Object *objects;
+} Overlay;
+  
+typedef struct {
+  char      ctype[16];
+  double    crval1, crpix1, cdelt1;
+  double    crval2, crpix2, cdelt2;
+  double    pc1_1, pc1_2;
+  double    pc2_1, pc2_2;
+} Coords;
+
+typedef struct {
+  float *x, *y, *z, *dxp, *dxm, *dyp, *dym;
+  int Npts;
+  int style, ptype, ltype, color, etype, ebar;
+  double lweight, size;
+  double x0, x1, y0, y1;  /* limits for this object */
+} Gobjects;
+
+typedef struct {
+  double min, max;
+  char isaxis, areticks, islabel, islog;
+  double fx, dfx, fy, dfy;  /* axis location on graphic */
+  char label[64];
+} Axis;
+
+
+/******** Here we define the Layout struct specific to this program  *******/
+typedef struct {
+  Axis      axis[4];    /* coordinate axes */
+  Label     label[8];   /* fixed axis labels */
+
+  Gobjects *objects;    /* graphic objects */    
+  int      Nobjects;    
+
+  Label    *ptext;      /* placed text labels */
+  int      Nptext;      
+
+  double   x, dx;      /* location of plot on window ( 0 - 1, 0 - 1 ) */
+  double   y, dy; 
+
+  char     name[64];
+
+} Layout;
Index: /tags/start/Ohana/src/kapa/rotfont/ReadMe
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/ReadMe	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/ReadMe	(revision 12606)
@@ -0,0 +1,10 @@
+start font server (as root): 
+ xfs &
+
+dump font to bdf file:
+
+fstobdf -s localhost:7100 -fn "-adobe-times-medium-r-*-*-12-*-*-*-*-*-*-*" > times12.bdf
+
+convert to .h file:
+ fixfont times12.bdf times12 > times12.h
+
Index: /tags/start/Ohana/src/kapa/rotfont/alphabet.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/alphabet.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/alphabet.h	(revision 12606)
@@ -0,0 +1,69 @@
+typedef struct {
+  int dx, dy, ascent;
+  char *bits;
+} RotFont;
+
+typedef struct {
+  RotFont *font;
+  char name[64];
+  int size;
+} FontSet;
+
+# include "../rotfont/times8.h"
+# include "../rotfont/times12.h"
+# include "../rotfont/times14.h"
+# include "../rotfont/times18.h"
+# include "../rotfont/times24.h"
+
+# include "../rotfont/courier8.h"
+# include "../rotfont/courier12.h"
+# include "../rotfont/courier14.h"
+# include "../rotfont/courier18.h"
+# include "../rotfont/courier24.h"
+
+# include "../rotfont/helvetica8.h"
+# include "../rotfont/helvetica12.h"
+# include "../rotfont/helvetica14.h"
+# include "../rotfont/helvetica18.h"
+# include "../rotfont/helvetica24.h"
+
+# include "../rotfont/symbol8.h"
+# include "../rotfont/symbol12.h"
+# include "../rotfont/symbol14.h"
+# include "../rotfont/symbol18.h"
+# include "../rotfont/symbol24.h"
+
+# define DEFFONT 1
+static FontSet HardwiredFonts[] = {
+  {times8font,  "times", 8},
+  {times12font, "times", 12},
+  {times14font, "times", 14},
+  {times18font, "times", 18},
+  {times24font, "times", 24},
+  
+  {courier8font,  "courier", 8},
+  {courier12font, "courier", 12},
+  {courier14font, "courier", 14},
+  {courier18font, "courier", 18},
+  {courier24font, "courier", 24},
+  
+  {helvetica8font,  "helvetica", 8},
+  {helvetica12font, "helvetica", 12},
+  {helvetica14font, "helvetica", 14},
+  {helvetica18font, "helvetica", 18},
+  {helvetica24font, "helvetica", 24},
+  
+  {symbol8font,  "symbol", 8},
+  {symbol12font, "symbol", 12},
+  {symbol14font, "symbol", 14},
+  {symbol18font, "symbol", 18},
+  {symbol24font, "symbol", 24}
+};
+
+int Nallfonts;
+FontSet *AllFonts;
+RotFont *activefont;
+double activescale;
+
+char currentname[64];
+int  currentsize;
Index: /tags/start/Ohana/src/kapa/rotfont/blank.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/blank.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/blank.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define blank_width 5
+#define blank_height 1
+static unsigned char blank_bits[] = {
+   0x00};
Index: /tags/start/Ohana/src/kapa/rotfont/courier12.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/courier12.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/courier12.bdf	(revision 12606)
@@ -0,0 +1,2839 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) IBM Corporation 1990,1991. IBM Courier is a Trademark of the IBM Corporation.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -adobe-courier-medium-r-normal--12-116-75-75-m-70-iso8859-1
+SIZE 12 75 75
+FONTBOUNDINGBOX 8 12 0 -2
+STARTPROPERTIES 25
+FOUNDRY "adobe"
+FAMILY_NAME "courier"
+WEIGHT_NAME "medium"
+SLANT "r"
+SETWIDTH_NAME "normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 116
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "m"
+AVERAGE_WIDTH 70
+CHARSET_REGISTRY "iso8859"
+CHARSET_ENCODING "1"
+FONT "-adobe-courier-medium-r-normal--12-116-75-75-m-70-iso8859-1"
+COPYRIGHT "Copyright (c) IBM Corporation 1990,1991. IBM Courier is a Trademark of the IBM Corporation."
+RAW_PIXEL_SIZE 1000
+RAW_POINT_SIZE 964
+RAW_ASCENT 841
+RAW_DESCENT 288
+RAW_AVERAGE_WIDTH 6000
+FACE_NAME "Couriere."
+DEFAULT_CHAR 0
+FONT_ASCENT 10
+FONT_DESCENT 3
+ENDPROPERTIES
+CHARS 190
+STARTCHAR space
+ENCODING 32
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 0 0 0 0
+ATTRIBUTES 0x0258
+BITMAP
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 7 3 0
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+80
+80
+00
+40
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 3 2 4
+ATTRIBUTES 0x0258
+BITMAP
+a0
+a0
+a0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+50
+50
+50
+f8
+50
+f8
+50
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+20
+60
+b8
+a8
+60
+38
+a8
+f0
+20
+20
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+90
+6c
+70
+4c
+12
+1c
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+48
+40
+28
+e8
+90
+68
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 3 2 4
+ATTRIBUTES 0x0258
+BITMAP
+40
+80
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 9 3 -1
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+40
+80
+80
+80
+40
+40
+40
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 9 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+40
+40
+40
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 4 1 3
+ATTRIBUTES 0x0258
+BITMAP
+20
+f0
+20
+50
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+ATTRIBUTES 0x0258
+BITMAP
+20
+20
+f8
+20
+20
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 3 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+40
+80
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 1 1 3
+ATTRIBUTES 0x0258
+BITMAP
+fc
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 2 3 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+08
+08
+10
+10
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+88
+88
+88
+88
+c8
+70
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+08
+08
+10
+20
+48
+f8
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+10
+10
+30
+08
+08
+f0
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+30
+50
+50
+f8
+10
+78
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+80
+f0
+88
+08
+08
+70
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+38
+40
+b0
+c8
+88
+88
+70
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+08
+10
+10
+10
+20
+20
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+88
+88
+70
+88
+88
+70
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+88
+88
+78
+08
+10
+e0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 5 3 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+00
+c0
+40
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 6 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+60
+20
+00
+60
+40
+40
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 1 1
+ATTRIBUTES 0x0258
+BITMAP
+18
+20
+e0
+18
+04
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 3 1 2
+ATTRIBUTES 0x0258
+BITMAP
+fc
+00
+fc
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 1 1
+ATTRIBUTES 0x0258
+BITMAP
+60
+10
+1c
+e0
+80
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+88
+08
+10
+20
+00
+20
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+38
+44
+9a
+aa
+aa
+7c
+3c
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+28
+28
+28
+7c
+42
+c6
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+88
+88
+f8
+84
+84
+f8
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+7c
+44
+80
+80
+80
+c4
+78
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+44
+42
+42
+42
+44
+f8
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+fc
+44
+50
+70
+50
+44
+fc
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+fc
+44
+50
+70
+50
+40
+e0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+3c
+44
+80
+80
+8e
+42
+3e
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+ee
+44
+44
+7c
+44
+44
+ee
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+7c
+08
+08
+08
+88
+88
+f8
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+cc
+48
+50
+60
+50
+48
+c4
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+40
+40
+40
+44
+44
+fc
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+c6
+6a
+6a
+6a
+52
+42
+e6
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+ee
+62
+52
+52
+4a
+4a
+e6
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+38
+44
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+44
+44
+4c
+78
+40
+e0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+38
+44
+82
+82
+82
+44
+38
+30
+2e
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+88
+98
+e0
+90
+88
+cc
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+88
+80
+70
+08
+88
+f0
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+fe
+92
+92
+10
+10
+10
+38
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+ee
+44
+44
+44
+44
+44
+38
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+ee
+44
+64
+28
+28
+28
+10
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+c6
+52
+52
+6a
+6a
+6a
+44
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+6c
+28
+28
+10
+28
+44
+e6
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+cc
+48
+48
+50
+20
+20
+78
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+90
+90
+20
+48
+88
+f8
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 9 4 -1
+ATTRIBUTES 0x0258
+BITMAP
+c0
+80
+80
+80
+80
+80
+80
+80
+c0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+80
+40
+40
+20
+20
+20
+10
+10
+08
+08
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 9 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+e0
+20
+20
+20
+20
+20
+20
+20
+e0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 6 1 1
+ATTRIBUTES 0x0258
+BITMAP
+20
+50
+50
+50
+88
+88
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 8 1 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+ff
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 3 2 4
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+80
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+78
+88
+88
+fc
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+7c
+42
+42
+42
+fc
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+84
+80
+80
+78
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+1c
+04
+7c
+84
+84
+c4
+3e
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+8c
+fc
+80
+78
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+7c
+40
+f8
+40
+40
+40
+f8
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+7e
+84
+84
+c4
+3c
+04
+38
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+7c
+44
+44
+44
+ee
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 8 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+00
+60
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 4 10 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+00
+f0
+10
+10
+10
+10
+10
+e0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+4e
+58
+70
+48
+4e
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+fe
+92
+92
+92
+da
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+fc
+44
+44
+44
+ee
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+7c
+82
+82
+c6
+3c
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+fc
+42
+42
+46
+7c
+40
+f0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+7e
+c4
+84
+c4
+3c
+04
+0e
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+fc
+40
+40
+40
+f0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+88
+f0
+c8
+b0
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+f8
+40
+40
+40
+78
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+cc
+44
+44
+44
+3e
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+e6
+44
+24
+28
+10
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+c6
+52
+6a
+6c
+24
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+66
+2c
+10
+6c
+c6
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+c6
+44
+24
+28
+10
+20
+f0
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+10
+20
+48
+f8
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 9 3 -1
+ATTRIBUTES 0x0258
+BITMAP
+60
+80
+80
+40
+80
+40
+40
+80
+60
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 1 10 3 -2
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 9 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+80
+40
+40
+40
+40
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 2 1 3
+ATTRIBUTES 0x0258
+BITMAP
+68
+90
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 7 3 -2
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 8 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+20
+78
+a8
+a0
+a0
+70
+20
+20
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+38
+40
+40
+f8
+40
+40
+78
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+ATTRIBUTES 0x0258
+BITMAP
+f8
+88
+88
+88
+f8
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+cc
+48
+50
+78
+78
+20
+78
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 1 10 3 -2
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+80
+00
+00
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 8 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+78
+48
+60
+90
+48
+38
+90
+f0
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 1 2 6
+ATTRIBUTES 0x0258
+BITMAP
+a0
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+38
+7c
+c6
+c2
+e6
+7c
+38
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 4 2 3
+ATTRIBUTES 0x0258
+BITMAP
+60
+e0
+e0
+e0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+28
+50
+a0
+50
+28
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 3 1 2
+ATTRIBUTES 0x0258
+BITMAP
+f8
+08
+08
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 1 2 3
+ATTRIBUTES 0x0258
+BITMAP
+e0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+38
+7c
+aa
+b2
+ba
+46
+38
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 4 1 2 6
+ATTRIBUTES 0x0258
+BITMAP
+f0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 4 3 2 4
+ATTRIBUTES 0x0258
+BITMAP
+e0
+90
+e0
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+20
+f8
+20
+20
+00
+f8
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 4 2 3
+ATTRIBUTES 0x0258
+BITMAP
+e0
+20
+40
+e0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 4 2 3
+ATTRIBUTES 0x0258
+BITMAP
+60
+40
+20
+e0
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 1 3 6
+ATTRIBUTES 0x0258
+BITMAP
+40
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+cc
+44
+44
+44
+7e
+40
+40
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 8 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+78
+a8
+a8
+68
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 2 3 3
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 3 2 -2
+ATTRIBUTES 0x0258
+BITMAP
+40
+60
+60
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 4 2 3
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+40
+e0
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 4 2 3
+ATTRIBUTES 0x0258
+BITMAP
+e0
+a0
+e0
+e0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+a0
+50
+28
+50
+a0
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+02
+42
+46
+4c
+ea
+16
+26
+4e
+46
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+02
+46
+44
+4c
+fe
+1a
+22
+44
+4e
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+02
+62
+66
+24
+ea
+16
+26
+4e
+46
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+20
+c0
+80
+88
+78
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+70
+28
+28
+28
+7c
+42
+c6
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+08
+00
+70
+28
+28
+28
+7c
+42
+c6
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+70
+28
+28
+28
+7c
+42
+c6
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+3c
+00
+70
+28
+28
+28
+7c
+42
+c6
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+28
+00
+70
+28
+28
+28
+7c
+42
+c6
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 10 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+28
+10
+70
+28
+28
+28
+7c
+42
+c6
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+3e
+12
+36
+3c
+74
+52
+de
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+7c
+8c
+80
+80
+80
+86
+78
+10
+30
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+fc
+44
+50
+70
+50
+44
+fc
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 1 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+fc
+44
+50
+70
+50
+44
+fc
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+fc
+44
+50
+70
+50
+44
+fc
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 1 0
+ATTRIBUTES 0x0258
+BITMAP
+50
+00
+fc
+44
+50
+70
+50
+44
+fc
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+f8
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+f8
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+f8
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+ATTRIBUTES 0x0258
+BITMAP
+50
+00
+f8
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+44
+42
+f2
+42
+44
+f8
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+3c
+00
+ee
+62
+52
+52
+4a
+4a
+e6
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+38
+44
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+08
+00
+38
+44
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+38
+44
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+3c
+00
+38
+44
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+28
+00
+38
+44
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 4 5 2 1
+ATTRIBUTES 0x0258
+BITMAP
+90
+70
+20
+d0
+90
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+3a
+44
+8a
+92
+92
+64
+78
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+ee
+44
+44
+44
+44
+44
+38
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+08
+00
+ee
+44
+44
+44
+44
+44
+38
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+ee
+44
+44
+44
+44
+44
+38
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+28
+00
+ee
+44
+44
+44
+44
+44
+38
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 1 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+cc
+48
+48
+50
+20
+20
+78
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+78
+4c
+44
+4c
+78
+e0
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+88
+b0
+88
+88
+88
+b0
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+70
+78
+88
+88
+fc
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+70
+78
+88
+88
+fc
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+00
+70
+78
+88
+88
+fc
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+00
+70
+78
+88
+88
+fc
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+50
+00
+70
+78
+88
+88
+fc
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 8 1 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+70
+00
+70
+78
+88
+88
+fc
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+7c
+12
+7e
+90
+6e
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+7c
+84
+80
+80
+78
+20
+30
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+78
+8c
+fc
+80
+78
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+78
+8c
+fc
+80
+78
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+00
+78
+8c
+fc
+80
+78
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+50
+00
+78
+8c
+fc
+80
+78
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+60
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+60
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+00
+60
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+50
+00
+60
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 8 0 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+28
+0c
+7e
+82
+82
+c6
+3c
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+3c
+00
+fc
+44
+44
+44
+ee
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+7c
+82
+82
+c6
+3c
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+08
+00
+7c
+82
+82
+c6
+3c
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+38
+00
+7c
+82
+82
+c6
+3c
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+3c
+00
+7c
+82
+82
+c6
+3c
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+28
+00
+7c
+82
+82
+c6
+3c
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+f8
+00
+20
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+7e
+8a
+92
+e6
+9c
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+cc
+44
+44
+44
+3e
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+08
+00
+cc
+44
+44
+44
+3e
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+38
+00
+cc
+44
+44
+44
+3e
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+28
+00
+cc
+44
+44
+44
+3e
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+08
+00
+c6
+44
+24
+28
+10
+20
+f0
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+7c
+42
+42
+46
+7c
+40
+f0
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+28
+00
+c6
+44
+24
+28
+10
+20
+f0
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/courier12.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/courier12.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/courier12.h	(revision 12606)
@@ -0,0 +1,768 @@
+static unsigned char courier12_0_bits[] = {
+0x00};
+static unsigned char courier12_1_bits[] = {
+0x00};
+static unsigned char courier12_2_bits[] = {
+0x00};
+static unsigned char courier12_3_bits[] = {
+0x00};
+static unsigned char courier12_4_bits[] = {
+0x00};
+static unsigned char courier12_5_bits[] = {
+0x00};
+static unsigned char courier12_6_bits[] = {
+0x00};
+static unsigned char courier12_7_bits[] = {
+0x00};
+static unsigned char courier12_8_bits[] = {
+0x00};
+static unsigned char courier12_9_bits[] = {
+0x00};
+static unsigned char courier12_10_bits[] = {
+0x00};
+static unsigned char courier12_11_bits[] = {
+0x00};
+static unsigned char courier12_12_bits[] = {
+0x00};
+static unsigned char courier12_13_bits[] = {
+0x00};
+static unsigned char courier12_14_bits[] = {
+0x00};
+static unsigned char courier12_15_bits[] = {
+0x00};
+static unsigned char courier12_16_bits[] = {
+0x00};
+static unsigned char courier12_17_bits[] = {
+0x00};
+static unsigned char courier12_18_bits[] = {
+0x00};
+static unsigned char courier12_19_bits[] = {
+0x00};
+static unsigned char courier12_20_bits[] = {
+0x00};
+static unsigned char courier12_21_bits[] = {
+0x00};
+static unsigned char courier12_22_bits[] = {
+0x00};
+static unsigned char courier12_23_bits[] = {
+0x00};
+static unsigned char courier12_24_bits[] = {
+0x00};
+static unsigned char courier12_25_bits[] = {
+0x00};
+static unsigned char courier12_26_bits[] = {
+0x00};
+static unsigned char courier12_27_bits[] = {
+0x00};
+static unsigned char courier12_28_bits[] = {
+0x00};
+static unsigned char courier12_29_bits[] = {
+0x00};
+static unsigned char courier12_30_bits[] = {
+0x00};
+static unsigned char courier12_31_bits[] = {
+0x00};
+static unsigned char courier12_32_bits[] = {};
+static unsigned char courier12_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02};
+static unsigned char courier12_34_bits[] = {
+0x05, 0x05, 0x05};
+static unsigned char courier12_35_bits[] = {
+0x0a, 0x0a, 0x0a, 0x1f, 0x0a, 0x1f, 0x0a, 0x0a, 0x0a};
+static unsigned char courier12_36_bits[] = {
+0x04, 0x06, 0x1d, 0x15, 0x06, 0x1c, 0x15, 0x0f, 0x04, 0x04};
+static unsigned char courier12_37_bits[] = {
+0x0e, 0x09, 0x36, 0x0e, 0x32, 0x48, 0x38};
+static unsigned char courier12_38_bits[] = {
+0x0c, 0x12, 0x02, 0x14, 0x17, 0x09, 0x16};
+static unsigned char courier12_39_bits[] = {
+0x02, 0x01, 0x01};
+static unsigned char courier12_40_bits[] = {
+0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02};
+static unsigned char courier12_41_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01};
+static unsigned char courier12_42_bits[] = {
+0x04, 0x0f, 0x04, 0x0a};
+static unsigned char courier12_43_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x04};
+static unsigned char courier12_44_bits[] = {
+0x02, 0x01, 0x01};
+static unsigned char courier12_45_bits[] = {
+0x3f};
+static unsigned char courier12_46_bits[] = {
+0x03, 0x02};
+static unsigned char courier12_47_bits[] = {
+0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01};
+static unsigned char courier12_48_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x11, 0x13, 0x0e};
+static unsigned char courier12_49_bits[] = {
+0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_50_bits[] = {
+0x0f, 0x10, 0x10, 0x08, 0x04, 0x12, 0x1f};
+static unsigned char courier12_51_bits[] = {
+0x0f, 0x08, 0x08, 0x0c, 0x10, 0x10, 0x0f};
+static unsigned char courier12_52_bits[] = {
+0x08, 0x0c, 0x0a, 0x0a, 0x1f, 0x08, 0x1e};
+static unsigned char courier12_53_bits[] = {
+0x0f, 0x01, 0x0f, 0x11, 0x10, 0x10, 0x0e};
+static unsigned char courier12_54_bits[] = {
+0x1c, 0x02, 0x0d, 0x13, 0x11, 0x11, 0x0e};
+static unsigned char courier12_55_bits[] = {
+0x1f, 0x10, 0x08, 0x08, 0x08, 0x04, 0x04};
+static unsigned char courier12_56_bits[] = {
+0x0e, 0x11, 0x11, 0x0e, 0x11, 0x11, 0x0e};
+static unsigned char courier12_57_bits[] = {
+0x0e, 0x11, 0x11, 0x1e, 0x10, 0x08, 0x07};
+static unsigned char courier12_58_bits[] = {
+0x03, 0x02, 0x00, 0x03, 0x02};
+static unsigned char courier12_59_bits[] = {
+0x06, 0x04, 0x00, 0x06, 0x02, 0x02};
+static unsigned char courier12_60_bits[] = {
+0x18, 0x04, 0x07, 0x18, 0x20};
+static unsigned char courier12_61_bits[] = {
+0x3f, 0x00, 0x3f};
+static unsigned char courier12_62_bits[] = {
+0x06, 0x08, 0x38, 0x07, 0x01};
+static unsigned char courier12_63_bits[] = {
+0x0f, 0x11, 0x10, 0x08, 0x04, 0x00, 0x04};
+static unsigned char courier12_64_bits[] = {
+0x1c, 0x22, 0x59, 0x55, 0x55, 0x3e, 0x3c};
+static unsigned char courier12_65_bits[] = {
+0x0e, 0x14, 0x14, 0x14, 0x3e, 0x42, 0x63};
+static unsigned char courier12_66_bits[] = {
+0x0f, 0x11, 0x11, 0x1f, 0x21, 0x21, 0x1f};
+static unsigned char courier12_67_bits[] = {
+0x3e, 0x22, 0x01, 0x01, 0x01, 0x23, 0x1e};
+static unsigned char courier12_68_bits[] = {
+0x1f, 0x22, 0x42, 0x42, 0x42, 0x22, 0x1f};
+static unsigned char courier12_69_bits[] = {
+0x3f, 0x22, 0x0a, 0x0e, 0x0a, 0x22, 0x3f};
+static unsigned char courier12_70_bits[] = {
+0x3f, 0x22, 0x0a, 0x0e, 0x0a, 0x02, 0x07};
+static unsigned char courier12_71_bits[] = {
+0x3c, 0x22, 0x01, 0x01, 0x71, 0x42, 0x7c};
+static unsigned char courier12_72_bits[] = {
+0x77, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x77};
+static unsigned char courier12_73_bits[] = {
+0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_74_bits[] = {
+0x3e, 0x10, 0x10, 0x10, 0x11, 0x11, 0x1f};
+static unsigned char courier12_75_bits[] = {
+0x33, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x23};
+static unsigned char courier12_76_bits[] = {
+0x07, 0x02, 0x02, 0x02, 0x22, 0x22, 0x3f};
+static unsigned char courier12_77_bits[] = {
+0x63, 0x56, 0x56, 0x56, 0x4a, 0x42, 0x67};
+static unsigned char courier12_78_bits[] = {
+0x77, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x67};
+static unsigned char courier12_79_bits[] = {
+0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char courier12_80_bits[] = {
+0x1f, 0x22, 0x22, 0x32, 0x1e, 0x02, 0x07};
+static unsigned char courier12_81_bits[] = {
+0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x0c, 0x74};
+static unsigned char courier12_82_bits[] = {
+0x0f, 0x11, 0x19, 0x07, 0x09, 0x11, 0x33};
+static unsigned char courier12_83_bits[] = {
+0x1e, 0x11, 0x01, 0x0e, 0x10, 0x11, 0x0f};
+static unsigned char courier12_84_bits[] = {
+0x7f, 0x49, 0x49, 0x08, 0x08, 0x08, 0x1c};
+static unsigned char courier12_85_bits[] = {
+0x77, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c};
+static unsigned char courier12_86_bits[] = {
+0x77, 0x22, 0x26, 0x14, 0x14, 0x14, 0x08};
+static unsigned char courier12_87_bits[] = {
+0x63, 0x4a, 0x4a, 0x56, 0x56, 0x56, 0x22};
+static unsigned char courier12_88_bits[] = {
+0x36, 0x14, 0x14, 0x08, 0x14, 0x22, 0x67};
+static unsigned char courier12_89_bits[] = {
+0x33, 0x12, 0x12, 0x0a, 0x04, 0x04, 0x1e};
+static unsigned char courier12_90_bits[] = {
+0x1f, 0x09, 0x09, 0x04, 0x12, 0x11, 0x1f};
+static unsigned char courier12_91_bits[] = {
+0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03};
+static unsigned char courier12_92_bits[] = {
+0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10};
+static unsigned char courier12_93_bits[] = {
+0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07};
+static unsigned char courier12_94_bits[] = {
+0x04, 0x0a, 0x0a, 0x0a, 0x11, 0x11};
+static unsigned char courier12_95_bits[] = {
+0xff};
+static unsigned char courier12_96_bits[] = {
+0x02, 0x02, 0x01};
+static unsigned char courier12_97_bits[] = {
+0x0e, 0x1e, 0x11, 0x11, 0x3f};
+static unsigned char courier12_98_bits[] = {
+0x02, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x3f};
+static unsigned char courier12_99_bits[] = {
+0x1e, 0x21, 0x01, 0x01, 0x1e};
+static unsigned char courier12_100_bits[] = {
+0x38, 0x20, 0x3e, 0x21, 0x21, 0x23, 0x7c};
+static unsigned char courier12_101_bits[] = {
+0x1e, 0x31, 0x3f, 0x01, 0x1e};
+static unsigned char courier12_102_bits[] = {
+0x3e, 0x02, 0x1f, 0x02, 0x02, 0x02, 0x1f};
+static unsigned char courier12_103_bits[] = {
+0x7e, 0x21, 0x21, 0x23, 0x3c, 0x20, 0x1c};
+static unsigned char courier12_104_bits[] = {
+0x02, 0x02, 0x3e, 0x22, 0x22, 0x22, 0x77};
+static unsigned char courier12_105_bits[] = {
+0x04, 0x00, 0x00, 0x06, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_106_bits[] = {
+0x08, 0x00, 0x00, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07};
+static unsigned char courier12_107_bits[] = {
+0x02, 0x02, 0x72, 0x1a, 0x0e, 0x12, 0x72};
+static unsigned char courier12_108_bits[] = {
+0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_109_bits[] = {
+0x7f, 0x49, 0x49, 0x49, 0x5b};
+static unsigned char courier12_110_bits[] = {
+0x3f, 0x22, 0x22, 0x22, 0x77};
+static unsigned char courier12_111_bits[] = {
+0x3e, 0x41, 0x41, 0x63, 0x3c};
+static unsigned char courier12_112_bits[] = {
+0x3f, 0x42, 0x42, 0x62, 0x3e, 0x02, 0x0f};
+static unsigned char courier12_113_bits[] = {
+0x7e, 0x23, 0x21, 0x23, 0x3c, 0x20, 0x70};
+static unsigned char courier12_114_bits[] = {
+0x3f, 0x02, 0x02, 0x02, 0x0f};
+static unsigned char courier12_115_bits[] = {
+0x1e, 0x11, 0x0f, 0x13, 0x0d};
+static unsigned char courier12_116_bits[] = {
+0x02, 0x02, 0x1f, 0x02, 0x02, 0x02, 0x1e};
+static unsigned char courier12_117_bits[] = {
+0x33, 0x22, 0x22, 0x22, 0x7c};
+static unsigned char courier12_118_bits[] = {
+0x67, 0x22, 0x24, 0x14, 0x08};
+static unsigned char courier12_119_bits[] = {
+0x63, 0x4a, 0x56, 0x36, 0x24};
+static unsigned char courier12_120_bits[] = {
+0x66, 0x34, 0x08, 0x36, 0x63};
+static unsigned char courier12_121_bits[] = {
+0x63, 0x22, 0x24, 0x14, 0x08, 0x04, 0x0f};
+static unsigned char courier12_122_bits[] = {
+0x1f, 0x08, 0x04, 0x12, 0x1f};
+static unsigned char courier12_123_bits[] = {
+0x06, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x06};
+static unsigned char courier12_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier12_125_bits[] = {
+0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03};
+static unsigned char courier12_126_bits[] = {
+0x16, 0x09};
+static unsigned char courier12_127_bits[] = {
+0x00};
+static unsigned char courier12_128_bits[] = {
+0x00};
+static unsigned char courier12_129_bits[] = {
+0x00};
+static unsigned char courier12_130_bits[] = {
+0x00};
+static unsigned char courier12_131_bits[] = {
+0x00};
+static unsigned char courier12_132_bits[] = {
+0x00};
+static unsigned char courier12_133_bits[] = {
+0x00};
+static unsigned char courier12_134_bits[] = {
+0x00};
+static unsigned char courier12_135_bits[] = {
+0x00};
+static unsigned char courier12_136_bits[] = {
+0x00};
+static unsigned char courier12_137_bits[] = {
+0x00};
+static unsigned char courier12_138_bits[] = {
+0x00};
+static unsigned char courier12_139_bits[] = {
+0x00};
+static unsigned char courier12_140_bits[] = {
+0x00};
+static unsigned char courier12_141_bits[] = {
+0x00};
+static unsigned char courier12_142_bits[] = {
+0x00};
+static unsigned char courier12_143_bits[] = {
+0x00};
+static unsigned char courier12_144_bits[] = {
+0x00};
+static unsigned char courier12_145_bits[] = {
+0x00};
+static unsigned char courier12_146_bits[] = {
+0x00};
+static unsigned char courier12_147_bits[] = {
+0x00};
+static unsigned char courier12_148_bits[] = {
+0x00};
+static unsigned char courier12_149_bits[] = {
+0x00};
+static unsigned char courier12_150_bits[] = {
+0x00};
+static unsigned char courier12_151_bits[] = {
+0x00};
+static unsigned char courier12_152_bits[] = {
+0x00};
+static unsigned char courier12_153_bits[] = {
+0x00};
+static unsigned char courier12_154_bits[] = {
+0x00};
+static unsigned char courier12_155_bits[] = {
+0x00};
+static unsigned char courier12_156_bits[] = {
+0x00};
+static unsigned char courier12_157_bits[] = {
+0x00};
+static unsigned char courier12_158_bits[] = {
+0x00};
+static unsigned char courier12_159_bits[] = {
+0x00};
+static unsigned char courier12_160_bits[] = {
+0x00};
+static unsigned char courier12_161_bits[] = {
+0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier12_162_bits[] = {
+0x04, 0x1e, 0x15, 0x05, 0x05, 0x0e, 0x04, 0x04};
+static unsigned char courier12_163_bits[] = {
+0x1c, 0x02, 0x02, 0x1f, 0x02, 0x02, 0x1e};
+static unsigned char courier12_164_bits[] = {
+0x1f, 0x11, 0x11, 0x11, 0x1f};
+static unsigned char courier12_165_bits[] = {
+0x33, 0x12, 0x0a, 0x1e, 0x1e, 0x04, 0x1e};
+static unsigned char courier12_166_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier12_167_bits[] = {
+0x1e, 0x12, 0x06, 0x09, 0x12, 0x1c, 0x09, 0x0f};
+static unsigned char courier12_168_bits[] = {
+0x05};
+static unsigned char courier12_169_bits[] = {
+0x1c, 0x3e, 0x63, 0x43, 0x67, 0x3e, 0x1c};
+static unsigned char courier12_170_bits[] = {
+0x06, 0x07, 0x07, 0x07};
+static unsigned char courier12_171_bits[] = {
+0x14, 0x0a, 0x05, 0x0a, 0x14};
+static unsigned char courier12_172_bits[] = {
+0x1f, 0x10, 0x10};
+static unsigned char courier12_173_bits[] = {
+0x07};
+static unsigned char courier12_174_bits[] = {
+0x1c, 0x3e, 0x55, 0x4d, 0x5d, 0x62, 0x1c};
+static unsigned char courier12_175_bits[] = {
+0x0f};
+static unsigned char courier12_176_bits[] = {
+0x07, 0x09, 0x07};
+static unsigned char courier12_177_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x04, 0x00, 0x1f};
+static unsigned char courier12_178_bits[] = {
+0x07, 0x04, 0x02, 0x07};
+static unsigned char courier12_179_bits[] = {
+0x06, 0x02, 0x04, 0x07};
+static unsigned char courier12_180_bits[] = {
+0x02};
+static unsigned char courier12_181_bits[] = {
+0x33, 0x22, 0x22, 0x22, 0x7e, 0x02, 0x02};
+static unsigned char courier12_182_bits[] = {
+0x1e, 0x15, 0x15, 0x16, 0x14, 0x14, 0x14, 0x14};
+static unsigned char courier12_183_bits[] = {
+0x03, 0x02};
+static unsigned char courier12_184_bits[] = {
+0x02, 0x06, 0x06};
+static unsigned char courier12_185_bits[] = {
+0x03, 0x02, 0x02, 0x07};
+static unsigned char courier12_186_bits[] = {
+0x07, 0x05, 0x07, 0x07};
+static unsigned char courier12_187_bits[] = {
+0x05, 0x0a, 0x14, 0x0a, 0x05};
+static unsigned char courier12_188_bits[] = {
+0x40, 0x42, 0x62, 0x32, 0x57, 0x68, 0x64, 0x72, 0x62};
+static unsigned char courier12_189_bits[] = {
+0x40, 0x62, 0x22, 0x32, 0x7f, 0x58, 0x44, 0x22, 0x72};
+static unsigned char courier12_190_bits[] = {
+0x40, 0x46, 0x66, 0x24, 0x57, 0x68, 0x64, 0x72, 0x62};
+static unsigned char courier12_191_bits[] = {
+0x08, 0x00, 0x04, 0x03, 0x01, 0x11, 0x1e};
+static unsigned char courier12_192_bits[] = {
+0x08, 0x00, 0x0e, 0x14, 0x14, 0x14, 0x3e, 0x42, 0x63};
+static unsigned char courier12_193_bits[] = {
+0x10, 0x00, 0x0e, 0x14, 0x14, 0x14, 0x3e, 0x42, 0x63};
+static unsigned char courier12_194_bits[] = {
+0x08, 0x00, 0x0e, 0x14, 0x14, 0x14, 0x3e, 0x42, 0x63};
+static unsigned char courier12_195_bits[] = {
+0x3c, 0x00, 0x0e, 0x14, 0x14, 0x14, 0x3e, 0x42, 0x63};
+static unsigned char courier12_196_bits[] = {
+0x14, 0x00, 0x0e, 0x14, 0x14, 0x14, 0x3e, 0x42, 0x63};
+static unsigned char courier12_197_bits[] = {
+0x08, 0x14, 0x08, 0x0e, 0x14, 0x14, 0x14, 0x3e, 0x42, 0x63};
+static unsigned char courier12_198_bits[] = {
+0x7c, 0x48, 0x6c, 0x3c, 0x2e, 0x4a, 0x7b};
+static unsigned char courier12_199_bits[] = {
+0x3e, 0x31, 0x01, 0x01, 0x01, 0x61, 0x1e, 0x08, 0x0c};
+static unsigned char courier12_200_bits[] = {
+0x04, 0x00, 0x3f, 0x22, 0x0a, 0x0e, 0x0a, 0x22, 0x3f};
+static unsigned char courier12_201_bits[] = {
+0x08, 0x00, 0x3f, 0x22, 0x0a, 0x0e, 0x0a, 0x22, 0x3f};
+static unsigned char courier12_202_bits[] = {
+0x04, 0x00, 0x3f, 0x22, 0x0a, 0x0e, 0x0a, 0x22, 0x3f};
+static unsigned char courier12_203_bits[] = {
+0x0a, 0x00, 0x3f, 0x22, 0x0a, 0x0e, 0x0a, 0x22, 0x3f};
+static unsigned char courier12_204_bits[] = {
+0x04, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_205_bits[] = {
+0x08, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_206_bits[] = {
+0x04, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_207_bits[] = {
+0x0a, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_208_bits[] = {
+0x1f, 0x22, 0x42, 0x4f, 0x42, 0x22, 0x1f};
+static unsigned char courier12_209_bits[] = {
+0x3c, 0x00, 0x77, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x67};
+static unsigned char courier12_210_bits[] = {
+0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char courier12_211_bits[] = {
+0x10, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char courier12_212_bits[] = {
+0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char courier12_213_bits[] = {
+0x3c, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char courier12_214_bits[] = {
+0x14, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char courier12_215_bits[] = {
+0x09, 0x0e, 0x04, 0x0b, 0x09};
+static unsigned char courier12_216_bits[] = {
+0x5c, 0x22, 0x51, 0x49, 0x49, 0x26, 0x1e};
+static unsigned char courier12_217_bits[] = {
+0x08, 0x00, 0x77, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c};
+static unsigned char courier12_218_bits[] = {
+0x10, 0x00, 0x77, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c};
+static unsigned char courier12_219_bits[] = {
+0x08, 0x00, 0x77, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c};
+static unsigned char courier12_220_bits[] = {
+0x14, 0x00, 0x77, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c};
+static unsigned char courier12_221_bits[] = {
+0x08, 0x00, 0x33, 0x12, 0x12, 0x0a, 0x04, 0x04, 0x1e};
+static unsigned char courier12_222_bits[] = {
+0x07, 0x1e, 0x32, 0x22, 0x32, 0x1e, 0x07};
+static unsigned char courier12_223_bits[] = {
+0x0e, 0x11, 0x0d, 0x11, 0x11, 0x11, 0x0d};
+static unsigned char courier12_224_bits[] = {
+0x04, 0x00, 0x0e, 0x1e, 0x11, 0x11, 0x3f};
+static unsigned char courier12_225_bits[] = {
+0x08, 0x00, 0x0e, 0x1e, 0x11, 0x11, 0x3f};
+static unsigned char courier12_226_bits[] = {
+0x0e, 0x00, 0x0e, 0x1e, 0x11, 0x11, 0x3f};
+static unsigned char courier12_227_bits[] = {
+0x1e, 0x00, 0x0e, 0x1e, 0x11, 0x11, 0x3f};
+static unsigned char courier12_228_bits[] = {
+0x0a, 0x00, 0x0e, 0x1e, 0x11, 0x11, 0x3f};
+static unsigned char courier12_229_bits[] = {
+0x0c, 0x0e, 0x00, 0x0e, 0x1e, 0x11, 0x11, 0x3f};
+static unsigned char courier12_230_bits[] = {
+0x3e, 0x48, 0x7e, 0x09, 0x76};
+static unsigned char courier12_231_bits[] = {
+0x3e, 0x21, 0x01, 0x01, 0x1e, 0x04, 0x0c};
+static unsigned char courier12_232_bits[] = {
+0x08, 0x00, 0x1e, 0x31, 0x3f, 0x01, 0x1e};
+static unsigned char courier12_233_bits[] = {
+0x08, 0x00, 0x1e, 0x31, 0x3f, 0x01, 0x1e};
+static unsigned char courier12_234_bits[] = {
+0x0e, 0x00, 0x1e, 0x31, 0x3f, 0x01, 0x1e};
+static unsigned char courier12_235_bits[] = {
+0x0a, 0x00, 0x1e, 0x31, 0x3f, 0x01, 0x1e};
+static unsigned char courier12_236_bits[] = {
+0x04, 0x00, 0x06, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_237_bits[] = {
+0x08, 0x00, 0x06, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_238_bits[] = {
+0x0e, 0x00, 0x06, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_239_bits[] = {
+0x0a, 0x00, 0x06, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_240_bits[] = {
+0x0c, 0x14, 0x30, 0x7e, 0x41, 0x41, 0x63, 0x3c};
+static unsigned char courier12_241_bits[] = {
+0x3c, 0x00, 0x3f, 0x22, 0x22, 0x22, 0x77};
+static unsigned char courier12_242_bits[] = {
+0x08, 0x00, 0x3e, 0x41, 0x41, 0x63, 0x3c};
+static unsigned char courier12_243_bits[] = {
+0x10, 0x00, 0x3e, 0x41, 0x41, 0x63, 0x3c};
+static unsigned char courier12_244_bits[] = {
+0x1c, 0x00, 0x3e, 0x41, 0x41, 0x63, 0x3c};
+static unsigned char courier12_245_bits[] = {
+0x3c, 0x00, 0x3e, 0x41, 0x41, 0x63, 0x3c};
+static unsigned char courier12_246_bits[] = {
+0x14, 0x00, 0x3e, 0x41, 0x41, 0x63, 0x3c};
+static unsigned char courier12_247_bits[] = {
+0x04, 0x00, 0x1f, 0x00, 0x04};
+static unsigned char courier12_248_bits[] = {
+0x7e, 0x51, 0x49, 0x67, 0x39};
+static unsigned char courier12_249_bits[] = {
+0x08, 0x00, 0x33, 0x22, 0x22, 0x22, 0x7c};
+static unsigned char courier12_250_bits[] = {
+0x10, 0x00, 0x33, 0x22, 0x22, 0x22, 0x7c};
+static unsigned char courier12_251_bits[] = {
+0x1c, 0x00, 0x33, 0x22, 0x22, 0x22, 0x7c};
+static unsigned char courier12_252_bits[] = {
+0x14, 0x00, 0x33, 0x22, 0x22, 0x22, 0x7c};
+static unsigned char courier12_253_bits[] = {
+0x10, 0x00, 0x63, 0x22, 0x24, 0x14, 0x08, 0x04, 0x0f};
+static unsigned char courier12_254_bits[] = {
+0x02, 0x02, 0x3e, 0x42, 0x42, 0x62, 0x3e, 0x02, 0x0f};
+static unsigned char courier12_255_bits[] = {
+0x14, 0x00, 0x63, 0x22, 0x24, 0x14, 0x08, 0x04, 0x0f};
+static RotFont courier12font[] = {
+{5, 1, 1, courier12_0_bits},
+{5, 1, 1, courier12_1_bits},
+{5, 1, 1, courier12_2_bits},
+{5, 1, 1, courier12_3_bits},
+{5, 1, 1, courier12_4_bits},
+{5, 1, 1, courier12_5_bits},
+{5, 1, 1, courier12_6_bits},
+{5, 1, 1, courier12_7_bits},
+{5, 1, 1, courier12_8_bits},
+{5, 1, 1, courier12_9_bits},
+{5, 1, 1, courier12_10_bits},
+{5, 1, 1, courier12_11_bits},
+{5, 1, 1, courier12_12_bits},
+{5, 1, 1, courier12_13_bits},
+{5, 1, 1, courier12_14_bits},
+{5, 1, 1, courier12_15_bits},
+{5, 1, 1, courier12_16_bits},
+{5, 1, 1, courier12_17_bits},
+{5, 1, 1, courier12_18_bits},
+{5, 1, 1, courier12_19_bits},
+{5, 1, 1, courier12_20_bits},
+{5, 1, 1, courier12_21_bits},
+{5, 1, 1, courier12_22_bits},
+{5, 1, 1, courier12_23_bits},
+{5, 1, 1, courier12_24_bits},
+{5, 1, 1, courier12_25_bits},
+{5, 1, 1, courier12_26_bits},
+{5, 1, 1, courier12_27_bits},
+{5, 1, 1, courier12_28_bits},
+{5, 1, 1, courier12_29_bits},
+{5, 1, 1, courier12_30_bits},
+{5, 1, 1, courier12_31_bits},
+{5, 0, 0, courier12_32_bits},
+{2, 7, 7, courier12_33_bits},
+{3, 3, 7, courier12_34_bits},
+{5, 9, 8, courier12_35_bits},
+{5, 10, 8, courier12_36_bits},
+{7, 7, 7, courier12_37_bits},
+{5, 7, 7, courier12_38_bits},
+{2, 3, 7, courier12_39_bits},
+{3, 9, 8, courier12_40_bits},
+{2, 9, 8, courier12_41_bits},
+{5, 4, 7, courier12_42_bits},
+{5, 5, 6, courier12_43_bits},
+{2, 3, 2, courier12_44_bits},
+{6, 1, 4, courier12_45_bits},
+{2, 2, 2, courier12_46_bits},
+{5, 10, 8, courier12_47_bits},
+{5, 7, 7, courier12_48_bits},
+{5, 7, 7, courier12_49_bits},
+{5, 7, 7, courier12_50_bits},
+{5, 7, 7, courier12_51_bits},
+{5, 7, 7, courier12_52_bits},
+{5, 7, 7, courier12_53_bits},
+{5, 7, 7, courier12_54_bits},
+{5, 7, 7, courier12_55_bits},
+{5, 7, 7, courier12_56_bits},
+{5, 7, 7, courier12_57_bits},
+{2, 5, 5, courier12_58_bits},
+{3, 6, 5, courier12_59_bits},
+{6, 5, 6, courier12_60_bits},
+{6, 3, 5, courier12_61_bits},
+{6, 5, 6, courier12_62_bits},
+{5, 7, 7, courier12_63_bits},
+{7, 7, 7, courier12_64_bits},
+{7, 7, 7, courier12_65_bits},
+{6, 7, 7, courier12_66_bits},
+{6, 7, 7, courier12_67_bits},
+{7, 7, 7, courier12_68_bits},
+{6, 7, 7, courier12_69_bits},
+{6, 7, 7, courier12_70_bits},
+{7, 7, 7, courier12_71_bits},
+{7, 7, 7, courier12_72_bits},
+{5, 7, 7, courier12_73_bits},
+{6, 7, 7, courier12_74_bits},
+{6, 7, 7, courier12_75_bits},
+{6, 7, 7, courier12_76_bits},
+{7, 7, 7, courier12_77_bits},
+{7, 7, 7, courier12_78_bits},
+{7, 7, 7, courier12_79_bits},
+{6, 7, 7, courier12_80_bits},
+{7, 9, 7, courier12_81_bits},
+{6, 7, 7, courier12_82_bits},
+{5, 7, 7, courier12_83_bits},
+{7, 7, 7, courier12_84_bits},
+{7, 7, 7, courier12_85_bits},
+{7, 7, 7, courier12_86_bits},
+{7, 7, 7, courier12_87_bits},
+{7, 7, 7, courier12_88_bits},
+{6, 7, 7, courier12_89_bits},
+{5, 7, 7, courier12_90_bits},
+{2, 9, 8, courier12_91_bits},
+{5, 10, 8, courier12_92_bits},
+{3, 9, 8, courier12_93_bits},
+{5, 6, 7, courier12_94_bits},
+{8, 1, -1, courier12_95_bits},
+{2, 3, 7, courier12_96_bits},
+{6, 5, 5, courier12_97_bits},
+{7, 7, 7, courier12_98_bits},
+{6, 5, 5, courier12_99_bits},
+{7, 7, 7, courier12_100_bits},
+{6, 5, 5, courier12_101_bits},
+{6, 7, 7, courier12_102_bits},
+{7, 7, 5, courier12_103_bits},
+{7, 7, 7, courier12_104_bits},
+{5, 8, 8, courier12_105_bits},
+{4, 10, 8, courier12_106_bits},
+{7, 7, 7, courier12_107_bits},
+{5, 7, 7, courier12_108_bits},
+{7, 5, 5, courier12_109_bits},
+{7, 5, 5, courier12_110_bits},
+{7, 5, 5, courier12_111_bits},
+{7, 7, 5, courier12_112_bits},
+{7, 7, 5, courier12_113_bits},
+{6, 5, 5, courier12_114_bits},
+{5, 5, 5, courier12_115_bits},
+{5, 7, 7, courier12_116_bits},
+{7, 5, 5, courier12_117_bits},
+{7, 5, 5, courier12_118_bits},
+{7, 5, 5, courier12_119_bits},
+{7, 5, 5, courier12_120_bits},
+{7, 7, 5, courier12_121_bits},
+{5, 5, 5, courier12_122_bits},
+{3, 9, 8, courier12_123_bits},
+{1, 10, 8, courier12_124_bits},
+{2, 9, 8, courier12_125_bits},
+{5, 2, 5, courier12_126_bits},
+{5, 1, 1, courier12_127_bits},
+{5, 1, 1, courier12_128_bits},
+{5, 1, 1, courier12_129_bits},
+{5, 1, 1, courier12_130_bits},
+{5, 1, 1, courier12_131_bits},
+{5, 1, 1, courier12_132_bits},
+{5, 1, 1, courier12_133_bits},
+{5, 1, 1, courier12_134_bits},
+{5, 1, 1, courier12_135_bits},
+{5, 1, 1, courier12_136_bits},
+{5, 1, 1, courier12_137_bits},
+{5, 1, 1, courier12_138_bits},
+{5, 1, 1, courier12_139_bits},
+{5, 1, 1, courier12_140_bits},
+{5, 1, 1, courier12_141_bits},
+{5, 1, 1, courier12_142_bits},
+{5, 1, 1, courier12_143_bits},
+{5, 1, 1, courier12_144_bits},
+{5, 1, 1, courier12_145_bits},
+{5, 1, 1, courier12_146_bits},
+{5, 1, 1, courier12_147_bits},
+{5, 1, 1, courier12_148_bits},
+{5, 1, 1, courier12_149_bits},
+{5, 1, 1, courier12_150_bits},
+{5, 1, 1, courier12_151_bits},
+{5, 1, 1, courier12_152_bits},
+{5, 1, 1, courier12_153_bits},
+{5, 1, 1, courier12_154_bits},
+{5, 1, 1, courier12_155_bits},
+{5, 1, 1, courier12_156_bits},
+{5, 1, 1, courier12_157_bits},
+{5, 1, 1, courier12_158_bits},
+{5, 1, 1, courier12_159_bits},
+{5, 1, 1, courier12_160_bits},
+{2, 7, 5, courier12_161_bits},
+{5, 8, 7, courier12_162_bits},
+{5, 7, 7, courier12_163_bits},
+{5, 5, 6, courier12_164_bits},
+{6, 7, 7, courier12_165_bits},
+{1, 10, 8, courier12_166_bits},
+{5, 8, 7, courier12_167_bits},
+{3, 1, 7, courier12_168_bits},
+{7, 7, 7, courier12_169_bits},
+{3, 4, 7, courier12_170_bits},
+{5, 5, 5, courier12_171_bits},
+{5, 3, 5, courier12_172_bits},
+{3, 1, 4, courier12_173_bits},
+{7, 7, 7, courier12_174_bits},
+{4, 1, 7, courier12_175_bits},
+{4, 3, 7, courier12_176_bits},
+{5, 7, 7, courier12_177_bits},
+{3, 4, 7, courier12_178_bits},
+{3, 4, 7, courier12_179_bits},
+{2, 1, 7, courier12_180_bits},
+{7, 7, 5, courier12_181_bits},
+{5, 8, 7, courier12_182_bits},
+{2, 2, 5, courier12_183_bits},
+{3, 3, 1, courier12_184_bits},
+{3, 4, 7, courier12_185_bits},
+{3, 4, 7, courier12_186_bits},
+{5, 5, 5, courier12_187_bits},
+{7, 9, 8, courier12_188_bits},
+{7, 9, 8, courier12_189_bits},
+{7, 9, 8, courier12_190_bits},
+{5, 7, 5, courier12_191_bits},
+{7, 9, 9, courier12_192_bits},
+{7, 9, 9, courier12_193_bits},
+{7, 9, 9, courier12_194_bits},
+{7, 9, 9, courier12_195_bits},
+{7, 9, 9, courier12_196_bits},
+{7, 10, 10, courier12_197_bits},
+{7, 7, 7, courier12_198_bits},
+{7, 9, 7, courier12_199_bits},
+{6, 9, 9, courier12_200_bits},
+{6, 9, 9, courier12_201_bits},
+{6, 9, 9, courier12_202_bits},
+{6, 9, 9, courier12_203_bits},
+{5, 9, 9, courier12_204_bits},
+{5, 9, 9, courier12_205_bits},
+{5, 9, 9, courier12_206_bits},
+{5, 9, 9, courier12_207_bits},
+{7, 7, 7, courier12_208_bits},
+{7, 9, 9, courier12_209_bits},
+{7, 9, 9, courier12_210_bits},
+{7, 9, 9, courier12_211_bits},
+{7, 9, 9, courier12_212_bits},
+{7, 9, 9, courier12_213_bits},
+{7, 9, 9, courier12_214_bits},
+{4, 5, 6, courier12_215_bits},
+{7, 7, 7, courier12_216_bits},
+{7, 9, 9, courier12_217_bits},
+{7, 9, 9, courier12_218_bits},
+{7, 9, 9, courier12_219_bits},
+{7, 9, 9, courier12_220_bits},
+{6, 9, 9, courier12_221_bits},
+{6, 7, 7, courier12_222_bits},
+{5, 7, 7, courier12_223_bits},
+{6, 7, 7, courier12_224_bits},
+{6, 7, 7, courier12_225_bits},
+{6, 7, 7, courier12_226_bits},
+{6, 7, 7, courier12_227_bits},
+{6, 7, 7, courier12_228_bits},
+{6, 8, 8, courier12_229_bits},
+{7, 5, 5, courier12_230_bits},
+{6, 7, 5, courier12_231_bits},
+{6, 7, 7, courier12_232_bits},
+{6, 7, 7, courier12_233_bits},
+{6, 7, 7, courier12_234_bits},
+{6, 7, 7, courier12_235_bits},
+{5, 7, 7, courier12_236_bits},
+{5, 7, 7, courier12_237_bits},
+{5, 7, 7, courier12_238_bits},
+{5, 7, 7, courier12_239_bits},
+{7, 8, 8, courier12_240_bits},
+{7, 7, 7, courier12_241_bits},
+{7, 7, 7, courier12_242_bits},
+{7, 7, 7, courier12_243_bits},
+{7, 7, 7, courier12_244_bits},
+{7, 7, 7, courier12_245_bits},
+{7, 7, 7, courier12_246_bits},
+{5, 5, 6, courier12_247_bits},
+{7, 5, 5, courier12_248_bits},
+{7, 7, 7, courier12_249_bits},
+{7, 7, 7, courier12_250_bits},
+{7, 7, 7, courier12_251_bits},
+{7, 7, 7, courier12_252_bits},
+{7, 9, 7, courier12_253_bits},
+{7, 9, 7, courier12_254_bits},
+{7, 9, 7, courier12_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/courier14.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/courier14.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/courier14.bdf	(revision 12606)
@@ -0,0 +1,3076 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Courier-Medium-R-Normal--14-100-100-100-M-90-ISO8859-1
+SIZE 10 100 100
+FONTBOUNDINGBOX 10 15 -1 -3
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Courier"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 14
+POINT_SIZE 100
+RESOLUTION_X 100
+RESOLUTION_Y 100
+SPACING "M"
+AVERAGE_WIDTH 90
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 9
+X_HEIGHT 7
+FACE_NAME "Courier"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "No mark"
+_DEC_DEVICE_FONTNAMES "PS=Courier"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Courier"
+FONT "-Adobe-Courier-Medium-R-Normal--14-100-100-100-M-90-ISO8859-1"
+WEIGHT 10
+RESOLUTION 138
+QUAD_WIDTH 9
+DEFAULT_CHAR 32
+FONT_ASCENT 11
+FONT_DESCENT 3
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 1 9 3 0
+BITMAP
+80
+80
+80
+80
+80
+80
+00
+80
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 4 4 2 6
+BITMAP
+90
+90
+90
+90
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 10 2 -1
+BITMAP
+50
+50
+50
+f8
+50
+50
+f8
+50
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 13 2 -2
+BITMAP
+20
+20
+78
+88
+80
+c0
+30
+08
+88
+f0
+20
+20
+20
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+60
+90
+90
+73
+0c
+30
+cc
+12
+12
+0c
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 8 1 0
+BITMAP
+38
+40
+40
+40
+a8
+90
+98
+64
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 4 2 6
+BITMAP
+60
+60
+c0
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 12 3 -2
+BITMAP
+20
+40
+40
+80
+80
+80
+80
+80
+80
+40
+40
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 12 2 -2
+BITMAP
+80
+40
+40
+20
+20
+20
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 6 1 3
+BITMAP
+20
+20
+f8
+20
+50
+88
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 1
+BITMAP
+10
+10
+10
+fe
+10
+10
+10
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 4 2 -2
+BITMAP
+60
+60
+c0
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 1 1 4
+BITMAP
+fe
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 2 2 3 0
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 11 1 -1
+BITMAP
+04
+08
+08
+10
+10
+20
+20
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 10 1 0
+BITMAP
+30
+48
+84
+84
+84
+84
+84
+84
+48
+30
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 10 1 0
+BITMAP
+20
+60
+a0
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 10 1 0
+BITMAP
+70
+88
+88
+08
+10
+20
+40
+80
+88
+f8
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 10 1 0
+BITMAP
+38
+44
+04
+04
+18
+04
+04
+04
+84
+78
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 10 1 0
+BITMAP
+18
+28
+28
+48
+48
+88
+88
+fc
+08
+1c
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 10 1 0
+BITMAP
+7c
+40
+40
+40
+78
+04
+04
+04
+84
+78
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 10 1 0
+BITMAP
+38
+40
+80
+80
+b8
+c4
+84
+84
+44
+38
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 10 1 0
+BITMAP
+fc
+84
+04
+08
+08
+08
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 10 2 0
+BITMAP
+70
+88
+88
+88
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 10 1 0
+BITMAP
+70
+88
+84
+84
+8c
+74
+04
+04
+08
+70
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 2 7 3 0
+BITMAP
+c0
+c0
+00
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 9 2 -2
+BITMAP
+60
+60
+00
+00
+00
+60
+60
+c0
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 0 1
+BITMAP
+06
+18
+60
+80
+60
+18
+06
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 3 1 3
+BITMAP
+fe
+00
+fe
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 1
+BITMAP
+c0
+30
+0c
+02
+0c
+30
+c0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+08
+08
+30
+20
+00
+20
+20
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 -1
+BITMAP
+38
+44
+84
+9c
+a4
+a4
+9e
+80
+40
+38
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 9 -1 0
+BITMAP
+3800
+0800
+1400
+1400
+2200
+3e00
+4100
+4100
+f780
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 0 0
+BITMAP
+fc
+42
+42
+42
+7c
+42
+42
+42
+fc
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+3a
+46
+82
+80
+80
+80
+80
+42
+3c
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+fc
+42
+41
+41
+41
+41
+41
+42
+fc
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+fe
+42
+42
+48
+78
+48
+42
+42
+fe
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+fe
+42
+42
+48
+78
+48
+40
+40
+f0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3a
+46
+82
+80
+80
+8f
+82
+42
+3c
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+e7
+42
+42
+42
+7e
+42
+42
+42
+e7
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 9 2 0
+BITMAP
+f8
+20
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+3e
+08
+08
+08
+08
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+ee
+44
+48
+50
+70
+48
+44
+44
+e3
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+f8
+20
+20
+20
+20
+21
+21
+21
+ff
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+e380
+6300
+5500
+5500
+4900
+4900
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+e7
+62
+52
+52
+4a
+4a
+46
+46
+e2
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+fc
+42
+42
+42
+42
+7c
+40
+40
+f0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 11 0 -2
+BITMAP
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+31
+5e
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+fc
+42
+42
+42
+44
+78
+44
+42
+e1
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 9 1 0
+BITMAP
+74
+8c
+84
+80
+78
+04
+84
+c4
+b8
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+fe
+92
+92
+10
+10
+10
+10
+10
+7c
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+e7
+42
+42
+42
+42
+42
+42
+42
+3c
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+e380
+4100
+4100
+2200
+2200
+1400
+1400
+0800
+0800
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+e380
+4100
+4900
+4900
+5500
+5500
+2200
+2200
+2200
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+e7
+42
+24
+24
+18
+24
+24
+42
+e7
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 0 0
+BITMAP
+ee
+44
+44
+28
+28
+10
+10
+10
+7c
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 9 1 0
+BITMAP
+fc
+84
+88
+10
+20
+20
+44
+84
+fc
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 12 3 -2
+BITMAP
+e0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+e0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 11 1 -1
+BITMAP
+80
+40
+40
+20
+20
+10
+10
+08
+08
+04
+04
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 12 2 -2
+BITMAP
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+e0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 5 2 4
+BITMAP
+20
+50
+50
+88
+88
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 1 0 -3
+BITMAP
+ff80
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 4 2 6
+BITMAP
+c0
+c0
+60
+20
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 0
+BITMAP
+78
+84
+04
+7c
+84
+84
+7a
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+c0
+40
+40
+5c
+62
+41
+41
+41
+62
+dc
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 0
+BITMAP
+3a
+46
+82
+80
+80
+42
+3c
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+06
+02
+02
+3a
+46
+82
+82
+82
+46
+3b
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 0
+BITMAP
+38
+44
+82
+fe
+80
+42
+3c
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+1e
+20
+20
+fc
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 -3
+BITMAP
+3b
+46
+82
+82
+82
+46
+3a
+02
+04
+78
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+c0
+40
+40
+5c
+62
+42
+42
+42
+42
+e7
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 10 2 0
+BITMAP
+20
+20
+00
+e0
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 13 1 -3
+BITMAP
+08
+08
+00
+f8
+08
+08
+08
+08
+08
+08
+08
+10
+e0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+c0
+40
+40
+4e
+48
+50
+60
+50
+48
+ce
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 10 2 0
+BITMAP
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 7 0 0
+BITMAP
+db00
+6d00
+4900
+4900
+4900
+4900
+ed80
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+dc
+62
+42
+42
+42
+42
+e7
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+3c
+42
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 -3
+BITMAP
+dc
+62
+41
+41
+41
+62
+5c
+40
+40
+f0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 -3
+BITMAP
+3b
+46
+82
+82
+82
+46
+3a
+02
+02
+0f
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 0
+BITMAP
+cc
+52
+60
+40
+40
+40
+f8
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 7 1 0
+BITMAP
+7c
+84
+80
+78
+04
+84
+f8
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 0 0
+BITMAP
+20
+20
+fc
+20
+20
+20
+20
+22
+1c
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+c6
+42
+42
+42
+42
+46
+3b
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+e7
+42
+42
+24
+24
+18
+18
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 7 0 0
+BITMAP
+e380
+4100
+4900
+4900
+2a00
+3600
+2200
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 0 0
+BITMAP
+ee
+44
+28
+10
+28
+44
+ee
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 -3
+BITMAP
+e7
+42
+42
+24
+24
+18
+08
+10
+10
+78
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 7 2 0
+BITMAP
+f8
+88
+10
+20
+40
+88
+f8
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 12 2 -2
+BITMAP
+20
+40
+40
+40
+40
+80
+40
+40
+40
+40
+40
+20
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 1 11 3 -2
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 12 2 -2
+BITMAP
+80
+40
+40
+40
+40
+20
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 2 1 3
+BITMAP
+64
+98
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 1 9 4 -2
+BITMAP
+80
+80
+00
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 9 2 0
+BITMAP
+20
+20
+78
+88
+80
+88
+70
+20
+20
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+18
+24
+20
+20
+78
+20
+20
+42
+fc
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 6 1 1
+BITMAP
+b4
+48
+84
+84
+48
+b4
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+ee
+44
+44
+28
+7c
+10
+7c
+10
+38
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 1 11 3 -2
+BITMAP
+80
+80
+80
+80
+00
+00
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 10 1 -1
+BITMAP
+3c
+44
+40
+f0
+88
+44
+3c
+08
+88
+f0
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 1 2 8
+BITMAP
+d8
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3c
+42
+99
+a5
+a1
+a5
+99
+42
+3c
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 4 6 2 3
+BITMAP
+c0
+20
+e0
+b0
+00
+f0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+11
+22
+44
+cc
+44
+22
+11
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 3 1 3
+BITMAP
+fe
+02
+02
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 1 1 4
+BITMAP
+fc
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3c
+42
+b9
+a5
+b9
+a9
+a5
+42
+3c
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 4 1 2 8
+BITMAP
+f0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 4 4 2 6
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 1
+BITMAP
+10
+10
+fe
+10
+10
+00
+fe
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 4 6 2 4
+BITMAP
+60
+90
+10
+20
+40
+f0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 4 6 2 4
+BITMAP
+60
+90
+60
+10
+90
+60
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 4 2 2 8
+BITMAP
+30
+c0
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 -3
+BITMAP
+c6
+42
+42
+42
+42
+46
+7b
+40
+40
+40
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 -1
+BITMAP
+7e
+94
+94
+94
+74
+14
+14
+14
+14
+3e
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 2 2 3 3
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 3 2 -3
+BITMAP
+40
+20
+e0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 6 3 4
+BITMAP
+40
+c0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 4 6 2 3
+BITMAP
+60
+90
+90
+60
+00
+f0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+88
+44
+22
+33
+22
+44
+88
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 10 10 -1 0
+BITMAP
+4000
+c100
+4200
+4400
+4480
+e980
+1280
+1480
+27c0
+4080
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 10 10 -1 0
+BITMAP
+4000
+c100
+4200
+4400
+4580
+ea40
+1040
+1080
+2100
+43c0
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 10 10 -1 0
+BITMAP
+6000
+9100
+6200
+1400
+9480
+6980
+1280
+1480
+27c0
+4080
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 9 2 -2
+BITMAP
+20
+20
+00
+20
+60
+80
+80
+88
+70
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+3000
+0c00
+0000
+3800
+0800
+1400
+1400
+2200
+3e00
+4100
+4100
+f780
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+0c00
+3000
+0000
+3800
+0800
+1400
+1400
+2200
+3e00
+4100
+4100
+f780
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+0800
+1400
+0000
+3800
+0800
+1400
+1400
+2200
+3e00
+4100
+4100
+f780
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+1a00
+2c00
+0000
+3800
+0800
+1400
+1400
+2200
+3e00
+4100
+4100
+f780
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 11 0 0
+BITMAP
+3600
+0000
+3800
+0800
+1400
+1400
+2200
+3e00
+4100
+4100
+f780
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+1800
+2400
+1800
+3800
+0800
+1400
+1400
+2200
+3e00
+4100
+4100
+f780
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 9 -1 0
+BITMAP
+1f80
+0c80
+1400
+1480
+2780
+3c80
+4400
+4480
+ef80
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+3a
+46
+82
+80
+80
+80
+80
+42
+3c
+10
+08
+38
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+60
+18
+00
+fe
+42
+42
+48
+78
+48
+42
+42
+fe
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+0c
+30
+00
+fe
+42
+42
+48
+78
+48
+42
+42
+fe
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+10
+28
+00
+fe
+42
+42
+48
+78
+48
+42
+42
+fe
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+6c
+00
+fe
+42
+42
+48
+78
+48
+42
+42
+fe
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 12 2 0
+BITMAP
+c0
+30
+00
+f8
+20
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 12 2 0
+BITMAP
+18
+60
+00
+f8
+20
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 12 2 0
+BITMAP
+20
+50
+00
+f8
+20
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 11 2 0
+BITMAP
+d8
+00
+f8
+20
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+fc
+42
+41
+41
+f1
+41
+41
+42
+fc
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+1a
+2c
+00
+e7
+62
+52
+52
+4a
+4a
+46
+46
+e2
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+30
+0c
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+0c
+30
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+10
+28
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+1a
+2c
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 11 0 0
+BITMAP
+66
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 1
+BITMAP
+82
+44
+28
+10
+28
+44
+82
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 9 -1 0
+BITMAP
+1e80
+2100
+4280
+4480
+4880
+5080
+2080
+6100
+9e00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+30
+0c
+00
+e7
+42
+42
+42
+42
+42
+42
+42
+3c
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+0c
+30
+00
+e7
+42
+42
+42
+42
+42
+42
+42
+3c
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+10
+28
+00
+e7
+42
+42
+42
+42
+42
+42
+42
+3c
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 11 0 0
+BITMAP
+66
+00
+e7
+42
+42
+42
+42
+42
+42
+42
+3c
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+0c
+30
+00
+ee
+44
+44
+28
+28
+10
+10
+10
+7c
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 0 0
+BITMAP
+e0
+40
+7c
+42
+42
+42
+7c
+40
+e0
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 0 0
+BITMAP
+38
+44
+44
+58
+44
+42
+42
+52
+cc
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+60
+18
+00
+78
+84
+04
+7c
+84
+8c
+76
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+18
+60
+00
+78
+84
+04
+7c
+84
+8c
+76
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+10
+28
+00
+78
+84
+04
+7c
+84
+8c
+76
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+34
+58
+00
+78
+84
+04
+7c
+84
+8c
+76
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+6c
+00
+78
+84
+04
+7c
+84
+8c
+76
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+30
+48
+30
+78
+84
+04
+7c
+84
+8c
+76
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+76
+89
+09
+7f
+88
+89
+76
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 -3
+BITMAP
+3a
+46
+82
+80
+80
+42
+3c
+10
+08
+38
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+60
+18
+00
+38
+44
+82
+fe
+80
+42
+3c
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+0c
+30
+00
+38
+44
+82
+fe
+80
+42
+3c
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+10
+28
+00
+38
+44
+82
+fe
+80
+42
+3c
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+6c
+00
+38
+44
+82
+fe
+80
+42
+3c
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 10 2 0
+BITMAP
+c0
+30
+00
+e0
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 10 2 0
+BITMAP
+30
+c0
+00
+e0
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 10 2 0
+BITMAP
+20
+50
+00
+e0
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 9 2 0
+BITMAP
+d8
+00
+e0
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+02
+e4
+18
+28
+44
+3c
+42
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+1a
+2c
+00
+dc
+62
+42
+42
+42
+42
+e7
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+30
+0c
+00
+3c
+42
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+0c
+30
+00
+3c
+42
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+10
+28
+00
+3c
+42
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+1a
+2c
+00
+3c
+42
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+6c
+00
+3c
+42
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 7 0 1
+BITMAP
+18
+18
+00
+ff
+00
+18
+18
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+3d
+46
+89
+91
+a1
+42
+bc
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+30
+0c
+00
+c6
+42
+42
+42
+42
+46
+3b
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+0c
+30
+00
+c6
+42
+42
+42
+42
+46
+3b
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+10
+28
+00
+c6
+42
+42
+42
+42
+46
+3b
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+6c
+00
+c6
+42
+42
+42
+42
+46
+3b
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 13 0 -3
+BITMAP
+06
+18
+00
+e7
+42
+42
+24
+24
+18
+08
+10
+10
+78
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 -3
+BITMAP
+c0
+40
+5c
+62
+41
+41
+41
+62
+5c
+40
+40
+f0
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 -3
+BITMAP
+36
+00
+e7
+42
+42
+24
+24
+18
+08
+10
+10
+78
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/courier14.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/courier14.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/courier14.h	(revision 12606)
@@ -0,0 +1,789 @@
+static unsigned char courier14_0_bits[] = {
+0x00};
+static unsigned char courier14_1_bits[] = {
+0x00};
+static unsigned char courier14_2_bits[] = {
+0x00};
+static unsigned char courier14_3_bits[] = {
+0x00};
+static unsigned char courier14_4_bits[] = {
+0x00};
+static unsigned char courier14_5_bits[] = {
+0x00};
+static unsigned char courier14_6_bits[] = {
+0x00};
+static unsigned char courier14_7_bits[] = {
+0x00};
+static unsigned char courier14_8_bits[] = {
+0x00};
+static unsigned char courier14_9_bits[] = {
+0x00};
+static unsigned char courier14_10_bits[] = {
+0x00};
+static unsigned char courier14_11_bits[] = {
+0x00};
+static unsigned char courier14_12_bits[] = {
+0x00};
+static unsigned char courier14_13_bits[] = {
+0x00};
+static unsigned char courier14_14_bits[] = {
+0x00};
+static unsigned char courier14_15_bits[] = {
+0x00};
+static unsigned char courier14_16_bits[] = {
+0x00};
+static unsigned char courier14_17_bits[] = {
+0x00};
+static unsigned char courier14_18_bits[] = {
+0x00};
+static unsigned char courier14_19_bits[] = {
+0x00};
+static unsigned char courier14_20_bits[] = {
+0x00};
+static unsigned char courier14_21_bits[] = {
+0x00};
+static unsigned char courier14_22_bits[] = {
+0x00};
+static unsigned char courier14_23_bits[] = {
+0x00};
+static unsigned char courier14_24_bits[] = {
+0x00};
+static unsigned char courier14_25_bits[] = {
+0x00};
+static unsigned char courier14_26_bits[] = {
+0x00};
+static unsigned char courier14_27_bits[] = {
+0x00};
+static unsigned char courier14_28_bits[] = {
+0x00};
+static unsigned char courier14_29_bits[] = {
+0x00};
+static unsigned char courier14_30_bits[] = {
+0x00};
+static unsigned char courier14_31_bits[] = {
+0x00};
+static unsigned char courier14_32_bits[] = {
+0x00};
+static unsigned char courier14_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01};
+static unsigned char courier14_34_bits[] = {
+0x09, 0x09, 0x09, 0x09};
+static unsigned char courier14_35_bits[] = {
+0x0a, 0x0a, 0x0a, 0x1f, 0x0a, 0x0a, 0x1f, 0x0a, 0x0a, 0x0a};
+static unsigned char courier14_36_bits[] = {
+0x04, 0x04, 0x1e, 0x11, 0x01, 0x03, 0x0c, 0x10, 0x11, 0x0f, 0x04, 0x04, 
+0x04};
+static unsigned char courier14_37_bits[] = {
+0x06, 0x09, 0x09, 0xce, 0x30, 0x0c, 0x33, 0x48, 0x48, 0x30};
+static unsigned char courier14_38_bits[] = {
+0x1c, 0x02, 0x02, 0x02, 0x15, 0x09, 0x19, 0x26};
+static unsigned char courier14_39_bits[] = {
+0x06, 0x06, 0x03, 0x01};
+static unsigned char courier14_40_bits[] = {
+0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x04};
+static unsigned char courier14_41_bits[] = {
+0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01};
+static unsigned char courier14_42_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x0a, 0x11};
+static unsigned char courier14_43_bits[] = {
+0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08};
+static unsigned char courier14_44_bits[] = {
+0x06, 0x06, 0x03, 0x01};
+static unsigned char courier14_45_bits[] = {
+0x7f};
+static unsigned char courier14_46_bits[] = {
+0x03, 0x03};
+static unsigned char courier14_47_bits[] = {
+0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x01, 0x01};
+static unsigned char courier14_48_bits[] = {
+0x0c, 0x12, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x12, 0x0c};
+static unsigned char courier14_49_bits[] = {
+0x04, 0x06, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_50_bits[] = {
+0x0e, 0x11, 0x11, 0x10, 0x08, 0x04, 0x02, 0x01, 0x11, 0x1f};
+static unsigned char courier14_51_bits[] = {
+0x1c, 0x22, 0x20, 0x20, 0x18, 0x20, 0x20, 0x20, 0x21, 0x1e};
+static unsigned char courier14_52_bits[] = {
+0x18, 0x14, 0x14, 0x12, 0x12, 0x11, 0x11, 0x3f, 0x10, 0x38};
+static unsigned char courier14_53_bits[] = {
+0x3e, 0x02, 0x02, 0x02, 0x1e, 0x20, 0x20, 0x20, 0x21, 0x1e};
+static unsigned char courier14_54_bits[] = {
+0x1c, 0x02, 0x01, 0x01, 0x1d, 0x23, 0x21, 0x21, 0x22, 0x1c};
+static unsigned char courier14_55_bits[] = {
+0x3f, 0x21, 0x20, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08};
+static unsigned char courier14_56_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char courier14_57_bits[] = {
+0x0e, 0x11, 0x21, 0x21, 0x31, 0x2e, 0x20, 0x20, 0x10, 0x0e};
+static unsigned char courier14_58_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03};
+static unsigned char courier14_59_bits[] = {
+0x06, 0x06, 0x00, 0x00, 0x00, 0x06, 0x06, 0x03, 0x01};
+static unsigned char courier14_60_bits[] = {
+0x60, 0x18, 0x06, 0x01, 0x06, 0x18, 0x60};
+static unsigned char courier14_61_bits[] = {
+0x7f, 0x00, 0x7f};
+static unsigned char courier14_62_bits[] = {
+0x03, 0x0c, 0x30, 0x40, 0x30, 0x0c, 0x03};
+static unsigned char courier14_63_bits[] = {
+0x0e, 0x11, 0x10, 0x10, 0x0c, 0x04, 0x00, 0x04, 0x04};
+static unsigned char courier14_64_bits[] = {
+0x1c, 0x22, 0x21, 0x39, 0x25, 0x25, 0x79, 0x01, 0x02, 0x1c};
+static unsigned char courier14_65_bits[] = {
+0x1c, 0x00, 0x10, 0x00, 0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0xef, 0x01};
+static unsigned char courier14_66_bits[] = {
+0x3f, 0x42, 0x42, 0x42, 0x3e, 0x42, 0x42, 0x42, 0x3f};
+static unsigned char courier14_67_bits[] = {
+0x5c, 0x62, 0x41, 0x01, 0x01, 0x01, 0x01, 0x42, 0x3c};
+static unsigned char courier14_68_bits[] = {
+0x3f, 0x42, 0x82, 0x82, 0x82, 0x82, 0x82, 0x42, 0x3f};
+static unsigned char courier14_69_bits[] = {
+0x7f, 0x42, 0x42, 0x12, 0x1e, 0x12, 0x42, 0x42, 0x7f};
+static unsigned char courier14_70_bits[] = {
+0x7f, 0x42, 0x42, 0x12, 0x1e, 0x12, 0x02, 0x02, 0x0f};
+static unsigned char courier14_71_bits[] = {
+0x5c, 0x62, 0x41, 0x01, 0x01, 0xf1, 0x41, 0x42, 0x3c};
+static unsigned char courier14_72_bits[] = {
+0xe7, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0xe7};
+static unsigned char courier14_73_bits[] = {
+0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_74_bits[] = {
+0x7c, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char courier14_75_bits[] = {
+0x77, 0x22, 0x12, 0x0a, 0x0e, 0x12, 0x22, 0x22, 0xc7};
+static unsigned char courier14_76_bits[] = {
+0x1f, 0x04, 0x04, 0x04, 0x04, 0x84, 0x84, 0x84, 0xff};
+static unsigned char courier14_77_bits[] = {
+0xc7, 0x01, 0xc6, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0x92, 0x00, 0x92, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char courier14_78_bits[] = {
+0xe7, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x62, 0x47};
+static unsigned char courier14_79_bits[] = {
+0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_80_bits[] = {
+0x3f, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x0f};
+static unsigned char courier14_81_bits[] = {
+0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x8c, 0x7a};
+static unsigned char courier14_82_bits[] = {
+0x3f, 0x42, 0x42, 0x42, 0x22, 0x1e, 0x22, 0x42, 0x87};
+static unsigned char courier14_83_bits[] = {
+0x2e, 0x31, 0x21, 0x01, 0x1e, 0x20, 0x21, 0x23, 0x1d};
+static unsigned char courier14_84_bits[] = {
+0x7f, 0x49, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e};
+static unsigned char courier14_85_bits[] = {
+0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c};
+static unsigned char courier14_86_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char courier14_87_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x92, 0x00, 0x92, 0x00, 0xaa, 0x00, 0xaa, 0x00, 
+0x44, 0x00, 0x44, 0x00, 0x44, 0x00};
+static unsigned char courier14_88_bits[] = {
+0xe7, 0x42, 0x24, 0x24, 0x18, 0x24, 0x24, 0x42, 0xe7};
+static unsigned char courier14_89_bits[] = {
+0x77, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x08, 0x3e};
+static unsigned char courier14_90_bits[] = {
+0x3f, 0x21, 0x11, 0x08, 0x04, 0x04, 0x22, 0x21, 0x3f};
+static unsigned char courier14_91_bits[] = {
+0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07};
+static unsigned char courier14_92_bits[] = {
+0x01, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20};
+static unsigned char courier14_93_bits[] = {
+0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07};
+static unsigned char courier14_94_bits[] = {
+0x04, 0x0a, 0x0a, 0x11, 0x11};
+static unsigned char courier14_95_bits[] = {
+0xff, 0x01};
+static unsigned char courier14_96_bits[] = {
+0x03, 0x03, 0x06, 0x04};
+static unsigned char courier14_97_bits[] = {
+0x1e, 0x21, 0x20, 0x3e, 0x21, 0x21, 0x5e};
+static unsigned char courier14_98_bits[] = {
+0x03, 0x02, 0x02, 0x3a, 0x46, 0x82, 0x82, 0x82, 0x46, 0x3b};
+static unsigned char courier14_99_bits[] = {
+0x5c, 0x62, 0x41, 0x01, 0x01, 0x42, 0x3c};
+static unsigned char courier14_100_bits[] = {
+0x60, 0x40, 0x40, 0x5c, 0x62, 0x41, 0x41, 0x41, 0x62, 0xdc};
+static unsigned char courier14_101_bits[] = {
+0x1c, 0x22, 0x41, 0x7f, 0x01, 0x42, 0x3c};
+static unsigned char courier14_102_bits[] = {
+0x78, 0x04, 0x04, 0x3f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_103_bits[] = {
+0xdc, 0x62, 0x41, 0x41, 0x41, 0x62, 0x5c, 0x40, 0x20, 0x1e};
+static unsigned char courier14_104_bits[] = {
+0x03, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0xe7};
+static unsigned char courier14_105_bits[] = {
+0x04, 0x04, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_106_bits[] = {
+0x10, 0x10, 0x00, 0x1f, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 
+0x07};
+static unsigned char courier14_107_bits[] = {
+0x03, 0x02, 0x02, 0x72, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x73};
+static unsigned char courier14_108_bits[] = {
+0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_109_bits[] = {
+0xdb, 0x00, 0xb6, 0x00, 0x92, 0x00, 0x92, 0x00, 0x92, 0x00, 0x92, 0x00, 
+0xb7, 0x01};
+static unsigned char courier14_110_bits[] = {
+0x3b, 0x46, 0x42, 0x42, 0x42, 0x42, 0xe7};
+static unsigned char courier14_111_bits[] = {
+0x3c, 0x42, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_112_bits[] = {
+0x3b, 0x46, 0x82, 0x82, 0x82, 0x46, 0x3a, 0x02, 0x02, 0x0f};
+static unsigned char courier14_113_bits[] = {
+0xdc, 0x62, 0x41, 0x41, 0x41, 0x62, 0x5c, 0x40, 0x40, 0xf0};
+static unsigned char courier14_114_bits[] = {
+0x33, 0x4a, 0x06, 0x02, 0x02, 0x02, 0x1f};
+static unsigned char courier14_115_bits[] = {
+0x3e, 0x21, 0x01, 0x1e, 0x20, 0x21, 0x1f};
+static unsigned char courier14_116_bits[] = {
+0x04, 0x04, 0x3f, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38};
+static unsigned char courier14_117_bits[] = {
+0x63, 0x42, 0x42, 0x42, 0x42, 0x62, 0xdc};
+static unsigned char courier14_118_bits[] = {
+0xe7, 0x42, 0x42, 0x24, 0x24, 0x18, 0x18};
+static unsigned char courier14_119_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x92, 0x00, 0x92, 0x00, 0x54, 0x00, 0x6c, 0x00, 
+0x44, 0x00};
+static unsigned char courier14_120_bits[] = {
+0x77, 0x22, 0x14, 0x08, 0x14, 0x22, 0x77};
+static unsigned char courier14_121_bits[] = {
+0xe7, 0x42, 0x42, 0x24, 0x24, 0x18, 0x10, 0x08, 0x08, 0x1e};
+static unsigned char courier14_122_bits[] = {
+0x1f, 0x11, 0x08, 0x04, 0x02, 0x11, 0x1f};
+static unsigned char courier14_123_bits[] = {
+0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04};
+static unsigned char courier14_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier14_125_bits[] = {
+0x01, 0x02, 0x02, 0x02, 0x02, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char courier14_126_bits[] = {
+0x26, 0x19};
+static unsigned char courier14_127_bits[] = {
+0x00};
+static unsigned char courier14_128_bits[] = {
+0x00};
+static unsigned char courier14_129_bits[] = {
+0x00};
+static unsigned char courier14_130_bits[] = {
+0x00};
+static unsigned char courier14_131_bits[] = {
+0x00};
+static unsigned char courier14_132_bits[] = {
+0x00};
+static unsigned char courier14_133_bits[] = {
+0x00};
+static unsigned char courier14_134_bits[] = {
+0x00};
+static unsigned char courier14_135_bits[] = {
+0x00};
+static unsigned char courier14_136_bits[] = {
+0x00};
+static unsigned char courier14_137_bits[] = {
+0x00};
+static unsigned char courier14_138_bits[] = {
+0x00};
+static unsigned char courier14_139_bits[] = {
+0x00};
+static unsigned char courier14_140_bits[] = {
+0x00};
+static unsigned char courier14_141_bits[] = {
+0x00};
+static unsigned char courier14_142_bits[] = {
+0x00};
+static unsigned char courier14_143_bits[] = {
+0x00};
+static unsigned char courier14_144_bits[] = {
+0x00};
+static unsigned char courier14_145_bits[] = {
+0x00};
+static unsigned char courier14_146_bits[] = {
+0x00};
+static unsigned char courier14_147_bits[] = {
+0x00};
+static unsigned char courier14_148_bits[] = {
+0x00};
+static unsigned char courier14_149_bits[] = {
+0x00};
+static unsigned char courier14_150_bits[] = {
+0x00};
+static unsigned char courier14_151_bits[] = {
+0x00};
+static unsigned char courier14_152_bits[] = {
+0x00};
+static unsigned char courier14_153_bits[] = {
+0x00};
+static unsigned char courier14_154_bits[] = {
+0x00};
+static unsigned char courier14_155_bits[] = {
+0x00};
+static unsigned char courier14_156_bits[] = {
+0x00};
+static unsigned char courier14_157_bits[] = {
+0x00};
+static unsigned char courier14_158_bits[] = {
+0x00};
+static unsigned char courier14_159_bits[] = {
+0x00};
+static unsigned char courier14_160_bits[] = {
+0x00};
+static unsigned char courier14_161_bits[] = {
+0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier14_162_bits[] = {
+0x04, 0x04, 0x1e, 0x11, 0x01, 0x11, 0x0e, 0x04, 0x04};
+static unsigned char courier14_163_bits[] = {
+0x18, 0x24, 0x04, 0x04, 0x1e, 0x04, 0x04, 0x42, 0x3f};
+static unsigned char courier14_164_bits[] = {
+0x2d, 0x12, 0x21, 0x21, 0x12, 0x2d};
+static unsigned char courier14_165_bits[] = {
+0x77, 0x22, 0x22, 0x14, 0x3e, 0x08, 0x3e, 0x08, 0x1c};
+static unsigned char courier14_166_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier14_167_bits[] = {
+0x3c, 0x22, 0x02, 0x0f, 0x11, 0x22, 0x3c, 0x10, 0x11, 0x0f};
+static unsigned char courier14_168_bits[] = {
+0x1b};
+static unsigned char courier14_169_bits[] = {
+0x3c, 0x42, 0x99, 0xa5, 0x85, 0xa5, 0x99, 0x42, 0x3c};
+static unsigned char courier14_170_bits[] = {
+0x03, 0x04, 0x07, 0x0d, 0x00, 0x0f};
+static unsigned char courier14_171_bits[] = {
+0x88, 0x44, 0x22, 0x33, 0x22, 0x44, 0x88};
+static unsigned char courier14_172_bits[] = {
+0x7f, 0x40, 0x40};
+static unsigned char courier14_173_bits[] = {
+0x3f};
+static unsigned char courier14_174_bits[] = {
+0x3c, 0x42, 0x9d, 0xa5, 0x9d, 0x95, 0xa5, 0x42, 0x3c};
+static unsigned char courier14_175_bits[] = {
+0x0f};
+static unsigned char courier14_176_bits[] = {
+0x06, 0x09, 0x09, 0x06};
+static unsigned char courier14_177_bits[] = {
+0x08, 0x08, 0x7f, 0x08, 0x08, 0x00, 0x7f};
+static unsigned char courier14_178_bits[] = {
+0x06, 0x09, 0x08, 0x04, 0x02, 0x0f};
+static unsigned char courier14_179_bits[] = {
+0x06, 0x09, 0x06, 0x08, 0x09, 0x06};
+static unsigned char courier14_180_bits[] = {
+0x0c, 0x03};
+static unsigned char courier14_181_bits[] = {
+0x63, 0x42, 0x42, 0x42, 0x42, 0x62, 0xde, 0x02, 0x02, 0x02};
+static unsigned char courier14_182_bits[] = {
+0x7e, 0x29, 0x29, 0x29, 0x2e, 0x28, 0x28, 0x28, 0x28, 0x7c};
+static unsigned char courier14_183_bits[] = {
+0x03, 0x03};
+static unsigned char courier14_184_bits[] = {
+0x02, 0x04, 0x07};
+static unsigned char courier14_185_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x02, 0x07};
+static unsigned char courier14_186_bits[] = {
+0x06, 0x09, 0x09, 0x06, 0x00, 0x0f};
+static unsigned char courier14_187_bits[] = {
+0x11, 0x22, 0x44, 0xcc, 0x44, 0x22, 0x11};
+static unsigned char courier14_188_bits[] = {
+0x02, 0x00, 0x83, 0x00, 0x42, 0x00, 0x22, 0x00, 0x22, 0x01, 0x97, 0x01, 
+0x48, 0x01, 0x28, 0x01, 0xe4, 0x03, 0x02, 0x01};
+static unsigned char courier14_189_bits[] = {
+0x02, 0x00, 0x83, 0x00, 0x42, 0x00, 0x22, 0x00, 0xa2, 0x01, 0x57, 0x02, 
+0x08, 0x02, 0x08, 0x01, 0x84, 0x00, 0xc2, 0x03};
+static unsigned char courier14_190_bits[] = {
+0x06, 0x00, 0x89, 0x00, 0x46, 0x00, 0x28, 0x00, 0x29, 0x01, 0x96, 0x01, 
+0x48, 0x01, 0x28, 0x01, 0xe4, 0x03, 0x02, 0x01};
+static unsigned char courier14_191_bits[] = {
+0x04, 0x04, 0x00, 0x04, 0x06, 0x01, 0x01, 0x11, 0x0e};
+static unsigned char courier14_192_bits[] = {
+0x0c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x82, 0x00, 0xef, 0x01};
+static unsigned char courier14_193_bits[] = {
+0x30, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x82, 0x00, 0xef, 0x01};
+static unsigned char courier14_194_bits[] = {
+0x10, 0x00, 0x28, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x82, 0x00, 0xef, 0x01};
+static unsigned char courier14_195_bits[] = {
+0x58, 0x00, 0x34, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x82, 0x00, 0xef, 0x01};
+static unsigned char courier14_196_bits[] = {
+0x6c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x10, 0x00, 0x28, 0x00, 0x28, 0x00, 
+0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x82, 0x00, 0xef, 0x01};
+static unsigned char courier14_197_bits[] = {
+0x18, 0x00, 0x24, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x82, 0x00, 0xef, 0x01};
+static unsigned char courier14_198_bits[] = {
+0xf8, 0x01, 0x30, 0x01, 0x28, 0x00, 0x28, 0x01, 0xe4, 0x01, 0x3c, 0x01, 
+0x22, 0x00, 0x22, 0x01, 0xf7, 0x01};
+static unsigned char courier14_199_bits[] = {
+0x5c, 0x62, 0x41, 0x01, 0x01, 0x01, 0x01, 0x42, 0x3c, 0x08, 0x10, 0x1c};
+static unsigned char courier14_200_bits[] = {
+0x06, 0x18, 0x00, 0x7f, 0x42, 0x42, 0x12, 0x1e, 0x12, 0x42, 0x42, 0x7f};
+static unsigned char courier14_201_bits[] = {
+0x30, 0x0c, 0x00, 0x7f, 0x42, 0x42, 0x12, 0x1e, 0x12, 0x42, 0x42, 0x7f};
+static unsigned char courier14_202_bits[] = {
+0x08, 0x14, 0x00, 0x7f, 0x42, 0x42, 0x12, 0x1e, 0x12, 0x42, 0x42, 0x7f};
+static unsigned char courier14_203_bits[] = {
+0x36, 0x00, 0x7f, 0x42, 0x42, 0x12, 0x1e, 0x12, 0x42, 0x42, 0x7f};
+static unsigned char courier14_204_bits[] = {
+0x03, 0x0c, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_205_bits[] = {
+0x18, 0x06, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_206_bits[] = {
+0x04, 0x0a, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_207_bits[] = {
+0x1b, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_208_bits[] = {
+0x3f, 0x42, 0x82, 0x82, 0x8f, 0x82, 0x82, 0x42, 0x3f};
+static unsigned char courier14_209_bits[] = {
+0x58, 0x34, 0x00, 0xe7, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x62, 0x47};
+static unsigned char courier14_210_bits[] = {
+0x0c, 0x30, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_211_bits[] = {
+0x30, 0x0c, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_212_bits[] = {
+0x08, 0x14, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_213_bits[] = {
+0x58, 0x34, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_214_bits[] = {
+0x66, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_215_bits[] = {
+0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41};
+static unsigned char courier14_216_bits[] = {
+0x78, 0x01, 0x84, 0x00, 0x42, 0x01, 0x22, 0x01, 0x12, 0x01, 0x0a, 0x01, 
+0x04, 0x01, 0x86, 0x00, 0x79, 0x00};
+static unsigned char courier14_217_bits[] = {
+0x0c, 0x30, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c};
+static unsigned char courier14_218_bits[] = {
+0x30, 0x0c, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c};
+static unsigned char courier14_219_bits[] = {
+0x08, 0x14, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c};
+static unsigned char courier14_220_bits[] = {
+0x66, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c};
+static unsigned char courier14_221_bits[] = {
+0x30, 0x0c, 0x00, 0x77, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x08, 0x3e};
+static unsigned char courier14_222_bits[] = {
+0x07, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x07};
+static unsigned char courier14_223_bits[] = {
+0x1c, 0x22, 0x22, 0x1a, 0x22, 0x42, 0x42, 0x4a, 0x33};
+static unsigned char courier14_224_bits[] = {
+0x06, 0x18, 0x00, 0x1e, 0x21, 0x20, 0x3e, 0x21, 0x31, 0x6e};
+static unsigned char courier14_225_bits[] = {
+0x18, 0x06, 0x00, 0x1e, 0x21, 0x20, 0x3e, 0x21, 0x31, 0x6e};
+static unsigned char courier14_226_bits[] = {
+0x08, 0x14, 0x00, 0x1e, 0x21, 0x20, 0x3e, 0x21, 0x31, 0x6e};
+static unsigned char courier14_227_bits[] = {
+0x2c, 0x1a, 0x00, 0x1e, 0x21, 0x20, 0x3e, 0x21, 0x31, 0x6e};
+static unsigned char courier14_228_bits[] = {
+0x36, 0x00, 0x1e, 0x21, 0x20, 0x3e, 0x21, 0x31, 0x6e};
+static unsigned char courier14_229_bits[] = {
+0x0c, 0x12, 0x0c, 0x1e, 0x21, 0x20, 0x3e, 0x21, 0x31, 0x6e};
+static unsigned char courier14_230_bits[] = {
+0x6e, 0x91, 0x90, 0xfe, 0x11, 0x91, 0x6e};
+static unsigned char courier14_231_bits[] = {
+0x5c, 0x62, 0x41, 0x01, 0x01, 0x42, 0x3c, 0x08, 0x10, 0x1c};
+static unsigned char courier14_232_bits[] = {
+0x06, 0x18, 0x00, 0x1c, 0x22, 0x41, 0x7f, 0x01, 0x42, 0x3c};
+static unsigned char courier14_233_bits[] = {
+0x30, 0x0c, 0x00, 0x1c, 0x22, 0x41, 0x7f, 0x01, 0x42, 0x3c};
+static unsigned char courier14_234_bits[] = {
+0x08, 0x14, 0x00, 0x1c, 0x22, 0x41, 0x7f, 0x01, 0x42, 0x3c};
+static unsigned char courier14_235_bits[] = {
+0x36, 0x00, 0x1c, 0x22, 0x41, 0x7f, 0x01, 0x42, 0x3c};
+static unsigned char courier14_236_bits[] = {
+0x03, 0x0c, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_237_bits[] = {
+0x0c, 0x03, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_238_bits[] = {
+0x04, 0x0a, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_239_bits[] = {
+0x1b, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_240_bits[] = {
+0x40, 0x27, 0x18, 0x14, 0x22, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_241_bits[] = {
+0x58, 0x34, 0x00, 0x3b, 0x46, 0x42, 0x42, 0x42, 0x42, 0xe7};
+static unsigned char courier14_242_bits[] = {
+0x0c, 0x30, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_243_bits[] = {
+0x30, 0x0c, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_244_bits[] = {
+0x08, 0x14, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_245_bits[] = {
+0x58, 0x34, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_246_bits[] = {
+0x36, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_247_bits[] = {
+0x18, 0x18, 0x00, 0xff, 0x00, 0x18, 0x18};
+static unsigned char courier14_248_bits[] = {
+0xbc, 0x62, 0x91, 0x89, 0x85, 0x42, 0x3d};
+static unsigned char courier14_249_bits[] = {
+0x0c, 0x30, 0x00, 0x63, 0x42, 0x42, 0x42, 0x42, 0x62, 0xdc};
+static unsigned char courier14_250_bits[] = {
+0x30, 0x0c, 0x00, 0x63, 0x42, 0x42, 0x42, 0x42, 0x62, 0xdc};
+static unsigned char courier14_251_bits[] = {
+0x08, 0x14, 0x00, 0x63, 0x42, 0x42, 0x42, 0x42, 0x62, 0xdc};
+static unsigned char courier14_252_bits[] = {
+0x36, 0x00, 0x63, 0x42, 0x42, 0x42, 0x42, 0x62, 0xdc};
+static unsigned char courier14_253_bits[] = {
+0x60, 0x18, 0x00, 0xe7, 0x42, 0x42, 0x24, 0x24, 0x18, 0x10, 0x08, 0x08, 
+0x1e};
+static unsigned char courier14_254_bits[] = {
+0x03, 0x02, 0x3a, 0x46, 0x82, 0x82, 0x82, 0x46, 0x3a, 0x02, 0x02, 0x0f};
+static unsigned char courier14_255_bits[] = {
+0x6c, 0x00, 0xe7, 0x42, 0x42, 0x24, 0x24, 0x18, 0x10, 0x08, 0x08, 0x1e};
+static RotFont courier14font[] = {
+{5, 1, 1, courier14_0_bits},
+{5, 1, 1, courier14_1_bits},
+{5, 1, 1, courier14_2_bits},
+{5, 1, 1, courier14_3_bits},
+{5, 1, 1, courier14_4_bits},
+{5, 1, 1, courier14_5_bits},
+{5, 1, 1, courier14_6_bits},
+{5, 1, 1, courier14_7_bits},
+{5, 1, 1, courier14_8_bits},
+{5, 1, 1, courier14_9_bits},
+{5, 1, 1, courier14_10_bits},
+{5, 1, 1, courier14_11_bits},
+{5, 1, 1, courier14_12_bits},
+{5, 1, 1, courier14_13_bits},
+{5, 1, 1, courier14_14_bits},
+{5, 1, 1, courier14_15_bits},
+{5, 1, 1, courier14_16_bits},
+{5, 1, 1, courier14_17_bits},
+{5, 1, 1, courier14_18_bits},
+{5, 1, 1, courier14_19_bits},
+{5, 1, 1, courier14_20_bits},
+{5, 1, 1, courier14_21_bits},
+{5, 1, 1, courier14_22_bits},
+{5, 1, 1, courier14_23_bits},
+{5, 1, 1, courier14_24_bits},
+{5, 1, 1, courier14_25_bits},
+{5, 1, 1, courier14_26_bits},
+{5, 1, 1, courier14_27_bits},
+{5, 1, 1, courier14_28_bits},
+{5, 1, 1, courier14_29_bits},
+{5, 1, 1, courier14_30_bits},
+{5, 1, 1, courier14_31_bits},
+{6, 1, 1, courier14_32_bits},
+{1, 9, 9, courier14_33_bits},
+{4, 4, 10, courier14_34_bits},
+{5, 10, 9, courier14_35_bits},
+{5, 13, 11, courier14_36_bits},
+{8, 10, 10, courier14_37_bits},
+{6, 8, 8, courier14_38_bits},
+{3, 4, 10, courier14_39_bits},
+{3, 12, 10, courier14_40_bits},
+{3, 12, 10, courier14_41_bits},
+{5, 6, 9, courier14_42_bits},
+{7, 7, 8, courier14_43_bits},
+{3, 4, 2, courier14_44_bits},
+{7, 1, 5, courier14_45_bits},
+{2, 2, 2, courier14_46_bits},
+{6, 11, 10, courier14_47_bits},
+{6, 10, 10, courier14_48_bits},
+{5, 10, 10, courier14_49_bits},
+{5, 10, 10, courier14_50_bits},
+{6, 10, 10, courier14_51_bits},
+{6, 10, 10, courier14_52_bits},
+{6, 10, 10, courier14_53_bits},
+{6, 10, 10, courier14_54_bits},
+{6, 10, 10, courier14_55_bits},
+{5, 10, 10, courier14_56_bits},
+{6, 10, 10, courier14_57_bits},
+{2, 7, 7, courier14_58_bits},
+{3, 9, 7, courier14_59_bits},
+{7, 7, 8, courier14_60_bits},
+{7, 3, 6, courier14_61_bits},
+{7, 7, 8, courier14_62_bits},
+{5, 9, 9, courier14_63_bits},
+{7, 10, 9, courier14_64_bits},
+{9, 9, 9, courier14_65_bits},
+{7, 9, 9, courier14_66_bits},
+{7, 9, 9, courier14_67_bits},
+{8, 9, 9, courier14_68_bits},
+{7, 9, 9, courier14_69_bits},
+{7, 9, 9, courier14_70_bits},
+{8, 9, 9, courier14_71_bits},
+{8, 9, 9, courier14_72_bits},
+{5, 9, 9, courier14_73_bits},
+{7, 9, 9, courier14_74_bits},
+{8, 9, 9, courier14_75_bits},
+{8, 9, 9, courier14_76_bits},
+{9, 9, 9, courier14_77_bits},
+{8, 9, 9, courier14_78_bits},
+{8, 9, 9, courier14_79_bits},
+{7, 9, 9, courier14_80_bits},
+{8, 11, 9, courier14_81_bits},
+{8, 9, 9, courier14_82_bits},
+{6, 9, 9, courier14_83_bits},
+{7, 9, 9, courier14_84_bits},
+{8, 9, 9, courier14_85_bits},
+{9, 9, 9, courier14_86_bits},
+{9, 9, 9, courier14_87_bits},
+{8, 9, 9, courier14_88_bits},
+{7, 9, 9, courier14_89_bits},
+{6, 9, 9, courier14_90_bits},
+{3, 12, 10, courier14_91_bits},
+{6, 11, 10, courier14_92_bits},
+{3, 12, 10, courier14_93_bits},
+{5, 5, 9, courier14_94_bits},
+{9, 1, -2, courier14_95_bits},
+{3, 4, 10, courier14_96_bits},
+{7, 7, 7, courier14_97_bits},
+{8, 10, 10, courier14_98_bits},
+{7, 7, 7, courier14_99_bits},
+{8, 10, 10, courier14_100_bits},
+{7, 7, 7, courier14_101_bits},
+{7, 10, 10, courier14_102_bits},
+{8, 10, 7, courier14_103_bits},
+{8, 10, 10, courier14_104_bits},
+{5, 10, 10, courier14_105_bits},
+{5, 13, 10, courier14_106_bits},
+{7, 10, 10, courier14_107_bits},
+{5, 10, 10, courier14_108_bits},
+{9, 7, 7, courier14_109_bits},
+{8, 7, 7, courier14_110_bits},
+{8, 7, 7, courier14_111_bits},
+{8, 10, 7, courier14_112_bits},
+{8, 10, 7, courier14_113_bits},
+{7, 7, 7, courier14_114_bits},
+{6, 7, 7, courier14_115_bits},
+{7, 9, 9, courier14_116_bits},
+{8, 7, 7, courier14_117_bits},
+{8, 7, 7, courier14_118_bits},
+{9, 7, 7, courier14_119_bits},
+{7, 7, 7, courier14_120_bits},
+{8, 10, 7, courier14_121_bits},
+{5, 7, 7, courier14_122_bits},
+{3, 12, 10, courier14_123_bits},
+{1, 11, 9, courier14_124_bits},
+{3, 12, 10, courier14_125_bits},
+{6, 2, 5, courier14_126_bits},
+{5, 1, 1, courier14_127_bits},
+{5, 1, 1, courier14_128_bits},
+{5, 1, 1, courier14_129_bits},
+{5, 1, 1, courier14_130_bits},
+{5, 1, 1, courier14_131_bits},
+{5, 1, 1, courier14_132_bits},
+{5, 1, 1, courier14_133_bits},
+{5, 1, 1, courier14_134_bits},
+{5, 1, 1, courier14_135_bits},
+{5, 1, 1, courier14_136_bits},
+{5, 1, 1, courier14_137_bits},
+{5, 1, 1, courier14_138_bits},
+{5, 1, 1, courier14_139_bits},
+{5, 1, 1, courier14_140_bits},
+{5, 1, 1, courier14_141_bits},
+{5, 1, 1, courier14_142_bits},
+{5, 1, 1, courier14_143_bits},
+{5, 1, 1, courier14_144_bits},
+{5, 1, 1, courier14_145_bits},
+{5, 1, 1, courier14_146_bits},
+{5, 1, 1, courier14_147_bits},
+{5, 1, 1, courier14_148_bits},
+{5, 1, 1, courier14_149_bits},
+{5, 1, 1, courier14_150_bits},
+{5, 1, 1, courier14_151_bits},
+{5, 1, 1, courier14_152_bits},
+{5, 1, 1, courier14_153_bits},
+{5, 1, 1, courier14_154_bits},
+{5, 1, 1, courier14_155_bits},
+{5, 1, 1, courier14_156_bits},
+{5, 1, 1, courier14_157_bits},
+{5, 1, 1, courier14_158_bits},
+{5, 1, 1, courier14_159_bits},
+{1, 1, 1, courier14_160_bits},
+{1, 9, 7, courier14_161_bits},
+{5, 9, 9, courier14_162_bits},
+{7, 9, 9, courier14_163_bits},
+{6, 6, 7, courier14_164_bits},
+{7, 9, 9, courier14_165_bits},
+{1, 11, 9, courier14_166_bits},
+{6, 10, 9, courier14_167_bits},
+{5, 1, 9, courier14_168_bits},
+{8, 9, 9, courier14_169_bits},
+{4, 6, 9, courier14_170_bits},
+{8, 7, 7, courier14_171_bits},
+{7, 3, 6, courier14_172_bits},
+{6, 1, 5, courier14_173_bits},
+{8, 9, 9, courier14_174_bits},
+{4, 1, 9, courier14_175_bits},
+{4, 4, 10, courier14_176_bits},
+{7, 7, 8, courier14_177_bits},
+{4, 6, 10, courier14_178_bits},
+{4, 6, 10, courier14_179_bits},
+{4, 2, 10, courier14_180_bits},
+{8, 10, 7, courier14_181_bits},
+{7, 10, 9, courier14_182_bits},
+{2, 2, 5, courier14_183_bits},
+{3, 3, 0, courier14_184_bits},
+{3, 6, 10, courier14_185_bits},
+{4, 6, 9, courier14_186_bits},
+{8, 7, 7, courier14_187_bits},
+{10, 10, 10, courier14_188_bits},
+{10, 10, 10, courier14_189_bits},
+{10, 10, 10, courier14_190_bits},
+{5, 9, 7, courier14_191_bits},
+{9, 12, 12, courier14_192_bits},
+{9, 12, 12, courier14_193_bits},
+{9, 12, 12, courier14_194_bits},
+{9, 12, 12, courier14_195_bits},
+{9, 11, 11, courier14_196_bits},
+{9, 12, 12, courier14_197_bits},
+{9, 9, 9, courier14_198_bits},
+{7, 12, 9, courier14_199_bits},
+{7, 12, 12, courier14_200_bits},
+{7, 12, 12, courier14_201_bits},
+{7, 12, 12, courier14_202_bits},
+{7, 11, 11, courier14_203_bits},
+{5, 12, 12, courier14_204_bits},
+{5, 12, 12, courier14_205_bits},
+{5, 12, 12, courier14_206_bits},
+{5, 11, 11, courier14_207_bits},
+{8, 9, 9, courier14_208_bits},
+{8, 12, 12, courier14_209_bits},
+{8, 12, 12, courier14_210_bits},
+{8, 12, 12, courier14_211_bits},
+{8, 12, 12, courier14_212_bits},
+{8, 12, 12, courier14_213_bits},
+{8, 11, 11, courier14_214_bits},
+{7, 7, 8, courier14_215_bits},
+{9, 9, 9, courier14_216_bits},
+{8, 12, 12, courier14_217_bits},
+{8, 12, 12, courier14_218_bits},
+{8, 12, 12, courier14_219_bits},
+{8, 11, 11, courier14_220_bits},
+{7, 12, 12, courier14_221_bits},
+{7, 9, 9, courier14_222_bits},
+{7, 9, 9, courier14_223_bits},
+{7, 10, 10, courier14_224_bits},
+{7, 10, 10, courier14_225_bits},
+{7, 10, 10, courier14_226_bits},
+{7, 10, 10, courier14_227_bits},
+{7, 9, 9, courier14_228_bits},
+{7, 10, 10, courier14_229_bits},
+{8, 7, 7, courier14_230_bits},
+{7, 10, 7, courier14_231_bits},
+{7, 10, 10, courier14_232_bits},
+{7, 10, 10, courier14_233_bits},
+{7, 10, 10, courier14_234_bits},
+{7, 9, 9, courier14_235_bits},
+{5, 10, 10, courier14_236_bits},
+{5, 10, 10, courier14_237_bits},
+{5, 10, 10, courier14_238_bits},
+{5, 9, 9, courier14_239_bits},
+{8, 12, 12, courier14_240_bits},
+{8, 10, 10, courier14_241_bits},
+{8, 10, 10, courier14_242_bits},
+{8, 10, 10, courier14_243_bits},
+{8, 10, 10, courier14_244_bits},
+{8, 10, 10, courier14_245_bits},
+{8, 9, 9, courier14_246_bits},
+{8, 7, 8, courier14_247_bits},
+{8, 7, 7, courier14_248_bits},
+{8, 10, 10, courier14_249_bits},
+{8, 10, 10, courier14_250_bits},
+{8, 10, 10, courier14_251_bits},
+{8, 9, 9, courier14_252_bits},
+{8, 13, 10, courier14_253_bits},
+{8, 12, 9, courier14_254_bits},
+{8, 12, 9, courier14_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/courier18.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/courier18.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/courier18.bdf	(revision 12606)
@@ -0,0 +1,3453 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Courier-Medium-R-Normal--18-180-75-75-M-110-ISO8859-1
+SIZE 18 75 75
+FONTBOUNDINGBOX 12 19 -1 -4
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Courier"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 18
+POINT_SIZE 180
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "M"
+AVERAGE_WIDTH 110
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 11
+X_HEIGHT 8
+FACE_NAME "Courier"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "No mark"
+_DEC_DEVICE_FONTNAMES "PS=Courier"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Courier"
+FONT "-Adobe-Courier-Medium-R-Normal--18-180-75-75-M-110-ISO8859-1"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 11
+DEFAULT_CHAR 32
+FONT_ASCENT 14
+FONT_DESCENT 4
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 2 12 4 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+40
+40
+00
+c0
+c0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 5 3 7
+BITMAP
+d8
+d8
+d8
+90
+90
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 15 1 -2
+BITMAP
+1200
+1200
+1200
+1200
+1200
+ff80
+2400
+2400
+2400
+ff00
+2400
+2400
+2400
+2400
+2400
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 15 2 -2
+BITMAP
+10
+10
+7a
+86
+82
+80
+70
+0c
+02
+82
+c2
+bc
+10
+10
+10
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+7000
+8800
+8800
+8800
+7180
+0e00
+3000
+ce00
+1100
+1100
+1100
+0e00
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 10 2 0
+BITMAP
+38
+44
+40
+40
+20
+74
+88
+88
+98
+66
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 4 5 3 7
+BITMAP
+30
+30
+60
+60
+c0
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 3 14 5 -2
+BITMAP
+20
+40
+40
+80
+80
+80
+80
+80
+80
+80
+80
+40
+40
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 3 14 3 -2
+BITMAP
+80
+40
+40
+20
+20
+20
+20
+20
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 8 2 4
+BITMAP
+10
+10
+10
+fe
+38
+28
+44
+44
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 9 1 1
+BITMAP
+0800
+0800
+0800
+0800
+ff80
+0800
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 4 5 3 -3
+BITMAP
+30
+30
+60
+60
+c0
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 1 1 5
+BITMAP
+ff80
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 2 2 4 0
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 16 1 -3
+BITMAP
+01
+01
+02
+02
+04
+04
+08
+08
+10
+10
+20
+20
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+38
+44
+82
+82
+82
+82
+82
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+30
+d0
+10
+10
+10
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+1c
+22
+41
+41
+01
+02
+04
+08
+10
+20
+41
+ff
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+78
+84
+02
+02
+04
+38
+04
+02
+02
+02
+84
+78
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+0c
+14
+14
+24
+24
+44
+44
+84
+fe
+04
+04
+1e
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+7e
+40
+40
+40
+5c
+62
+01
+01
+01
+01
+c2
+3c
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+1e
+20
+40
+40
+80
+b8
+c4
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 2 0
+BITMAP
+ff
+81
+02
+02
+04
+04
+04
+04
+08
+08
+08
+08
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+38
+44
+82
+82
+44
+38
+44
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+38
+44
+82
+82
+82
+46
+3a
+02
+02
+04
+08
+f0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 2 8 5 0
+BITMAP
+c0
+c0
+00
+00
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 11 2 -3
+BITMAP
+18
+18
+00
+00
+00
+00
+30
+30
+60
+60
+c0
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 9 0 1
+BITMAP
+00c0
+0300
+0c00
+3000
+c000
+3000
+0c00
+0300
+00c0
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 4 1 3
+BITMAP
+ff80
+0000
+0000
+ff80
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 9 0 1
+BITMAP
+c000
+3000
+0c00
+0300
+00c0
+0300
+0c00
+3000
+c000
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 11 2 0
+BITMAP
+7c
+86
+82
+02
+04
+08
+30
+20
+00
+30
+30
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 13 2 -1
+BITMAP
+3c
+42
+82
+82
+8e
+92
+92
+92
+8f
+80
+80
+43
+3c
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 11 0 0
+BITMAP
+3c00
+0400
+0a00
+0a00
+1100
+1100
+2080
+3f80
+4040
+4040
+f1e0
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+fe00
+4100
+4100
+4100
+4200
+7e00
+4100
+4080
+4080
+4100
+fe00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+1e80
+6180
+4080
+8000
+8000
+8000
+8000
+8000
+4080
+6100
+1e00
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 1 0
+BITMAP
+fc
+42
+41
+41
+41
+41
+41
+41
+41
+42
+fc
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 1 0
+BITMAP
+ff
+41
+41
+41
+48
+78
+48
+41
+41
+41
+ff
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 1 0
+BITMAP
+ff
+41
+41
+41
+48
+78
+48
+40
+40
+40
+f0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 11 1 0
+BITMAP
+1e80
+6180
+4080
+8000
+8000
+8000
+83c0
+8080
+4080
+6100
+1e00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+e380
+4100
+4100
+4100
+4100
+7f00
+4100
+4100
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 11 2 0
+BITMAP
+fe
+10
+10
+10
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+1f80
+0200
+0200
+0200
+0200
+0200
+8200
+8200
+8200
+4400
+3800
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 11 0 0
+BITMAP
+f3c0
+4100
+4200
+4400
+4800
+5800
+6400
+4200
+4200
+4100
+f1c0
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+f800
+2000
+2000
+2000
+2000
+2000
+2000
+2080
+2080
+2080
+ff80
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 11 0 0
+BITMAP
+e0e0
+60c0
+5140
+5140
+4a40
+4a40
+4440
+4440
+4040
+4040
+f1e0
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+e780
+6100
+5100
+5100
+4900
+4900
+4500
+4500
+4300
+4300
+f100
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+fe00
+4100
+4080
+4080
+4080
+4100
+7e00
+4000
+4000
+4000
+f800
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 -2
+BITMAP
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+3880
+4700
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 11 1 0
+BITMAP
+fe00
+4100
+4100
+4100
+4200
+7c00
+4200
+4200
+4100
+4100
+f0c0
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 2 0
+BITMAP
+3a
+46
+82
+80
+40
+3c
+02
+01
+81
+c2
+bc
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+ff80
+8880
+8880
+8880
+0800
+0800
+0800
+0800
+0800
+0800
+3e00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 11 0 0
+BITMAP
+f3c0
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+2100
+1e00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 11 0 0
+BITMAP
+f1e0
+4040
+4040
+2080
+2080
+1100
+1100
+0a00
+0a00
+0400
+0400
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 11 0 0
+BITMAP
+f1e0
+4040
+4440
+4440
+4440
+2a80
+2a80
+2a80
+2a80
+1100
+1100
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+e380
+4100
+2200
+2200
+1400
+0800
+1400
+2200
+2200
+4100
+e380
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+e380
+4100
+2200
+2200
+1400
+1400
+0800
+0800
+0800
+0800
+3e00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 11 2 0
+BITMAP
+fe
+82
+84
+08
+08
+10
+20
+20
+42
+82
+fe
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 3 15 5 -3
+BITMAP
+e0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+e0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 16 2 -3
+BITMAP
+80
+80
+40
+40
+20
+20
+10
+10
+08
+08
+04
+04
+02
+02
+01
+01
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 3 15 3 -3
+BITMAP
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+e0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 4 2 8
+BITMAP
+10
+28
+44
+82
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 1 0 -4
+BITMAP
+ffe0
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 4 5 3 7
+BITMAP
+c0
+c0
+60
+60
+30
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 8 1 0
+BITMAP
+3c00
+4200
+0200
+7e00
+8200
+8200
+8600
+7b80
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+c000
+4000
+4000
+4000
+5e00
+6100
+4080
+4080
+4080
+4080
+6100
+de00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 8 1 0
+BITMAP
+3d
+43
+81
+80
+80
+80
+43
+3c
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+0300
+0100
+0100
+0100
+3d00
+4300
+8100
+8100
+8100
+8100
+4300
+3d80
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 8 1 0
+BITMAP
+3c
+42
+81
+ff
+80
+80
+43
+3c
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 2 0
+BITMAP
+0f
+10
+20
+20
+fe
+20
+20
+20
+20
+20
+20
+fe
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 -4
+BITMAP
+3d80
+4300
+8100
+8100
+8100
+8100
+4300
+3d00
+0100
+0100
+0200
+7c00
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+c000
+4000
+4000
+4000
+5e00
+6100
+4100
+4100
+4100
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 11 2 0
+BITMAP
+10
+10
+00
+70
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 6 15 2 -4
+BITMAP
+08
+08
+00
+fc
+04
+04
+04
+04
+04
+04
+04
+04
+04
+08
+f0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+c000
+4000
+4000
+4000
+4f00
+4400
+4800
+7000
+4800
+4400
+4200
+c780
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+f0
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 8 0 0
+BITMAP
+d980
+6640
+4440
+4440
+4440
+4440
+4440
+e660
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 8 1 0
+BITMAP
+de00
+6100
+4100
+4100
+4100
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 8 1 0
+BITMAP
+3c
+42
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 -4
+BITMAP
+de00
+6100
+4080
+4080
+4080
+4080
+6100
+5e00
+4000
+4000
+4000
+f000
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 -4
+BITMAP
+3d80
+4300
+8100
+8100
+8100
+8100
+4300
+3d00
+0100
+0100
+0100
+0780
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 8 1 0
+BITMAP
+ee
+31
+20
+20
+20
+20
+20
+fe
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 8 2 0
+BITMAP
+7a
+86
+82
+70
+0c
+82
+c2
+bc
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 2 0
+BITMAP
+20
+20
+20
+fe
+20
+20
+20
+20
+20
+21
+1e
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 8 1 0
+BITMAP
+c300
+4100
+4100
+4100
+4100
+4100
+4300
+3d80
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 8 1 0
+BITMAP
+e380
+4100
+2200
+2200
+1400
+1400
+0800
+0800
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 8 1 0
+BITMAP
+e380
+4100
+4900
+4900
+5500
+5500
+2200
+2200
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 8 1 0
+BITMAP
+e7
+42
+24
+18
+18
+24
+42
+e7
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 -4
+BITMAP
+e380
+4100
+4100
+2200
+2200
+1400
+1400
+0800
+0800
+1000
+1000
+f800
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 8 2 0
+BITMAP
+fe
+82
+84
+08
+10
+22
+42
+fe
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 15 3 -3
+BITMAP
+18
+20
+20
+20
+20
+20
+c0
+20
+20
+20
+20
+20
+20
+20
+18
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 1 15 5 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 15 3 -3
+BITMAP
+c0
+20
+20
+20
+20
+20
+18
+20
+20
+20
+20
+20
+20
+20
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 3 1 4
+BITMAP
+60
+99
+06
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 2 13 4 -4
+BITMAP
+c0
+c0
+00
+00
+80
+80
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 6 12 2 0
+BITMAP
+10
+10
+10
+3c
+44
+84
+80
+80
+44
+38
+10
+10
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 1 0
+BITMAP
+1c
+22
+20
+20
+10
+fc
+10
+20
+21
+41
+7e
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 6 7 2 2
+BITMAP
+84
+78
+84
+84
+84
+78
+84
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+e380
+4100
+2200
+2200
+1400
+1400
+7f00
+0800
+7f00
+0800
+3e00
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 1 15 5 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+00
+00
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 13 2 -1
+BITMAP
+3e
+42
+42
+40
+70
+8c
+82
+62
+1c
+04
+84
+84
+f8
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 1 3 10
+BITMAP
+d8
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 11 0 0
+BITMAP
+1e00
+6180
+4e80
+9240
+a040
+a040
+a040
+9240
+4c80
+6180
+1e00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 6 8 2 3
+BITMAP
+70
+08
+78
+88
+98
+ec
+00
+fc
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 8 1 0
+BITMAP
+0880
+3300
+6600
+cc00
+cc00
+6600
+3300
+0880
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 4 1 3
+BITMAP
+ff80
+0080
+0080
+0080
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 1 1 5
+BITMAP
+ff
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 11 0 0
+BITMAP
+1f00
+60c0
+5e40
+9120
+9120
+9e20
+9420
+9220
+51c0
+6080
+1f00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 1 3 9
+BITMAP
+f8
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 5 3 7
+BITMAP
+70
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 9 1 1
+BITMAP
+0800
+0800
+0800
+ff80
+0800
+0800
+0800
+0000
+ff80
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 7 3 5
+BITMAP
+70
+88
+08
+10
+20
+40
+f8
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 7 3 5
+BITMAP
+70
+88
+08
+30
+08
+88
+70
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 3 3 4 9
+BITMAP
+20
+40
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 -4
+BITMAP
+c300
+4100
+4100
+4100
+4100
+4100
+4300
+7d80
+4000
+4000
+4000
+4000
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 13 1 -1
+BITMAP
+3f
+4a
+8a
+8a
+8a
+4a
+3a
+0a
+0a
+0a
+0a
+0a
+3b
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 2 2 4 5
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 3 3 4 -3
+BITMAP
+40
+20
+c0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 7 3 5
+BITMAP
+20
+e0
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 6 8 2 3
+BITMAP
+78
+84
+84
+84
+84
+78
+00
+fc
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 8 1 0
+BITMAP
+8800
+6600
+3300
+1980
+1980
+3300
+6600
+8800
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 13 0 0
+BITMAP
+2000
+e000
+2040
+2080
+2100
+2100
+fa40
+04c0
+0940
+0a40
+13e0
+2040
+00e0
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 13 0 0
+BITMAP
+2000
+e000
+2040
+2080
+2100
+2100
+fac0
+0520
+0920
+0840
+1080
+2100
+03e0
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 13 0 0
+BITMAP
+7000
+8800
+0840
+3080
+0900
+8900
+7240
+04c0
+0940
+0a40
+13e0
+2040
+00e0
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 6 12 2 -3
+BITMAP
+18
+18
+00
+10
+10
+70
+80
+80
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 15 0 0
+BITMAP
+1000
+0800
+0400
+0000
+3c00
+0400
+0a00
+0a00
+1100
+1100
+2080
+3f80
+4040
+4040
+f1e0
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 15 0 0
+BITMAP
+0200
+0400
+0800
+0000
+3c00
+0400
+0a00
+0a00
+1100
+1100
+2080
+3f80
+4040
+4040
+f1e0
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 15 0 0
+BITMAP
+0400
+0a00
+1100
+0000
+3c00
+0400
+0a00
+0a00
+1100
+1100
+2080
+3f80
+4040
+4040
+f1e0
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 14 0 0
+BITMAP
+1900
+2600
+0000
+3c00
+0400
+0a00
+0a00
+1100
+1100
+2080
+3f80
+4040
+4040
+f1e0
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 14 0 0
+BITMAP
+1b00
+0000
+0000
+3c00
+0400
+0a00
+0a00
+1100
+1100
+2080
+3f80
+4040
+4040
+f1e0
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 15 0 0
+BITMAP
+0c00
+1200
+1200
+0c00
+7c00
+0400
+0a00
+0a00
+1100
+1100
+2080
+3f80
+4040
+4040
+f1e0
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 11 -1 0
+BITMAP
+1fe0
+0620
+0a20
+0a00
+1240
+13c0
+3e40
+2200
+4220
+4220
+e7e0
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 -3
+BITMAP
+1e80
+6180
+4080
+8000
+8000
+8000
+8000
+8000
+4080
+6100
+1e00
+0800
+0400
+1800
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 15 1 0
+BITMAP
+20
+10
+08
+00
+ff
+41
+41
+41
+48
+78
+48
+41
+41
+41
+ff
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 15 1 0
+BITMAP
+04
+08
+10
+00
+ff
+41
+41
+41
+48
+78
+48
+41
+41
+41
+ff
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 15 1 0
+BITMAP
+18
+24
+42
+00
+ff
+41
+41
+41
+48
+78
+48
+41
+41
+41
+ff
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 14 1 0
+BITMAP
+66
+00
+00
+ff
+41
+41
+41
+48
+78
+48
+41
+41
+41
+ff
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 15 2 0
+BITMAP
+20
+10
+08
+00
+fe
+10
+10
+10
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 15 2 0
+BITMAP
+08
+10
+20
+00
+fe
+10
+10
+10
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 15 2 0
+BITMAP
+10
+28
+44
+00
+fe
+10
+10
+10
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 14 2 0
+BITMAP
+6c
+00
+00
+fe
+10
+10
+10
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 1 0
+BITMAP
+fc
+42
+41
+41
+41
+f1
+41
+41
+41
+42
+fc
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+1900
+2600
+0000
+e780
+6100
+5100
+5100
+4900
+4900
+4500
+4500
+4300
+4300
+f100
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 15 1 0
+BITMAP
+1000
+0800
+0400
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 15 1 0
+BITMAP
+0400
+0800
+1000
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 15 1 0
+BITMAP
+0800
+1400
+2200
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+1900
+2600
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+3600
+0000
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 9 1 1
+BITMAP
+8080
+4100
+2200
+1400
+0800
+1400
+2200
+4100
+8080
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 11 0 0
+BITMAP
+0e20
+3140
+2080
+4140
+4240
+4440
+4840
+5040
+2080
+5180
+8e00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 15 0 0
+BITMAP
+1000
+0800
+0400
+0000
+f3c0
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+2100
+1e00
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 15 0 0
+BITMAP
+0200
+0400
+0800
+0000
+f3c0
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+2100
+1e00
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 15 0 0
+BITMAP
+0c00
+1200
+2100
+0000
+f3c0
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+2100
+1e00
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 14 0 0
+BITMAP
+3300
+0000
+0000
+f3c0
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+2100
+1e00
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 15 1 0
+BITMAP
+0200
+0400
+0800
+0000
+e380
+4100
+2200
+2200
+1400
+1400
+0800
+0800
+0800
+0800
+3e00
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+e000
+4000
+7e00
+4100
+4080
+4080
+4100
+7e00
+4000
+4000
+e000
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+1c
+22
+42
+42
+44
+4c
+42
+41
+41
+41
+49
+e6
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+2000
+1000
+0800
+0000
+3c00
+4200
+0200
+7e00
+8200
+8200
+8600
+7b80
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+0400
+0800
+1000
+0000
+3c00
+4200
+0200
+7e00
+8200
+8200
+8600
+7b80
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+1800
+2400
+4200
+0000
+3c00
+4200
+0200
+7e00
+8200
+8200
+8600
+7b80
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+3200
+4c00
+0000
+3c00
+4200
+0200
+7e00
+8200
+8200
+8600
+7b80
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+3600
+0000
+0000
+3c00
+4200
+0200
+7e00
+8200
+8200
+8600
+7b80
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+1800
+2400
+2400
+1800
+0000
+3c00
+4200
+0200
+7e00
+8200
+8200
+8600
+7b80
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 8 0 0
+BITMAP
+7180
+8a40
+0420
+7fe0
+8400
+8400
+8a20
+71c0
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 1 -3
+BITMAP
+3d
+43
+81
+80
+80
+80
+43
+3c
+10
+08
+30
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+20
+10
+08
+00
+3c
+42
+81
+ff
+80
+80
+43
+3c
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+04
+08
+10
+00
+3c
+42
+81
+ff
+80
+80
+43
+3c
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+18
+24
+42
+00
+3c
+42
+81
+ff
+80
+80
+43
+3c
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 1 0
+BITMAP
+66
+00
+00
+3c
+42
+81
+ff
+80
+80
+43
+3c
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+40
+20
+10
+00
+70
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+08
+10
+20
+00
+70
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+10
+28
+44
+00
+70
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 11 2 0
+BITMAP
+6c
+00
+00
+70
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+73
+8c
+34
+42
+02
+3d
+43
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+1900
+2600
+0000
+de00
+6100
+4100
+4100
+4100
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+20
+10
+08
+00
+3c
+42
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+02
+04
+08
+00
+3c
+42
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+18
+24
+42
+00
+3c
+42
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 1 0
+BITMAP
+32
+4c
+00
+3c
+42
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 1 0
+BITMAP
+66
+00
+00
+3c
+42
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 9 1 1
+BITMAP
+18
+18
+00
+00
+ff
+00
+00
+18
+18
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 8 1 0
+BITMAP
+3d
+42
+85
+89
+91
+a1
+42
+bc
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+1000
+0800
+0400
+0000
+c300
+4100
+4100
+4100
+4100
+4100
+4300
+3d80
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+0400
+0800
+1000
+0000
+c300
+4100
+4100
+4100
+4100
+4100
+4300
+3d80
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+0800
+1400
+2200
+0000
+c300
+4100
+4100
+4100
+4100
+4100
+4300
+3d80
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+3600
+0000
+0000
+c300
+4100
+4100
+4100
+4100
+4100
+4300
+3d80
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 16 1 -4
+BITMAP
+0200
+0400
+0800
+0000
+e380
+4100
+4100
+2200
+2200
+1400
+1400
+0800
+0800
+1000
+1000
+f800
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 16 1 -4
+BITMAP
+c000
+4000
+4000
+4000
+5e00
+6100
+4080
+4080
+4080
+4080
+6100
+5e00
+4000
+4000
+4000
+f000
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 15 1 -4
+BITMAP
+3600
+0000
+0000
+e380
+4100
+4100
+2200
+2200
+1400
+1400
+0800
+0800
+1000
+1000
+f800
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/courier18.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/courier18.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/courier18.h	(revision 12606)
@@ -0,0 +1,906 @@
+static unsigned char courier18_0_bits[] = {
+0x00};
+static unsigned char courier18_1_bits[] = {
+0x00};
+static unsigned char courier18_2_bits[] = {
+0x00};
+static unsigned char courier18_3_bits[] = {
+0x00};
+static unsigned char courier18_4_bits[] = {
+0x00};
+static unsigned char courier18_5_bits[] = {
+0x00};
+static unsigned char courier18_6_bits[] = {
+0x00};
+static unsigned char courier18_7_bits[] = {
+0x00};
+static unsigned char courier18_8_bits[] = {
+0x00};
+static unsigned char courier18_9_bits[] = {
+0x00};
+static unsigned char courier18_10_bits[] = {
+0x00};
+static unsigned char courier18_11_bits[] = {
+0x00};
+static unsigned char courier18_12_bits[] = {
+0x00};
+static unsigned char courier18_13_bits[] = {
+0x00};
+static unsigned char courier18_14_bits[] = {
+0x00};
+static unsigned char courier18_15_bits[] = {
+0x00};
+static unsigned char courier18_16_bits[] = {
+0x00};
+static unsigned char courier18_17_bits[] = {
+0x00};
+static unsigned char courier18_18_bits[] = {
+0x00};
+static unsigned char courier18_19_bits[] = {
+0x00};
+static unsigned char courier18_20_bits[] = {
+0x00};
+static unsigned char courier18_21_bits[] = {
+0x00};
+static unsigned char courier18_22_bits[] = {
+0x00};
+static unsigned char courier18_23_bits[] = {
+0x00};
+static unsigned char courier18_24_bits[] = {
+0x00};
+static unsigned char courier18_25_bits[] = {
+0x00};
+static unsigned char courier18_26_bits[] = {
+0x00};
+static unsigned char courier18_27_bits[] = {
+0x00};
+static unsigned char courier18_28_bits[] = {
+0x00};
+static unsigned char courier18_29_bits[] = {
+0x00};
+static unsigned char courier18_30_bits[] = {
+0x00};
+static unsigned char courier18_31_bits[] = {
+0x00};
+static unsigned char courier18_32_bits[] = {
+0x00};
+static unsigned char courier18_33_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x00, 0x03, 0x03};
+static unsigned char courier18_34_bits[] = {
+0x1b, 0x1b, 0x1b, 0x09, 0x09};
+static unsigned char courier18_35_bits[] = {
+0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 0xff, 0x01, 
+0x24, 0x00, 0x24, 0x00, 0x24, 0x00, 0xff, 0x00, 0x24, 0x00, 0x24, 0x00, 
+0x24, 0x00, 0x24, 0x00, 0x24, 0x00};
+static unsigned char courier18_36_bits[] = {
+0x08, 0x08, 0x5e, 0x61, 0x41, 0x01, 0x0e, 0x30, 0x40, 0x41, 0x43, 0x3d, 
+0x08, 0x08, 0x08};
+static unsigned char courier18_37_bits[] = {
+0x0e, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x8e, 0x01, 0x70, 0x00, 
+0x0c, 0x00, 0x73, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x70, 0x00};
+static unsigned char courier18_38_bits[] = {
+0x1c, 0x22, 0x02, 0x02, 0x04, 0x2e, 0x11, 0x11, 0x19, 0x66};
+static unsigned char courier18_39_bits[] = {
+0x0c, 0x0c, 0x06, 0x06, 0x03};
+static unsigned char courier18_40_bits[] = {
+0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 
+0x02, 0x04};
+static unsigned char courier18_41_bits[] = {
+0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 
+0x02, 0x01};
+static unsigned char courier18_42_bits[] = {
+0x08, 0x08, 0x08, 0x7f, 0x1c, 0x14, 0x22, 0x22};
+static unsigned char courier18_43_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0xff, 0x01, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char courier18_44_bits[] = {
+0x0c, 0x0c, 0x06, 0x06, 0x03};
+static unsigned char courier18_45_bits[] = {
+0xff, 0x01};
+static unsigned char courier18_46_bits[] = {
+0x03, 0x03};
+static unsigned char courier18_47_bits[] = {
+0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 
+0x02, 0x02, 0x01, 0x01};
+static unsigned char courier18_48_bits[] = {
+0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char courier18_49_bits[] = {
+0x0c, 0x0b, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f};
+static unsigned char courier18_50_bits[] = {
+0x38, 0x44, 0x82, 0x82, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x82, 0xff};
+static unsigned char courier18_51_bits[] = {
+0x1e, 0x21, 0x40, 0x40, 0x20, 0x1c, 0x20, 0x40, 0x40, 0x40, 0x21, 0x1e};
+static unsigned char courier18_52_bits[] = {
+0x30, 0x28, 0x28, 0x24, 0x24, 0x22, 0x22, 0x21, 0x7f, 0x20, 0x20, 0x78};
+static unsigned char courier18_53_bits[] = {
+0x7e, 0x02, 0x02, 0x02, 0x3a, 0x46, 0x80, 0x80, 0x80, 0x80, 0x43, 0x3c};
+static unsigned char courier18_54_bits[] = {
+0x78, 0x04, 0x02, 0x02, 0x01, 0x1d, 0x23, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char courier18_55_bits[] = {
+0xff, 0x81, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10};
+static unsigned char courier18_56_bits[] = {
+0x1c, 0x22, 0x41, 0x41, 0x22, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char courier18_57_bits[] = {
+0x1c, 0x22, 0x41, 0x41, 0x41, 0x62, 0x5c, 0x40, 0x40, 0x20, 0x10, 0x0f};
+static unsigned char courier18_58_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03};
+static unsigned char courier18_59_bits[] = {
+0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x06, 0x06, 0x03};
+static unsigned char courier18_60_bits[] = {
+0x00, 0x03, 0xc0, 0x00, 0x30, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x0c, 0x00, 
+0x30, 0x00, 0xc0, 0x00, 0x00, 0x03};
+static unsigned char courier18_61_bits[] = {
+0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01};
+static unsigned char courier18_62_bits[] = {
+0x03, 0x00, 0x0c, 0x00, 0x30, 0x00, 0xc0, 0x00, 0x00, 0x03, 0xc0, 0x00, 
+0x30, 0x00, 0x0c, 0x00, 0x03, 0x00};
+static unsigned char courier18_63_bits[] = {
+0x3e, 0x61, 0x41, 0x40, 0x20, 0x10, 0x0c, 0x04, 0x00, 0x0c, 0x0c};
+static unsigned char courier18_64_bits[] = {
+0x3c, 0x42, 0x41, 0x41, 0x71, 0x49, 0x49, 0x49, 0xf1, 0x01, 0x01, 0xc2, 
+0x3c};
+static unsigned char courier18_65_bits[] = {
+0x3c, 0x00, 0x20, 0x00, 0x50, 0x00, 0x50, 0x00, 0x88, 0x00, 0x88, 0x00, 
+0x04, 0x01, 0xfc, 0x01, 0x02, 0x02, 0x02, 0x02, 0x8f, 0x07};
+static unsigned char courier18_66_bits[] = {
+0x7f, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x42, 0x00, 0x7e, 0x00, 
+0x82, 0x00, 0x02, 0x01, 0x02, 0x01, 0x82, 0x00, 0x7f, 0x00};
+static unsigned char courier18_67_bits[] = {
+0x78, 0x01, 0x86, 0x01, 0x02, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x02, 0x01, 0x86, 0x00, 0x78, 0x00};
+static unsigned char courier18_68_bits[] = {
+0x3f, 0x42, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x42, 0x3f};
+static unsigned char courier18_69_bits[] = {
+0xff, 0x82, 0x82, 0x82, 0x12, 0x1e, 0x12, 0x82, 0x82, 0x82, 0xff};
+static unsigned char courier18_70_bits[] = {
+0xff, 0x82, 0x82, 0x82, 0x12, 0x1e, 0x12, 0x02, 0x02, 0x02, 0x0f};
+static unsigned char courier18_71_bits[] = {
+0x78, 0x01, 0x86, 0x01, 0x02, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0xc1, 0x03, 0x01, 0x01, 0x02, 0x01, 0x86, 0x00, 0x78, 0x00};
+static unsigned char courier18_72_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xfe, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char courier18_73_bits[] = {
+0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f};
+static unsigned char courier18_74_bits[] = {
+0xf8, 0x01, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 
+0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x22, 0x00, 0x1c, 0x00};
+static unsigned char courier18_75_bits[] = {
+0xcf, 0x03, 0x82, 0x00, 0x42, 0x00, 0x22, 0x00, 0x12, 0x00, 0x1a, 0x00, 
+0x26, 0x00, 0x42, 0x00, 0x42, 0x00, 0x82, 0x00, 0x8f, 0x03};
+static unsigned char courier18_76_bits[] = {
+0x1f, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 
+0x04, 0x00, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0xff, 0x01};
+static unsigned char courier18_77_bits[] = {
+0x07, 0x07, 0x06, 0x03, 0x8a, 0x02, 0x8a, 0x02, 0x52, 0x02, 0x52, 0x02, 
+0x22, 0x02, 0x22, 0x02, 0x02, 0x02, 0x02, 0x02, 0x8f, 0x07};
+static unsigned char courier18_78_bits[] = {
+0xe7, 0x01, 0x86, 0x00, 0x8a, 0x00, 0x8a, 0x00, 0x92, 0x00, 0x92, 0x00, 
+0xa2, 0x00, 0xa2, 0x00, 0xc2, 0x00, 0xc2, 0x00, 0x8f, 0x00};
+static unsigned char courier18_79_bits[] = {
+0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 0xc6, 0x00, 0x38, 0x00};
+static unsigned char courier18_80_bits[] = {
+0x7f, 0x00, 0x82, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x82, 0x00, 
+0x7e, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x1f, 0x00};
+static unsigned char courier18_81_bits[] = {
+0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 0xc6, 0x00, 0x38, 0x00, 0x1c, 0x01, 
+0xe2, 0x00};
+static unsigned char courier18_82_bits[] = {
+0x7f, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x42, 0x00, 0x3e, 0x00, 
+0x42, 0x00, 0x42, 0x00, 0x82, 0x00, 0x82, 0x00, 0x0f, 0x03};
+static unsigned char courier18_83_bits[] = {
+0x5c, 0x62, 0x41, 0x01, 0x02, 0x3c, 0x40, 0x80, 0x81, 0x43, 0x3d};
+static unsigned char courier18_84_bits[] = {
+0xff, 0x01, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x10, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x7c, 0x00};
+static unsigned char courier18_85_bits[] = {
+0xcf, 0x03, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 
+0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x84, 0x00, 0x78, 0x00};
+static unsigned char courier18_86_bits[] = {
+0x8f, 0x07, 0x02, 0x02, 0x02, 0x02, 0x04, 0x01, 0x04, 0x01, 0x88, 0x00, 
+0x88, 0x00, 0x50, 0x00, 0x50, 0x00, 0x20, 0x00, 0x20, 0x00};
+static unsigned char courier18_87_bits[] = {
+0x8f, 0x07, 0x02, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x54, 0x01, 
+0x54, 0x01, 0x54, 0x01, 0x54, 0x01, 0x88, 0x00, 0x88, 0x00};
+static unsigned char courier18_88_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char courier18_89_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x7c, 0x00};
+static unsigned char courier18_90_bits[] = {
+0x7f, 0x41, 0x21, 0x10, 0x10, 0x08, 0x04, 0x04, 0x42, 0x41, 0x7f};
+static unsigned char courier18_91_bits[] = {
+0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x07};
+static unsigned char courier18_92_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 
+0x40, 0x40, 0x80, 0x80};
+static unsigned char courier18_93_bits[] = {
+0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x07};
+static unsigned char courier18_94_bits[] = {
+0x08, 0x14, 0x22, 0x41};
+static unsigned char courier18_95_bits[] = {
+0xff, 0x07};
+static unsigned char courier18_96_bits[] = {
+0x03, 0x03, 0x06, 0x06, 0x0c};
+static unsigned char courier18_97_bits[] = {
+0x3c, 0x00, 0x42, 0x00, 0x40, 0x00, 0x7e, 0x00, 0x41, 0x00, 0x41, 0x00, 
+0x61, 0x00, 0xde, 0x01};
+static unsigned char courier18_98_bits[] = {
+0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7a, 0x00, 0x86, 0x00, 
+0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x86, 0x00, 0x7b, 0x00};
+static unsigned char courier18_99_bits[] = {
+0xbc, 0xc2, 0x81, 0x01, 0x01, 0x01, 0xc2, 0x3c};
+static unsigned char courier18_100_bits[] = {
+0xc0, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xbc, 0x00, 0xc2, 0x00, 
+0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0xc2, 0x00, 0xbc, 0x01};
+static unsigned char courier18_101_bits[] = {
+0x3c, 0x42, 0x81, 0xff, 0x01, 0x01, 0xc2, 0x3c};
+static unsigned char courier18_102_bits[] = {
+0xf0, 0x08, 0x04, 0x04, 0x7f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x7f};
+static unsigned char courier18_103_bits[] = {
+0xbc, 0x01, 0xc2, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 
+0xc2, 0x00, 0xbc, 0x00, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x3e, 0x00};
+static unsigned char courier18_104_bits[] = {
+0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7a, 0x00, 0x86, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char courier18_105_bits[] = {
+0x08, 0x08, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f};
+static unsigned char courier18_106_bits[] = {
+0x10, 0x10, 0x00, 0x3f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+0x20, 0x10, 0x0f};
+static unsigned char courier18_107_bits[] = {
+0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0xf2, 0x00, 0x22, 0x00, 
+0x12, 0x00, 0x0e, 0x00, 0x12, 0x00, 0x22, 0x00, 0x42, 0x00, 0xe3, 0x01};
+static unsigned char courier18_108_bits[] = {
+0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f};
+static unsigned char courier18_109_bits[] = {
+0x9b, 0x01, 0x66, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 
+0x22, 0x02, 0x67, 0x06};
+static unsigned char courier18_110_bits[] = {
+0x7b, 0x00, 0x86, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0xc7, 0x01};
+static unsigned char courier18_111_bits[] = {
+0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier18_112_bits[] = {
+0x7b, 0x00, 0x86, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 
+0x86, 0x00, 0x7a, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x0f, 0x00};
+static unsigned char courier18_113_bits[] = {
+0xbc, 0x01, 0xc2, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 
+0xc2, 0x00, 0xbc, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xe0, 0x01};
+static unsigned char courier18_114_bits[] = {
+0x77, 0x8c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x7f};
+static unsigned char courier18_115_bits[] = {
+0x5e, 0x61, 0x41, 0x0e, 0x30, 0x41, 0x43, 0x3d};
+static unsigned char courier18_116_bits[] = {
+0x04, 0x04, 0x04, 0x7f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x84, 0x78};
+static unsigned char courier18_117_bits[] = {
+0xc3, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 
+0xc2, 0x00, 0xbc, 0x01};
+static unsigned char courier18_118_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 
+0x10, 0x00, 0x10, 0x00};
+static unsigned char courier18_119_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x92, 0x00, 0x92, 0x00, 0xaa, 0x00, 0xaa, 0x00, 
+0x44, 0x00, 0x44, 0x00};
+static unsigned char courier18_120_bits[] = {
+0xe7, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0xe7};
+static unsigned char courier18_121_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0x1f, 0x00};
+static unsigned char courier18_122_bits[] = {
+0x7f, 0x41, 0x21, 0x10, 0x08, 0x44, 0x42, 0x7f};
+static unsigned char courier18_123_bits[] = {
+0x18, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x18};
+static unsigned char courier18_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01};
+static unsigned char courier18_125_bits[] = {
+0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x18, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x03};
+static unsigned char courier18_126_bits[] = {
+0x06, 0x99, 0x60};
+static unsigned char courier18_127_bits[] = {
+0x00};
+static unsigned char courier18_128_bits[] = {
+0x00};
+static unsigned char courier18_129_bits[] = {
+0x00};
+static unsigned char courier18_130_bits[] = {
+0x00};
+static unsigned char courier18_131_bits[] = {
+0x00};
+static unsigned char courier18_132_bits[] = {
+0x00};
+static unsigned char courier18_133_bits[] = {
+0x00};
+static unsigned char courier18_134_bits[] = {
+0x00};
+static unsigned char courier18_135_bits[] = {
+0x00};
+static unsigned char courier18_136_bits[] = {
+0x00};
+static unsigned char courier18_137_bits[] = {
+0x00};
+static unsigned char courier18_138_bits[] = {
+0x00};
+static unsigned char courier18_139_bits[] = {
+0x00};
+static unsigned char courier18_140_bits[] = {
+0x00};
+static unsigned char courier18_141_bits[] = {
+0x00};
+static unsigned char courier18_142_bits[] = {
+0x00};
+static unsigned char courier18_143_bits[] = {
+0x00};
+static unsigned char courier18_144_bits[] = {
+0x00};
+static unsigned char courier18_145_bits[] = {
+0x00};
+static unsigned char courier18_146_bits[] = {
+0x00};
+static unsigned char courier18_147_bits[] = {
+0x00};
+static unsigned char courier18_148_bits[] = {
+0x00};
+static unsigned char courier18_149_bits[] = {
+0x00};
+static unsigned char courier18_150_bits[] = {
+0x00};
+static unsigned char courier18_151_bits[] = {
+0x00};
+static unsigned char courier18_152_bits[] = {
+0x00};
+static unsigned char courier18_153_bits[] = {
+0x00};
+static unsigned char courier18_154_bits[] = {
+0x00};
+static unsigned char courier18_155_bits[] = {
+0x00};
+static unsigned char courier18_156_bits[] = {
+0x00};
+static unsigned char courier18_157_bits[] = {
+0x00};
+static unsigned char courier18_158_bits[] = {
+0x00};
+static unsigned char courier18_159_bits[] = {
+0x00};
+static unsigned char courier18_160_bits[] = {
+0x00};
+static unsigned char courier18_161_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char courier18_162_bits[] = {
+0x08, 0x08, 0x08, 0x3c, 0x22, 0x21, 0x01, 0x01, 0x22, 0x1c, 0x08, 0x08};
+static unsigned char courier18_163_bits[] = {
+0x38, 0x44, 0x04, 0x04, 0x08, 0x3f, 0x08, 0x04, 0x84, 0x82, 0x7e};
+static unsigned char courier18_164_bits[] = {
+0x21, 0x1e, 0x21, 0x21, 0x21, 0x1e, 0x21};
+static unsigned char courier18_165_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 
+0xfe, 0x00, 0x10, 0x00, 0xfe, 0x00, 0x10, 0x00, 0x7c, 0x00};
+static unsigned char courier18_166_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01};
+static unsigned char courier18_167_bits[] = {
+0x7c, 0x42, 0x42, 0x02, 0x0e, 0x31, 0x41, 0x46, 0x38, 0x20, 0x21, 0x21, 
+0x1f};
+static unsigned char courier18_168_bits[] = {
+0x1b};
+static unsigned char courier18_169_bits[] = {
+0x78, 0x00, 0x86, 0x01, 0x72, 0x01, 0x49, 0x02, 0x05, 0x02, 0x05, 0x02, 
+0x05, 0x02, 0x49, 0x02, 0x32, 0x01, 0x86, 0x01, 0x78, 0x00};
+static unsigned char courier18_170_bits[] = {
+0x0e, 0x10, 0x1e, 0x11, 0x19, 0x37, 0x00, 0x3f};
+static unsigned char courier18_171_bits[] = {
+0x10, 0x01, 0xcc, 0x00, 0x66, 0x00, 0x33, 0x00, 0x33, 0x00, 0x66, 0x00, 
+0xcc, 0x00, 0x10, 0x01};
+static unsigned char courier18_172_bits[] = {
+0xff, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01};
+static unsigned char courier18_173_bits[] = {
+0xff};
+static unsigned char courier18_174_bits[] = {
+0xf8, 0x00, 0x06, 0x03, 0x7a, 0x02, 0x89, 0x04, 0x89, 0x04, 0x79, 0x04, 
+0x29, 0x04, 0x49, 0x04, 0x8a, 0x03, 0x06, 0x01, 0xf8, 0x00};
+static unsigned char courier18_175_bits[] = {
+0x1f};
+static unsigned char courier18_176_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char courier18_177_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0xff, 0x01, 0x10, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x00, 0x00, 0xff, 0x01};
+static unsigned char courier18_178_bits[] = {
+0x0e, 0x11, 0x10, 0x08, 0x04, 0x02, 0x1f};
+static unsigned char courier18_179_bits[] = {
+0x0e, 0x11, 0x10, 0x0c, 0x10, 0x11, 0x0e};
+static unsigned char courier18_180_bits[] = {
+0x04, 0x02, 0x01};
+static unsigned char courier18_181_bits[] = {
+0xc3, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 
+0xc2, 0x00, 0xbe, 0x01, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00};
+static unsigned char courier18_182_bits[] = {
+0xfc, 0x52, 0x51, 0x51, 0x51, 0x52, 0x5c, 0x50, 0x50, 0x50, 0x50, 0x50, 
+0xdc};
+static unsigned char courier18_183_bits[] = {
+0x03, 0x03};
+static unsigned char courier18_184_bits[] = {
+0x02, 0x04, 0x03};
+static unsigned char courier18_185_bits[] = {
+0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier18_186_bits[] = {
+0x1e, 0x21, 0x21, 0x21, 0x21, 0x1e, 0x00, 0x3f};
+static unsigned char courier18_187_bits[] = {
+0x11, 0x00, 0x66, 0x00, 0xcc, 0x00, 0x98, 0x01, 0x98, 0x01, 0xcc, 0x00, 
+0x66, 0x00, 0x11, 0x00};
+static unsigned char courier18_188_bits[] = {
+0x04, 0x00, 0x07, 0x00, 0x04, 0x02, 0x04, 0x01, 0x84, 0x00, 0x84, 0x00, 
+0x5f, 0x02, 0x20, 0x03, 0x90, 0x02, 0x50, 0x02, 0xc8, 0x07, 0x04, 0x02, 
+0x00, 0x07};
+static unsigned char courier18_189_bits[] = {
+0x04, 0x00, 0x07, 0x00, 0x04, 0x02, 0x04, 0x01, 0x84, 0x00, 0x84, 0x00, 
+0x5f, 0x03, 0xa0, 0x04, 0x90, 0x04, 0x10, 0x02, 0x08, 0x01, 0x84, 0x00, 
+0xc0, 0x07};
+static unsigned char courier18_190_bits[] = {
+0x0e, 0x00, 0x11, 0x00, 0x10, 0x02, 0x0c, 0x01, 0x90, 0x00, 0x91, 0x00, 
+0x4e, 0x02, 0x20, 0x03, 0x90, 0x02, 0x50, 0x02, 0xc8, 0x07, 0x04, 0x02, 
+0x00, 0x07};
+static unsigned char courier18_191_bits[] = {
+0x18, 0x18, 0x00, 0x08, 0x08, 0x0e, 0x01, 0x01, 0x21, 0x21, 0x21, 0x1e};
+static unsigned char courier18_192_bits[] = {
+0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x20, 0x00, 
+0x50, 0x00, 0x50, 0x00, 0x88, 0x00, 0x88, 0x00, 0x04, 0x01, 0xfc, 0x01, 
+0x02, 0x02, 0x02, 0x02, 0x8f, 0x07};
+static unsigned char courier18_193_bits[] = {
+0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x20, 0x00, 
+0x50, 0x00, 0x50, 0x00, 0x88, 0x00, 0x88, 0x00, 0x04, 0x01, 0xfc, 0x01, 
+0x02, 0x02, 0x02, 0x02, 0x8f, 0x07};
+static unsigned char courier18_194_bits[] = {
+0x20, 0x00, 0x50, 0x00, 0x88, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x20, 0x00, 
+0x50, 0x00, 0x50, 0x00, 0x88, 0x00, 0x88, 0x00, 0x04, 0x01, 0xfc, 0x01, 
+0x02, 0x02, 0x02, 0x02, 0x8f, 0x07};
+static unsigned char courier18_195_bits[] = {
+0x98, 0x00, 0x64, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x20, 0x00, 0x50, 0x00, 
+0x50, 0x00, 0x88, 0x00, 0x88, 0x00, 0x04, 0x01, 0xfc, 0x01, 0x02, 0x02, 
+0x02, 0x02, 0x8f, 0x07};
+static unsigned char courier18_196_bits[] = {
+0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x20, 0x00, 0x50, 0x00, 
+0x50, 0x00, 0x88, 0x00, 0x88, 0x00, 0x04, 0x01, 0xfc, 0x01, 0x02, 0x02, 
+0x02, 0x02, 0x8f, 0x07};
+static unsigned char courier18_197_bits[] = {
+0x30, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, 0x00, 0x3e, 0x00, 0x20, 0x00, 
+0x50, 0x00, 0x50, 0x00, 0x88, 0x00, 0x88, 0x00, 0x04, 0x01, 0xfc, 0x01, 
+0x02, 0x02, 0x02, 0x02, 0x8f, 0x07};
+static unsigned char courier18_198_bits[] = {
+0xf8, 0x07, 0x60, 0x04, 0x50, 0x04, 0x50, 0x00, 0x48, 0x02, 0xc8, 0x03, 
+0x7c, 0x02, 0x44, 0x00, 0x42, 0x04, 0x42, 0x04, 0xe7, 0x07};
+static unsigned char courier18_199_bits[] = {
+0x78, 0x01, 0x86, 0x01, 0x02, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x02, 0x01, 0x86, 0x00, 0x78, 0x00, 0x10, 0x00, 
+0x20, 0x00, 0x18, 0x00};
+static unsigned char courier18_200_bits[] = {
+0x04, 0x08, 0x10, 0x00, 0xff, 0x82, 0x82, 0x82, 0x12, 0x1e, 0x12, 0x82, 
+0x82, 0x82, 0xff};
+static unsigned char courier18_201_bits[] = {
+0x20, 0x10, 0x08, 0x00, 0xff, 0x82, 0x82, 0x82, 0x12, 0x1e, 0x12, 0x82, 
+0x82, 0x82, 0xff};
+static unsigned char courier18_202_bits[] = {
+0x18, 0x24, 0x42, 0x00, 0xff, 0x82, 0x82, 0x82, 0x12, 0x1e, 0x12, 0x82, 
+0x82, 0x82, 0xff};
+static unsigned char courier18_203_bits[] = {
+0x66, 0x00, 0x00, 0xff, 0x82, 0x82, 0x82, 0x12, 0x1e, 0x12, 0x82, 0x82, 
+0x82, 0xff};
+static unsigned char courier18_204_bits[] = {
+0x04, 0x08, 0x10, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0x7f};
+static unsigned char courier18_205_bits[] = {
+0x10, 0x08, 0x04, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0x7f};
+static unsigned char courier18_206_bits[] = {
+0x08, 0x14, 0x22, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0x7f};
+static unsigned char courier18_207_bits[] = {
+0x36, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x7f};
+static unsigned char courier18_208_bits[] = {
+0x3f, 0x42, 0x82, 0x82, 0x82, 0x8f, 0x82, 0x82, 0x82, 0x42, 0x3f};
+static unsigned char courier18_209_bits[] = {
+0x98, 0x00, 0x64, 0x00, 0x00, 0x00, 0xe7, 0x01, 0x86, 0x00, 0x8a, 0x00, 
+0x8a, 0x00, 0x92, 0x00, 0x92, 0x00, 0xa2, 0x00, 0xa2, 0x00, 0xc2, 0x00, 
+0xc2, 0x00, 0x8f, 0x00};
+static unsigned char courier18_210_bits[] = {
+0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 
+0x82, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x82, 0x00, 0xc6, 0x00, 0x38, 0x00};
+static unsigned char courier18_211_bits[] = {
+0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 
+0x82, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x82, 0x00, 0xc6, 0x00, 0x38, 0x00};
+static unsigned char courier18_212_bits[] = {
+0x10, 0x00, 0x28, 0x00, 0x44, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 
+0x82, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x82, 0x00, 0xc6, 0x00, 0x38, 0x00};
+static unsigned char courier18_213_bits[] = {
+0x98, 0x00, 0x64, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 
+0xc6, 0x00, 0x38, 0x00};
+static unsigned char courier18_214_bits[] = {
+0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 
+0xc6, 0x00, 0x38, 0x00};
+static unsigned char courier18_215_bits[] = {
+0x01, 0x01, 0x82, 0x00, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x44, 0x00, 0x82, 0x00, 0x01, 0x01};
+static unsigned char courier18_216_bits[] = {
+0x70, 0x04, 0x8c, 0x02, 0x04, 0x01, 0x82, 0x02, 0x42, 0x02, 0x22, 0x02, 
+0x12, 0x02, 0x0a, 0x02, 0x04, 0x01, 0x8a, 0x01, 0x71, 0x00};
+static unsigned char courier18_217_bits[] = {
+0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0xcf, 0x03, 0x02, 0x01, 
+0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 
+0x02, 0x01, 0x84, 0x00, 0x78, 0x00};
+static unsigned char courier18_218_bits[] = {
+0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0x03, 0x02, 0x01, 
+0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 
+0x02, 0x01, 0x84, 0x00, 0x78, 0x00};
+static unsigned char courier18_219_bits[] = {
+0x30, 0x00, 0x48, 0x00, 0x84, 0x00, 0x00, 0x00, 0xcf, 0x03, 0x02, 0x01, 
+0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 
+0x02, 0x01, 0x84, 0x00, 0x78, 0x00};
+static unsigned char courier18_220_bits[] = {
+0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x03, 0x02, 0x01, 0x02, 0x01, 
+0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 
+0x84, 0x00, 0x78, 0x00};
+static unsigned char courier18_221_bits[] = {
+0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0xc7, 0x01, 0x82, 0x00, 
+0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x7c, 0x00};
+static unsigned char courier18_222_bits[] = {
+0x07, 0x00, 0x02, 0x00, 0x7e, 0x00, 0x82, 0x00, 0x02, 0x01, 0x02, 0x01, 
+0x82, 0x00, 0x7e, 0x00, 0x02, 0x00, 0x02, 0x00, 0x07, 0x00};
+static unsigned char courier18_223_bits[] = {
+0x38, 0x44, 0x42, 0x42, 0x22, 0x32, 0x42, 0x82, 0x82, 0x82, 0x92, 0x67};
+static unsigned char courier18_224_bits[] = {
+0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x42, 0x00, 
+0x40, 0x00, 0x7e, 0x00, 0x41, 0x00, 0x41, 0x00, 0x61, 0x00, 0xde, 0x01};
+static unsigned char courier18_225_bits[] = {
+0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x42, 0x00, 
+0x40, 0x00, 0x7e, 0x00, 0x41, 0x00, 0x41, 0x00, 0x61, 0x00, 0xde, 0x01};
+static unsigned char courier18_226_bits[] = {
+0x18, 0x00, 0x24, 0x00, 0x42, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x42, 0x00, 
+0x40, 0x00, 0x7e, 0x00, 0x41, 0x00, 0x41, 0x00, 0x61, 0x00, 0xde, 0x01};
+static unsigned char courier18_227_bits[] = {
+0x4c, 0x00, 0x32, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x42, 0x00, 0x40, 0x00, 
+0x7e, 0x00, 0x41, 0x00, 0x41, 0x00, 0x61, 0x00, 0xde, 0x01};
+static unsigned char courier18_228_bits[] = {
+0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x42, 0x00, 0x40, 0x00, 
+0x7e, 0x00, 0x41, 0x00, 0x41, 0x00, 0x61, 0x00, 0xde, 0x01};
+static unsigned char courier18_229_bits[] = {
+0x18, 0x00, 0x24, 0x00, 0x24, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3c, 0x00, 
+0x42, 0x00, 0x40, 0x00, 0x7e, 0x00, 0x41, 0x00, 0x41, 0x00, 0x61, 0x00, 
+0xde, 0x01};
+static unsigned char courier18_230_bits[] = {
+0x8e, 0x01, 0x51, 0x02, 0x20, 0x04, 0xfe, 0x07, 0x21, 0x00, 0x21, 0x00, 
+0x51, 0x04, 0x8e, 0x03};
+static unsigned char courier18_231_bits[] = {
+0xbc, 0xc2, 0x81, 0x01, 0x01, 0x01, 0xc2, 0x3c, 0x08, 0x10, 0x0c};
+static unsigned char courier18_232_bits[] = {
+0x04, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x81, 0xff, 0x01, 0x01, 0xc2, 0x3c};
+static unsigned char courier18_233_bits[] = {
+0x20, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x81, 0xff, 0x01, 0x01, 0xc2, 0x3c};
+static unsigned char courier18_234_bits[] = {
+0x18, 0x24, 0x42, 0x00, 0x3c, 0x42, 0x81, 0xff, 0x01, 0x01, 0xc2, 0x3c};
+static unsigned char courier18_235_bits[] = {
+0x66, 0x00, 0x00, 0x3c, 0x42, 0x81, 0xff, 0x01, 0x01, 0xc2, 0x3c};
+static unsigned char courier18_236_bits[] = {
+0x02, 0x04, 0x08, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f};
+static unsigned char courier18_237_bits[] = {
+0x10, 0x08, 0x04, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f};
+static unsigned char courier18_238_bits[] = {
+0x08, 0x14, 0x22, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f};
+static unsigned char courier18_239_bits[] = {
+0x36, 0x00, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f};
+static unsigned char courier18_240_bits[] = {
+0xce, 0x31, 0x2c, 0x42, 0x40, 0xbc, 0xc2, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier18_241_bits[] = {
+0x98, 0x00, 0x64, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x86, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char courier18_242_bits[] = {
+0x04, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier18_243_bits[] = {
+0x40, 0x20, 0x10, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier18_244_bits[] = {
+0x18, 0x24, 0x42, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier18_245_bits[] = {
+0x4c, 0x32, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier18_246_bits[] = {
+0x66, 0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier18_247_bits[] = {
+0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x18, 0x18};
+static unsigned char courier18_248_bits[] = {
+0xbc, 0x42, 0xa1, 0x91, 0x89, 0x85, 0x42, 0x3d};
+static unsigned char courier18_249_bits[] = {
+0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc2, 0x00, 0xbc, 0x01};
+static unsigned char courier18_250_bits[] = {
+0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc2, 0x00, 0xbc, 0x01};
+static unsigned char courier18_251_bits[] = {
+0x10, 0x00, 0x28, 0x00, 0x44, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc2, 0x00, 0xbc, 0x01};
+static unsigned char courier18_252_bits[] = {
+0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x82, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc2, 0x00, 0xbc, 0x01};
+static unsigned char courier18_253_bits[] = {
+0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0xc7, 0x01, 0x82, 0x00, 
+0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0x1f, 0x00};
+static unsigned char courier18_254_bits[] = {
+0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7a, 0x00, 0x86, 0x00, 
+0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x86, 0x00, 0x7a, 0x00, 
+0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x0f, 0x00};
+static unsigned char courier18_255_bits[] = {
+0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x01, 0x82, 0x00, 0x82, 0x00, 
+0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x08, 0x00, 0x08, 0x00, 0x1f, 0x00};
+static RotFont courier18font[] = {
+{5, 1, 1, courier18_0_bits},
+{5, 1, 1, courier18_1_bits},
+{5, 1, 1, courier18_2_bits},
+{5, 1, 1, courier18_3_bits},
+{5, 1, 1, courier18_4_bits},
+{5, 1, 1, courier18_5_bits},
+{5, 1, 1, courier18_6_bits},
+{5, 1, 1, courier18_7_bits},
+{5, 1, 1, courier18_8_bits},
+{5, 1, 1, courier18_9_bits},
+{5, 1, 1, courier18_10_bits},
+{5, 1, 1, courier18_11_bits},
+{5, 1, 1, courier18_12_bits},
+{5, 1, 1, courier18_13_bits},
+{5, 1, 1, courier18_14_bits},
+{5, 1, 1, courier18_15_bits},
+{5, 1, 1, courier18_16_bits},
+{5, 1, 1, courier18_17_bits},
+{5, 1, 1, courier18_18_bits},
+{5, 1, 1, courier18_19_bits},
+{5, 1, 1, courier18_20_bits},
+{5, 1, 1, courier18_21_bits},
+{5, 1, 1, courier18_22_bits},
+{5, 1, 1, courier18_23_bits},
+{5, 1, 1, courier18_24_bits},
+{5, 1, 1, courier18_25_bits},
+{5, 1, 1, courier18_26_bits},
+{5, 1, 1, courier18_27_bits},
+{5, 1, 1, courier18_28_bits},
+{5, 1, 1, courier18_29_bits},
+{5, 1, 1, courier18_30_bits},
+{5, 1, 1, courier18_31_bits},
+{7, 1, 1, courier18_32_bits},
+{2, 12, 12, courier18_33_bits},
+{5, 5, 12, courier18_34_bits},
+{9, 15, 13, courier18_35_bits},
+{7, 15, 13, courier18_36_bits},
+{9, 12, 12, courier18_37_bits},
+{7, 10, 10, courier18_38_bits},
+{4, 5, 12, courier18_39_bits},
+{3, 14, 12, courier18_40_bits},
+{3, 14, 12, courier18_41_bits},
+{7, 8, 12, courier18_42_bits},
+{9, 9, 10, courier18_43_bits},
+{4, 5, 2, courier18_44_bits},
+{9, 1, 6, courier18_45_bits},
+{2, 2, 2, courier18_46_bits},
+{8, 16, 13, courier18_47_bits},
+{7, 12, 12, courier18_48_bits},
+{7, 12, 12, courier18_49_bits},
+{8, 12, 12, courier18_50_bits},
+{7, 12, 12, courier18_51_bits},
+{7, 12, 12, courier18_52_bits},
+{8, 12, 12, courier18_53_bits},
+{7, 12, 12, courier18_54_bits},
+{8, 12, 12, courier18_55_bits},
+{7, 12, 12, courier18_56_bits},
+{7, 12, 12, courier18_57_bits},
+{2, 8, 8, courier18_58_bits},
+{5, 11, 8, courier18_59_bits},
+{10, 9, 10, courier18_60_bits},
+{9, 4, 7, courier18_61_bits},
+{10, 9, 10, courier18_62_bits},
+{7, 11, 11, courier18_63_bits},
+{8, 13, 12, courier18_64_bits},
+{11, 11, 11, courier18_65_bits},
+{9, 11, 11, courier18_66_bits},
+{9, 11, 11, courier18_67_bits},
+{8, 11, 11, courier18_68_bits},
+{8, 11, 11, courier18_69_bits},
+{8, 11, 11, courier18_70_bits},
+{10, 11, 11, courier18_71_bits},
+{9, 11, 11, courier18_72_bits},
+{7, 11, 11, courier18_73_bits},
+{9, 11, 11, courier18_74_bits},
+{10, 11, 11, courier18_75_bits},
+{9, 11, 11, courier18_76_bits},
+{11, 11, 11, courier18_77_bits},
+{9, 11, 11, courier18_78_bits},
+{9, 11, 11, courier18_79_bits},
+{9, 11, 11, courier18_80_bits},
+{9, 13, 11, courier18_81_bits},
+{10, 11, 11, courier18_82_bits},
+{8, 11, 11, courier18_83_bits},
+{9, 11, 11, courier18_84_bits},
+{10, 11, 11, courier18_85_bits},
+{11, 11, 11, courier18_86_bits},
+{11, 11, 11, courier18_87_bits},
+{9, 11, 11, courier18_88_bits},
+{9, 11, 11, courier18_89_bits},
+{7, 11, 11, courier18_90_bits},
+{3, 15, 12, courier18_91_bits},
+{8, 16, 13, courier18_92_bits},
+{3, 15, 12, courier18_93_bits},
+{7, 4, 12, courier18_94_bits},
+{11, 1, -3, courier18_95_bits},
+{4, 5, 12, courier18_96_bits},
+{9, 8, 8, courier18_97_bits},
+{9, 12, 12, courier18_98_bits},
+{8, 8, 8, courier18_99_bits},
+{9, 12, 12, courier18_100_bits},
+{8, 8, 8, courier18_101_bits},
+{8, 12, 12, courier18_102_bits},
+{9, 12, 8, courier18_103_bits},
+{9, 12, 12, courier18_104_bits},
+{7, 11, 11, courier18_105_bits},
+{6, 15, 11, courier18_106_bits},
+{9, 12, 12, courier18_107_bits},
+{7, 12, 12, courier18_108_bits},
+{11, 8, 8, courier18_109_bits},
+{9, 8, 8, courier18_110_bits},
+{8, 8, 8, courier18_111_bits},
+{9, 12, 8, courier18_112_bits},
+{9, 12, 8, courier18_113_bits},
+{8, 8, 8, courier18_114_bits},
+{7, 8, 8, courier18_115_bits},
+{8, 11, 11, courier18_116_bits},
+{9, 8, 8, courier18_117_bits},
+{9, 8, 8, courier18_118_bits},
+{9, 8, 8, courier18_119_bits},
+{8, 8, 8, courier18_120_bits},
+{9, 12, 8, courier18_121_bits},
+{7, 8, 8, courier18_122_bits},
+{5, 15, 12, courier18_123_bits},
+{1, 15, 12, courier18_124_bits},
+{5, 15, 12, courier18_125_bits},
+{8, 3, 7, courier18_126_bits},
+{5, 1, 1, courier18_127_bits},
+{5, 1, 1, courier18_128_bits},
+{5, 1, 1, courier18_129_bits},
+{5, 1, 1, courier18_130_bits},
+{5, 1, 1, courier18_131_bits},
+{5, 1, 1, courier18_132_bits},
+{5, 1, 1, courier18_133_bits},
+{5, 1, 1, courier18_134_bits},
+{5, 1, 1, courier18_135_bits},
+{5, 1, 1, courier18_136_bits},
+{5, 1, 1, courier18_137_bits},
+{5, 1, 1, courier18_138_bits},
+{5, 1, 1, courier18_139_bits},
+{5, 1, 1, courier18_140_bits},
+{5, 1, 1, courier18_141_bits},
+{5, 1, 1, courier18_142_bits},
+{5, 1, 1, courier18_143_bits},
+{5, 1, 1, courier18_144_bits},
+{5, 1, 1, courier18_145_bits},
+{5, 1, 1, courier18_146_bits},
+{5, 1, 1, courier18_147_bits},
+{5, 1, 1, courier18_148_bits},
+{5, 1, 1, courier18_149_bits},
+{5, 1, 1, courier18_150_bits},
+{5, 1, 1, courier18_151_bits},
+{5, 1, 1, courier18_152_bits},
+{5, 1, 1, courier18_153_bits},
+{5, 1, 1, courier18_154_bits},
+{5, 1, 1, courier18_155_bits},
+{5, 1, 1, courier18_156_bits},
+{5, 1, 1, courier18_157_bits},
+{5, 1, 1, courier18_158_bits},
+{5, 1, 1, courier18_159_bits},
+{1, 1, 1, courier18_160_bits},
+{2, 13, 9, courier18_161_bits},
+{6, 12, 12, courier18_162_bits},
+{8, 11, 11, courier18_163_bits},
+{6, 7, 9, courier18_164_bits},
+{9, 11, 11, courier18_165_bits},
+{1, 15, 12, courier18_166_bits},
+{7, 13, 12, courier18_167_bits},
+{5, 1, 11, courier18_168_bits},
+{10, 11, 11, courier18_169_bits},
+{6, 8, 11, courier18_170_bits},
+{9, 8, 8, courier18_171_bits},
+{9, 4, 7, courier18_172_bits},
+{8, 1, 6, courier18_173_bits},
+{11, 11, 11, courier18_174_bits},
+{5, 1, 10, courier18_175_bits},
+{5, 5, 12, courier18_176_bits},
+{9, 9, 10, courier18_177_bits},
+{5, 7, 12, courier18_178_bits},
+{5, 7, 12, courier18_179_bits},
+{3, 3, 12, courier18_180_bits},
+{9, 12, 8, courier18_181_bits},
+{8, 13, 12, courier18_182_bits},
+{2, 2, 7, courier18_183_bits},
+{3, 3, 0, courier18_184_bits},
+{5, 7, 12, courier18_185_bits},
+{6, 8, 11, courier18_186_bits},
+{9, 8, 8, courier18_187_bits},
+{11, 13, 13, courier18_188_bits},
+{11, 13, 13, courier18_189_bits},
+{11, 13, 13, courier18_190_bits},
+{6, 12, 9, courier18_191_bits},
+{11, 15, 15, courier18_192_bits},
+{11, 15, 15, courier18_193_bits},
+{11, 15, 15, courier18_194_bits},
+{11, 14, 14, courier18_195_bits},
+{11, 14, 14, courier18_196_bits},
+{11, 15, 15, courier18_197_bits},
+{11, 11, 11, courier18_198_bits},
+{9, 14, 11, courier18_199_bits},
+{8, 15, 15, courier18_200_bits},
+{8, 15, 15, courier18_201_bits},
+{8, 15, 15, courier18_202_bits},
+{8, 14, 14, courier18_203_bits},
+{7, 15, 15, courier18_204_bits},
+{7, 15, 15, courier18_205_bits},
+{7, 15, 15, courier18_206_bits},
+{7, 14, 14, courier18_207_bits},
+{8, 11, 11, courier18_208_bits},
+{9, 14, 14, courier18_209_bits},
+{9, 15, 15, courier18_210_bits},
+{9, 15, 15, courier18_211_bits},
+{9, 15, 15, courier18_212_bits},
+{9, 14, 14, courier18_213_bits},
+{9, 14, 14, courier18_214_bits},
+{9, 9, 10, courier18_215_bits},
+{11, 11, 11, courier18_216_bits},
+{10, 15, 15, courier18_217_bits},
+{10, 15, 15, courier18_218_bits},
+{10, 15, 15, courier18_219_bits},
+{10, 14, 14, courier18_220_bits},
+{9, 15, 15, courier18_221_bits},
+{9, 11, 11, courier18_222_bits},
+{8, 12, 12, courier18_223_bits},
+{9, 12, 12, courier18_224_bits},
+{9, 12, 12, courier18_225_bits},
+{9, 12, 12, courier18_226_bits},
+{9, 11, 11, courier18_227_bits},
+{9, 11, 11, courier18_228_bits},
+{9, 13, 13, courier18_229_bits},
+{11, 8, 8, courier18_230_bits},
+{8, 11, 8, courier18_231_bits},
+{8, 12, 12, courier18_232_bits},
+{8, 12, 12, courier18_233_bits},
+{8, 12, 12, courier18_234_bits},
+{8, 11, 11, courier18_235_bits},
+{7, 12, 12, courier18_236_bits},
+{7, 12, 12, courier18_237_bits},
+{7, 12, 12, courier18_238_bits},
+{7, 11, 11, courier18_239_bits},
+{8, 12, 12, courier18_240_bits},
+{9, 11, 11, courier18_241_bits},
+{8, 12, 12, courier18_242_bits},
+{8, 12, 12, courier18_243_bits},
+{8, 12, 12, courier18_244_bits},
+{8, 11, 11, courier18_245_bits},
+{8, 11, 11, courier18_246_bits},
+{8, 9, 10, courier18_247_bits},
+{8, 8, 8, courier18_248_bits},
+{9, 12, 12, courier18_249_bits},
+{9, 12, 12, courier18_250_bits},
+{9, 12, 12, courier18_251_bits},
+{9, 11, 11, courier18_252_bits},
+{9, 16, 12, courier18_253_bits},
+{9, 16, 12, courier18_254_bits},
+{9, 15, 11, courier18_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/courier24.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/courier24.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/courier24.bdf	(revision 12606)
@@ -0,0 +1,4150 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) IBM Corporation 1990,1991. IBM Courier is a Trademark of the IBM Corporation.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -adobe-courier-medium-r-normal--24-231-75-75-m-140-iso8859-1
+SIZE 23 75 75
+FONTBOUNDINGBOX 17 24 -1 -5
+STARTPROPERTIES 25
+FOUNDRY "adobe"
+FAMILY_NAME "courier"
+WEIGHT_NAME "medium"
+SLANT "r"
+SETWIDTH_NAME "normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 24
+POINT_SIZE 231
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "m"
+AVERAGE_WIDTH 140
+CHARSET_REGISTRY "iso8859"
+CHARSET_ENCODING "1"
+FONT "-adobe-courier-medium-r-normal--24-231-75-75-m-140-iso8859-1"
+COPYRIGHT "Copyright (c) IBM Corporation 1990,1991. IBM Courier is a Trademark of the IBM Corporation."
+RAW_PIXEL_SIZE 1000
+RAW_POINT_SIZE 964
+RAW_ASCENT 841
+RAW_DESCENT 288
+RAW_AVERAGE_WIDTH 6000
+FACE_NAME "Couriere."
+DEFAULT_CHAR 0
+FONT_ASCENT 20
+FONT_DESCENT 7
+ENDPROPERTIES
+CHARS 190
+STARTCHAR space
+ENCODING 32
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 0 0 0 0
+ATTRIBUTES 0x0258
+BITMAP
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 3 14 6 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+00
+00
+e0
+e0
+e0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 6 7 4 7
+ATTRIBUTES 0x0258
+BITMAP
+cc
+cc
+cc
+cc
+cc
+cc
+cc
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 17 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+1180
+1100
+1100
+1100
+1100
+1100
+ffe0
+2100
+2100
+2100
+2100
+ffe0
+2100
+2100
+2100
+2100
+2100
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 19 2 -3
+ATTRIBUTES 0x0258
+BITMAP
+0400
+0400
+0400
+1f80
+2580
+4480
+4480
+64c0
+3c00
+0f00
+0580
+c440
+4440
+6440
+7480
+7f00
+0400
+0400
+0400
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+3800
+4400
+8200
+8200
+8200
+4460
+39e0
+0f80
+7c00
+71c0
+0220
+0410
+0410
+0630
+01e0
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 13 3 0
+ATTRIBUTES 0x0258
+BITMAP
+3d00
+6200
+4000
+4000
+2000
+3000
+51c0
+c900
+8d00
+8600
+8600
+c700
+79c0
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 6 4 8
+ATTRIBUTES 0x0258
+BITMAP
+30
+70
+60
+60
+c0
+c0
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 18 7 -2
+ATTRIBUTES 0x0258
+BITMAP
+10
+20
+20
+40
+40
+40
+80
+80
+80
+80
+80
+80
+c0
+40
+40
+20
+20
+10
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 18 3 -2
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+60
+20
+20
+10
+10
+10
+10
+10
+10
+10
+10
+20
+20
+60
+40
+c0
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 9 3 5
+ATTRIBUTES 0x0258
+BITMAP
+0800
+0800
+8880
+ff80
+3e00
+1c00
+3600
+6300
+2200
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 11 2 2
+ATTRIBUTES 0x0258
+BITMAP
+0400
+0400
+0400
+0400
+0400
+ffe0
+0400
+0400
+0400
+0400
+0400
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 6 4 -3
+ATTRIBUTES 0x0258
+BITMAP
+30
+60
+60
+60
+c0
+c0
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 1 2 7
+ATTRIBUTES 0x0258
+BITMAP
+ffe0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 3 5 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+f0
+70
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 20 2 -3
+ATTRIBUTES 0x0258
+BITMAP
+0040
+0080
+0080
+0180
+0100
+0300
+0200
+0200
+0400
+0400
+0800
+0800
+1000
+1000
+3000
+2000
+6000
+4000
+c000
+8000
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 15 3 0
+ATTRIBUTES 0x0258
+BITMAP
+3c00
+6200
+4100
+8100
+8080
+8080
+8080
+8080
+8080
+8080
+8080
+8100
+4100
+6200
+3c00
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0c00
+3c00
+6400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+7fc0
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+1e00
+2300
+4180
+4080
+0080
+0080
+0180
+0100
+0200
+0400
+0800
+1080
+6080
+8080
+ff80
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+3c00
+6200
+4100
+0100
+0100
+0100
+0600
+0f00
+0100
+0080
+0080
+0080
+0080
+8300
+7e00
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0600
+0a00
+0a00
+1200
+1200
+2200
+4200
+4200
+8200
+ffc0
+0200
+0200
+0200
+1fc0
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+7f80
+4000
+4000
+4000
+4000
+4000
+5e00
+6180
+00c0
+0040
+0040
+0040
+0080
+c180
+7e00
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 15 3 0
+ATTRIBUTES 0x0258
+BITMAP
+0f80
+3800
+6000
+4000
+c000
+8000
+bc00
+e200
+c300
+8100
+8100
+8100
+4100
+6200
+3c00
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+ffc0
+8040
+8080
+8080
+0080
+0100
+0100
+0300
+0200
+0200
+0600
+0400
+0c00
+0c00
+0800
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 15 3 0
+ATTRIBUTES 0x0258
+BITMAP
+3c00
+6200
+c100
+8100
+8100
+8100
+6200
+3c00
+4300
+c100
+8080
+8080
+8080
+4300
+3e00
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+3c00
+6200
+4100
+8080
+8080
+8080
+c180
+6380
+3c80
+0080
+0100
+0100
+0200
+0400
+f800
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 9 5 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+f0
+70
+00
+00
+00
+60
+f0
+70
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 5 12 4 -3
+ATTRIBUTES 0x0258
+BITMAP
+30
+78
+38
+00
+00
+00
+30
+70
+60
+60
+40
+c0
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 11 1 2
+ATTRIBUTES 0x0258
+BITMAP
+0010
+0070
+0180
+0600
+3800
+e000
+3800
+0f00
+03e0
+0070
+0010
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 5 2 5
+ATTRIBUTES 0x0258
+BITMAP
+ffe0
+0000
+0000
+0000
+ffe0
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 11 1 2
+ATTRIBUTES 0x0258
+BITMAP
+8000
+e000
+3800
+0600
+01c0
+0070
+03c0
+1f00
+fc00
+f000
+c000
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 8 14 3 0
+ATTRIBUTES 0x0258
+BITMAP
+7c
+c2
+81
+81
+01
+01
+02
+1c
+10
+10
+00
+38
+38
+38
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 13 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0f80
+3060
+6010
+4698
+8d88
+8988
+9188
+9118
+9310
+dee0
+4400
+3070
+1fc0
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 14 0 0
+ATTRIBUTES 0x0258
+BITMAP
+3f00
+0300
+0780
+0680
+04c0
+0cc0
+0840
+1860
+1820
+1fe0
+3030
+2010
+6018
+f87c
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+ff80
+20c0
+2020
+2020
+2020
+2060
+3f80
+2060
+2030
+2010
+2010
+2010
+2060
+ffc0
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0f20
+30e0
+6060
+4060
+8020
+8000
+8000
+8000
+8000
+8000
+4000
+4030
+3060
+1f80
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+ff00
+20c0
+2060
+2020
+2010
+2010
+2010
+2010
+2010
+2010
+2030
+2020
+20c0
+ff80
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+fff0
+1010
+1010
+1010
+1010
+1080
+1f80
+1080
+1080
+1000
+1010
+1010
+1010
+fff0
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 14 2 0
+ATTRIBUTES 0x0258
+BITMAP
+ffe0
+2020
+2020
+2020
+2020
+2100
+3f00
+2100
+2100
+2000
+2000
+2000
+2000
+fc00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0fa0
+30e0
+2060
+4020
+c020
+8000
+8000
+8000
+81f8
+8010
+4010
+6010
+3030
+0fc0
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8f0
+2020
+2020
+2020
+2020
+2020
+2020
+3fe0
+2020
+2020
+2020
+2020
+2020
+f8f0
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 14 2 0
+ATTRIBUTES 0x0258
+BITMAP
+ffc0
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0ff8
+0040
+0040
+0040
+0040
+0040
+0040
+0040
+4040
+4040
+4040
+4040
+6080
+1f80
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+fcf8
+1020
+1040
+1080
+1100
+1200
+1400
+1e00
+1180
+1080
+1040
+1060
+1020
+fc38
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+fe00
+1000
+1000
+1000
+1000
+1000
+1000
+1000
+1010
+1010
+1010
+1010
+1010
+fff0
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 14 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f03c
+2828
+2828
+2848
+2448
+2448
+2488
+2288
+2288
+2308
+2008
+2008
+2008
+f87c
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0f8
+3810
+2810
+2810
+2410
+2410
+2210
+2210
+2110
+2110
+2090
+2090
+2050
+f870
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0f80
+30c0
+6060
+4020
+c010
+8010
+8010
+8010
+8010
+8010
+4020
+6020
+30c0
+0f80
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 14 2 0
+ATTRIBUTES 0x0258
+BITMAP
+ff00
+21c0
+2040
+2020
+2020
+2020
+2060
+21c0
+3f80
+2000
+2000
+2000
+2000
+fc00
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 17 1 -3
+ATTRIBUTES 0x0258
+BITMAP
+0f00
+30c0
+6060
+4020
+c010
+8010
+8010
+8010
+8010
+8010
+4020
+6020
+30c0
+1f80
+0c00
+1f10
+10e0
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+ff80
+20c0
+2060
+2020
+2020
+2020
+20c0
+3f80
+2300
+2100
+2080
+2040
+2040
+f838
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 14 3 0
+ATTRIBUTES 0x0258
+BITMAP
+3c80
+4380
+8180
+8080
+8080
+8000
+6000
+3f00
+0180
+0080
+8080
+8080
+c100
+be00
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+7ff0
+4210
+4210
+4210
+4210
+c218
+0200
+0200
+0200
+0200
+0200
+0200
+0200
+1fc0
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f9f8
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+6020
+6020
+3040
+1f80
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 14 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f87c
+2010
+2010
+1010
+1020
+1020
+0820
+0840
+0c40
+04c0
+0480
+0280
+0380
+0300
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 15 14 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f83e
+6004
+6004
+6108
+2308
+2388
+2288
+2488
+24c8
+3458
+3850
+3830
+1830
+1030
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8f0
+2040
+3040
+1880
+0900
+0500
+0600
+0600
+0d00
+0880
+10c0
+3060
+2020
+f8f8
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8f8
+2020
+3060
+1040
+0880
+0c80
+0500
+0700
+0200
+0200
+0200
+0200
+0200
+1fc0
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 14 2 0
+ATTRIBUTES 0x0258
+BITMAP
+ff80
+8080
+8100
+8100
+8200
+0400
+0c00
+0800
+1000
+3040
+2040
+4040
+c040
+ffc0
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 18 8 -2
+ATTRIBUTES 0x0258
+BITMAP
+f0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+f0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 20 2 -3
+ATTRIBUTES 0x0258
+BITMAP
+8000
+c000
+4000
+6000
+2000
+3000
+1000
+1000
+0800
+0800
+0400
+0400
+0200
+0200
+0300
+0100
+0180
+0080
+00c0
+0040
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 18 3 -2
+ATTRIBUTES 0x0258
+BITMAP
+f0
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+f0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 11 2 3
+ATTRIBUTES 0x0258
+BITMAP
+0e00
+0a00
+1a00
+1900
+1100
+3180
+2080
+60c0
+60c0
+c040
+c060
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 17 1 -1 -3
+ATTRIBUTES 0x0258
+BITMAP
+ffff80
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 6 4 8
+ATTRIBUTES 0x0258
+BITMAP
+30
+30
+60
+60
+e0
+c0
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 10 2 0
+ATTRIBUTES 0x0258
+BITMAP
+3f00
+0180
+0080
+3f80
+4180
+8080
+8080
+8180
+c380
+7ce0
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 15 0 0
+ATTRIBUTES 0x0258
+BITMAP
+e000
+2000
+2000
+2000
+2000
+27c0
+2c30
+3010
+3008
+3008
+3008
+3008
+3810
+3c30
+e7c0
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 10 2 0
+ATTRIBUTES 0x0258
+BITMAP
+1fe0
+60c0
+4040
+8000
+8000
+8000
+8000
+4020
+60c0
+1f00
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+00e0
+0020
+0020
+0020
+0020
+1f20
+20e0
+4060
+8060
+8020
+8020
+8060
+4060
+31a0
+1f38
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 10 2 0
+ATTRIBUTES 0x0258
+BITMAP
+1f00
+60c0
+c060
+8020
+ffe0
+8000
+8000
+4000
+6060
+1f80
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0fc0
+1840
+1000
+1000
+1000
+ff80
+1000
+1000
+1000
+1000
+1000
+1000
+1000
+1000
+ff80
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 -4
+ATTRIBUTES 0x0258
+BITMAP
+1f70
+61c0
+40c0
+8040
+8040
+8040
+c040
+40c0
+31c0
+1e40
+0040
+0040
+0080
+1f00
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e000
+2000
+2000
+2000
+2000
+2f80
+3860
+2020
+2020
+2020
+2020
+2020
+2020
+2020
+f8f8
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 16 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0c00
+0c00
+0c00
+0000
+0000
+0000
+7c00
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 8 20 2 -4
+ATTRIBUTES 0x0258
+BITMAP
+03
+03
+03
+00
+00
+00
+fe
+02
+02
+02
+02
+02
+02
+02
+02
+02
+02
+02
+84
+f8
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e000
+2000
+2000
+2000
+2000
+21f0
+2180
+2300
+2c00
+3c00
+2200
+2180
+20c0
+2060
+e0f8
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+7c00
+4400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 15 10 0 0
+ATTRIBUTES 0x0258
+BITMAP
+eef0
+3188
+2108
+2108
+2108
+2108
+2108
+2108
+2108
+f9ce
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 10 1 0
+ATTRIBUTES 0x0258
+BITMAP
+ef80
+3040
+2020
+2020
+2020
+2020
+2020
+2020
+2020
+f9f8
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 10 1 0
+ATTRIBUTES 0x0258
+BITMAP
+1f80
+6060
+4020
+8010
+8010
+8010
+8010
+4020
+3060
+1f80
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 0 -4
+ATTRIBUTES 0x0258
+BITMAP
+f7c0
+1c30
+1810
+1008
+1008
+1008
+1008
+1810
+1c20
+17c0
+1000
+1000
+1000
+fe00
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 -4
+ATTRIBUTES 0x0258
+BITMAP
+1fb8
+60e0
+4060
+8020
+8020
+8020
+8020
+4060
+30a0
+1f20
+0020
+0020
+0020
+03f8
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 10 2 0
+ATTRIBUTES 0x0258
+BITMAP
+f3e0
+1620
+1800
+1000
+1000
+1000
+1000
+1000
+1000
+ff80
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 10 2 0
+ATTRIBUTES 0x0258
+BITMAP
+3e80
+4180
+4080
+6000
+3f00
+8380
+8040
+c040
+e0c0
+9f00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 14 3 0
+ATTRIBUTES 0x0258
+BITMAP
+4000
+4000
+4000
+4000
+ff00
+4000
+4000
+4000
+4000
+4000
+4000
+4000
+20c0
+1f00
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 10 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e1c0
+2040
+2040
+2040
+2040
+2040
+2040
+2040
+31c0
+1f70
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 10 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8f8
+2020
+3040
+1040
+1080
+0880
+0980
+0500
+0700
+0600
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 10 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f03c
+4008
+4108
+2310
+2390
+2290
+1490
+1460
+1460
+0860
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 10 0 0
+ATTRIBUTES 0x0258
+BITMAP
+7c78
+1820
+0c40
+0680
+0300
+0780
+0cc0
+1860
+3030
+f87c
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 -4
+ATTRIBUTES 0x0258
+BITMAP
+f078
+2020
+2020
+1040
+10c0
+0880
+0980
+0500
+0600
+0600
+0400
+0400
+0800
+fe00
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 10 2 0
+ATTRIBUTES 0x0258
+BITMAP
+7fc0
+4080
+4100
+0200
+0400
+0c00
+1800
+3040
+6040
+ffc0
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 5 18 6 -2
+ATTRIBUTES 0x0258
+BITMAP
+18
+20
+40
+40
+40
+60
+20
+20
+60
+c0
+60
+20
+20
+60
+40
+40
+60
+38
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 1 21 7 -5
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 6 18 3 -2
+ATTRIBUTES 0x0258
+BITMAP
+e0
+30
+10
+10
+10
+10
+10
+10
+18
+0c
+10
+10
+10
+10
+10
+10
+10
+e0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 4 2 5
+ATTRIBUTES 0x0258
+BITMAP
+2040
+7cc0
+8780
+8000
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 3 13 6 -3
+ATTRIBUTES 0x0258
+BITMAP
+e0
+e0
+e0
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 16 3 -1
+ATTRIBUTES 0x0258
+BITMAP
+0800
+0800
+0800
+0800
+3e80
+4980
+8880
+8800
+8800
+8800
+4880
+6b00
+1c00
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0f00
+18c0
+3040
+2040
+2000
+2000
+3000
+ffc0
+1000
+1000
+1000
+1000
+2000
+3c20
+63c0
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 11 2 1
+ATTRIBUTES 0x0258
+BITMAP
+8040
+5ec0
+3100
+6080
+4080
+4080
+4080
+2100
+5e80
+8040
+8040
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8f8
+2060
+1040
+18c0
+0d80
+0700
+0200
+1fe0
+0200
+1fe0
+0200
+0200
+0200
+1fc0
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 1 21 7 -5
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+00
+00
+00
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 16 3 -2
+ATTRIBUTES 0x0258
+BITMAP
+3f00
+6100
+4100
+4100
+3000
+f800
+8c00
+8600
+4100
+3080
+1980
+0f00
+0600
+8200
+8200
+fc00
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 5 3 5 12
+ATTRIBUTES 0x0258
+BITMAP
+d8
+d8
+d8
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 14 0 0
+ATTRIBUTES 0x0258
+BITMAP
+07c0
+1820
+2010
+4788
+4c4c
+9044
+9004
+9004
+9804
+4c44
+4788
+2010
+1820
+07c0
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 6 8 4 6
+ATTRIBUTES 0x0258
+BITMAP
+78
+08
+78
+88
+98
+7c
+00
+fc
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 10 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0440
+1980
+3300
+6600
+cc00
+cc00
+6200
+1100
+0cc0
+0440
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 6 2 4
+ATTRIBUTES 0x0258
+BITMAP
+ffc0
+0040
+0040
+0040
+0040
+0040
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 5 1 5 6
+ATTRIBUTES 0x0258
+BITMAP
+f8
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 14 0 0
+ATTRIBUTES 0x0258
+BITMAP
+07c0
+1820
+2010
+4788
+c444
+84c4
+8704
+8484
+8484
+4f4c
+4008
+2010
+1820
+07c0
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 8 1 3 13
+ATTRIBUTES 0x0258
+BITMAP
+ff
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 7 7 4 8
+ATTRIBUTES 0x0258
+BITMAP
+38
+44
+82
+82
+82
+c4
+78
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 13 2 1
+ATTRIBUTES 0x0258
+BITMAP
+0400
+0400
+0400
+0400
+0400
+ffe0
+0400
+0400
+0400
+0400
+0000
+0000
+ffe0
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 6 9 4 6
+ATTRIBUTES 0x0258
+BITMAP
+78
+cc
+84
+04
+08
+10
+20
+44
+fc
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 6 9 4 6
+ATTRIBUTES 0x0258
+BITMAP
+70
+88
+08
+08
+38
+08
+04
+0c
+78
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 5 3 5 12
+ATTRIBUTES 0x0258
+BITMAP
+30
+60
+c0
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 -4
+ATTRIBUTES 0x0258
+BITMAP
+e1c0
+2040
+2040
+2040
+2040
+2040
+2040
+2040
+30c0
+2ff0
+2000
+2000
+2000
+2000
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 16 3 -2
+ATTRIBUTES 0x0258
+BITMAP
+3f80
+4900
+8900
+8900
+8900
+8900
+4900
+3900
+0900
+0900
+0900
+0900
+0900
+0900
+0900
+3b80
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 3 5 6
+ATTRIBUTES 0x0258
+BITMAP
+60
+f0
+70
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 4 5 -3
+ATTRIBUTES 0x0258
+BITMAP
+20
+30
+30
+f0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 6 9 4 6
+ATTRIBUTES 0x0258
+BITMAP
+30
+f0
+10
+10
+10
+10
+10
+10
+fc
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 6 8 4 6
+ATTRIBUTES 0x0258
+BITMAP
+78
+c4
+84
+84
+cc
+38
+00
+fc
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 10 2 0
+ATTRIBUTES 0x0258
+BITMAP
+8800
+6600
+3300
+1980
+0cc0
+0cc0
+1980
+2200
+cc00
+4400
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 17 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+6008
+a018
+2010
+2020
+2040
+2040
+2080
+2100
+f230
+0230
+0450
+0850
+1890
+1110
+21f8
+4010
+4078
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 17 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+3004
+5008
+1010
+1030
+1020
+1040
+10c0
+1080
+7938
+0244
+0604
+0404
+0808
+1018
+1030
+2044
+407c
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 17 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+700c
+8808
+0810
+1820
+3060
+0840
+0880
+0900
+f130
+0230
+0450
+0850
+0890
+1190
+21f8
+4010
+4078
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 8 13 3 -3
+ATTRIBUTES 0x0258
+BITMAP
+1c
+1c
+1c
+00
+08
+18
+60
+40
+80
+80
+81
+41
+3e
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 18 0 0
+ATTRIBUTES 0x0258
+BITMAP
+0200
+0100
+0080
+0000
+3f00
+0300
+0780
+0680
+04c0
+0cc0
+0840
+1860
+1820
+1fe0
+3030
+2010
+6018
+f87c
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 18 0 0
+ATTRIBUTES 0x0258
+BITMAP
+0180
+0300
+0600
+0000
+3f00
+0300
+0780
+0680
+04c0
+0cc0
+0840
+1860
+1820
+1fe0
+3030
+2010
+6018
+f87c
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 18 0 0
+ATTRIBUTES 0x0258
+BITMAP
+0300
+0480
+0840
+0000
+3f00
+0300
+0780
+0680
+04c0
+0cc0
+0840
+1860
+1820
+1fe0
+3030
+2010
+6018
+f87c
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 18 0 0
+ATTRIBUTES 0x0258
+BITMAP
+0e20
+09c0
+0080
+0000
+3f00
+0300
+0780
+0680
+04c0
+0cc0
+0840
+1860
+1820
+1fe0
+3030
+2010
+6018
+f87c
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 18 0 0
+ATTRIBUTES 0x0258
+BITMAP
+06c0
+06c0
+06c0
+0000
+3f00
+0300
+0780
+0680
+04c0
+0cc0
+0840
+1860
+1820
+1fe0
+3030
+2010
+6018
+f87c
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 19 0 0
+ATTRIBUTES 0x0258
+BITMAP
+0300
+0480
+0480
+0300
+0000
+3f00
+0300
+0780
+0680
+04c0
+0cc0
+0840
+1860
+1820
+1fe0
+3030
+2010
+6018
+f87c
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 0 0
+ATTRIBUTES 0x0258
+BITMAP
+0ff8
+0308
+0308
+0508
+0528
+0d20
+09e0
+0920
+1920
+1f20
+3108
+3108
+6108
+f9f8
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 17 2 -3
+ATTRIBUTES 0x0258
+BITMAP
+1f20
+30e0
+4060
+4060
+8020
+8000
+8000
+8000
+8000
+8000
+c000
+4030
+20e0
+1f80
+0400
+0700
+0f00
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0400
+0200
+0100
+0000
+fff0
+1010
+1010
+1010
+1010
+1080
+1f80
+1080
+1080
+1000
+1010
+1010
+1010
+fff0
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0300
+0600
+0c00
+0000
+fff0
+1010
+1010
+1010
+1010
+1080
+1f80
+1080
+1080
+1000
+1010
+1010
+1010
+fff0
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0900
+1080
+0000
+fff0
+1010
+1010
+1010
+1010
+1080
+1f80
+1080
+1080
+1000
+1010
+1010
+1010
+fff0
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0d80
+0d80
+0d80
+0000
+fff0
+1010
+1010
+1010
+1010
+1080
+1f80
+1080
+1080
+1000
+1010
+1010
+1010
+fff0
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 18 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0800
+0400
+0200
+0000
+ffc0
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 18 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0c00
+1800
+0000
+ffc0
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 18 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0c00
+1200
+2100
+0000
+ffc0
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 18 2 0
+ATTRIBUTES 0x0258
+BITMAP
+1b00
+1b00
+1b00
+0000
+ffc0
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+ff00
+20c0
+2060
+2020
+2010
+2010
+fe10
+2010
+2010
+2010
+2020
+2060
+20c0
+ff80
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+1c40
+1380
+0100
+0000
+f0f8
+3810
+2810
+2810
+2410
+2410
+2210
+2210
+2110
+2110
+2090
+2090
+2050
+f870
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0400
+0200
+0100
+0000
+0f80
+30c0
+6060
+4020
+c010
+8010
+8010
+8010
+8010
+8010
+4020
+6020
+30c0
+0f80
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0300
+0600
+0c00
+0000
+0f80
+30c0
+6060
+4020
+c010
+8010
+8010
+8010
+8010
+8010
+4020
+6020
+30c0
+0f80
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0900
+1080
+0000
+0f80
+30c0
+6060
+4020
+c010
+8010
+8010
+8010
+8010
+8010
+4020
+6020
+30c0
+0f80
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+1c40
+1380
+0100
+0000
+0f80
+30c0
+6060
+4020
+c010
+8010
+8010
+8010
+8010
+8010
+4020
+6020
+30c0
+0f80
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0d80
+0d80
+0d80
+0000
+0f80
+30c0
+6060
+4020
+c010
+8010
+8010
+8010
+8010
+8010
+4020
+6020
+30c0
+0f80
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 9 3 3
+ATTRIBUTES 0x0258
+BITMAP
+4080
+c180
+6380
+3600
+1c00
+1c00
+3200
+4300
+8180
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0fa0
+30e0
+6060
+4070
+c090
+8110
+8310
+8210
+8410
+c810
+5820
+7020
+70c0
+5f80
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0400
+0200
+0100
+0000
+f9f8
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+6020
+6020
+3040
+1f80
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0300
+0600
+0c00
+0000
+f9f8
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+6020
+6020
+3040
+1f80
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0900
+1080
+0000
+f9f8
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+6020
+6020
+3040
+1f80
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0d80
+0d80
+0d80
+0000
+f9f8
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+6020
+6020
+3040
+1f80
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0300
+0600
+0c00
+0000
+f8f8
+2020
+3060
+1040
+0880
+0c80
+0500
+0700
+0200
+0200
+0200
+0200
+0200
+1fc0
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 14 2 0
+ATTRIBUTES 0x0258
+BITMAP
+fc00
+2000
+2000
+3f80
+20c0
+2060
+2020
+2020
+2060
+20c0
+3f80
+2000
+2000
+fc00
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+1e00
+3100
+6080
+4080
+4080
+4300
+4e00
+4180
+4080
+4040
+4040
+4040
+4040
+4880
+cf00
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0800
+0400
+0200
+0000
+0000
+3f00
+0180
+0080
+3f80
+4180
+8080
+8080
+8180
+c380
+7ce0
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0c00
+1800
+0000
+0000
+3f00
+0180
+0080
+3f80
+4180
+8080
+8080
+8180
+c380
+7ce0
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0c00
+1600
+2100
+0000
+0000
+3f00
+0180
+0080
+3f80
+4180
+8080
+8080
+8180
+c380
+7ce0
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+3880
+2700
+0200
+0000
+0000
+3f00
+0180
+0080
+3f80
+4180
+8080
+8080
+8180
+c380
+7ce0
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+1b00
+1b00
+1b00
+0000
+0000
+3f00
+0180
+0080
+3f80
+4180
+8080
+8080
+8180
+c380
+7ce0
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0e00
+1200
+0e00
+0000
+0000
+3f00
+0180
+0080
+3f80
+4180
+8080
+8080
+8180
+c380
+7ce0
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 10 1 0
+ATTRIBUTES 0x0258
+BITMAP
+7fe0
+0230
+0210
+0210
+3ff0
+4200
+8200
+8200
+8700
+78f0
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 13 2 -3
+ATTRIBUTES 0x0258
+BITMAP
+1f60
+60c0
+4040
+8000
+8000
+8000
+8000
+4020
+60c0
+1f00
+0400
+0600
+0e00
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0800
+0400
+0200
+0000
+0000
+1f00
+60c0
+c060
+8020
+ffe0
+8000
+8000
+4000
+6060
+1f80
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0c00
+1800
+0000
+0000
+1f00
+60c0
+c060
+8020
+ffe0
+8000
+8000
+4000
+6060
+1f80
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0c00
+1600
+2100
+0000
+0000
+1f00
+60c0
+c060
+8020
+ffe0
+8000
+8000
+4000
+6060
+1f80
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+1b00
+1b00
+1b00
+0000
+0000
+1f00
+60c0
+c060
+8020
+ffe0
+8000
+8000
+4000
+6060
+1f80
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0800
+0400
+0200
+0000
+0000
+7c00
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0c00
+1800
+0000
+0000
+7c00
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0c00
+1600
+2100
+0000
+0000
+7c00
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+1b00
+1b00
+1b00
+0000
+0000
+7c00
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 17 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0200
+3c00
+0e00
+0b00
+1980
+00c0
+0060
+1fe0
+6070
+4030
+8010
+8010
+8010
+8010
+4020
+3060
+1f80
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+1c40
+1380
+0100
+0000
+0000
+ef80
+3040
+2020
+2020
+2020
+2020
+2020
+2020
+2020
+f9f8
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0400
+0200
+0100
+0000
+0000
+1f80
+6060
+4020
+8010
+8010
+8010
+8010
+4020
+3060
+1f80
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0300
+0600
+0c00
+0000
+0000
+1f80
+6060
+4020
+8010
+8010
+8010
+8010
+4020
+3060
+1f80
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0b00
+1080
+0000
+0000
+1f80
+6060
+4020
+8010
+8010
+8010
+8010
+4020
+3060
+1f80
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+1c40
+1380
+0100
+0000
+0000
+1f80
+6060
+4020
+8010
+8010
+8010
+8010
+4020
+3060
+1f80
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0d80
+0d80
+0d80
+0000
+0000
+1f80
+6060
+4020
+8010
+8010
+8010
+8010
+4020
+3060
+1f80
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 11 2 2
+ATTRIBUTES 0x0258
+BITMAP
+0c00
+0c00
+0000
+0000
+0000
+ffe0
+0000
+0000
+0000
+0c00
+0c00
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 10 1 0
+ATTRIBUTES 0x0258
+BITMAP
+1fa0
+6060
+40b0
+8110
+8210
+8c10
+d810
+7020
+7060
+df80
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0400
+0200
+0100
+0000
+0000
+e1c0
+2040
+2040
+2040
+2040
+2040
+2040
+2040
+31c0
+1f70
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0300
+0600
+0c00
+0000
+0000
+e1c0
+2040
+2040
+2040
+2040
+2040
+2040
+2040
+31c0
+1f70
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0b00
+1080
+0000
+0000
+e1c0
+2040
+2040
+2040
+2040
+2040
+2040
+2040
+31c0
+1f70
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0d80
+0d80
+0d80
+0000
+0000
+e1c0
+2040
+2040
+2040
+2040
+2040
+2040
+2040
+31c0
+1f70
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 19 1 -4
+ATTRIBUTES 0x0258
+BITMAP
+0300
+0600
+0c00
+0000
+0000
+f078
+2020
+2020
+1040
+10c0
+0880
+0980
+0500
+0600
+0600
+0400
+0400
+0800
+fe00
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 19 0 -4
+ATTRIBUTES 0x0258
+BITMAP
+f000
+1000
+1000
+1000
+1000
+17c0
+1c30
+1810
+1008
+1008
+1008
+1008
+1810
+1c20
+17c0
+1000
+1000
+1000
+fe00
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 19 1 -4
+ATTRIBUTES 0x0258
+BITMAP
+0d80
+0d80
+0d80
+0000
+0000
+f078
+2020
+2020
+1040
+10c0
+0880
+0980
+0500
+0600
+0600
+0400
+0400
+0800
+fe00
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/courier24.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/courier24.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/courier24.h	(revision 12606)
@@ -0,0 +1,1068 @@
+static unsigned char courier24_0_bits[] = {
+0x00};
+static unsigned char courier24_1_bits[] = {
+0x00};
+static unsigned char courier24_2_bits[] = {
+0x00};
+static unsigned char courier24_3_bits[] = {
+0x00};
+static unsigned char courier24_4_bits[] = {
+0x00};
+static unsigned char courier24_5_bits[] = {
+0x00};
+static unsigned char courier24_6_bits[] = {
+0x00};
+static unsigned char courier24_7_bits[] = {
+0x00};
+static unsigned char courier24_8_bits[] = {
+0x00};
+static unsigned char courier24_9_bits[] = {
+0x00};
+static unsigned char courier24_10_bits[] = {
+0x00};
+static unsigned char courier24_11_bits[] = {
+0x00};
+static unsigned char courier24_12_bits[] = {
+0x00};
+static unsigned char courier24_13_bits[] = {
+0x00};
+static unsigned char courier24_14_bits[] = {
+0x00};
+static unsigned char courier24_15_bits[] = {
+0x00};
+static unsigned char courier24_16_bits[] = {
+0x00};
+static unsigned char courier24_17_bits[] = {
+0x00};
+static unsigned char courier24_18_bits[] = {
+0x00};
+static unsigned char courier24_19_bits[] = {
+0x00};
+static unsigned char courier24_20_bits[] = {
+0x00};
+static unsigned char courier24_21_bits[] = {
+0x00};
+static unsigned char courier24_22_bits[] = {
+0x00};
+static unsigned char courier24_23_bits[] = {
+0x00};
+static unsigned char courier24_24_bits[] = {
+0x00};
+static unsigned char courier24_25_bits[] = {
+0x00};
+static unsigned char courier24_26_bits[] = {
+0x00};
+static unsigned char courier24_27_bits[] = {
+0x00};
+static unsigned char courier24_28_bits[] = {
+0x00};
+static unsigned char courier24_29_bits[] = {
+0x00};
+static unsigned char courier24_30_bits[] = {
+0x00};
+static unsigned char courier24_31_bits[] = {
+0x00};
+static unsigned char courier24_32_bits[] = {
+0x00, 0x00};
+static unsigned char courier24_33_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x07, 
+0x07, 0x07};
+static unsigned char courier24_34_bits[] = {
+0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33};
+static unsigned char courier24_35_bits[] = {
+0x88, 0x01, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 
+0xff, 0x07, 0x84, 0x00, 0x84, 0x00, 0x84, 0x00, 0x84, 0x00, 0xff, 0x07, 
+0x84, 0x00, 0x84, 0x00, 0x84, 0x00, 0x84, 0x00, 0x84, 0x00};
+static unsigned char courier24_36_bits[] = {
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xf8, 0x01, 0xa4, 0x01, 0x22, 0x01, 
+0x22, 0x01, 0x26, 0x03, 0x3c, 0x00, 0xf0, 0x00, 0xa0, 0x01, 0x23, 0x02, 
+0x22, 0x02, 0x26, 0x02, 0x2e, 0x01, 0xfe, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00};
+static unsigned char courier24_37_bits[] = {
+0x1c, 0x00, 0x22, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x22, 0x06, 
+0x9c, 0x07, 0xf0, 0x01, 0x3e, 0x00, 0x8e, 0x03, 0x40, 0x04, 0x20, 0x08, 
+0x20, 0x08, 0x60, 0x0c, 0x80, 0x07};
+static unsigned char courier24_38_bits[] = {
+0xbc, 0x00, 0x46, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x0c, 0x00, 
+0x8a, 0x03, 0x93, 0x00, 0xb1, 0x00, 0x61, 0x00, 0x61, 0x00, 0xe3, 0x00, 
+0x9e, 0x03};
+static unsigned char courier24_39_bits[] = {
+0x0c, 0x0e, 0x06, 0x06, 0x03, 0x03};
+static unsigned char courier24_40_bits[] = {
+0x08, 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x03, 0x02, 0x02, 0x04, 0x04, 0x08};
+static unsigned char courier24_41_bits[] = {
+0x02, 0x02, 0x06, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x04, 0x04, 0x06, 0x02, 0x03};
+static unsigned char courier24_42_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x11, 0x01, 0xff, 0x01, 0x7c, 0x00, 0x38, 0x00, 
+0x6c, 0x00, 0xc6, 0x00, 0x44, 0x00};
+static unsigned char courier24_43_bits[] = {
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xff, 0x07, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00};
+static unsigned char courier24_44_bits[] = {
+0x0c, 0x06, 0x06, 0x06, 0x03, 0x03};
+static unsigned char courier24_45_bits[] = {
+0xff, 0x07};
+static unsigned char courier24_46_bits[] = {
+0x06, 0x0f, 0x0e};
+static unsigned char courier24_47_bits[] = {
+0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0xc0, 0x00, 
+0x40, 0x00, 0x40, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x08, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x06, 0x00, 0x02, 0x00, 
+0x03, 0x00, 0x01, 0x00};
+static unsigned char courier24_48_bits[] = {
+0x3c, 0x00, 0x46, 0x00, 0x82, 0x00, 0x81, 0x00, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x81, 0x00, 
+0x82, 0x00, 0x46, 0x00, 0x3c, 0x00};
+static unsigned char courier24_49_bits[] = {
+0x30, 0x00, 0x3c, 0x00, 0x26, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0xfe, 0x03};
+static unsigned char courier24_50_bits[] = {
+0x78, 0x00, 0xc4, 0x00, 0x82, 0x01, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 
+0x80, 0x01, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x01, 
+0x06, 0x01, 0x01, 0x01, 0xff, 0x01};
+static unsigned char courier24_51_bits[] = {
+0x3c, 0x00, 0x46, 0x00, 0x82, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 
+0x60, 0x00, 0xf0, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 
+0x00, 0x01, 0xc1, 0x00, 0x7e, 0x00};
+static unsigned char courier24_52_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x50, 0x00, 0x50, 0x00, 0x48, 0x00, 0x48, 0x00, 
+0x44, 0x00, 0x42, 0x00, 0x42, 0x00, 0x41, 0x00, 0xff, 0x03, 0x40, 0x00, 
+0x40, 0x00, 0x40, 0x00, 0xf8, 0x03};
+static unsigned char courier24_53_bits[] = {
+0xfe, 0x01, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 
+0x7a, 0x00, 0x86, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 
+0x00, 0x01, 0x83, 0x01, 0x7e, 0x00};
+static unsigned char courier24_54_bits[] = {
+0xf0, 0x01, 0x1c, 0x00, 0x06, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 
+0x3d, 0x00, 0x47, 0x00, 0xc3, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 
+0x82, 0x00, 0x46, 0x00, 0x3c, 0x00};
+static unsigned char courier24_55_bits[] = {
+0xff, 0x03, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x80, 0x00, 
+0x80, 0x00, 0xc0, 0x00, 0x40, 0x00, 0x40, 0x00, 0x60, 0x00, 0x20, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x10, 0x00};
+static unsigned char courier24_56_bits[] = {
+0x3c, 0x00, 0x46, 0x00, 0x83, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 
+0x46, 0x00, 0x3c, 0x00, 0xc2, 0x00, 0x83, 0x00, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0xc2, 0x00, 0x7c, 0x00};
+static unsigned char courier24_57_bits[] = {
+0x3c, 0x00, 0x46, 0x00, 0x82, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x83, 0x01, 0xc6, 0x01, 0x3c, 0x01, 0x00, 0x01, 0x80, 0x00, 0x80, 0x00, 
+0x40, 0x00, 0x20, 0x00, 0x1f, 0x00};
+static unsigned char courier24_58_bits[] = {
+0x06, 0x0f, 0x0e, 0x00, 0x00, 0x00, 0x06, 0x0f, 0x0e};
+static unsigned char courier24_59_bits[] = {
+0x0c, 0x1e, 0x1c, 0x00, 0x00, 0x00, 0x0c, 0x0e, 0x06, 0x06, 0x02, 0x03};
+static unsigned char courier24_60_bits[] = {
+0x00, 0x08, 0x00, 0x0e, 0x80, 0x01, 0x60, 0x00, 0x1c, 0x00, 0x07, 0x00, 
+0x1c, 0x00, 0xf0, 0x00, 0xc0, 0x07, 0x00, 0x0e, 0x00, 0x08};
+static unsigned char courier24_61_bits[] = {
+0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07};
+static unsigned char courier24_62_bits[] = {
+0x01, 0x00, 0x07, 0x00, 0x1c, 0x00, 0x60, 0x00, 0x80, 0x03, 0x00, 0x0e, 
+0xc0, 0x03, 0xf8, 0x00, 0x3f, 0x00, 0x0f, 0x00, 0x03, 0x00};
+static unsigned char courier24_63_bits[] = {
+0x3e, 0x43, 0x81, 0x81, 0x80, 0x80, 0x40, 0x38, 0x08, 0x08, 0x00, 0x1c, 
+0x1c, 0x1c};
+static unsigned char courier24_64_bits[] = {
+0xf0, 0x01, 0x0c, 0x06, 0x06, 0x08, 0x62, 0x19, 0xb1, 0x11, 0x91, 0x11, 
+0x89, 0x11, 0x89, 0x18, 0xc9, 0x08, 0x7b, 0x07, 0x22, 0x00, 0x0c, 0x0e, 
+0xf8, 0x03};
+static unsigned char courier24_65_bits[] = {
+0xfc, 0x00, 0xc0, 0x00, 0xe0, 0x01, 0x60, 0x01, 0x20, 0x03, 0x30, 0x03, 
+0x10, 0x02, 0x18, 0x06, 0x18, 0x04, 0xf8, 0x07, 0x0c, 0x0c, 0x04, 0x08, 
+0x06, 0x18, 0x1f, 0x3e};
+static unsigned char courier24_66_bits[] = {
+0xff, 0x01, 0x04, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 
+0xfc, 0x01, 0x04, 0x06, 0x04, 0x0c, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 
+0x04, 0x06, 0xff, 0x03};
+static unsigned char courier24_67_bits[] = {
+0xf0, 0x04, 0x0c, 0x07, 0x06, 0x06, 0x02, 0x06, 0x01, 0x04, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x0c, 
+0x0c, 0x06, 0xf8, 0x01};
+static unsigned char courier24_68_bits[] = {
+0xff, 0x00, 0x04, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x08, 0x04, 0x08, 
+0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x0c, 0x04, 0x04, 
+0x04, 0x03, 0xff, 0x01};
+static unsigned char courier24_69_bits[] = {
+0xff, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x01, 
+0xf8, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0xff, 0x0f};
+static unsigned char courier24_70_bits[] = {
+0xff, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x84, 0x00, 
+0xfc, 0x00, 0x84, 0x00, 0x84, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 
+0x04, 0x00, 0x3f, 0x00};
+static unsigned char courier24_71_bits[] = {
+0xf0, 0x05, 0x0c, 0x07, 0x04, 0x06, 0x02, 0x04, 0x03, 0x04, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x81, 0x1f, 0x01, 0x08, 0x02, 0x08, 0x06, 0x08, 
+0x0c, 0x0c, 0xf0, 0x03};
+static unsigned char courier24_72_bits[] = {
+0x1f, 0x0f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0xfc, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x1f, 0x0f};
+static unsigned char courier24_73_bits[] = {
+0xff, 0x03, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_74_bits[] = {
+0xf0, 0x1f, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 
+0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
+0x06, 0x01, 0xf8, 0x01};
+static unsigned char courier24_75_bits[] = {
+0x3f, 0x1f, 0x08, 0x04, 0x08, 0x02, 0x08, 0x01, 0x88, 0x00, 0x48, 0x00, 
+0x28, 0x00, 0x78, 0x00, 0x88, 0x01, 0x08, 0x01, 0x08, 0x02, 0x08, 0x06, 
+0x08, 0x04, 0x3f, 0x1c};
+static unsigned char courier24_76_bits[] = {
+0x7f, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 
+0x08, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0xff, 0x0f};
+static unsigned char courier24_77_bits[] = {
+0x0f, 0x3c, 0x14, 0x14, 0x14, 0x14, 0x14, 0x12, 0x24, 0x12, 0x24, 0x12, 
+0x24, 0x11, 0x44, 0x11, 0x44, 0x11, 0xc4, 0x10, 0x04, 0x10, 0x04, 0x10, 
+0x04, 0x10, 0x1f, 0x3e};
+static unsigned char courier24_78_bits[] = {
+0x0f, 0x1f, 0x1c, 0x08, 0x14, 0x08, 0x14, 0x08, 0x24, 0x08, 0x24, 0x08, 
+0x44, 0x08, 0x44, 0x08, 0x84, 0x08, 0x84, 0x08, 0x04, 0x09, 0x04, 0x09, 
+0x04, 0x0a, 0x1f, 0x0e};
+static unsigned char courier24_79_bits[] = {
+0xf0, 0x01, 0x0c, 0x03, 0x06, 0x06, 0x02, 0x04, 0x03, 0x08, 0x01, 0x08, 
+0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x02, 0x04, 0x06, 0x04, 
+0x0c, 0x03, 0xf0, 0x01};
+static unsigned char courier24_80_bits[] = {
+0xff, 0x00, 0x84, 0x03, 0x04, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x06, 0x84, 0x03, 0xfc, 0x01, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 
+0x04, 0x00, 0x3f, 0x00};
+static unsigned char courier24_81_bits[] = {
+0xf0, 0x00, 0x0c, 0x03, 0x06, 0x06, 0x02, 0x04, 0x03, 0x08, 0x01, 0x08, 
+0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x02, 0x04, 0x06, 0x04, 
+0x0c, 0x03, 0xf8, 0x01, 0x30, 0x00, 0xf8, 0x08, 0x08, 0x07};
+static unsigned char courier24_82_bits[] = {
+0xff, 0x01, 0x04, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x03, 0xfc, 0x01, 0xc4, 0x00, 0x84, 0x00, 0x04, 0x01, 0x04, 0x02, 
+0x04, 0x02, 0x1f, 0x1c};
+static unsigned char courier24_83_bits[] = {
+0x3c, 0x01, 0xc2, 0x01, 0x81, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 
+0x06, 0x00, 0xfc, 0x00, 0x80, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x83, 0x00, 0x7d, 0x00};
+static unsigned char courier24_84_bits[] = {
+0xfe, 0x0f, 0x42, 0x08, 0x42, 0x08, 0x42, 0x08, 0x42, 0x08, 0x43, 0x18, 
+0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 
+0x40, 0x00, 0xf8, 0x03};
+static unsigned char courier24_85_bits[] = {
+0x9f, 0x1f, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 
+0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x06, 0x04, 0x06, 0x04, 
+0x0c, 0x02, 0xf8, 0x01};
+static unsigned char courier24_86_bits[] = {
+0x1f, 0x3e, 0x04, 0x08, 0x04, 0x08, 0x08, 0x08, 0x08, 0x04, 0x08, 0x04, 
+0x10, 0x04, 0x10, 0x02, 0x30, 0x02, 0x20, 0x03, 0x20, 0x01, 0x40, 0x01, 
+0xc0, 0x01, 0xc0, 0x00};
+static unsigned char courier24_87_bits[] = {
+0x1f, 0x7c, 0x06, 0x20, 0x06, 0x20, 0x86, 0x10, 0xc4, 0x10, 0xc4, 0x11, 
+0x44, 0x11, 0x24, 0x11, 0x24, 0x13, 0x2c, 0x1a, 0x1c, 0x0a, 0x1c, 0x0c, 
+0x18, 0x0c, 0x08, 0x0c};
+static unsigned char courier24_88_bits[] = {
+0x1f, 0x0f, 0x04, 0x02, 0x0c, 0x02, 0x18, 0x01, 0x90, 0x00, 0xa0, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0xb0, 0x00, 0x10, 0x01, 0x08, 0x03, 0x0c, 0x06, 
+0x04, 0x04, 0x1f, 0x1f};
+static unsigned char courier24_89_bits[] = {
+0x1f, 0x1f, 0x04, 0x04, 0x0c, 0x06, 0x08, 0x02, 0x10, 0x01, 0x30, 0x01, 
+0xa0, 0x00, 0xe0, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 
+0x40, 0x00, 0xf8, 0x03};
+static unsigned char courier24_90_bits[] = {
+0xff, 0x01, 0x01, 0x01, 0x81, 0x00, 0x81, 0x00, 0x41, 0x00, 0x20, 0x00, 
+0x30, 0x00, 0x10, 0x00, 0x08, 0x00, 0x0c, 0x02, 0x04, 0x02, 0x02, 0x02, 
+0x03, 0x02, 0xff, 0x03};
+static unsigned char courier24_91_bits[] = {
+0x0f, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x0f};
+static unsigned char courier24_92_bits[] = {
+0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x06, 0x00, 0x04, 0x00, 0x0c, 0x00, 
+0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x10, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x40, 0x00, 0x40, 0x00, 0xc0, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0x01, 
+0x00, 0x03, 0x00, 0x02};
+static unsigned char courier24_93_bits[] = {
+0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x08, 0x08, 0x0f};
+static unsigned char courier24_94_bits[] = {
+0x70, 0x00, 0x50, 0x00, 0x58, 0x00, 0x98, 0x00, 0x88, 0x00, 0x8c, 0x01, 
+0x04, 0x01, 0x06, 0x03, 0x06, 0x03, 0x03, 0x02, 0x03, 0x06};
+static unsigned char courier24_95_bits[] = {
+0xff, 0xff, 0x01};
+static unsigned char courier24_96_bits[] = {
+0x0c, 0x0c, 0x06, 0x06, 0x07, 0x03};
+static unsigned char courier24_97_bits[] = {
+0xfc, 0x00, 0x80, 0x01, 0x00, 0x01, 0xfc, 0x01, 0x82, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x81, 0x01, 0xc3, 0x01, 0x3e, 0x07};
+static unsigned char courier24_98_bits[] = {
+0x07, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0xe4, 0x03, 
+0x34, 0x0c, 0x0c, 0x08, 0x0c, 0x10, 0x0c, 0x10, 0x0c, 0x10, 0x0c, 0x10, 
+0x1c, 0x08, 0x3c, 0x0c, 0xe7, 0x03};
+static unsigned char courier24_99_bits[] = {
+0xf8, 0x07, 0x06, 0x03, 0x02, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x02, 0x04, 0x06, 0x03, 0xf8, 0x00};
+static unsigned char courier24_100_bits[] = {
+0x00, 0x07, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0xf8, 0x04, 
+0x04, 0x07, 0x02, 0x06, 0x01, 0x06, 0x01, 0x04, 0x01, 0x04, 0x01, 0x06, 
+0x02, 0x06, 0x8c, 0x05, 0xf8, 0x1c};
+static unsigned char courier24_101_bits[] = {
+0xf8, 0x00, 0x06, 0x03, 0x03, 0x06, 0x01, 0x04, 0xff, 0x07, 0x01, 0x00, 
+0x01, 0x00, 0x02, 0x00, 0x06, 0x06, 0xf8, 0x01};
+static unsigned char courier24_102_bits[] = {
+0xf0, 0x03, 0x18, 0x02, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0xff, 0x01, 
+0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 
+0x08, 0x00, 0x08, 0x00, 0xff, 0x01};
+static unsigned char courier24_103_bits[] = {
+0xf8, 0x0e, 0x86, 0x03, 0x02, 0x03, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 
+0x03, 0x02, 0x02, 0x03, 0x8c, 0x03, 0x78, 0x02, 0x00, 0x02, 0x00, 0x02, 
+0x00, 0x01, 0xf8, 0x00};
+static unsigned char courier24_104_bits[] = {
+0x07, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0xf4, 0x01, 
+0x1c, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x04, 0x04, 0x1f, 0x1f};
+static unsigned char courier24_105_bits[] = {
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x3e, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_106_bits[] = {
+0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x7f, 0x40, 0x40, 0x40, 0x40, 0x40, 
+0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x21, 0x1f};
+static unsigned char courier24_107_bits[] = {
+0x07, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x84, 0x0f, 
+0x84, 0x01, 0xc4, 0x00, 0x34, 0x00, 0x3c, 0x00, 0x44, 0x00, 0x84, 0x01, 
+0x04, 0x03, 0x04, 0x06, 0x07, 0x1f};
+static unsigned char courier24_108_bits[] = {
+0x3e, 0x00, 0x22, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_109_bits[] = {
+0x77, 0x0f, 0x8c, 0x11, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 
+0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x9f, 0x73};
+static unsigned char courier24_110_bits[] = {
+0xf7, 0x01, 0x0c, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x9f, 0x1f};
+static unsigned char courier24_111_bits[] = {
+0xf8, 0x01, 0x06, 0x06, 0x02, 0x04, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x01, 0x08, 0x02, 0x04, 0x0c, 0x06, 0xf8, 0x01};
+static unsigned char courier24_112_bits[] = {
+0xef, 0x03, 0x38, 0x0c, 0x18, 0x08, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 
+0x08, 0x10, 0x18, 0x08, 0x38, 0x04, 0xe8, 0x03, 0x08, 0x00, 0x08, 0x00, 
+0x08, 0x00, 0x7f, 0x00};
+static unsigned char courier24_113_bits[] = {
+0xf8, 0x1d, 0x06, 0x07, 0x02, 0x06, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 
+0x01, 0x04, 0x02, 0x06, 0x0c, 0x05, 0xf8, 0x04, 0x00, 0x04, 0x00, 0x04, 
+0x00, 0x04, 0xc0, 0x1f};
+static unsigned char courier24_114_bits[] = {
+0xcf, 0x07, 0x68, 0x04, 0x18, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 
+0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0xff, 0x01};
+static unsigned char courier24_115_bits[] = {
+0x7c, 0x01, 0x82, 0x01, 0x02, 0x01, 0x06, 0x00, 0xfc, 0x00, 0xc1, 0x01, 
+0x01, 0x02, 0x03, 0x02, 0x07, 0x03, 0xf9, 0x00};
+static unsigned char courier24_116_bits[] = {
+0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0xff, 0x00, 0x02, 0x00, 
+0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 
+0x04, 0x03, 0xf8, 0x00};
+static unsigned char courier24_117_bits[] = {
+0x87, 0x03, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 
+0x04, 0x02, 0x04, 0x02, 0x8c, 0x03, 0xf8, 0x0e};
+static unsigned char courier24_118_bits[] = {
+0x1f, 0x1f, 0x04, 0x04, 0x0c, 0x02, 0x08, 0x02, 0x08, 0x01, 0x10, 0x01, 
+0x90, 0x01, 0xa0, 0x00, 0xe0, 0x00, 0x60, 0x00};
+static unsigned char courier24_119_bits[] = {
+0x0f, 0x3c, 0x02, 0x10, 0x82, 0x10, 0xc4, 0x08, 0xc4, 0x09, 0x44, 0x09, 
+0x28, 0x09, 0x28, 0x06, 0x28, 0x06, 0x10, 0x06};
+static unsigned char courier24_120_bits[] = {
+0x3e, 0x1e, 0x18, 0x04, 0x30, 0x02, 0x60, 0x01, 0xc0, 0x00, 0xe0, 0x01, 
+0x30, 0x03, 0x18, 0x06, 0x0c, 0x0c, 0x1f, 0x3e};
+static unsigned char courier24_121_bits[] = {
+0x0f, 0x1e, 0x04, 0x04, 0x04, 0x04, 0x08, 0x02, 0x08, 0x03, 0x10, 0x01, 
+0x90, 0x01, 0xa0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x10, 0x00, 0x7f, 0x00};
+static unsigned char courier24_122_bits[] = {
+0xfe, 0x03, 0x02, 0x01, 0x82, 0x00, 0x40, 0x00, 0x20, 0x00, 0x30, 0x00, 
+0x18, 0x00, 0x0c, 0x02, 0x06, 0x02, 0xff, 0x03};
+static unsigned char courier24_123_bits[] = {
+0x18, 0x04, 0x02, 0x02, 0x02, 0x06, 0x04, 0x04, 0x06, 0x03, 0x06, 0x04, 
+0x04, 0x06, 0x02, 0x02, 0x06, 0x1c};
+static unsigned char courier24_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier24_125_bits[] = {
+0x07, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x18, 0x30, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x08, 0x08, 0x07};
+static unsigned char courier24_126_bits[] = {
+0x04, 0x02, 0x3e, 0x03, 0xe1, 0x01, 0x01, 0x00};
+static unsigned char courier24_127_bits[] = {
+0x00};
+static unsigned char courier24_128_bits[] = {
+0x00};
+static unsigned char courier24_129_bits[] = {
+0x00};
+static unsigned char courier24_130_bits[] = {
+0x00};
+static unsigned char courier24_131_bits[] = {
+0x00};
+static unsigned char courier24_132_bits[] = {
+0x00};
+static unsigned char courier24_133_bits[] = {
+0x00};
+static unsigned char courier24_134_bits[] = {
+0x00};
+static unsigned char courier24_135_bits[] = {
+0x00};
+static unsigned char courier24_136_bits[] = {
+0x00};
+static unsigned char courier24_137_bits[] = {
+0x00};
+static unsigned char courier24_138_bits[] = {
+0x00};
+static unsigned char courier24_139_bits[] = {
+0x00};
+static unsigned char courier24_140_bits[] = {
+0x00};
+static unsigned char courier24_141_bits[] = {
+0x00};
+static unsigned char courier24_142_bits[] = {
+0x00};
+static unsigned char courier24_143_bits[] = {
+0x00};
+static unsigned char courier24_144_bits[] = {
+0x00};
+static unsigned char courier24_145_bits[] = {
+0x00};
+static unsigned char courier24_146_bits[] = {
+0x00};
+static unsigned char courier24_147_bits[] = {
+0x00};
+static unsigned char courier24_148_bits[] = {
+0x00};
+static unsigned char courier24_149_bits[] = {
+0x00};
+static unsigned char courier24_150_bits[] = {
+0x00};
+static unsigned char courier24_151_bits[] = {
+0x00};
+static unsigned char courier24_152_bits[] = {
+0x00};
+static unsigned char courier24_153_bits[] = {
+0x00};
+static unsigned char courier24_154_bits[] = {
+0x00};
+static unsigned char courier24_155_bits[] = {
+0x00};
+static unsigned char courier24_156_bits[] = {
+0x00};
+static unsigned char courier24_157_bits[] = {
+0x00};
+static unsigned char courier24_158_bits[] = {
+0x00};
+static unsigned char courier24_159_bits[] = {
+0x00};
+static unsigned char courier24_160_bits[] = {
+0x00};
+static unsigned char courier24_161_bits[] = {
+0x07, 0x07, 0x07, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06};
+static unsigned char courier24_162_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x7c, 0x01, 0x92, 0x01, 
+0x11, 0x01, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x12, 0x01, 0xd6, 0x00, 
+0x38, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char courier24_163_bits[] = {
+0xf0, 0x00, 0x18, 0x03, 0x0c, 0x02, 0x04, 0x02, 0x04, 0x00, 0x04, 0x00, 
+0x0c, 0x00, 0xff, 0x03, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 
+0x04, 0x00, 0x3c, 0x04, 0xc6, 0x03};
+static unsigned char courier24_164_bits[] = {
+0x01, 0x02, 0x7a, 0x03, 0x8c, 0x00, 0x06, 0x01, 0x02, 0x01, 0x02, 0x01, 
+0x02, 0x01, 0x84, 0x00, 0x7a, 0x01, 0x01, 0x02, 0x01, 0x02};
+static unsigned char courier24_165_bits[] = {
+0x1f, 0x1f, 0x04, 0x06, 0x08, 0x02, 0x18, 0x03, 0xb0, 0x01, 0xe0, 0x00, 
+0x40, 0x00, 0xf8, 0x07, 0x40, 0x00, 0xf8, 0x07, 0x40, 0x00, 0x40, 0x00, 
+0x40, 0x00, 0xf8, 0x03};
+static unsigned char courier24_166_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier24_167_bits[] = {
+0xfc, 0x00, 0x86, 0x00, 0x82, 0x00, 0x82, 0x00, 0x0c, 0x00, 0x1f, 0x00, 
+0x31, 0x00, 0x61, 0x00, 0x82, 0x00, 0x0c, 0x01, 0x98, 0x01, 0xf0, 0x00, 
+0x60, 0x00, 0x41, 0x00, 0x41, 0x00, 0x3f, 0x00};
+static unsigned char courier24_168_bits[] = {
+0x1b, 0x1b, 0x1b};
+static unsigned char courier24_169_bits[] = {
+0xe0, 0x03, 0x18, 0x04, 0x04, 0x08, 0xe2, 0x11, 0x32, 0x32, 0x09, 0x22, 
+0x09, 0x20, 0x09, 0x20, 0x19, 0x20, 0x32, 0x22, 0xe2, 0x11, 0x04, 0x08, 
+0x18, 0x04, 0xe0, 0x03};
+static unsigned char courier24_170_bits[] = {
+0x1e, 0x10, 0x1e, 0x11, 0x19, 0x3e, 0x00, 0x3f};
+static unsigned char courier24_171_bits[] = {
+0x20, 0x02, 0x98, 0x01, 0xcc, 0x00, 0x66, 0x00, 0x33, 0x00, 0x33, 0x00, 
+0x46, 0x00, 0x88, 0x00, 0x30, 0x03, 0x20, 0x02};
+static unsigned char courier24_172_bits[] = {
+0xff, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02};
+static unsigned char courier24_173_bits[] = {
+0x1f};
+static unsigned char courier24_174_bits[] = {
+0xe0, 0x03, 0x18, 0x04, 0x04, 0x08, 0xe2, 0x11, 0x23, 0x22, 0x21, 0x23, 
+0xe1, 0x20, 0x21, 0x21, 0x21, 0x21, 0xf2, 0x32, 0x02, 0x10, 0x04, 0x08, 
+0x18, 0x04, 0xe0, 0x03};
+static unsigned char courier24_175_bits[] = {
+0xff};
+static unsigned char courier24_176_bits[] = {
+0x1c, 0x22, 0x41, 0x41, 0x41, 0x23, 0x1e};
+static unsigned char courier24_177_bits[] = {
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xff, 0x07, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0xff, 0x07};
+static unsigned char courier24_178_bits[] = {
+0x1e, 0x33, 0x21, 0x20, 0x10, 0x08, 0x04, 0x22, 0x3f};
+static unsigned char courier24_179_bits[] = {
+0x0e, 0x11, 0x10, 0x10, 0x1c, 0x10, 0x20, 0x30, 0x1e};
+static unsigned char courier24_180_bits[] = {
+0x0c, 0x06, 0x03};
+static unsigned char courier24_181_bits[] = {
+0x87, 0x03, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 
+0x04, 0x02, 0x04, 0x02, 0x0c, 0x03, 0xf4, 0x0f, 0x04, 0x00, 0x04, 0x00, 
+0x04, 0x00, 0x04, 0x00};
+static unsigned char courier24_182_bits[] = {
+0xfc, 0x01, 0x92, 0x00, 0x91, 0x00, 0x91, 0x00, 0x91, 0x00, 0x91, 0x00, 
+0x92, 0x00, 0x9c, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 
+0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0xdc, 0x01};
+static unsigned char courier24_183_bits[] = {
+0x06, 0x0f, 0x0e};
+static unsigned char courier24_184_bits[] = {
+0x04, 0x0c, 0x0c, 0x0f};
+static unsigned char courier24_185_bits[] = {
+0x0c, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3f};
+static unsigned char courier24_186_bits[] = {
+0x1e, 0x23, 0x21, 0x21, 0x33, 0x1c, 0x00, 0x3f};
+static unsigned char courier24_187_bits[] = {
+0x11, 0x00, 0x66, 0x00, 0xcc, 0x00, 0x98, 0x01, 0x30, 0x03, 0x30, 0x03, 
+0x98, 0x01, 0x44, 0x00, 0x33, 0x00, 0x22, 0x00};
+static unsigned char courier24_188_bits[] = {
+0x06, 0x10, 0x05, 0x18, 0x04, 0x08, 0x04, 0x04, 0x04, 0x02, 0x04, 0x02, 
+0x04, 0x01, 0x84, 0x00, 0x4f, 0x0c, 0x40, 0x0c, 0x20, 0x0a, 0x10, 0x0a, 
+0x18, 0x09, 0x88, 0x08, 0x84, 0x1f, 0x02, 0x08, 0x02, 0x1e};
+static unsigned char courier24_189_bits[] = {
+0x0c, 0x20, 0x0a, 0x10, 0x08, 0x08, 0x08, 0x0c, 0x08, 0x04, 0x08, 0x02, 
+0x08, 0x03, 0x08, 0x01, 0x9e, 0x1c, 0x40, 0x22, 0x60, 0x20, 0x20, 0x20, 
+0x10, 0x10, 0x08, 0x18, 0x08, 0x0c, 0x04, 0x22, 0x02, 0x3e};
+static unsigned char courier24_190_bits[] = {
+0x0e, 0x30, 0x11, 0x10, 0x10, 0x08, 0x18, 0x04, 0x0c, 0x06, 0x10, 0x02, 
+0x10, 0x01, 0x90, 0x00, 0x8f, 0x0c, 0x40, 0x0c, 0x20, 0x0a, 0x10, 0x0a, 
+0x10, 0x09, 0x88, 0x09, 0x84, 0x1f, 0x02, 0x08, 0x02, 0x1e};
+static unsigned char courier24_191_bits[] = {
+0x38, 0x38, 0x38, 0x00, 0x10, 0x18, 0x06, 0x02, 0x01, 0x01, 0x81, 0x82, 
+0x7c};
+static unsigned char courier24_192_bits[] = {
+0x40, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0xfc, 0x00, 0xc0, 0x00, 
+0xe0, 0x01, 0x60, 0x01, 0x20, 0x03, 0x30, 0x03, 0x10, 0x02, 0x18, 0x06, 
+0x18, 0x04, 0xf8, 0x07, 0x0c, 0x0c, 0x04, 0x08, 0x06, 0x18, 0x1f, 0x3e};
+static unsigned char courier24_193_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xc0, 0x00, 
+0xe0, 0x01, 0x60, 0x01, 0x20, 0x03, 0x30, 0x03, 0x10, 0x02, 0x18, 0x06, 
+0x18, 0x04, 0xf8, 0x07, 0x0c, 0x0c, 0x04, 0x08, 0x06, 0x18, 0x1f, 0x3e};
+static unsigned char courier24_194_bits[] = {
+0xc0, 0x00, 0x20, 0x01, 0x10, 0x02, 0x00, 0x00, 0xfc, 0x00, 0xc0, 0x00, 
+0xe0, 0x01, 0x60, 0x01, 0x20, 0x03, 0x30, 0x03, 0x10, 0x02, 0x18, 0x06, 
+0x18, 0x04, 0xf8, 0x07, 0x0c, 0x0c, 0x04, 0x08, 0x06, 0x18, 0x1f, 0x3e};
+static unsigned char courier24_195_bits[] = {
+0x70, 0x04, 0x90, 0x03, 0x00, 0x01, 0x00, 0x00, 0xfc, 0x00, 0xc0, 0x00, 
+0xe0, 0x01, 0x60, 0x01, 0x20, 0x03, 0x30, 0x03, 0x10, 0x02, 0x18, 0x06, 
+0x18, 0x04, 0xf8, 0x07, 0x0c, 0x0c, 0x04, 0x08, 0x06, 0x18, 0x1f, 0x3e};
+static unsigned char courier24_196_bits[] = {
+0x60, 0x03, 0x60, 0x03, 0x60, 0x03, 0x00, 0x00, 0xfc, 0x00, 0xc0, 0x00, 
+0xe0, 0x01, 0x60, 0x01, 0x20, 0x03, 0x30, 0x03, 0x10, 0x02, 0x18, 0x06, 
+0x18, 0x04, 0xf8, 0x07, 0x0c, 0x0c, 0x04, 0x08, 0x06, 0x18, 0x1f, 0x3e};
+static unsigned char courier24_197_bits[] = {
+0xc0, 0x00, 0x20, 0x01, 0x20, 0x01, 0xc0, 0x00, 0x00, 0x00, 0xfc, 0x00, 
+0xc0, 0x00, 0xe0, 0x01, 0x60, 0x01, 0x20, 0x03, 0x30, 0x03, 0x10, 0x02, 
+0x18, 0x06, 0x18, 0x04, 0xf8, 0x07, 0x0c, 0x0c, 0x04, 0x08, 0x06, 0x18, 
+0x1f, 0x3e};
+static unsigned char courier24_198_bits[] = {
+0xf0, 0x1f, 0xc0, 0x10, 0xc0, 0x10, 0xa0, 0x10, 0xa0, 0x14, 0xb0, 0x04, 
+0x90, 0x07, 0x90, 0x04, 0x98, 0x04, 0xf8, 0x04, 0x8c, 0x10, 0x8c, 0x10, 
+0x86, 0x10, 0x9f, 0x1f};
+static unsigned char courier24_199_bits[] = {
+0xf8, 0x04, 0x0c, 0x07, 0x02, 0x06, 0x02, 0x06, 0x01, 0x04, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x0c, 
+0x04, 0x07, 0xf8, 0x01, 0x20, 0x00, 0xe0, 0x00, 0xf0, 0x00};
+static unsigned char courier24_200_bits[] = {
+0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x01, 0xf8, 0x01, 0x08, 0x01, 
+0x08, 0x01, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x0f};
+static unsigned char courier24_201_bits[] = {
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x01, 0xf8, 0x01, 0x08, 0x01, 
+0x08, 0x01, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x0f};
+static unsigned char courier24_202_bits[] = {
+0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x00, 0x00, 0xff, 0x0f, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x01, 0xf8, 0x01, 0x08, 0x01, 
+0x08, 0x01, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x0f};
+static unsigned char courier24_203_bits[] = {
+0xb0, 0x01, 0xb0, 0x01, 0xb0, 0x01, 0x00, 0x00, 0xff, 0x0f, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x01, 0xf8, 0x01, 0x08, 0x01, 
+0x08, 0x01, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x0f};
+static unsigned char courier24_204_bits[] = {
+0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0xff, 0x03, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_205_bits[] = {
+0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x00, 0x00, 0xff, 0x03, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_206_bits[] = {
+0x30, 0x00, 0x48, 0x00, 0x84, 0x00, 0x00, 0x00, 0xff, 0x03, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_207_bits[] = {
+0xd8, 0x00, 0xd8, 0x00, 0xd8, 0x00, 0x00, 0x00, 0xff, 0x03, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_208_bits[] = {
+0xff, 0x00, 0x04, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x08, 0x04, 0x08, 
+0x7f, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x04, 0x04, 0x06, 
+0x04, 0x03, 0xff, 0x01};
+static unsigned char courier24_209_bits[] = {
+0x38, 0x02, 0xc8, 0x01, 0x80, 0x00, 0x00, 0x00, 0x0f, 0x1f, 0x1c, 0x08, 
+0x14, 0x08, 0x14, 0x08, 0x24, 0x08, 0x24, 0x08, 0x44, 0x08, 0x44, 0x08, 
+0x84, 0x08, 0x84, 0x08, 0x04, 0x09, 0x04, 0x09, 0x04, 0x0a, 0x1f, 0x0e};
+static unsigned char courier24_210_bits[] = {
+0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x0c, 0x03, 
+0x06, 0x06, 0x02, 0x04, 0x03, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x01, 0x08, 0x01, 0x08, 0x02, 0x04, 0x06, 0x04, 0x0c, 0x03, 0xf0, 0x01};
+static unsigned char courier24_211_bits[] = {
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x0c, 0x03, 
+0x06, 0x06, 0x02, 0x04, 0x03, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x01, 0x08, 0x01, 0x08, 0x02, 0x04, 0x06, 0x04, 0x0c, 0x03, 0xf0, 0x01};
+static unsigned char courier24_212_bits[] = {
+0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x00, 0x00, 0xf0, 0x01, 0x0c, 0x03, 
+0x06, 0x06, 0x02, 0x04, 0x03, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x01, 0x08, 0x01, 0x08, 0x02, 0x04, 0x06, 0x04, 0x0c, 0x03, 0xf0, 0x01};
+static unsigned char courier24_213_bits[] = {
+0x38, 0x02, 0xc8, 0x01, 0x80, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x0c, 0x03, 
+0x06, 0x06, 0x02, 0x04, 0x03, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x01, 0x08, 0x01, 0x08, 0x02, 0x04, 0x06, 0x04, 0x0c, 0x03, 0xf0, 0x01};
+static unsigned char courier24_214_bits[] = {
+0xb0, 0x01, 0xb0, 0x01, 0xb0, 0x01, 0x00, 0x00, 0xf0, 0x01, 0x0c, 0x03, 
+0x06, 0x06, 0x02, 0x04, 0x03, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x01, 0x08, 0x01, 0x08, 0x02, 0x04, 0x06, 0x04, 0x0c, 0x03, 0xf0, 0x01};
+static unsigned char courier24_215_bits[] = {
+0x02, 0x01, 0x83, 0x01, 0xc6, 0x01, 0x6c, 0x00, 0x38, 0x00, 0x38, 0x00, 
+0x4c, 0x00, 0xc2, 0x00, 0x81, 0x01};
+static unsigned char courier24_216_bits[] = {
+0xf0, 0x05, 0x0c, 0x07, 0x06, 0x06, 0x02, 0x0e, 0x03, 0x09, 0x81, 0x08, 
+0xc1, 0x08, 0x41, 0x08, 0x21, 0x08, 0x13, 0x08, 0x1a, 0x04, 0x0e, 0x04, 
+0x0e, 0x03, 0xfa, 0x01};
+static unsigned char courier24_217_bits[] = {
+0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 0x00, 0x9f, 0x1f, 0x02, 0x04, 
+0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 
+0x02, 0x04, 0x02, 0x04, 0x06, 0x04, 0x06, 0x04, 0x0c, 0x02, 0xf8, 0x01};
+static unsigned char courier24_218_bits[] = {
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x9f, 0x1f, 0x02, 0x04, 
+0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 
+0x02, 0x04, 0x02, 0x04, 0x06, 0x04, 0x06, 0x04, 0x0c, 0x02, 0xf8, 0x01};
+static unsigned char courier24_219_bits[] = {
+0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x00, 0x00, 0x9f, 0x1f, 0x02, 0x04, 
+0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 
+0x02, 0x04, 0x02, 0x04, 0x06, 0x04, 0x06, 0x04, 0x0c, 0x02, 0xf8, 0x01};
+static unsigned char courier24_220_bits[] = {
+0xb0, 0x01, 0xb0, 0x01, 0xb0, 0x01, 0x00, 0x00, 0x9f, 0x1f, 0x02, 0x04, 
+0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 
+0x02, 0x04, 0x02, 0x04, 0x06, 0x04, 0x06, 0x04, 0x0c, 0x02, 0xf8, 0x01};
+static unsigned char courier24_221_bits[] = {
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x04, 0x04, 
+0x0c, 0x06, 0x08, 0x02, 0x10, 0x01, 0x30, 0x01, 0xa0, 0x00, 0xe0, 0x00, 
+0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xf8, 0x03};
+static unsigned char courier24_222_bits[] = {
+0x3f, 0x00, 0x04, 0x00, 0x04, 0x00, 0xfc, 0x01, 0x04, 0x03, 0x04, 0x06, 
+0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x04, 0x03, 0xfc, 0x01, 0x04, 0x00, 
+0x04, 0x00, 0x3f, 0x00};
+static unsigned char courier24_223_bits[] = {
+0x78, 0x00, 0x8c, 0x00, 0x06, 0x01, 0x02, 0x01, 0x02, 0x01, 0xc2, 0x00, 
+0x72, 0x00, 0x82, 0x01, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
+0x02, 0x02, 0x12, 0x01, 0xf3, 0x00};
+static unsigned char courier24_224_bits[] = {
+0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 
+0x80, 0x01, 0x00, 0x01, 0xfc, 0x01, 0x82, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x81, 0x01, 0xc3, 0x01, 0x3e, 0x07};
+static unsigned char courier24_225_bits[] = {
+0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 
+0x80, 0x01, 0x00, 0x01, 0xfc, 0x01, 0x82, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x81, 0x01, 0xc3, 0x01, 0x3e, 0x07};
+static unsigned char courier24_226_bits[] = {
+0x30, 0x00, 0x68, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 
+0x80, 0x01, 0x00, 0x01, 0xfc, 0x01, 0x82, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x81, 0x01, 0xc3, 0x01, 0x3e, 0x07};
+static unsigned char courier24_227_bits[] = {
+0x1c, 0x01, 0xe4, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 
+0x80, 0x01, 0x00, 0x01, 0xfc, 0x01, 0x82, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x81, 0x01, 0xc3, 0x01, 0x3e, 0x07};
+static unsigned char courier24_228_bits[] = {
+0xd8, 0x00, 0xd8, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 
+0x80, 0x01, 0x00, 0x01, 0xfc, 0x01, 0x82, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x81, 0x01, 0xc3, 0x01, 0x3e, 0x07};
+static unsigned char courier24_229_bits[] = {
+0x70, 0x00, 0x48, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 
+0x80, 0x01, 0x00, 0x01, 0xfc, 0x01, 0x82, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x81, 0x01, 0xc3, 0x01, 0x3e, 0x07};
+static unsigned char courier24_230_bits[] = {
+0xfe, 0x07, 0x40, 0x0c, 0x40, 0x08, 0x40, 0x08, 0xfc, 0x0f, 0x42, 0x00, 
+0x41, 0x00, 0x41, 0x00, 0xe1, 0x00, 0x1e, 0x0f};
+static unsigned char courier24_231_bits[] = {
+0xf8, 0x06, 0x06, 0x03, 0x02, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x02, 0x04, 0x06, 0x03, 0xf8, 0x00, 0x20, 0x00, 0x60, 0x00, 
+0x70, 0x00};
+static unsigned char courier24_232_bits[] = {
+0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 
+0x06, 0x03, 0x03, 0x06, 0x01, 0x04, 0xff, 0x07, 0x01, 0x00, 0x01, 0x00, 
+0x02, 0x00, 0x06, 0x06, 0xf8, 0x01};
+static unsigned char courier24_233_bits[] = {
+0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 
+0x06, 0x03, 0x03, 0x06, 0x01, 0x04, 0xff, 0x07, 0x01, 0x00, 0x01, 0x00, 
+0x02, 0x00, 0x06, 0x06, 0xf8, 0x01};
+static unsigned char courier24_234_bits[] = {
+0x30, 0x00, 0x68, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 
+0x06, 0x03, 0x03, 0x06, 0x01, 0x04, 0xff, 0x07, 0x01, 0x00, 0x01, 0x00, 
+0x02, 0x00, 0x06, 0x06, 0xf8, 0x01};
+static unsigned char courier24_235_bits[] = {
+0xd8, 0x00, 0xd8, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 
+0x06, 0x03, 0x03, 0x06, 0x01, 0x04, 0xff, 0x07, 0x01, 0x00, 0x01, 0x00, 
+0x02, 0x00, 0x06, 0x06, 0xf8, 0x01};
+static unsigned char courier24_236_bits[] = {
+0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_237_bits[] = {
+0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_238_bits[] = {
+0x30, 0x00, 0x68, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_239_bits[] = {
+0xd8, 0x00, 0xd8, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_240_bits[] = {
+0x40, 0x00, 0x3c, 0x00, 0x70, 0x00, 0xd0, 0x00, 0x98, 0x01, 0x00, 0x03, 
+0x00, 0x06, 0xf8, 0x07, 0x06, 0x0e, 0x02, 0x0c, 0x01, 0x08, 0x01, 0x08, 
+0x01, 0x08, 0x01, 0x08, 0x02, 0x04, 0x0c, 0x06, 0xf8, 0x01};
+static unsigned char courier24_241_bits[] = {
+0x38, 0x02, 0xc8, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x01, 
+0x0c, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x04, 0x04, 0x9f, 0x1f};
+static unsigned char courier24_242_bits[] = {
+0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 
+0x06, 0x06, 0x02, 0x04, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x02, 0x04, 0x0c, 0x06, 0xf8, 0x01};
+static unsigned char courier24_243_bits[] = {
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 
+0x06, 0x06, 0x02, 0x04, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x02, 0x04, 0x0c, 0x06, 0xf8, 0x01};
+static unsigned char courier24_244_bits[] = {
+0x60, 0x00, 0xd0, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 
+0x06, 0x06, 0x02, 0x04, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x02, 0x04, 0x0c, 0x06, 0xf8, 0x01};
+static unsigned char courier24_245_bits[] = {
+0x38, 0x02, 0xc8, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 
+0x06, 0x06, 0x02, 0x04, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x02, 0x04, 0x0c, 0x06, 0xf8, 0x01};
+static unsigned char courier24_246_bits[] = {
+0xb0, 0x01, 0xb0, 0x01, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 
+0x06, 0x06, 0x02, 0x04, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x02, 0x04, 0x0c, 0x06, 0xf8, 0x01};
+static unsigned char courier24_247_bits[] = {
+0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00};
+static unsigned char courier24_248_bits[] = {
+0xf8, 0x05, 0x06, 0x06, 0x02, 0x0d, 0x81, 0x08, 0x41, 0x08, 0x31, 0x08, 
+0x1b, 0x08, 0x0e, 0x04, 0x0e, 0x06, 0xfb, 0x01};
+static unsigned char courier24_249_bits[] = {
+0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x03, 
+0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 
+0x04, 0x02, 0x8c, 0x03, 0xf8, 0x0e};
+static unsigned char courier24_250_bits[] = {
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x03, 
+0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 
+0x04, 0x02, 0x8c, 0x03, 0xf8, 0x0e};
+static unsigned char courier24_251_bits[] = {
+0x60, 0x00, 0xd0, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x87, 0x03, 
+0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 
+0x04, 0x02, 0x8c, 0x03, 0xf8, 0x0e};
+static unsigned char courier24_252_bits[] = {
+0xb0, 0x01, 0xb0, 0x01, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x87, 0x03, 
+0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 
+0x04, 0x02, 0x8c, 0x03, 0xf8, 0x0e};
+static unsigned char courier24_253_bits[] = {
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x1e, 
+0x04, 0x04, 0x04, 0x04, 0x08, 0x02, 0x08, 0x03, 0x10, 0x01, 0x90, 0x01, 
+0xa0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 
+0x7f, 0x00};
+static unsigned char courier24_254_bits[] = {
+0x0f, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0xe8, 0x03, 
+0x38, 0x0c, 0x18, 0x08, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 
+0x18, 0x08, 0x38, 0x04, 0xe8, 0x03, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 
+0x7f, 0x00};
+static unsigned char courier24_255_bits[] = {
+0xb0, 0x01, 0xb0, 0x01, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x1e, 
+0x04, 0x04, 0x04, 0x04, 0x08, 0x02, 0x08, 0x03, 0x10, 0x01, 0x90, 0x01, 
+0xa0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 
+0x7f, 0x00};
+static RotFont courier24font[] = {
+{5, 1, 1, courier24_0_bits},
+{5, 1, 1, courier24_1_bits},
+{5, 1, 1, courier24_2_bits},
+{5, 1, 1, courier24_3_bits},
+{5, 1, 1, courier24_4_bits},
+{5, 1, 1, courier24_5_bits},
+{5, 1, 1, courier24_6_bits},
+{5, 1, 1, courier24_7_bits},
+{5, 1, 1, courier24_8_bits},
+{5, 1, 1, courier24_9_bits},
+{5, 1, 1, courier24_10_bits},
+{5, 1, 1, courier24_11_bits},
+{5, 1, 1, courier24_12_bits},
+{5, 1, 1, courier24_13_bits},
+{5, 1, 1, courier24_14_bits},
+{5, 1, 1, courier24_15_bits},
+{5, 1, 1, courier24_16_bits},
+{5, 1, 1, courier24_17_bits},
+{5, 1, 1, courier24_18_bits},
+{5, 1, 1, courier24_19_bits},
+{5, 1, 1, courier24_20_bits},
+{5, 1, 1, courier24_21_bits},
+{5, 1, 1, courier24_22_bits},
+{5, 1, 1, courier24_23_bits},
+{5, 1, 1, courier24_24_bits},
+{5, 1, 1, courier24_25_bits},
+{5, 1, 1, courier24_26_bits},
+{5, 1, 1, courier24_27_bits},
+{5, 1, 1, courier24_28_bits},
+{5, 1, 1, courier24_29_bits},
+{5, 1, 1, courier24_30_bits},
+{5, 1, 1, courier24_31_bits},
+{10, 1, 1, courier24_32_bits},
+{3, 14, 14, courier24_33_bits},
+{6, 7, 14, courier24_34_bits},
+{11, 17, 16, courier24_35_bits},
+{10, 19, 16, courier24_36_bits},
+{12, 15, 15, courier24_37_bits},
+{10, 13, 13, courier24_38_bits},
+{4, 6, 14, courier24_39_bits},
+{4, 18, 16, courier24_40_bits},
+{4, 18, 16, courier24_41_bits},
+{9, 9, 14, courier24_42_bits},
+{11, 11, 13, courier24_43_bits},
+{4, 6, 3, courier24_44_bits},
+{11, 1, 8, courier24_45_bits},
+{4, 3, 3, courier24_46_bits},
+{10, 20, 17, courier24_47_bits},
+{9, 15, 15, courier24_48_bits},
+{10, 15, 15, courier24_49_bits},
+{9, 15, 15, courier24_50_bits},
+{9, 15, 15, courier24_51_bits},
+{10, 15, 15, courier24_52_bits},
+{10, 15, 15, courier24_53_bits},
+{9, 15, 15, courier24_54_bits},
+{10, 15, 15, courier24_55_bits},
+{9, 15, 15, courier24_56_bits},
+{9, 15, 15, courier24_57_bits},
+{4, 9, 9, courier24_58_bits},
+{5, 12, 9, courier24_59_bits},
+{12, 11, 13, courier24_60_bits},
+{11, 5, 10, courier24_61_bits},
+{12, 11, 13, courier24_62_bits},
+{8, 14, 14, courier24_63_bits},
+{13, 13, 13, courier24_64_bits},
+{14, 14, 14, courier24_65_bits},
+{12, 14, 14, courier24_66_bits},
+{12, 14, 14, courier24_67_bits},
+{12, 14, 14, courier24_68_bits},
+{12, 14, 14, courier24_69_bits},
+{11, 14, 14, courier24_70_bits},
+{13, 14, 14, courier24_71_bits},
+{12, 14, 14, courier24_72_bits},
+{10, 14, 14, courier24_73_bits},
+{13, 14, 14, courier24_74_bits},
+{13, 14, 14, courier24_75_bits},
+{12, 14, 14, courier24_76_bits},
+{14, 14, 14, courier24_77_bits},
+{13, 14, 14, courier24_78_bits},
+{12, 14, 14, courier24_79_bits},
+{11, 14, 14, courier24_80_bits},
+{12, 17, 14, courier24_81_bits},
+{13, 14, 14, courier24_82_bits},
+{9, 14, 14, courier24_83_bits},
+{13, 14, 14, courier24_84_bits},
+{13, 14, 14, courier24_85_bits},
+{14, 14, 14, courier24_86_bits},
+{15, 14, 14, courier24_87_bits},
+{13, 14, 14, courier24_88_bits},
+{13, 14, 14, courier24_89_bits},
+{10, 14, 14, courier24_90_bits},
+{4, 18, 16, courier24_91_bits},
+{10, 20, 17, courier24_92_bits},
+{4, 18, 16, courier24_93_bits},
+{11, 11, 14, courier24_94_bits},
+{17, 1, -2, courier24_95_bits},
+{4, 6, 14, courier24_96_bits},
+{11, 10, 10, courier24_97_bits},
+{13, 15, 15, courier24_98_bits},
+{11, 10, 10, courier24_99_bits},
+{13, 15, 15, courier24_100_bits},
+{11, 10, 10, courier24_101_bits},
+{10, 15, 15, courier24_102_bits},
+{12, 14, 10, courier24_103_bits},
+{13, 15, 15, courier24_104_bits},
+{10, 16, 16, courier24_105_bits},
+{8, 20, 16, courier24_106_bits},
+{13, 15, 15, courier24_107_bits},
+{10, 15, 15, courier24_108_bits},
+{15, 10, 10, courier24_109_bits},
+{13, 10, 10, courier24_110_bits},
+{12, 10, 10, courier24_111_bits},
+{13, 14, 10, courier24_112_bits},
+{13, 14, 10, courier24_113_bits},
+{12, 10, 10, courier24_114_bits},
+{10, 10, 10, courier24_115_bits},
+{10, 14, 14, courier24_116_bits},
+{12, 10, 10, courier24_117_bits},
+{13, 10, 10, courier24_118_bits},
+{14, 10, 10, courier24_119_bits},
+{14, 10, 10, courier24_120_bits},
+{13, 14, 10, courier24_121_bits},
+{10, 10, 10, courier24_122_bits},
+{5, 18, 16, courier24_123_bits},
+{1, 21, 16, courier24_124_bits},
+{6, 18, 16, courier24_125_bits},
+{10, 4, 9, courier24_126_bits},
+{5, 1, 1, courier24_127_bits},
+{5, 1, 1, courier24_128_bits},
+{5, 1, 1, courier24_129_bits},
+{5, 1, 1, courier24_130_bits},
+{5, 1, 1, courier24_131_bits},
+{5, 1, 1, courier24_132_bits},
+{5, 1, 1, courier24_133_bits},
+{5, 1, 1, courier24_134_bits},
+{5, 1, 1, courier24_135_bits},
+{5, 1, 1, courier24_136_bits},
+{5, 1, 1, courier24_137_bits},
+{5, 1, 1, courier24_138_bits},
+{5, 1, 1, courier24_139_bits},
+{5, 1, 1, courier24_140_bits},
+{5, 1, 1, courier24_141_bits},
+{5, 1, 1, courier24_142_bits},
+{5, 1, 1, courier24_143_bits},
+{5, 1, 1, courier24_144_bits},
+{5, 1, 1, courier24_145_bits},
+{5, 1, 1, courier24_146_bits},
+{5, 1, 1, courier24_147_bits},
+{5, 1, 1, courier24_148_bits},
+{5, 1, 1, courier24_149_bits},
+{5, 1, 1, courier24_150_bits},
+{5, 1, 1, courier24_151_bits},
+{5, 1, 1, courier24_152_bits},
+{5, 1, 1, courier24_153_bits},
+{5, 1, 1, courier24_154_bits},
+{5, 1, 1, courier24_155_bits},
+{5, 1, 1, courier24_156_bits},
+{5, 1, 1, courier24_157_bits},
+{5, 1, 1, courier24_158_bits},
+{5, 1, 1, courier24_159_bits},
+{5, 1, 1, courier24_160_bits},
+{3, 13, 10, courier24_161_bits},
+{9, 16, 15, courier24_162_bits},
+{11, 15, 15, courier24_163_bits},
+{11, 11, 12, courier24_164_bits},
+{13, 14, 14, courier24_165_bits},
+{1, 21, 16, courier24_166_bits},
+{9, 16, 14, courier24_167_bits},
+{5, 3, 15, courier24_168_bits},
+{14, 14, 14, courier24_169_bits},
+{6, 8, 14, courier24_170_bits},
+{10, 10, 10, courier24_171_bits},
+{10, 6, 10, courier24_172_bits},
+{5, 1, 7, courier24_173_bits},
+{14, 14, 14, courier24_174_bits},
+{8, 1, 14, courier24_175_bits},
+{7, 7, 15, courier24_176_bits},
+{11, 13, 14, courier24_177_bits},
+{6, 9, 15, courier24_178_bits},
+{6, 9, 15, courier24_179_bits},
+{5, 3, 15, courier24_180_bits},
+{12, 14, 10, courier24_181_bits},
+{9, 16, 14, courier24_182_bits},
+{4, 3, 9, courier24_183_bits},
+{4, 4, 1, courier24_184_bits},
+{6, 9, 15, courier24_185_bits},
+{6, 8, 14, courier24_186_bits},
+{10, 10, 10, courier24_187_bits},
+{13, 17, 15, courier24_188_bits},
+{14, 17, 15, courier24_189_bits},
+{14, 17, 15, courier24_190_bits},
+{8, 13, 10, courier24_191_bits},
+{14, 18, 18, courier24_192_bits},
+{14, 18, 18, courier24_193_bits},
+{14, 18, 18, courier24_194_bits},
+{14, 18, 18, courier24_195_bits},
+{14, 18, 18, courier24_196_bits},
+{14, 19, 19, courier24_197_bits},
+{13, 14, 14, courier24_198_bits},
+{12, 17, 14, courier24_199_bits},
+{12, 18, 18, courier24_200_bits},
+{12, 18, 18, courier24_201_bits},
+{12, 18, 18, courier24_202_bits},
+{12, 18, 18, courier24_203_bits},
+{10, 18, 18, courier24_204_bits},
+{10, 18, 18, courier24_205_bits},
+{10, 18, 18, courier24_206_bits},
+{10, 18, 18, courier24_207_bits},
+{12, 14, 14, courier24_208_bits},
+{13, 18, 18, courier24_209_bits},
+{12, 18, 18, courier24_210_bits},
+{12, 18, 18, courier24_211_bits},
+{12, 18, 18, courier24_212_bits},
+{12, 18, 18, courier24_213_bits},
+{12, 18, 18, courier24_214_bits},
+{9, 9, 12, courier24_215_bits},
+{12, 14, 14, courier24_216_bits},
+{13, 18, 18, courier24_217_bits},
+{13, 18, 18, courier24_218_bits},
+{13, 18, 18, courier24_219_bits},
+{13, 18, 18, courier24_220_bits},
+{13, 18, 18, courier24_221_bits},
+{11, 14, 14, courier24_222_bits},
+{10, 15, 15, courier24_223_bits},
+{11, 15, 15, courier24_224_bits},
+{11, 15, 15, courier24_225_bits},
+{11, 15, 15, courier24_226_bits},
+{11, 15, 15, courier24_227_bits},
+{11, 15, 15, courier24_228_bits},
+{11, 15, 15, courier24_229_bits},
+{13, 10, 10, courier24_230_bits},
+{11, 13, 10, courier24_231_bits},
+{11, 15, 15, courier24_232_bits},
+{11, 15, 15, courier24_233_bits},
+{11, 15, 15, courier24_234_bits},
+{11, 15, 15, courier24_235_bits},
+{10, 15, 15, courier24_236_bits},
+{10, 15, 15, courier24_237_bits},
+{10, 15, 15, courier24_238_bits},
+{10, 15, 15, courier24_239_bits},
+{12, 17, 17, courier24_240_bits},
+{13, 15, 15, courier24_241_bits},
+{12, 15, 15, courier24_242_bits},
+{12, 15, 15, courier24_243_bits},
+{12, 15, 15, courier24_244_bits},
+{12, 15, 15, courier24_245_bits},
+{12, 15, 15, courier24_246_bits},
+{11, 11, 13, courier24_247_bits},
+{12, 10, 10, courier24_248_bits},
+{12, 15, 15, courier24_249_bits},
+{12, 15, 15, courier24_250_bits},
+{12, 15, 15, courier24_251_bits},
+{12, 15, 15, courier24_252_bits},
+{13, 19, 15, courier24_253_bits},
+{13, 19, 15, courier24_254_bits},
+{13, 19, 15, courier24_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/courier8.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/courier8.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/courier8.bdf	(revision 12606)
@@ -0,0 +1,2404 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) IBM Corporation 1990,1991. IBM Courier is a Trademark of the IBM Corporation.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -adobe-courier-medium-r-normal--8-77-75-75-m-50-iso8859-1
+SIZE 8 75 75
+FONTBOUNDINGBOX 7 9 -1 -2
+STARTPROPERTIES 25
+FOUNDRY "adobe"
+FAMILY_NAME "courier"
+WEIGHT_NAME "medium"
+SLANT "r"
+SETWIDTH_NAME "normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 8
+POINT_SIZE 77
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "m"
+AVERAGE_WIDTH 50
+CHARSET_REGISTRY "iso8859"
+CHARSET_ENCODING "1"
+FONT "-adobe-courier-medium-r-normal--8-77-75-75-m-50-iso8859-1"
+COPYRIGHT "Copyright (c) IBM Corporation 1990,1991. IBM Courier is a Trademark of the IBM Corporation."
+RAW_PIXEL_SIZE 1000
+RAW_POINT_SIZE 964
+RAW_ASCENT 841
+RAW_DESCENT 288
+RAW_AVERAGE_WIDTH 6000
+FACE_NAME "Couriere."
+DEFAULT_CHAR 0
+FONT_ASCENT 7
+FONT_DESCENT 2
+ENDPROPERTIES
+CHARS 190
+STARTCHAR space
+ENCODING 32
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 0 0 0 0
+ATTRIBUTES 0x0258
+BITMAP
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 4 2 0
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 2 1 2
+ATTRIBUTES 0x0258
+BITMAP
+a0
+a0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+a0
+a0
+e0
+e0
+a0
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 6 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+e0
+e0
+c0
+e0
+e0
+40
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+e0
+f8
+38
+38
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+80
+a0
+e0
+e0
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 2 2 2
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 6 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 6 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+80
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 1
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+a0
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 1
+ATTRIBUTES 0x0258
+BITMAP
+40
+e0
+40
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 2 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 1 0 2
+ATTRIBUTES 0x0258
+BITMAP
+f0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 1 2 0
+ATTRIBUTES 0x0258
+BITMAP
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 7 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+20
+20
+20
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+a0
+a0
+a0
+c0
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+10
+30
+40
+f0
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+60
+20
+c0
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+60
+60
+f0
+30
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+80
+e0
+20
+e0
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+80
+e0
+a0
+e0
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+10
+20
+20
+20
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+a0
+c0
+a0
+e0
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+90
+70
+10
+60
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 3 2 0
+ATTRIBUTES 0x0258
+BITMAP
+80
+00
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 4 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+40
+40
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 3 0 1
+ATTRIBUTES 0x0258
+BITMAP
+60
+c0
+20
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 3 0 1
+ATTRIBUTES 0x0258
+BITMAP
+f0
+00
+f0
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 3 0 1
+ATTRIBUTES 0x0258
+BITMAP
+60
+30
+c0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 4 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+20
+40
+40
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+a8
+e8
+f8
+70
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+50
+70
+d8
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+70
+48
+f0
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+80
+80
+70
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+48
+48
+f0
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+70
+40
+f8
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+e0
+80
+c0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+80
+98
+78
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+d0
+70
+50
+d0
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 4 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+40
+40
+e0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+38
+10
+90
+f0
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+d8
+60
+50
+c8
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+40
+48
+f8
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 6 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+dc
+d8
+a8
+d8
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+d8
+68
+68
+d8
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+88
+88
+70
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+90
+e0
+c0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+70
+88
+88
+70
+70
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+60
+50
+d8
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+c0
+20
+e0
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+20
+20
+70
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+d8
+90
+90
+f0
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+d8
+50
+50
+20
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+d8
+d8
+50
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+d0
+20
+50
+d8
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+50
+20
+70
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+20
+50
+70
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 7 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+c0
+80
+80
+80
+80
+80
+c0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 7 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+40
+40
+40
+20
+20
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 7 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+40
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 3 0 1
+ATTRIBUTES 0x0258
+BITMAP
+60
+e0
+90
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 6 1 -1 -1
+ATTRIBUTES 0x0258
+BITMAP
+fc
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 2 2 2
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+90
+e8
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+f0
+88
+f0
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+80
+70
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+10
+f0
+90
+78
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+a8
+78
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+e0
+80
+80
+e0
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+70
+90
+70
+10
+60
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+70
+50
+d8
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+c0
+40
+e0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 7 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+c0
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+70
+60
+d8
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+a8
+e8
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+50
+d8
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+88
+70
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+f0
+48
+70
+40
+c0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+78
+90
+70
+10
+38
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+80
+e0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+70
+f0
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 4 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+80
+80
+e0
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+d0
+50
+70
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+d8
+50
+20
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+a8
+b8
+50
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+60
+d8
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+d0
+50
+20
+20
+e0
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+40
+e0
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 7 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+40
+80
+80
+80
+80
+80
+40
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 7 2 -2
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 7 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+80
+40
+40
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 1 1 2
+ATTRIBUTES 0x0258
+BITMAP
+e0
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 4 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+e0
+c0
+f0
+40
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+80
+e0
+80
+e0
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+a0
+c0
+b0
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+50
+70
+70
+70
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 7 2 -2
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+00
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+e0
+c0
+e0
+20
+e0
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 1 1 4
+ATTRIBUTES 0x0258
+BITMAP
+c0
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+e8
+88
+70
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 2 1 2
+ATTRIBUTES 0x0258
+BITMAP
+c0
+e0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+c0
+c0
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 2 1 1
+ATTRIBUTES 0x0258
+BITMAP
+e0
+20
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 1 1 2
+ATTRIBUTES 0x0258
+BITMAP
+c0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+f8
+f8
+70
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 1 1 4
+ATTRIBUTES 0x0258
+BITMAP
+e0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 2
+ATTRIBUTES 0x0258
+BITMAP
+e0
+a0
+40
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 4 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+40
+40
+e0
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 2
+ATTRIBUTES 0x0258
+BITMAP
+e0
+20
+e0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 2
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+e0
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 1 1 4
+ATTRIBUTES 0x0258
+BITMAP
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+d0
+50
+70
+40
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+e0
+e0
+60
+60
+60
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 1 2 2
+ATTRIBUTES 0x0258
+BITMAP
+80
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 2 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 3 1 2
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+c0
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 2 1 2
+ATTRIBUTES 0x0258
+BITMAP
+e0
+e0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+60
+60
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+c8
+50
+d8
+38
+58
+58
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+c8
+50
+f8
+28
+48
+98
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+c8
+50
+d0
+38
+58
+58
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 4 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+80
+e0
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+70
+50
+70
+d8
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+70
+50
+70
+d8
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+50
+70
+d8
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+00
+70
+50
+70
+d8
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+50
+70
+d8
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+60
+00
+70
+50
+70
+d8
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+30
+78
+f8
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+78
+80
+80
+70
+30
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+f8
+70
+40
+f8
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+f8
+70
+40
+f8
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+f8
+70
+40
+f8
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+f8
+70
+40
+f8
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 6 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+e0
+40
+40
+e0
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 6 1 0
+ATTRIBUTES 0x0258
+BITMAP
+80
+00
+e0
+40
+40
+e0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 6 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+00
+e0
+40
+40
+e0
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 6 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+00
+e0
+40
+40
+e0
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+e8
+48
+f0
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+00
+d8
+68
+68
+d8
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+70
+88
+88
+70
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+70
+88
+88
+70
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+88
+88
+70
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+00
+70
+88
+88
+70
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+88
+88
+70
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 1
+ATTRIBUTES 0x0258
+BITMAP
+a0
+60
+a0
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+a8
+a8
+f0
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+d8
+90
+90
+f0
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+d8
+90
+90
+f0
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+d8
+90
+90
+f0
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+d8
+90
+90
+f0
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+f8
+50
+20
+70
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+90
+e0
+c0
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+a0
+e0
+a0
+e0
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+70
+90
+e8
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+70
+90
+e8
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+90
+e8
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+00
+70
+90
+e8
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+90
+e8
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+90
+e8
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+f8
+f8
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+78
+80
+70
+20
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+70
+a8
+78
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+70
+a8
+78
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+a8
+78
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+a8
+78
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+c0
+40
+e0
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+80
+00
+c0
+40
+e0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+00
+c0
+40
+e0
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+00
+c0
+40
+e0
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+20
+10
+f8
+88
+70
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+00
+f0
+50
+d8
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+70
+88
+70
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+70
+88
+70
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+88
+70
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+00
+70
+88
+70
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+88
+70
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 4 2 0
+ATTRIBUTES 0x0258
+BITMAP
+80
+00
+00
+80
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+e8
+b0
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+d0
+50
+70
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+d0
+50
+70
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+d0
+50
+70
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+d0
+50
+70
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+d0
+50
+20
+20
+e0
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 7 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+70
+48
+70
+40
+c0
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+d0
+50
+20
+20
+e0
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/courier8.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/courier8.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/courier8.h	(revision 12606)
@@ -0,0 +1,769 @@
+static unsigned char courier8_0_bits[] = {
+0x00};
+static unsigned char courier8_1_bits[] = {
+0x00};
+static unsigned char courier8_2_bits[] = {
+0x00};
+static unsigned char courier8_3_bits[] = {
+0x00};
+static unsigned char courier8_4_bits[] = {
+0x00};
+static unsigned char courier8_5_bits[] = {
+0x00};
+static unsigned char courier8_6_bits[] = {
+0x00};
+static unsigned char courier8_7_bits[] = {
+0x00};
+static unsigned char courier8_8_bits[] = {
+0x00};
+static unsigned char courier8_9_bits[] = {
+0x00};
+static unsigned char courier8_10_bits[] = {
+0x00};
+static unsigned char courier8_11_bits[] = {
+0x00};
+static unsigned char courier8_12_bits[] = {
+0x00};
+static unsigned char courier8_13_bits[] = {
+0x00};
+static unsigned char courier8_14_bits[] = {
+0x00};
+static unsigned char courier8_15_bits[] = {
+0x00};
+static unsigned char courier8_16_bits[] = {
+0x00};
+static unsigned char courier8_17_bits[] = {
+0x00};
+static unsigned char courier8_18_bits[] = {
+0x00};
+static unsigned char courier8_19_bits[] = {
+0x00};
+static unsigned char courier8_20_bits[] = {
+0x00};
+static unsigned char courier8_21_bits[] = {
+0x00};
+static unsigned char courier8_22_bits[] = {
+0x00};
+static unsigned char courier8_23_bits[] = {
+0x00};
+static unsigned char courier8_24_bits[] = {
+0x00};
+static unsigned char courier8_25_bits[] = {
+0x00};
+static unsigned char courier8_26_bits[] = {
+0x00};
+static unsigned char courier8_27_bits[] = {
+0x00};
+static unsigned char courier8_28_bits[] = {
+0x00};
+static unsigned char courier8_29_bits[] = {
+0x00};
+static unsigned char courier8_30_bits[] = {
+0x00};
+static unsigned char courier8_31_bits[] = {
+0x00};
+static unsigned char courier8_32_bits[] = {
+0x00};
+static unsigned char courier8_33_bits[] = {
+0x01, 0x01, 0x01, 0x01};
+static unsigned char courier8_34_bits[] = {
+0x05, 0x05};
+static unsigned char courier8_35_bits[] = {
+0x05, 0x05, 0x07, 0x07, 0x05};
+static unsigned char courier8_36_bits[] = {
+0x07, 0x07, 0x03, 0x07, 0x07, 0x02};
+static unsigned char courier8_37_bits[] = {
+0x07, 0x07, 0x1f, 0x1c, 0x1c};
+static unsigned char courier8_38_bits[] = {
+0x02, 0x01, 0x05, 0x07, 0x07};
+static unsigned char courier8_39_bits[] = {
+0x01, 0x01};
+static unsigned char courier8_40_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier8_41_bits[] = {
+0x01, 0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char courier8_42_bits[] = {
+0x02, 0x02, 0x05};
+static unsigned char courier8_43_bits[] = {
+0x02, 0x07, 0x02};
+static unsigned char courier8_44_bits[] = {
+0x01, 0x01};
+static unsigned char courier8_45_bits[] = {
+0x0f};
+static unsigned char courier8_46_bits[] = {
+0x01};
+static unsigned char courier8_47_bits[] = {
+0x04, 0x04, 0x04, 0x02, 0x02, 0x01, 0x01};
+static unsigned char courier8_48_bits[] = {
+0x03, 0x05, 0x05, 0x05, 0x03};
+static unsigned char courier8_49_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x07};
+static unsigned char courier8_50_bits[] = {
+0x06, 0x08, 0x0c, 0x02, 0x0f};
+static unsigned char courier8_51_bits[] = {
+0x03, 0x02, 0x06, 0x04, 0x03};
+static unsigned char courier8_52_bits[] = {
+0x04, 0x06, 0x06, 0x0f, 0x0c};
+static unsigned char courier8_53_bits[] = {
+0x03, 0x01, 0x07, 0x04, 0x07};
+static unsigned char courier8_54_bits[] = {
+0x06, 0x01, 0x07, 0x05, 0x07};
+static unsigned char courier8_55_bits[] = {
+0x0f, 0x08, 0x04, 0x04, 0x04};
+static unsigned char courier8_56_bits[] = {
+0x07, 0x05, 0x03, 0x05, 0x07};
+static unsigned char courier8_57_bits[] = {
+0x06, 0x09, 0x0e, 0x08, 0x06};
+static unsigned char courier8_58_bits[] = {
+0x01, 0x00, 0x01};
+static unsigned char courier8_59_bits[] = {
+0x02, 0x00, 0x02, 0x02};
+static unsigned char courier8_60_bits[] = {
+0x06, 0x03, 0x04};
+static unsigned char courier8_61_bits[] = {
+0x0f, 0x00, 0x0f};
+static unsigned char courier8_62_bits[] = {
+0x06, 0x0c, 0x03};
+static unsigned char courier8_63_bits[] = {
+0x07, 0x04, 0x02, 0x02};
+static unsigned char courier8_64_bits[] = {
+0x0e, 0x15, 0x17, 0x1f, 0x0e};
+static unsigned char courier8_65_bits[] = {
+0x0e, 0x0a, 0x0e, 0x1b};
+static unsigned char courier8_66_bits[] = {
+0x0f, 0x0e, 0x12, 0x0f};
+static unsigned char courier8_67_bits[] = {
+0x1e, 0x01, 0x01, 0x0e};
+static unsigned char courier8_68_bits[] = {
+0x1f, 0x12, 0x12, 0x0f};
+static unsigned char courier8_69_bits[] = {
+0x1f, 0x0e, 0x02, 0x1f};
+static unsigned char courier8_70_bits[] = {
+0x0f, 0x07, 0x01, 0x03};
+static unsigned char courier8_71_bits[] = {
+0x1e, 0x01, 0x19, 0x1e};
+static unsigned char courier8_72_bits[] = {
+0x0b, 0x0e, 0x0a, 0x0b};
+static unsigned char courier8_73_bits[] = {
+0x07, 0x02, 0x02, 0x07};
+static unsigned char courier8_74_bits[] = {
+0x1c, 0x08, 0x09, 0x0f};
+static unsigned char courier8_75_bits[] = {
+0x1b, 0x06, 0x0a, 0x13};
+static unsigned char courier8_76_bits[] = {
+0x07, 0x02, 0x12, 0x1f};
+static unsigned char courier8_77_bits[] = {
+0x3b, 0x1b, 0x15, 0x1b};
+static unsigned char courier8_78_bits[] = {
+0x1b, 0x16, 0x16, 0x1b};
+static unsigned char courier8_79_bits[] = {
+0x0e, 0x11, 0x11, 0x0e};
+static unsigned char courier8_80_bits[] = {
+0x0f, 0x09, 0x07, 0x03};
+static unsigned char courier8_81_bits[] = {
+0x0e, 0x11, 0x11, 0x0e, 0x0e};
+static unsigned char courier8_82_bits[] = {
+0x0f, 0x06, 0x0a, 0x1b};
+static unsigned char courier8_83_bits[] = {
+0x0f, 0x03, 0x04, 0x07};
+static unsigned char courier8_84_bits[] = {
+0x1f, 0x04, 0x04, 0x0e};
+static unsigned char courier8_85_bits[] = {
+0x1b, 0x09, 0x09, 0x0f};
+static unsigned char courier8_86_bits[] = {
+0x1b, 0x0a, 0x0a, 0x04};
+static unsigned char courier8_87_bits[] = {
+0x1f, 0x1b, 0x1b, 0x0a};
+static unsigned char courier8_88_bits[] = {
+0x0b, 0x04, 0x0a, 0x1b};
+static unsigned char courier8_89_bits[] = {
+0x1f, 0x0a, 0x04, 0x0e};
+static unsigned char courier8_90_bits[] = {
+0x0f, 0x04, 0x0a, 0x0e};
+static unsigned char courier8_91_bits[] = {
+0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03};
+static unsigned char courier8_92_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x02, 0x04, 0x04};
+static unsigned char courier8_93_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03};
+static unsigned char courier8_94_bits[] = {
+0x06, 0x07, 0x09};
+static unsigned char courier8_95_bits[] = {
+0x3f};
+static unsigned char courier8_96_bits[] = {
+0x01, 0x01};
+static unsigned char courier8_97_bits[] = {
+0x0e, 0x09, 0x17};
+static unsigned char courier8_98_bits[] = {
+0x01, 0x01, 0x0f, 0x11, 0x0f};
+static unsigned char courier8_99_bits[] = {
+0x1e, 0x01, 0x0e};
+static unsigned char courier8_100_bits[] = {
+0x0c, 0x08, 0x0f, 0x09, 0x1e};
+static unsigned char courier8_101_bits[] = {
+0x0e, 0x15, 0x1e};
+static unsigned char courier8_102_bits[] = {
+0x07, 0x07, 0x01, 0x01, 0x07};
+static unsigned char courier8_103_bits[] = {
+0x0e, 0x09, 0x0e, 0x08, 0x06};
+static unsigned char courier8_104_bits[] = {
+0x03, 0x02, 0x0e, 0x0a, 0x1b};
+static unsigned char courier8_105_bits[] = {
+0x02, 0x00, 0x03, 0x02, 0x07};
+static unsigned char courier8_106_bits[] = {
+0x02, 0x00, 0x03, 0x02, 0x02, 0x02, 0x03};
+static unsigned char courier8_107_bits[] = {
+0x03, 0x02, 0x0e, 0x06, 0x1b};
+static unsigned char courier8_108_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x07};
+static unsigned char courier8_109_bits[] = {
+0x1f, 0x15, 0x17};
+static unsigned char courier8_110_bits[] = {
+0x0f, 0x0a, 0x1b};
+static unsigned char courier8_111_bits[] = {
+0x0e, 0x11, 0x0e};
+static unsigned char courier8_112_bits[] = {
+0x0f, 0x12, 0x0e, 0x02, 0x03};
+static unsigned char courier8_113_bits[] = {
+0x1e, 0x09, 0x0e, 0x08, 0x1c};
+static unsigned char courier8_114_bits[] = {
+0x07, 0x01, 0x07};
+static unsigned char courier8_115_bits[] = {
+0x1e, 0x0e, 0x0f};
+static unsigned char courier8_116_bits[] = {
+0x07, 0x01, 0x01, 0x07};
+static unsigned char courier8_117_bits[] = {
+0x0b, 0x0a, 0x0e};
+static unsigned char courier8_118_bits[] = {
+0x1b, 0x0a, 0x04};
+static unsigned char courier8_119_bits[] = {
+0x15, 0x1d, 0x0a};
+static unsigned char courier8_120_bits[] = {
+0x0f, 0x06, 0x1b};
+static unsigned char courier8_121_bits[] = {
+0x0b, 0x0a, 0x04, 0x04, 0x07};
+static unsigned char courier8_122_bits[] = {
+0x07, 0x02, 0x07};
+static unsigned char courier8_123_bits[] = {
+0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02};
+static unsigned char courier8_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier8_125_bits[] = {
+0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03};
+static unsigned char courier8_126_bits[] = {
+0x07};
+static unsigned char courier8_127_bits[] = {
+0x00};
+static unsigned char courier8_128_bits[] = {
+0x00};
+static unsigned char courier8_129_bits[] = {
+0x00};
+static unsigned char courier8_130_bits[] = {
+0x00};
+static unsigned char courier8_131_bits[] = {
+0x00};
+static unsigned char courier8_132_bits[] = {
+0x00};
+static unsigned char courier8_133_bits[] = {
+0x00};
+static unsigned char courier8_134_bits[] = {
+0x00};
+static unsigned char courier8_135_bits[] = {
+0x00};
+static unsigned char courier8_136_bits[] = {
+0x00};
+static unsigned char courier8_137_bits[] = {
+0x00};
+static unsigned char courier8_138_bits[] = {
+0x00};
+static unsigned char courier8_139_bits[] = {
+0x00};
+static unsigned char courier8_140_bits[] = {
+0x00};
+static unsigned char courier8_141_bits[] = {
+0x00};
+static unsigned char courier8_142_bits[] = {
+0x00};
+static unsigned char courier8_143_bits[] = {
+0x00};
+static unsigned char courier8_144_bits[] = {
+0x00};
+static unsigned char courier8_145_bits[] = {
+0x00};
+static unsigned char courier8_146_bits[] = {
+0x00};
+static unsigned char courier8_147_bits[] = {
+0x00};
+static unsigned char courier8_148_bits[] = {
+0x00};
+static unsigned char courier8_149_bits[] = {
+0x00};
+static unsigned char courier8_150_bits[] = {
+0x00};
+static unsigned char courier8_151_bits[] = {
+0x00};
+static unsigned char courier8_152_bits[] = {
+0x00};
+static unsigned char courier8_153_bits[] = {
+0x00};
+static unsigned char courier8_154_bits[] = {
+0x00};
+static unsigned char courier8_155_bits[] = {
+0x00};
+static unsigned char courier8_156_bits[] = {
+0x00};
+static unsigned char courier8_157_bits[] = {
+0x00};
+static unsigned char courier8_158_bits[] = {
+0x00};
+static unsigned char courier8_159_bits[] = {
+0x00};
+static unsigned char courier8_160_bits[] = {
+0x00};
+static unsigned char courier8_161_bits[] = {
+0x01, 0x01, 0x01, 0x01};
+static unsigned char courier8_162_bits[] = {
+0x02, 0x07, 0x03, 0x0f, 0x02};
+static unsigned char courier8_163_bits[] = {
+0x06, 0x01, 0x07, 0x01, 0x07};
+static unsigned char courier8_164_bits[] = {
+0x07, 0x05, 0x03, 0x0d};
+static unsigned char courier8_165_bits[] = {
+0x1f, 0x0a, 0x0e, 0x0e, 0x0e};
+static unsigned char courier8_166_bits[] = {
+0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01};
+static unsigned char courier8_167_bits[] = {
+0x07, 0x03, 0x07, 0x04, 0x07};
+static unsigned char courier8_168_bits[] = {
+0x03};
+static unsigned char courier8_169_bits[] = {
+0x0e, 0x17, 0x11, 0x0e};
+static unsigned char courier8_170_bits[] = {
+0x03, 0x07};
+static unsigned char courier8_171_bits[] = {
+0x06, 0x03, 0x03};
+static unsigned char courier8_172_bits[] = {
+0x07, 0x04};
+static unsigned char courier8_173_bits[] = {
+0x03};
+static unsigned char courier8_174_bits[] = {
+0x1e, 0x1f, 0x1f, 0x0e};
+static unsigned char courier8_175_bits[] = {
+0x07};
+static unsigned char courier8_176_bits[] = {
+0x07, 0x05, 0x02};
+static unsigned char courier8_177_bits[] = {
+0x07, 0x02, 0x02, 0x07};
+static unsigned char courier8_178_bits[] = {
+0x07, 0x04, 0x07};
+static unsigned char courier8_179_bits[] = {
+0x03, 0x02, 0x07};
+static unsigned char courier8_180_bits[] = {
+0x01};
+static unsigned char courier8_181_bits[] = {
+0x0b, 0x0a, 0x0e, 0x02};
+static unsigned char courier8_182_bits[] = {
+0x07, 0x07, 0x06, 0x06, 0x06};
+static unsigned char courier8_183_bits[] = {
+0x01};
+static unsigned char courier8_184_bits[] = {
+0x01, 0x01};
+static unsigned char courier8_185_bits[] = {
+0x03, 0x02, 0x03};
+static unsigned char courier8_186_bits[] = {
+0x07, 0x07};
+static unsigned char courier8_187_bits[] = {
+0x03, 0x06, 0x06};
+static unsigned char courier8_188_bits[] = {
+0x13, 0x0a, 0x1b, 0x1c, 0x1a, 0x1a};
+static unsigned char courier8_189_bits[] = {
+0x13, 0x0a, 0x1f, 0x14, 0x12, 0x19};
+static unsigned char courier8_190_bits[] = {
+0x13, 0x0a, 0x0b, 0x1c, 0x1a, 0x1a};
+static unsigned char courier8_191_bits[] = {
+0x02, 0x02, 0x01, 0x07};
+static unsigned char courier8_192_bits[] = {
+0x08, 0x00, 0x0e, 0x0a, 0x0e, 0x1b};
+static unsigned char courier8_193_bits[] = {
+0x02, 0x00, 0x0e, 0x0a, 0x0e, 0x1b};
+static unsigned char courier8_194_bits[] = {
+0x06, 0x00, 0x0e, 0x0a, 0x0e, 0x1b};
+static unsigned char courier8_195_bits[] = {
+0x0c, 0x00, 0x0e, 0x0a, 0x0e, 0x1b};
+static unsigned char courier8_196_bits[] = {
+0x06, 0x00, 0x0e, 0x0a, 0x0e, 0x1b};
+static unsigned char courier8_197_bits[] = {
+0x04, 0x06, 0x00, 0x0e, 0x0a, 0x0e, 0x1b};
+static unsigned char courier8_198_bits[] = {
+0x1e, 0x0c, 0x1e, 0x1f};
+static unsigned char courier8_199_bits[] = {
+0x1e, 0x01, 0x01, 0x0e, 0x0c};
+static unsigned char courier8_200_bits[] = {
+0x08, 0x00, 0x1f, 0x0e, 0x02, 0x1f};
+static unsigned char courier8_201_bits[] = {
+0x02, 0x00, 0x1f, 0x0e, 0x02, 0x1f};
+static unsigned char courier8_202_bits[] = {
+0x06, 0x00, 0x1f, 0x0e, 0x02, 0x1f};
+static unsigned char courier8_203_bits[] = {
+0x06, 0x00, 0x1f, 0x0e, 0x02, 0x1f};
+static unsigned char courier8_204_bits[] = {
+0x04, 0x00, 0x07, 0x02, 0x02, 0x07};
+static unsigned char courier8_205_bits[] = {
+0x01, 0x00, 0x07, 0x02, 0x02, 0x07};
+static unsigned char courier8_206_bits[] = {
+0x03, 0x00, 0x07, 0x02, 0x02, 0x07};
+static unsigned char courier8_207_bits[] = {
+0x03, 0x00, 0x07, 0x02, 0x02, 0x07};
+static unsigned char courier8_208_bits[] = {
+0x1f, 0x17, 0x12, 0x0f};
+static unsigned char courier8_209_bits[] = {
+0x0c, 0x00, 0x1b, 0x16, 0x16, 0x1b};
+static unsigned char courier8_210_bits[] = {
+0x08, 0x00, 0x0e, 0x11, 0x11, 0x0e};
+static unsigned char courier8_211_bits[] = {
+0x02, 0x00, 0x0e, 0x11, 0x11, 0x0e};
+static unsigned char courier8_212_bits[] = {
+0x06, 0x00, 0x0e, 0x11, 0x11, 0x0e};
+static unsigned char courier8_213_bits[] = {
+0x0c, 0x00, 0x0e, 0x11, 0x11, 0x0e};
+static unsigned char courier8_214_bits[] = {
+0x06, 0x00, 0x0e, 0x11, 0x11, 0x0e};
+static unsigned char courier8_215_bits[] = {
+0x05, 0x06, 0x05};
+static unsigned char courier8_216_bits[] = {
+0x1e, 0x15, 0x15, 0x0f};
+static unsigned char courier8_217_bits[] = {
+0x08, 0x00, 0x1b, 0x09, 0x09, 0x0f};
+static unsigned char courier8_218_bits[] = {
+0x02, 0x00, 0x1b, 0x09, 0x09, 0x0f};
+static unsigned char courier8_219_bits[] = {
+0x06, 0x00, 0x1b, 0x09, 0x09, 0x0f};
+static unsigned char courier8_220_bits[] = {
+0x06, 0x00, 0x1b, 0x09, 0x09, 0x0f};
+static unsigned char courier8_221_bits[] = {
+0x02, 0x00, 0x1f, 0x0a, 0x04, 0x0e};
+static unsigned char courier8_222_bits[] = {
+0x07, 0x09, 0x07, 0x03};
+static unsigned char courier8_223_bits[] = {
+0x07, 0x05, 0x07, 0x05, 0x07};
+static unsigned char courier8_224_bits[] = {
+0x08, 0x00, 0x0e, 0x09, 0x17};
+static unsigned char courier8_225_bits[] = {
+0x02, 0x00, 0x0e, 0x09, 0x17};
+static unsigned char courier8_226_bits[] = {
+0x06, 0x00, 0x0e, 0x09, 0x17};
+static unsigned char courier8_227_bits[] = {
+0x0c, 0x00, 0x0e, 0x09, 0x17};
+static unsigned char courier8_228_bits[] = {
+0x06, 0x00, 0x0e, 0x09, 0x17};
+static unsigned char courier8_229_bits[] = {
+0x06, 0x00, 0x0e, 0x09, 0x17};
+static unsigned char courier8_230_bits[] = {
+0x0e, 0x1f, 0x1f};
+static unsigned char courier8_231_bits[] = {
+0x1e, 0x01, 0x0e, 0x04};
+static unsigned char courier8_232_bits[] = {
+0x08, 0x00, 0x0e, 0x15, 0x1e};
+static unsigned char courier8_233_bits[] = {
+0x02, 0x00, 0x0e, 0x15, 0x1e};
+static unsigned char courier8_234_bits[] = {
+0x06, 0x00, 0x0e, 0x15, 0x1e};
+static unsigned char courier8_235_bits[] = {
+0x06, 0x00, 0x0e, 0x15, 0x1e};
+static unsigned char courier8_236_bits[] = {
+0x04, 0x00, 0x03, 0x02, 0x07};
+static unsigned char courier8_237_bits[] = {
+0x01, 0x00, 0x03, 0x02, 0x07};
+static unsigned char courier8_238_bits[] = {
+0x03, 0x00, 0x03, 0x02, 0x07};
+static unsigned char courier8_239_bits[] = {
+0x03, 0x00, 0x03, 0x02, 0x07};
+static unsigned char courier8_240_bits[] = {
+0x04, 0x04, 0x08, 0x1f, 0x11, 0x0e};
+static unsigned char courier8_241_bits[] = {
+0x0c, 0x00, 0x0f, 0x0a, 0x1b};
+static unsigned char courier8_242_bits[] = {
+0x08, 0x00, 0x0e, 0x11, 0x0e};
+static unsigned char courier8_243_bits[] = {
+0x02, 0x00, 0x0e, 0x11, 0x0e};
+static unsigned char courier8_244_bits[] = {
+0x06, 0x00, 0x0e, 0x11, 0x0e};
+static unsigned char courier8_245_bits[] = {
+0x0c, 0x00, 0x0e, 0x11, 0x0e};
+static unsigned char courier8_246_bits[] = {
+0x06, 0x00, 0x0e, 0x11, 0x0e};
+static unsigned char courier8_247_bits[] = {
+0x01, 0x00, 0x00, 0x01};
+static unsigned char courier8_248_bits[] = {
+0x1e, 0x17, 0x0d};
+static unsigned char courier8_249_bits[] = {
+0x08, 0x00, 0x0b, 0x0a, 0x0e};
+static unsigned char courier8_250_bits[] = {
+0x02, 0x00, 0x0b, 0x0a, 0x0e};
+static unsigned char courier8_251_bits[] = {
+0x06, 0x00, 0x0b, 0x0a, 0x0e};
+static unsigned char courier8_252_bits[] = {
+0x06, 0x00, 0x0b, 0x0a, 0x0e};
+static unsigned char courier8_253_bits[] = {
+0x02, 0x00, 0x0b, 0x0a, 0x04, 0x04, 0x07};
+static unsigned char courier8_254_bits[] = {
+0x03, 0x02, 0x0e, 0x12, 0x0e, 0x02, 0x03};
+static unsigned char courier8_255_bits[] = {
+0x06, 0x00, 0x0b, 0x0a, 0x04, 0x04, 0x07};
+static RotFont courier8font[] = {
+{5, 1, 1, courier8_0_bits},
+{5, 1, 1, courier8_1_bits},
+{5, 1, 1, courier8_2_bits},
+{5, 1, 1, courier8_3_bits},
+{5, 1, 1, courier8_4_bits},
+{5, 1, 1, courier8_5_bits},
+{5, 1, 1, courier8_6_bits},
+{5, 1, 1, courier8_7_bits},
+{5, 1, 1, courier8_8_bits},
+{5, 1, 1, courier8_9_bits},
+{5, 1, 1, courier8_10_bits},
+{5, 1, 1, courier8_11_bits},
+{5, 1, 1, courier8_12_bits},
+{5, 1, 1, courier8_13_bits},
+{5, 1, 1, courier8_14_bits},
+{5, 1, 1, courier8_15_bits},
+{5, 1, 1, courier8_16_bits},
+{5, 1, 1, courier8_17_bits},
+{5, 1, 1, courier8_18_bits},
+{5, 1, 1, courier8_19_bits},
+{5, 1, 1, courier8_20_bits},
+{5, 1, 1, courier8_21_bits},
+{5, 1, 1, courier8_22_bits},
+{5, 1, 1, courier8_23_bits},
+{5, 1, 1, courier8_24_bits},
+{5, 1, 1, courier8_25_bits},
+{5, 1, 1, courier8_26_bits},
+{5, 1, 1, courier8_27_bits},
+{5, 1, 1, courier8_28_bits},
+{5, 1, 1, courier8_29_bits},
+{5, 1, 1, courier8_30_bits},
+{5, 1, 1, courier8_31_bits},
+{5, 1, 1, courier8_32_bits},
+{1, 4, 4, courier8_33_bits},
+{3, 2, 4, courier8_34_bits},
+{3, 5, 5, courier8_35_bits},
+{3, 6, 5, courier8_36_bits},
+{5, 5, 5, courier8_37_bits},
+{3, 5, 5, courier8_38_bits},
+{1, 2, 4, courier8_39_bits},
+{2, 6, 5, courier8_40_bits},
+{2, 6, 5, courier8_41_bits},
+{3, 3, 4, courier8_42_bits},
+{3, 3, 4, courier8_43_bits},
+{1, 2, 1, courier8_44_bits},
+{4, 1, 3, courier8_45_bits},
+{1, 1, 1, courier8_46_bits},
+{3, 7, 6, courier8_47_bits},
+{3, 5, 5, courier8_48_bits},
+{3, 5, 5, courier8_49_bits},
+{4, 5, 5, courier8_50_bits},
+{3, 5, 5, courier8_51_bits},
+{4, 5, 5, courier8_52_bits},
+{3, 5, 5, courier8_53_bits},
+{3, 5, 5, courier8_54_bits},
+{4, 5, 5, courier8_55_bits},
+{3, 5, 5, courier8_56_bits},
+{4, 5, 5, courier8_57_bits},
+{1, 3, 3, courier8_58_bits},
+{2, 4, 3, courier8_59_bits},
+{4, 3, 4, courier8_60_bits},
+{4, 3, 4, courier8_61_bits},
+{4, 3, 4, courier8_62_bits},
+{3, 4, 4, courier8_63_bits},
+{5, 5, 5, courier8_64_bits},
+{5, 4, 4, courier8_65_bits},
+{5, 4, 4, courier8_66_bits},
+{5, 4, 4, courier8_67_bits},
+{5, 4, 4, courier8_68_bits},
+{5, 4, 4, courier8_69_bits},
+{4, 4, 4, courier8_70_bits},
+{5, 4, 4, courier8_71_bits},
+{4, 4, 4, courier8_72_bits},
+{3, 4, 4, courier8_73_bits},
+{5, 4, 4, courier8_74_bits},
+{5, 4, 4, courier8_75_bits},
+{5, 4, 4, courier8_76_bits},
+{6, 4, 4, courier8_77_bits},
+{5, 4, 4, courier8_78_bits},
+{5, 4, 4, courier8_79_bits},
+{4, 4, 4, courier8_80_bits},
+{5, 5, 4, courier8_81_bits},
+{5, 4, 4, courier8_82_bits},
+{4, 4, 4, courier8_83_bits},
+{5, 4, 4, courier8_84_bits},
+{5, 4, 4, courier8_85_bits},
+{5, 4, 4, courier8_86_bits},
+{5, 4, 4, courier8_87_bits},
+{5, 4, 4, courier8_88_bits},
+{5, 4, 4, courier8_89_bits},
+{4, 4, 4, courier8_90_bits},
+{2, 7, 6, courier8_91_bits},
+{3, 7, 6, courier8_92_bits},
+{2, 7, 6, courier8_93_bits},
+{4, 3, 4, courier8_94_bits},
+{6, 1, 0, courier8_95_bits},
+{1, 2, 4, courier8_96_bits},
+{5, 3, 3, courier8_97_bits},
+{5, 5, 5, courier8_98_bits},
+{5, 3, 3, courier8_99_bits},
+{5, 5, 5, courier8_100_bits},
+{5, 3, 3, courier8_101_bits},
+{3, 5, 5, courier8_102_bits},
+{4, 5, 3, courier8_103_bits},
+{5, 5, 5, courier8_104_bits},
+{3, 5, 5, courier8_105_bits},
+{2, 7, 5, courier8_106_bits},
+{5, 5, 5, courier8_107_bits},
+{3, 5, 5, courier8_108_bits},
+{5, 3, 3, courier8_109_bits},
+{5, 3, 3, courier8_110_bits},
+{5, 3, 3, courier8_111_bits},
+{5, 5, 3, courier8_112_bits},
+{5, 5, 3, courier8_113_bits},
+{3, 3, 3, courier8_114_bits},
+{5, 3, 3, courier8_115_bits},
+{3, 4, 4, courier8_116_bits},
+{4, 3, 3, courier8_117_bits},
+{5, 3, 3, courier8_118_bits},
+{5, 3, 3, courier8_119_bits},
+{5, 3, 3, courier8_120_bits},
+{4, 5, 3, courier8_121_bits},
+{3, 3, 3, courier8_122_bits},
+{2, 7, 6, courier8_123_bits},
+{1, 7, 5, courier8_124_bits},
+{2, 7, 6, courier8_125_bits},
+{3, 1, 3, courier8_126_bits},
+{5, 1, 1, courier8_127_bits},
+{5, 1, 1, courier8_128_bits},
+{5, 1, 1, courier8_129_bits},
+{5, 1, 1, courier8_130_bits},
+{5, 1, 1, courier8_131_bits},
+{5, 1, 1, courier8_132_bits},
+{5, 1, 1, courier8_133_bits},
+{5, 1, 1, courier8_134_bits},
+{5, 1, 1, courier8_135_bits},
+{5, 1, 1, courier8_136_bits},
+{5, 1, 1, courier8_137_bits},
+{5, 1, 1, courier8_138_bits},
+{5, 1, 1, courier8_139_bits},
+{5, 1, 1, courier8_140_bits},
+{5, 1, 1, courier8_141_bits},
+{5, 1, 1, courier8_142_bits},
+{5, 1, 1, courier8_143_bits},
+{5, 1, 1, courier8_144_bits},
+{5, 1, 1, courier8_145_bits},
+{5, 1, 1, courier8_146_bits},
+{5, 1, 1, courier8_147_bits},
+{5, 1, 1, courier8_148_bits},
+{5, 1, 1, courier8_149_bits},
+{5, 1, 1, courier8_150_bits},
+{5, 1, 1, courier8_151_bits},
+{5, 1, 1, courier8_152_bits},
+{5, 1, 1, courier8_153_bits},
+{5, 1, 1, courier8_154_bits},
+{5, 1, 1, courier8_155_bits},
+{5, 1, 1, courier8_156_bits},
+{5, 1, 1, courier8_157_bits},
+{5, 1, 1, courier8_158_bits},
+{5, 1, 1, courier8_159_bits},
+{5, 1, 1, courier8_160_bits},
+{1, 4, 3, courier8_161_bits},
+{4, 5, 5, courier8_162_bits},
+{3, 5, 5, courier8_163_bits},
+{4, 4, 4, courier8_164_bits},
+{5, 5, 5, courier8_165_bits},
+{1, 7, 5, courier8_166_bits},
+{3, 5, 4, courier8_167_bits},
+{2, 1, 5, courier8_168_bits},
+{5, 4, 4, courier8_169_bits},
+{3, 2, 4, courier8_170_bits},
+{3, 3, 3, courier8_171_bits},
+{3, 2, 3, courier8_172_bits},
+{2, 1, 3, courier8_173_bits},
+{5, 4, 4, courier8_174_bits},
+{3, 1, 5, courier8_175_bits},
+{3, 3, 5, courier8_176_bits},
+{3, 4, 4, courier8_177_bits},
+{3, 3, 5, courier8_178_bits},
+{3, 3, 5, courier8_179_bits},
+{2, 1, 5, courier8_180_bits},
+{4, 4, 3, courier8_181_bits},
+{3, 5, 4, courier8_182_bits},
+{1, 1, 3, courier8_183_bits},
+{1, 2, 1, courier8_184_bits},
+{2, 3, 5, courier8_185_bits},
+{3, 2, 4, courier8_186_bits},
+{3, 3, 3, courier8_187_bits},
+{5, 6, 5, courier8_188_bits},
+{5, 6, 5, courier8_189_bits},
+{5, 6, 5, courier8_190_bits},
+{3, 4, 3, courier8_191_bits},
+{5, 6, 6, courier8_192_bits},
+{5, 6, 6, courier8_193_bits},
+{5, 6, 6, courier8_194_bits},
+{5, 6, 6, courier8_195_bits},
+{5, 6, 6, courier8_196_bits},
+{5, 7, 7, courier8_197_bits},
+{5, 4, 4, courier8_198_bits},
+{5, 5, 4, courier8_199_bits},
+{5, 6, 6, courier8_200_bits},
+{5, 6, 6, courier8_201_bits},
+{5, 6, 6, courier8_202_bits},
+{5, 6, 6, courier8_203_bits},
+{3, 6, 6, courier8_204_bits},
+{3, 6, 6, courier8_205_bits},
+{3, 6, 6, courier8_206_bits},
+{3, 6, 6, courier8_207_bits},
+{5, 4, 4, courier8_208_bits},
+{5, 6, 6, courier8_209_bits},
+{5, 6, 6, courier8_210_bits},
+{5, 6, 6, courier8_211_bits},
+{5, 6, 6, courier8_212_bits},
+{5, 6, 6, courier8_213_bits},
+{5, 6, 6, courier8_214_bits},
+{3, 3, 4, courier8_215_bits},
+{5, 4, 4, courier8_216_bits},
+{5, 6, 6, courier8_217_bits},
+{5, 6, 6, courier8_218_bits},
+{5, 6, 6, courier8_219_bits},
+{5, 6, 6, courier8_220_bits},
+{5, 6, 6, courier8_221_bits},
+{4, 4, 4, courier8_222_bits},
+{3, 5, 5, courier8_223_bits},
+{5, 5, 5, courier8_224_bits},
+{5, 5, 5, courier8_225_bits},
+{5, 5, 5, courier8_226_bits},
+{5, 5, 5, courier8_227_bits},
+{5, 5, 5, courier8_228_bits},
+{5, 5, 5, courier8_229_bits},
+{5, 3, 3, courier8_230_bits},
+{5, 4, 3, courier8_231_bits},
+{5, 5, 5, courier8_232_bits},
+{5, 5, 5, courier8_233_bits},
+{5, 5, 5, courier8_234_bits},
+{5, 5, 5, courier8_235_bits},
+{3, 5, 5, courier8_236_bits},
+{3, 5, 5, courier8_237_bits},
+{3, 5, 5, courier8_238_bits},
+{3, 5, 5, courier8_239_bits},
+{5, 6, 6, courier8_240_bits},
+{5, 5, 5, courier8_241_bits},
+{5, 5, 5, courier8_242_bits},
+{5, 5, 5, courier8_243_bits},
+{5, 5, 5, courier8_244_bits},
+{5, 5, 5, courier8_245_bits},
+{5, 5, 5, courier8_246_bits},
+{1, 4, 4, courier8_247_bits},
+{5, 3, 3, courier8_248_bits},
+{4, 5, 5, courier8_249_bits},
+{4, 5, 5, courier8_250_bits},
+{4, 5, 5, courier8_251_bits},
+{4, 5, 5, courier8_252_bits},
+{4, 7, 5, courier8_253_bits},
+{5, 7, 5, courier8_254_bits},
+{4, 7, 5, courier8_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/fixed.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/fixed.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/fixed.h	(revision 12606)
@@ -0,0 +1,765 @@
+static unsigned char fixed_0_bits[] = {};
+static unsigned char fixed_1_bits[] = {
+0x4, 0xe, 0xe, 0x1f, 0xe, 0xe, 0x04};
+static unsigned char fixed_2_bits[] = {
+0x15, 0xa, 0x15, 0xa, 0x15, 0xa, 0x15};
+static unsigned char fixed_3_bits[] = {
+0x9, 0x9, 0xf, 0x9, 0x9, 0x1e, 0x8, 0x8, 0x08};
+static unsigned char fixed_4_bits[] = {
+0x7, 0x1, 0x3, 0x1, 0x1d, 0x4, 0xc, 0x4, 0x04};
+static unsigned char fixed_5_bits[] = {
+0xe, 0x1, 0x1, 0xe, 0xe, 0x12, 0xe, 0x12, 0x12};
+static unsigned char fixed_6_bits[] = {
+0x1, 0x1, 0x1, 0xf, 0x1e, 0x2, 0xe, 0x2, 0x02};
+static unsigned char fixed_7_bits[] = {
+0x2, 0x5, 0x02};
+static unsigned char fixed_8_bits[] = {
+0x4, 0x4, 0x1f, 0x4, 0x4, 0x1f};
+static unsigned char fixed_9_bits[] = {
+0x9, 0xb, 0xb, 0xd, 0x9, 0x2, 0x2, 0x2, 0x1e};
+static unsigned char fixed_10_bits[] = {
+0x9, 0x9, 0x6, 0x2, 0x1e, 0x8, 0x8, 0x8, 0x08};
+static unsigned char fixed_11_bits[] = {
+0x8, 0x8, 0x8, 0x8, 0x0f};
+static unsigned char fixed_12_bits[] = {
+0xf, 0x8, 0x8, 0x8, 0x8, 0x08};
+static unsigned char fixed_13_bits[] = {
+0x7, 0x1, 0x1, 0x1, 0x1, 0x01};
+static unsigned char fixed_14_bits[] = {
+0x1, 0x1, 0x1, 0x1, 0x07};
+static unsigned char fixed_15_bits[] = {
+0x8, 0x8, 0x8, 0x8, 0x3f, 0x8, 0x8, 0x8, 0x8, 0x08};
+static unsigned char fixed_16_bits[] = {
+0x3f};
+static unsigned char fixed_17_bits[] = {
+0x3f};
+static unsigned char fixed_18_bits[] = {
+0x3f};
+static unsigned char fixed_19_bits[] = {
+0x3f};
+static unsigned char fixed_20_bits[] = {
+0x3f};
+static unsigned char fixed_21_bits[] = {
+0x1, 0x1, 0x1, 0x1, 0x7, 0x1, 0x1, 0x1, 0x1, 0x01};
+static unsigned char fixed_22_bits[] = {
+0x8, 0x8, 0x8, 0x8, 0xf, 0x8, 0x8, 0x8, 0x8, 0x08};
+static unsigned char fixed_23_bits[] = {
+0x8, 0x8, 0x8, 0x8, 0x3f};
+static unsigned char fixed_24_bits[] = {
+0x3f, 0x8, 0x8, 0x8, 0x8, 0x08};
+static unsigned char fixed_25_bits[] = {
+0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x01};
+static unsigned char fixed_26_bits[] = {
+0x10, 0x8, 0x2, 0x1, 0x2, 0x8, 0x10, 0x1f};
+static unsigned char fixed_27_bits[] = {
+0x1, 0x2, 0x8, 0x10, 0x8, 0x2, 0x1, 0x1f};
+static unsigned char fixed_28_bits[] = {
+0x1f, 0xa, 0xa, 0xa, 0x0a};
+static unsigned char fixed_29_bits[] = {
+0x10, 0x8, 0x1f, 0x4, 0x1f, 0x2, 0x01};
+static unsigned char fixed_30_bits[] = {
+0xc, 0x12, 0x2, 0x7, 0x2, 0x12, 0x0d};
+static unsigned char fixed_31_bits[] = {
+0x01};
+static unsigned char fixed_32_bits[] = {};
+static unsigned char fixed_33_bits[] = {
+0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x01};
+static unsigned char fixed_34_bits[] = {
+0x5, 0x5, 0x05};
+static unsigned char fixed_35_bits[] = {
+0xa, 0xa, 0x1f, 0xa, 0x1f, 0xa, 0x0a};
+static unsigned char fixed_36_bits[] = {
+0x4, 0xe, 0x5, 0xe, 0x14, 0xe, 0x04};
+static unsigned char fixed_37_bits[] = {
+0x12, 0x15, 0xa, 0x4, 0xa, 0x15, 0x09};
+static unsigned char fixed_38_bits[] = {
+0x2, 0x5, 0x5, 0x2, 0x15, 0x9, 0x16};
+static unsigned char fixed_39_bits[] = {
+0x6, 0x2, 0x01};
+static unsigned char fixed_40_bits[] = {
+0x4, 0x2, 0x1, 0x1, 0x1, 0x2, 0x04};
+static unsigned char fixed_41_bits[] = {
+0x1, 0x2, 0x4, 0x4, 0x4, 0x2, 0x01};
+static unsigned char fixed_42_bits[] = {
+0x11, 0xa, 0x1f, 0xa, 0x11};
+static unsigned char fixed_43_bits[] = {
+0x4, 0x4, 0x1f, 0x4, 0x04};
+static unsigned char fixed_44_bits[] = {
+0x6, 0x2, 0x01};
+static unsigned char fixed_45_bits[] = {
+0x1f};
+static unsigned char fixed_46_bits[] = {
+0x2, 0x7, 0x02};
+static unsigned char fixed_47_bits[] = {
+0x10, 0x10, 0x8, 0x4, 0x2, 0x1, 0x01};
+static unsigned char fixed_48_bits[] = {
+0x4, 0xa, 0x11, 0x11, 0x11, 0xa, 0x04};
+static unsigned char fixed_49_bits[] = {
+0x4, 0x6, 0x5, 0x4, 0x4, 0x4, 0x1f};
+static unsigned char fixed_50_bits[] = {
+0xe, 0x11, 0x10, 0xc, 0x2, 0x1, 0x1f};
+static unsigned char fixed_51_bits[] = {
+0x1f, 0x10, 0x8, 0xc, 0x10, 0x11, 0x0e};
+static unsigned char fixed_52_bits[] = {
+0x8, 0xc, 0xa, 0x9, 0x1f, 0x8, 0x08};
+static unsigned char fixed_53_bits[] = {
+0x1f, 0x1, 0xd, 0x13, 0x10, 0x11, 0x0e};
+static unsigned char fixed_54_bits[] = {
+0xc, 0x2, 0x1, 0xd, 0x13, 0x11, 0x0e};
+static unsigned char fixed_55_bits[] = {
+0x1f, 0x10, 0x8, 0x8, 0x4, 0x2, 0x02};
+static unsigned char fixed_56_bits[] = {
+0xe, 0x11, 0x11, 0xe, 0x11, 0x11, 0x0e};
+static unsigned char fixed_57_bits[] = {
+0xe, 0x11, 0x19, 0x16, 0x10, 0x8, 0x06};
+static unsigned char fixed_58_bits[] = {
+0x2, 0x7, 0x2, 0x0, 0x2, 0x7, 0x02};
+static unsigned char fixed_59_bits[] = {
+0x2, 0x7, 0x2, 0x0, 0x6, 0x2, 0x01};
+static unsigned char fixed_60_bits[] = {
+0x8, 0x4, 0x2, 0x1, 0x2, 0x4, 0x08};
+static unsigned char fixed_61_bits[] = {
+0x1f, 0x0, 0x1f};
+static unsigned char fixed_62_bits[] = {
+0x1, 0x2, 0x4, 0x8, 0x4, 0x2, 0x01};
+static unsigned char fixed_63_bits[] = {
+0xe, 0x11, 0x8, 0x4, 0x4, 0x0, 0x04};
+static unsigned char fixed_64_bits[] = {
+0xe, 0x11, 0x19, 0x15, 0xd, 0x1, 0x0e};
+static unsigned char fixed_65_bits[] = {
+0x4, 0xa, 0x11, 0x11, 0x1f, 0x11, 0x11};
+static unsigned char fixed_66_bits[] = {
+0xf, 0x12, 0x12, 0xe, 0x12, 0x12, 0x0f};
+static unsigned char fixed_67_bits[] = {
+0xe, 0x11, 0x1, 0x1, 0x1, 0x11, 0x0e};
+static unsigned char fixed_68_bits[] = {
+0xf, 0x12, 0x12, 0x12, 0x12, 0x12, 0x0f};
+static unsigned char fixed_69_bits[] = {
+0x1f, 0x1, 0x1, 0xf, 0x1, 0x1, 0x1f};
+static unsigned char fixed_70_bits[] = {
+0x1f, 0x1, 0x1, 0xf, 0x1, 0x1, 0x01};
+static unsigned char fixed_71_bits[] = {
+0xe, 0x11, 0x1, 0x1, 0x19, 0x11, 0x0e};
+static unsigned char fixed_72_bits[] = {
+0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11};
+static unsigned char fixed_73_bits[] = {
+0x7, 0x2, 0x2, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_74_bits[] = {
+0x1c, 0x10, 0x10, 0x10, 0x10, 0x11, 0x0e};
+static unsigned char fixed_75_bits[] = {
+0x11, 0x9, 0x5, 0x3, 0x5, 0x9, 0x11};
+static unsigned char fixed_76_bits[] = {
+0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1f};
+static unsigned char fixed_77_bits[] = {
+0x11, 0x11, 0x1b, 0x15, 0x11, 0x11, 0x11};
+static unsigned char fixed_78_bits[] = {
+0x11, 0x11, 0x13, 0x15, 0x19, 0x11, 0x11};
+static unsigned char fixed_79_bits[] = {
+0xe, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_80_bits[] = {
+0xf, 0x11, 0x11, 0xf, 0x1, 0x1, 0x01};
+static unsigned char fixed_81_bits[] = {
+0xe, 0x11, 0x11, 0x11, 0x11, 0x15, 0xe, 0x10};
+static unsigned char fixed_82_bits[] = {
+0xf, 0x11, 0x11, 0xf, 0x5, 0x9, 0x11};
+static unsigned char fixed_83_bits[] = {
+0xe, 0x11, 0x1, 0xe, 0x10, 0x11, 0x0e};
+static unsigned char fixed_84_bits[] = {
+0x1f, 0x4, 0x4, 0x4, 0x4, 0x4, 0x04};
+static unsigned char fixed_85_bits[] = {
+0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_86_bits[] = {
+0x11, 0x11, 0x11, 0xa, 0xa, 0xa, 0x04};
+static unsigned char fixed_87_bits[] = {
+0x11, 0x11, 0x11, 0x15, 0x15, 0x1b, 0x11};
+static unsigned char fixed_88_bits[] = {
+0x11, 0x11, 0xa, 0x4, 0xa, 0x11, 0x11};
+static unsigned char fixed_89_bits[] = {
+0x11, 0x11, 0xa, 0x4, 0x4, 0x4, 0x04};
+static unsigned char fixed_90_bits[] = {
+0x1f, 0x10, 0x8, 0x4, 0x2, 0x1, 0x1f};
+static unsigned char fixed_91_bits[] = {
+0x7, 0x1, 0x1, 0x1, 0x1, 0x1, 0x07};
+static unsigned char fixed_92_bits[] = {
+0x1, 0x1, 0x2, 0x4, 0x8, 0x10, 0x10};
+static unsigned char fixed_93_bits[] = {
+0x7, 0x4, 0x4, 0x4, 0x4, 0x4, 0x07};
+static unsigned char fixed_94_bits[] = {
+0x4, 0xa, 0x11};
+static unsigned char fixed_95_bits[] = {
+0x1f};
+static unsigned char fixed_96_bits[] = {
+0x3, 0x2, 0x04};
+static unsigned char fixed_97_bits[] = {
+0xe, 0x10, 0x1e, 0x11, 0x1e};
+static unsigned char fixed_98_bits[] = {
+0x1, 0x1, 0xd, 0x13, 0x11, 0x13, 0x0d};
+static unsigned char fixed_99_bits[] = {
+0xe, 0x11, 0x1, 0x11, 0x0e};
+static unsigned char fixed_100_bits[] = {
+0x10, 0x10, 0x16, 0x19, 0x11, 0x19, 0x16};
+static unsigned char fixed_101_bits[] = {
+0xe, 0x11, 0x1f, 0x1, 0x0e};
+static unsigned char fixed_102_bits[] = {
+0xc, 0x12, 0x2, 0xf, 0x2, 0x2, 0x02};
+static unsigned char fixed_103_bits[] = {
+0x16, 0x9, 0x6, 0x1, 0xe, 0x11, 0x0e};
+static unsigned char fixed_104_bits[] = {
+0x1, 0x1, 0xd, 0x13, 0x11, 0x11, 0x11};
+static unsigned char fixed_105_bits[] = {
+0x2, 0x0, 0x3, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_106_bits[] = {
+0x8, 0x0, 0xc, 0x8, 0x8, 0x8, 0x9, 0x9, 0x06};
+static unsigned char fixed_107_bits[] = {
+0x1, 0x1, 0x11, 0x9, 0x7, 0x9, 0x11};
+static unsigned char fixed_108_bits[] = {
+0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_109_bits[] = {
+0xb, 0x15, 0x15, 0x15, 0x11};
+static unsigned char fixed_110_bits[] = {
+0xd, 0x13, 0x11, 0x11, 0x11};
+static unsigned char fixed_111_bits[] = {
+0xe, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_112_bits[] = {
+0xd, 0x13, 0x13, 0xd, 0x1, 0x1, 0x01};
+static unsigned char fixed_113_bits[] = {
+0x16, 0x19, 0x19, 0x16, 0x10, 0x10, 0x10};
+static unsigned char fixed_114_bits[] = {
+0xd, 0x13, 0x1, 0x1, 0x01};
+static unsigned char fixed_115_bits[] = {
+0xe, 0x1, 0xe, 0x10, 0x0f};
+static unsigned char fixed_116_bits[] = {
+0x2, 0x2, 0xf, 0x2, 0x2, 0x12, 0x0c};
+static unsigned char fixed_117_bits[] = {
+0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char fixed_118_bits[] = {
+0x11, 0x11, 0xa, 0xa, 0x04};
+static unsigned char fixed_119_bits[] = {
+0x11, 0x11, 0x15, 0x15, 0x0a};
+static unsigned char fixed_120_bits[] = {
+0x11, 0xa, 0x4, 0xa, 0x11};
+static unsigned char fixed_121_bits[] = {
+0x11, 0x11, 0x19, 0x16, 0x10, 0x11, 0x0e};
+static unsigned char fixed_122_bits[] = {
+0x1f, 0x8, 0x4, 0x2, 0x1f};
+static unsigned char fixed_123_bits[] = {
+0xc, 0x2, 0x4, 0x3, 0x4, 0x2, 0x0c};
+static unsigned char fixed_124_bits[] = {
+0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x01};
+static unsigned char fixed_125_bits[] = {
+0x3, 0x4, 0x2, 0xc, 0x2, 0x4, 0x03};
+static unsigned char fixed_126_bits[] = {
+0x12, 0x15, 0x09};
+static unsigned char fixed_127_bits[] = {};
+static unsigned char fixed_128_bits[] = {
+0x00};
+static unsigned char fixed_129_bits[] = {
+0x00};
+static unsigned char fixed_130_bits[] = {
+0x00};
+static unsigned char fixed_131_bits[] = {
+0x00};
+static unsigned char fixed_132_bits[] = {
+0x00};
+static unsigned char fixed_133_bits[] = {
+0x00};
+static unsigned char fixed_134_bits[] = {
+0x00};
+static unsigned char fixed_135_bits[] = {
+0x00};
+static unsigned char fixed_136_bits[] = {
+0x00};
+static unsigned char fixed_137_bits[] = {
+0x00};
+static unsigned char fixed_138_bits[] = {
+0x00};
+static unsigned char fixed_139_bits[] = {
+0x00};
+static unsigned char fixed_140_bits[] = {
+0x00};
+static unsigned char fixed_141_bits[] = {
+0x00};
+static unsigned char fixed_142_bits[] = {
+0x00};
+static unsigned char fixed_143_bits[] = {
+0x00};
+static unsigned char fixed_144_bits[] = {
+0x00};
+static unsigned char fixed_145_bits[] = {
+0x00};
+static unsigned char fixed_146_bits[] = {
+0x00};
+static unsigned char fixed_147_bits[] = {
+0x00};
+static unsigned char fixed_148_bits[] = {
+0x00};
+static unsigned char fixed_149_bits[] = {
+0x00};
+static unsigned char fixed_150_bits[] = {
+0x00};
+static unsigned char fixed_151_bits[] = {
+0x00};
+static unsigned char fixed_152_bits[] = {
+0x00};
+static unsigned char fixed_153_bits[] = {
+0x00};
+static unsigned char fixed_154_bits[] = {
+0x00};
+static unsigned char fixed_155_bits[] = {
+0x00};
+static unsigned char fixed_156_bits[] = {
+0x00};
+static unsigned char fixed_157_bits[] = {
+0x00};
+static unsigned char fixed_158_bits[] = {
+0x00};
+static unsigned char fixed_159_bits[] = {
+0x00};
+static unsigned char fixed_160_bits[] = {};
+static unsigned char fixed_161_bits[] = {
+0x1, 0x0, 0x1, 0x1, 0x1, 0x1, 0x01};
+static unsigned char fixed_162_bits[] = {
+0x4, 0x1e, 0x5, 0x5, 0x5, 0x1e, 0x04};
+static unsigned char fixed_163_bits[] = {
+0xc, 0x12, 0x2, 0x7, 0x2, 0x12, 0x0d};
+static unsigned char fixed_164_bits[] = {
+0x11, 0xe, 0xa, 0xe, 0x11};
+static unsigned char fixed_165_bits[] = {
+0x11, 0x11, 0xa, 0x4, 0x1f, 0x4, 0x4, 0x04};
+static unsigned char fixed_166_bits[] = {
+0x1, 0x1, 0x1, 0x0, 0x1, 0x1, 0x01};
+static unsigned char fixed_167_bits[] = {
+0xe, 0x1, 0x7, 0x9, 0x12, 0x1c, 0x10, 0x0e};
+static unsigned char fixed_168_bits[] = {
+0x05};
+static unsigned char fixed_169_bits[] = {
+0xe, 0x11, 0x15, 0x13, 0x15, 0x11, 0x0e};
+static unsigned char fixed_170_bits[] = {
+0xe, 0x9, 0xd, 0xa, 0x0, 0x0f};
+static unsigned char fixed_171_bits[] = {
+0x24, 0x12, 0x9, 0x12, 0x24};
+static unsigned char fixed_172_bits[] = {
+0xf, 0x08};
+static unsigned char fixed_173_bits[] = {
+0x1f};
+static unsigned char fixed_174_bits[] = {
+0xe, 0x11, 0x17, 0x13, 0x13, 0x11, 0x0e};
+static unsigned char fixed_175_bits[] = {
+0x1f};
+static unsigned char fixed_176_bits[] = {
+0x2, 0x5, 0x02};
+static unsigned char fixed_177_bits[] = {
+0x4, 0x4, 0x1f, 0x4, 0x4, 0x1f};
+static unsigned char fixed_178_bits[] = {
+0x6, 0x9, 0x4, 0x2, 0x0f};
+static unsigned char fixed_179_bits[] = {
+0x7, 0x8, 0x6, 0x8, 0x07};
+static unsigned char fixed_180_bits[] = {
+0x6, 0x03};
+static unsigned char fixed_181_bits[] = {
+0x11, 0x11, 0x11, 0x13, 0xd, 0x01};
+static unsigned char fixed_182_bits[] = {
+0x1e, 0x17, 0x17, 0x16, 0x14, 0x14, 0x14};
+static unsigned char fixed_183_bits[] = {
+0x01};
+static unsigned char fixed_184_bits[] = {
+0x2, 0x01};
+static unsigned char fixed_185_bits[] = {
+0x2, 0x3, 0x2, 0x2, 0x07};
+static unsigned char fixed_186_bits[] = {
+0x6, 0x9, 0x9, 0x6, 0x0, 0x0f};
+static unsigned char fixed_187_bits[] = {
+0x9, 0x12, 0x24, 0x12, 0x09};
+static unsigned char fixed_188_bits[] = {
+0x2, 0x3, 0x2, 0x2, 0x27, 0x30, 0x28, 0x3c, 0x20};
+static unsigned char fixed_189_bits[] = {
+0x2, 0x3, 0x2, 0x2, 0x17, 0x28, 0x20, 0x10, 0x38};
+static unsigned char fixed_190_bits[] = {
+0x3, 0x4, 0x2, 0x4, 0x13, 0x18, 0x14, 0x1e, 0x10};
+static unsigned char fixed_191_bits[] = {
+0x4, 0x0, 0x4, 0x4, 0x2, 0x11, 0x0e};
+static unsigned char fixed_192_bits[] = {
+0x2, 0x4, 0xe, 0x11, 0x11, 0x1f, 0x11, 0x11};
+static unsigned char fixed_193_bits[] = {
+0x8, 0x4, 0xe, 0x11, 0x11, 0x1f, 0x11, 0x11};
+static unsigned char fixed_194_bits[] = {
+0x4, 0xa, 0xe, 0x11, 0x11, 0x1f, 0x11, 0x11};
+static unsigned char fixed_195_bits[] = {
+0x12, 0xd, 0xe, 0x11, 0x11, 0x1f, 0x11, 0x11};
+static unsigned char fixed_196_bits[] = {
+0xa, 0x0, 0xe, 0x11, 0x11, 0x1f, 0x11, 0x11};
+static unsigned char fixed_197_bits[] = {
+0x4, 0xa, 0xe, 0x11, 0x11, 0x1f, 0x11, 0x11};
+static unsigned char fixed_198_bits[] = {
+0x3c, 0xa, 0x9, 0x39, 0xf, 0x9, 0x39};
+static unsigned char fixed_199_bits[] = {
+0xe, 0x11, 0x1, 0x1, 0x1, 0x11, 0xe, 0x4, 0x02};
+static unsigned char fixed_200_bits[] = {
+0x2, 0x1f, 0x1, 0x1, 0xf, 0x1, 0x1, 0x1f};
+static unsigned char fixed_201_bits[] = {
+0x8, 0x1f, 0x1, 0x1, 0xf, 0x1, 0x1, 0x1f};
+static unsigned char fixed_202_bits[] = {
+0x4, 0x1f, 0x1, 0x1, 0xf, 0x1, 0x1, 0x1f};
+static unsigned char fixed_203_bits[] = {
+0xa, 0x1f, 0x1, 0x1, 0xf, 0x1, 0x1, 0x1f};
+static unsigned char fixed_204_bits[] = {
+0x1, 0x7, 0x2, 0x2, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_205_bits[] = {
+0x4, 0x7, 0x2, 0x2, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_206_bits[] = {
+0x2, 0x7, 0x2, 0x2, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_207_bits[] = {
+0x5, 0x7, 0x2, 0x2, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_208_bits[] = {
+0xf, 0x12, 0x12, 0x17, 0x12, 0x12, 0x0f};
+static unsigned char fixed_209_bits[] = {
+0xc, 0x11, 0x11, 0x13, 0x15, 0x19, 0x11, 0x11};
+static unsigned char fixed_210_bits[] = {
+0x2, 0xe, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_211_bits[] = {
+0x8, 0xe, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_212_bits[] = {
+0x4, 0xe, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_213_bits[] = {
+0xe, 0xe, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_214_bits[] = {
+0xa, 0xe, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_215_bits[] = {
+0x11, 0xa, 0x4, 0xa, 0x11};
+static unsigned char fixed_216_bits[] = {
+0xe, 0x19, 0x19, 0x15, 0x13, 0x13, 0x0e};
+static unsigned char fixed_217_bits[] = {
+0x2, 0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_218_bits[] = {
+0x8, 0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_219_bits[] = {
+0x4, 0x1b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_220_bits[] = {
+0xa, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_221_bits[] = {
+0x8, 0x15, 0x11, 0xa, 0x4, 0x4, 0x4, 0x04};
+static unsigned char fixed_222_bits[] = {
+0x1, 0xf, 0x11, 0xf, 0x1, 0x1, 0x01};
+static unsigned char fixed_223_bits[] = {
+0xe, 0x11, 0x11, 0xf, 0x11, 0x11, 0xf, 0x01};
+static unsigned char fixed_224_bits[] = {
+0x2, 0x4, 0xe, 0x10, 0x1e, 0x11, 0x1e};
+static unsigned char fixed_225_bits[] = {
+0x8, 0x4, 0xe, 0x10, 0x1e, 0x11, 0x1e};
+static unsigned char fixed_226_bits[] = {
+0x4, 0xa, 0xe, 0x10, 0x1e, 0x11, 0x1e};
+static unsigned char fixed_227_bits[] = {
+0x14, 0xa, 0xe, 0x10, 0x1e, 0x11, 0x1e};
+static unsigned char fixed_228_bits[] = {
+0xa, 0x0, 0xe, 0x10, 0x1e, 0x11, 0x1e};
+static unsigned char fixed_229_bits[] = {
+0x4, 0xa, 0x4, 0xe, 0x10, 0x1e, 0x11, 0x1e};
+static unsigned char fixed_230_bits[] = {
+0x1e, 0x28, 0x3e, 0x9, 0x3e};
+static unsigned char fixed_231_bits[] = {
+0xe, 0x11, 0x1, 0x11, 0xe, 0x4, 0x02};
+static unsigned char fixed_232_bits[] = {
+0x2, 0x4, 0xe, 0x11, 0x1f, 0x1, 0x0e};
+static unsigned char fixed_233_bits[] = {
+0x8, 0x4, 0xe, 0x11, 0x1f, 0x1, 0x0e};
+static unsigned char fixed_234_bits[] = {
+0x4, 0xa, 0xe, 0x11, 0x1f, 0x1, 0x0e};
+static unsigned char fixed_235_bits[] = {
+0xa, 0x0, 0xe, 0x11, 0x1f, 0x1, 0x0e};
+static unsigned char fixed_236_bits[] = {
+0x1, 0x2, 0x0, 0x3, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_237_bits[] = {
+0x2, 0x1, 0x0, 0x3, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_238_bits[] = {
+0x2, 0x5, 0x0, 0x3, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_239_bits[] = {
+0x5, 0x0, 0x3, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_240_bits[] = {
+0x3, 0xc, 0xe, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_241_bits[] = {
+0x14, 0xa, 0xd, 0x13, 0x11, 0x11, 0x11};
+static unsigned char fixed_242_bits[] = {
+0x2, 0x4, 0xe, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_243_bits[] = {
+0x8, 0x4, 0xe, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_244_bits[] = {
+0x4, 0xa, 0xe, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_245_bits[] = {
+0x14, 0xa, 0xe, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_246_bits[] = {
+0xa, 0x0, 0xe, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_247_bits[] = {
+0x4, 0x0, 0x1f, 0x0, 0x04};
+static unsigned char fixed_248_bits[] = {
+0x1e, 0x19, 0x15, 0x13, 0x0f};
+static unsigned char fixed_249_bits[] = {
+0x2, 0x4, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char fixed_250_bits[] = {
+0x8, 0x4, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char fixed_251_bits[] = {
+0x4, 0xa, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char fixed_252_bits[] = {
+0xa, 0x0, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char fixed_253_bits[] = {
+0x8, 0x4, 0x11, 0x11, 0x19, 0x16, 0x10, 0x11, 0x0e};
+static unsigned char fixed_254_bits[] = {
+0x1, 0xf, 0x11, 0x11, 0x11, 0xf, 0x1, 0x01};
+static unsigned char fixed_255_bits[] = {
+0xa, 0x0, 0x11, 0x11, 0x19, 0x16, 0x10, 0x11, 0x0e};
+static RotFont fixedfont[] = {
+{0, 0, 0, fixed_0_bits},
+{5, 7, 7, fixed_1_bits},
+{5, 7, 7, fixed_2_bits},
+{5, 9, 7, fixed_3_bits},
+{5, 9, 7, fixed_4_bits},
+{5, 9, 7, fixed_5_bits},
+{5, 9, 7, fixed_6_bits},
+{3, 3, 7, fixed_7_bits},
+{5, 6, 6, fixed_8_bits},
+{5, 9, 7, fixed_9_bits},
+{5, 9, 7, fixed_10_bits},
+{4, 5, 8, fixed_11_bits},
+{4, 6, 4, fixed_12_bits},
+{3, 6, 4, fixed_13_bits},
+{3, 5, 8, fixed_14_bits},
+{6, 10, 8, fixed_15_bits},
+{6, 1, 8, fixed_16_bits},
+{6, 1, 6, fixed_17_bits},
+{6, 1, 4, fixed_18_bits},
+{6, 1, 2, fixed_19_bits},
+{6, 1, 0, fixed_20_bits},
+{3, 10, 8, fixed_21_bits},
+{4, 10, 8, fixed_22_bits},
+{6, 5, 8, fixed_23_bits},
+{6, 6, 4, fixed_24_bits},
+{1, 10, 8, fixed_25_bits},
+{5, 8, 7, fixed_26_bits},
+{5, 8, 7, fixed_27_bits},
+{5, 5, 5, fixed_28_bits},
+{5, 7, 7, fixed_29_bits},
+{5, 7, 7, fixed_30_bits},
+{1, 1, 4, fixed_31_bits},
+{0, 0, 0, fixed_32_bits},
+{1, 7, 7, fixed_33_bits},
+{3, 3, 7, fixed_34_bits},
+{5, 7, 7, fixed_35_bits},
+{5, 7, 7, fixed_36_bits},
+{5, 7, 7, fixed_37_bits},
+{5, 7, 7, fixed_38_bits},
+{3, 3, 7, fixed_39_bits},
+{3, 7, 7, fixed_40_bits},
+{3, 7, 7, fixed_41_bits},
+{5, 5, 6, fixed_42_bits},
+{5, 5, 6, fixed_43_bits},
+{3, 3, 2, fixed_44_bits},
+{5, 1, 4, fixed_45_bits},
+{3, 3, 2, fixed_46_bits},
+{5, 7, 7, fixed_47_bits},
+{5, 7, 7, fixed_48_bits},
+{5, 7, 7, fixed_49_bits},
+{5, 7, 7, fixed_50_bits},
+{5, 7, 7, fixed_51_bits},
+{5, 7, 7, fixed_52_bits},
+{5, 7, 7, fixed_53_bits},
+{5, 7, 7, fixed_54_bits},
+{5, 7, 7, fixed_55_bits},
+{5, 7, 7, fixed_56_bits},
+{5, 7, 7, fixed_57_bits},
+{3, 7, 6, fixed_58_bits},
+{3, 7, 6, fixed_59_bits},
+{4, 7, 7, fixed_60_bits},
+{5, 3, 5, fixed_61_bits},
+{4, 7, 7, fixed_62_bits},
+{5, 7, 7, fixed_63_bits},
+{5, 7, 7, fixed_64_bits},
+{5, 7, 7, fixed_65_bits},
+{5, 7, 7, fixed_66_bits},
+{5, 7, 7, fixed_67_bits},
+{5, 7, 7, fixed_68_bits},
+{5, 7, 7, fixed_69_bits},
+{5, 7, 7, fixed_70_bits},
+{5, 7, 7, fixed_71_bits},
+{5, 7, 7, fixed_72_bits},
+{3, 7, 7, fixed_73_bits},
+{5, 7, 7, fixed_74_bits},
+{5, 7, 7, fixed_75_bits},
+{5, 7, 7, fixed_76_bits},
+{5, 7, 7, fixed_77_bits},
+{5, 7, 7, fixed_78_bits},
+{5, 7, 7, fixed_79_bits},
+{5, 7, 7, fixed_80_bits},
+{5, 8, 7, fixed_81_bits},
+{5, 7, 7, fixed_82_bits},
+{5, 7, 7, fixed_83_bits},
+{5, 7, 7, fixed_84_bits},
+{5, 7, 7, fixed_85_bits},
+{5, 7, 7, fixed_86_bits},
+{5, 7, 7, fixed_87_bits},
+{5, 7, 7, fixed_88_bits},
+{5, 7, 7, fixed_89_bits},
+{5, 7, 7, fixed_90_bits},
+{3, 7, 7, fixed_91_bits},
+{5, 7, 7, fixed_92_bits},
+{3, 7, 7, fixed_93_bits},
+{5, 3, 7, fixed_94_bits},
+{5, 1, 0, fixed_95_bits},
+{3, 3, 7, fixed_96_bits},
+{5, 5, 5, fixed_97_bits},
+{5, 7, 7, fixed_98_bits},
+{5, 5, 5, fixed_99_bits},
+{5, 7, 7, fixed_100_bits},
+{5, 5, 5, fixed_101_bits},
+{5, 7, 7, fixed_102_bits},
+{5, 7, 5, fixed_103_bits},
+{5, 7, 7, fixed_104_bits},
+{3, 7, 7, fixed_105_bits},
+{4, 9, 7, fixed_106_bits},
+{5, 7, 7, fixed_107_bits},
+{3, 7, 7, fixed_108_bits},
+{5, 5, 5, fixed_109_bits},
+{5, 5, 5, fixed_110_bits},
+{5, 5, 5, fixed_111_bits},
+{5, 7, 5, fixed_112_bits},
+{5, 7, 5, fixed_113_bits},
+{5, 5, 5, fixed_114_bits},
+{5, 5, 5, fixed_115_bits},
+{5, 7, 7, fixed_116_bits},
+{5, 5, 5, fixed_117_bits},
+{5, 5, 5, fixed_118_bits},
+{5, 5, 5, fixed_119_bits},
+{5, 5, 5, fixed_120_bits},
+{5, 7, 5, fixed_121_bits},
+{5, 5, 5, fixed_122_bits},
+{4, 7, 7, fixed_123_bits},
+{1, 7, 7, fixed_124_bits},
+{4, 7, 7, fixed_125_bits},
+{5, 3, 7, fixed_126_bits},
+{0, 0, 0, fixed_127_bits},
+{5, 1, 1, fixed_128_bits},
+{5, 1, 1, fixed_129_bits},
+{5, 1, 1, fixed_130_bits},
+{5, 1, 1, fixed_131_bits},
+{5, 1, 1, fixed_132_bits},
+{5, 1, 1, fixed_133_bits},
+{5, 1, 1, fixed_134_bits},
+{5, 1, 1, fixed_135_bits},
+{5, 1, 1, fixed_136_bits},
+{5, 1, 1, fixed_137_bits},
+{5, 1, 1, fixed_138_bits},
+{5, 1, 1, fixed_139_bits},
+{5, 1, 1, fixed_140_bits},
+{5, 1, 1, fixed_141_bits},
+{5, 1, 1, fixed_142_bits},
+{5, 1, 1, fixed_143_bits},
+{5, 1, 1, fixed_144_bits},
+{5, 1, 1, fixed_145_bits},
+{5, 1, 1, fixed_146_bits},
+{5, 1, 1, fixed_147_bits},
+{5, 1, 1, fixed_148_bits},
+{5, 1, 1, fixed_149_bits},
+{5, 1, 1, fixed_150_bits},
+{5, 1, 1, fixed_151_bits},
+{5, 1, 1, fixed_152_bits},
+{5, 1, 1, fixed_153_bits},
+{5, 1, 1, fixed_154_bits},
+{5, 1, 1, fixed_155_bits},
+{5, 1, 1, fixed_156_bits},
+{5, 1, 1, fixed_157_bits},
+{5, 1, 1, fixed_158_bits},
+{5, 1, 1, fixed_159_bits},
+{0, 0, 0, fixed_160_bits},
+{1, 7, 7, fixed_161_bits},
+{5, 7, 6, fixed_162_bits},
+{5, 7, 7, fixed_163_bits},
+{5, 5, 5, fixed_164_bits},
+{5, 8, 7, fixed_165_bits},
+{1, 7, 7, fixed_166_bits},
+{5, 8, 7, fixed_167_bits},
+{3, 1, 8, fixed_168_bits},
+{5, 7, 7, fixed_169_bits},
+{4, 6, 7, fixed_170_bits},
+{6, 5, 5, fixed_171_bits},
+{4, 2, 4, fixed_172_bits},
+{5, 1, 4, fixed_173_bits},
+{5, 7, 7, fixed_174_bits},
+{5, 1, 8, fixed_175_bits},
+{3, 3, 7, fixed_176_bits},
+{5, 6, 6, fixed_177_bits},
+{4, 5, 8, fixed_178_bits},
+{4, 5, 8, fixed_179_bits},
+{3, 2, 8, fixed_180_bits},
+{5, 6, 5, fixed_181_bits},
+{5, 7, 7, fixed_182_bits},
+{1, 1, 4, fixed_183_bits},
+{2, 2, 0, fixed_184_bits},
+{3, 5, 8, fixed_185_bits},
+{4, 6, 7, fixed_186_bits},
+{6, 5, 5, fixed_187_bits},
+{6, 9, 8, fixed_188_bits},
+{6, 9, 8, fixed_189_bits},
+{5, 9, 8, fixed_190_bits},
+{5, 7, 7, fixed_191_bits},
+{5, 8, 8, fixed_192_bits},
+{5, 8, 8, fixed_193_bits},
+{5, 8, 8, fixed_194_bits},
+{5, 8, 8, fixed_195_bits},
+{5, 8, 8, fixed_196_bits},
+{5, 8, 8, fixed_197_bits},
+{6, 7, 7, fixed_198_bits},
+{5, 9, 7, fixed_199_bits},
+{5, 8, 8, fixed_200_bits},
+{5, 8, 8, fixed_201_bits},
+{5, 8, 8, fixed_202_bits},
+{5, 8, 8, fixed_203_bits},
+{3, 8, 8, fixed_204_bits},
+{3, 8, 8, fixed_205_bits},
+{3, 8, 8, fixed_206_bits},
+{3, 8, 8, fixed_207_bits},
+{5, 7, 7, fixed_208_bits},
+{5, 8, 8, fixed_209_bits},
+{5, 8, 8, fixed_210_bits},
+{5, 8, 8, fixed_211_bits},
+{5, 8, 8, fixed_212_bits},
+{5, 8, 8, fixed_213_bits},
+{5, 8, 8, fixed_214_bits},
+{5, 5, 5, fixed_215_bits},
+{5, 7, 7, fixed_216_bits},
+{5, 8, 8, fixed_217_bits},
+{5, 8, 8, fixed_218_bits},
+{5, 8, 8, fixed_219_bits},
+{5, 8, 8, fixed_220_bits},
+{5, 8, 8, fixed_221_bits},
+{5, 7, 7, fixed_222_bits},
+{5, 8, 7, fixed_223_bits},
+{5, 7, 7, fixed_224_bits},
+{5, 7, 7, fixed_225_bits},
+{5, 7, 7, fixed_226_bits},
+{5, 7, 7, fixed_227_bits},
+{5, 7, 7, fixed_228_bits},
+{5, 8, 8, fixed_229_bits},
+{6, 5, 5, fixed_230_bits},
+{5, 7, 5, fixed_231_bits},
+{5, 7, 7, fixed_232_bits},
+{5, 7, 7, fixed_233_bits},
+{5, 7, 7, fixed_234_bits},
+{5, 7, 7, fixed_235_bits},
+{3, 8, 8, fixed_236_bits},
+{3, 8, 8, fixed_237_bits},
+{3, 8, 8, fixed_238_bits},
+{3, 7, 7, fixed_239_bits},
+{5, 7, 7, fixed_240_bits},
+{5, 7, 7, fixed_241_bits},
+{5, 7, 7, fixed_242_bits},
+{5, 7, 7, fixed_243_bits},
+{5, 7, 7, fixed_244_bits},
+{5, 7, 7, fixed_245_bits},
+{5, 7, 7, fixed_246_bits},
+{5, 5, 6, fixed_247_bits},
+{5, 5, 5, fixed_248_bits},
+{5, 7, 7, fixed_249_bits},
+{5, 7, 7, fixed_250_bits},
+{5, 7, 7, fixed_251_bits},
+{5, 7, 7, fixed_252_bits},
+{5, 9, 7, fixed_253_bits},
+{5, 8, 6, fixed_254_bits},
+{5, 9, 7, fixed_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/fixfont.c
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/fixfont.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/fixfont.c	(revision 12606)
@@ -0,0 +1,180 @@
+# include <stdio.h>
+# include <math.h>
+# define TRUE 1
+# define FALSE 0
+
+# define ALLOCATE(X,T,S)  \
+  X=(T *)malloc((unsigned) ((S)*sizeof(T)));\
+  if(X==NULL) \
+    { \
+      fprintf(stderr,"failed to malloc X\n");\
+        exit(0);\
+    } 
+# define REALLOCATE(X,T,S) \
+  X=(T *)realloc(X,(unsigned) ((S)*sizeof(T))); \
+  if(X==NULL) \
+    { \
+       fprintf(stderr,"failed to realloc X\n"); \
+       exit(0); \
+    }
+
+#define blank_width 5
+#define blank_height 1
+static unsigned char blank_bits[] = {0x00};
+
+typedef struct {
+  int dx, dy, ascent, Nb;
+  unsigned char *bits;
+  char name[64];
+} RotFont;
+
+char flip_bits (char a);
+int scan_line (FILE *f, char *line);
+
+main (int argc, char **argv) {
+
+  int BitMap, Nvalue, code;
+  unsigned int bits;
+  int i, j, dx, dy, ddx, ddy;
+  char buffer[1000], name[1000], glyph[1000];
+  unsigned char value[1000], bitchar[3];
+  RotFont font[256];
+  
+  FILE *f;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: fixfont (file.bdf) (name)\n");
+    exit (0);
+  }
+
+  f = fopen (argv[1], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "failed to open file %s\n", argv[1]);
+    exit (0);
+  }
+
+  for (i = 0; i < 256; i++) {
+    font[i].bits = 0;
+  }
+
+  BitMap = FALSE;
+  Nvalue = 0;
+  while (scan_line (f, buffer) != EOF) {
+    sscanf (buffer, "%s", name);
+    if (!strcmp (name, "ENDCHAR")) {
+      BitMap = FALSE;
+      if ((code >= 0) && (code < 256)) {
+	font[code].dx = dx;
+	font[code].dy = dy;
+	font[code].ascent = dy + ddy;
+	font[code].Nb = Nvalue;
+	ALLOCATE (font[code].bits, unsigned char, Nvalue);
+	strcpy (font[code].name, glyph);
+	for (i = 0; i < Nvalue; i++) { 
+	  font[code].bits[i] = value[i];
+	}
+      }
+      fprintf (stderr, "found %s\n", glyph);
+    }
+    if (BitMap) {
+      bitchar[2] = 0;
+      for (j = 0; buffer[j] != 0; j+=2) {
+	bitchar[0] = buffer[j];
+	bitchar[1] = buffer[j+1];
+	sscanf (bitchar, "%x", &bits);
+	value[Nvalue] = flip_bits (bits);
+	Nvalue ++;
+      }
+      continue;
+    } 
+    if (!strcmp (name, "STARTCHAR")) {
+      sscanf (buffer, "%*s %s", glyph);
+    }
+    if (!strcmp (name, "ENCODING")) {
+      sscanf (buffer, "%*s %d", &code);
+    }
+    if (!strcmp (name, "BBX")) {
+      sscanf (buffer, "%*s %d %d %d %d", &dx, &dy, &ddx, &ddy);
+    }
+    if (!strcmp (name, "BITMAP")) {
+      BitMap = TRUE;
+      Nvalue = 0;
+    }
+  }    
+
+  for (i = 0; i < 256; i++) {
+    if (font[i].bits  == 0) {
+      font[i].bits = blank_bits;
+      font[i].dx = blank_width;
+      font[i].dy = blank_height;
+      font[i].Nb = 1;
+      font[i].ascent = blank_height;
+      strcpy (font[i].name, "blank");
+    }
+    fprintf (stdout, "static unsigned char %s_%d_bits[] = {", argv[2], i);
+    for (j = 0; j < font[i].Nb; j++) {
+      if (!(j % 12)) fprintf (stdout, "\n");
+      if (j == font[i].Nb - 1) fprintf (stdout, "0x%02x", font[i].bits[j]);
+      else fprintf (stdout, "0x%02x, ", font[i].bits[j]);
+    }
+    fprintf (stdout, "};\n");
+  }
+  
+  fprintf (stdout, "static RotFont %sfont[] = {\n", argv[2]);
+  for (i = 0; i < 255; i++) {
+    fprintf (stdout, "{%d, %d, %d, %s_%d_bits},\n", 
+	     font[i].dx, font[i].dy, font[i].ascent, argv[2], i);
+  }
+  fprintf (stdout, "{%d, %d, %d, %s_%d_bits}};\n", 
+	   font[i].dx, font[i].dy, font[i].ascent, argv[2], i);
+
+      
+}
+
+int scan_line (FILE *f, char *line) {
+
+  int i, status;
+  char c;
+  
+  status = EOF + 1;
+  
+  for (i = 0, c = 0; (c != '\n') && (status != EOF); i++) {
+    status = fscanf (f, "%c", &c);
+    line[i] = c;
+  }
+  line[i - 1] = 0;  /* this could make things crash! */
+
+  if (i > 1) {
+    status = EOF + 1;
+  }
+
+  return (status);
+
+}
+
+char flip_bits (char a) {
+
+  char b, c;
+  
+  c = 0;
+  b = (a & 0x01) << 7;
+  c = c | b;
+  b = (a & 0x02) << 5;
+  c = c | b;
+  b = (a & 0x04) << 3;
+  c = c | b;
+  b = (a & 0x08) << 1;
+  c = c | b;
+  b = (a & 0x10) >> 1;
+  c = c | b;
+  b = (a & 0x20) >> 3;
+  c = c | b;
+  b = (a & 0x40) >> 5;
+  c = c | b;
+  b = (a & 0x80) >> 7;
+  c = c | b;
+
+  return (c);
+
+}
+
Index: /tags/start/Ohana/src/kapa/rotfont/helvetica12.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/helvetica12.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/helvetica12.bdf	(revision 12606)
@@ -0,0 +1,3020 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Helvetica-Medium-R-Normal--12-120-75-75-P-67-ISO8859-1
+SIZE 12 75 75
+FONTBOUNDINGBOX 11 15 0 -3
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Helvetica"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 67
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 9
+X_HEIGHT 7
+FACE_NAME "Helvetica"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.  "
+_DEC_DEVICE_FONTNAMES "PS=Helvetica"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Helvetica"
+FONT "-Adobe-Helvetica-Medium-R-Normal--12-120-75-75-P-67-ISO8859-1"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 7
+DEFAULT_CHAR 32
+FONT_ASCENT 11
+FONT_DESCENT 3
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 3 1 6
+BITMAP
+a0
+a0
+a0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 8 0 0
+BITMAP
+28
+28
+fc
+28
+fc
+50
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -1
+BITMAP
+20
+70
+a8
+a0
+70
+28
+a8
+a8
+70
+20
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+6200
+9400
+9400
+6800
+0800
+1300
+1480
+1480
+2300
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+30
+48
+48
+30
+50
+8a
+84
+8c
+72
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 3 1 6
+BITMAP
+c0
+40
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 12 1 -3
+BITMAP
+20
+40
+40
+80
+80
+80
+80
+80
+80
+40
+40
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 12 0 -3
+BITMAP
+80
+40
+40
+20
+20
+20
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 3 1 6
+BITMAP
+a0
+40
+a0
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+20
+f8
+20
+20
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 3 1 -2
+BITMAP
+40
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 5 1 1 3
+BITMAP
+f8
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 1 1 0
+BITMAP
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 9 0 0
+BITMAP
+10
+10
+20
+20
+40
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 9 1 0
+BITMAP
+20
+e0
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+08
+10
+20
+40
+80
+80
+f8
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+08
+30
+08
+08
+88
+88
+70
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+08
+18
+28
+28
+48
+88
+fc
+08
+08
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+f8
+80
+80
+f0
+08
+08
+88
+88
+70
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+80
+b0
+c8
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+f8
+08
+10
+10
+20
+20
+20
+40
+40
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+88
+78
+08
+08
+88
+70
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 6 1 0
+BITMAP
+80
+00
+00
+00
+00
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 8 0 -2
+BITMAP
+40
+00
+00
+00
+00
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+0c
+30
+c0
+30
+0c
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 3 1 2
+BITMAP
+f8
+00
+f8
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 1 1
+BITMAP
+c0
+30
+0c
+30
+c0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+10
+10
+20
+20
+00
+20
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 960 0
+DWIDTH 12 0
+BBX 10 10 1 -1
+BITMAP
+1f00
+6080
+4d40
+9240
+a240
+a240
+a680
+9b00
+4000
+3e00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+10
+28
+28
+44
+44
+7c
+82
+82
+82
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+f8
+84
+84
+84
+f8
+84
+84
+84
+f8
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+3c
+42
+80
+80
+80
+80
+80
+42
+3c
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+f8
+84
+82
+82
+82
+82
+82
+84
+f8
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+fc
+80
+80
+80
+fc
+80
+80
+80
+fc
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+fc
+80
+80
+80
+f8
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+3c
+42
+80
+80
+8e
+82
+82
+46
+3a
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+82
+82
+82
+fe
+82
+82
+82
+82
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+08
+08
+08
+08
+08
+08
+88
+88
+70
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 1 0
+BITMAP
+84
+88
+90
+a0
+e0
+90
+88
+84
+82
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+f8
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+8080
+c180
+c180
+a280
+a280
+9480
+9480
+8880
+8880
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+c2
+a2
+a2
+92
+8a
+8a
+86
+82
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+f8
+84
+84
+84
+f8
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3c
+42
+81
+81
+81
+89
+85
+42
+3d
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+f8
+84
+84
+84
+f8
+88
+84
+84
+84
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+78
+84
+80
+60
+18
+04
+84
+84
+78
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+fe
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+82
+44
+44
+44
+28
+28
+10
+10
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+8880
+8880
+8880
+4900
+5500
+5500
+2200
+2200
+2200
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+44
+44
+28
+10
+28
+44
+44
+82
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+82
+44
+44
+28
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+fe
+02
+04
+08
+10
+20
+40
+80
+fe
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 12 1 -3
+BITMAP
+c0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+c0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 9 0 0
+BITMAP
+80
+80
+40
+40
+20
+20
+20
+10
+10
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 12 0 -3
+BITMAP
+c0
+40
+40
+40
+40
+40
+40
+40
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 3 0 5
+BITMAP
+20
+50
+88
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 1 0 -2
+BITMAP
+fe
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 3 0 6
+BITMAP
+40
+80
+c0
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+BITMAP
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+80
+80
+b0
+c8
+88
+88
+88
+c8
+b0
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+80
+80
+80
+88
+70
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+08
+08
+68
+98
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+88
+f8
+80
+88
+70
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 4 9 0 0
+BITMAP
+30
+40
+e0
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+68
+98
+88
+88
+88
+98
+68
+08
+88
+70
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+80
+80
+b0
+c8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 12 0 -3
+BITMAP
+40
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+80
+80
+90
+a0
+c0
+c0
+a0
+90
+88
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 7 1 0
+BITMAP
+a4
+da
+92
+92
+92
+92
+92
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+b0
+c8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+b0
+c8
+88
+88
+88
+c8
+b0
+80
+80
+80
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+68
+98
+88
+88
+88
+98
+68
+08
+08
+08
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 7 1 0
+BITMAP
+a0
+c0
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 7 1 0
+BITMAP
+60
+90
+80
+60
+10
+90
+60
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+40
+40
+e0
+40
+40
+40
+40
+40
+60
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+88
+88
+88
+50
+50
+20
+20
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 7 0 0
+BITMAP
+8880
+8880
+4900
+4900
+5500
+2200
+2200
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+84
+48
+30
+30
+48
+84
+84
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+88
+88
+88
+90
+50
+50
+20
+20
+40
+80
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 7 1 0
+BITMAP
+f0
+10
+20
+40
+40
+80
+f0
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 12 0 -3
+BITMAP
+30
+40
+40
+40
+40
+80
+40
+40
+40
+40
+40
+30
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 12 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 12 0 -3
+BITMAP
+c0
+20
+20
+20
+20
+10
+20
+20
+20
+20
+20
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 2 0 3
+BITMAP
+64
+98
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 10 1 -3
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 -1
+BITMAP
+10
+70
+a8
+a0
+a0
+a0
+c8
+70
+40
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+30
+48
+40
+40
+f0
+20
+20
+48
+b0
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 6 0 1
+BITMAP
+84
+78
+48
+48
+78
+84
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+88
+88
+50
+20
+f8
+20
+f8
+20
+20
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 11 1 -2
+BITMAP
+80
+80
+80
+80
+00
+00
+00
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 12 0 -3
+BITMAP
+70
+88
+80
+60
+90
+88
+88
+48
+30
+08
+88
+70
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 1 0 8
+BITMAP
+a0
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+3e00
+4100
+9c80
+a280
+a080
+a280
+9c80
+4100
+3e00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 5 1 4
+BITMAP
+e0
+20
+a0
+00
+e0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+28
+50
+a0
+50
+28
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 4 1 2
+BITMAP
+fc
+04
+04
+04
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 1 0 3
+BITMAP
+f0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+3e00
+4100
+9c80
+9480
+9880
+9480
+9480
+4100
+3e00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 1 0 8
+BITMAP
+f0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 4 0 4
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+20
+20
+f8
+20
+20
+00
+f8
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 5 0 3
+BITMAP
+60
+90
+20
+40
+f0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 5 0 3
+BITMAP
+e0
+20
+40
+20
+c0
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 160 0
+DWIDTH 2 0
+BBX 2 2 0 8
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+88
+88
+88
+88
+88
+98
+e8
+80
+80
+80
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+3c
+68
+e8
+e8
+e8
+68
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 1 1 3
+BITMAP
+80
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 4 0 -3
+BITMAP
+40
+20
+20
+c0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 5 1 3
+BITMAP
+40
+c0
+40
+40
+40
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 5 1 4
+BITMAP
+e0
+a0
+e0
+00
+e0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+a0
+50
+28
+50
+a0
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+4100
+c200
+4400
+4400
+4900
+1300
+1500
+2780
+4100
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+4100
+c200
+4400
+4800
+4b00
+1480
+1100
+2200
+4780
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+e100
+2200
+4400
+2400
+c900
+0b00
+1500
+1780
+2100
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 -3
+BITMAP
+20
+00
+20
+20
+40
+40
+88
+88
+70
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+20
+10
+00
+10
+10
+28
+44
+44
+7c
+82
+82
+82
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+08
+10
+00
+10
+10
+28
+44
+44
+7c
+82
+82
+82
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+10
+28
+00
+10
+10
+28
+44
+44
+7c
+82
+82
+82
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+14
+28
+00
+10
+10
+28
+44
+44
+7c
+82
+82
+82
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+28
+00
+10
+10
+28
+44
+44
+7c
+82
+82
+82
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+10
+28
+10
+10
+10
+28
+44
+44
+7c
+82
+82
+82
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+1f80
+2800
+2800
+4800
+4f80
+7800
+8800
+8800
+8f80
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+3c
+42
+80
+80
+80
+80
+80
+42
+3c
+08
+08
+30
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+20
+10
+00
+fc
+80
+80
+80
+fc
+80
+80
+80
+fc
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+08
+10
+00
+fc
+80
+80
+80
+fc
+80
+80
+80
+fc
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+10
+28
+00
+fc
+80
+80
+80
+fc
+80
+80
+80
+fc
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+28
+00
+fc
+80
+80
+80
+fc
+80
+80
+80
+fc
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 12 0 0
+BITMAP
+80
+40
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 12 1 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 12 0 0
+BITMAP
+40
+a0
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 11 0 0
+BITMAP
+a0
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+7c
+42
+41
+41
+f1
+41
+41
+42
+7c
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+14
+28
+00
+82
+c2
+a2
+a2
+92
+8a
+8a
+86
+82
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+10
+08
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+04
+08
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+08
+14
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+14
+28
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+24
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+88
+50
+20
+50
+88
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 10 11 0 -1
+BITMAP
+0040
+1e80
+2100
+4280
+4480
+4480
+4880
+5080
+2100
+5e00
+8000
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+20
+10
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+08
+10
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+10
+28
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+48
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+08
+10
+00
+82
+82
+44
+44
+28
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+80
+80
+f8
+84
+84
+84
+f8
+80
+80
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+88
+b0
+88
+88
+88
+b0
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+20
+10
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+10
+20
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+20
+50
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+28
+50
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+50
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+30
+48
+30
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 7 1 0
+BITMAP
+7700
+8880
+0880
+7f80
+8800
+8880
+7700
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+70
+88
+80
+80
+80
+88
+70
+20
+10
+60
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+40
+20
+00
+70
+88
+88
+f8
+80
+88
+70
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+10
+20
+00
+70
+88
+88
+f8
+80
+88
+70
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+20
+50
+00
+70
+88
+88
+f8
+80
+88
+70
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+50
+00
+70
+88
+88
+f8
+80
+88
+70
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 10 0 0
+BITMAP
+80
+40
+00
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 10 1 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 10 0 0
+BITMAP
+40
+a0
+00
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+a0
+00
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+68
+30
+50
+08
+78
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+28
+50
+00
+b0
+c8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+40
+20
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+10
+20
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+20
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+28
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+00
+f8
+00
+20
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+3a
+44
+4c
+54
+64
+44
+b8
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+40
+20
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+10
+20
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+20
+50
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+50
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+10
+20
+00
+88
+88
+88
+90
+50
+50
+20
+20
+40
+80
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+80
+80
+b0
+c8
+88
+88
+88
+c8
+b0
+80
+80
+80
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+50
+00
+88
+88
+48
+50
+50
+30
+20
+20
+20
+c0
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/helvetica12.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/helvetica12.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/helvetica12.h	(revision 12606)
@@ -0,0 +1,783 @@
+static unsigned char helvetica12_0_bits[] = {
+0x00};
+static unsigned char helvetica12_1_bits[] = {
+0x00};
+static unsigned char helvetica12_2_bits[] = {
+0x00};
+static unsigned char helvetica12_3_bits[] = {
+0x00};
+static unsigned char helvetica12_4_bits[] = {
+0x00};
+static unsigned char helvetica12_5_bits[] = {
+0x00};
+static unsigned char helvetica12_6_bits[] = {
+0x00};
+static unsigned char helvetica12_7_bits[] = {
+0x00};
+static unsigned char helvetica12_8_bits[] = {
+0x00};
+static unsigned char helvetica12_9_bits[] = {
+0x00};
+static unsigned char helvetica12_10_bits[] = {
+0x00};
+static unsigned char helvetica12_11_bits[] = {
+0x00};
+static unsigned char helvetica12_12_bits[] = {
+0x00};
+static unsigned char helvetica12_13_bits[] = {
+0x00};
+static unsigned char helvetica12_14_bits[] = {
+0x00};
+static unsigned char helvetica12_15_bits[] = {
+0x00};
+static unsigned char helvetica12_16_bits[] = {
+0x00};
+static unsigned char helvetica12_17_bits[] = {
+0x00};
+static unsigned char helvetica12_18_bits[] = {
+0x00};
+static unsigned char helvetica12_19_bits[] = {
+0x00};
+static unsigned char helvetica12_20_bits[] = {
+0x00};
+static unsigned char helvetica12_21_bits[] = {
+0x00};
+static unsigned char helvetica12_22_bits[] = {
+0x00};
+static unsigned char helvetica12_23_bits[] = {
+0x00};
+static unsigned char helvetica12_24_bits[] = {
+0x00};
+static unsigned char helvetica12_25_bits[] = {
+0x00};
+static unsigned char helvetica12_26_bits[] = {
+0x00};
+static unsigned char helvetica12_27_bits[] = {
+0x00};
+static unsigned char helvetica12_28_bits[] = {
+0x00};
+static unsigned char helvetica12_29_bits[] = {
+0x00};
+static unsigned char helvetica12_30_bits[] = {
+0x00};
+static unsigned char helvetica12_31_bits[] = {
+0x00};
+static unsigned char helvetica12_32_bits[] = {
+0x00};
+static unsigned char helvetica12_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01};
+static unsigned char helvetica12_34_bits[] = {
+0x05, 0x05, 0x05};
+static unsigned char helvetica12_35_bits[] = {
+0x14, 0x14, 0x3f, 0x14, 0x3f, 0x0a, 0x0a, 0x0a};
+static unsigned char helvetica12_36_bits[] = {
+0x04, 0x0e, 0x15, 0x05, 0x0e, 0x14, 0x15, 0x15, 0x0e, 0x04};
+static unsigned char helvetica12_37_bits[] = {
+0x46, 0x00, 0x29, 0x00, 0x29, 0x00, 0x16, 0x00, 0x10, 0x00, 0xc8, 0x00, 
+0x28, 0x01, 0x28, 0x01, 0xc4, 0x00};
+static unsigned char helvetica12_38_bits[] = {
+0x0c, 0x12, 0x12, 0x0c, 0x0a, 0x51, 0x21, 0x31, 0x4e};
+static unsigned char helvetica12_39_bits[] = {
+0x03, 0x02, 0x01};
+static unsigned char helvetica12_40_bits[] = {
+0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x04};
+static unsigned char helvetica12_41_bits[] = {
+0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01};
+static unsigned char helvetica12_42_bits[] = {
+0x05, 0x02, 0x05};
+static unsigned char helvetica12_43_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x04};
+static unsigned char helvetica12_44_bits[] = {
+0x02, 0x02, 0x01};
+static unsigned char helvetica12_45_bits[] = {
+0x1f};
+static unsigned char helvetica12_46_bits[] = {
+0x01};
+static unsigned char helvetica12_47_bits[] = {
+0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01};
+static unsigned char helvetica12_48_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_49_bits[] = {
+0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04};
+static unsigned char helvetica12_50_bits[] = {
+0x0e, 0x11, 0x10, 0x08, 0x04, 0x02, 0x01, 0x01, 0x1f};
+static unsigned char helvetica12_51_bits[] = {
+0x0e, 0x11, 0x10, 0x0c, 0x10, 0x10, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_52_bits[] = {
+0x10, 0x18, 0x14, 0x14, 0x12, 0x11, 0x3f, 0x10, 0x10};
+static unsigned char helvetica12_53_bits[] = {
+0x1f, 0x01, 0x01, 0x0f, 0x10, 0x10, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_54_bits[] = {
+0x0e, 0x11, 0x01, 0x0d, 0x13, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_55_bits[] = {
+0x1f, 0x10, 0x08, 0x08, 0x04, 0x04, 0x04, 0x02, 0x02};
+static unsigned char helvetica12_56_bits[] = {
+0x0e, 0x11, 0x11, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_57_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x1e, 0x10, 0x10, 0x11, 0x0e};
+static unsigned char helvetica12_58_bits[] = {
+0x01, 0x00, 0x00, 0x00, 0x00, 0x01};
+static unsigned char helvetica12_59_bits[] = {
+0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01};
+static unsigned char helvetica12_60_bits[] = {
+0x30, 0x0c, 0x03, 0x0c, 0x30};
+static unsigned char helvetica12_61_bits[] = {
+0x1f, 0x00, 0x1f};
+static unsigned char helvetica12_62_bits[] = {
+0x03, 0x0c, 0x30, 0x0c, 0x03};
+static unsigned char helvetica12_63_bits[] = {
+0x0e, 0x11, 0x11, 0x08, 0x08, 0x04, 0x04, 0x00, 0x04};
+static unsigned char helvetica12_64_bits[] = {
+0xf8, 0x00, 0x06, 0x01, 0xb2, 0x02, 0x49, 0x02, 0x45, 0x02, 0x45, 0x02, 
+0x65, 0x01, 0xd9, 0x00, 0x02, 0x00, 0x7c, 0x00};
+static unsigned char helvetica12_65_bits[] = {
+0x08, 0x14, 0x14, 0x22, 0x22, 0x3e, 0x41, 0x41, 0x41};
+static unsigned char helvetica12_66_bits[] = {
+0x1f, 0x21, 0x21, 0x21, 0x1f, 0x21, 0x21, 0x21, 0x1f};
+static unsigned char helvetica12_67_bits[] = {
+0x3c, 0x42, 0x01, 0x01, 0x01, 0x01, 0x01, 0x42, 0x3c};
+static unsigned char helvetica12_68_bits[] = {
+0x1f, 0x21, 0x41, 0x41, 0x41, 0x41, 0x41, 0x21, 0x1f};
+static unsigned char helvetica12_69_bits[] = {
+0x3f, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 0x3f};
+static unsigned char helvetica12_70_bits[] = {
+0x3f, 0x01, 0x01, 0x01, 0x1f, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_71_bits[] = {
+0x3c, 0x42, 0x01, 0x01, 0x71, 0x41, 0x41, 0x62, 0x5c};
+static unsigned char helvetica12_72_bits[] = {
+0x41, 0x41, 0x41, 0x41, 0x7f, 0x41, 0x41, 0x41, 0x41};
+static unsigned char helvetica12_73_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_74_bits[] = {
+0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_75_bits[] = {
+0x21, 0x11, 0x09, 0x05, 0x07, 0x09, 0x11, 0x21, 0x41};
+static unsigned char helvetica12_76_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1f};
+static unsigned char helvetica12_77_bits[] = {
+0x01, 0x01, 0x83, 0x01, 0x83, 0x01, 0x45, 0x01, 0x45, 0x01, 0x29, 0x01, 
+0x29, 0x01, 0x11, 0x01, 0x11, 0x01};
+static unsigned char helvetica12_78_bits[] = {
+0x41, 0x43, 0x45, 0x45, 0x49, 0x51, 0x51, 0x61, 0x41};
+static unsigned char helvetica12_79_bits[] = {
+0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char helvetica12_80_bits[] = {
+0x1f, 0x21, 0x21, 0x21, 0x1f, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_81_bits[] = {
+0x3c, 0x42, 0x81, 0x81, 0x81, 0x91, 0xa1, 0x42, 0xbc};
+static unsigned char helvetica12_82_bits[] = {
+0x1f, 0x21, 0x21, 0x21, 0x1f, 0x11, 0x21, 0x21, 0x21};
+static unsigned char helvetica12_83_bits[] = {
+0x1e, 0x21, 0x01, 0x06, 0x18, 0x20, 0x21, 0x21, 0x1e};
+static unsigned char helvetica12_84_bits[] = {
+0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
+static unsigned char helvetica12_85_bits[] = {
+0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x1e};
+static unsigned char helvetica12_86_bits[] = {
+0x41, 0x41, 0x22, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08};
+static unsigned char helvetica12_87_bits[] = {
+0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x92, 0x00, 0xaa, 0x00, 0xaa, 0x00, 
+0x44, 0x00, 0x44, 0x00, 0x44, 0x00};
+static unsigned char helvetica12_88_bits[] = {
+0x41, 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x41};
+static unsigned char helvetica12_89_bits[] = {
+0x41, 0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08};
+static unsigned char helvetica12_90_bits[] = {
+0x7f, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x7f};
+static unsigned char helvetica12_91_bits[] = {
+0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03};
+static unsigned char helvetica12_92_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08};
+static unsigned char helvetica12_93_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03};
+static unsigned char helvetica12_94_bits[] = {
+0x04, 0x0a, 0x11};
+static unsigned char helvetica12_95_bits[] = {
+0x7f};
+static unsigned char helvetica12_96_bits[] = {
+0x02, 0x01, 0x03};
+static unsigned char helvetica12_97_bits[] = {
+0x0e, 0x11, 0x10, 0x1e, 0x11, 0x11, 0x2e};
+static unsigned char helvetica12_98_bits[] = {
+0x01, 0x01, 0x0d, 0x13, 0x11, 0x11, 0x11, 0x13, 0x0d};
+static unsigned char helvetica12_99_bits[] = {
+0x0e, 0x11, 0x01, 0x01, 0x01, 0x11, 0x0e};
+static unsigned char helvetica12_100_bits[] = {
+0x10, 0x10, 0x16, 0x19, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char helvetica12_101_bits[] = {
+0x0e, 0x11, 0x11, 0x1f, 0x01, 0x11, 0x0e};
+static unsigned char helvetica12_102_bits[] = {
+0x0c, 0x02, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica12_103_bits[] = {
+0x16, 0x19, 0x11, 0x11, 0x11, 0x19, 0x16, 0x10, 0x11, 0x0e};
+static unsigned char helvetica12_104_bits[] = {
+0x01, 0x01, 0x0d, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11};
+static unsigned char helvetica12_105_bits[] = {
+0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_106_bits[] = {
+0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char helvetica12_107_bits[] = {
+0x01, 0x01, 0x09, 0x05, 0x03, 0x03, 0x05, 0x09, 0x11};
+static unsigned char helvetica12_108_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_109_bits[] = {
+0x25, 0x5b, 0x49, 0x49, 0x49, 0x49, 0x49};
+static unsigned char helvetica12_110_bits[] = {
+0x0d, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11};
+static unsigned char helvetica12_111_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_112_bits[] = {
+0x0d, 0x13, 0x11, 0x11, 0x11, 0x13, 0x0d, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_113_bits[] = {
+0x16, 0x19, 0x11, 0x11, 0x11, 0x19, 0x16, 0x10, 0x10, 0x10};
+static unsigned char helvetica12_114_bits[] = {
+0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_115_bits[] = {
+0x06, 0x09, 0x01, 0x06, 0x08, 0x09, 0x06};
+static unsigned char helvetica12_116_bits[] = {
+0x02, 0x02, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x06};
+static unsigned char helvetica12_117_bits[] = {
+0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char helvetica12_118_bits[] = {
+0x11, 0x11, 0x11, 0x0a, 0x0a, 0x04, 0x04};
+static unsigned char helvetica12_119_bits[] = {
+0x11, 0x01, 0x11, 0x01, 0x92, 0x00, 0x92, 0x00, 0xaa, 0x00, 0x44, 0x00, 
+0x44, 0x00};
+static unsigned char helvetica12_120_bits[] = {
+0x21, 0x12, 0x0c, 0x0c, 0x12, 0x21, 0x21};
+static unsigned char helvetica12_121_bits[] = {
+0x11, 0x11, 0x11, 0x09, 0x0a, 0x0a, 0x04, 0x04, 0x02, 0x01};
+static unsigned char helvetica12_122_bits[] = {
+0x0f, 0x08, 0x04, 0x02, 0x02, 0x01, 0x0f};
+static unsigned char helvetica12_123_bits[] = {
+0x0c, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0c};
+static unsigned char helvetica12_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_125_bits[] = {
+0x03, 0x04, 0x04, 0x04, 0x04, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03};
+static unsigned char helvetica12_126_bits[] = {
+0x26, 0x19};
+static unsigned char helvetica12_127_bits[] = {
+0x00};
+static unsigned char helvetica12_128_bits[] = {
+0x00};
+static unsigned char helvetica12_129_bits[] = {
+0x00};
+static unsigned char helvetica12_130_bits[] = {
+0x00};
+static unsigned char helvetica12_131_bits[] = {
+0x00};
+static unsigned char helvetica12_132_bits[] = {
+0x00};
+static unsigned char helvetica12_133_bits[] = {
+0x00};
+static unsigned char helvetica12_134_bits[] = {
+0x00};
+static unsigned char helvetica12_135_bits[] = {
+0x00};
+static unsigned char helvetica12_136_bits[] = {
+0x00};
+static unsigned char helvetica12_137_bits[] = {
+0x00};
+static unsigned char helvetica12_138_bits[] = {
+0x00};
+static unsigned char helvetica12_139_bits[] = {
+0x00};
+static unsigned char helvetica12_140_bits[] = {
+0x00};
+static unsigned char helvetica12_141_bits[] = {
+0x00};
+static unsigned char helvetica12_142_bits[] = {
+0x00};
+static unsigned char helvetica12_143_bits[] = {
+0x00};
+static unsigned char helvetica12_144_bits[] = {
+0x00};
+static unsigned char helvetica12_145_bits[] = {
+0x00};
+static unsigned char helvetica12_146_bits[] = {
+0x00};
+static unsigned char helvetica12_147_bits[] = {
+0x00};
+static unsigned char helvetica12_148_bits[] = {
+0x00};
+static unsigned char helvetica12_149_bits[] = {
+0x00};
+static unsigned char helvetica12_150_bits[] = {
+0x00};
+static unsigned char helvetica12_151_bits[] = {
+0x00};
+static unsigned char helvetica12_152_bits[] = {
+0x00};
+static unsigned char helvetica12_153_bits[] = {
+0x00};
+static unsigned char helvetica12_154_bits[] = {
+0x00};
+static unsigned char helvetica12_155_bits[] = {
+0x00};
+static unsigned char helvetica12_156_bits[] = {
+0x00};
+static unsigned char helvetica12_157_bits[] = {
+0x00};
+static unsigned char helvetica12_158_bits[] = {
+0x00};
+static unsigned char helvetica12_159_bits[] = {
+0x00};
+static unsigned char helvetica12_160_bits[] = {
+0x00};
+static unsigned char helvetica12_161_bits[] = {
+0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_162_bits[] = {
+0x08, 0x0e, 0x15, 0x05, 0x05, 0x05, 0x13, 0x0e, 0x02};
+static unsigned char helvetica12_163_bits[] = {
+0x0c, 0x12, 0x02, 0x02, 0x0f, 0x04, 0x04, 0x12, 0x0d};
+static unsigned char helvetica12_164_bits[] = {
+0x21, 0x1e, 0x12, 0x12, 0x1e, 0x21};
+static unsigned char helvetica12_165_bits[] = {
+0x11, 0x11, 0x0a, 0x04, 0x1f, 0x04, 0x1f, 0x04, 0x04};
+static unsigned char helvetica12_166_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_167_bits[] = {
+0x0e, 0x11, 0x01, 0x06, 0x09, 0x11, 0x11, 0x12, 0x0c, 0x10, 0x11, 0x0e};
+static unsigned char helvetica12_168_bits[] = {
+0x05};
+static unsigned char helvetica12_169_bits[] = {
+0x7c, 0x00, 0x82, 0x00, 0x39, 0x01, 0x45, 0x01, 0x05, 0x01, 0x45, 0x01, 
+0x39, 0x01, 0x82, 0x00, 0x7c, 0x00};
+static unsigned char helvetica12_170_bits[] = {
+0x07, 0x04, 0x05, 0x00, 0x07};
+static unsigned char helvetica12_171_bits[] = {
+0x14, 0x0a, 0x05, 0x0a, 0x14};
+static unsigned char helvetica12_172_bits[] = {
+0x3f, 0x20, 0x20, 0x20};
+static unsigned char helvetica12_173_bits[] = {
+0x0f};
+static unsigned char helvetica12_174_bits[] = {
+0x7c, 0x00, 0x82, 0x00, 0x39, 0x01, 0x29, 0x01, 0x19, 0x01, 0x29, 0x01, 
+0x29, 0x01, 0x82, 0x00, 0x7c, 0x00};
+static unsigned char helvetica12_175_bits[] = {
+0x0f};
+static unsigned char helvetica12_176_bits[] = {
+0x06, 0x09, 0x09, 0x06};
+static unsigned char helvetica12_177_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x04, 0x00, 0x1f};
+static unsigned char helvetica12_178_bits[] = {
+0x06, 0x09, 0x04, 0x02, 0x0f};
+static unsigned char helvetica12_179_bits[] = {
+0x07, 0x04, 0x02, 0x04, 0x03};
+static unsigned char helvetica12_180_bits[] = {
+0x02, 0x01};
+static unsigned char helvetica12_181_bits[] = {
+0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x17, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_182_bits[] = {
+0x3c, 0x16, 0x17, 0x17, 0x17, 0x16, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14};
+static unsigned char helvetica12_183_bits[] = {
+0x01};
+static unsigned char helvetica12_184_bits[] = {
+0x02, 0x04, 0x04, 0x03};
+static unsigned char helvetica12_185_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x02};
+static unsigned char helvetica12_186_bits[] = {
+0x07, 0x05, 0x07, 0x00, 0x07};
+static unsigned char helvetica12_187_bits[] = {
+0x05, 0x0a, 0x14, 0x0a, 0x05};
+static unsigned char helvetica12_188_bits[] = {
+0x82, 0x00, 0x43, 0x00, 0x22, 0x00, 0x22, 0x00, 0x92, 0x00, 0xc8, 0x00, 
+0xa8, 0x00, 0xe4, 0x01, 0x82, 0x00};
+static unsigned char helvetica12_189_bits[] = {
+0x82, 0x00, 0x43, 0x00, 0x22, 0x00, 0x12, 0x00, 0xd2, 0x00, 0x28, 0x01, 
+0x88, 0x00, 0x44, 0x00, 0xe2, 0x01};
+static unsigned char helvetica12_190_bits[] = {
+0x87, 0x00, 0x44, 0x00, 0x22, 0x00, 0x24, 0x00, 0x93, 0x00, 0xd0, 0x00, 
+0xa8, 0x00, 0xe8, 0x01, 0x84, 0x00};
+static unsigned char helvetica12_191_bits[] = {
+0x04, 0x00, 0x04, 0x04, 0x02, 0x02, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_192_bits[] = {
+0x04, 0x08, 0x00, 0x08, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x41, 0x41, 0x41};
+static unsigned char helvetica12_193_bits[] = {
+0x10, 0x08, 0x00, 0x08, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x41, 0x41, 0x41};
+static unsigned char helvetica12_194_bits[] = {
+0x08, 0x14, 0x00, 0x08, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x41, 0x41, 0x41};
+static unsigned char helvetica12_195_bits[] = {
+0x28, 0x14, 0x00, 0x08, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x41, 0x41, 0x41};
+static unsigned char helvetica12_196_bits[] = {
+0x14, 0x00, 0x08, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x41, 0x41, 0x41};
+static unsigned char helvetica12_197_bits[] = {
+0x08, 0x14, 0x08, 0x08, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x41, 0x41, 0x41};
+static unsigned char helvetica12_198_bits[] = {
+0xf8, 0x01, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0xf2, 0x01, 0x1e, 0x00, 
+0x11, 0x00, 0x11, 0x00, 0xf1, 0x01};
+static unsigned char helvetica12_199_bits[] = {
+0x3c, 0x42, 0x01, 0x01, 0x01, 0x01, 0x01, 0x42, 0x3c, 0x10, 0x10, 0x0c};
+static unsigned char helvetica12_200_bits[] = {
+0x04, 0x08, 0x00, 0x3f, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 0x3f};
+static unsigned char helvetica12_201_bits[] = {
+0x10, 0x08, 0x00, 0x3f, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 0x3f};
+static unsigned char helvetica12_202_bits[] = {
+0x08, 0x14, 0x00, 0x3f, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 0x3f};
+static unsigned char helvetica12_203_bits[] = {
+0x14, 0x00, 0x3f, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 0x3f};
+static unsigned char helvetica12_204_bits[] = {
+0x01, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica12_205_bits[] = {
+0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_206_bits[] = {
+0x02, 0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica12_207_bits[] = {
+0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica12_208_bits[] = {
+0x3e, 0x42, 0x82, 0x82, 0x8f, 0x82, 0x82, 0x42, 0x3e};
+static unsigned char helvetica12_209_bits[] = {
+0x28, 0x14, 0x00, 0x41, 0x43, 0x45, 0x45, 0x49, 0x51, 0x51, 0x61, 0x41};
+static unsigned char helvetica12_210_bits[] = {
+0x08, 0x10, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char helvetica12_211_bits[] = {
+0x20, 0x10, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char helvetica12_212_bits[] = {
+0x10, 0x28, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char helvetica12_213_bits[] = {
+0x28, 0x14, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char helvetica12_214_bits[] = {
+0x24, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char helvetica12_215_bits[] = {
+0x11, 0x0a, 0x04, 0x0a, 0x11};
+static unsigned char helvetica12_216_bits[] = {
+0x00, 0x02, 0x78, 0x01, 0x84, 0x00, 0x42, 0x01, 0x22, 0x01, 0x22, 0x01, 
+0x12, 0x01, 0x0a, 0x01, 0x84, 0x00, 0x7a, 0x00, 0x01, 0x00};
+static unsigned char helvetica12_217_bits[] = {
+0x04, 0x08, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x1e};
+static unsigned char helvetica12_218_bits[] = {
+0x10, 0x08, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x1e};
+static unsigned char helvetica12_219_bits[] = {
+0x08, 0x14, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x1e};
+static unsigned char helvetica12_220_bits[] = {
+0x12, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x1e};
+static unsigned char helvetica12_221_bits[] = {
+0x10, 0x08, 0x00, 0x41, 0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08};
+static unsigned char helvetica12_222_bits[] = {
+0x01, 0x01, 0x1f, 0x21, 0x21, 0x21, 0x1f, 0x01, 0x01};
+static unsigned char helvetica12_223_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x0d, 0x11, 0x11, 0x11, 0x0d};
+static unsigned char helvetica12_224_bits[] = {
+0x04, 0x08, 0x00, 0x0e, 0x11, 0x10, 0x1e, 0x11, 0x11, 0x2e};
+static unsigned char helvetica12_225_bits[] = {
+0x08, 0x04, 0x00, 0x0e, 0x11, 0x10, 0x1e, 0x11, 0x11, 0x2e};
+static unsigned char helvetica12_226_bits[] = {
+0x04, 0x0a, 0x00, 0x0e, 0x11, 0x10, 0x1e, 0x11, 0x11, 0x2e};
+static unsigned char helvetica12_227_bits[] = {
+0x14, 0x0a, 0x00, 0x0e, 0x11, 0x10, 0x1e, 0x11, 0x11, 0x2e};
+static unsigned char helvetica12_228_bits[] = {
+0x0a, 0x00, 0x0e, 0x11, 0x10, 0x1e, 0x11, 0x11, 0x2e};
+static unsigned char helvetica12_229_bits[] = {
+0x0c, 0x12, 0x0c, 0x0e, 0x11, 0x10, 0x1e, 0x11, 0x11, 0x2e};
+static unsigned char helvetica12_230_bits[] = {
+0xee, 0x00, 0x11, 0x01, 0x10, 0x01, 0xfe, 0x01, 0x11, 0x00, 0x11, 0x01, 
+0xee, 0x00};
+static unsigned char helvetica12_231_bits[] = {
+0x0e, 0x11, 0x01, 0x01, 0x01, 0x11, 0x0e, 0x04, 0x08, 0x06};
+static unsigned char helvetica12_232_bits[] = {
+0x02, 0x04, 0x00, 0x0e, 0x11, 0x11, 0x1f, 0x01, 0x11, 0x0e};
+static unsigned char helvetica12_233_bits[] = {
+0x08, 0x04, 0x00, 0x0e, 0x11, 0x11, 0x1f, 0x01, 0x11, 0x0e};
+static unsigned char helvetica12_234_bits[] = {
+0x04, 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x1f, 0x01, 0x11, 0x0e};
+static unsigned char helvetica12_235_bits[] = {
+0x0a, 0x00, 0x0e, 0x11, 0x11, 0x1f, 0x01, 0x11, 0x0e};
+static unsigned char helvetica12_236_bits[] = {
+0x01, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica12_237_bits[] = {
+0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_238_bits[] = {
+0x02, 0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica12_239_bits[] = {
+0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica12_240_bits[] = {
+0x16, 0x0c, 0x0a, 0x10, 0x1e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_241_bits[] = {
+0x14, 0x0a, 0x00, 0x0d, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11};
+static unsigned char helvetica12_242_bits[] = {
+0x02, 0x04, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_243_bits[] = {
+0x08, 0x04, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_244_bits[] = {
+0x04, 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_245_bits[] = {
+0x14, 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_246_bits[] = {
+0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_247_bits[] = {
+0x04, 0x00, 0x1f, 0x00, 0x04};
+static unsigned char helvetica12_248_bits[] = {
+0x5c, 0x22, 0x32, 0x2a, 0x26, 0x22, 0x1d};
+static unsigned char helvetica12_249_bits[] = {
+0x02, 0x04, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char helvetica12_250_bits[] = {
+0x08, 0x04, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char helvetica12_251_bits[] = {
+0x04, 0x0a, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char helvetica12_252_bits[] = {
+0x0a, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char helvetica12_253_bits[] = {
+0x08, 0x04, 0x00, 0x11, 0x11, 0x11, 0x09, 0x0a, 0x0a, 0x04, 0x04, 0x02, 
+0x01};
+static unsigned char helvetica12_254_bits[] = {
+0x01, 0x01, 0x0d, 0x13, 0x11, 0x11, 0x11, 0x13, 0x0d, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_255_bits[] = {
+0x0a, 0x00, 0x11, 0x11, 0x12, 0x0a, 0x0a, 0x0c, 0x04, 0x04, 0x04, 0x03};
+static RotFont helvetica12font[] = {
+{5, 1, 1, helvetica12_0_bits},
+{5, 1, 1, helvetica12_1_bits},
+{5, 1, 1, helvetica12_2_bits},
+{5, 1, 1, helvetica12_3_bits},
+{5, 1, 1, helvetica12_4_bits},
+{5, 1, 1, helvetica12_5_bits},
+{5, 1, 1, helvetica12_6_bits},
+{5, 1, 1, helvetica12_7_bits},
+{5, 1, 1, helvetica12_8_bits},
+{5, 1, 1, helvetica12_9_bits},
+{5, 1, 1, helvetica12_10_bits},
+{5, 1, 1, helvetica12_11_bits},
+{5, 1, 1, helvetica12_12_bits},
+{5, 1, 1, helvetica12_13_bits},
+{5, 1, 1, helvetica12_14_bits},
+{5, 1, 1, helvetica12_15_bits},
+{5, 1, 1, helvetica12_16_bits},
+{5, 1, 1, helvetica12_17_bits},
+{5, 1, 1, helvetica12_18_bits},
+{5, 1, 1, helvetica12_19_bits},
+{5, 1, 1, helvetica12_20_bits},
+{5, 1, 1, helvetica12_21_bits},
+{5, 1, 1, helvetica12_22_bits},
+{5, 1, 1, helvetica12_23_bits},
+{5, 1, 1, helvetica12_24_bits},
+{5, 1, 1, helvetica12_25_bits},
+{5, 1, 1, helvetica12_26_bits},
+{5, 1, 1, helvetica12_27_bits},
+{5, 1, 1, helvetica12_28_bits},
+{5, 1, 1, helvetica12_29_bits},
+{5, 1, 1, helvetica12_30_bits},
+{5, 1, 1, helvetica12_31_bits},
+{6, 1, 1, helvetica12_32_bits},
+{1, 9, 9, helvetica12_33_bits},
+{3, 3, 9, helvetica12_34_bits},
+{6, 8, 8, helvetica12_35_bits},
+{5, 10, 9, helvetica12_36_bits},
+{9, 9, 9, helvetica12_37_bits},
+{7, 9, 9, helvetica12_38_bits},
+{2, 3, 9, helvetica12_39_bits},
+{3, 12, 9, helvetica12_40_bits},
+{3, 12, 9, helvetica12_41_bits},
+{3, 3, 9, helvetica12_42_bits},
+{5, 5, 6, helvetica12_43_bits},
+{2, 3, 1, helvetica12_44_bits},
+{5, 1, 4, helvetica12_45_bits},
+{1, 1, 1, helvetica12_46_bits},
+{4, 9, 9, helvetica12_47_bits},
+{5, 9, 9, helvetica12_48_bits},
+{3, 9, 9, helvetica12_49_bits},
+{5, 9, 9, helvetica12_50_bits},
+{5, 9, 9, helvetica12_51_bits},
+{6, 9, 9, helvetica12_52_bits},
+{5, 9, 9, helvetica12_53_bits},
+{5, 9, 9, helvetica12_54_bits},
+{5, 9, 9, helvetica12_55_bits},
+{5, 9, 9, helvetica12_56_bits},
+{5, 9, 9, helvetica12_57_bits},
+{1, 6, 6, helvetica12_58_bits},
+{2, 8, 6, helvetica12_59_bits},
+{6, 5, 6, helvetica12_60_bits},
+{5, 3, 5, helvetica12_61_bits},
+{6, 5, 6, helvetica12_62_bits},
+{5, 9, 9, helvetica12_63_bits},
+{10, 10, 9, helvetica12_64_bits},
+{7, 9, 9, helvetica12_65_bits},
+{6, 9, 9, helvetica12_66_bits},
+{7, 9, 9, helvetica12_67_bits},
+{7, 9, 9, helvetica12_68_bits},
+{6, 9, 9, helvetica12_69_bits},
+{6, 9, 9, helvetica12_70_bits},
+{7, 9, 9, helvetica12_71_bits},
+{7, 9, 9, helvetica12_72_bits},
+{1, 9, 9, helvetica12_73_bits},
+{5, 9, 9, helvetica12_74_bits},
+{7, 9, 9, helvetica12_75_bits},
+{5, 9, 9, helvetica12_76_bits},
+{9, 9, 9, helvetica12_77_bits},
+{7, 9, 9, helvetica12_78_bits},
+{8, 9, 9, helvetica12_79_bits},
+{6, 9, 9, helvetica12_80_bits},
+{8, 9, 9, helvetica12_81_bits},
+{6, 9, 9, helvetica12_82_bits},
+{6, 9, 9, helvetica12_83_bits},
+{7, 9, 9, helvetica12_84_bits},
+{6, 9, 9, helvetica12_85_bits},
+{7, 9, 9, helvetica12_86_bits},
+{9, 9, 9, helvetica12_87_bits},
+{7, 9, 9, helvetica12_88_bits},
+{7, 9, 9, helvetica12_89_bits},
+{7, 9, 9, helvetica12_90_bits},
+{2, 12, 9, helvetica12_91_bits},
+{4, 9, 9, helvetica12_92_bits},
+{2, 12, 9, helvetica12_93_bits},
+{5, 3, 8, helvetica12_94_bits},
+{7, 1, -1, helvetica12_95_bits},
+{2, 3, 9, helvetica12_96_bits},
+{6, 7, 7, helvetica12_97_bits},
+{5, 9, 9, helvetica12_98_bits},
+{5, 7, 7, helvetica12_99_bits},
+{5, 9, 9, helvetica12_100_bits},
+{5, 7, 7, helvetica12_101_bits},
+{4, 9, 9, helvetica12_102_bits},
+{5, 10, 7, helvetica12_103_bits},
+{5, 9, 9, helvetica12_104_bits},
+{1, 9, 9, helvetica12_105_bits},
+{2, 12, 9, helvetica12_106_bits},
+{5, 9, 9, helvetica12_107_bits},
+{1, 9, 9, helvetica12_108_bits},
+{7, 7, 7, helvetica12_109_bits},
+{5, 7, 7, helvetica12_110_bits},
+{5, 7, 7, helvetica12_111_bits},
+{5, 10, 7, helvetica12_112_bits},
+{5, 10, 7, helvetica12_113_bits},
+{3, 7, 7, helvetica12_114_bits},
+{4, 7, 7, helvetica12_115_bits},
+{3, 9, 9, helvetica12_116_bits},
+{5, 7, 7, helvetica12_117_bits},
+{5, 7, 7, helvetica12_118_bits},
+{9, 7, 7, helvetica12_119_bits},
+{6, 7, 7, helvetica12_120_bits},
+{5, 10, 7, helvetica12_121_bits},
+{4, 7, 7, helvetica12_122_bits},
+{4, 12, 9, helvetica12_123_bits},
+{1, 12, 9, helvetica12_124_bits},
+{4, 12, 9, helvetica12_125_bits},
+{6, 2, 5, helvetica12_126_bits},
+{5, 1, 1, helvetica12_127_bits},
+{5, 1, 1, helvetica12_128_bits},
+{5, 1, 1, helvetica12_129_bits},
+{5, 1, 1, helvetica12_130_bits},
+{5, 1, 1, helvetica12_131_bits},
+{5, 1, 1, helvetica12_132_bits},
+{5, 1, 1, helvetica12_133_bits},
+{5, 1, 1, helvetica12_134_bits},
+{5, 1, 1, helvetica12_135_bits},
+{5, 1, 1, helvetica12_136_bits},
+{5, 1, 1, helvetica12_137_bits},
+{5, 1, 1, helvetica12_138_bits},
+{5, 1, 1, helvetica12_139_bits},
+{5, 1, 1, helvetica12_140_bits},
+{5, 1, 1, helvetica12_141_bits},
+{5, 1, 1, helvetica12_142_bits},
+{5, 1, 1, helvetica12_143_bits},
+{5, 1, 1, helvetica12_144_bits},
+{5, 1, 1, helvetica12_145_bits},
+{5, 1, 1, helvetica12_146_bits},
+{5, 1, 1, helvetica12_147_bits},
+{5, 1, 1, helvetica12_148_bits},
+{5, 1, 1, helvetica12_149_bits},
+{5, 1, 1, helvetica12_150_bits},
+{5, 1, 1, helvetica12_151_bits},
+{5, 1, 1, helvetica12_152_bits},
+{5, 1, 1, helvetica12_153_bits},
+{5, 1, 1, helvetica12_154_bits},
+{5, 1, 1, helvetica12_155_bits},
+{5, 1, 1, helvetica12_156_bits},
+{5, 1, 1, helvetica12_157_bits},
+{5, 1, 1, helvetica12_158_bits},
+{5, 1, 1, helvetica12_159_bits},
+{1, 1, 1, helvetica12_160_bits},
+{1, 10, 7, helvetica12_161_bits},
+{5, 9, 8, helvetica12_162_bits},
+{5, 9, 9, helvetica12_163_bits},
+{6, 6, 7, helvetica12_164_bits},
+{5, 9, 9, helvetica12_165_bits},
+{1, 11, 9, helvetica12_166_bits},
+{5, 12, 9, helvetica12_167_bits},
+{3, 1, 9, helvetica12_168_bits},
+{9, 9, 9, helvetica12_169_bits},
+{3, 5, 9, helvetica12_170_bits},
+{5, 5, 6, helvetica12_171_bits},
+{6, 4, 6, helvetica12_172_bits},
+{4, 1, 4, helvetica12_173_bits},
+{9, 9, 9, helvetica12_174_bits},
+{4, 1, 9, helvetica12_175_bits},
+{4, 4, 8, helvetica12_176_bits},
+{5, 7, 7, helvetica12_177_bits},
+{4, 5, 8, helvetica12_178_bits},
+{3, 5, 8, helvetica12_179_bits},
+{2, 2, 10, helvetica12_180_bits},
+{5, 10, 7, helvetica12_181_bits},
+{6, 12, 9, helvetica12_182_bits},
+{1, 1, 4, helvetica12_183_bits},
+{3, 4, 1, helvetica12_184_bits},
+{2, 5, 8, helvetica12_185_bits},
+{3, 5, 9, helvetica12_186_bits},
+{5, 5, 6, helvetica12_187_bits},
+{9, 9, 9, helvetica12_188_bits},
+{9, 9, 9, helvetica12_189_bits},
+{9, 9, 9, helvetica12_190_bits},
+{5, 9, 6, helvetica12_191_bits},
+{7, 12, 12, helvetica12_192_bits},
+{7, 12, 12, helvetica12_193_bits},
+{7, 12, 12, helvetica12_194_bits},
+{7, 12, 12, helvetica12_195_bits},
+{7, 11, 11, helvetica12_196_bits},
+{7, 12, 12, helvetica12_197_bits},
+{9, 9, 9, helvetica12_198_bits},
+{7, 12, 9, helvetica12_199_bits},
+{6, 12, 12, helvetica12_200_bits},
+{6, 12, 12, helvetica12_201_bits},
+{6, 12, 12, helvetica12_202_bits},
+{6, 11, 11, helvetica12_203_bits},
+{2, 12, 12, helvetica12_204_bits},
+{2, 12, 12, helvetica12_205_bits},
+{3, 12, 12, helvetica12_206_bits},
+{3, 11, 11, helvetica12_207_bits},
+{8, 9, 9, helvetica12_208_bits},
+{7, 12, 12, helvetica12_209_bits},
+{8, 12, 12, helvetica12_210_bits},
+{8, 12, 12, helvetica12_211_bits},
+{8, 12, 12, helvetica12_212_bits},
+{8, 12, 12, helvetica12_213_bits},
+{8, 11, 11, helvetica12_214_bits},
+{5, 5, 6, helvetica12_215_bits},
+{10, 11, 10, helvetica12_216_bits},
+{6, 12, 12, helvetica12_217_bits},
+{6, 12, 12, helvetica12_218_bits},
+{6, 12, 12, helvetica12_219_bits},
+{6, 11, 11, helvetica12_220_bits},
+{7, 12, 12, helvetica12_221_bits},
+{6, 9, 9, helvetica12_222_bits},
+{5, 9, 9, helvetica12_223_bits},
+{6, 10, 10, helvetica12_224_bits},
+{6, 10, 10, helvetica12_225_bits},
+{6, 10, 10, helvetica12_226_bits},
+{6, 10, 10, helvetica12_227_bits},
+{6, 9, 9, helvetica12_228_bits},
+{6, 10, 10, helvetica12_229_bits},
+{9, 7, 7, helvetica12_230_bits},
+{5, 10, 7, helvetica12_231_bits},
+{5, 10, 10, helvetica12_232_bits},
+{5, 10, 10, helvetica12_233_bits},
+{5, 10, 10, helvetica12_234_bits},
+{5, 9, 9, helvetica12_235_bits},
+{2, 10, 10, helvetica12_236_bits},
+{2, 10, 10, helvetica12_237_bits},
+{3, 10, 10, helvetica12_238_bits},
+{3, 9, 9, helvetica12_239_bits},
+{5, 10, 10, helvetica12_240_bits},
+{5, 10, 10, helvetica12_241_bits},
+{5, 10, 10, helvetica12_242_bits},
+{5, 10, 10, helvetica12_243_bits},
+{5, 10, 10, helvetica12_244_bits},
+{5, 10, 10, helvetica12_245_bits},
+{5, 9, 9, helvetica12_246_bits},
+{5, 5, 6, helvetica12_247_bits},
+{7, 7, 7, helvetica12_248_bits},
+{5, 10, 10, helvetica12_249_bits},
+{5, 10, 10, helvetica12_250_bits},
+{5, 10, 10, helvetica12_251_bits},
+{5, 9, 9, helvetica12_252_bits},
+{5, 13, 10, helvetica12_253_bits},
+{5, 12, 9, helvetica12_254_bits},
+{5, 12, 9, helvetica12_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/helvetica14.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/helvetica14.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/helvetica14.bdf	(revision 12606)
@@ -0,0 +1,3309 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Helvetica-Medium-R-Normal--14-100-100-100-P-76-ISO8859-1
+SIZE 10 100 100
+FONTBOUNDINGBOX 14 17 -1 -3
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Helvetica"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 14
+POINT_SIZE 100
+RESOLUTION_X 100
+RESOLUTION_Y 100
+SPACING "P"
+AVERAGE_WIDTH 76
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 11
+X_HEIGHT 8
+FACE_NAME "Helvetica"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.  "
+_DEC_DEVICE_FONTNAMES "PS=Helvetica"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Helvetica"
+FONT "-Adobe-Helvetica-Medium-R-Normal--14-100-100-100-P-76-ISO8859-1"
+WEIGHT 10
+RESOLUTION 138
+QUAD_WIDTH 8
+DEFAULT_CHAR 32
+FONT_ASCENT 13
+FONT_DESCENT 3
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 1 11 2 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+00
+80
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 3 1 8
+BITMAP
+a0
+a0
+a0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 10 0 0
+BITMAP
+14
+14
+14
+7e
+28
+28
+fc
+50
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 14 0 -2
+BITMAP
+10
+7c
+92
+92
+90
+50
+38
+14
+12
+92
+92
+7c
+10
+10
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 11 11 0 0
+BITMAP
+7080
+8900
+8900
+7200
+0200
+0400
+0800
+09c0
+1220
+1220
+21c0
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+30
+48
+48
+30
+20
+52
+8a
+84
+8a
+71
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 2 3 1 8
+BITMAP
+c0
+40
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 14 1 -3
+BITMAP
+20
+40
+40
+80
+80
+80
+80
+80
+80
+80
+80
+40
+40
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 14 1 -3
+BITMAP
+80
+40
+40
+20
+20
+20
+20
+20
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 5 1 6
+BITMAP
+20
+a8
+70
+a8
+20
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 1
+BITMAP
+10
+10
+10
+fe
+10
+10
+10
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 2 4 0 -2
+BITMAP
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 1 1 4
+BITMAP
+fe
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 2 1 0
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 11 0 0
+BITMAP
+10
+10
+20
+20
+20
+40
+40
+40
+80
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+78
+84
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 3 11 2 0
+BITMAP
+20
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+78
+84
+84
+04
+08
+10
+20
+40
+80
+80
+fc
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+78
+84
+84
+04
+04
+38
+04
+04
+84
+84
+78
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 11 1 0
+BITMAP
+04
+0c
+14
+24
+44
+84
+84
+fe
+04
+04
+04
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+fc
+80
+80
+80
+f8
+04
+04
+04
+84
+84
+78
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+78
+84
+80
+80
+b8
+c4
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+fc
+04
+08
+08
+10
+10
+20
+20
+40
+40
+40
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+78
+84
+84
+84
+84
+78
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+78
+84
+84
+84
+84
+7c
+04
+04
+84
+84
+78
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 8 1 0
+BITMAP
+80
+80
+00
+00
+00
+00
+80
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 10 0 -2
+BITMAP
+40
+40
+00
+00
+00
+00
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 5 1 2
+BITMAP
+0c
+30
+c0
+30
+0c
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 3 1 3
+BITMAP
+fc
+00
+fc
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 5 1 2
+BITMAP
+c0
+30
+0c
+30
+c0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+30
+cc
+84
+84
+04
+08
+10
+20
+00
+20
+20
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 936 0
+DWIDTH 13 0
+BBX 11 12 1 -1
+BITMAP
+0f00
+30c0
+4020
+46a0
+8920
+9120
+9120
+9340
+8d80
+4000
+6080
+1f00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 11 0 0
+BITMAP
+0800
+1c00
+1400
+1400
+2200
+2200
+4100
+7f00
+4100
+8080
+8080
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+fc
+86
+82
+82
+84
+f8
+84
+82
+82
+86
+fc
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+1c
+63
+41
+80
+80
+80
+80
+80
+41
+63
+1c
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+f8
+86
+82
+81
+81
+81
+81
+81
+82
+86
+f8
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+fe
+80
+80
+80
+80
+fc
+80
+80
+80
+80
+fe
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 11 1 0
+BITMAP
+fe
+80
+80
+80
+80
+fc
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+1e00
+6180
+4080
+8000
+8000
+8780
+8080
+8080
+4080
+6380
+1c80
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+81
+81
+81
+81
+81
+ff
+81
+81
+81
+81
+81
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 1 11 2 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 0 0
+BITMAP
+04
+04
+04
+04
+04
+04
+04
+04
+84
+84
+78
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 11 1 0
+BITMAP
+82
+84
+88
+90
+a0
+e0
+90
+88
+84
+82
+81
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 2 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+fc
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 11 11 0 0
+BITMAP
+8020
+c060
+c060
+a0a0
+a0a0
+9120
+9120
+8a20
+8a20
+8420
+8420
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+c1
+a1
+a1
+91
+91
+89
+89
+85
+85
+83
+83
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+fc
+86
+82
+82
+86
+fc
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+1c00
+6300
+4100
+8080
+8080
+8080
+8880
+8480
+4300
+6300
+1c80
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+fe
+83
+81
+81
+82
+fc
+82
+81
+81
+81
+81
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+38
+c6
+82
+80
+60
+18
+06
+02
+82
+c6
+38
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 11 0 0
+BITMAP
+ff80
+0800
+0800
+0800
+0800
+0800
+0800
+0800
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+81
+81
+81
+81
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 11 0 0
+BITMAP
+8080
+8080
+4100
+4100
+6300
+2200
+2200
+1400
+1400
+0800
+0800
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 936 0
+DWIDTH 13 0
+BBX 13 11 0 0
+BITMAP
+8208
+8208
+8508
+4510
+4510
+4510
+28a0
+28a0
+28a0
+1040
+1040
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 11 0 0
+BITMAP
+8080
+4100
+2200
+1400
+0800
+0800
+1400
+2200
+4100
+4100
+8080
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 11 0 0
+BITMAP
+8080
+c180
+4100
+2200
+2200
+1400
+1c00
+0800
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+fe
+02
+04
+08
+18
+10
+20
+60
+40
+80
+fe
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 3 14 1 -3
+BITMAP
+e0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+e0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 11 0 0
+BITMAP
+80
+80
+40
+40
+40
+20
+20
+20
+10
+10
+10
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 3 14 0 -3
+BITMAP
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+e0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 5 1 6
+BITMAP
+20
+50
+50
+88
+88
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 8 1 0 -3
+BITMAP
+ff
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 2 3 0 8
+BITMAP
+40
+80
+c0
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 8 1 0
+BITMAP
+78
+cc
+04
+7c
+c4
+84
+cc
+76
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+80
+80
+80
+b8
+cc
+84
+84
+84
+84
+cc
+b8
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 8 1 0
+BITMAP
+78
+cc
+80
+80
+80
+84
+cc
+78
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+04
+04
+04
+74
+cc
+84
+84
+84
+84
+cc
+74
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 8 1 0
+BITMAP
+78
+cc
+84
+fc
+80
+80
+cc
+78
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 11 0 0
+BITMAP
+30
+40
+40
+e0
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 -3
+BITMAP
+74
+cc
+84
+84
+84
+84
+cc
+74
+04
+cc
+78
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+80
+80
+80
+b8
+cc
+84
+84
+84
+84
+84
+84
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 11 1 0
+BITMAP
+80
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 3 14 -1 -3
+BITMAP
+20
+20
+00
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+c0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+80
+80
+80
+88
+90
+a0
+c0
+a0
+90
+88
+84
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 11 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 8 1 0
+BITMAP
+b300
+cc80
+8880
+8880
+8880
+8880
+8880
+8880
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 8 1 0
+BITMAP
+b8
+cc
+84
+84
+84
+84
+84
+84
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 8 1 0
+BITMAP
+78
+cc
+84
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 -3
+BITMAP
+b8
+cc
+84
+84
+84
+84
+cc
+b8
+80
+80
+80
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 -3
+BITMAP
+74
+cc
+84
+84
+84
+84
+cc
+74
+04
+04
+04
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 4 8 1 0
+BITMAP
+b0
+c0
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 8 1 0
+BITMAP
+70
+88
+c0
+70
+18
+08
+88
+70
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 10 0 0
+BITMAP
+40
+40
+e0
+40
+40
+40
+40
+40
+40
+30
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 8 1 0
+BITMAP
+84
+84
+84
+84
+84
+84
+cc
+74
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+82
+82
+44
+44
+44
+28
+28
+10
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 9 8 0 0
+BITMAP
+8880
+8880
+8880
+4900
+4900
+5500
+2200
+2200
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+c6
+44
+28
+10
+10
+28
+44
+c6
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 11 0 -3
+BITMAP
+82
+c2
+44
+44
+24
+28
+18
+10
+10
+30
+60
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 8 0 0
+BITMAP
+fc
+04
+08
+10
+20
+40
+80
+fc
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 5 14 0 -3
+BITMAP
+18
+20
+20
+20
+20
+40
+80
+40
+20
+20
+20
+20
+20
+18
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 14 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 5 14 0 -3
+BITMAP
+c0
+20
+20
+20
+20
+10
+08
+10
+20
+20
+20
+20
+20
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 3 1 3
+BITMAP
+64
+b4
+98
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 1 11 1 -3
+BITMAP
+80
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 10 1 -1
+BITMAP
+04
+78
+cc
+90
+90
+a0
+a4
+cc
+78
+80
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 11 0 0
+BITMAP
+38
+44
+40
+40
+f8
+20
+20
+20
+40
+62
+dc
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 6 1 2
+BITMAP
+84
+78
+48
+48
+78
+84
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+82
+82
+82
+44
+44
+28
+fe
+10
+fe
+10
+10
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 14 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+00
+00
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 5 14 2 -3
+BITMAP
+70
+d8
+88
+c0
+70
+98
+88
+88
+c8
+70
+18
+88
+d8
+70
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 5 1 0 9
+BITMAP
+d8
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 10 11 1 0
+BITMAP
+1e00
+6180
+5c80
+a2c0
+a240
+a040
+a240
+9c40
+4080
+6180
+1e00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 4 7 1 4
+BITMAP
+e0
+10
+70
+90
+d0
+00
+f0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 5 1 2
+BITMAP
+24
+48
+90
+48
+24
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 4 1 2
+BITMAP
+fe
+02
+02
+02
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 3 1 0 4
+BITMAP
+e0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 10 11 1 0
+BITMAP
+1e00
+6180
+5c80
+9240
+9240
+9c40
+9240
+9240
+4080
+6180
+1e00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 1 0 9
+BITMAP
+f0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 4 4 1 7
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+10
+10
+10
+fe
+10
+10
+10
+00
+fe
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 4 6 0 5
+BITMAP
+60
+90
+10
+20
+40
+f0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 4 6 0 5
+BITMAP
+60
+90
+20
+10
+90
+60
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 2 2 2 9
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 -3
+BITMAP
+84
+84
+84
+84
+84
+84
+cc
+b4
+80
+80
+80
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 14 0 -3
+BITMAP
+3e
+74
+f4
+f4
+f4
+74
+34
+14
+14
+14
+14
+14
+14
+14
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 1 1 4
+BITMAP
+c0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 4 3 0 -3
+BITMAP
+20
+90
+60
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 2 6 1 5
+BITMAP
+40
+c0
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 4 7 1 4
+BITMAP
+60
+90
+90
+90
+60
+00
+f0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 5 1 2
+BITMAP
+90
+48
+24
+48
+90
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 10 11 1 0
+BITMAP
+4200
+c200
+4400
+4400
+4800
+4880
+0980
+1280
+1480
+27c0
+2080
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 9 11 1 0
+BITMAP
+4200
+c200
+4400
+4400
+4800
+4b00
+1480
+1080
+1100
+2200
+2780
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 11 11 0 0
+BITMAP
+6100
+9100
+2200
+1200
+9400
+6440
+04c0
+0940
+0a40
+13e0
+1040
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 -3
+BITMAP
+10
+10
+00
+10
+20
+40
+80
+84
+84
+cc
+30
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 14 0 0
+BITMAP
+1000
+0800
+0000
+0800
+1c00
+1400
+1400
+2200
+2200
+4100
+7f00
+4100
+8080
+8080
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 14 0 0
+BITMAP
+0400
+0800
+0000
+0800
+1c00
+1400
+1400
+2200
+2200
+4100
+7f00
+4100
+8080
+8080
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 14 0 0
+BITMAP
+0c00
+1200
+0000
+0800
+1c00
+1400
+1400
+2200
+2200
+4100
+7f00
+4100
+8080
+8080
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 14 0 0
+BITMAP
+1a00
+2c00
+0000
+0800
+1c00
+1400
+1400
+2200
+2200
+4100
+7f00
+4100
+8080
+8080
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 13 0 0
+BITMAP
+3600
+0000
+0800
+1c00
+1400
+1400
+2200
+2200
+4100
+7f00
+4100
+8080
+8080
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 14 0 0
+BITMAP
+0c00
+1200
+1200
+0c00
+0c00
+1400
+1400
+2200
+2200
+4100
+7f00
+4100
+8080
+8080
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 1008 0
+DWIDTH 14 0
+BBX 12 11 1 0
+BITMAP
+1ff0
+1200
+1200
+2200
+2200
+23f0
+7e00
+4200
+4200
+8200
+83f0
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 -3
+BITMAP
+1c
+63
+41
+80
+80
+80
+80
+80
+41
+63
+1c
+08
+24
+18
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+20
+10
+00
+fe
+80
+80
+80
+80
+fc
+80
+80
+80
+80
+fe
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+08
+10
+00
+fe
+80
+80
+80
+80
+fc
+80
+80
+80
+80
+fe
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+18
+24
+00
+fe
+80
+80
+80
+80
+fc
+80
+80
+80
+80
+fe
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+6c
+00
+fe
+80
+80
+80
+80
+fc
+80
+80
+80
+80
+fe
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 14 1 0
+BITMAP
+80
+40
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 14 2 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 14 1 0
+BITMAP
+60
+90
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 5 13 0 0
+BITMAP
+d8
+00
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 9 11 0 0
+BITMAP
+7c00
+4300
+4100
+4080
+4080
+f080
+4080
+4080
+4100
+4300
+7c00
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+1a
+2c
+00
+c1
+a1
+a1
+91
+91
+89
+89
+85
+85
+83
+83
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+1000
+0800
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+0400
+0800
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+0c00
+1200
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+1a00
+2c00
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+3300
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 1
+BITMAP
+82
+44
+28
+10
+28
+44
+82
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 11 11 0 0
+BITMAP
+0e20
+31c0
+2080
+4140
+4240
+4440
+4840
+5040
+2080
+7180
+8e00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+10
+08
+00
+81
+81
+81
+81
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+04
+08
+00
+81
+81
+81
+81
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+18
+24
+00
+81
+81
+81
+81
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+66
+00
+81
+81
+81
+81
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 14 0 0
+BITMAP
+0400
+0800
+0000
+8080
+c180
+4100
+2200
+2200
+1400
+1c00
+0800
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+80
+80
+fc
+86
+82
+82
+86
+fc
+80
+80
+80
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+70
+88
+88
+88
+b0
+90
+88
+88
+88
+88
+b0
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 11 1 0
+BITMAP
+20
+10
+00
+78
+cc
+04
+7c
+c4
+84
+cc
+76
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 11 1 0
+BITMAP
+10
+20
+00
+78
+cc
+04
+7c
+c4
+84
+cc
+76
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 11 1 0
+BITMAP
+30
+48
+00
+78
+cc
+04
+7c
+c4
+84
+cc
+76
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 11 1 0
+BITMAP
+34
+58
+00
+78
+cc
+04
+7c
+c4
+84
+cc
+76
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 11 1 0
+BITMAP
+48
+48
+00
+78
+cc
+04
+7c
+c4
+84
+cc
+76
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 12 1 0
+BITMAP
+30
+48
+30
+00
+78
+cc
+04
+7c
+c4
+84
+cc
+76
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 936 0
+DWIDTH 13 0
+BBX 11 8 1 0
+BITMAP
+7bc0
+c660
+0420
+7fe0
+c400
+8400
+ce60
+7bc0
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 -3
+BITMAP
+78
+cc
+80
+80
+80
+84
+cc
+78
+10
+48
+30
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+20
+10
+00
+78
+cc
+84
+fc
+80
+80
+cc
+78
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+10
+20
+00
+78
+cc
+84
+fc
+80
+80
+cc
+78
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+30
+48
+00
+78
+cc
+84
+fc
+80
+80
+cc
+78
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+48
+48
+00
+78
+cc
+84
+fc
+80
+80
+cc
+78
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 2 11 1 0
+BITMAP
+80
+40
+00
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 2 11 1 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 4 11 0 0
+BITMAP
+60
+90
+00
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 3 11 0 0
+BITMAP
+a0
+a0
+00
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+d8
+70
+90
+78
+cc
+84
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+68
+b0
+00
+b8
+cc
+84
+84
+84
+84
+84
+84
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+20
+10
+00
+78
+cc
+84
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+10
+20
+00
+78
+cc
+84
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+30
+48
+00
+78
+cc
+84
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+68
+b0
+00
+78
+cc
+84
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+48
+48
+00
+78
+cc
+84
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 1
+BITMAP
+10
+10
+00
+fe
+00
+10
+10
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 8 8 0 0
+BITMAP
+3d
+62
+46
+4a
+52
+62
+46
+bc
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+20
+10
+00
+84
+84
+84
+84
+84
+84
+cc
+74
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+10
+20
+00
+84
+84
+84
+84
+84
+84
+cc
+74
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+30
+48
+00
+84
+84
+84
+84
+84
+84
+cc
+74
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+48
+48
+00
+84
+84
+84
+84
+84
+84
+cc
+74
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 14 0 -3
+BITMAP
+08
+10
+00
+82
+c2
+44
+44
+24
+28
+18
+10
+10
+30
+60
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 14 1 -3
+BITMAP
+80
+80
+80
+b8
+cc
+84
+84
+84
+84
+cc
+b8
+80
+80
+80
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 14 0 -3
+BITMAP
+24
+24
+00
+82
+c2
+44
+44
+24
+28
+18
+10
+10
+30
+60
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/helvetica14.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/helvetica14.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/helvetica14.h	(revision 12606)
@@ -0,0 +1,845 @@
+static unsigned char helvetica14_0_bits[] = {
+0x00};
+static unsigned char helvetica14_1_bits[] = {
+0x00};
+static unsigned char helvetica14_2_bits[] = {
+0x00};
+static unsigned char helvetica14_3_bits[] = {
+0x00};
+static unsigned char helvetica14_4_bits[] = {
+0x00};
+static unsigned char helvetica14_5_bits[] = {
+0x00};
+static unsigned char helvetica14_6_bits[] = {
+0x00};
+static unsigned char helvetica14_7_bits[] = {
+0x00};
+static unsigned char helvetica14_8_bits[] = {
+0x00};
+static unsigned char helvetica14_9_bits[] = {
+0x00};
+static unsigned char helvetica14_10_bits[] = {
+0x00};
+static unsigned char helvetica14_11_bits[] = {
+0x00};
+static unsigned char helvetica14_12_bits[] = {
+0x00};
+static unsigned char helvetica14_13_bits[] = {
+0x00};
+static unsigned char helvetica14_14_bits[] = {
+0x00};
+static unsigned char helvetica14_15_bits[] = {
+0x00};
+static unsigned char helvetica14_16_bits[] = {
+0x00};
+static unsigned char helvetica14_17_bits[] = {
+0x00};
+static unsigned char helvetica14_18_bits[] = {
+0x00};
+static unsigned char helvetica14_19_bits[] = {
+0x00};
+static unsigned char helvetica14_20_bits[] = {
+0x00};
+static unsigned char helvetica14_21_bits[] = {
+0x00};
+static unsigned char helvetica14_22_bits[] = {
+0x00};
+static unsigned char helvetica14_23_bits[] = {
+0x00};
+static unsigned char helvetica14_24_bits[] = {
+0x00};
+static unsigned char helvetica14_25_bits[] = {
+0x00};
+static unsigned char helvetica14_26_bits[] = {
+0x00};
+static unsigned char helvetica14_27_bits[] = {
+0x00};
+static unsigned char helvetica14_28_bits[] = {
+0x00};
+static unsigned char helvetica14_29_bits[] = {
+0x00};
+static unsigned char helvetica14_30_bits[] = {
+0x00};
+static unsigned char helvetica14_31_bits[] = {
+0x00};
+static unsigned char helvetica14_32_bits[] = {
+0x00};
+static unsigned char helvetica14_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01};
+static unsigned char helvetica14_34_bits[] = {
+0x05, 0x05, 0x05};
+static unsigned char helvetica14_35_bits[] = {
+0x28, 0x28, 0x28, 0x7e, 0x14, 0x14, 0x3f, 0x0a, 0x0a, 0x0a};
+static unsigned char helvetica14_36_bits[] = {
+0x08, 0x3e, 0x49, 0x49, 0x09, 0x0a, 0x1c, 0x28, 0x48, 0x49, 0x49, 0x3e, 
+0x08, 0x08};
+static unsigned char helvetica14_37_bits[] = {
+0x0e, 0x01, 0x91, 0x00, 0x91, 0x00, 0x4e, 0x00, 0x40, 0x00, 0x20, 0x00, 
+0x10, 0x00, 0x90, 0x03, 0x48, 0x04, 0x48, 0x04, 0x84, 0x03};
+static unsigned char helvetica14_38_bits[] = {
+0x0c, 0x12, 0x12, 0x0c, 0x04, 0x4a, 0x51, 0x21, 0x51, 0x8e};
+static unsigned char helvetica14_39_bits[] = {
+0x03, 0x02, 0x01};
+static unsigned char helvetica14_40_bits[] = {
+0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 
+0x02, 0x04};
+static unsigned char helvetica14_41_bits[] = {
+0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 
+0x02, 0x01};
+static unsigned char helvetica14_42_bits[] = {
+0x04, 0x15, 0x0e, 0x15, 0x04};
+static unsigned char helvetica14_43_bits[] = {
+0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08};
+static unsigned char helvetica14_44_bits[] = {
+0x02, 0x02, 0x02, 0x01};
+static unsigned char helvetica14_45_bits[] = {
+0x7f};
+static unsigned char helvetica14_46_bits[] = {
+0x01, 0x01};
+static unsigned char helvetica14_47_bits[] = {
+0x08, 0x08, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_48_bits[] = {
+0x1e, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x1e};
+static unsigned char helvetica14_49_bits[] = {
+0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04};
+static unsigned char helvetica14_50_bits[] = {
+0x1e, 0x21, 0x21, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x01, 0x3f};
+static unsigned char helvetica14_51_bits[] = {
+0x1e, 0x21, 0x21, 0x20, 0x20, 0x1c, 0x20, 0x20, 0x21, 0x21, 0x1e};
+static unsigned char helvetica14_52_bits[] = {
+0x20, 0x30, 0x28, 0x24, 0x22, 0x21, 0x21, 0x7f, 0x20, 0x20, 0x20};
+static unsigned char helvetica14_53_bits[] = {
+0x3f, 0x01, 0x01, 0x01, 0x1f, 0x20, 0x20, 0x20, 0x21, 0x21, 0x1e};
+static unsigned char helvetica14_54_bits[] = {
+0x1e, 0x21, 0x01, 0x01, 0x1d, 0x23, 0x21, 0x21, 0x21, 0x21, 0x1e};
+static unsigned char helvetica14_55_bits[] = {
+0x3f, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x02};
+static unsigned char helvetica14_56_bits[] = {
+0x1e, 0x21, 0x21, 0x21, 0x21, 0x1e, 0x21, 0x21, 0x21, 0x21, 0x1e};
+static unsigned char helvetica14_57_bits[] = {
+0x1e, 0x21, 0x21, 0x21, 0x21, 0x3e, 0x20, 0x20, 0x21, 0x21, 0x1e};
+static unsigned char helvetica14_58_bits[] = {
+0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01};
+static unsigned char helvetica14_59_bits[] = {
+0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x01};
+static unsigned char helvetica14_60_bits[] = {
+0x30, 0x0c, 0x03, 0x0c, 0x30};
+static unsigned char helvetica14_61_bits[] = {
+0x3f, 0x00, 0x3f};
+static unsigned char helvetica14_62_bits[] = {
+0x03, 0x0c, 0x30, 0x0c, 0x03};
+static unsigned char helvetica14_63_bits[] = {
+0x0c, 0x33, 0x21, 0x21, 0x20, 0x10, 0x08, 0x04, 0x00, 0x04, 0x04};
+static unsigned char helvetica14_64_bits[] = {
+0xf0, 0x00, 0x0c, 0x03, 0x02, 0x04, 0x62, 0x05, 0x91, 0x04, 0x89, 0x04, 
+0x89, 0x04, 0xc9, 0x02, 0xb1, 0x01, 0x02, 0x00, 0x06, 0x01, 0xf8, 0x00};
+static unsigned char helvetica14_65_bits[] = {
+0x10, 0x00, 0x38, 0x00, 0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 
+0x82, 0x00, 0xfe, 0x00, 0x82, 0x00, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_66_bits[] = {
+0x3f, 0x61, 0x41, 0x41, 0x21, 0x1f, 0x21, 0x41, 0x41, 0x61, 0x3f};
+static unsigned char helvetica14_67_bits[] = {
+0x38, 0xc6, 0x82, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0xc6, 0x38};
+static unsigned char helvetica14_68_bits[] = {
+0x1f, 0x61, 0x41, 0x81, 0x81, 0x81, 0x81, 0x81, 0x41, 0x61, 0x1f};
+static unsigned char helvetica14_69_bits[] = {
+0x7f, 0x01, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 0x01, 0x7f};
+static unsigned char helvetica14_70_bits[] = {
+0x7f, 0x01, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_71_bits[] = {
+0x78, 0x00, 0x86, 0x01, 0x02, 0x01, 0x01, 0x00, 0x01, 0x00, 0xe1, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0xc6, 0x01, 0x38, 0x01};
+static unsigned char helvetica14_72_bits[] = {
+0x81, 0x81, 0x81, 0x81, 0x81, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81};
+static unsigned char helvetica14_73_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_74_bits[] = {
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x1e};
+static unsigned char helvetica14_75_bits[] = {
+0x41, 0x21, 0x11, 0x09, 0x05, 0x07, 0x09, 0x11, 0x21, 0x41, 0x81};
+static unsigned char helvetica14_76_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x3f};
+static unsigned char helvetica14_77_bits[] = {
+0x01, 0x04, 0x03, 0x06, 0x03, 0x06, 0x05, 0x05, 0x05, 0x05, 0x89, 0x04, 
+0x89, 0x04, 0x51, 0x04, 0x51, 0x04, 0x21, 0x04, 0x21, 0x04};
+static unsigned char helvetica14_78_bits[] = {
+0x83, 0x85, 0x85, 0x89, 0x89, 0x91, 0x91, 0xa1, 0xa1, 0xc1, 0xc1};
+static unsigned char helvetica14_79_bits[] = {
+0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 0xc6, 0x00, 0x38, 0x00};
+static unsigned char helvetica14_80_bits[] = {
+0x3f, 0x61, 0x41, 0x41, 0x61, 0x3f, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_81_bits[] = {
+0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x11, 0x01, 0x21, 0x01, 0xc2, 0x00, 0xc6, 0x00, 0x38, 0x01};
+static unsigned char helvetica14_82_bits[] = {
+0x7f, 0xc1, 0x81, 0x81, 0x41, 0x3f, 0x41, 0x81, 0x81, 0x81, 0x81};
+static unsigned char helvetica14_83_bits[] = {
+0x1c, 0x63, 0x41, 0x01, 0x06, 0x18, 0x60, 0x40, 0x41, 0x63, 0x1c};
+static unsigned char helvetica14_84_bits[] = {
+0xff, 0x01, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char helvetica14_85_bits[] = {
+0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char helvetica14_86_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 0x82, 0x00, 0xc6, 0x00, 0x44, 0x00, 
+0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char helvetica14_87_bits[] = {
+0x41, 0x10, 0x41, 0x10, 0xa1, 0x10, 0xa2, 0x08, 0xa2, 0x08, 0xa2, 0x08, 
+0x14, 0x05, 0x14, 0x05, 0x14, 0x05, 0x08, 0x02, 0x08, 0x02};
+static unsigned char helvetica14_88_bits[] = {
+0x01, 0x01, 0x82, 0x00, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x82, 0x00, 0x82, 0x00, 0x01, 0x01};
+static unsigned char helvetica14_89_bits[] = {
+0x01, 0x01, 0x83, 0x01, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 
+0x38, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char helvetica14_90_bits[] = {
+0x7f, 0x40, 0x20, 0x10, 0x18, 0x08, 0x04, 0x06, 0x02, 0x01, 0x7f};
+static unsigned char helvetica14_91_bits[] = {
+0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x07};
+static unsigned char helvetica14_92_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08};
+static unsigned char helvetica14_93_bits[] = {
+0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x07};
+static unsigned char helvetica14_94_bits[] = {
+0x04, 0x0a, 0x0a, 0x11, 0x11};
+static unsigned char helvetica14_95_bits[] = {
+0xff};
+static unsigned char helvetica14_96_bits[] = {
+0x02, 0x01, 0x03};
+static unsigned char helvetica14_97_bits[] = {
+0x1e, 0x33, 0x20, 0x3e, 0x23, 0x21, 0x33, 0x6e};
+static unsigned char helvetica14_98_bits[] = {
+0x01, 0x01, 0x01, 0x1d, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1d};
+static unsigned char helvetica14_99_bits[] = {
+0x1e, 0x33, 0x01, 0x01, 0x01, 0x21, 0x33, 0x1e};
+static unsigned char helvetica14_100_bits[] = {
+0x20, 0x20, 0x20, 0x2e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x2e};
+static unsigned char helvetica14_101_bits[] = {
+0x1e, 0x33, 0x21, 0x3f, 0x01, 0x01, 0x33, 0x1e};
+static unsigned char helvetica14_102_bits[] = {
+0x0c, 0x02, 0x02, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica14_103_bits[] = {
+0x2e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x2e, 0x20, 0x33, 0x1e};
+static unsigned char helvetica14_104_bits[] = {
+0x01, 0x01, 0x01, 0x1d, 0x33, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21};
+static unsigned char helvetica14_105_bits[] = {
+0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_106_bits[] = {
+0x04, 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x03};
+static unsigned char helvetica14_107_bits[] = {
+0x01, 0x01, 0x01, 0x11, 0x09, 0x05, 0x03, 0x05, 0x09, 0x11, 0x21};
+static unsigned char helvetica14_108_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_109_bits[] = {
+0xcd, 0x00, 0x33, 0x01, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 
+0x11, 0x01, 0x11, 0x01};
+static unsigned char helvetica14_110_bits[] = {
+0x1d, 0x33, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21};
+static unsigned char helvetica14_111_bits[] = {
+0x1e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char helvetica14_112_bits[] = {
+0x1d, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1d, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_113_bits[] = {
+0x2e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x2e, 0x20, 0x20, 0x20};
+static unsigned char helvetica14_114_bits[] = {
+0x0d, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_115_bits[] = {
+0x0e, 0x11, 0x03, 0x0e, 0x18, 0x10, 0x11, 0x0e};
+static unsigned char helvetica14_116_bits[] = {
+0x02, 0x02, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0c};
+static unsigned char helvetica14_117_bits[] = {
+0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x33, 0x2e};
+static unsigned char helvetica14_118_bits[] = {
+0x41, 0x41, 0x22, 0x22, 0x22, 0x14, 0x14, 0x08};
+static unsigned char helvetica14_119_bits[] = {
+0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x92, 0x00, 0x92, 0x00, 0xaa, 0x00, 
+0x44, 0x00, 0x44, 0x00};
+static unsigned char helvetica14_120_bits[] = {
+0x63, 0x22, 0x14, 0x08, 0x08, 0x14, 0x22, 0x63};
+static unsigned char helvetica14_121_bits[] = {
+0x41, 0x43, 0x22, 0x22, 0x24, 0x14, 0x18, 0x08, 0x08, 0x0c, 0x06};
+static unsigned char helvetica14_122_bits[] = {
+0x3f, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x3f};
+static unsigned char helvetica14_123_bits[] = {
+0x18, 0x04, 0x04, 0x04, 0x04, 0x02, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x18};
+static unsigned char helvetica14_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01};
+static unsigned char helvetica14_125_bits[] = {
+0x03, 0x04, 0x04, 0x04, 0x04, 0x08, 0x10, 0x08, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x03};
+static unsigned char helvetica14_126_bits[] = {
+0x26, 0x2d, 0x19};
+static unsigned char helvetica14_127_bits[] = {
+0x00};
+static unsigned char helvetica14_128_bits[] = {
+0x00};
+static unsigned char helvetica14_129_bits[] = {
+0x00};
+static unsigned char helvetica14_130_bits[] = {
+0x00};
+static unsigned char helvetica14_131_bits[] = {
+0x00};
+static unsigned char helvetica14_132_bits[] = {
+0x00};
+static unsigned char helvetica14_133_bits[] = {
+0x00};
+static unsigned char helvetica14_134_bits[] = {
+0x00};
+static unsigned char helvetica14_135_bits[] = {
+0x00};
+static unsigned char helvetica14_136_bits[] = {
+0x00};
+static unsigned char helvetica14_137_bits[] = {
+0x00};
+static unsigned char helvetica14_138_bits[] = {
+0x00};
+static unsigned char helvetica14_139_bits[] = {
+0x00};
+static unsigned char helvetica14_140_bits[] = {
+0x00};
+static unsigned char helvetica14_141_bits[] = {
+0x00};
+static unsigned char helvetica14_142_bits[] = {
+0x00};
+static unsigned char helvetica14_143_bits[] = {
+0x00};
+static unsigned char helvetica14_144_bits[] = {
+0x00};
+static unsigned char helvetica14_145_bits[] = {
+0x00};
+static unsigned char helvetica14_146_bits[] = {
+0x00};
+static unsigned char helvetica14_147_bits[] = {
+0x00};
+static unsigned char helvetica14_148_bits[] = {
+0x00};
+static unsigned char helvetica14_149_bits[] = {
+0x00};
+static unsigned char helvetica14_150_bits[] = {
+0x00};
+static unsigned char helvetica14_151_bits[] = {
+0x00};
+static unsigned char helvetica14_152_bits[] = {
+0x00};
+static unsigned char helvetica14_153_bits[] = {
+0x00};
+static unsigned char helvetica14_154_bits[] = {
+0x00};
+static unsigned char helvetica14_155_bits[] = {
+0x00};
+static unsigned char helvetica14_156_bits[] = {
+0x00};
+static unsigned char helvetica14_157_bits[] = {
+0x00};
+static unsigned char helvetica14_158_bits[] = {
+0x00};
+static unsigned char helvetica14_159_bits[] = {
+0x00};
+static unsigned char helvetica14_160_bits[] = {
+0x00};
+static unsigned char helvetica14_161_bits[] = {
+0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_162_bits[] = {
+0x20, 0x1e, 0x33, 0x09, 0x09, 0x05, 0x25, 0x33, 0x1e, 0x01};
+static unsigned char helvetica14_163_bits[] = {
+0x1c, 0x22, 0x02, 0x02, 0x1f, 0x04, 0x04, 0x04, 0x02, 0x46, 0x3b};
+static unsigned char helvetica14_164_bits[] = {
+0x21, 0x1e, 0x12, 0x12, 0x1e, 0x21};
+static unsigned char helvetica14_165_bits[] = {
+0x41, 0x41, 0x41, 0x22, 0x22, 0x14, 0x7f, 0x08, 0x7f, 0x08, 0x08};
+static unsigned char helvetica14_166_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01};
+static unsigned char helvetica14_167_bits[] = {
+0x0e, 0x1b, 0x11, 0x03, 0x0e, 0x19, 0x11, 0x11, 0x13, 0x0e, 0x18, 0x11, 
+0x1b, 0x0e};
+static unsigned char helvetica14_168_bits[] = {
+0x1b};
+static unsigned char helvetica14_169_bits[] = {
+0x78, 0x00, 0x86, 0x01, 0x3a, 0x01, 0x45, 0x03, 0x45, 0x02, 0x05, 0x02, 
+0x45, 0x02, 0x39, 0x02, 0x02, 0x01, 0x86, 0x01, 0x78, 0x00};
+static unsigned char helvetica14_170_bits[] = {
+0x07, 0x08, 0x0e, 0x09, 0x0b, 0x00, 0x0f};
+static unsigned char helvetica14_171_bits[] = {
+0x24, 0x12, 0x09, 0x12, 0x24};
+static unsigned char helvetica14_172_bits[] = {
+0x7f, 0x40, 0x40, 0x40};
+static unsigned char helvetica14_173_bits[] = {
+0x07};
+static unsigned char helvetica14_174_bits[] = {
+0x78, 0x00, 0x86, 0x01, 0x3a, 0x01, 0x49, 0x02, 0x49, 0x02, 0x39, 0x02, 
+0x49, 0x02, 0x49, 0x02, 0x02, 0x01, 0x86, 0x01, 0x78, 0x00};
+static unsigned char helvetica14_175_bits[] = {
+0x0f};
+static unsigned char helvetica14_176_bits[] = {
+0x06, 0x09, 0x09, 0x06};
+static unsigned char helvetica14_177_bits[] = {
+0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08, 0x00, 0x7f};
+static unsigned char helvetica14_178_bits[] = {
+0x06, 0x09, 0x08, 0x04, 0x02, 0x0f};
+static unsigned char helvetica14_179_bits[] = {
+0x06, 0x09, 0x04, 0x08, 0x09, 0x06};
+static unsigned char helvetica14_180_bits[] = {
+0x02, 0x01};
+static unsigned char helvetica14_181_bits[] = {
+0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x33, 0x2d, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_182_bits[] = {
+0x7c, 0x2e, 0x2f, 0x2f, 0x2f, 0x2e, 0x2c, 0x28, 0x28, 0x28, 0x28, 0x28, 
+0x28, 0x28};
+static unsigned char helvetica14_183_bits[] = {
+0x03};
+static unsigned char helvetica14_184_bits[] = {
+0x04, 0x09, 0x06};
+static unsigned char helvetica14_185_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica14_186_bits[] = {
+0x06, 0x09, 0x09, 0x09, 0x06, 0x00, 0x0f};
+static unsigned char helvetica14_187_bits[] = {
+0x09, 0x12, 0x24, 0x12, 0x09};
+static unsigned char helvetica14_188_bits[] = {
+0x42, 0x00, 0x43, 0x00, 0x22, 0x00, 0x22, 0x00, 0x12, 0x00, 0x12, 0x01, 
+0x90, 0x01, 0x48, 0x01, 0x28, 0x01, 0xe4, 0x03, 0x04, 0x01};
+static unsigned char helvetica14_189_bits[] = {
+0x42, 0x00, 0x43, 0x00, 0x22, 0x00, 0x22, 0x00, 0x12, 0x00, 0xd2, 0x00, 
+0x28, 0x01, 0x08, 0x01, 0x88, 0x00, 0x44, 0x00, 0xe4, 0x01};
+static unsigned char helvetica14_190_bits[] = {
+0x86, 0x00, 0x89, 0x00, 0x44, 0x00, 0x48, 0x00, 0x29, 0x00, 0x26, 0x02, 
+0x20, 0x03, 0x90, 0x02, 0x50, 0x02, 0xc8, 0x07, 0x08, 0x02};
+static unsigned char helvetica14_191_bits[] = {
+0x08, 0x08, 0x00, 0x08, 0x04, 0x02, 0x01, 0x21, 0x21, 0x33, 0x0c};
+static unsigned char helvetica14_192_bits[] = {
+0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x38, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x82, 0x00, 0xfe, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_193_bits[] = {
+0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x38, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x82, 0x00, 0xfe, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_194_bits[] = {
+0x30, 0x00, 0x48, 0x00, 0x00, 0x00, 0x10, 0x00, 0x38, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x82, 0x00, 0xfe, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_195_bits[] = {
+0x58, 0x00, 0x34, 0x00, 0x00, 0x00, 0x10, 0x00, 0x38, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x82, 0x00, 0xfe, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_196_bits[] = {
+0x6c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x38, 0x00, 0x28, 0x00, 0x28, 0x00, 
+0x44, 0x00, 0x44, 0x00, 0x82, 0x00, 0xfe, 0x00, 0x82, 0x00, 0x01, 0x01, 
+0x01, 0x01};
+static unsigned char helvetica14_197_bits[] = {
+0x30, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, 0x00, 0x30, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x82, 0x00, 0xfe, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_198_bits[] = {
+0xf8, 0x0f, 0x48, 0x00, 0x48, 0x00, 0x44, 0x00, 0x44, 0x00, 0xc4, 0x0f, 
+0x7e, 0x00, 0x42, 0x00, 0x42, 0x00, 0x41, 0x00, 0xc1, 0x0f};
+static unsigned char helvetica14_199_bits[] = {
+0x38, 0xc6, 0x82, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0xc6, 0x38, 0x10, 
+0x24, 0x18};
+static unsigned char helvetica14_200_bits[] = {
+0x04, 0x08, 0x00, 0x7f, 0x01, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 
+0x01, 0x7f};
+static unsigned char helvetica14_201_bits[] = {
+0x10, 0x08, 0x00, 0x7f, 0x01, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 
+0x01, 0x7f};
+static unsigned char helvetica14_202_bits[] = {
+0x18, 0x24, 0x00, 0x7f, 0x01, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 
+0x01, 0x7f};
+static unsigned char helvetica14_203_bits[] = {
+0x36, 0x00, 0x7f, 0x01, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 0x01, 
+0x7f};
+static unsigned char helvetica14_204_bits[] = {
+0x01, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
+0x02, 0x02};
+static unsigned char helvetica14_205_bits[] = {
+0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01};
+static unsigned char helvetica14_206_bits[] = {
+0x06, 0x09, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
+0x02, 0x02};
+static unsigned char helvetica14_207_bits[] = {
+0x1b, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04};
+static unsigned char helvetica14_208_bits[] = {
+0x3e, 0x00, 0xc2, 0x00, 0x82, 0x00, 0x02, 0x01, 0x02, 0x01, 0x0f, 0x01, 
+0x02, 0x01, 0x02, 0x01, 0x82, 0x00, 0xc2, 0x00, 0x3e, 0x00};
+static unsigned char helvetica14_209_bits[] = {
+0x58, 0x34, 0x00, 0x83, 0x85, 0x85, 0x89, 0x89, 0x91, 0x91, 0xa1, 0xa1, 
+0xc1, 0xc1};
+static unsigned char helvetica14_210_bits[] = {
+0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 
+0xc6, 0x00, 0x38, 0x00};
+static unsigned char helvetica14_211_bits[] = {
+0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 
+0xc6, 0x00, 0x38, 0x00};
+static unsigned char helvetica14_212_bits[] = {
+0x30, 0x00, 0x48, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 
+0xc6, 0x00, 0x38, 0x00};
+static unsigned char helvetica14_213_bits[] = {
+0x58, 0x00, 0x34, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 
+0xc6, 0x00, 0x38, 0x00};
+static unsigned char helvetica14_214_bits[] = {
+0xcc, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 0xc6, 0x00, 
+0x38, 0x00};
+static unsigned char helvetica14_215_bits[] = {
+0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41};
+static unsigned char helvetica14_216_bits[] = {
+0x70, 0x04, 0x8c, 0x03, 0x04, 0x01, 0x82, 0x02, 0x42, 0x02, 0x22, 0x02, 
+0x12, 0x02, 0x0a, 0x02, 0x04, 0x01, 0x8e, 0x01, 0x71, 0x00};
+static unsigned char helvetica14_217_bits[] = {
+0x08, 0x10, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 
+0x42, 0x3c};
+static unsigned char helvetica14_218_bits[] = {
+0x20, 0x10, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 
+0x42, 0x3c};
+static unsigned char helvetica14_219_bits[] = {
+0x18, 0x24, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 
+0x42, 0x3c};
+static unsigned char helvetica14_220_bits[] = {
+0x66, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 
+0x3c};
+static unsigned char helvetica14_221_bits[] = {
+0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x83, 0x01, 0x82, 0x00, 
+0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x38, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00};
+static unsigned char helvetica14_222_bits[] = {
+0x01, 0x01, 0x3f, 0x61, 0x41, 0x41, 0x61, 0x3f, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_223_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x0d, 0x09, 0x11, 0x11, 0x11, 0x11, 0x0d};
+static unsigned char helvetica14_224_bits[] = {
+0x04, 0x08, 0x00, 0x1e, 0x33, 0x20, 0x3e, 0x23, 0x21, 0x33, 0x6e};
+static unsigned char helvetica14_225_bits[] = {
+0x08, 0x04, 0x00, 0x1e, 0x33, 0x20, 0x3e, 0x23, 0x21, 0x33, 0x6e};
+static unsigned char helvetica14_226_bits[] = {
+0x0c, 0x12, 0x00, 0x1e, 0x33, 0x20, 0x3e, 0x23, 0x21, 0x33, 0x6e};
+static unsigned char helvetica14_227_bits[] = {
+0x2c, 0x1a, 0x00, 0x1e, 0x33, 0x20, 0x3e, 0x23, 0x21, 0x33, 0x6e};
+static unsigned char helvetica14_228_bits[] = {
+0x12, 0x12, 0x00, 0x1e, 0x33, 0x20, 0x3e, 0x23, 0x21, 0x33, 0x6e};
+static unsigned char helvetica14_229_bits[] = {
+0x0c, 0x12, 0x0c, 0x00, 0x1e, 0x33, 0x20, 0x3e, 0x23, 0x21, 0x33, 0x6e};
+static unsigned char helvetica14_230_bits[] = {
+0xde, 0x03, 0x63, 0x06, 0x20, 0x04, 0xfe, 0x07, 0x23, 0x00, 0x21, 0x00, 
+0x73, 0x06, 0xde, 0x03};
+static unsigned char helvetica14_231_bits[] = {
+0x1e, 0x33, 0x01, 0x01, 0x01, 0x21, 0x33, 0x1e, 0x08, 0x12, 0x0c};
+static unsigned char helvetica14_232_bits[] = {
+0x04, 0x08, 0x00, 0x1e, 0x33, 0x21, 0x3f, 0x01, 0x01, 0x33, 0x1e};
+static unsigned char helvetica14_233_bits[] = {
+0x08, 0x04, 0x00, 0x1e, 0x33, 0x21, 0x3f, 0x01, 0x01, 0x33, 0x1e};
+static unsigned char helvetica14_234_bits[] = {
+0x0c, 0x12, 0x00, 0x1e, 0x33, 0x21, 0x3f, 0x01, 0x01, 0x33, 0x1e};
+static unsigned char helvetica14_235_bits[] = {
+0x12, 0x12, 0x00, 0x1e, 0x33, 0x21, 0x3f, 0x01, 0x01, 0x33, 0x1e};
+static unsigned char helvetica14_236_bits[] = {
+0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_237_bits[] = {
+0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_238_bits[] = {
+0x06, 0x09, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica14_239_bits[] = {
+0x05, 0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica14_240_bits[] = {
+0x1b, 0x0e, 0x09, 0x1e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char helvetica14_241_bits[] = {
+0x16, 0x0d, 0x00, 0x1d, 0x33, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21};
+static unsigned char helvetica14_242_bits[] = {
+0x04, 0x08, 0x00, 0x1e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char helvetica14_243_bits[] = {
+0x08, 0x04, 0x00, 0x1e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char helvetica14_244_bits[] = {
+0x0c, 0x12, 0x00, 0x1e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char helvetica14_245_bits[] = {
+0x16, 0x0d, 0x00, 0x1e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char helvetica14_246_bits[] = {
+0x12, 0x12, 0x00, 0x1e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char helvetica14_247_bits[] = {
+0x08, 0x08, 0x00, 0x7f, 0x00, 0x08, 0x08};
+static unsigned char helvetica14_248_bits[] = {
+0xbc, 0x46, 0x62, 0x52, 0x4a, 0x46, 0x62, 0x3d};
+static unsigned char helvetica14_249_bits[] = {
+0x04, 0x08, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x33, 0x2e};
+static unsigned char helvetica14_250_bits[] = {
+0x08, 0x04, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x33, 0x2e};
+static unsigned char helvetica14_251_bits[] = {
+0x0c, 0x12, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x33, 0x2e};
+static unsigned char helvetica14_252_bits[] = {
+0x12, 0x12, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x33, 0x2e};
+static unsigned char helvetica14_253_bits[] = {
+0x10, 0x08, 0x00, 0x41, 0x43, 0x22, 0x22, 0x24, 0x14, 0x18, 0x08, 0x08, 
+0x0c, 0x06};
+static unsigned char helvetica14_254_bits[] = {
+0x01, 0x01, 0x01, 0x1d, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1d, 0x01, 
+0x01, 0x01};
+static unsigned char helvetica14_255_bits[] = {
+0x24, 0x24, 0x00, 0x41, 0x43, 0x22, 0x22, 0x24, 0x14, 0x18, 0x08, 0x08, 
+0x0c, 0x06};
+static RotFont helvetica14font[] = {
+{5, 1, 1, helvetica14_0_bits},
+{5, 1, 1, helvetica14_1_bits},
+{5, 1, 1, helvetica14_2_bits},
+{5, 1, 1, helvetica14_3_bits},
+{5, 1, 1, helvetica14_4_bits},
+{5, 1, 1, helvetica14_5_bits},
+{5, 1, 1, helvetica14_6_bits},
+{5, 1, 1, helvetica14_7_bits},
+{5, 1, 1, helvetica14_8_bits},
+{5, 1, 1, helvetica14_9_bits},
+{5, 1, 1, helvetica14_10_bits},
+{5, 1, 1, helvetica14_11_bits},
+{5, 1, 1, helvetica14_12_bits},
+{5, 1, 1, helvetica14_13_bits},
+{5, 1, 1, helvetica14_14_bits},
+{5, 1, 1, helvetica14_15_bits},
+{5, 1, 1, helvetica14_16_bits},
+{5, 1, 1, helvetica14_17_bits},
+{5, 1, 1, helvetica14_18_bits},
+{5, 1, 1, helvetica14_19_bits},
+{5, 1, 1, helvetica14_20_bits},
+{5, 1, 1, helvetica14_21_bits},
+{5, 1, 1, helvetica14_22_bits},
+{5, 1, 1, helvetica14_23_bits},
+{5, 1, 1, helvetica14_24_bits},
+{5, 1, 1, helvetica14_25_bits},
+{5, 1, 1, helvetica14_26_bits},
+{5, 1, 1, helvetica14_27_bits},
+{5, 1, 1, helvetica14_28_bits},
+{5, 1, 1, helvetica14_29_bits},
+{5, 1, 1, helvetica14_30_bits},
+{5, 1, 1, helvetica14_31_bits},
+{7, 1, 1, helvetica14_32_bits},
+{1, 11, 11, helvetica14_33_bits},
+{3, 3, 11, helvetica14_34_bits},
+{7, 10, 10, helvetica14_35_bits},
+{7, 14, 12, helvetica14_36_bits},
+{11, 11, 11, helvetica14_37_bits},
+{8, 10, 10, helvetica14_38_bits},
+{2, 3, 11, helvetica14_39_bits},
+{3, 14, 11, helvetica14_40_bits},
+{3, 14, 11, helvetica14_41_bits},
+{5, 5, 11, helvetica14_42_bits},
+{7, 7, 8, helvetica14_43_bits},
+{2, 4, 2, helvetica14_44_bits},
+{7, 1, 5, helvetica14_45_bits},
+{1, 2, 2, helvetica14_46_bits},
+{4, 11, 11, helvetica14_47_bits},
+{6, 11, 11, helvetica14_48_bits},
+{3, 11, 11, helvetica14_49_bits},
+{6, 11, 11, helvetica14_50_bits},
+{6, 11, 11, helvetica14_51_bits},
+{7, 11, 11, helvetica14_52_bits},
+{6, 11, 11, helvetica14_53_bits},
+{6, 11, 11, helvetica14_54_bits},
+{6, 11, 11, helvetica14_55_bits},
+{6, 11, 11, helvetica14_56_bits},
+{6, 11, 11, helvetica14_57_bits},
+{1, 8, 8, helvetica14_58_bits},
+{2, 10, 8, helvetica14_59_bits},
+{6, 5, 7, helvetica14_60_bits},
+{6, 3, 6, helvetica14_61_bits},
+{6, 5, 7, helvetica14_62_bits},
+{6, 11, 11, helvetica14_63_bits},
+{11, 12, 11, helvetica14_64_bits},
+{9, 11, 11, helvetica14_65_bits},
+{7, 11, 11, helvetica14_66_bits},
+{8, 11, 11, helvetica14_67_bits},
+{8, 11, 11, helvetica14_68_bits},
+{7, 11, 11, helvetica14_69_bits},
+{7, 11, 11, helvetica14_70_bits},
+{9, 11, 11, helvetica14_71_bits},
+{8, 11, 11, helvetica14_72_bits},
+{1, 11, 11, helvetica14_73_bits},
+{6, 11, 11, helvetica14_74_bits},
+{8, 11, 11, helvetica14_75_bits},
+{6, 11, 11, helvetica14_76_bits},
+{11, 11, 11, helvetica14_77_bits},
+{8, 11, 11, helvetica14_78_bits},
+{9, 11, 11, helvetica14_79_bits},
+{7, 11, 11, helvetica14_80_bits},
+{9, 11, 11, helvetica14_81_bits},
+{8, 11, 11, helvetica14_82_bits},
+{7, 11, 11, helvetica14_83_bits},
+{9, 11, 11, helvetica14_84_bits},
+{8, 11, 11, helvetica14_85_bits},
+{9, 11, 11, helvetica14_86_bits},
+{13, 11, 11, helvetica14_87_bits},
+{9, 11, 11, helvetica14_88_bits},
+{9, 11, 11, helvetica14_89_bits},
+{7, 11, 11, helvetica14_90_bits},
+{3, 14, 11, helvetica14_91_bits},
+{4, 11, 11, helvetica14_92_bits},
+{3, 14, 11, helvetica14_93_bits},
+{5, 5, 11, helvetica14_94_bits},
+{8, 1, -2, helvetica14_95_bits},
+{2, 3, 11, helvetica14_96_bits},
+{7, 8, 8, helvetica14_97_bits},
+{6, 11, 11, helvetica14_98_bits},
+{6, 8, 8, helvetica14_99_bits},
+{6, 11, 11, helvetica14_100_bits},
+{6, 8, 8, helvetica14_101_bits},
+{4, 11, 11, helvetica14_102_bits},
+{6, 11, 8, helvetica14_103_bits},
+{6, 11, 11, helvetica14_104_bits},
+{1, 11, 11, helvetica14_105_bits},
+{3, 14, 11, helvetica14_106_bits},
+{6, 11, 11, helvetica14_107_bits},
+{1, 11, 11, helvetica14_108_bits},
+{9, 8, 8, helvetica14_109_bits},
+{6, 8, 8, helvetica14_110_bits},
+{6, 8, 8, helvetica14_111_bits},
+{6, 11, 8, helvetica14_112_bits},
+{6, 11, 8, helvetica14_113_bits},
+{4, 8, 8, helvetica14_114_bits},
+{5, 8, 8, helvetica14_115_bits},
+{4, 10, 10, helvetica14_116_bits},
+{6, 8, 8, helvetica14_117_bits},
+{7, 8, 8, helvetica14_118_bits},
+{9, 8, 8, helvetica14_119_bits},
+{7, 8, 8, helvetica14_120_bits},
+{7, 11, 8, helvetica14_121_bits},
+{6, 8, 8, helvetica14_122_bits},
+{5, 14, 11, helvetica14_123_bits},
+{1, 14, 11, helvetica14_124_bits},
+{5, 14, 11, helvetica14_125_bits},
+{6, 3, 6, helvetica14_126_bits},
+{5, 1, 1, helvetica14_127_bits},
+{5, 1, 1, helvetica14_128_bits},
+{5, 1, 1, helvetica14_129_bits},
+{5, 1, 1, helvetica14_130_bits},
+{5, 1, 1, helvetica14_131_bits},
+{5, 1, 1, helvetica14_132_bits},
+{5, 1, 1, helvetica14_133_bits},
+{5, 1, 1, helvetica14_134_bits},
+{5, 1, 1, helvetica14_135_bits},
+{5, 1, 1, helvetica14_136_bits},
+{5, 1, 1, helvetica14_137_bits},
+{5, 1, 1, helvetica14_138_bits},
+{5, 1, 1, helvetica14_139_bits},
+{5, 1, 1, helvetica14_140_bits},
+{5, 1, 1, helvetica14_141_bits},
+{5, 1, 1, helvetica14_142_bits},
+{5, 1, 1, helvetica14_143_bits},
+{5, 1, 1, helvetica14_144_bits},
+{5, 1, 1, helvetica14_145_bits},
+{5, 1, 1, helvetica14_146_bits},
+{5, 1, 1, helvetica14_147_bits},
+{5, 1, 1, helvetica14_148_bits},
+{5, 1, 1, helvetica14_149_bits},
+{5, 1, 1, helvetica14_150_bits},
+{5, 1, 1, helvetica14_151_bits},
+{5, 1, 1, helvetica14_152_bits},
+{5, 1, 1, helvetica14_153_bits},
+{5, 1, 1, helvetica14_154_bits},
+{5, 1, 1, helvetica14_155_bits},
+{5, 1, 1, helvetica14_156_bits},
+{5, 1, 1, helvetica14_157_bits},
+{5, 1, 1, helvetica14_158_bits},
+{5, 1, 1, helvetica14_159_bits},
+{1, 1, 1, helvetica14_160_bits},
+{1, 11, 8, helvetica14_161_bits},
+{6, 10, 9, helvetica14_162_bits},
+{7, 11, 11, helvetica14_163_bits},
+{6, 6, 8, helvetica14_164_bits},
+{7, 11, 11, helvetica14_165_bits},
+{1, 14, 11, helvetica14_166_bits},
+{5, 14, 11, helvetica14_167_bits},
+{5, 1, 10, helvetica14_168_bits},
+{10, 11, 11, helvetica14_169_bits},
+{4, 7, 11, helvetica14_170_bits},
+{6, 5, 7, helvetica14_171_bits},
+{7, 4, 6, helvetica14_172_bits},
+{3, 1, 5, helvetica14_173_bits},
+{10, 11, 11, helvetica14_174_bits},
+{4, 1, 10, helvetica14_175_bits},
+{4, 4, 11, helvetica14_176_bits},
+{7, 9, 9, helvetica14_177_bits},
+{4, 6, 11, helvetica14_178_bits},
+{4, 6, 11, helvetica14_179_bits},
+{2, 2, 11, helvetica14_180_bits},
+{6, 11, 8, helvetica14_181_bits},
+{7, 14, 11, helvetica14_182_bits},
+{2, 1, 5, helvetica14_183_bits},
+{4, 3, 0, helvetica14_184_bits},
+{2, 6, 11, helvetica14_185_bits},
+{4, 7, 11, helvetica14_186_bits},
+{6, 5, 7, helvetica14_187_bits},
+{10, 11, 11, helvetica14_188_bits},
+{9, 11, 11, helvetica14_189_bits},
+{11, 11, 11, helvetica14_190_bits},
+{6, 11, 8, helvetica14_191_bits},
+{9, 14, 14, helvetica14_192_bits},
+{9, 14, 14, helvetica14_193_bits},
+{9, 14, 14, helvetica14_194_bits},
+{9, 14, 14, helvetica14_195_bits},
+{9, 13, 13, helvetica14_196_bits},
+{9, 14, 14, helvetica14_197_bits},
+{12, 11, 11, helvetica14_198_bits},
+{8, 14, 11, helvetica14_199_bits},
+{7, 14, 14, helvetica14_200_bits},
+{7, 14, 14, helvetica14_201_bits},
+{7, 14, 14, helvetica14_202_bits},
+{7, 13, 13, helvetica14_203_bits},
+{2, 14, 14, helvetica14_204_bits},
+{2, 14, 14, helvetica14_205_bits},
+{4, 14, 14, helvetica14_206_bits},
+{5, 13, 13, helvetica14_207_bits},
+{9, 11, 11, helvetica14_208_bits},
+{8, 14, 14, helvetica14_209_bits},
+{9, 14, 14, helvetica14_210_bits},
+{9, 14, 14, helvetica14_211_bits},
+{9, 14, 14, helvetica14_212_bits},
+{9, 14, 14, helvetica14_213_bits},
+{9, 13, 13, helvetica14_214_bits},
+{7, 7, 8, helvetica14_215_bits},
+{11, 11, 11, helvetica14_216_bits},
+{8, 14, 14, helvetica14_217_bits},
+{8, 14, 14, helvetica14_218_bits},
+{8, 14, 14, helvetica14_219_bits},
+{8, 13, 13, helvetica14_220_bits},
+{9, 14, 14, helvetica14_221_bits},
+{7, 11, 11, helvetica14_222_bits},
+{5, 11, 11, helvetica14_223_bits},
+{7, 11, 11, helvetica14_224_bits},
+{7, 11, 11, helvetica14_225_bits},
+{7, 11, 11, helvetica14_226_bits},
+{7, 11, 11, helvetica14_227_bits},
+{7, 11, 11, helvetica14_228_bits},
+{7, 12, 12, helvetica14_229_bits},
+{11, 8, 8, helvetica14_230_bits},
+{6, 11, 8, helvetica14_231_bits},
+{6, 11, 11, helvetica14_232_bits},
+{6, 11, 11, helvetica14_233_bits},
+{6, 11, 11, helvetica14_234_bits},
+{6, 11, 11, helvetica14_235_bits},
+{2, 11, 11, helvetica14_236_bits},
+{2, 11, 11, helvetica14_237_bits},
+{4, 11, 11, helvetica14_238_bits},
+{3, 11, 11, helvetica14_239_bits},
+{6, 11, 11, helvetica14_240_bits},
+{6, 11, 11, helvetica14_241_bits},
+{6, 11, 11, helvetica14_242_bits},
+{6, 11, 11, helvetica14_243_bits},
+{6, 11, 11, helvetica14_244_bits},
+{6, 11, 11, helvetica14_245_bits},
+{6, 11, 11, helvetica14_246_bits},
+{7, 7, 8, helvetica14_247_bits},
+{8, 8, 8, helvetica14_248_bits},
+{6, 11, 11, helvetica14_249_bits},
+{6, 11, 11, helvetica14_250_bits},
+{6, 11, 11, helvetica14_251_bits},
+{6, 11, 11, helvetica14_252_bits},
+{7, 14, 11, helvetica14_253_bits},
+{6, 14, 11, helvetica14_254_bits},
+{7, 14, 11, helvetica14_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/helvetica18.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/helvetica18.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/helvetica18.bdf	(revision 12606)
@@ -0,0 +1,3830 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Helvetica-Medium-R-Normal--18-180-75-75-P-98-ISO8859-1
+SIZE 18 75 75
+FONTBOUNDINGBOX 18 22 -1 -4
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Helvetica"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 18
+POINT_SIZE 180
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 98
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 14
+X_HEIGHT 10
+FACE_NAME "Helvetica"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.  "
+_DEC_DEVICE_FONTNAMES "PS=Helvetica"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 11-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Helvetica"
+FONT "-Adobe-Helvetica-Medium-R-Normal--18-180-75-75-P-98-ISO8859-1"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 11
+DEFAULT_CHAR 32
+FONT_ASCENT 16
+FONT_DESCENT 5
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 2 14 2 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+80
+80
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 5 0 9
+BITMAP
+d8
+d8
+d8
+90
+90
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 10 13 0 0
+BITMAP
+0900
+0900
+0900
+7fc0
+7fc0
+1200
+1200
+1200
+ff80
+ff80
+2400
+2400
+2400
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 16 1 -2
+BITMAP
+0800
+3e00
+7f00
+cb00
+c800
+e800
+7800
+3e00
+0f00
+0980
+c980
+eb80
+7f00
+3e00
+0800
+0800
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 853 0
+DWIDTH 16 0
+BBX 14 13 1 0
+BITMAP
+7860
+fcc0
+ccc0
+cd80
+fd80
+7b00
+0300
+0678
+06fc
+0ccc
+0ccc
+18fc
+1878
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 13 1 0
+BITMAP
+3c00
+7e00
+6600
+6600
+3c00
+7c00
+eec0
+c6c0
+c3c0
+c380
+e7c0
+7ee0
+3c70
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 5 1 9
+BITMAP
+c0
+c0
+40
+40
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 18 1 -4
+BITMAP
+10
+30
+60
+60
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+60
+60
+30
+10
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 18 1 -4
+BITMAP
+80
+c0
+60
+60
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+60
+60
+c0
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 6 1 8
+BITMAP
+20
+20
+f8
+70
+70
+88
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+18
+18
+18
+18
+ff
+ff
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 2 5 1 -3
+BITMAP
+c0
+c0
+40
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 2 1 4
+BITMAP
+ff
+ff
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 2 2 1 0
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 14 0 0
+BITMAP
+18
+18
+10
+10
+30
+30
+20
+20
+60
+60
+40
+40
+c0
+c0
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3c
+7e
+66
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+66
+7e
+3c
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 5 13 2 0
+BITMAP
+18
+f8
+f8
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3c
+fe
+c3
+03
+07
+0e
+1c
+38
+70
+e0
+c0
+ff
+ff
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3c
+7e
+c3
+c3
+06
+1c
+1e
+07
+03
+c3
+c7
+7e
+3c
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 13 1 0
+BITMAP
+0300
+0700
+0f00
+1b00
+3300
+3300
+6300
+c300
+ff80
+ff80
+0300
+0300
+0300
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+fe
+fe
+c0
+c0
+fc
+fe
+c7
+03
+03
+c3
+c7
+fe
+7c
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3c
+7f
+63
+c0
+c0
+dc
+fe
+c3
+c3
+c3
+e3
+7e
+3c
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+ff
+ff
+03
+06
+0c
+0c
+18
+18
+30
+30
+30
+60
+60
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3c
+7e
+e7
+c3
+c3
+66
+7e
+66
+c3
+c3
+e7
+7e
+3c
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3c
+7e
+c7
+c3
+c3
+c3
+7f
+3b
+03
+03
+c6
+fe
+7c
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 2 10 1 0
+BITMAP
+c0
+c0
+00
+00
+00
+00
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 2 13 1 -3
+BITMAP
+c0
+c0
+00
+00
+00
+00
+00
+00
+c0
+c0
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+03
+0f
+3c
+70
+c0
+70
+3c
+0f
+03
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 6 2 2
+BITMAP
+fe
+fe
+00
+00
+fe
+fe
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+c0
+f0
+3c
+0e
+03
+0e
+3c
+f0
+c0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 7 14 1 0
+BITMAP
+7c
+fe
+c6
+c6
+0e
+1c
+38
+30
+30
+30
+00
+00
+30
+30
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 16 17 1 -3
+BITMAP
+03f0
+0ffc
+1c0e
+3006
+63b3
+6773
+c633
+cc63
+cc66
+cc66
+cccc
+cff8
+6770
+7000
+3800
+1ff0
+07e0
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 14 0 0
+BITMAP
+0600
+0600
+0f00
+0f00
+1980
+1980
+30c0
+30c0
+3fc0
+7fe0
+6060
+6060
+c030
+c030
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+ff00
+ff80
+c1c0
+c0c0
+c0c0
+c180
+ff80
+ffc0
+c0e0
+c060
+c060
+c0e0
+ffc0
+ff80
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 14 1 0
+BITMAP
+0f80
+3fe0
+7070
+6030
+e000
+c000
+c000
+c000
+c000
+e000
+6030
+7070
+3fe0
+0f80
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+ff00
+ff80
+c1c0
+c0c0
+c060
+c060
+c060
+c060
+c060
+c060
+c0c0
+c1c0
+ff80
+ff00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+ff80
+ff80
+c000
+c000
+c000
+c000
+ff00
+ff00
+c000
+c000
+c000
+c000
+ff80
+ff80
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+ff80
+ff80
+c000
+c000
+c000
+c000
+ff00
+ff00
+c000
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 14 1 0
+BITMAP
+0f80
+3fe0
+7070
+6030
+e030
+c000
+c000
+c1f0
+c1f0
+e030
+6030
+7070
+3ff0
+0fb0
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+c060
+c060
+c060
+c060
+c060
+c060
+ffe0
+ffe0
+c060
+c060
+c060
+c060
+c060
+c060
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 2 14 2 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+03
+03
+03
+03
+03
+03
+03
+03
+03
+c3
+c3
+e7
+7e
+3c
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 14 1 0
+BITMAP
+c0e0
+c1c0
+c380
+c700
+ce00
+dc00
+f800
+fc00
+ce00
+c700
+c380
+c1c0
+c0e0
+c070
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ff
+ff
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 853 0
+DWIDTH 16 0
+BBX 14 14 1 0
+BITMAP
+c00c
+c00c
+e01c
+e01c
+f03c
+f03c
+d86c
+d86c
+cccc
+cccc
+c48c
+c78c
+c30c
+c30c
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+c060
+e060
+f060
+f060
+d860
+cc60
+cc60
+c660
+c660
+c360
+c1e0
+c1e0
+c0e0
+c060
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 14 1 0
+BITMAP
+0f80
+3fe0
+7070
+6030
+e038
+c018
+c018
+c018
+c018
+e038
+6030
+7070
+3fe0
+0f80
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+ff00
+ff80
+c1c0
+c0c0
+c0c0
+c1c0
+ff80
+ff00
+c000
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 15 1 -1
+BITMAP
+0f80
+3fe0
+7070
+6030
+e038
+c018
+c018
+c018
+c018
+e1b8
+61b0
+70f0
+3fe0
+0fb0
+0030
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+ff00
+ff80
+c1c0
+c0c0
+c0c0
+c1c0
+ff80
+ff00
+c180
+c180
+c0c0
+c0c0
+c0c0
+c0c0
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+1f00
+7fc0
+e0e0
+c060
+e000
+7c00
+1f00
+03c0
+00e0
+0060
+c060
+e0e0
+7fc0
+3f00
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+ffc0
+ffc0
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+7fc0
+1f00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 14 1 0
+BITMAP
+c030
+c030
+6060
+6060
+6060
+30c0
+30c0
+30c0
+1980
+1980
+1980
+0f00
+0f00
+0600
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 16 14 1 0
+BITMAP
+c183
+c183
+c183
+c3c3
+63c6
+6246
+6666
+6666
+366c
+366c
+342c
+1c38
+1818
+1818
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+c060
+e0e0
+60c0
+71c0
+3180
+1b00
+0e00
+0e00
+1b00
+3180
+71c0
+60c0
+e0e0
+c060
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 14 1 0
+BITMAP
+c030
+c030
+6060
+6060
+30c0
+30c0
+1980
+0f00
+0600
+0600
+0600
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+ffc0
+ffc0
+00c0
+0180
+0300
+0600
+0c00
+1c00
+1800
+3000
+6000
+c000
+ffc0
+ffc0
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 4 18 1 -4
+BITMAP
+f0
+f0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+f0
+f0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 14 0 0
+BITMAP
+c0
+c0
+40
+40
+60
+60
+20
+20
+30
+30
+10
+10
+18
+18
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 4 18 0 -4
+BITMAP
+f0
+f0
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+f0
+f0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 5 1 8
+BITMAP
+10
+38
+6c
+c6
+82
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 10 2 0 -4
+BITMAP
+ffc0
+ffc0
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 5 1 9
+BITMAP
+40
+80
+80
+c0
+c0
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+7c
+ee
+c6
+0e
+7e
+e6
+c6
+c6
+ee
+76
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+c000
+c000
+c000
+c000
+de00
+ff00
+e300
+c180
+c180
+c180
+c180
+e300
+ff00
+de00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+3e
+7f
+63
+c0
+c0
+c0
+c0
+63
+7f
+3e
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+0180
+0180
+0180
+0180
+3d80
+7f80
+6380
+c180
+c180
+c180
+c180
+6380
+7f80
+3d80
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+3c
+7e
+c3
+c3
+ff
+c0
+c0
+e3
+7f
+3c
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 14 0 0
+BITMAP
+1c
+3c
+30
+30
+fc
+fc
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 -4
+BITMAP
+3d80
+7f80
+6180
+c180
+c180
+c180
+c180
+6380
+7f80
+3d80
+0180
+6300
+7f00
+1c00
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+c0
+c0
+c0
+c0
+ce
+df
+e3
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 14 1 0
+BITMAP
+c0
+c0
+00
+00
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 4 18 -1 -4
+BITMAP
+30
+30
+00
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+f0
+e0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 14 1 0
+BITMAP
+c0
+c0
+c0
+c0
+c6
+cc
+d8
+f0
+f8
+d8
+cc
+ce
+c6
+c7
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 14 1 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 10 1 0
+BITMAP
+cc60
+def0
+e730
+c630
+c630
+c630
+c630
+c630
+c630
+c630
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+ce
+df
+e3
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+3e00
+7f00
+6300
+c180
+c180
+c180
+c180
+6300
+7f00
+3e00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 -4
+BITMAP
+de00
+ff00
+e300
+c180
+c180
+c180
+c180
+e300
+ff00
+de00
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 -4
+BITMAP
+3d80
+7f80
+6380
+c180
+c180
+c180
+c180
+6380
+7f80
+3d80
+0180
+0180
+0180
+0180
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 10 1 0
+BITMAP
+d8
+d8
+e0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+3c
+7e
+c6
+c0
+fc
+3e
+06
+c6
+fc
+78
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 13 0 0
+BITMAP
+30
+30
+30
+fc
+fc
+30
+30
+30
+30
+30
+30
+38
+18
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+c7
+fb
+73
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+c3
+c3
+c3
+66
+66
+66
+24
+3c
+18
+18
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 10 1 0
+BITMAP
+c630
+c630
+c630
+6660
+6660
+6960
+2940
+39c0
+1980
+1980
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+c3
+e7
+66
+3c
+18
+18
+3c
+66
+e7
+c3
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 -4
+BITMAP
+c3
+c3
+c3
+66
+66
+66
+24
+3c
+18
+18
+18
+18
+70
+70
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+fe
+fe
+06
+0c
+18
+30
+60
+c0
+fe
+fe
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 18 0 -4
+BITMAP
+0c
+18
+30
+30
+30
+30
+30
+60
+c0
+60
+30
+30
+30
+30
+30
+30
+18
+0c
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 18 1 -4
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 18 0 -4
+BITMAP
+c0
+60
+30
+30
+30
+30
+30
+18
+0c
+18
+30
+30
+30
+30
+30
+30
+60
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 3 1 4
+BITMAP
+33
+7e
+cc
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 2 14 2 -4
+BITMAP
+c0
+c0
+00
+00
+40
+40
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 -2
+BITMAP
+04
+04
+3e
+7f
+6b
+c8
+c8
+c8
+c8
+6b
+7f
+3e
+10
+10
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 13 0 0
+BITMAP
+1e00
+3f00
+6180
+6180
+6000
+3000
+7e00
+1800
+1800
+3000
+6080
+ff80
+df00
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 7 1 3
+BITMAP
+c3
+ff
+66
+66
+66
+ff
+c3
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+c3
+c3
+66
+66
+66
+3c
+ff
+18
+ff
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 17 1 -3
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+00
+00
+00
+00
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 18 1 -4
+BITMAP
+3c
+7e
+c3
+c3
+f0
+7c
+6e
+c7
+c3
+e3
+73
+3e
+0e
+07
+c3
+c3
+7e
+3c
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 2 0 11
+BITMAP
+d8
+d8
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+0f80
+3060
+4010
+4710
+8888
+9008
+9008
+9008
+8888
+4710
+4010
+3060
+0f80
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 8 1 6
+BITMAP
+70
+c8
+38
+48
+d8
+68
+00
+f8
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 8 1 1
+BITMAP
+12
+36
+6c
+d8
+d8
+6c
+36
+12
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 5 1 3
+BITMAP
+ff80
+ff80
+0180
+0180
+0180
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 2 1 4
+BITMAP
+f8
+f8
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 13 13 1 0
+BITMAP
+0f80
+3060
+4010
+4f90
+8848
+8848
+8f88
+8908
+8888
+4850
+4010
+3060
+0f80
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 1 0 12
+BITMAP
+f8
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 5 1 8
+BITMAP
+70
+d8
+88
+d8
+70
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+18
+18
+18
+ff
+ff
+18
+18
+18
+00
+ff
+ff
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 8 0 5
+BITMAP
+70
+f8
+98
+18
+30
+60
+f8
+f8
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 8 0 5
+BITMAP
+70
+f8
+98
+30
+30
+98
+f8
+70
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 4 3 0 11
+BITMAP
+30
+60
+c0
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 -4
+BITMAP
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+e7
+ff
+db
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 18 1 -4
+BITMAP
+3f
+72
+f2
+f2
+f2
+f2
+72
+32
+12
+12
+12
+12
+12
+12
+12
+12
+12
+12
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 2 1 4
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 5 0 -4
+BITMAP
+60
+70
+18
+d8
+f0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 3 8 1 5
+BITMAP
+60
+e0
+e0
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 8 1 6
+BITMAP
+70
+d8
+88
+88
+d8
+70
+00
+f8
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 8 1 1
+BITMAP
+90
+d8
+6c
+36
+36
+6c
+d8
+90
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+6060
+e060
+e0c0
+6180
+6180
+6310
+6230
+6670
+0cf0
+0db0
+19f8
+3030
+3030
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+6060
+e060
+e0c0
+6180
+6180
+6370
+62f8
+6698
+0c18
+0c30
+1860
+30f8
+30f8
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 14 13 0 0
+BITMAP
+7030
+f830
+9860
+30c0
+30c0
+9988
+f918
+7338
+0678
+06d8
+0cfc
+1818
+1818
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 7 14 1 -4
+BITMAP
+18
+18
+00
+00
+18
+18
+18
+38
+70
+e0
+c6
+c6
+fe
+7c
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 18 0 0
+BITMAP
+1800
+0c00
+0600
+0000
+0600
+0600
+0f00
+0f00
+1980
+1980
+30c0
+30c0
+3fc0
+7fe0
+6060
+6060
+c030
+c030
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 18 0 0
+BITMAP
+0180
+0300
+0600
+0000
+0600
+0600
+0f00
+0f00
+1980
+1980
+30c0
+30c0
+3fc0
+7fe0
+6060
+6060
+c030
+c030
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 18 0 0
+BITMAP
+0600
+0f00
+1980
+0000
+0600
+0600
+0f00
+0f00
+1980
+1980
+30c0
+30c0
+3fc0
+7fe0
+6060
+6060
+c030
+c030
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 18 0 0
+BITMAP
+0c80
+1680
+1300
+0000
+0600
+0600
+0f00
+0f00
+1980
+1980
+30c0
+30c0
+3fc0
+7fe0
+6060
+6060
+c030
+c030
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 17 0 0
+BITMAP
+1980
+1980
+0000
+0600
+0600
+0f00
+0f00
+1980
+1980
+30c0
+30c0
+3fc0
+7fe0
+6060
+6060
+c030
+c030
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 18 0 0
+BITMAP
+0f00
+1980
+1980
+0f00
+0600
+0600
+0f00
+0f00
+1980
+1980
+30c0
+30c0
+3fc0
+7fe0
+6060
+6060
+c030
+c030
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 16 14 1 0
+BITMAP
+07ff
+07ff
+0d80
+0d80
+1980
+1980
+31fe
+31fe
+3f80
+7f80
+6180
+6180
+c1ff
+c1ff
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 18 1 -4
+BITMAP
+0f80
+3fe0
+7070
+6030
+e000
+c000
+c000
+c000
+c000
+e000
+6030
+7070
+3fe0
+0f80
+0e00
+0300
+1b00
+1e00
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 18 1 0
+BITMAP
+3000
+1800
+0c00
+0000
+ff80
+ff80
+c000
+c000
+c000
+c000
+ff00
+ff00
+c000
+c000
+c000
+c000
+ff80
+ff80
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 18 1 0
+BITMAP
+0300
+0600
+0c00
+0000
+ff80
+ff80
+c000
+c000
+c000
+c000
+ff00
+ff00
+c000
+c000
+c000
+c000
+ff80
+ff80
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 18 1 0
+BITMAP
+0c00
+1e00
+3300
+0000
+ff80
+ff80
+c000
+c000
+c000
+c000
+ff00
+ff00
+c000
+c000
+c000
+c000
+ff80
+ff80
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+3300
+3300
+0000
+ff80
+ff80
+c000
+c000
+c000
+c000
+ff00
+ff00
+c000
+c000
+c000
+c000
+ff80
+ff80
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 18 0 0
+BITMAP
+c0
+60
+30
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 18 2 0
+BITMAP
+30
+60
+c0
+00
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 18 0 0
+BITMAP
+30
+78
+cc
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 17 0 0
+BITMAP
+cc
+cc
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 14 0 0
+BITMAP
+7f80
+7fc0
+60e0
+6060
+6030
+6030
+fc30
+fc30
+6030
+6030
+6060
+60e0
+7fc0
+7f80
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+0c80
+1680
+1300
+0000
+e060
+e060
+f060
+d860
+d860
+cc60
+cc60
+c660
+c660
+c360
+c1e0
+c1e0
+c0e0
+c060
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 18 1 0
+BITMAP
+0c00
+0600
+0300
+0000
+0f80
+3fe0
+7070
+6030
+e038
+c018
+c018
+c018
+c018
+e038
+6030
+7070
+3fe0
+0f80
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 18 1 0
+BITMAP
+00c0
+0180
+0300
+0000
+0f80
+3fe0
+7070
+6030
+e038
+c018
+c018
+c018
+c018
+e038
+6030
+7070
+3fe0
+0f80
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 18 1 0
+BITMAP
+0300
+0780
+0cc0
+0000
+0f80
+3fe0
+7070
+6030
+e038
+c018
+c018
+c018
+c018
+e038
+6030
+7070
+3fe0
+0f80
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 18 1 0
+BITMAP
+0640
+0b40
+0980
+0000
+0f80
+3fe0
+7070
+6030
+e038
+c018
+c018
+c018
+c018
+e038
+6030
+7070
+3fe0
+0f80
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+0d80
+0d80
+0000
+0f80
+3fe0
+7070
+6030
+e038
+c018
+c018
+c018
+c018
+e038
+6030
+7070
+3fe0
+0f80
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 10 9 0 0
+BITMAP
+c0c0
+6180
+3300
+1e00
+0c00
+1e00
+3300
+6180
+c0c0
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 14 14 0 0
+BITMAP
+07cc
+1ffc
+3838
+3078
+70dc
+61cc
+638c
+670c
+6e0c
+6c1c
+3818
+7838
+fff0
+c7c0
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+1800
+0c00
+0600
+0000
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+7fc0
+1f00
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+0300
+0600
+0c00
+0000
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+7fc0
+1f00
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+0600
+0f00
+1980
+0000
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+7fc0
+1f00
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+1980
+1980
+0000
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+7fc0
+1f00
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 18 1 0
+BITMAP
+0180
+0300
+0600
+0000
+c030
+c030
+6060
+6060
+30c0
+30c0
+1980
+0f00
+0600
+0600
+0600
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+c000
+c000
+c000
+ff00
+ff80
+c1c0
+c0c0
+c0c0
+c1c0
+ff80
+ff00
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+38
+7c
+c6
+c6
+c6
+c6
+dc
+dc
+c6
+c6
+c6
+c6
+de
+dc
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+60
+30
+18
+00
+7c
+ee
+c6
+0e
+7e
+e6
+c6
+c6
+ee
+76
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+0c
+18
+30
+00
+7c
+ee
+c6
+0e
+7e
+e6
+c6
+c6
+ee
+76
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+18
+3c
+66
+00
+7c
+ee
+c6
+0e
+7e
+e6
+c6
+c6
+ee
+76
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+32
+5a
+4c
+00
+7c
+ee
+c6
+0e
+7e
+e6
+c6
+c6
+ee
+76
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+6c
+6c
+00
+7c
+ee
+c6
+0e
+7e
+e6
+c6
+c6
+ee
+76
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+38
+6c
+6c
+38
+7c
+ee
+c6
+0e
+7e
+e6
+c6
+c6
+ee
+76
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 10 1 0
+BITMAP
+7de0
+eff0
+c618
+0e18
+7ff8
+e600
+c600
+c718
+eff8
+75e0
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 -4
+BITMAP
+3e
+7f
+63
+c0
+c0
+c0
+c0
+63
+7f
+3e
+38
+0c
+6c
+78
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+60
+30
+18
+00
+3c
+7e
+c3
+c3
+ff
+c0
+c0
+e3
+7f
+3c
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+06
+0c
+18
+00
+3c
+7e
+c3
+c3
+ff
+c0
+c0
+e3
+7f
+3c
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+18
+3c
+66
+00
+3c
+7e
+c3
+c3
+ff
+c0
+c0
+e3
+7f
+3c
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+36
+36
+00
+3c
+7e
+c3
+c3
+ff
+c0
+c0
+e3
+7f
+3c
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 4 14 0 0
+BITMAP
+c0
+60
+30
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 4 14 0 0
+BITMAP
+30
+60
+c0
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 6 14 -1 0
+BITMAP
+30
+78
+cc
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 5 13 0 0
+BITMAP
+d8
+d8
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+6000
+3600
+3800
+4c00
+3e00
+7f00
+6300
+c180
+c180
+c180
+c180
+6300
+7f00
+3e00
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+32
+5a
+4c
+00
+ce
+df
+e3
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+3000
+1800
+0c00
+0000
+3e00
+7f00
+6300
+c180
+c180
+c180
+c180
+6300
+7f00
+3e00
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+0600
+0c00
+1800
+0000
+3e00
+7f00
+6300
+c180
+c180
+c180
+c180
+6300
+7f00
+3e00
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+0c00
+1e00
+3300
+0000
+3e00
+7f00
+6300
+c180
+c180
+c180
+c180
+6300
+7f00
+3e00
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+1900
+2d00
+2600
+0000
+3e00
+7f00
+6300
+c180
+c180
+c180
+c180
+6300
+7f00
+3e00
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+3600
+3600
+0000
+3e00
+7f00
+6300
+c180
+c180
+c180
+c180
+6300
+7f00
+3e00
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 8 1 1
+BITMAP
+18
+18
+00
+ff
+ff
+00
+18
+18
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 10 0 0
+BITMAP
+0e60
+3fc0
+3180
+63c0
+66c0
+6cc0
+78c0
+3180
+7f80
+ce00
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+30
+18
+0c
+00
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+c7
+fb
+73
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+06
+0c
+18
+00
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+c7
+fb
+73
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+18
+3c
+66
+00
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+c7
+fb
+73
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+66
+66
+00
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+c7
+fb
+73
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 18 1 -4
+BITMAP
+06
+0c
+18
+00
+c3
+c3
+c3
+66
+66
+66
+24
+3c
+18
+18
+18
+18
+70
+70
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 18 1 -4
+BITMAP
+c000
+c000
+c000
+c000
+de00
+ff00
+e300
+c180
+c180
+c180
+c180
+e300
+ff00
+de00
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 17 1 -4
+BITMAP
+66
+66
+00
+c3
+c3
+c3
+66
+66
+66
+24
+3c
+18
+18
+18
+18
+70
+70
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/helvetica18.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/helvetica18.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/helvetica18.h	(revision 12606)
@@ -0,0 +1,988 @@
+static unsigned char helvetica18_0_bits[] = {
+0x00};
+static unsigned char helvetica18_1_bits[] = {
+0x00};
+static unsigned char helvetica18_2_bits[] = {
+0x00};
+static unsigned char helvetica18_3_bits[] = {
+0x00};
+static unsigned char helvetica18_4_bits[] = {
+0x00};
+static unsigned char helvetica18_5_bits[] = {
+0x00};
+static unsigned char helvetica18_6_bits[] = {
+0x00};
+static unsigned char helvetica18_7_bits[] = {
+0x00};
+static unsigned char helvetica18_8_bits[] = {
+0x00};
+static unsigned char helvetica18_9_bits[] = {
+0x00};
+static unsigned char helvetica18_10_bits[] = {
+0x00};
+static unsigned char helvetica18_11_bits[] = {
+0x00};
+static unsigned char helvetica18_12_bits[] = {
+0x00};
+static unsigned char helvetica18_13_bits[] = {
+0x00};
+static unsigned char helvetica18_14_bits[] = {
+0x00};
+static unsigned char helvetica18_15_bits[] = {
+0x00};
+static unsigned char helvetica18_16_bits[] = {
+0x00};
+static unsigned char helvetica18_17_bits[] = {
+0x00};
+static unsigned char helvetica18_18_bits[] = {
+0x00};
+static unsigned char helvetica18_19_bits[] = {
+0x00};
+static unsigned char helvetica18_20_bits[] = {
+0x00};
+static unsigned char helvetica18_21_bits[] = {
+0x00};
+static unsigned char helvetica18_22_bits[] = {
+0x00};
+static unsigned char helvetica18_23_bits[] = {
+0x00};
+static unsigned char helvetica18_24_bits[] = {
+0x00};
+static unsigned char helvetica18_25_bits[] = {
+0x00};
+static unsigned char helvetica18_26_bits[] = {
+0x00};
+static unsigned char helvetica18_27_bits[] = {
+0x00};
+static unsigned char helvetica18_28_bits[] = {
+0x00};
+static unsigned char helvetica18_29_bits[] = {
+0x00};
+static unsigned char helvetica18_30_bits[] = {
+0x00};
+static unsigned char helvetica18_31_bits[] = {
+0x00};
+static unsigned char helvetica18_32_bits[] = {
+0x00};
+static unsigned char helvetica18_33_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 
+0x03, 0x03};
+static unsigned char helvetica18_34_bits[] = {
+0x1b, 0x1b, 0x1b, 0x09, 0x09};
+static unsigned char helvetica18_35_bits[] = {
+0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0xfe, 0x03, 0xfe, 0x03, 0x48, 0x00, 
+0x48, 0x00, 0x48, 0x00, 0xff, 0x01, 0xff, 0x01, 0x24, 0x00, 0x24, 0x00, 
+0x24, 0x00};
+static unsigned char helvetica18_36_bits[] = {
+0x10, 0x00, 0x7c, 0x00, 0xfe, 0x00, 0xd3, 0x00, 0x13, 0x00, 0x17, 0x00, 
+0x1e, 0x00, 0x7c, 0x00, 0xf0, 0x00, 0x90, 0x01, 0x93, 0x01, 0xd7, 0x01, 
+0xfe, 0x00, 0x7c, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char helvetica18_37_bits[] = {
+0x1e, 0x06, 0x3f, 0x03, 0x33, 0x03, 0xb3, 0x01, 0xbf, 0x01, 0xde, 0x00, 
+0xc0, 0x00, 0x60, 0x1e, 0x60, 0x3f, 0x30, 0x33, 0x30, 0x33, 0x18, 0x3f, 
+0x18, 0x1e};
+static unsigned char helvetica18_38_bits[] = {
+0x3c, 0x00, 0x7e, 0x00, 0x66, 0x00, 0x66, 0x00, 0x3c, 0x00, 0x3e, 0x00, 
+0x77, 0x03, 0x63, 0x03, 0xc3, 0x03, 0xc3, 0x01, 0xe7, 0x03, 0x7e, 0x07, 
+0x3c, 0x0e};
+static unsigned char helvetica18_39_bits[] = {
+0x03, 0x03, 0x02, 0x02, 0x01};
+static unsigned char helvetica18_40_bits[] = {
+0x08, 0x0c, 0x06, 0x06, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x06, 0x06, 0x0c, 0x08};
+static unsigned char helvetica18_41_bits[] = {
+0x01, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x06, 0x06, 0x03, 0x01};
+static unsigned char helvetica18_42_bits[] = {
+0x04, 0x04, 0x1f, 0x0e, 0x0e, 0x11};
+static unsigned char helvetica18_43_bits[] = {
+0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18};
+static unsigned char helvetica18_44_bits[] = {
+0x03, 0x03, 0x02, 0x02, 0x01};
+static unsigned char helvetica18_45_bits[] = {
+0xff, 0xff};
+static unsigned char helvetica18_46_bits[] = {
+0x03, 0x03};
+static unsigned char helvetica18_47_bits[] = {
+0x18, 0x18, 0x08, 0x08, 0x0c, 0x0c, 0x04, 0x04, 0x06, 0x06, 0x02, 0x02, 
+0x03, 0x03};
+static unsigned char helvetica18_48_bits[] = {
+0x3c, 0x7e, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x7e, 
+0x3c};
+static unsigned char helvetica18_49_bits[] = {
+0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18};
+static unsigned char helvetica18_50_bits[] = {
+0x3c, 0x7f, 0xc3, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x07, 0x03, 0xff, 
+0xff};
+static unsigned char helvetica18_51_bits[] = {
+0x3c, 0x7e, 0xc3, 0xc3, 0x60, 0x38, 0x78, 0xe0, 0xc0, 0xc3, 0xe3, 0x7e, 
+0x3c};
+static unsigned char helvetica18_52_bits[] = {
+0xc0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xd8, 0x00, 0xcc, 0x00, 0xcc, 0x00, 
+0xc6, 0x00, 0xc3, 0x00, 0xff, 0x01, 0xff, 0x01, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00};
+static unsigned char helvetica18_53_bits[] = {
+0x7f, 0x7f, 0x03, 0x03, 0x3f, 0x7f, 0xe3, 0xc0, 0xc0, 0xc3, 0xe3, 0x7f, 
+0x3e};
+static unsigned char helvetica18_54_bits[] = {
+0x3c, 0xfe, 0xc6, 0x03, 0x03, 0x3b, 0x7f, 0xc3, 0xc3, 0xc3, 0xc7, 0x7e, 
+0x3c};
+static unsigned char helvetica18_55_bits[] = {
+0xff, 0xff, 0xc0, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x0c, 0x06, 
+0x06};
+static unsigned char helvetica18_56_bits[] = {
+0x3c, 0x7e, 0xe7, 0xc3, 0xc3, 0x66, 0x7e, 0x66, 0xc3, 0xc3, 0xe7, 0x7e, 
+0x3c};
+static unsigned char helvetica18_57_bits[] = {
+0x3c, 0x7e, 0xe3, 0xc3, 0xc3, 0xc3, 0xfe, 0xdc, 0xc0, 0xc0, 0x63, 0x7f, 
+0x3e};
+static unsigned char helvetica18_58_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03};
+static unsigned char helvetica18_59_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x02, 0x02, 
+0x01};
+static unsigned char helvetica18_60_bits[] = {
+0xc0, 0xf0, 0x3c, 0x0e, 0x03, 0x0e, 0x3c, 0xf0, 0xc0};
+static unsigned char helvetica18_61_bits[] = {
+0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f};
+static unsigned char helvetica18_62_bits[] = {
+0x03, 0x0f, 0x3c, 0x70, 0xc0, 0x70, 0x3c, 0x0f, 0x03};
+static unsigned char helvetica18_63_bits[] = {
+0x3e, 0x7f, 0x63, 0x63, 0x70, 0x38, 0x1c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 
+0x0c, 0x0c};
+static unsigned char helvetica18_64_bits[] = {
+0xc0, 0x0f, 0xf0, 0x3f, 0x38, 0x70, 0x0c, 0x60, 0xc6, 0xcd, 0xe6, 0xce, 
+0x63, 0xcc, 0x33, 0xc6, 0x33, 0x66, 0x33, 0x66, 0x33, 0x33, 0xf3, 0x1f, 
+0xe6, 0x0e, 0x0e, 0x00, 0x1c, 0x00, 0xf8, 0x0f, 0xe0, 0x07};
+static unsigned char helvetica18_65_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 
+0x0c, 0x03, 0x0c, 0x03, 0xfc, 0x03, 0xfe, 0x07, 0x06, 0x06, 0x06, 0x06, 
+0x03, 0x0c, 0x03, 0x0c};
+static unsigned char helvetica18_66_bits[] = {
+0xff, 0x00, 0xff, 0x01, 0x83, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x01, 
+0xff, 0x01, 0xff, 0x03, 0x03, 0x07, 0x03, 0x06, 0x03, 0x06, 0x03, 0x07, 
+0xff, 0x03, 0xff, 0x01};
+static unsigned char helvetica18_67_bits[] = {
+0xf0, 0x01, 0xfc, 0x07, 0x0e, 0x0e, 0x06, 0x0c, 0x07, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x07, 0x00, 0x06, 0x0c, 0x0e, 0x0e, 
+0xfc, 0x07, 0xf0, 0x01};
+static unsigned char helvetica18_68_bits[] = {
+0xff, 0x00, 0xff, 0x01, 0x83, 0x03, 0x03, 0x03, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x03, 0x83, 0x03, 
+0xff, 0x01, 0xff, 0x00};
+static unsigned char helvetica18_69_bits[] = {
+0xff, 0x01, 0xff, 0x01, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0xff, 0x00, 0xff, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0xff, 0x01, 0xff, 0x01};
+static unsigned char helvetica18_70_bits[] = {
+0xff, 0x01, 0xff, 0x01, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0xff, 0x00, 0xff, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00};
+static unsigned char helvetica18_71_bits[] = {
+0xf0, 0x01, 0xfc, 0x07, 0x0e, 0x0e, 0x06, 0x0c, 0x07, 0x0c, 0x03, 0x00, 
+0x03, 0x00, 0x83, 0x0f, 0x83, 0x0f, 0x07, 0x0c, 0x06, 0x0c, 0x0e, 0x0e, 
+0xfc, 0x0f, 0xf0, 0x0d};
+static unsigned char helvetica18_72_bits[] = {
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0xff, 0x07, 0xff, 0x07, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06};
+static unsigned char helvetica18_73_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03};
+static unsigned char helvetica18_74_bits[] = {
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc3, 0xc3, 0xe7, 
+0x7e, 0x3c};
+static unsigned char helvetica18_75_bits[] = {
+0x03, 0x07, 0x83, 0x03, 0xc3, 0x01, 0xe3, 0x00, 0x73, 0x00, 0x3b, 0x00, 
+0x1f, 0x00, 0x3f, 0x00, 0x73, 0x00, 0xe3, 0x00, 0xc3, 0x01, 0x83, 0x03, 
+0x03, 0x07, 0x03, 0x0e};
+static unsigned char helvetica18_76_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0xff, 0xff};
+static unsigned char helvetica18_77_bits[] = {
+0x03, 0x30, 0x03, 0x30, 0x07, 0x38, 0x07, 0x38, 0x0f, 0x3c, 0x0f, 0x3c, 
+0x1b, 0x36, 0x1b, 0x36, 0x33, 0x33, 0x33, 0x33, 0x23, 0x31, 0xe3, 0x31, 
+0xc3, 0x30, 0xc3, 0x30};
+static unsigned char helvetica18_78_bits[] = {
+0x03, 0x06, 0x07, 0x06, 0x0f, 0x06, 0x0f, 0x06, 0x1b, 0x06, 0x33, 0x06, 
+0x33, 0x06, 0x63, 0x06, 0x63, 0x06, 0xc3, 0x06, 0x83, 0x07, 0x83, 0x07, 
+0x03, 0x07, 0x03, 0x06};
+static unsigned char helvetica18_79_bits[] = {
+0xf0, 0x01, 0xfc, 0x07, 0x0e, 0x0e, 0x06, 0x0c, 0x07, 0x1c, 0x03, 0x18, 
+0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x07, 0x1c, 0x06, 0x0c, 0x0e, 0x0e, 
+0xfc, 0x07, 0xf0, 0x01};
+static unsigned char helvetica18_80_bits[] = {
+0xff, 0x00, 0xff, 0x01, 0x83, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 
+0xff, 0x01, 0xff, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00};
+static unsigned char helvetica18_81_bits[] = {
+0xf0, 0x01, 0xfc, 0x07, 0x0e, 0x0e, 0x06, 0x0c, 0x07, 0x1c, 0x03, 0x18, 
+0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x87, 0x1d, 0x86, 0x0d, 0x0e, 0x0f, 
+0xfc, 0x07, 0xf0, 0x0d, 0x00, 0x0c};
+static unsigned char helvetica18_82_bits[] = {
+0xff, 0x00, 0xff, 0x01, 0x83, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 
+0xff, 0x01, 0xff, 0x00, 0x83, 0x01, 0x83, 0x01, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica18_83_bits[] = {
+0xf8, 0x00, 0xfe, 0x03, 0x07, 0x07, 0x03, 0x06, 0x07, 0x00, 0x3e, 0x00, 
+0xf8, 0x00, 0xc0, 0x03, 0x00, 0x07, 0x00, 0x06, 0x03, 0x06, 0x07, 0x07, 
+0xfe, 0x03, 0xfc, 0x00};
+static unsigned char helvetica18_84_bits[] = {
+0xff, 0x03, 0xff, 0x03, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00};
+static unsigned char helvetica18_85_bits[] = {
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 
+0xfe, 0x03, 0xf8, 0x00};
+static unsigned char helvetica18_86_bits[] = {
+0x03, 0x0c, 0x03, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 
+0x0c, 0x03, 0x0c, 0x03, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0xf0, 0x00, 
+0xf0, 0x00, 0x60, 0x00};
+static unsigned char helvetica18_87_bits[] = {
+0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0xc3, 0xc3, 0xc6, 0x63, 0x46, 0x62, 
+0x66, 0x66, 0x66, 0x66, 0x6c, 0x36, 0x6c, 0x36, 0x2c, 0x34, 0x38, 0x1c, 
+0x18, 0x18, 0x18, 0x18};
+static unsigned char helvetica18_88_bits[] = {
+0x03, 0x06, 0x07, 0x07, 0x06, 0x03, 0x8e, 0x03, 0x8c, 0x01, 0xd8, 0x00, 
+0x70, 0x00, 0x70, 0x00, 0xd8, 0x00, 0x8c, 0x01, 0x8e, 0x03, 0x06, 0x03, 
+0x07, 0x07, 0x03, 0x06};
+static unsigned char helvetica18_89_bits[] = {
+0x03, 0x0c, 0x03, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 0x0c, 0x03, 
+0x98, 0x01, 0xf0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00};
+static unsigned char helvetica18_90_bits[] = {
+0xff, 0x03, 0xff, 0x03, 0x00, 0x03, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 
+0x30, 0x00, 0x38, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x03, 0x00, 
+0xff, 0x03, 0xff, 0x03};
+static unsigned char helvetica18_91_bits[] = {
+0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x0f, 0x0f};
+static unsigned char helvetica18_92_bits[] = {
+0x03, 0x03, 0x02, 0x02, 0x06, 0x06, 0x04, 0x04, 0x0c, 0x0c, 0x08, 0x08, 
+0x18, 0x18};
+static unsigned char helvetica18_93_bits[] = {
+0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f};
+static unsigned char helvetica18_94_bits[] = {
+0x08, 0x1c, 0x36, 0x63, 0x41};
+static unsigned char helvetica18_95_bits[] = {
+0xff, 0x03, 0xff, 0x03};
+static unsigned char helvetica18_96_bits[] = {
+0x02, 0x01, 0x01, 0x03, 0x03};
+static unsigned char helvetica18_97_bits[] = {
+0x3e, 0x77, 0x63, 0x70, 0x7e, 0x67, 0x63, 0x63, 0x77, 0x6e};
+static unsigned char helvetica18_98_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x7b, 0x00, 0xff, 0x00, 
+0xc7, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc7, 0x00, 
+0xff, 0x00, 0x7b, 0x00};
+static unsigned char helvetica18_99_bits[] = {
+0x7c, 0xfe, 0xc6, 0x03, 0x03, 0x03, 0x03, 0xc6, 0xfe, 0x7c};
+static unsigned char helvetica18_100_bits[] = {
+0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xbc, 0x01, 0xfe, 0x01, 
+0xc6, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc6, 0x01, 
+0xfe, 0x01, 0xbc, 0x01};
+static unsigned char helvetica18_101_bits[] = {
+0x3c, 0x7e, 0xc3, 0xc3, 0xff, 0x03, 0x03, 0xc7, 0xfe, 0x3c};
+static unsigned char helvetica18_102_bits[] = {
+0x38, 0x3c, 0x0c, 0x0c, 0x3f, 0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c};
+static unsigned char helvetica18_103_bits[] = {
+0xbc, 0x01, 0xfe, 0x01, 0x86, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 
+0x83, 0x01, 0xc6, 0x01, 0xfe, 0x01, 0xbc, 0x01, 0x80, 0x01, 0xc6, 0x00, 
+0xfe, 0x00, 0x38, 0x00};
+static unsigned char helvetica18_104_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x73, 0xfb, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 
+0xc3, 0xc3};
+static unsigned char helvetica18_105_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03};
+static unsigned char helvetica18_106_bits[] = {
+0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x07};
+static unsigned char helvetica18_107_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x63, 0x33, 0x1b, 0x0f, 0x1f, 0x1b, 0x33, 0x73, 
+0x63, 0xe3};
+static unsigned char helvetica18_108_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03};
+static unsigned char helvetica18_109_bits[] = {
+0x33, 0x06, 0x7b, 0x0f, 0xe7, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 
+0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c};
+static unsigned char helvetica18_110_bits[] = {
+0x73, 0xfb, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3};
+static unsigned char helvetica18_111_bits[] = {
+0x7c, 0x00, 0xfe, 0x00, 0xc6, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 
+0x83, 0x01, 0xc6, 0x00, 0xfe, 0x00, 0x7c, 0x00};
+static unsigned char helvetica18_112_bits[] = {
+0x7b, 0x00, 0xff, 0x00, 0xc7, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 
+0x83, 0x01, 0xc7, 0x00, 0xff, 0x00, 0x7b, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00};
+static unsigned char helvetica18_113_bits[] = {
+0xbc, 0x01, 0xfe, 0x01, 0xc6, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 
+0x83, 0x01, 0xc6, 0x01, 0xfe, 0x01, 0xbc, 0x01, 0x80, 0x01, 0x80, 0x01, 
+0x80, 0x01, 0x80, 0x01};
+static unsigned char helvetica18_114_bits[] = {
+0x1b, 0x1b, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica18_115_bits[] = {
+0x3c, 0x7e, 0x63, 0x03, 0x3f, 0x7c, 0x60, 0x63, 0x3f, 0x1e};
+static unsigned char helvetica18_116_bits[] = {
+0x0c, 0x0c, 0x0c, 0x3f, 0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x1c, 
+0x18};
+static unsigned char helvetica18_117_bits[] = {
+0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe3, 0xdf, 0xce};
+static unsigned char helvetica18_118_bits[] = {
+0xc3, 0xc3, 0xc3, 0x66, 0x66, 0x66, 0x24, 0x3c, 0x18, 0x18};
+static unsigned char helvetica18_119_bits[] = {
+0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x66, 0x06, 0x66, 0x06, 0x96, 0x06, 
+0x94, 0x02, 0x9c, 0x03, 0x98, 0x01, 0x98, 0x01};
+static unsigned char helvetica18_120_bits[] = {
+0xc3, 0xe7, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x66, 0xe7, 0xc3};
+static unsigned char helvetica18_121_bits[] = {
+0xc3, 0xc3, 0xc3, 0x66, 0x66, 0x66, 0x24, 0x3c, 0x18, 0x18, 0x18, 0x18, 
+0x0e, 0x0e};
+static unsigned char helvetica18_122_bits[] = {
+0x7f, 0x7f, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x7f, 0x7f};
+static unsigned char helvetica18_123_bits[] = {
+0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30};
+static unsigned char helvetica18_124_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica18_125_bits[] = {
+0x03, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x18, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x06, 0x03};
+static unsigned char helvetica18_126_bits[] = {
+0xcc, 0x7e, 0x33};
+static unsigned char helvetica18_127_bits[] = {
+0x00};
+static unsigned char helvetica18_128_bits[] = {
+0x00};
+static unsigned char helvetica18_129_bits[] = {
+0x00};
+static unsigned char helvetica18_130_bits[] = {
+0x00};
+static unsigned char helvetica18_131_bits[] = {
+0x00};
+static unsigned char helvetica18_132_bits[] = {
+0x00};
+static unsigned char helvetica18_133_bits[] = {
+0x00};
+static unsigned char helvetica18_134_bits[] = {
+0x00};
+static unsigned char helvetica18_135_bits[] = {
+0x00};
+static unsigned char helvetica18_136_bits[] = {
+0x00};
+static unsigned char helvetica18_137_bits[] = {
+0x00};
+static unsigned char helvetica18_138_bits[] = {
+0x00};
+static unsigned char helvetica18_139_bits[] = {
+0x00};
+static unsigned char helvetica18_140_bits[] = {
+0x00};
+static unsigned char helvetica18_141_bits[] = {
+0x00};
+static unsigned char helvetica18_142_bits[] = {
+0x00};
+static unsigned char helvetica18_143_bits[] = {
+0x00};
+static unsigned char helvetica18_144_bits[] = {
+0x00};
+static unsigned char helvetica18_145_bits[] = {
+0x00};
+static unsigned char helvetica18_146_bits[] = {
+0x00};
+static unsigned char helvetica18_147_bits[] = {
+0x00};
+static unsigned char helvetica18_148_bits[] = {
+0x00};
+static unsigned char helvetica18_149_bits[] = {
+0x00};
+static unsigned char helvetica18_150_bits[] = {
+0x00};
+static unsigned char helvetica18_151_bits[] = {
+0x00};
+static unsigned char helvetica18_152_bits[] = {
+0x00};
+static unsigned char helvetica18_153_bits[] = {
+0x00};
+static unsigned char helvetica18_154_bits[] = {
+0x00};
+static unsigned char helvetica18_155_bits[] = {
+0x00};
+static unsigned char helvetica18_156_bits[] = {
+0x00};
+static unsigned char helvetica18_157_bits[] = {
+0x00};
+static unsigned char helvetica18_158_bits[] = {
+0x00};
+static unsigned char helvetica18_159_bits[] = {
+0x00};
+static unsigned char helvetica18_160_bits[] = {
+0x00};
+static unsigned char helvetica18_161_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03};
+static unsigned char helvetica18_162_bits[] = {
+0x20, 0x20, 0x7c, 0xfe, 0xd6, 0x13, 0x13, 0x13, 0x13, 0xd6, 0xfe, 0x7c, 
+0x08, 0x08};
+static unsigned char helvetica18_163_bits[] = {
+0x78, 0x00, 0xfc, 0x00, 0x86, 0x01, 0x86, 0x01, 0x06, 0x00, 0x0c, 0x00, 
+0x7e, 0x00, 0x18, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x06, 0x01, 0xff, 0x01, 
+0xfb, 0x00};
+static unsigned char helvetica18_164_bits[] = {
+0xc3, 0xff, 0x66, 0x66, 0x66, 0xff, 0xc3};
+static unsigned char helvetica18_165_bits[] = {
+0xc3, 0xc3, 0x66, 0x66, 0x66, 0x3c, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 
+0x18};
+static unsigned char helvetica18_166_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica18_167_bits[] = {
+0x3c, 0x7e, 0xc3, 0xc3, 0x0f, 0x3e, 0x76, 0xe3, 0xc3, 0xc7, 0xce, 0x7c, 
+0x70, 0xe0, 0xc3, 0xc3, 0x7e, 0x3c};
+static unsigned char helvetica18_168_bits[] = {
+0x1b, 0x1b};
+static unsigned char helvetica18_169_bits[] = {
+0xf0, 0x01, 0x0c, 0x06, 0x02, 0x08, 0xe2, 0x08, 0x11, 0x11, 0x09, 0x10, 
+0x09, 0x10, 0x09, 0x10, 0x11, 0x11, 0xe2, 0x08, 0x02, 0x08, 0x0c, 0x06, 
+0xf0, 0x01};
+static unsigned char helvetica18_170_bits[] = {
+0x0e, 0x13, 0x1c, 0x12, 0x1b, 0x16, 0x00, 0x1f};
+static unsigned char helvetica18_171_bits[] = {
+0x48, 0x6c, 0x36, 0x1b, 0x1b, 0x36, 0x6c, 0x48};
+static unsigned char helvetica18_172_bits[] = {
+0xff, 0x01, 0xff, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01};
+static unsigned char helvetica18_173_bits[] = {
+0x1f, 0x1f};
+static unsigned char helvetica18_174_bits[] = {
+0xf0, 0x01, 0x0c, 0x06, 0x02, 0x08, 0xf2, 0x09, 0x11, 0x12, 0x11, 0x12, 
+0xf1, 0x11, 0x91, 0x10, 0x11, 0x11, 0x12, 0x0a, 0x02, 0x08, 0x0c, 0x06, 
+0xf0, 0x01};
+static unsigned char helvetica18_175_bits[] = {
+0x1f};
+static unsigned char helvetica18_176_bits[] = {
+0x0e, 0x1b, 0x11, 0x1b, 0x0e};
+static unsigned char helvetica18_177_bits[] = {
+0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00, 0xff, 0xff};
+static unsigned char helvetica18_178_bits[] = {
+0x0e, 0x1f, 0x19, 0x18, 0x0c, 0x06, 0x1f, 0x1f};
+static unsigned char helvetica18_179_bits[] = {
+0x0e, 0x1f, 0x19, 0x0c, 0x0c, 0x19, 0x1f, 0x0e};
+static unsigned char helvetica18_180_bits[] = {
+0x0c, 0x06, 0x03};
+static unsigned char helvetica18_181_bits[] = {
+0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0xff, 0xdb, 0x03, 0x03, 
+0x03, 0x03};
+static unsigned char helvetica18_182_bits[] = {
+0xfc, 0x4e, 0x4f, 0x4f, 0x4f, 0x4f, 0x4e, 0x4c, 0x48, 0x48, 0x48, 0x48, 
+0x48, 0x48, 0x48, 0x48, 0x48, 0x48};
+static unsigned char helvetica18_183_bits[] = {
+0x03, 0x03};
+static unsigned char helvetica18_184_bits[] = {
+0x06, 0x0e, 0x18, 0x1b, 0x0f};
+static unsigned char helvetica18_185_bits[] = {
+0x06, 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06};
+static unsigned char helvetica18_186_bits[] = {
+0x0e, 0x1b, 0x11, 0x11, 0x1b, 0x0e, 0x00, 0x1f};
+static unsigned char helvetica18_187_bits[] = {
+0x09, 0x1b, 0x36, 0x6c, 0x6c, 0x36, 0x1b, 0x09};
+static unsigned char helvetica18_188_bits[] = {
+0x06, 0x06, 0x07, 0x06, 0x07, 0x03, 0x86, 0x01, 0x86, 0x01, 0xc6, 0x08, 
+0x46, 0x0c, 0x66, 0x0e, 0x30, 0x0f, 0xb0, 0x0d, 0x98, 0x1f, 0x0c, 0x0c, 
+0x0c, 0x0c};
+static unsigned char helvetica18_189_bits[] = {
+0x06, 0x06, 0x07, 0x06, 0x07, 0x03, 0x86, 0x01, 0x86, 0x01, 0xc6, 0x0e, 
+0x46, 0x1f, 0x66, 0x19, 0x30, 0x18, 0x30, 0x0c, 0x18, 0x06, 0x0c, 0x1f, 
+0x0c, 0x1f};
+static unsigned char helvetica18_190_bits[] = {
+0x0e, 0x0c, 0x1f, 0x0c, 0x19, 0x06, 0x0c, 0x03, 0x0c, 0x03, 0x99, 0x11, 
+0x9f, 0x18, 0xce, 0x1c, 0x60, 0x1e, 0x60, 0x1b, 0x30, 0x3f, 0x18, 0x18, 
+0x18, 0x18};
+static unsigned char helvetica18_191_bits[] = {
+0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x1c, 0x0e, 0x07, 0x63, 0x63, 
+0x7f, 0x3e};
+static unsigned char helvetica18_192_bits[] = {
+0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0xf0, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0x0c, 0x03, 0x0c, 0x03, 
+0xfc, 0x03, 0xfe, 0x07, 0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c};
+static unsigned char helvetica18_193_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0xf0, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0x0c, 0x03, 0x0c, 0x03, 
+0xfc, 0x03, 0xfe, 0x07, 0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c};
+static unsigned char helvetica18_194_bits[] = {
+0x60, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0xf0, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0x0c, 0x03, 0x0c, 0x03, 
+0xfc, 0x03, 0xfe, 0x07, 0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c};
+static unsigned char helvetica18_195_bits[] = {
+0x30, 0x01, 0x68, 0x01, 0xc8, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0xf0, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0x0c, 0x03, 0x0c, 0x03, 
+0xfc, 0x03, 0xfe, 0x07, 0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c};
+static unsigned char helvetica18_196_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0xf0, 0x00, 
+0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0x0c, 0x03, 0x0c, 0x03, 0xfc, 0x03, 
+0xfe, 0x07, 0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c};
+static unsigned char helvetica18_197_bits[] = {
+0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0xf0, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0xf0, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0x0c, 0x03, 0x0c, 0x03, 
+0xfc, 0x03, 0xfe, 0x07, 0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c};
+static unsigned char helvetica18_198_bits[] = {
+0xe0, 0xff, 0xe0, 0xff, 0xb0, 0x01, 0xb0, 0x01, 0x98, 0x01, 0x98, 0x01, 
+0x8c, 0x7f, 0x8c, 0x7f, 0xfc, 0x01, 0xfe, 0x01, 0x86, 0x01, 0x86, 0x01, 
+0x83, 0xff, 0x83, 0xff};
+static unsigned char helvetica18_199_bits[] = {
+0xf0, 0x01, 0xfc, 0x07, 0x0e, 0x0e, 0x06, 0x0c, 0x07, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x07, 0x00, 0x06, 0x0c, 0x0e, 0x0e, 
+0xfc, 0x07, 0xf0, 0x01, 0x70, 0x00, 0xc0, 0x00, 0xd8, 0x00, 0x78, 0x00};
+static unsigned char helvetica18_200_bits[] = {
+0x0c, 0x00, 0x18, 0x00, 0x30, 0x00, 0x00, 0x00, 0xff, 0x01, 0xff, 0x01, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x00, 0xff, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x01, 0xff, 0x01};
+static unsigned char helvetica18_201_bits[] = {
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0xff, 0x01, 0xff, 0x01, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x00, 0xff, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x01, 0xff, 0x01};
+static unsigned char helvetica18_202_bits[] = {
+0x30, 0x00, 0x78, 0x00, 0xcc, 0x00, 0x00, 0x00, 0xff, 0x01, 0xff, 0x01, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x00, 0xff, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x01, 0xff, 0x01};
+static unsigned char helvetica18_203_bits[] = {
+0xcc, 0x00, 0xcc, 0x00, 0x00, 0x00, 0xff, 0x01, 0xff, 0x01, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x00, 0xff, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x01, 0xff, 0x01};
+static unsigned char helvetica18_204_bits[] = {
+0x03, 0x06, 0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
+static unsigned char helvetica18_205_bits[] = {
+0x0c, 0x06, 0x03, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica18_206_bits[] = {
+0x0c, 0x1e, 0x33, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
+static unsigned char helvetica18_207_bits[] = {
+0x33, 0x33, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
+static unsigned char helvetica18_208_bits[] = {
+0xfe, 0x01, 0xfe, 0x03, 0x06, 0x07, 0x06, 0x06, 0x06, 0x0c, 0x06, 0x0c, 
+0x3f, 0x0c, 0x3f, 0x0c, 0x06, 0x0c, 0x06, 0x0c, 0x06, 0x06, 0x06, 0x07, 
+0xfe, 0x03, 0xfe, 0x01};
+static unsigned char helvetica18_209_bits[] = {
+0x30, 0x01, 0x68, 0x01, 0xc8, 0x00, 0x00, 0x00, 0x07, 0x06, 0x07, 0x06, 
+0x0f, 0x06, 0x1b, 0x06, 0x1b, 0x06, 0x33, 0x06, 0x33, 0x06, 0x63, 0x06, 
+0x63, 0x06, 0xc3, 0x06, 0x83, 0x07, 0x83, 0x07, 0x03, 0x07, 0x03, 0x06};
+static unsigned char helvetica18_210_bits[] = {
+0x30, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xf0, 0x01, 0xfc, 0x07, 
+0x0e, 0x0e, 0x06, 0x0c, 0x07, 0x1c, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x03, 0x18, 0x07, 0x1c, 0x06, 0x0c, 0x0e, 0x0e, 0xfc, 0x07, 0xf0, 0x01};
+static unsigned char helvetica18_211_bits[] = {
+0x00, 0x03, 0x80, 0x01, 0xc0, 0x00, 0x00, 0x00, 0xf0, 0x01, 0xfc, 0x07, 
+0x0e, 0x0e, 0x06, 0x0c, 0x07, 0x1c, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x03, 0x18, 0x07, 0x1c, 0x06, 0x0c, 0x0e, 0x0e, 0xfc, 0x07, 0xf0, 0x01};
+static unsigned char helvetica18_212_bits[] = {
+0xc0, 0x00, 0xe0, 0x01, 0x30, 0x03, 0x00, 0x00, 0xf0, 0x01, 0xfc, 0x07, 
+0x0e, 0x0e, 0x06, 0x0c, 0x07, 0x1c, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x03, 0x18, 0x07, 0x1c, 0x06, 0x0c, 0x0e, 0x0e, 0xfc, 0x07, 0xf0, 0x01};
+static unsigned char helvetica18_213_bits[] = {
+0x60, 0x02, 0xd0, 0x02, 0x90, 0x01, 0x00, 0x00, 0xf0, 0x01, 0xfc, 0x07, 
+0x0e, 0x0e, 0x06, 0x0c, 0x07, 0x1c, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x03, 0x18, 0x07, 0x1c, 0x06, 0x0c, 0x0e, 0x0e, 0xfc, 0x07, 0xf0, 0x01};
+static unsigned char helvetica18_214_bits[] = {
+0xb0, 0x01, 0xb0, 0x01, 0x00, 0x00, 0xf0, 0x01, 0xfc, 0x07, 0x0e, 0x0e, 
+0x06, 0x0c, 0x07, 0x1c, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x07, 0x1c, 0x06, 0x0c, 0x0e, 0x0e, 0xfc, 0x07, 0xf0, 0x01};
+static unsigned char helvetica18_215_bits[] = {
+0x03, 0x03, 0x86, 0x01, 0xcc, 0x00, 0x78, 0x00, 0x30, 0x00, 0x78, 0x00, 
+0xcc, 0x00, 0x86, 0x01, 0x03, 0x03};
+static unsigned char helvetica18_216_bits[] = {
+0xe0, 0x33, 0xf8, 0x3f, 0x1c, 0x1c, 0x0c, 0x1e, 0x0e, 0x3b, 0x86, 0x33, 
+0xc6, 0x31, 0xe6, 0x30, 0x76, 0x30, 0x36, 0x38, 0x1c, 0x18, 0x1e, 0x1c, 
+0xff, 0x0f, 0xe3, 0x03};
+static unsigned char helvetica18_217_bits[] = {
+0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0xfe, 0x03, 0xf8, 0x00};
+static unsigned char helvetica18_218_bits[] = {
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0xfe, 0x03, 0xf8, 0x00};
+static unsigned char helvetica18_219_bits[] = {
+0x60, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x00, 0x00, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0xfe, 0x03, 0xf8, 0x00};
+static unsigned char helvetica18_220_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0xfe, 0x03, 0xf8, 0x00};
+static unsigned char helvetica18_221_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x0c, 0x03, 0x0c, 
+0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 0x0c, 0x03, 0x98, 0x01, 0xf0, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char helvetica18_222_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x00, 0xff, 0x01, 0x83, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0xff, 0x01, 0xff, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00};
+static unsigned char helvetica18_223_bits[] = {
+0x1c, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x3b, 0x3b, 0x63, 0x63, 0x63, 0x63, 
+0x7b, 0x3b};
+static unsigned char helvetica18_224_bits[] = {
+0x06, 0x0c, 0x18, 0x00, 0x3e, 0x77, 0x63, 0x70, 0x7e, 0x67, 0x63, 0x63, 
+0x77, 0x6e};
+static unsigned char helvetica18_225_bits[] = {
+0x30, 0x18, 0x0c, 0x00, 0x3e, 0x77, 0x63, 0x70, 0x7e, 0x67, 0x63, 0x63, 
+0x77, 0x6e};
+static unsigned char helvetica18_226_bits[] = {
+0x18, 0x3c, 0x66, 0x00, 0x3e, 0x77, 0x63, 0x70, 0x7e, 0x67, 0x63, 0x63, 
+0x77, 0x6e};
+static unsigned char helvetica18_227_bits[] = {
+0x4c, 0x5a, 0x32, 0x00, 0x3e, 0x77, 0x63, 0x70, 0x7e, 0x67, 0x63, 0x63, 
+0x77, 0x6e};
+static unsigned char helvetica18_228_bits[] = {
+0x36, 0x36, 0x00, 0x3e, 0x77, 0x63, 0x70, 0x7e, 0x67, 0x63, 0x63, 0x77, 
+0x6e};
+static unsigned char helvetica18_229_bits[] = {
+0x1c, 0x36, 0x36, 0x1c, 0x3e, 0x77, 0x63, 0x70, 0x7e, 0x67, 0x63, 0x63, 
+0x77, 0x6e};
+static unsigned char helvetica18_230_bits[] = {
+0xbe, 0x07, 0xf7, 0x0f, 0x63, 0x18, 0x70, 0x18, 0xfe, 0x1f, 0x67, 0x00, 
+0x63, 0x00, 0xe3, 0x18, 0xf7, 0x1f, 0xae, 0x07};
+static unsigned char helvetica18_231_bits[] = {
+0x7c, 0xfe, 0xc6, 0x03, 0x03, 0x03, 0x03, 0xc6, 0xfe, 0x7c, 0x1c, 0x30, 
+0x36, 0x1e};
+static unsigned char helvetica18_232_bits[] = {
+0x06, 0x0c, 0x18, 0x00, 0x3c, 0x7e, 0xc3, 0xc3, 0xff, 0x03, 0x03, 0xc7, 
+0xfe, 0x3c};
+static unsigned char helvetica18_233_bits[] = {
+0x60, 0x30, 0x18, 0x00, 0x3c, 0x7e, 0xc3, 0xc3, 0xff, 0x03, 0x03, 0xc7, 
+0xfe, 0x3c};
+static unsigned char helvetica18_234_bits[] = {
+0x18, 0x3c, 0x66, 0x00, 0x3c, 0x7e, 0xc3, 0xc3, 0xff, 0x03, 0x03, 0xc7, 
+0xfe, 0x3c};
+static unsigned char helvetica18_235_bits[] = {
+0x6c, 0x6c, 0x00, 0x3c, 0x7e, 0xc3, 0xc3, 0xff, 0x03, 0x03, 0xc7, 0xfe, 
+0x3c};
+static unsigned char helvetica18_236_bits[] = {
+0x03, 0x06, 0x0c, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06};
+static unsigned char helvetica18_237_bits[] = {
+0x0c, 0x06, 0x03, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06};
+static unsigned char helvetica18_238_bits[] = {
+0x0c, 0x1e, 0x33, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c};
+static unsigned char helvetica18_239_bits[] = {
+0x1b, 0x1b, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06};
+static unsigned char helvetica18_240_bits[] = {
+0x06, 0x00, 0x6c, 0x00, 0x1c, 0x00, 0x32, 0x00, 0x7c, 0x00, 0xfe, 0x00, 
+0xc6, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc6, 0x00, 
+0xfe, 0x00, 0x7c, 0x00};
+static unsigned char helvetica18_241_bits[] = {
+0x4c, 0x5a, 0x32, 0x00, 0x73, 0xfb, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 
+0xc3, 0xc3};
+static unsigned char helvetica18_242_bits[] = {
+0x0c, 0x00, 0x18, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xfe, 0x00, 
+0xc6, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc6, 0x00, 
+0xfe, 0x00, 0x7c, 0x00};
+static unsigned char helvetica18_243_bits[] = {
+0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xfe, 0x00, 
+0xc6, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc6, 0x00, 
+0xfe, 0x00, 0x7c, 0x00};
+static unsigned char helvetica18_244_bits[] = {
+0x30, 0x00, 0x78, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xfe, 0x00, 
+0xc6, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc6, 0x00, 
+0xfe, 0x00, 0x7c, 0x00};
+static unsigned char helvetica18_245_bits[] = {
+0x98, 0x00, 0xb4, 0x00, 0x64, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xfe, 0x00, 
+0xc6, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc6, 0x00, 
+0xfe, 0x00, 0x7c, 0x00};
+static unsigned char helvetica18_246_bits[] = {
+0x6c, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xfe, 0x00, 0xc6, 0x00, 
+0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc6, 0x00, 0xfe, 0x00, 
+0x7c, 0x00};
+static unsigned char helvetica18_247_bits[] = {
+0x18, 0x18, 0x00, 0xff, 0xff, 0x00, 0x18, 0x18};
+static unsigned char helvetica18_248_bits[] = {
+0x70, 0x06, 0xfc, 0x03, 0x8c, 0x01, 0xc6, 0x03, 0x66, 0x03, 0x36, 0x03, 
+0x1e, 0x03, 0x8c, 0x01, 0xfe, 0x01, 0x73, 0x00};
+static unsigned char helvetica18_249_bits[] = {
+0x0c, 0x18, 0x30, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe3, 
+0xdf, 0xce};
+static unsigned char helvetica18_250_bits[] = {
+0x60, 0x30, 0x18, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe3, 
+0xdf, 0xce};
+static unsigned char helvetica18_251_bits[] = {
+0x18, 0x3c, 0x66, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe3, 
+0xdf, 0xce};
+static unsigned char helvetica18_252_bits[] = {
+0x66, 0x66, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe3, 0xdf, 
+0xce};
+static unsigned char helvetica18_253_bits[] = {
+0x60, 0x30, 0x18, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x66, 0x66, 0x24, 0x3c, 
+0x18, 0x18, 0x18, 0x18, 0x0e, 0x0e};
+static unsigned char helvetica18_254_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x7b, 0x00, 0xff, 0x00, 
+0xc7, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc7, 0x00, 
+0xff, 0x00, 0x7b, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00};
+static unsigned char helvetica18_255_bits[] = {
+0x66, 0x66, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x66, 0x66, 0x24, 0x3c, 0x18, 
+0x18, 0x18, 0x18, 0x0e, 0x0e};
+static RotFont helvetica18font[] = {
+{5, 1, 1, helvetica18_0_bits},
+{5, 1, 1, helvetica18_1_bits},
+{5, 1, 1, helvetica18_2_bits},
+{5, 1, 1, helvetica18_3_bits},
+{5, 1, 1, helvetica18_4_bits},
+{5, 1, 1, helvetica18_5_bits},
+{5, 1, 1, helvetica18_6_bits},
+{5, 1, 1, helvetica18_7_bits},
+{5, 1, 1, helvetica18_8_bits},
+{5, 1, 1, helvetica18_9_bits},
+{5, 1, 1, helvetica18_10_bits},
+{5, 1, 1, helvetica18_11_bits},
+{5, 1, 1, helvetica18_12_bits},
+{5, 1, 1, helvetica18_13_bits},
+{5, 1, 1, helvetica18_14_bits},
+{5, 1, 1, helvetica18_15_bits},
+{5, 1, 1, helvetica18_16_bits},
+{5, 1, 1, helvetica18_17_bits},
+{5, 1, 1, helvetica18_18_bits},
+{5, 1, 1, helvetica18_19_bits},
+{5, 1, 1, helvetica18_20_bits},
+{5, 1, 1, helvetica18_21_bits},
+{5, 1, 1, helvetica18_22_bits},
+{5, 1, 1, helvetica18_23_bits},
+{5, 1, 1, helvetica18_24_bits},
+{5, 1, 1, helvetica18_25_bits},
+{5, 1, 1, helvetica18_26_bits},
+{5, 1, 1, helvetica18_27_bits},
+{5, 1, 1, helvetica18_28_bits},
+{5, 1, 1, helvetica18_29_bits},
+{5, 1, 1, helvetica18_30_bits},
+{5, 1, 1, helvetica18_31_bits},
+{9, 1, 1, helvetica18_32_bits},
+{2, 14, 14, helvetica18_33_bits},
+{5, 5, 14, helvetica18_34_bits},
+{10, 13, 13, helvetica18_35_bits},
+{9, 16, 14, helvetica18_36_bits},
+{14, 13, 13, helvetica18_37_bits},
+{12, 13, 13, helvetica18_38_bits},
+{2, 5, 14, helvetica18_39_bits},
+{4, 18, 14, helvetica18_40_bits},
+{4, 18, 14, helvetica18_41_bits},
+{5, 6, 14, helvetica18_42_bits},
+{8, 10, 10, helvetica18_43_bits},
+{2, 5, 2, helvetica18_44_bits},
+{8, 2, 6, helvetica18_45_bits},
+{2, 2, 2, helvetica18_46_bits},
+{5, 14, 14, helvetica18_47_bits},
+{8, 13, 13, helvetica18_48_bits},
+{5, 13, 13, helvetica18_49_bits},
+{8, 13, 13, helvetica18_50_bits},
+{8, 13, 13, helvetica18_51_bits},
+{9, 13, 13, helvetica18_52_bits},
+{8, 13, 13, helvetica18_53_bits},
+{8, 13, 13, helvetica18_54_bits},
+{8, 13, 13, helvetica18_55_bits},
+{8, 13, 13, helvetica18_56_bits},
+{8, 13, 13, helvetica18_57_bits},
+{2, 10, 10, helvetica18_58_bits},
+{2, 13, 10, helvetica18_59_bits},
+{8, 9, 9, helvetica18_60_bits},
+{7, 6, 8, helvetica18_61_bits},
+{8, 9, 9, helvetica18_62_bits},
+{7, 14, 14, helvetica18_63_bits},
+{16, 17, 14, helvetica18_64_bits},
+{12, 14, 14, helvetica18_65_bits},
+{11, 14, 14, helvetica18_66_bits},
+{12, 14, 14, helvetica18_67_bits},
+{11, 14, 14, helvetica18_68_bits},
+{9, 14, 14, helvetica18_69_bits},
+{9, 14, 14, helvetica18_70_bits},
+{12, 14, 14, helvetica18_71_bits},
+{11, 14, 14, helvetica18_72_bits},
+{2, 14, 14, helvetica18_73_bits},
+{8, 14, 14, helvetica18_74_bits},
+{12, 14, 14, helvetica18_75_bits},
+{8, 14, 14, helvetica18_76_bits},
+{14, 14, 14, helvetica18_77_bits},
+{11, 14, 14, helvetica18_78_bits},
+{13, 14, 14, helvetica18_79_bits},
+{10, 14, 14, helvetica18_80_bits},
+{13, 15, 14, helvetica18_81_bits},
+{10, 14, 14, helvetica18_82_bits},
+{11, 14, 14, helvetica18_83_bits},
+{10, 14, 14, helvetica18_84_bits},
+{11, 14, 14, helvetica18_85_bits},
+{12, 14, 14, helvetica18_86_bits},
+{16, 14, 14, helvetica18_87_bits},
+{11, 14, 14, helvetica18_88_bits},
+{12, 14, 14, helvetica18_89_bits},
+{10, 14, 14, helvetica18_90_bits},
+{4, 18, 14, helvetica18_91_bits},
+{5, 14, 14, helvetica18_92_bits},
+{4, 18, 14, helvetica18_93_bits},
+{7, 5, 13, helvetica18_94_bits},
+{10, 2, -2, helvetica18_95_bits},
+{2, 5, 14, helvetica18_96_bits},
+{7, 10, 10, helvetica18_97_bits},
+{9, 14, 14, helvetica18_98_bits},
+{8, 10, 10, helvetica18_99_bits},
+{9, 14, 14, helvetica18_100_bits},
+{8, 10, 10, helvetica18_101_bits},
+{6, 14, 14, helvetica18_102_bits},
+{9, 14, 10, helvetica18_103_bits},
+{8, 14, 14, helvetica18_104_bits},
+{2, 14, 14, helvetica18_105_bits},
+{4, 18, 14, helvetica18_106_bits},
+{8, 14, 14, helvetica18_107_bits},
+{2, 14, 14, helvetica18_108_bits},
+{12, 10, 10, helvetica18_109_bits},
+{8, 10, 10, helvetica18_110_bits},
+{9, 10, 10, helvetica18_111_bits},
+{9, 14, 10, helvetica18_112_bits},
+{9, 14, 10, helvetica18_113_bits},
+{5, 10, 10, helvetica18_114_bits},
+{7, 10, 10, helvetica18_115_bits},
+{6, 13, 13, helvetica18_116_bits},
+{8, 10, 10, helvetica18_117_bits},
+{8, 10, 10, helvetica18_118_bits},
+{12, 10, 10, helvetica18_119_bits},
+{8, 10, 10, helvetica18_120_bits},
+{8, 14, 10, helvetica18_121_bits},
+{7, 10, 10, helvetica18_122_bits},
+{6, 18, 14, helvetica18_123_bits},
+{2, 18, 14, helvetica18_124_bits},
+{6, 18, 14, helvetica18_125_bits},
+{8, 3, 7, helvetica18_126_bits},
+{5, 1, 1, helvetica18_127_bits},
+{5, 1, 1, helvetica18_128_bits},
+{5, 1, 1, helvetica18_129_bits},
+{5, 1, 1, helvetica18_130_bits},
+{5, 1, 1, helvetica18_131_bits},
+{5, 1, 1, helvetica18_132_bits},
+{5, 1, 1, helvetica18_133_bits},
+{5, 1, 1, helvetica18_134_bits},
+{5, 1, 1, helvetica18_135_bits},
+{5, 1, 1, helvetica18_136_bits},
+{5, 1, 1, helvetica18_137_bits},
+{5, 1, 1, helvetica18_138_bits},
+{5, 1, 1, helvetica18_139_bits},
+{5, 1, 1, helvetica18_140_bits},
+{5, 1, 1, helvetica18_141_bits},
+{5, 1, 1, helvetica18_142_bits},
+{5, 1, 1, helvetica18_143_bits},
+{5, 1, 1, helvetica18_144_bits},
+{5, 1, 1, helvetica18_145_bits},
+{5, 1, 1, helvetica18_146_bits},
+{5, 1, 1, helvetica18_147_bits},
+{5, 1, 1, helvetica18_148_bits},
+{5, 1, 1, helvetica18_149_bits},
+{5, 1, 1, helvetica18_150_bits},
+{5, 1, 1, helvetica18_151_bits},
+{5, 1, 1, helvetica18_152_bits},
+{5, 1, 1, helvetica18_153_bits},
+{5, 1, 1, helvetica18_154_bits},
+{5, 1, 1, helvetica18_155_bits},
+{5, 1, 1, helvetica18_156_bits},
+{5, 1, 1, helvetica18_157_bits},
+{5, 1, 1, helvetica18_158_bits},
+{5, 1, 1, helvetica18_159_bits},
+{1, 1, 1, helvetica18_160_bits},
+{2, 14, 10, helvetica18_161_bits},
+{8, 14, 12, helvetica18_162_bits},
+{9, 13, 13, helvetica18_163_bits},
+{8, 7, 10, helvetica18_164_bits},
+{8, 13, 13, helvetica18_165_bits},
+{2, 17, 14, helvetica18_166_bits},
+{8, 18, 14, helvetica18_167_bits},
+{5, 2, 13, helvetica18_168_bits},
+{13, 13, 13, helvetica18_169_bits},
+{5, 8, 14, helvetica18_170_bits},
+{7, 8, 9, helvetica18_171_bits},
+{9, 5, 8, helvetica18_172_bits},
+{5, 2, 6, helvetica18_173_bits},
+{13, 13, 13, helvetica18_174_bits},
+{5, 1, 13, helvetica18_175_bits},
+{5, 5, 13, helvetica18_176_bits},
+{8, 11, 11, helvetica18_177_bits},
+{5, 8, 13, helvetica18_178_bits},
+{5, 8, 13, helvetica18_179_bits},
+{4, 3, 14, helvetica18_180_bits},
+{8, 14, 10, helvetica18_181_bits},
+{8, 18, 14, helvetica18_182_bits},
+{2, 2, 6, helvetica18_183_bits},
+{5, 5, 1, helvetica18_184_bits},
+{3, 8, 13, helvetica18_185_bits},
+{5, 8, 14, helvetica18_186_bits},
+{7, 8, 9, helvetica18_187_bits},
+{13, 13, 13, helvetica18_188_bits},
+{13, 13, 13, helvetica18_189_bits},
+{14, 13, 13, helvetica18_190_bits},
+{7, 14, 10, helvetica18_191_bits},
+{12, 18, 18, helvetica18_192_bits},
+{12, 18, 18, helvetica18_193_bits},
+{12, 18, 18, helvetica18_194_bits},
+{12, 18, 18, helvetica18_195_bits},
+{12, 17, 17, helvetica18_196_bits},
+{12, 18, 18, helvetica18_197_bits},
+{16, 14, 14, helvetica18_198_bits},
+{12, 18, 14, helvetica18_199_bits},
+{9, 18, 18, helvetica18_200_bits},
+{9, 18, 18, helvetica18_201_bits},
+{9, 18, 18, helvetica18_202_bits},
+{9, 17, 17, helvetica18_203_bits},
+{4, 18, 18, helvetica18_204_bits},
+{4, 18, 18, helvetica18_205_bits},
+{6, 18, 18, helvetica18_206_bits},
+{6, 17, 17, helvetica18_207_bits},
+{12, 14, 14, helvetica18_208_bits},
+{11, 18, 18, helvetica18_209_bits},
+{13, 18, 18, helvetica18_210_bits},
+{13, 18, 18, helvetica18_211_bits},
+{13, 18, 18, helvetica18_212_bits},
+{13, 18, 18, helvetica18_213_bits},
+{13, 17, 17, helvetica18_214_bits},
+{10, 9, 9, helvetica18_215_bits},
+{14, 14, 14, helvetica18_216_bits},
+{11, 18, 18, helvetica18_217_bits},
+{11, 18, 18, helvetica18_218_bits},
+{11, 18, 18, helvetica18_219_bits},
+{11, 17, 17, helvetica18_220_bits},
+{12, 18, 18, helvetica18_221_bits},
+{10, 14, 14, helvetica18_222_bits},
+{7, 14, 14, helvetica18_223_bits},
+{7, 14, 14, helvetica18_224_bits},
+{7, 14, 14, helvetica18_225_bits},
+{7, 14, 14, helvetica18_226_bits},
+{7, 14, 14, helvetica18_227_bits},
+{7, 13, 13, helvetica18_228_bits},
+{7, 14, 14, helvetica18_229_bits},
+{13, 10, 10, helvetica18_230_bits},
+{8, 14, 10, helvetica18_231_bits},
+{8, 14, 14, helvetica18_232_bits},
+{8, 14, 14, helvetica18_233_bits},
+{8, 14, 14, helvetica18_234_bits},
+{8, 13, 13, helvetica18_235_bits},
+{4, 14, 14, helvetica18_236_bits},
+{4, 14, 14, helvetica18_237_bits},
+{6, 14, 14, helvetica18_238_bits},
+{5, 13, 13, helvetica18_239_bits},
+{9, 14, 14, helvetica18_240_bits},
+{8, 14, 14, helvetica18_241_bits},
+{9, 14, 14, helvetica18_242_bits},
+{9, 14, 14, helvetica18_243_bits},
+{9, 14, 14, helvetica18_244_bits},
+{9, 14, 14, helvetica18_245_bits},
+{9, 13, 13, helvetica18_246_bits},
+{8, 8, 9, helvetica18_247_bits},
+{11, 10, 10, helvetica18_248_bits},
+{8, 14, 14, helvetica18_249_bits},
+{8, 14, 14, helvetica18_250_bits},
+{8, 14, 14, helvetica18_251_bits},
+{8, 13, 13, helvetica18_252_bits},
+{8, 18, 14, helvetica18_253_bits},
+{9, 18, 14, helvetica18_254_bits},
+{8, 17, 13, helvetica18_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/helvetica24.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/helvetica24.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/helvetica24.bdf	(revision 12606)
@@ -0,0 +1,4679 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Helvetica-Medium-R-Normal--24-240-75-75-P-130-ISO8859-1
+SIZE 24 75 75
+FONTBOUNDINGBOX 25 29 -1 -5
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Helvetica"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 24
+POINT_SIZE 240
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 130
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 19
+X_HEIGHT 14
+FACE_NAME "Helvetica"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.  "
+_DEC_DEVICE_FONTNAMES "PS=Helvetica"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Helvetica"
+FONT "-Adobe-Helvetica-Medium-R-Normal--24-240-75-75-P-130-ISO8859-1"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 15
+DEFAULT_CHAR 32
+FONT_ASCENT 22
+FONT_DESCENT 5
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 19 2 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+80
+80
+00
+00
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 6 1 13
+BITMAP
+cc
+cc
+cc
+cc
+cc
+44
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 11 17 2 0
+BITMAP
+0cc0
+0cc0
+0cc0
+1980
+ffe0
+ffe0
+1980
+1980
+3300
+3300
+ffe0
+ffe0
+3300
+3300
+6600
+6600
+6600
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 21 1 -2
+BITMAP
+0600
+0600
+3f80
+7fc0
+e6e0
+c660
+c600
+e600
+7600
+3e00
+0f80
+07c0
+06e0
+0660
+c660
+c660
+e6e0
+7fc0
+3f80
+0600
+0600
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 880 0
+DWIDTH 22 0
+BBX 19 18 1 0
+BITMAP
+000600
+3c0c00
+7e0c00
+c31800
+c31800
+c33000
+c33000
+7e6000
+3c6000
+00c000
+00c780
+018fc0
+019860
+031860
+031860
+061860
+060fc0
+040780
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 14 18 1 0
+BITMAP
+0f00
+1f80
+39c0
+30c0
+30c0
+30c0
+1980
+0f00
+1e00
+3f18
+7398
+61d8
+c0f0
+c060
+c0f0
+e1d8
+7f9c
+1e00
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 6 2 13
+BITMAP
+c0
+c0
+c0
+40
+40
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 5 24 2 -5
+BITMAP
+18
+18
+30
+30
+60
+60
+60
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+60
+60
+60
+30
+30
+18
+18
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 5 24 1 -5
+BITMAP
+c0
+c0
+60
+60
+30
+30
+30
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+30
+30
+30
+60
+60
+c0
+c0
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 7 7 1 12
+BITMAP
+10
+10
+d6
+7c
+38
+6c
+44
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 12 1 1
+BITMAP
+0600
+0600
+0600
+0600
+0600
+fff0
+fff0
+0600
+0600
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 6 2 -3
+BITMAP
+c0
+c0
+c0
+40
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 11 2 2 6
+BITMAP
+ffe0
+ffe0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 3 2 0
+BITMAP
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 7 19 0 0
+BITMAP
+06
+06
+06
+0c
+0c
+0c
+18
+18
+18
+18
+30
+30
+30
+60
+60
+60
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+1f00
+3f80
+71c0
+60c0
+60c0
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 6 18 2 0
+BITMAP
+0c
+0c
+1c
+fc
+fc
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+1e00
+7f80
+61c0
+c0c0
+c060
+c060
+0060
+00c0
+01c0
+0380
+0f00
+1c00
+3800
+7000
+e000
+c000
+ffe0
+ffe0
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+1f00
+7f80
+6180
+c0c0
+c0c0
+c0c0
+00c0
+0180
+0f00
+0fc0
+00c0
+0060
+0060
+c060
+c0c0
+61c0
+7f80
+1f00
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+0180
+0380
+0380
+0780
+0f80
+0d80
+1980
+3980
+3180
+6180
+e180
+c180
+ffe0
+ffe0
+0180
+0180
+0180
+0180
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+7fc0
+7fc0
+6000
+6000
+6000
+6000
+6e00
+7f80
+71c0
+00c0
+0060
+0060
+0060
+c060
+c0c0
+e1c0
+7f80
+1e00
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+0f00
+3fc0
+70c0
+6060
+e060
+c000
+c000
+cf00
+df80
+f1c0
+e0c0
+c060
+c060
+c060
+e060
+60c0
+7fc0
+1f00
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+ffe0
+ffe0
+00e0
+00c0
+0180
+0180
+0300
+0300
+0600
+0600
+0c00
+0c00
+1c00
+1800
+1800
+3800
+3000
+3000
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+0e00
+3f80
+3180
+60c0
+60c0
+60c0
+60c0
+3180
+1f00
+3f80
+60c0
+e0e0
+c060
+c060
+c060
+71c0
+7fc0
+1f00
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+1f00
+7fc0
+71c0
+e0c0
+c060
+c060
+c060
+c060
+e0e0
+71e0
+7f60
+1e60
+0060
+00e0
+c0c0
+e1c0
+7f80
+1e00
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 14 2 0
+BITMAP
+c0
+c0
+c0
+00
+00
+00
+00
+00
+00
+00
+00
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 17 2 -3
+BITMAP
+c0
+c0
+c0
+00
+00
+00
+00
+00
+00
+00
+00
+c0
+c0
+c0
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 12 12 1 1
+BITMAP
+0030
+00f0
+03c0
+0f00
+3c00
+e000
+e000
+3c00
+0f00
+03c0
+00f0
+0030
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 10 6 2 5
+BITMAP
+ffc0
+ffc0
+0000
+0000
+ffc0
+ffc0
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 12 12 1 1
+BITMAP
+c000
+f000
+3c00
+0f00
+03c0
+0070
+0070
+03c0
+0f00
+3c00
+f000
+c000
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 19 1 0
+BITMAP
+1f00
+7f80
+71c0
+e0c0
+c0c0
+c1c0
+0180
+0380
+0700
+0600
+0c00
+0c00
+0c00
+0c00
+0000
+0000
+0c00
+0c00
+0c00
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 1000 0
+DWIDTH 25 0
+BBX 22 23 2 -4
+BITMAP
+00ff00
+03ffc0
+0f01e0
+1c0070
+380018
+300018
+60730c
+60fb0c
+c1c70c
+c3860c
+c3060c
+c6060c
+c60c1c
+c60c18
+c60c38
+e71c70
+63f7e0
+71e380
+380000
+1c0000
+0f0300
+07ff00
+00fc00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 19 1 0
+BITMAP
+0380
+0380
+06c0
+06c0
+0c40
+0c60
+0c60
+1830
+1830
+1830
+3018
+3ff8
+3ff8
+600c
+600c
+600c
+c006
+c006
+c006
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 14 19 2 0
+BITMAP
+ffc0
+fff0
+c070
+c018
+c018
+c018
+c018
+c030
+ffe0
+fff0
+c018
+c00c
+c00c
+c00c
+c00c
+c01c
+c038
+fff0
+ffc0
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 19 1 0
+BITMAP
+07e0
+1ff8
+3c3c
+700e
+6006
+e006
+c000
+c000
+c000
+c000
+c000
+c000
+c003
+e003
+6006
+700e
+3c3c
+1ff8
+07e0
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 15 19 2 0
+BITMAP
+ffc0
+fff0
+c078
+c01c
+c00c
+c00e
+c006
+c006
+c006
+c006
+c006
+c006
+c006
+c00e
+c00c
+c01c
+c078
+fff0
+ffc0
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 12 19 2 0
+BITMAP
+fff0
+fff0
+c000
+c000
+c000
+c000
+c000
+c000
+ffe0
+ffe0
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+fff0
+fff0
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 11 19 2 0
+BITMAP
+ffe0
+ffe0
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+ffc0
+ffc0
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 16 19 1 0
+BITMAP
+07e0
+1ff8
+3c3c
+700e
+6006
+e006
+c000
+c000
+c000
+c07f
+c07f
+c003
+c003
+e003
+6007
+700f
+3c3f
+1ffb
+07e3
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 19 2 0
+BITMAP
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+fffc
+fffc
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 2 19 3 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 10 19 1 0
+BITMAP
+00c0
+00c0
+00c0
+00c0
+00c0
+00c0
+00c0
+00c0
+00c0
+00c0
+00c0
+00c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+7f80
+3f00
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 15 19 2 0
+BITMAP
+c038
+c070
+c0e0
+c1c0
+c380
+c700
+ce00
+dc00
+fc00
+fe00
+e700
+c380
+c1c0
+c0e0
+c070
+c038
+c01c
+c00e
+c006
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 11 19 2 0
+BITMAP
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+ffe0
+ffe0
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 840 0
+DWIDTH 21 0
+BBX 17 19 2 0
+BITMAP
+c00180
+e00380
+e00380
+f00780
+f00780
+d80d80
+d80d80
+d80d80
+cc1980
+cc1980
+cc1980
+c63180
+c63180
+c63180
+c36180
+c36180
+c36180
+c1c180
+c1c180
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 19 2 0
+BITMAP
+e00c
+f00c
+f00c
+d80c
+dc0c
+cc0c
+ce0c
+c60c
+c70c
+c30c
+c38c
+c18c
+c1cc
+c0cc
+c0ec
+c06c
+c03c
+c03c
+c01c
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 19 1 0
+BITMAP
+07e0
+1ff8
+3c3c
+700e
+6006
+e007
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+e007
+6006
+700e
+3c3c
+1ff8
+07e0
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 13 19 2 0
+BITMAP
+ffe0
+fff0
+c030
+c018
+c018
+c018
+c018
+c030
+fff0
+ffe0
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 19 1 0
+BITMAP
+07e0
+1ff8
+3c3c
+700e
+6006
+e007
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+e007
+60e6
+707e
+3c1c
+1ffe
+07e7
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 13 19 2 0
+BITMAP
+ffe0
+fff0
+c030
+c018
+c018
+c018
+c018
+c030
+fff0
+ffe0
+c070
+c030
+c018
+c018
+c018
+c018
+c018
+c018
+c018
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 19 1 0
+BITMAP
+07c0
+1ff0
+3838
+7018
+6018
+6000
+7000
+3e00
+0fc0
+01f0
+0078
+001c
+000c
+c00c
+c00c
+e01c
+7838
+3ff0
+0fc0
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 19 1 0
+BITMAP
+fffc
+fffc
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 19 2 0
+BITMAP
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+6018
+7038
+3ff0
+0fc0
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 19 1 0
+BITMAP
+c006
+c006
+e00e
+600c
+701c
+3018
+3018
+3838
+1830
+1830
+1c70
+0c60
+0c60
+0ee0
+06c0
+06c0
+0380
+0380
+0380
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 880 0
+DWIDTH 22 0
+BBX 20 19 1 0
+BITMAP
+c06030
+c06030
+c06030
+c0f030
+60f060
+619860
+619860
+619860
+619860
+3198c0
+330cc0
+330cc0
+330cc0
+1b0d80
+1b0d80
+1e0780
+0e0700
+0c0300
+0c0300
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 19 1 0
+BITMAP
+c006
+e00e
+701c
+3018
+1830
+1c70
+0ee0
+07c0
+0380
+0380
+07c0
+0ee0
+0c60
+1c70
+3838
+3018
+600c
+e00e
+c006
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 19 1 0
+BITMAP
+c00c
+e01c
+6018
+7038
+3030
+3870
+1860
+1ce0
+0cc0
+0fc0
+0780
+0780
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 19 1 0
+BITMAP
+fff8
+fff8
+0038
+0070
+00e0
+01c0
+01c0
+0380
+0700
+0700
+0e00
+1c00
+1c00
+3800
+7000
+7000
+e000
+fff8
+fff8
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 4 24 2 -5
+BITMAP
+f0
+f0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+f0
+f0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 7 19 0 0
+BITMAP
+c0
+c0
+c0
+60
+60
+60
+30
+30
+30
+30
+18
+18
+18
+0c
+0c
+0c
+06
+06
+06
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 4 24 1 -5
+BITMAP
+f0
+f0
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+f0
+f0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 9 1 10
+BITMAP
+0c00
+0c00
+1e00
+1200
+3300
+6180
+6180
+c0c0
+c0c0
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 14 2 0 -5
+BITMAP
+fffc
+fffc
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 6 2 13
+BITMAP
+40
+80
+80
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+1f00
+3f80
+61c0
+60c0
+00c0
+07c0
+3fc0
+78c0
+e0c0
+c0c0
+c1c0
+e3c0
+7ee0
+3c60
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 11 19 2 0
+BITMAP
+c000
+c000
+c000
+c000
+c000
+cf00
+df80
+f1c0
+e0c0
+c060
+c060
+c060
+c060
+c060
+c060
+e0c0
+f1c0
+df80
+cf00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+1f00
+3f80
+71c0
+60c0
+c000
+c000
+c000
+c000
+c000
+c000
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 11 19 1 0
+BITMAP
+0060
+0060
+0060
+0060
+0060
+1e60
+3f60
+71e0
+60e0
+c060
+c060
+c060
+c060
+c060
+c060
+60e0
+71e0
+3f60
+1e60
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+0e00
+3f80
+71c0
+60c0
+c060
+c060
+ffe0
+ffe0
+c000
+c000
+6060
+70e0
+3fc0
+0f00
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 19 1 0
+BITMAP
+1c
+3c
+30
+30
+30
+fc
+fc
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 11 19 1 -5
+BITMAP
+1e60
+3f60
+71e0
+60e0
+c060
+c060
+c060
+c060
+c060
+c060
+60e0
+71e0
+3f60
+1e60
+0060
+c060
+e0c0
+7fc0
+1f00
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 10 19 2 0
+BITMAP
+c000
+c000
+c000
+c000
+c000
+ce00
+df80
+f180
+e0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 19 2 0
+BITMAP
+c0
+c0
+c0
+00
+00
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 4 24 0 -5
+BITMAP
+30
+30
+30
+00
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+f0
+e0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 19 2 0
+BITMAP
+c000
+c000
+c000
+c000
+c000
+c180
+c380
+c700
+ce00
+dc00
+f800
+fc00
+ce00
+c600
+c700
+c380
+c180
+c1c0
+c0c0
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 19 2 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 800 0
+DWIDTH 20 0
+BBX 16 14 2 0
+BITMAP
+ce3c
+ff7e
+e3c7
+c183
+c183
+c183
+c183
+c183
+c183
+c183
+c183
+c183
+c183
+c183
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 14 2 0
+BITMAP
+ce00
+df80
+f180
+e0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+1f00
+3f80
+71c0
+60c0
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 11 19 2 -5
+BITMAP
+cf00
+df80
+f1c0
+e0c0
+c060
+c060
+c060
+c060
+c060
+c060
+e0c0
+f1c0
+df80
+cf00
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 11 19 1 -5
+BITMAP
+1e60
+3f60
+71e0
+60e0
+c060
+c060
+c060
+c060
+c060
+c060
+60e0
+71e0
+3f60
+1e60
+0060
+0060
+0060
+0060
+0060
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 360 0
+DWIDTH 9 0
+BBX 6 14 2 0
+BITMAP
+cc
+dc
+fc
+e0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+3e00
+7f80
+e1c0
+c0c0
+c000
+f800
+7f00
+0f80
+01c0
+00c0
+c0c0
+c1c0
+ff80
+3f00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 18 1 0
+BITMAP
+30
+30
+30
+30
+fc
+fc
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+3c
+1c
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 14 2 0
+BITMAP
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c1c0
+63c0
+7ec0
+1cc0
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+c060
+c060
+c060
+60c0
+60c0
+71c0
+3180
+3180
+1b00
+1b00
+1b00
+0e00
+0e00
+0e00
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 18 14 0 0
+BITMAP
+c0c0c0
+c0c0c0
+61e180
+61e180
+61e180
+312300
+333300
+333300
+1b3600
+1a1600
+1e1e00
+0e1c00
+0c0c00
+0c0c00
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+c0c0
+e1c0
+6180
+3300
+3f00
+1e00
+0c00
+1e00
+1e00
+3300
+7380
+6180
+e1c0
+c0c0
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 12 19 0 -5
+BITMAP
+c030
+c030
+6030
+7060
+3060
+38e0
+18c0
+18c0
+0d80
+0d80
+0780
+0700
+0300
+0300
+0600
+0600
+0c00
+3c00
+3800
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+ffc0
+ffc0
+0180
+0300
+0700
+0e00
+0c00
+1c00
+3800
+3000
+6000
+e000
+ffc0
+ffc0
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 24 1 -5
+BITMAP
+0c
+18
+30
+30
+30
+30
+30
+30
+30
+30
+60
+c0
+c0
+60
+30
+30
+30
+30
+30
+30
+30
+30
+18
+0c
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 24 2 -5
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 24 1 -5
+BITMAP
+c0
+60
+30
+30
+30
+30
+30
+30
+30
+30
+18
+0c
+0c
+18
+30
+30
+30
+30
+30
+30
+30
+30
+60
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 4 2 5
+BITMAP
+70c0
+fcc0
+cfc0
+c380
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 19 2 -5
+BITMAP
+c0
+c0
+c0
+00
+00
+40
+40
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 10 18 1 -2
+BITMAP
+0180
+0180
+1f00
+3f80
+73c0
+66c0
+c600
+cc00
+cc00
+cc00
+d800
+d800
+d8c0
+71c0
+7f80
+3f00
+6000
+6000
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 18 1 0
+BITMAP
+1f80
+3fe0
+7070
+6030
+6000
+7000
+3000
+1800
+ff80
+ff80
+1800
+1800
+1800
+3000
+3000
+6730
+fff0
+f0e0
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 12 1 3
+BITMAP
+c060
+eee0
+7fc0
+3180
+60c0
+60c0
+60c0
+60c0
+3180
+7fc0
+eee0
+c060
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 14 18 0 0
+BITMAP
+e01c
+6018
+7038
+3030
+3870
+1860
+1ce0
+0cc0
+3ff0
+3ff0
+0300
+3ff0
+3ff0
+0300
+0300
+0300
+0300
+0300
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 23 2 -4
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+00
+00
+00
+00
+00
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 24 1 -5
+BITMAP
+1f00
+3f80
+71c0
+60c0
+70c0
+3800
+1c00
+7e00
+e700
+c380
+c1c0
+c0c0
+6060
+7060
+3860
+1cc0
+0f80
+0700
+0380
+61c0
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 2 1 16
+BITMAP
+cc
+cc
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 17 17 1 0
+BITMAP
+07f000
+1c1c00
+300600
+600300
+43e100
+c63180
+8c1080
+880080
+880080
+880080
+8c1080
+c63180
+43e100
+600300
+300600
+1c1c00
+07f000
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 360 0
+DWIDTH 9 0
+BBX 7 12 1 7
+BITMAP
+78
+cc
+cc
+0c
+7c
+cc
+cc
+dc
+76
+00
+fe
+fe
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 9 8 2 3
+BITMAP
+1980
+3300
+6600
+cc00
+cc00
+6600
+3300
+1980
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 8 1 3
+BITMAP
+fff8
+fff8
+0018
+0018
+0018
+0018
+0018
+0018
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 2 1 6
+BITMAP
+fc
+fc
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 17 17 1 0
+BITMAP
+07f000
+1c1c00
+300600
+600300
+43e100
+c21180
+821080
+821080
+83e080
+824080
+822080
+c22180
+421100
+600300
+300600
+1c1c00
+07f000
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 2 1 16
+BITMAP
+fc
+fc
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 360 0
+DWIDTH 9 0
+BBX 8 7 0 11
+BITMAP
+3c
+66
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+0600
+0600
+0600
+0600
+fff0
+fff0
+0600
+0600
+0600
+0600
+0000
+fff0
+fff0
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 7 10 0 8
+BITMAP
+3c
+7e
+c6
+06
+0c
+18
+30
+60
+fe
+fe
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 7 10 0 8
+BITMAP
+7c
+fe
+c6
+06
+3c
+3c
+06
+c6
+fe
+7c
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 5 4 1 15
+BITMAP
+18
+30
+60
+c0
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 19 2 -5
+BITMAP
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c1c0
+e3c0
+fec0
+dcc0
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 23 1 -4
+BITMAP
+1fc0
+7fc0
+7980
+f980
+f980
+f980
+f980
+f980
+f980
+7980
+7980
+3980
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 3 2 6
+BITMAP
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 5 6 1 -5
+BITMAP
+60
+70
+18
+18
+f8
+70
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 4 10 1 8
+BITMAP
+30
+30
+f0
+f0
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 360 0
+DWIDTH 9 0
+BBX 7 12 1 7
+BITMAP
+38
+6c
+c6
+c6
+c6
+c6
+c6
+6c
+38
+00
+fe
+fe
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 9 8 3 3
+BITMAP
+cc00
+6600
+3300
+1980
+1980
+3300
+6600
+cc00
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 18 18 1 0
+BITMAP
+301800
+301800
+f03000
+f03000
+306000
+306000
+30c000
+30c000
+318300
+318700
+030f00
+030f00
+061b00
+063300
+0c7fc0
+0c7fc0
+180300
+180300
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 18 18 1 0
+BITMAP
+301800
+301800
+f03000
+f03000
+306000
+306000
+30c000
+30c000
+318780
+318fc0
+0318c0
+0300c0
+060180
+060300
+0c0600
+0c0c00
+181fc0
+181fc0
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 19 18 0 0
+BITMAP
+7c0c00
+fe0c00
+c61800
+061800
+3c3000
+3c3000
+066000
+c66000
+fec180
+7cc380
+018780
+018780
+030d80
+031980
+063fe0
+063fe0
+0c0180
+0c0180
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 19 1 -5
+BITMAP
+0c00
+0c00
+0c00
+0000
+0000
+0c00
+0c00
+0c00
+0c00
+1800
+3800
+7000
+6000
+e0c0
+c0c0
+c1c0
+e380
+7f80
+3e00
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 24 1 0
+BITMAP
+0c00
+0600
+0300
+0180
+0000
+0380
+0380
+06c0
+06c0
+0c40
+0c60
+0c60
+1830
+1830
+1830
+3018
+3ff8
+3ff8
+600c
+600c
+600c
+c006
+c006
+c006
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 24 1 0
+BITMAP
+0060
+00c0
+0180
+0300
+0000
+0380
+0380
+06c0
+06c0
+0c40
+0c60
+0c60
+1830
+1830
+1830
+3018
+3ff8
+3ff8
+600c
+600c
+600c
+c006
+c006
+c006
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 24 1 0
+BITMAP
+0180
+03c0
+0660
+0c30
+0000
+0380
+0380
+06c0
+06c0
+0c40
+0c60
+0c60
+1830
+1830
+1830
+3018
+3ff8
+3ff8
+600c
+600c
+600c
+c006
+c006
+c006
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 23 1 0
+BITMAP
+0710
+0db0
+08e0
+0000
+0380
+0380
+06c0
+06c0
+0c40
+0c60
+0c60
+1830
+1830
+1830
+3018
+3ff8
+3ff8
+600c
+600c
+600c
+c006
+c006
+c006
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 23 1 0
+BITMAP
+0c60
+0c60
+0000
+0000
+0380
+0380
+06c0
+06c0
+0c40
+0c60
+0c60
+1830
+1830
+1830
+3018
+3ff8
+3ff8
+600c
+600c
+600c
+c006
+c006
+c006
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 24 1 0
+BITMAP
+0380
+06c0
+06c0
+0380
+0000
+0380
+0380
+06c0
+06c0
+0c40
+0c60
+0c60
+1830
+1830
+1830
+3018
+3ff8
+3ff8
+600c
+600c
+600c
+c006
+c006
+c006
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 920 0
+DWIDTH 23 0
+BBX 21 19 1 0
+BITMAP
+03fff8
+03fff8
+066000
+066000
+0c6000
+0c6000
+0c6000
+186000
+187ff8
+187ff8
+306000
+3fe000
+3fe000
+606000
+606000
+606000
+c06000
+c07ff8
+c07ff8
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 24 1 -5
+BITMAP
+07e0
+1ff8
+3c3c
+700e
+6006
+e006
+c000
+c000
+c000
+c000
+c000
+c000
+c003
+e003
+6006
+700e
+3c3c
+1ff8
+07e0
+0380
+00c0
+00c0
+07c0
+0380
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 12 24 2 0
+BITMAP
+3000
+1800
+0c00
+0600
+0000
+fff0
+fff0
+c000
+c000
+c000
+c000
+c000
+c000
+ffe0
+ffe0
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+fff0
+fff0
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 12 24 2 0
+BITMAP
+0180
+0300
+0600
+0c00
+0000
+fff0
+fff0
+c000
+c000
+c000
+c000
+c000
+c000
+ffe0
+ffe0
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+fff0
+fff0
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 12 24 2 0
+BITMAP
+0600
+0f00
+1980
+30c0
+0000
+fff0
+fff0
+c000
+c000
+c000
+c000
+c000
+c000
+ffe0
+ffe0
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+fff0
+fff0
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 12 23 2 0
+BITMAP
+1980
+1980
+0000
+0000
+fff0
+fff0
+c000
+c000
+c000
+c000
+c000
+c000
+ffe0
+ffe0
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+fff0
+fff0
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 5 24 1 0
+BITMAP
+c0
+60
+30
+18
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 5 24 2 0
+BITMAP
+18
+30
+60
+c0
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 8 24 0 0
+BITMAP
+18
+3c
+66
+c3
+00
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 23 1 0
+BITMAP
+cc
+cc
+00
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 17 19 0 0
+BITMAP
+3ff000
+3ffc00
+301e00
+300700
+300300
+300380
+300180
+300180
+ff0180
+ff0180
+300180
+300180
+300180
+300380
+300300
+300700
+301e00
+3ffc00
+3ff000
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 23 2 0
+BITMAP
+0710
+0db0
+08e0
+0000
+e00c
+f00c
+f00c
+d80c
+dc0c
+cc0c
+ce0c
+c60c
+c70c
+c30c
+c38c
+c18c
+c1cc
+c0cc
+c0ec
+c06c
+c03c
+c03c
+c01c
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 24 1 0
+BITMAP
+0600
+0300
+0180
+00c0
+0000
+07e0
+1ff8
+3c3c
+700e
+6006
+e007
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+e007
+6006
+700e
+3c3c
+1ff8
+07e0
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 24 1 0
+BITMAP
+0030
+0060
+00c0
+0180
+0000
+07e0
+1ff8
+3c3c
+700e
+6006
+e007
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+e007
+6006
+700e
+3c3c
+1ff8
+07e0
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 24 1 0
+BITMAP
+0180
+03c0
+0660
+0c30
+0000
+07e0
+1ff8
+3c3c
+700e
+6006
+e007
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+e007
+6006
+700e
+3c3c
+1ff8
+07e0
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 23 1 0
+BITMAP
+0710
+0db0
+08e0
+0000
+07e0
+1ff8
+3c3c
+700e
+6006
+e007
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+e007
+6006
+700e
+3c3c
+1ff8
+07e0
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 23 1 0
+BITMAP
+0660
+0660
+0000
+0000
+07e0
+1ff8
+3c3c
+700e
+6006
+e007
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+e007
+6006
+700e
+3c3c
+1ff8
+07e0
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 13 12 0 1
+BITMAP
+c018
+6030
+3060
+18c0
+0d80
+0700
+0700
+0d80
+18c0
+3060
+6030
+c018
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 18 19 0 0
+BITMAP
+03f040
+0ffcc0
+1e1f80
+380700
+300700
+700d80
+601980
+603180
+606180
+60c180
+618180
+630180
+660180
+6c0380
+380300
+380700
+7e1e00
+cffc00
+83f000
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 24 2 0
+BITMAP
+0c00
+0600
+0300
+0180
+0000
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+6018
+7038
+3ff0
+0fc0
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 24 2 0
+BITMAP
+0060
+00c0
+0180
+0300
+0000
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+6018
+7038
+3ff0
+0fc0
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 24 2 0
+BITMAP
+0300
+0780
+0cc0
+1860
+0000
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+6018
+7038
+3ff0
+0fc0
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 23 2 0
+BITMAP
+0cc0
+0cc0
+0000
+0000
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+6018
+7038
+3ff0
+0fc0
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 24 1 0
+BITMAP
+0060
+00c0
+0180
+0300
+0000
+c00c
+e01c
+6018
+7038
+3030
+3870
+1860
+1ce0
+0cc0
+0fc0
+0780
+0780
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 13 19 2 0
+BITMAP
+c000
+c000
+c000
+c000
+ffe0
+fff0
+c030
+c018
+c018
+c018
+c018
+c030
+fff0
+ffe0
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 10 19 3 0
+BITMAP
+1c00
+7f00
+e300
+c180
+c180
+c180
+c300
+c700
+ce00
+cf00
+c380
+c180
+c0c0
+c0c0
+c0c0
+c180
+c380
+cf00
+ce00
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+1800
+0c00
+0600
+0300
+0000
+1f00
+3f80
+61c0
+60c0
+00c0
+07c0
+3fc0
+78c0
+e0c0
+c0c0
+c1c0
+e3c0
+7ee0
+3c60
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+0180
+0300
+0600
+0c00
+0000
+1f00
+3f80
+61c0
+60c0
+00c0
+07c0
+3fc0
+78c0
+e0c0
+c0c0
+c1c0
+e3c0
+7ee0
+3c60
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+0600
+0f00
+1980
+30c0
+0000
+1f00
+3f80
+61c0
+60c0
+00c0
+07c0
+3fc0
+78c0
+e0c0
+c0c0
+c1c0
+e3c0
+7ee0
+3c60
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+1c40
+36c0
+2380
+0000
+0000
+1f00
+3f80
+61c0
+60c0
+00c0
+07c0
+3fc0
+78c0
+e0c0
+c0c0
+c1c0
+e3c0
+7ee0
+3c60
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+1980
+1980
+0000
+0000
+1f00
+3f80
+61c0
+60c0
+00c0
+07c0
+3fc0
+78c0
+e0c0
+c0c0
+c1c0
+e3c0
+7ee0
+3c60
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+0e00
+1b00
+1100
+1b00
+0e00
+1f00
+3f80
+61c0
+60c0
+00c0
+07c0
+3fc0
+78c0
+e0c0
+c0c0
+c1c0
+e3c0
+7ee0
+3c60
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 840 0
+DWIDTH 21 0
+BBX 19 14 1 0
+BITMAP
+1f0e00
+3fbf80
+61f1c0
+60e0c0
+00c060
+07c060
+3fffe0
+78ffe0
+e0c000
+c0c000
+c1e060
+e3f0e0
+7e3fc0
+3c0f00
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 19 1 -5
+BITMAP
+1f00
+3f80
+71c0
+60c0
+c000
+c000
+c000
+c000
+c000
+c000
+60c0
+71c0
+3f80
+1f00
+1c00
+0600
+0600
+3e00
+1c00
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+1800
+0c00
+0600
+0300
+0000
+0e00
+3f80
+71c0
+60c0
+c060
+c060
+ffe0
+ffe0
+c000
+c000
+6060
+70e0
+3fc0
+0f00
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+0180
+0300
+0600
+0c00
+0000
+0e00
+3f80
+71c0
+60c0
+c060
+c060
+ffe0
+ffe0
+c000
+c000
+6060
+70e0
+3fc0
+0f00
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+0600
+0f00
+1980
+30c0
+0000
+0e00
+3f80
+71c0
+60c0
+c060
+c060
+ffe0
+ffe0
+c000
+c000
+6060
+70e0
+3fc0
+0f00
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+1980
+1980
+0000
+0000
+0e00
+3f80
+71c0
+60c0
+c060
+c060
+ffe0
+ffe0
+c000
+c000
+6060
+70e0
+3fc0
+0f00
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 5 19 0 0
+BITMAP
+c0
+60
+30
+18
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 5 19 1 0
+BITMAP
+18
+30
+60
+c0
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 8 19 -1 0
+BITMAP
+18
+3c
+66
+c3
+00
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 6 18 0 0
+BITMAP
+cc
+cc
+00
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+e000
+7180
+1e00
+3c00
+c600
+1f00
+3f80
+71c0
+60c0
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 18 2 0
+BITMAP
+3880
+6d80
+4700
+0000
+ce00
+df80
+f180
+e0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+1800
+0c00
+0600
+0300
+0000
+1f00
+3f80
+71c0
+60c0
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+0180
+0300
+0600
+0c00
+0000
+1f00
+3f80
+71c0
+60c0
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+0600
+0f00
+1980
+30c0
+0000
+1f00
+3f80
+71c0
+60c0
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+1c40
+36c0
+2380
+0000
+1f00
+3f80
+71c0
+60c0
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+3180
+3180
+0000
+0000
+1f00
+3f80
+71c0
+60c0
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 12 1 1
+BITMAP
+0600
+0600
+0600
+0000
+0000
+fff0
+fff0
+0000
+0000
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 13 14 0 0
+BITMAP
+0f98
+1ff0
+38e0
+3060
+60f0
+61b0
+6330
+6630
+6630
+6c30
+3860
+30e0
+7fc0
+cf80
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 19 2 0
+BITMAP
+3000
+1800
+0c00
+0600
+0000
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c1c0
+63c0
+7ec0
+1cc0
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 19 2 0
+BITMAP
+0180
+0300
+0600
+0c00
+0000
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c1c0
+63c0
+7ec0
+1cc0
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 19 2 0
+BITMAP
+0c00
+1e00
+3300
+6180
+0000
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c1c0
+63c0
+7ec0
+1cc0
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 18 2 0
+BITMAP
+3300
+3300
+0000
+0000
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c1c0
+63c0
+7ec0
+1cc0
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 12 24 0 -5
+BITMAP
+00c0
+0180
+0300
+0600
+0000
+c030
+c030
+6030
+7060
+3060
+38e0
+18c0
+18c0
+0d80
+0d80
+0780
+0700
+0300
+0300
+0600
+0600
+0c00
+3c00
+3800
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 11 24 2 -5
+BITMAP
+c000
+c000
+c000
+c000
+c000
+cf00
+df80
+f1c0
+e0c0
+c060
+c060
+c060
+c060
+c060
+c060
+e0c0
+f1c0
+df80
+cf00
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 12 23 0 -5
+BITMAP
+1980
+1980
+0000
+0000
+c030
+c030
+6030
+7060
+3060
+38e0
+18c0
+18c0
+0d80
+0d80
+0780
+0700
+0300
+0300
+0600
+0600
+0c00
+3c00
+3800
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/helvetica24.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/helvetica24.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/helvetica24.h	(revision 12606)
@@ -0,0 +1,1170 @@
+static unsigned char helvetica24_0_bits[] = {
+0x00};
+static unsigned char helvetica24_1_bits[] = {
+0x00};
+static unsigned char helvetica24_2_bits[] = {
+0x00};
+static unsigned char helvetica24_3_bits[] = {
+0x00};
+static unsigned char helvetica24_4_bits[] = {
+0x00};
+static unsigned char helvetica24_5_bits[] = {
+0x00};
+static unsigned char helvetica24_6_bits[] = {
+0x00};
+static unsigned char helvetica24_7_bits[] = {
+0x00};
+static unsigned char helvetica24_8_bits[] = {
+0x00};
+static unsigned char helvetica24_9_bits[] = {
+0x00};
+static unsigned char helvetica24_10_bits[] = {
+0x00};
+static unsigned char helvetica24_11_bits[] = {
+0x00};
+static unsigned char helvetica24_12_bits[] = {
+0x00};
+static unsigned char helvetica24_13_bits[] = {
+0x00};
+static unsigned char helvetica24_14_bits[] = {
+0x00};
+static unsigned char helvetica24_15_bits[] = {
+0x00};
+static unsigned char helvetica24_16_bits[] = {
+0x00};
+static unsigned char helvetica24_17_bits[] = {
+0x00};
+static unsigned char helvetica24_18_bits[] = {
+0x00};
+static unsigned char helvetica24_19_bits[] = {
+0x00};
+static unsigned char helvetica24_20_bits[] = {
+0x00};
+static unsigned char helvetica24_21_bits[] = {
+0x00};
+static unsigned char helvetica24_22_bits[] = {
+0x00};
+static unsigned char helvetica24_23_bits[] = {
+0x00};
+static unsigned char helvetica24_24_bits[] = {
+0x00};
+static unsigned char helvetica24_25_bits[] = {
+0x00};
+static unsigned char helvetica24_26_bits[] = {
+0x00};
+static unsigned char helvetica24_27_bits[] = {
+0x00};
+static unsigned char helvetica24_28_bits[] = {
+0x00};
+static unsigned char helvetica24_29_bits[] = {
+0x00};
+static unsigned char helvetica24_30_bits[] = {
+0x00};
+static unsigned char helvetica24_31_bits[] = {
+0x00, 0x00};
+static unsigned char helvetica24_32_bits[] = {
+0x00, 0x00};
+static unsigned char helvetica24_33_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x01, 0x01, 0x00, 0x00, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_34_bits[] = {
+0x33, 0x33, 0x33, 0x33, 0x33, 0x22};
+static unsigned char helvetica24_35_bits[] = {
+0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x98, 0x01, 0xff, 0x07, 0xff, 0x07, 
+0x98, 0x01, 0x98, 0x01, 0xcc, 0x00, 0xcc, 0x00, 0xff, 0x07, 0xff, 0x07, 
+0xcc, 0x00, 0xcc, 0x00, 0x66, 0x00, 0x66, 0x00, 0x66, 0x00};
+static unsigned char helvetica24_36_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0xfc, 0x01, 0xfe, 0x03, 0x67, 0x07, 0x63, 0x06, 
+0x63, 0x00, 0x67, 0x00, 0x6e, 0x00, 0x7c, 0x00, 0xf0, 0x01, 0xe0, 0x03, 
+0x60, 0x07, 0x60, 0x06, 0x63, 0x06, 0x63, 0x06, 0x67, 0x07, 0xfe, 0x03, 
+0xfc, 0x01, 0x60, 0x00, 0x60, 0x00};
+static unsigned char helvetica24_37_bits[] = {
+0x00, 0x60, 0x00, 0x3c, 0x30, 0x00, 0x7e, 0x30, 0x00, 0xc3, 0x18, 0x00, 
+0xc3, 0x18, 0x00, 0xc3, 0x0c, 0x00, 0xc3, 0x0c, 0x00, 0x7e, 0x06, 0x00, 
+0x3c, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0xe3, 0x01, 0x80, 0xf1, 0x03, 
+0x80, 0x19, 0x06, 0xc0, 0x18, 0x06, 0xc0, 0x18, 0x06, 0x60, 0x18, 0x06, 
+0x60, 0xf0, 0x03, 0x20, 0xe0, 0x01};
+static unsigned char helvetica24_38_bits[] = {
+0xf0, 0x00, 0xf8, 0x01, 0x9c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 
+0x98, 0x01, 0xf0, 0x00, 0x78, 0x00, 0xfc, 0x18, 0xce, 0x19, 0x86, 0x1b, 
+0x03, 0x0f, 0x03, 0x06, 0x03, 0x0f, 0x87, 0x1b, 0xfe, 0x39, 0x78, 0x00};
+static unsigned char helvetica24_39_bits[] = {
+0x03, 0x03, 0x03, 0x02, 0x02, 0x01};
+static unsigned char helvetica24_40_bits[] = {
+0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x06, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18};
+static unsigned char helvetica24_41_bits[] = {
+0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03};
+static unsigned char helvetica24_42_bits[] = {
+0x08, 0x08, 0x6b, 0x3e, 0x1c, 0x36, 0x22};
+static unsigned char helvetica24_43_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xff, 0x0f, 
+0xff, 0x0f, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char helvetica24_44_bits[] = {
+0x03, 0x03, 0x03, 0x02, 0x02, 0x01};
+static unsigned char helvetica24_45_bits[] = {
+0xff, 0x07, 0xff, 0x07};
+static unsigned char helvetica24_46_bits[] = {
+0x03, 0x03, 0x03};
+static unsigned char helvetica24_47_bits[] = {
+0x60, 0x60, 0x60, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x0c, 
+0x0c, 0x06, 0x06, 0x06, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_48_bits[] = {
+0xf8, 0x00, 0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x06, 0x03, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x06, 0x03, 0x06, 0x03, 0x8e, 0x03, 0xfc, 0x01, 0xf8, 0x00};
+static unsigned char helvetica24_49_bits[] = {
+0x30, 0x30, 0x38, 0x3f, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 
+0x30, 0x30, 0x30, 0x30, 0x30, 0x30};
+static unsigned char helvetica24_50_bits[] = {
+0x78, 0x00, 0xfe, 0x01, 0x86, 0x03, 0x03, 0x03, 0x03, 0x06, 0x03, 0x06, 
+0x00, 0x06, 0x00, 0x03, 0x80, 0x03, 0xc0, 0x01, 0xf0, 0x00, 0x38, 0x00, 
+0x1c, 0x00, 0x0e, 0x00, 0x07, 0x00, 0x03, 0x00, 0xff, 0x07, 0xff, 0x07};
+static unsigned char helvetica24_51_bits[] = {
+0xf8, 0x00, 0xfe, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x00, 0x03, 0x80, 0x01, 0xf0, 0x00, 0xf0, 0x03, 0x00, 0x03, 0x00, 0x06, 
+0x00, 0x06, 0x03, 0x06, 0x03, 0x03, 0x86, 0x03, 0xfe, 0x01, 0xf8, 0x00};
+static unsigned char helvetica24_52_bits[] = {
+0x80, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xe0, 0x01, 0xf0, 0x01, 0xb0, 0x01, 
+0x98, 0x01, 0x9c, 0x01, 0x8c, 0x01, 0x86, 0x01, 0x87, 0x01, 0x83, 0x01, 
+0xff, 0x07, 0xff, 0x07, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01};
+static unsigned char helvetica24_53_bits[] = {
+0xfe, 0x03, 0xfe, 0x03, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 
+0x76, 0x00, 0xfe, 0x01, 0x8e, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0x06, 
+0x00, 0x06, 0x03, 0x06, 0x03, 0x03, 0x87, 0x03, 0xfe, 0x01, 0x78, 0x00};
+static unsigned char helvetica24_54_bits[] = {
+0xf0, 0x00, 0xfc, 0x03, 0x0e, 0x03, 0x06, 0x06, 0x07, 0x06, 0x03, 0x00, 
+0x03, 0x00, 0xf3, 0x00, 0xfb, 0x01, 0x8f, 0x03, 0x07, 0x03, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x07, 0x06, 0x06, 0x03, 0xfe, 0x03, 0xf8, 0x00};
+static unsigned char helvetica24_55_bits[] = {
+0xff, 0x07, 0xff, 0x07, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0x80, 0x01, 
+0xc0, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x38, 0x00, 0x18, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x0c, 0x00, 0x0c, 0x00};
+static unsigned char helvetica24_56_bits[] = {
+0x70, 0x00, 0xfc, 0x01, 0x8c, 0x01, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x8c, 0x01, 0xf8, 0x00, 0xfc, 0x01, 0x06, 0x03, 0x07, 0x07, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x8e, 0x03, 0xfe, 0x03, 0xf8, 0x00};
+static unsigned char helvetica24_57_bits[] = {
+0xf8, 0x00, 0xfe, 0x03, 0x8e, 0x03, 0x07, 0x03, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x07, 0x07, 0x8e, 0x07, 0xfe, 0x06, 0x78, 0x06, 
+0x00, 0x06, 0x00, 0x07, 0x03, 0x03, 0x87, 0x03, 0xfe, 0x01, 0x78, 0x00};
+static unsigned char helvetica24_58_bits[] = {
+0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 
+0x03, 0x03};
+static unsigned char helvetica24_59_bits[] = {
+0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 
+0x03, 0x03, 0x02, 0x02, 0x01};
+static unsigned char helvetica24_60_bits[] = {
+0x00, 0x0c, 0x00, 0x0f, 0xc0, 0x03, 0xf0, 0x00, 0x3c, 0x00, 0x07, 0x00, 
+0x07, 0x00, 0x3c, 0x00, 0xf0, 0x00, 0xc0, 0x03, 0x00, 0x0f, 0x00, 0x0c};
+static unsigned char helvetica24_61_bits[] = {
+0xff, 0x03, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xff, 0x03};
+static unsigned char helvetica24_62_bits[] = {
+0x03, 0x00, 0x0f, 0x00, 0x3c, 0x00, 0xf0, 0x00, 0xc0, 0x03, 0x00, 0x0e, 
+0x00, 0x0e, 0xc0, 0x03, 0xf0, 0x00, 0x3c, 0x00, 0x0f, 0x00, 0x03, 0x00};
+static unsigned char helvetica24_63_bits[] = {
+0xf8, 0x00, 0xfe, 0x01, 0x8e, 0x03, 0x07, 0x03, 0x03, 0x03, 0x83, 0x03, 
+0x80, 0x01, 0xc0, 0x01, 0xe0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x30, 0x00};
+static unsigned char helvetica24_64_bits[] = {
+0x00, 0xff, 0x00, 0xc0, 0xff, 0x03, 0xf0, 0x80, 0x07, 0x38, 0x00, 0x0e, 
+0x1c, 0x00, 0x18, 0x0c, 0x00, 0x18, 0x06, 0xce, 0x30, 0x06, 0xdf, 0x30, 
+0x83, 0xe3, 0x30, 0xc3, 0x61, 0x30, 0xc3, 0x60, 0x30, 0x63, 0x60, 0x30, 
+0x63, 0x30, 0x38, 0x63, 0x30, 0x18, 0x63, 0x30, 0x1c, 0xe7, 0x38, 0x0e, 
+0xc6, 0xef, 0x07, 0x8e, 0xc7, 0x01, 0x1c, 0x00, 0x00, 0x38, 0x00, 0x00, 
+0xf0, 0xc0, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x3f, 0x00};
+static unsigned char helvetica24_65_bits[] = {
+0xc0, 0x01, 0xc0, 0x01, 0x60, 0x03, 0x60, 0x03, 0x30, 0x02, 0x30, 0x06, 
+0x30, 0x06, 0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x0c, 0x18, 0xfc, 0x1f, 
+0xfc, 0x1f, 0x06, 0x30, 0x06, 0x30, 0x06, 0x30, 0x03, 0x60, 0x03, 0x60, 
+0x03, 0x60};
+static unsigned char helvetica24_66_bits[] = {
+0xff, 0x03, 0xff, 0x0f, 0x03, 0x0e, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x03, 0x18, 0x03, 0x0c, 0xff, 0x07, 0xff, 0x0f, 0x03, 0x18, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x38, 0x03, 0x1c, 0xff, 0x0f, 
+0xff, 0x03};
+static unsigned char helvetica24_67_bits[] = {
+0xe0, 0x07, 0xf8, 0x1f, 0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0x60, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0xc0, 0x07, 0xc0, 0x06, 0x60, 0x0e, 0x70, 0x3c, 0x3c, 0xf8, 0x1f, 
+0xe0, 0x07};
+static unsigned char helvetica24_68_bits[] = {
+0xff, 0x03, 0xff, 0x0f, 0x03, 0x1e, 0x03, 0x38, 0x03, 0x30, 0x03, 0x70, 
+0x03, 0x60, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60, 
+0x03, 0x60, 0x03, 0x70, 0x03, 0x30, 0x03, 0x38, 0x03, 0x1e, 0xff, 0x0f, 
+0xff, 0x03};
+static unsigned char helvetica24_69_bits[] = {
+0xff, 0x0f, 0xff, 0x0f, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0xff, 0x07, 0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x0f, 
+0xff, 0x0f};
+static unsigned char helvetica24_70_bits[] = {
+0xff, 0x07, 0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x03, 0xff, 0x03, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00};
+static unsigned char helvetica24_71_bits[] = {
+0xe0, 0x07, 0xf8, 0x1f, 0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0x60, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0xfe, 0x03, 0xfe, 0x03, 0xc0, 
+0x03, 0xc0, 0x07, 0xc0, 0x06, 0xe0, 0x0e, 0xf0, 0x3c, 0xfc, 0xf8, 0xdf, 
+0xe0, 0xc7};
+static unsigned char helvetica24_72_bits[] = {
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0xff, 0x3f, 0xff, 0x3f, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30};
+static unsigned char helvetica24_73_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_74_bits[] = {
+0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 
+0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x86, 0x01, 0xfe, 0x01, 
+0xfc, 0x00};
+static unsigned char helvetica24_75_bits[] = {
+0x03, 0x1c, 0x03, 0x0e, 0x03, 0x07, 0x83, 0x03, 0xc3, 0x01, 0xe3, 0x00, 
+0x73, 0x00, 0x3b, 0x00, 0x3f, 0x00, 0x7f, 0x00, 0xe7, 0x00, 0xc3, 0x01, 
+0x83, 0x03, 0x03, 0x07, 0x03, 0x0e, 0x03, 0x1c, 0x03, 0x38, 0x03, 0x70, 
+0x03, 0x60};
+static unsigned char helvetica24_76_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x07, 
+0xff, 0x07};
+static unsigned char helvetica24_77_bits[] = {
+0x03, 0x80, 0x01, 0x07, 0xc0, 0x01, 0x07, 0xc0, 0x01, 0x0f, 0xe0, 0x01, 
+0x0f, 0xe0, 0x01, 0x1b, 0xb0, 0x01, 0x1b, 0xb0, 0x01, 0x1b, 0xb0, 0x01, 
+0x33, 0x98, 0x01, 0x33, 0x98, 0x01, 0x33, 0x98, 0x01, 0x63, 0x8c, 0x01, 
+0x63, 0x8c, 0x01, 0x63, 0x8c, 0x01, 0xc3, 0x86, 0x01, 0xc3, 0x86, 0x01, 
+0xc3, 0x86, 0x01, 0x83, 0x83, 0x01, 0x83, 0x83, 0x01};
+static unsigned char helvetica24_78_bits[] = {
+0x07, 0x30, 0x0f, 0x30, 0x0f, 0x30, 0x1b, 0x30, 0x3b, 0x30, 0x33, 0x30, 
+0x73, 0x30, 0x63, 0x30, 0xe3, 0x30, 0xc3, 0x30, 0xc3, 0x31, 0x83, 0x31, 
+0x83, 0x33, 0x03, 0x33, 0x03, 0x37, 0x03, 0x36, 0x03, 0x3c, 0x03, 0x3c, 
+0x03, 0x38};
+static unsigned char helvetica24_79_bits[] = {
+0xe0, 0x07, 0xf8, 0x1f, 0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0xe0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0, 0x07, 0xe0, 0x06, 0x60, 0x0e, 0x70, 0x3c, 0x3c, 0xf8, 0x1f, 
+0xe0, 0x07};
+static unsigned char helvetica24_80_bits[] = {
+0xff, 0x07, 0xff, 0x0f, 0x03, 0x0c, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x03, 0x18, 0x03, 0x0c, 0xff, 0x0f, 0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00};
+static unsigned char helvetica24_81_bits[] = {
+0xe0, 0x07, 0xf8, 0x1f, 0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0xe0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0, 0x07, 0xe0, 0x06, 0x67, 0x0e, 0x7e, 0x3c, 0x38, 0xf8, 0x7f, 
+0xe0, 0xe7};
+static unsigned char helvetica24_82_bits[] = {
+0xff, 0x07, 0xff, 0x0f, 0x03, 0x0c, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x03, 0x18, 0x03, 0x0c, 0xff, 0x0f, 0xff, 0x07, 0x03, 0x0e, 0x03, 0x0c, 
+0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x03, 0x18};
+static unsigned char helvetica24_83_bits[] = {
+0xe0, 0x03, 0xf8, 0x0f, 0x1c, 0x1c, 0x0e, 0x18, 0x06, 0x18, 0x06, 0x00, 
+0x0e, 0x00, 0x7c, 0x00, 0xf0, 0x03, 0x80, 0x0f, 0x00, 0x1e, 0x00, 0x38, 
+0x00, 0x30, 0x03, 0x30, 0x03, 0x30, 0x07, 0x38, 0x1e, 0x1c, 0xfc, 0x0f, 
+0xf0, 0x03};
+static unsigned char helvetica24_84_bits[] = {
+0xff, 0x3f, 0xff, 0x3f, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00};
+static unsigned char helvetica24_85_bits[] = {
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x06, 0x18, 0x0e, 0x1c, 0xfc, 0x0f, 
+0xf0, 0x03};
+static unsigned char helvetica24_86_bits[] = {
+0x03, 0x60, 0x03, 0x60, 0x07, 0x70, 0x06, 0x30, 0x0e, 0x38, 0x0c, 0x18, 
+0x0c, 0x18, 0x1c, 0x1c, 0x18, 0x0c, 0x18, 0x0c, 0x38, 0x0e, 0x30, 0x06, 
+0x30, 0x06, 0x70, 0x07, 0x60, 0x03, 0x60, 0x03, 0xc0, 0x01, 0xc0, 0x01, 
+0xc0, 0x01};
+static unsigned char helvetica24_87_bits[] = {
+0x03, 0x06, 0x0c, 0x03, 0x06, 0x0c, 0x03, 0x06, 0x0c, 0x03, 0x0f, 0x0c, 
+0x06, 0x0f, 0x06, 0x86, 0x19, 0x06, 0x86, 0x19, 0x06, 0x86, 0x19, 0x06, 
+0x86, 0x19, 0x06, 0x8c, 0x19, 0x03, 0xcc, 0x30, 0x03, 0xcc, 0x30, 0x03, 
+0xcc, 0x30, 0x03, 0xd8, 0xb0, 0x01, 0xd8, 0xb0, 0x01, 0x78, 0xe0, 0x01, 
+0x70, 0xe0, 0x00, 0x30, 0xc0, 0x00, 0x30, 0xc0, 0x00};
+static unsigned char helvetica24_88_bits[] = {
+0x03, 0x60, 0x07, 0x70, 0x0e, 0x38, 0x0c, 0x18, 0x18, 0x0c, 0x38, 0x0e, 
+0x70, 0x07, 0xe0, 0x03, 0xc0, 0x01, 0xc0, 0x01, 0xe0, 0x03, 0x70, 0x07, 
+0x30, 0x06, 0x38, 0x0e, 0x1c, 0x1c, 0x0c, 0x18, 0x06, 0x30, 0x07, 0x70, 
+0x03, 0x60};
+static unsigned char helvetica24_89_bits[] = {
+0x03, 0x30, 0x07, 0x38, 0x06, 0x18, 0x0e, 0x1c, 0x0c, 0x0c, 0x1c, 0x0e, 
+0x18, 0x06, 0x38, 0x07, 0x30, 0x03, 0xf0, 0x03, 0xe0, 0x01, 0xe0, 0x01, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00};
+static unsigned char helvetica24_90_bits[] = {
+0xff, 0x1f, 0xff, 0x1f, 0x00, 0x1c, 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 
+0x80, 0x03, 0xc0, 0x01, 0xe0, 0x00, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 
+0x38, 0x00, 0x1c, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x07, 0x00, 0xff, 0x1f, 
+0xff, 0x1f};
+static unsigned char helvetica24_91_bits[] = {
+0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x0f, 0x0f};
+static unsigned char helvetica24_92_bits[] = {
+0x03, 0x03, 0x03, 0x06, 0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x18, 
+0x18, 0x30, 0x30, 0x30, 0x60, 0x60, 0x60};
+static unsigned char helvetica24_93_bits[] = {
+0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f};
+static unsigned char helvetica24_94_bits[] = {
+0x30, 0x00, 0x30, 0x00, 0x78, 0x00, 0x48, 0x00, 0xcc, 0x00, 0x86, 0x01, 
+0x86, 0x01, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_95_bits[] = {
+0xff, 0x3f, 0xff, 0x3f};
+static unsigned char helvetica24_96_bits[] = {
+0x02, 0x01, 0x01, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_97_bits[] = {
+0xf8, 0x00, 0xfc, 0x01, 0x86, 0x03, 0x06, 0x03, 0x00, 0x03, 0xe0, 0x03, 
+0xfc, 0x03, 0x1e, 0x03, 0x07, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc7, 0x03, 
+0x7e, 0x07, 0x3c, 0x06};
+static unsigned char helvetica24_98_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xf3, 0x00, 
+0xfb, 0x01, 0x8f, 0x03, 0x07, 0x03, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x07, 0x03, 0x8f, 0x03, 0xfb, 0x01, 
+0xf3, 0x00};
+static unsigned char helvetica24_99_bits[] = {
+0xf8, 0x00, 0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x03, 0x8e, 0x03, 
+0xfc, 0x01, 0xf8, 0x00};
+static unsigned char helvetica24_100_bits[] = {
+0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x78, 0x06, 
+0xfc, 0x06, 0x8e, 0x07, 0x06, 0x07, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x07, 0x8e, 0x07, 0xfc, 0x06, 
+0x78, 0x06};
+static unsigned char helvetica24_101_bits[] = {
+0x70, 0x00, 0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 
+0xff, 0x07, 0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x06, 0x06, 0x0e, 0x07, 
+0xfc, 0x03, 0xf0, 0x00};
+static unsigned char helvetica24_102_bits[] = {
+0x38, 0x3c, 0x0c, 0x0c, 0x0c, 0x3f, 0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
+static unsigned char helvetica24_103_bits[] = {
+0x78, 0x06, 0xfc, 0x06, 0x8e, 0x07, 0x06, 0x07, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x07, 0x8e, 0x07, 
+0xfc, 0x06, 0x78, 0x06, 0x00, 0x06, 0x03, 0x06, 0x07, 0x03, 0xfe, 0x03, 
+0xf8, 0x00};
+static unsigned char helvetica24_104_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x73, 0x00, 
+0xfb, 0x01, 0x8f, 0x01, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03};
+static unsigned char helvetica24_105_bits[] = {
+0x03, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_106_bits[] = {
+0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x07};
+static unsigned char helvetica24_107_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x83, 0x01, 
+0xc3, 0x01, 0xe3, 0x00, 0x73, 0x00, 0x3b, 0x00, 0x1f, 0x00, 0x3f, 0x00, 
+0x73, 0x00, 0x63, 0x00, 0xe3, 0x00, 0xc3, 0x01, 0x83, 0x01, 0x83, 0x03, 
+0x03, 0x03};
+static unsigned char helvetica24_108_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_109_bits[] = {
+0x73, 0x3c, 0xff, 0x7e, 0xc7, 0xe3, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 
+0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 
+0x83, 0xc1, 0x83, 0xc1};
+static unsigned char helvetica24_110_bits[] = {
+0x73, 0x00, 0xfb, 0x01, 0x8f, 0x01, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_111_bits[] = {
+0xf8, 0x00, 0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0x8e, 0x03, 
+0xfc, 0x01, 0xf8, 0x00};
+static unsigned char helvetica24_112_bits[] = {
+0xf3, 0x00, 0xfb, 0x01, 0x8f, 0x03, 0x07, 0x03, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x07, 0x03, 0x8f, 0x03, 
+0xfb, 0x01, 0xf3, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00};
+static unsigned char helvetica24_113_bits[] = {
+0x78, 0x06, 0xfc, 0x06, 0x8e, 0x07, 0x06, 0x07, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x07, 0x8e, 0x07, 
+0xfc, 0x06, 0x78, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 
+0x00, 0x06};
+static unsigned char helvetica24_114_bits[] = {
+0x33, 0x3b, 0x3f, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03};
+static unsigned char helvetica24_115_bits[] = {
+0x7c, 0x00, 0xfe, 0x01, 0x87, 0x03, 0x03, 0x03, 0x03, 0x00, 0x1f, 0x00, 
+0xfe, 0x00, 0xf0, 0x01, 0x80, 0x03, 0x00, 0x03, 0x03, 0x03, 0x83, 0x03, 
+0xff, 0x01, 0xfc, 0x00};
+static unsigned char helvetica24_116_bits[] = {
+0x0c, 0x0c, 0x0c, 0x0c, 0x3f, 0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x38};
+static unsigned char helvetica24_117_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc6, 0x03, 
+0x7e, 0x03, 0x38, 0x03};
+static unsigned char helvetica24_118_bits[] = {
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0x06, 0x03, 0x8e, 0x03, 
+0x8c, 0x01, 0x8c, 0x01, 0xd8, 0x00, 0xd8, 0x00, 0xd8, 0x00, 0x70, 0x00, 
+0x70, 0x00, 0x70, 0x00};
+static unsigned char helvetica24_119_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x86, 0x87, 0x01, 0x86, 0x87, 0x01, 
+0x86, 0x87, 0x01, 0x8c, 0xc4, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00, 
+0xd8, 0x6c, 0x00, 0x58, 0x68, 0x00, 0x78, 0x78, 0x00, 0x70, 0x38, 0x00, 
+0x30, 0x30, 0x00, 0x30, 0x30, 0x00};
+static unsigned char helvetica24_120_bits[] = {
+0x03, 0x03, 0x87, 0x03, 0x86, 0x01, 0xcc, 0x00, 0xfc, 0x00, 0x78, 0x00, 
+0x30, 0x00, 0x78, 0x00, 0x78, 0x00, 0xcc, 0x00, 0xce, 0x01, 0x86, 0x01, 
+0x87, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_121_bits[] = {
+0x03, 0x0c, 0x03, 0x0c, 0x06, 0x0c, 0x0e, 0x06, 0x0c, 0x06, 0x1c, 0x07, 
+0x18, 0x03, 0x18, 0x03, 0xb0, 0x01, 0xb0, 0x01, 0xe0, 0x01, 0xe0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x3c, 0x00, 
+0x1c, 0x00};
+static unsigned char helvetica24_122_bits[] = {
+0xff, 0x03, 0xff, 0x03, 0x80, 0x01, 0xc0, 0x00, 0xe0, 0x00, 0x70, 0x00, 
+0x30, 0x00, 0x38, 0x00, 0x1c, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x07, 0x00, 
+0xff, 0x03, 0xff, 0x03};
+static unsigned char helvetica24_123_bits[] = {
+0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x06, 0x03, 
+0x03, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30};
+static unsigned char helvetica24_124_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_125_bits[] = {
+0x03, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 
+0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x06, 0x03};
+static unsigned char helvetica24_126_bits[] = {
+0x0e, 0x03, 0x3f, 0x03, 0xf3, 0x03, 0xc3, 0x01};
+static unsigned char helvetica24_127_bits[] = {
+0x00};
+static unsigned char helvetica24_128_bits[] = {
+0x00};
+static unsigned char helvetica24_129_bits[] = {
+0x00};
+static unsigned char helvetica24_130_bits[] = {
+0x00};
+static unsigned char helvetica24_131_bits[] = {
+0x00};
+static unsigned char helvetica24_132_bits[] = {
+0x00};
+static unsigned char helvetica24_133_bits[] = {
+0x00};
+static unsigned char helvetica24_134_bits[] = {
+0x00};
+static unsigned char helvetica24_135_bits[] = {
+0x00};
+static unsigned char helvetica24_136_bits[] = {
+0x00};
+static unsigned char helvetica24_137_bits[] = {
+0x00};
+static unsigned char helvetica24_138_bits[] = {
+0x00};
+static unsigned char helvetica24_139_bits[] = {
+0x00};
+static unsigned char helvetica24_140_bits[] = {
+0x00};
+static unsigned char helvetica24_141_bits[] = {
+0x00};
+static unsigned char helvetica24_142_bits[] = {
+0x00};
+static unsigned char helvetica24_143_bits[] = {
+0x00};
+static unsigned char helvetica24_144_bits[] = {
+0x00};
+static unsigned char helvetica24_145_bits[] = {
+0x00};
+static unsigned char helvetica24_146_bits[] = {
+0x00};
+static unsigned char helvetica24_147_bits[] = {
+0x00};
+static unsigned char helvetica24_148_bits[] = {
+0x00};
+static unsigned char helvetica24_149_bits[] = {
+0x00};
+static unsigned char helvetica24_150_bits[] = {
+0x00};
+static unsigned char helvetica24_151_bits[] = {
+0x00};
+static unsigned char helvetica24_152_bits[] = {
+0x00};
+static unsigned char helvetica24_153_bits[] = {
+0x00};
+static unsigned char helvetica24_154_bits[] = {
+0x00};
+static unsigned char helvetica24_155_bits[] = {
+0x00};
+static unsigned char helvetica24_156_bits[] = {
+0x00};
+static unsigned char helvetica24_157_bits[] = {
+0x00};
+static unsigned char helvetica24_158_bits[] = {
+0x00};
+static unsigned char helvetica24_159_bits[] = {
+0x00};
+static unsigned char helvetica24_160_bits[] = {
+0x00};
+static unsigned char helvetica24_161_bits[] = {
+0x03, 0x03, 0x03, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_162_bits[] = {
+0x80, 0x01, 0x80, 0x01, 0xf8, 0x00, 0xfc, 0x01, 0xce, 0x03, 0x66, 0x03, 
+0x63, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x1b, 0x00, 0x1b, 0x00, 
+0x1b, 0x03, 0x8e, 0x03, 0xfe, 0x01, 0xfc, 0x00, 0x06, 0x00, 0x06, 0x00};
+static unsigned char helvetica24_163_bits[] = {
+0xf8, 0x01, 0xfc, 0x07, 0x0e, 0x0e, 0x06, 0x0c, 0x06, 0x00, 0x0e, 0x00, 
+0x0c, 0x00, 0x18, 0x00, 0xff, 0x01, 0xff, 0x01, 0x18, 0x00, 0x18, 0x00, 
+0x18, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0xe6, 0x0c, 0xff, 0x0f, 0x0f, 0x07};
+static unsigned char helvetica24_164_bits[] = {
+0x03, 0x06, 0x77, 0x07, 0xfe, 0x03, 0x8c, 0x01, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x8c, 0x01, 0xfe, 0x03, 0x77, 0x07, 0x03, 0x06};
+static unsigned char helvetica24_165_bits[] = {
+0x07, 0x38, 0x06, 0x18, 0x0e, 0x1c, 0x0c, 0x0c, 0x1c, 0x0e, 0x18, 0x06, 
+0x38, 0x07, 0x30, 0x03, 0xfc, 0x0f, 0xfc, 0x0f, 0xc0, 0x00, 0xfc, 0x0f, 
+0xfc, 0x0f, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00};
+static unsigned char helvetica24_166_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_167_bits[] = {
+0xf8, 0x00, 0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x0e, 0x03, 0x1c, 0x00, 
+0x38, 0x00, 0x7e, 0x00, 0xe7, 0x00, 0xc3, 0x01, 0x83, 0x03, 0x03, 0x03, 
+0x06, 0x06, 0x0e, 0x06, 0x1c, 0x06, 0x38, 0x03, 0xf0, 0x01, 0xe0, 0x00, 
+0xc0, 0x01, 0x86, 0x03, 0x06, 0x03, 0x8e, 0x03, 0xfc, 0x01, 0xf8, 0x00};
+static unsigned char helvetica24_168_bits[] = {
+0x33, 0x33};
+static unsigned char helvetica24_169_bits[] = {
+0xe0, 0x0f, 0x00, 0x38, 0x38, 0x00, 0x0c, 0x60, 0x00, 0x06, 0xc0, 0x00, 
+0xc2, 0x87, 0x00, 0x63, 0x8c, 0x01, 0x31, 0x08, 0x01, 0x11, 0x00, 0x01, 
+0x11, 0x00, 0x01, 0x11, 0x00, 0x01, 0x31, 0x08, 0x01, 0x63, 0x8c, 0x01, 
+0xc2, 0x87, 0x00, 0x06, 0xc0, 0x00, 0x0c, 0x60, 0x00, 0x38, 0x38, 0x00, 
+0xe0, 0x0f, 0x00};
+static unsigned char helvetica24_170_bits[] = {
+0x1e, 0x33, 0x33, 0x30, 0x3e, 0x33, 0x33, 0x3b, 0x6e, 0x00, 0x7f, 0x7f};
+static unsigned char helvetica24_171_bits[] = {
+0x98, 0x01, 0xcc, 0x00, 0x66, 0x00, 0x33, 0x00, 0x33, 0x00, 0x66, 0x00, 
+0xcc, 0x00, 0x98, 0x01};
+static unsigned char helvetica24_172_bits[] = {
+0xff, 0x1f, 0xff, 0x1f, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 
+0x00, 0x18, 0x00, 0x18};
+static unsigned char helvetica24_173_bits[] = {
+0x3f, 0x3f};
+static unsigned char helvetica24_174_bits[] = {
+0xe0, 0x0f, 0x00, 0x38, 0x38, 0x00, 0x0c, 0x60, 0x00, 0x06, 0xc0, 0x00, 
+0xc2, 0x87, 0x00, 0x43, 0x88, 0x01, 0x41, 0x08, 0x01, 0x41, 0x08, 0x01, 
+0xc1, 0x07, 0x01, 0x41, 0x02, 0x01, 0x41, 0x04, 0x01, 0x43, 0x84, 0x01, 
+0x42, 0x88, 0x00, 0x06, 0xc0, 0x00, 0x0c, 0x60, 0x00, 0x38, 0x38, 0x00, 
+0xe0, 0x0f, 0x00};
+static unsigned char helvetica24_175_bits[] = {
+0x3f, 0x3f};
+static unsigned char helvetica24_176_bits[] = {
+0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0x66, 0x3c};
+static unsigned char helvetica24_177_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xff, 0x0f, 0xff, 0x0f, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0xff, 0x0f, 
+0xff, 0x0f};
+static unsigned char helvetica24_178_bits[] = {
+0x3c, 0x7e, 0x63, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x7f, 0x7f};
+static unsigned char helvetica24_179_bits[] = {
+0x3e, 0x7f, 0x63, 0x60, 0x3c, 0x3c, 0x60, 0x63, 0x7f, 0x3e};
+static unsigned char helvetica24_180_bits[] = {
+0x18, 0x0c, 0x06, 0x03};
+static unsigned char helvetica24_181_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc7, 0x03, 
+0x7f, 0x03, 0x3b, 0x03, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00};
+static unsigned char helvetica24_182_bits[] = {
+0xf8, 0x03, 0xfe, 0x03, 0x9e, 0x01, 0x9f, 0x01, 0x9f, 0x01, 0x9f, 0x01, 
+0x9f, 0x01, 0x9f, 0x01, 0x9f, 0x01, 0x9e, 0x01, 0x9e, 0x01, 0x9c, 0x01, 
+0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 
+0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01};
+static unsigned char helvetica24_183_bits[] = {
+0x03, 0x03, 0x03};
+static unsigned char helvetica24_184_bits[] = {
+0x06, 0x0e, 0x18, 0x18, 0x1f, 0x0e};
+static unsigned char helvetica24_185_bits[] = {
+0x0c, 0x0c, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
+static unsigned char helvetica24_186_bits[] = {
+0x1c, 0x36, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x1c, 0x00, 0x7f, 0x7f};
+static unsigned char helvetica24_187_bits[] = {
+0x33, 0x00, 0x66, 0x00, 0xcc, 0x00, 0x98, 0x01, 0x98, 0x01, 0xcc, 0x00, 
+0x66, 0x00, 0x33, 0x00};
+static unsigned char helvetica24_188_bits[] = {
+0x0c, 0x18, 0x00, 0x0c, 0x18, 0x00, 0x0f, 0x0c, 0x00, 0x0f, 0x0c, 0x00, 
+0x0c, 0x06, 0x00, 0x0c, 0x06, 0x00, 0x0c, 0x03, 0x00, 0x0c, 0x03, 0x00, 
+0x8c, 0xc1, 0x00, 0x8c, 0xe1, 0x00, 0xc0, 0xf0, 0x00, 0xc0, 0xf0, 0x00, 
+0x60, 0xd8, 0x00, 0x60, 0xcc, 0x00, 0x30, 0xfe, 0x03, 0x30, 0xfe, 0x03, 
+0x18, 0xc0, 0x00, 0x18, 0xc0, 0x00};
+static unsigned char helvetica24_189_bits[] = {
+0x0c, 0x18, 0x00, 0x0c, 0x18, 0x00, 0x0f, 0x0c, 0x00, 0x0f, 0x0c, 0x00, 
+0x0c, 0x06, 0x00, 0x0c, 0x06, 0x00, 0x0c, 0x03, 0x00, 0x0c, 0x03, 0x00, 
+0x8c, 0xe1, 0x01, 0x8c, 0xf1, 0x03, 0xc0, 0x18, 0x03, 0xc0, 0x00, 0x03, 
+0x60, 0x80, 0x01, 0x60, 0xc0, 0x00, 0x30, 0x60, 0x00, 0x30, 0x30, 0x00, 
+0x18, 0xf8, 0x03, 0x18, 0xf8, 0x03};
+static unsigned char helvetica24_190_bits[] = {
+0x3e, 0x30, 0x00, 0x7f, 0x30, 0x00, 0x63, 0x18, 0x00, 0x60, 0x18, 0x00, 
+0x3c, 0x0c, 0x00, 0x3c, 0x0c, 0x00, 0x60, 0x06, 0x00, 0x63, 0x06, 0x00, 
+0x7f, 0x83, 0x01, 0x3e, 0xc3, 0x01, 0x80, 0xe1, 0x01, 0x80, 0xe1, 0x01, 
+0xc0, 0xb0, 0x01, 0xc0, 0x98, 0x01, 0x60, 0xfc, 0x07, 0x60, 0xfc, 0x07, 
+0x30, 0x80, 0x01, 0x30, 0x80, 0x01};
+static unsigned char helvetica24_191_bits[] = {
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x0e, 0x00, 
+0x06, 0x00, 0x07, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc7, 0x01, 0xfe, 0x01, 
+0x7c, 0x00};
+static unsigned char helvetica24_192_bits[] = {
+0x30, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x80, 0x01, 0x00, 0x00, 0xc0, 0x01, 
+0xc0, 0x01, 0x60, 0x03, 0x60, 0x03, 0x30, 0x02, 0x30, 0x06, 0x30, 0x06, 
+0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x0c, 0x18, 0xfc, 0x1f, 0xfc, 0x1f, 
+0x06, 0x30, 0x06, 0x30, 0x06, 0x30, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60};
+static unsigned char helvetica24_193_bits[] = {
+0x00, 0x06, 0x00, 0x03, 0x80, 0x01, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x01, 
+0xc0, 0x01, 0x60, 0x03, 0x60, 0x03, 0x30, 0x02, 0x30, 0x06, 0x30, 0x06, 
+0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x0c, 0x18, 0xfc, 0x1f, 0xfc, 0x1f, 
+0x06, 0x30, 0x06, 0x30, 0x06, 0x30, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60};
+static unsigned char helvetica24_194_bits[] = {
+0x80, 0x01, 0xc0, 0x03, 0x60, 0x06, 0x30, 0x0c, 0x00, 0x00, 0xc0, 0x01, 
+0xc0, 0x01, 0x60, 0x03, 0x60, 0x03, 0x30, 0x02, 0x30, 0x06, 0x30, 0x06, 
+0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x0c, 0x18, 0xfc, 0x1f, 0xfc, 0x1f, 
+0x06, 0x30, 0x06, 0x30, 0x06, 0x30, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60};
+static unsigned char helvetica24_195_bits[] = {
+0xe0, 0x08, 0xb0, 0x0d, 0x10, 0x07, 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x01, 
+0x60, 0x03, 0x60, 0x03, 0x30, 0x02, 0x30, 0x06, 0x30, 0x06, 0x18, 0x0c, 
+0x18, 0x0c, 0x18, 0x0c, 0x0c, 0x18, 0xfc, 0x1f, 0xfc, 0x1f, 0x06, 0x30, 
+0x06, 0x30, 0x06, 0x30, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60};
+static unsigned char helvetica24_196_bits[] = {
+0x30, 0x06, 0x30, 0x06, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x01, 
+0x60, 0x03, 0x60, 0x03, 0x30, 0x02, 0x30, 0x06, 0x30, 0x06, 0x18, 0x0c, 
+0x18, 0x0c, 0x18, 0x0c, 0x0c, 0x18, 0xfc, 0x1f, 0xfc, 0x1f, 0x06, 0x30, 
+0x06, 0x30, 0x06, 0x30, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60};
+static unsigned char helvetica24_197_bits[] = {
+0xc0, 0x01, 0x60, 0x03, 0x60, 0x03, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 
+0xc0, 0x01, 0x60, 0x03, 0x60, 0x03, 0x30, 0x02, 0x30, 0x06, 0x30, 0x06, 
+0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x0c, 0x18, 0xfc, 0x1f, 0xfc, 0x1f, 
+0x06, 0x30, 0x06, 0x30, 0x06, 0x30, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60};
+static unsigned char helvetica24_198_bits[] = {
+0xc0, 0xff, 0x1f, 0xc0, 0xff, 0x1f, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 
+0x30, 0x06, 0x00, 0x30, 0x06, 0x00, 0x30, 0x06, 0x00, 0x18, 0x06, 0x00, 
+0x18, 0xfe, 0x1f, 0x18, 0xfe, 0x1f, 0x0c, 0x06, 0x00, 0xfc, 0x07, 0x00, 
+0xfc, 0x07, 0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x00, 
+0x03, 0x06, 0x00, 0x03, 0xfe, 0x1f, 0x03, 0xfe, 0x1f};
+static unsigned char helvetica24_199_bits[] = {
+0xe0, 0x07, 0xf8, 0x1f, 0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0x60, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0xc0, 0x07, 0xc0, 0x06, 0x60, 0x0e, 0x70, 0x3c, 0x3c, 0xf8, 0x1f, 
+0xe0, 0x07, 0xc0, 0x01, 0x00, 0x03, 0x00, 0x03, 0xe0, 0x03, 0xc0, 0x01};
+static unsigned char helvetica24_200_bits[] = {
+0x0c, 0x00, 0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0x00, 0x00, 0xff, 0x0f, 
+0xff, 0x0f, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0xff, 0x07, 0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x0f, 0xff, 0x0f};
+static unsigned char helvetica24_201_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0xff, 0x0f, 
+0xff, 0x0f, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0xff, 0x07, 0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x0f, 0xff, 0x0f};
+static unsigned char helvetica24_202_bits[] = {
+0x60, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x0c, 0x03, 0x00, 0x00, 0xff, 0x0f, 
+0xff, 0x0f, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0xff, 0x07, 0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x0f, 0xff, 0x0f};
+static unsigned char helvetica24_203_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0xff, 0x0f, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0xff, 0x07, 0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x0f, 0xff, 0x0f};
+static unsigned char helvetica24_204_bits[] = {
+0x03, 0x06, 0x0c, 0x18, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
+static unsigned char helvetica24_205_bits[] = {
+0x18, 0x0c, 0x06, 0x03, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06};
+static unsigned char helvetica24_206_bits[] = {
+0x18, 0x3c, 0x66, 0xc3, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18};
+static unsigned char helvetica24_207_bits[] = {
+0x33, 0x33, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
+static unsigned char helvetica24_208_bits[] = {
+0xfc, 0x0f, 0x00, 0xfc, 0x3f, 0x00, 0x0c, 0x78, 0x00, 0x0c, 0xe0, 0x00, 
+0x0c, 0xc0, 0x00, 0x0c, 0xc0, 0x01, 0x0c, 0x80, 0x01, 0x0c, 0x80, 0x01, 
+0xff, 0x80, 0x01, 0xff, 0x80, 0x01, 0x0c, 0x80, 0x01, 0x0c, 0x80, 0x01, 
+0x0c, 0x80, 0x01, 0x0c, 0xc0, 0x01, 0x0c, 0xc0, 0x00, 0x0c, 0xe0, 0x00, 
+0x0c, 0x78, 0x00, 0xfc, 0x3f, 0x00, 0xfc, 0x0f, 0x00};
+static unsigned char helvetica24_209_bits[] = {
+0xe0, 0x08, 0xb0, 0x0d, 0x10, 0x07, 0x00, 0x00, 0x07, 0x30, 0x0f, 0x30, 
+0x0f, 0x30, 0x1b, 0x30, 0x3b, 0x30, 0x33, 0x30, 0x73, 0x30, 0x63, 0x30, 
+0xe3, 0x30, 0xc3, 0x30, 0xc3, 0x31, 0x83, 0x31, 0x83, 0x33, 0x03, 0x33, 
+0x03, 0x37, 0x03, 0x36, 0x03, 0x3c, 0x03, 0x3c, 0x03, 0x38};
+static unsigned char helvetica24_210_bits[] = {
+0x60, 0x00, 0xc0, 0x00, 0x80, 0x01, 0x00, 0x03, 0x00, 0x00, 0xe0, 0x07, 
+0xf8, 0x1f, 0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0xe0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x07, 0xe0, 0x06, 0x60, 0x0e, 0x70, 0x3c, 0x3c, 0xf8, 0x1f, 0xe0, 0x07};
+static unsigned char helvetica24_211_bits[] = {
+0x00, 0x0c, 0x00, 0x06, 0x00, 0x03, 0x80, 0x01, 0x00, 0x00, 0xe0, 0x07, 
+0xf8, 0x1f, 0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0xe0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x07, 0xe0, 0x06, 0x60, 0x0e, 0x70, 0x3c, 0x3c, 0xf8, 0x1f, 0xe0, 0x07};
+static unsigned char helvetica24_212_bits[] = {
+0x80, 0x01, 0xc0, 0x03, 0x60, 0x06, 0x30, 0x0c, 0x00, 0x00, 0xe0, 0x07, 
+0xf8, 0x1f, 0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0xe0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x07, 0xe0, 0x06, 0x60, 0x0e, 0x70, 0x3c, 0x3c, 0xf8, 0x1f, 0xe0, 0x07};
+static unsigned char helvetica24_213_bits[] = {
+0xe0, 0x08, 0xb0, 0x0d, 0x10, 0x07, 0x00, 0x00, 0xe0, 0x07, 0xf8, 0x1f, 
+0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0xe0, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x07, 0xe0, 
+0x06, 0x60, 0x0e, 0x70, 0x3c, 0x3c, 0xf8, 0x1f, 0xe0, 0x07};
+static unsigned char helvetica24_214_bits[] = {
+0x60, 0x06, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xf8, 0x1f, 
+0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0xe0, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x07, 0xe0, 
+0x06, 0x60, 0x0e, 0x70, 0x3c, 0x3c, 0xf8, 0x1f, 0xe0, 0x07};
+static unsigned char helvetica24_215_bits[] = {
+0x03, 0x18, 0x06, 0x0c, 0x0c, 0x06, 0x18, 0x03, 0xb0, 0x01, 0xe0, 0x00, 
+0xe0, 0x00, 0xb0, 0x01, 0x18, 0x03, 0x0c, 0x06, 0x06, 0x0c, 0x03, 0x18};
+static unsigned char helvetica24_216_bits[] = {
+0xc0, 0x0f, 0x02, 0xf0, 0x3f, 0x03, 0x78, 0xf8, 0x01, 0x1c, 0xe0, 0x00, 
+0x0c, 0xe0, 0x00, 0x0e, 0xb0, 0x01, 0x06, 0x98, 0x01, 0x06, 0x8c, 0x01, 
+0x06, 0x86, 0x01, 0x06, 0x83, 0x01, 0x86, 0x81, 0x01, 0xc6, 0x80, 0x01, 
+0x66, 0x80, 0x01, 0x36, 0xc0, 0x01, 0x1c, 0xc0, 0x00, 0x1c, 0xe0, 0x00, 
+0x7e, 0x78, 0x00, 0xf3, 0x3f, 0x00, 0xc1, 0x0f, 0x00};
+static unsigned char helvetica24_217_bits[] = {
+0x30, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x80, 0x01, 0x00, 0x00, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x06, 0x18, 0x0e, 0x1c, 0xfc, 0x0f, 0xf0, 0x03};
+static unsigned char helvetica24_218_bits[] = {
+0x00, 0x06, 0x00, 0x03, 0x80, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x06, 0x18, 0x0e, 0x1c, 0xfc, 0x0f, 0xf0, 0x03};
+static unsigned char helvetica24_219_bits[] = {
+0xc0, 0x00, 0xe0, 0x01, 0x30, 0x03, 0x18, 0x06, 0x00, 0x00, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x06, 0x18, 0x0e, 0x1c, 0xfc, 0x0f, 0xf0, 0x03};
+static unsigned char helvetica24_220_bits[] = {
+0x30, 0x03, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x06, 0x18, 0x0e, 0x1c, 0xfc, 0x0f, 0xf0, 0x03};
+static unsigned char helvetica24_221_bits[] = {
+0x00, 0x06, 0x00, 0x03, 0x80, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x03, 0x30, 
+0x07, 0x38, 0x06, 0x18, 0x0e, 0x1c, 0x0c, 0x0c, 0x1c, 0x0e, 0x18, 0x06, 
+0x38, 0x07, 0x30, 0x03, 0xf0, 0x03, 0xe0, 0x01, 0xe0, 0x01, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00};
+static unsigned char helvetica24_222_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x07, 0xff, 0x0f, 
+0x03, 0x0c, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x0c, 
+0xff, 0x0f, 0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00};
+static unsigned char helvetica24_223_bits[] = {
+0x38, 0x00, 0xfe, 0x00, 0xc7, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 
+0xc3, 0x00, 0xe3, 0x00, 0x73, 0x00, 0xf3, 0x00, 0xc3, 0x01, 0x83, 0x01, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x01, 0xc3, 0x01, 0xf3, 0x00, 
+0x73, 0x00};
+static unsigned char helvetica24_224_bits[] = {
+0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xf8, 0x00, 
+0xfc, 0x01, 0x86, 0x03, 0x06, 0x03, 0x00, 0x03, 0xe0, 0x03, 0xfc, 0x03, 
+0x1e, 0x03, 0x07, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc7, 0x03, 0x7e, 0x07, 
+0x3c, 0x06};
+static unsigned char helvetica24_225_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 
+0xfc, 0x01, 0x86, 0x03, 0x06, 0x03, 0x00, 0x03, 0xe0, 0x03, 0xfc, 0x03, 
+0x1e, 0x03, 0x07, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc7, 0x03, 0x7e, 0x07, 
+0x3c, 0x06};
+static unsigned char helvetica24_226_bits[] = {
+0x60, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x0c, 0x03, 0x00, 0x00, 0xf8, 0x00, 
+0xfc, 0x01, 0x86, 0x03, 0x06, 0x03, 0x00, 0x03, 0xe0, 0x03, 0xfc, 0x03, 
+0x1e, 0x03, 0x07, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc7, 0x03, 0x7e, 0x07, 
+0x3c, 0x06};
+static unsigned char helvetica24_227_bits[] = {
+0x38, 0x02, 0x6c, 0x03, 0xc4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 
+0xfc, 0x01, 0x86, 0x03, 0x06, 0x03, 0x00, 0x03, 0xe0, 0x03, 0xfc, 0x03, 
+0x1e, 0x03, 0x07, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc7, 0x03, 0x7e, 0x07, 
+0x3c, 0x06};
+static unsigned char helvetica24_228_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xfc, 0x01, 
+0x86, 0x03, 0x06, 0x03, 0x00, 0x03, 0xe0, 0x03, 0xfc, 0x03, 0x1e, 0x03, 
+0x07, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc7, 0x03, 0x7e, 0x07, 0x3c, 0x06};
+static unsigned char helvetica24_229_bits[] = {
+0x70, 0x00, 0xd8, 0x00, 0x88, 0x00, 0xd8, 0x00, 0x70, 0x00, 0xf8, 0x00, 
+0xfc, 0x01, 0x86, 0x03, 0x06, 0x03, 0x00, 0x03, 0xe0, 0x03, 0xfc, 0x03, 
+0x1e, 0x03, 0x07, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc7, 0x03, 0x7e, 0x07, 
+0x3c, 0x06};
+static unsigned char helvetica24_230_bits[] = {
+0xf8, 0x70, 0x00, 0xfc, 0xfd, 0x01, 0x86, 0x8f, 0x03, 0x06, 0x07, 0x03, 
+0x00, 0x03, 0x06, 0xe0, 0x03, 0x06, 0xfc, 0xff, 0x07, 0x1e, 0xff, 0x07, 
+0x07, 0x03, 0x00, 0x03, 0x03, 0x00, 0x83, 0x07, 0x06, 0xc7, 0x0f, 0x07, 
+0x7e, 0xfc, 0x03, 0x3c, 0xf0, 0x00};
+static unsigned char helvetica24_231_bits[] = {
+0xf8, 0x00, 0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x03, 0x8e, 0x03, 
+0xfc, 0x01, 0xf8, 0x00, 0x38, 0x00, 0x60, 0x00, 0x60, 0x00, 0x7c, 0x00, 
+0x38, 0x00};
+static unsigned char helvetica24_232_bits[] = {
+0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x70, 0x00, 
+0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0xff, 0x07, 
+0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x06, 0x06, 0x0e, 0x07, 0xfc, 0x03, 
+0xf0, 0x00};
+static unsigned char helvetica24_233_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 
+0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0xff, 0x07, 
+0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x06, 0x06, 0x0e, 0x07, 0xfc, 0x03, 
+0xf0, 0x00};
+static unsigned char helvetica24_234_bits[] = {
+0x60, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x0c, 0x03, 0x00, 0x00, 0x70, 0x00, 
+0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0xff, 0x07, 
+0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x06, 0x06, 0x0e, 0x07, 0xfc, 0x03, 
+0xf0, 0x00};
+static unsigned char helvetica24_235_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0xfc, 0x01, 
+0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0xff, 0x07, 0xff, 0x07, 
+0x03, 0x00, 0x03, 0x00, 0x06, 0x06, 0x0e, 0x07, 0xfc, 0x03, 0xf0, 0x00};
+static unsigned char helvetica24_236_bits[] = {
+0x03, 0x06, 0x0c, 0x18, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
+static unsigned char helvetica24_237_bits[] = {
+0x18, 0x0c, 0x06, 0x03, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06};
+static unsigned char helvetica24_238_bits[] = {
+0x18, 0x3c, 0x66, 0xc3, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18};
+static unsigned char helvetica24_239_bits[] = {
+0x33, 0x33, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
+static unsigned char helvetica24_240_bits[] = {
+0x07, 0x00, 0x8e, 0x01, 0x78, 0x00, 0x3c, 0x00, 0x63, 0x00, 0xf8, 0x00, 
+0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0x8e, 0x03, 0xfc, 0x01, 
+0xf8, 0x00};
+static unsigned char helvetica24_241_bits[] = {
+0x1c, 0x01, 0xb6, 0x01, 0xe2, 0x00, 0x00, 0x00, 0x73, 0x00, 0xfb, 0x01, 
+0x8f, 0x01, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_242_bits[] = {
+0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xf8, 0x00, 
+0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0x8e, 0x03, 0xfc, 0x01, 
+0xf8, 0x00};
+static unsigned char helvetica24_243_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 
+0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0x8e, 0x03, 0xfc, 0x01, 
+0xf8, 0x00};
+static unsigned char helvetica24_244_bits[] = {
+0x60, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x0c, 0x03, 0x00, 0x00, 0xf8, 0x00, 
+0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0x8e, 0x03, 0xfc, 0x01, 
+0xf8, 0x00};
+static unsigned char helvetica24_245_bits[] = {
+0x38, 0x02, 0x6c, 0x03, 0xc4, 0x01, 0x00, 0x00, 0xf8, 0x00, 0xfc, 0x01, 
+0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0x8e, 0x03, 0xfc, 0x01, 0xf8, 0x00};
+static unsigned char helvetica24_246_bits[] = {
+0x8c, 0x01, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xfc, 0x01, 
+0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0x8e, 0x03, 0xfc, 0x01, 0xf8, 0x00};
+static unsigned char helvetica24_247_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 
+0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char helvetica24_248_bits[] = {
+0xf0, 0x19, 0xf8, 0x0f, 0x1c, 0x07, 0x0c, 0x06, 0x06, 0x0f, 0x86, 0x0d, 
+0xc6, 0x0c, 0x66, 0x0c, 0x66, 0x0c, 0x36, 0x0c, 0x1c, 0x06, 0x0c, 0x07, 
+0xfe, 0x03, 0xf3, 0x01};
+static unsigned char helvetica24_249_bits[] = {
+0x0c, 0x00, 0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc6, 0x03, 0x7e, 0x03, 
+0x38, 0x03};
+static unsigned char helvetica24_250_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc6, 0x03, 0x7e, 0x03, 
+0x38, 0x03};
+static unsigned char helvetica24_251_bits[] = {
+0x30, 0x00, 0x78, 0x00, 0xcc, 0x00, 0x86, 0x01, 0x00, 0x00, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc6, 0x03, 0x7e, 0x03, 
+0x38, 0x03};
+static unsigned char helvetica24_252_bits[] = {
+0xcc, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc6, 0x03, 0x7e, 0x03, 0x38, 0x03};
+static unsigned char helvetica24_253_bits[] = {
+0x00, 0x03, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x0c, 
+0x03, 0x0c, 0x06, 0x0c, 0x0e, 0x06, 0x0c, 0x06, 0x1c, 0x07, 0x18, 0x03, 
+0x18, 0x03, 0xb0, 0x01, 0xb0, 0x01, 0xe0, 0x01, 0xe0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x3c, 0x00, 0x1c, 0x00};
+static unsigned char helvetica24_254_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xf3, 0x00, 
+0xfb, 0x01, 0x8f, 0x03, 0x07, 0x03, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x07, 0x03, 0x8f, 0x03, 0xfb, 0x01, 
+0xf3, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00};
+static unsigned char helvetica24_255_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0c, 0x03, 0x0c, 
+0x06, 0x0c, 0x0e, 0x06, 0x0c, 0x06, 0x1c, 0x07, 0x18, 0x03, 0x18, 0x03, 
+0xb0, 0x01, 0xb0, 0x01, 0xe0, 0x01, 0xe0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x3c, 0x00, 0x1c, 0x00};
+static RotFont helvetica24font[] = {
+{5, 1, 1, helvetica24_0_bits},
+{5, 1, 1, helvetica24_1_bits},
+{5, 1, 1, helvetica24_2_bits},
+{5, 1, 1, helvetica24_3_bits},
+{5, 1, 1, helvetica24_4_bits},
+{5, 1, 1, helvetica24_5_bits},
+{5, 1, 1, helvetica24_6_bits},
+{5, 1, 1, helvetica24_7_bits},
+{5, 1, 1, helvetica24_8_bits},
+{5, 1, 1, helvetica24_9_bits},
+{5, 1, 1, helvetica24_10_bits},
+{5, 1, 1, helvetica24_11_bits},
+{5, 1, 1, helvetica24_12_bits},
+{5, 1, 1, helvetica24_13_bits},
+{5, 1, 1, helvetica24_14_bits},
+{5, 1, 1, helvetica24_15_bits},
+{5, 1, 1, helvetica24_16_bits},
+{5, 1, 1, helvetica24_17_bits},
+{5, 1, 1, helvetica24_18_bits},
+{5, 1, 1, helvetica24_19_bits},
+{5, 1, 1, helvetica24_20_bits},
+{5, 1, 1, helvetica24_21_bits},
+{5, 1, 1, helvetica24_22_bits},
+{5, 1, 1, helvetica24_23_bits},
+{5, 1, 1, helvetica24_24_bits},
+{5, 1, 1, helvetica24_25_bits},
+{5, 1, 1, helvetica24_26_bits},
+{5, 1, 1, helvetica24_27_bits},
+{5, 1, 1, helvetica24_28_bits},
+{5, 1, 1, helvetica24_29_bits},
+{5, 1, 1, helvetica24_30_bits},
+{5, 1, 1, helvetica24_31_bits},
+{10, 1, 1, helvetica24_32_bits},
+{2, 19, 19, helvetica24_33_bits},
+{6, 6, 19, helvetica24_34_bits},
+{11, 17, 17, helvetica24_35_bits},
+{11, 21, 19, helvetica24_36_bits},
+{19, 18, 18, helvetica24_37_bits},
+{14, 18, 18, helvetica24_38_bits},
+{2, 6, 19, helvetica24_39_bits},
+{5, 24, 19, helvetica24_40_bits},
+{5, 24, 19, helvetica24_41_bits},
+{7, 7, 19, helvetica24_42_bits},
+{12, 12, 13, helvetica24_43_bits},
+{2, 6, 3, helvetica24_44_bits},
+{11, 2, 8, helvetica24_45_bits},
+{2, 3, 3, helvetica24_46_bits},
+{7, 19, 19, helvetica24_47_bits},
+{11, 18, 18, helvetica24_48_bits},
+{6, 18, 18, helvetica24_49_bits},
+{11, 18, 18, helvetica24_50_bits},
+{11, 18, 18, helvetica24_51_bits},
+{11, 18, 18, helvetica24_52_bits},
+{11, 18, 18, helvetica24_53_bits},
+{11, 18, 18, helvetica24_54_bits},
+{11, 18, 18, helvetica24_55_bits},
+{11, 18, 18, helvetica24_56_bits},
+{11, 18, 18, helvetica24_57_bits},
+{2, 14, 14, helvetica24_58_bits},
+{2, 17, 14, helvetica24_59_bits},
+{12, 12, 13, helvetica24_60_bits},
+{10, 6, 11, helvetica24_61_bits},
+{12, 12, 13, helvetica24_62_bits},
+{10, 19, 19, helvetica24_63_bits},
+{22, 23, 19, helvetica24_64_bits},
+{15, 19, 19, helvetica24_65_bits},
+{14, 19, 19, helvetica24_66_bits},
+{16, 19, 19, helvetica24_67_bits},
+{15, 19, 19, helvetica24_68_bits},
+{12, 19, 19, helvetica24_69_bits},
+{11, 19, 19, helvetica24_70_bits},
+{16, 19, 19, helvetica24_71_bits},
+{14, 19, 19, helvetica24_72_bits},
+{2, 19, 19, helvetica24_73_bits},
+{10, 19, 19, helvetica24_74_bits},
+{15, 19, 19, helvetica24_75_bits},
+{11, 19, 19, helvetica24_76_bits},
+{17, 19, 19, helvetica24_77_bits},
+{14, 19, 19, helvetica24_78_bits},
+{16, 19, 19, helvetica24_79_bits},
+{13, 19, 19, helvetica24_80_bits},
+{16, 19, 19, helvetica24_81_bits},
+{13, 19, 19, helvetica24_82_bits},
+{14, 19, 19, helvetica24_83_bits},
+{14, 19, 19, helvetica24_84_bits},
+{14, 19, 19, helvetica24_85_bits},
+{15, 19, 19, helvetica24_86_bits},
+{20, 19, 19, helvetica24_87_bits},
+{15, 19, 19, helvetica24_88_bits},
+{14, 19, 19, helvetica24_89_bits},
+{13, 19, 19, helvetica24_90_bits},
+{4, 24, 19, helvetica24_91_bits},
+{7, 19, 19, helvetica24_92_bits},
+{4, 24, 19, helvetica24_93_bits},
+{10, 9, 19, helvetica24_94_bits},
+{14, 2, -3, helvetica24_95_bits},
+{2, 6, 19, helvetica24_96_bits},
+{11, 14, 14, helvetica24_97_bits},
+{11, 19, 19, helvetica24_98_bits},
+{10, 14, 14, helvetica24_99_bits},
+{11, 19, 19, helvetica24_100_bits},
+{11, 14, 14, helvetica24_101_bits},
+{6, 19, 19, helvetica24_102_bits},
+{11, 19, 14, helvetica24_103_bits},
+{10, 19, 19, helvetica24_104_bits},
+{2, 19, 19, helvetica24_105_bits},
+{4, 24, 19, helvetica24_106_bits},
+{10, 19, 19, helvetica24_107_bits},
+{2, 19, 19, helvetica24_108_bits},
+{16, 14, 14, helvetica24_109_bits},
+{10, 14, 14, helvetica24_110_bits},
+{11, 14, 14, helvetica24_111_bits},
+{11, 19, 14, helvetica24_112_bits},
+{11, 19, 14, helvetica24_113_bits},
+{6, 14, 14, helvetica24_114_bits},
+{10, 14, 14, helvetica24_115_bits},
+{6, 18, 18, helvetica24_116_bits},
+{10, 14, 14, helvetica24_117_bits},
+{11, 14, 14, helvetica24_118_bits},
+{18, 14, 14, helvetica24_119_bits},
+{10, 14, 14, helvetica24_120_bits},
+{12, 19, 14, helvetica24_121_bits},
+{10, 14, 14, helvetica24_122_bits},
+{6, 24, 19, helvetica24_123_bits},
+{2, 24, 19, helvetica24_124_bits},
+{6, 24, 19, helvetica24_125_bits},
+{10, 4, 9, helvetica24_126_bits},
+{5, 1, 1, helvetica24_127_bits},
+{5, 1, 1, helvetica24_128_bits},
+{5, 1, 1, helvetica24_129_bits},
+{5, 1, 1, helvetica24_130_bits},
+{5, 1, 1, helvetica24_131_bits},
+{5, 1, 1, helvetica24_132_bits},
+{5, 1, 1, helvetica24_133_bits},
+{5, 1, 1, helvetica24_134_bits},
+{5, 1, 1, helvetica24_135_bits},
+{5, 1, 1, helvetica24_136_bits},
+{5, 1, 1, helvetica24_137_bits},
+{5, 1, 1, helvetica24_138_bits},
+{5, 1, 1, helvetica24_139_bits},
+{5, 1, 1, helvetica24_140_bits},
+{5, 1, 1, helvetica24_141_bits},
+{5, 1, 1, helvetica24_142_bits},
+{5, 1, 1, helvetica24_143_bits},
+{5, 1, 1, helvetica24_144_bits},
+{5, 1, 1, helvetica24_145_bits},
+{5, 1, 1, helvetica24_146_bits},
+{5, 1, 1, helvetica24_147_bits},
+{5, 1, 1, helvetica24_148_bits},
+{5, 1, 1, helvetica24_149_bits},
+{5, 1, 1, helvetica24_150_bits},
+{5, 1, 1, helvetica24_151_bits},
+{5, 1, 1, helvetica24_152_bits},
+{5, 1, 1, helvetica24_153_bits},
+{5, 1, 1, helvetica24_154_bits},
+{5, 1, 1, helvetica24_155_bits},
+{5, 1, 1, helvetica24_156_bits},
+{5, 1, 1, helvetica24_157_bits},
+{5, 1, 1, helvetica24_158_bits},
+{5, 1, 1, helvetica24_159_bits},
+{1, 1, 1, helvetica24_160_bits},
+{2, 19, 14, helvetica24_161_bits},
+{10, 18, 16, helvetica24_162_bits},
+{12, 18, 18, helvetica24_163_bits},
+{11, 12, 15, helvetica24_164_bits},
+{14, 18, 18, helvetica24_165_bits},
+{2, 23, 19, helvetica24_166_bits},
+{11, 24, 19, helvetica24_167_bits},
+{6, 2, 18, helvetica24_168_bits},
+{17, 17, 17, helvetica24_169_bits},
+{7, 12, 19, helvetica24_170_bits},
+{9, 8, 11, helvetica24_171_bits},
+{13, 8, 11, helvetica24_172_bits},
+{6, 2, 8, helvetica24_173_bits},
+{17, 17, 17, helvetica24_174_bits},
+{6, 2, 18, helvetica24_175_bits},
+{8, 7, 18, helvetica24_176_bits},
+{12, 13, 13, helvetica24_177_bits},
+{7, 10, 18, helvetica24_178_bits},
+{7, 10, 18, helvetica24_179_bits},
+{5, 4, 19, helvetica24_180_bits},
+{10, 19, 14, helvetica24_181_bits},
+{10, 23, 19, helvetica24_182_bits},
+{2, 3, 9, helvetica24_183_bits},
+{5, 6, 1, helvetica24_184_bits},
+{4, 10, 18, helvetica24_185_bits},
+{7, 12, 19, helvetica24_186_bits},
+{9, 8, 11, helvetica24_187_bits},
+{18, 18, 18, helvetica24_188_bits},
+{18, 18, 18, helvetica24_189_bits},
+{19, 18, 18, helvetica24_190_bits},
+{10, 19, 14, helvetica24_191_bits},
+{15, 24, 24, helvetica24_192_bits},
+{15, 24, 24, helvetica24_193_bits},
+{15, 24, 24, helvetica24_194_bits},
+{15, 23, 23, helvetica24_195_bits},
+{15, 23, 23, helvetica24_196_bits},
+{15, 24, 24, helvetica24_197_bits},
+{21, 19, 19, helvetica24_198_bits},
+{16, 24, 19, helvetica24_199_bits},
+{12, 24, 24, helvetica24_200_bits},
+{12, 24, 24, helvetica24_201_bits},
+{12, 24, 24, helvetica24_202_bits},
+{12, 23, 23, helvetica24_203_bits},
+{5, 24, 24, helvetica24_204_bits},
+{5, 24, 24, helvetica24_205_bits},
+{8, 24, 24, helvetica24_206_bits},
+{6, 23, 23, helvetica24_207_bits},
+{17, 19, 19, helvetica24_208_bits},
+{14, 23, 23, helvetica24_209_bits},
+{16, 24, 24, helvetica24_210_bits},
+{16, 24, 24, helvetica24_211_bits},
+{16, 24, 24, helvetica24_212_bits},
+{16, 23, 23, helvetica24_213_bits},
+{16, 23, 23, helvetica24_214_bits},
+{13, 12, 13, helvetica24_215_bits},
+{18, 19, 19, helvetica24_216_bits},
+{14, 24, 24, helvetica24_217_bits},
+{14, 24, 24, helvetica24_218_bits},
+{14, 24, 24, helvetica24_219_bits},
+{14, 23, 23, helvetica24_220_bits},
+{14, 24, 24, helvetica24_221_bits},
+{13, 19, 19, helvetica24_222_bits},
+{10, 19, 19, helvetica24_223_bits},
+{11, 19, 19, helvetica24_224_bits},
+{11, 19, 19, helvetica24_225_bits},
+{11, 19, 19, helvetica24_226_bits},
+{11, 19, 19, helvetica24_227_bits},
+{11, 18, 18, helvetica24_228_bits},
+{11, 19, 19, helvetica24_229_bits},
+{19, 14, 14, helvetica24_230_bits},
+{10, 19, 14, helvetica24_231_bits},
+{11, 19, 19, helvetica24_232_bits},
+{11, 19, 19, helvetica24_233_bits},
+{11, 19, 19, helvetica24_234_bits},
+{11, 18, 18, helvetica24_235_bits},
+{5, 19, 19, helvetica24_236_bits},
+{5, 19, 19, helvetica24_237_bits},
+{8, 19, 19, helvetica24_238_bits},
+{6, 18, 18, helvetica24_239_bits},
+{11, 19, 19, helvetica24_240_bits},
+{10, 18, 18, helvetica24_241_bits},
+{11, 19, 19, helvetica24_242_bits},
+{11, 19, 19, helvetica24_243_bits},
+{11, 19, 19, helvetica24_244_bits},
+{11, 18, 18, helvetica24_245_bits},
+{11, 18, 18, helvetica24_246_bits},
+{12, 12, 13, helvetica24_247_bits},
+{13, 14, 14, helvetica24_248_bits},
+{10, 19, 19, helvetica24_249_bits},
+{10, 19, 19, helvetica24_250_bits},
+{10, 19, 19, helvetica24_251_bits},
+{10, 18, 18, helvetica24_252_bits},
+{12, 24, 19, helvetica24_253_bits},
+{11, 24, 19, helvetica24_254_bits},
+{12, 23, 18, helvetica24_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/helvetica8.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/helvetica8.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/helvetica8.bdf	(revision 12606)
@@ -0,0 +1,2572 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Helvetica-Medium-R-Normal--8-80-75-75-P-46-ISO8859-1
+SIZE 8 75 75
+FONTBOUNDINGBOX 9 11 0 -2
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Helvetica"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 8
+POINT_SIZE 80
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 46
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 6
+X_HEIGHT 5
+FACE_NAME "Helvetica"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.  "
+_DEC_DEVICE_FONTNAMES "PS=Helvetica"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2-1, 04-Dec-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Helvetica"
+FONT "-Adobe-Helvetica-Medium-R-Normal--8-80-75-75-P-46-ISO8859-1"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 5
+DEFAULT_CHAR 32
+FONT_ASCENT 8
+FONT_DESCENT 2
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 6 1 0
+BITMAP
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 3 1 3
+BITMAP
+a0
+a0
+a0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+BITMAP
+50
+f8
+50
+f8
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 1 -1
+BITMAP
+20
+70
+80
+60
+10
+e0
+40
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 6 6 1 0
+BITMAP
+e8
+a8
+d0
+2c
+54
+5c
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+40
+a0
+48
+a8
+b0
+58
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 3 1 3
+BITMAP
+80
+80
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 7 1 -1
+BITMAP
+40
+80
+80
+80
+80
+80
+40
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 7 1 -1
+BITMAP
+80
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 3 1 2
+BITMAP
+40
+e0
+40
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 1 0
+BITMAP
+20
+20
+f8
+20
+20
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 3 0 -2
+BITMAP
+40
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 1 2 2
+BITMAP
+f0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 1 0
+BITMAP
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 7 1 -1
+BITMAP
+40
+40
+40
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 0
+BITMAP
+60
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 6 2 0
+BITMAP
+40
+c0
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 0
+BITMAP
+60
+90
+10
+20
+40
+f0
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 6 2 0
+BITMAP
+c0
+20
+c0
+20
+20
+c0
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 0
+BITMAP
+20
+20
+60
+f0
+20
+20
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 6 2 0
+BITMAP
+e0
+80
+c0
+20
+20
+c0
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 0
+BITMAP
+70
+80
+e0
+90
+90
+60
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 0
+BITMAP
+f0
+10
+20
+40
+40
+40
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 0
+BITMAP
+60
+90
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 0
+BITMAP
+60
+90
+90
+70
+10
+60
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 4 1 0
+BITMAP
+80
+00
+00
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 6 0 -2
+BITMAP
+40
+00
+00
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+BITMAP
+20
+40
+80
+40
+20
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 3 1 1
+BITMAP
+e0
+00
+e0
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 2 0
+BITMAP
+80
+40
+20
+40
+80
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 2 0
+BITMAP
+c0
+20
+40
+00
+40
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 1080 0
+DWIDTH 9 0
+BBX 8 7 1 -1
+BITMAP
+3e
+41
+99
+a5
+9e
+80
+78
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+20
+20
+50
+70
+88
+88
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 2 0
+BITMAP
+e0
+90
+e0
+90
+90
+e0
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+70
+88
+80
+80
+88
+70
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+f0
+88
+88
+88
+88
+f0
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 2 0
+BITMAP
+f0
+80
+e0
+80
+80
+f0
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 2 0
+BITMAP
+f0
+80
+e0
+80
+80
+80
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+70
+80
+98
+88
+88
+70
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+88
+88
+f8
+88
+88
+88
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 6 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 1 0
+BITMAP
+20
+20
+20
+20
+a0
+40
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 2 0
+BITMAP
+90
+a0
+c0
+e0
+90
+90
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 6 2 0
+BITMAP
+80
+80
+80
+80
+80
+e0
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 5 6 2 0
+BITMAP
+88
+d8
+a8
+a8
+a8
+a8
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+88
+c8
+a8
+a8
+98
+88
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 2 0
+BITMAP
+e0
+90
+90
+e0
+80
+80
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 1 -2
+BITMAP
+70
+88
+88
+88
+88
+70
+20
+10
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 2 0
+BITMAP
+e0
+90
+90
+e0
+90
+90
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 2 0
+BITMAP
+70
+80
+e0
+10
+10
+e0
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 1 0
+BITMAP
+e0
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 2 0
+BITMAP
+90
+90
+90
+90
+a0
+40
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 7 6 1 0
+BITMAP
+92
+92
+92
+6c
+48
+48
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 2 0
+BITMAP
+90
+90
+60
+60
+90
+90
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+c8
+48
+48
+30
+20
+20
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 2 0
+BITMAP
+f0
+10
+20
+40
+80
+f0
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 7 1 -1
+BITMAP
+c0
+80
+80
+80
+80
+80
+c0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 7 0 -1
+BITMAP
+80
+80
+80
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 7 0 -1
+BITMAP
+c0
+40
+40
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 2
+BITMAP
+20
+50
+88
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 1 0 -1
+BITMAP
+f8
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 3 1 3
+BITMAP
+80
+80
+80
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 5 1 0
+BITMAP
+c0
+20
+e0
+a0
+d0
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 1 0
+BITMAP
+80
+80
+e0
+90
+90
+90
+e0
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 1 0
+BITMAP
+60
+80
+80
+80
+60
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 1 0
+BITMAP
+10
+10
+70
+90
+90
+90
+70
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 1 0
+BITMAP
+40
+a0
+e0
+80
+60
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 7 1 0
+BITMAP
+20
+40
+e0
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 -1
+BITMAP
+70
+90
+90
+70
+10
+60
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 1 0
+BITMAP
+80
+80
+e0
+90
+90
+90
+90
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 7 1 0
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 9 0 -2
+BITMAP
+40
+00
+40
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 1 0
+BITMAP
+80
+80
+a0
+c0
+c0
+a0
+a0
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 7 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 1 0
+BITMAP
+f0
+a8
+a8
+a8
+a8
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 1 0
+BITMAP
+e0
+90
+90
+90
+90
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 1 0
+BITMAP
+60
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 -1
+BITMAP
+e0
+90
+90
+90
+e0
+80
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 -1
+BITMAP
+70
+90
+90
+90
+70
+10
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 5 1 0
+BITMAP
+a0
+c0
+80
+80
+80
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 1 0
+BITMAP
+60
+80
+60
+20
+c0
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 7 1 0
+BITMAP
+40
+40
+e0
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 1 0
+BITMAP
+a0
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 1 0
+BITMAP
+90
+90
+90
+a0
+40
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 1 0
+BITMAP
+a8
+a8
+a8
+50
+50
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 1 0
+BITMAP
+90
+90
+60
+90
+90
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 6 1 -1
+BITMAP
+90
+90
+90
+60
+40
+80
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 1 0
+BITMAP
+e0
+20
+40
+80
+e0
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 7 0 -1
+BITMAP
+20
+40
+40
+c0
+40
+40
+20
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 7 1 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 7 0 -1
+BITMAP
+80
+40
+40
+60
+40
+40
+80
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 2 1 2
+BITMAP
+48
+b0
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 7 1 -2
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 7 1 -1
+BITMAP
+40
+40
+a0
+80
+a0
+40
+40
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 0
+BITMAP
+30
+40
+e0
+40
+40
+f0
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 5 5 0 0
+BITMAP
+88
+70
+50
+70
+88
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 1 0
+BITMAP
+88
+50
+f8
+20
+20
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 7 1 -1
+BITMAP
+80
+80
+80
+00
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 1 -2
+BITMAP
+70
+80
+60
+90
+60
+30
+10
+e0
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 4 1 0 5
+BITMAP
+90
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 6 7 1 -1
+BITMAP
+78
+84
+b4
+a4
+b4
+84
+78
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 5 0 1
+BITMAP
+c0
+20
+e0
+00
+e0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 3 1 1
+BITMAP
+50
+a0
+50
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 3 1 1
+BITMAP
+f0
+10
+10
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 1 0 2
+BITMAP
+c0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 6 7 1 -1
+BITMAP
+78
+84
+b4
+b4
+ac
+84
+78
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 1 0 5
+BITMAP
+e0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 3 1 3
+BITMAP
+40
+a0
+40
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 1 0
+BITMAP
+20
+f0
+20
+00
+f0
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 4 1 2
+BITMAP
+80
+40
+80
+c0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 4 0 2
+BITMAP
+e0
+60
+20
+c0
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 2 0 4
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 1 -2
+BITMAP
+a0
+a0
+a0
+e0
+80
+80
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 8 0 -2
+BITMAP
+78
+d0
+d0
+d0
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 2 1 1
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 2 0 -2
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 4 0 2
+BITMAP
+40
+c0
+40
+40
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 5 0 1
+BITMAP
+e0
+a0
+e0
+00
+e0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 3 1 1
+BITMAP
+a0
+50
+a0
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 7 7 0 -1
+BITMAP
+40
+c4
+48
+54
+2c
+5e
+04
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 7 7 0 -1
+BITMAP
+40
+c4
+48
+5c
+22
+44
+0e
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 7 7 0 -1
+BITMAP
+e0
+64
+28
+d4
+2c
+5e
+04
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 -1
+BITMAP
+20
+00
+20
+40
+90
+60
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+40
+20
+00
+20
+20
+50
+70
+88
+88
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+10
+20
+00
+20
+20
+50
+70
+88
+88
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+20
+50
+00
+20
+20
+50
+70
+88
+88
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+28
+50
+00
+20
+20
+50
+70
+88
+88
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 1 0
+BITMAP
+50
+00
+20
+20
+50
+70
+88
+88
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+20
+50
+20
+20
+20
+50
+70
+88
+88
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 7 6 1 0
+BITMAP
+3e
+30
+50
+7c
+90
+9e
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 1 -2
+BITMAP
+70
+88
+88
+80
+88
+70
+40
+80
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 9 2 0
+BITMAP
+40
+20
+00
+f0
+80
+e0
+80
+80
+f0
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 9 2 0
+BITMAP
+20
+40
+00
+f0
+80
+e0
+80
+80
+f0
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 9 2 0
+BITMAP
+40
+a0
+00
+f0
+80
+e0
+80
+80
+f0
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 8 2 0
+BITMAP
+a0
+00
+f0
+80
+e0
+80
+80
+f0
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 9 0 0
+BITMAP
+80
+40
+00
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 9 1 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 9 0 0
+BITMAP
+40
+a0
+00
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 8 0 0
+BITMAP
+a0
+00
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+70
+48
+e8
+48
+48
+70
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+28
+50
+00
+88
+c8
+a8
+a8
+98
+88
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+40
+20
+00
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+10
+20
+00
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+20
+50
+00
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+28
+50
+00
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 1 0
+BITMAP
+50
+00
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 1 0
+BITMAP
+90
+60
+60
+90
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 1 -1
+BITMAP
+08
+78
+88
+98
+a8
+c8
+f0
+80
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+40
+20
+00
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+10
+20
+00
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+20
+50
+00
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 1 0
+BITMAP
+50
+00
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+08
+10
+00
+c8
+48
+48
+30
+20
+20
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+80
+f0
+88
+88
+f0
+80
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 7 2 -1
+BITMAP
+60
+90
+a0
+90
+90
+a0
+80
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 8 1 0
+BITMAP
+80
+40
+00
+c0
+20
+e0
+a0
+d0
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 8 1 0
+BITMAP
+20
+40
+00
+c0
+20
+e0
+a0
+d0
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 8 1 0
+BITMAP
+40
+a0
+00
+c0
+20
+e0
+a0
+d0
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 5 8 0 0
+BITMAP
+68
+b0
+00
+60
+10
+70
+50
+68
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 7 1 0
+BITMAP
+a0
+00
+c0
+20
+e0
+a0
+d0
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 8 1 0
+BITMAP
+40
+a0
+40
+c0
+20
+e0
+a0
+d0
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 1 0
+BITMAP
+d0
+28
+f8
+a0
+d8
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 1 -2
+BITMAP
+60
+80
+80
+80
+60
+40
+80
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 8 1 0
+BITMAP
+40
+20
+00
+40
+a0
+e0
+80
+60
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 8 1 0
+BITMAP
+20
+40
+00
+40
+a0
+e0
+80
+60
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 8 1 0
+BITMAP
+40
+a0
+00
+40
+a0
+e0
+80
+60
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 1 0
+BITMAP
+a0
+00
+40
+a0
+e0
+80
+60
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 8 0 0
+BITMAP
+80
+40
+00
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 8 1 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 8 0 0
+BITMAP
+40
+a0
+00
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 7 0 0
+BITMAP
+a0
+00
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 1 0
+BITMAP
+90
+60
+a0
+70
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 1 0
+BITMAP
+50
+a0
+00
+e0
+90
+90
+90
+90
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 1 0
+BITMAP
+40
+20
+00
+60
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 1 0
+BITMAP
+10
+20
+00
+60
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 1 0
+BITMAP
+40
+a0
+00
+60
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 1 0
+BITMAP
+50
+a0
+00
+60
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 1 0
+BITMAP
+90
+00
+60
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 1 0
+BITMAP
+20
+00
+f0
+00
+20
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 7 7 0 -1
+BITMAP
+02
+3c
+48
+58
+68
+70
+80
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 8 1 0
+BITMAP
+80
+40
+00
+a0
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 8 1 0
+BITMAP
+20
+40
+00
+a0
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 8 1 0
+BITMAP
+40
+a0
+00
+a0
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 1 0
+BITMAP
+a0
+00
+a0
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 9 1 -1
+BITMAP
+10
+20
+00
+90
+90
+90
+60
+40
+80
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 1 -1
+BITMAP
+80
+e0
+90
+90
+90
+e0
+80
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 8 1 -1
+BITMAP
+50
+00
+90
+90
+90
+60
+40
+80
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/helvetica8.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/helvetica8.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/helvetica8.h	(revision 12606)
@@ -0,0 +1,769 @@
+static unsigned char helvetica8_0_bits[] = {
+0x00};
+static unsigned char helvetica8_1_bits[] = {
+0x00};
+static unsigned char helvetica8_2_bits[] = {
+0x00};
+static unsigned char helvetica8_3_bits[] = {
+0x00};
+static unsigned char helvetica8_4_bits[] = {
+0x00};
+static unsigned char helvetica8_5_bits[] = {
+0x00};
+static unsigned char helvetica8_6_bits[] = {
+0x00};
+static unsigned char helvetica8_7_bits[] = {
+0x00};
+static unsigned char helvetica8_8_bits[] = {
+0x00};
+static unsigned char helvetica8_9_bits[] = {
+0x00};
+static unsigned char helvetica8_10_bits[] = {
+0x00};
+static unsigned char helvetica8_11_bits[] = {
+0x00};
+static unsigned char helvetica8_12_bits[] = {
+0x00};
+static unsigned char helvetica8_13_bits[] = {
+0x00};
+static unsigned char helvetica8_14_bits[] = {
+0x00};
+static unsigned char helvetica8_15_bits[] = {
+0x00};
+static unsigned char helvetica8_16_bits[] = {
+0x00};
+static unsigned char helvetica8_17_bits[] = {
+0x00};
+static unsigned char helvetica8_18_bits[] = {
+0x00};
+static unsigned char helvetica8_19_bits[] = {
+0x00};
+static unsigned char helvetica8_20_bits[] = {
+0x00};
+static unsigned char helvetica8_21_bits[] = {
+0x00};
+static unsigned char helvetica8_22_bits[] = {
+0x00};
+static unsigned char helvetica8_23_bits[] = {
+0x00};
+static unsigned char helvetica8_24_bits[] = {
+0x00};
+static unsigned char helvetica8_25_bits[] = {
+0x00};
+static unsigned char helvetica8_26_bits[] = {
+0x00};
+static unsigned char helvetica8_27_bits[] = {
+0x00};
+static unsigned char helvetica8_28_bits[] = {
+0x00};
+static unsigned char helvetica8_29_bits[] = {
+0x00};
+static unsigned char helvetica8_30_bits[] = {
+0x00};
+static unsigned char helvetica8_31_bits[] = {
+0x00};
+static unsigned char helvetica8_32_bits[] = {
+0x00};
+static unsigned char helvetica8_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x00, 0x01};
+static unsigned char helvetica8_34_bits[] = {
+0x05, 0x05, 0x05};
+static unsigned char helvetica8_35_bits[] = {
+0x0a, 0x1f, 0x0a, 0x1f, 0x0a};
+static unsigned char helvetica8_36_bits[] = {
+0x04, 0x0e, 0x01, 0x06, 0x08, 0x07, 0x02};
+static unsigned char helvetica8_37_bits[] = {
+0x17, 0x15, 0x0b, 0x34, 0x2a, 0x3a};
+static unsigned char helvetica8_38_bits[] = {
+0x02, 0x05, 0x12, 0x15, 0x0d, 0x1a};
+static unsigned char helvetica8_39_bits[] = {
+0x01, 0x01, 0x01};
+static unsigned char helvetica8_40_bits[] = {
+0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02};
+static unsigned char helvetica8_41_bits[] = {
+0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char helvetica8_42_bits[] = {
+0x02, 0x07, 0x02};
+static unsigned char helvetica8_43_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x04};
+static unsigned char helvetica8_44_bits[] = {
+0x02, 0x02, 0x01};
+static unsigned char helvetica8_45_bits[] = {
+0x0f};
+static unsigned char helvetica8_46_bits[] = {
+0x01};
+static unsigned char helvetica8_47_bits[] = {
+0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_48_bits[] = {
+0x06, 0x09, 0x09, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_49_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_50_bits[] = {
+0x06, 0x09, 0x08, 0x04, 0x02, 0x0f};
+static unsigned char helvetica8_51_bits[] = {
+0x03, 0x04, 0x03, 0x04, 0x04, 0x03};
+static unsigned char helvetica8_52_bits[] = {
+0x04, 0x04, 0x06, 0x0f, 0x04, 0x04};
+static unsigned char helvetica8_53_bits[] = {
+0x07, 0x01, 0x03, 0x04, 0x04, 0x03};
+static unsigned char helvetica8_54_bits[] = {
+0x0e, 0x01, 0x07, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_55_bits[] = {
+0x0f, 0x08, 0x04, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_56_bits[] = {
+0x06, 0x09, 0x06, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_57_bits[] = {
+0x06, 0x09, 0x09, 0x0e, 0x08, 0x06};
+static unsigned char helvetica8_58_bits[] = {
+0x01, 0x00, 0x00, 0x01};
+static unsigned char helvetica8_59_bits[] = {
+0x02, 0x00, 0x00, 0x02, 0x02, 0x01};
+static unsigned char helvetica8_60_bits[] = {
+0x04, 0x02, 0x01, 0x02, 0x04};
+static unsigned char helvetica8_61_bits[] = {
+0x07, 0x00, 0x07};
+static unsigned char helvetica8_62_bits[] = {
+0x01, 0x02, 0x04, 0x02, 0x01};
+static unsigned char helvetica8_63_bits[] = {
+0x03, 0x04, 0x02, 0x00, 0x02};
+static unsigned char helvetica8_64_bits[] = {
+0x7c, 0x82, 0x99, 0xa5, 0x79, 0x01, 0x1e};
+static unsigned char helvetica8_65_bits[] = {
+0x04, 0x04, 0x0a, 0x0e, 0x11, 0x11};
+static unsigned char helvetica8_66_bits[] = {
+0x07, 0x09, 0x07, 0x09, 0x09, 0x07};
+static unsigned char helvetica8_67_bits[] = {
+0x0e, 0x11, 0x01, 0x01, 0x11, 0x0e};
+static unsigned char helvetica8_68_bits[] = {
+0x0f, 0x11, 0x11, 0x11, 0x11, 0x0f};
+static unsigned char helvetica8_69_bits[] = {
+0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f};
+static unsigned char helvetica8_70_bits[] = {
+0x0f, 0x01, 0x07, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_71_bits[] = {
+0x0e, 0x01, 0x19, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_72_bits[] = {
+0x11, 0x11, 0x1f, 0x11, 0x11, 0x11};
+static unsigned char helvetica8_73_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_74_bits[] = {
+0x04, 0x04, 0x04, 0x04, 0x05, 0x02};
+static unsigned char helvetica8_75_bits[] = {
+0x09, 0x05, 0x03, 0x07, 0x09, 0x09};
+static unsigned char helvetica8_76_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x07};
+static unsigned char helvetica8_77_bits[] = {
+0x11, 0x1b, 0x15, 0x15, 0x15, 0x15};
+static unsigned char helvetica8_78_bits[] = {
+0x11, 0x13, 0x15, 0x15, 0x19, 0x11};
+static unsigned char helvetica8_79_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_80_bits[] = {
+0x07, 0x09, 0x09, 0x07, 0x01, 0x01};
+static unsigned char helvetica8_81_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e, 0x04, 0x08};
+static unsigned char helvetica8_82_bits[] = {
+0x07, 0x09, 0x09, 0x07, 0x09, 0x09};
+static unsigned char helvetica8_83_bits[] = {
+0x0e, 0x01, 0x07, 0x08, 0x08, 0x07};
+static unsigned char helvetica8_84_bits[] = {
+0x07, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_85_bits[] = {
+0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_86_bits[] = {
+0x09, 0x09, 0x09, 0x09, 0x05, 0x02};
+static unsigned char helvetica8_87_bits[] = {
+0x49, 0x49, 0x49, 0x36, 0x12, 0x12};
+static unsigned char helvetica8_88_bits[] = {
+0x09, 0x09, 0x06, 0x06, 0x09, 0x09};
+static unsigned char helvetica8_89_bits[] = {
+0x13, 0x12, 0x12, 0x0c, 0x04, 0x04};
+static unsigned char helvetica8_90_bits[] = {
+0x0f, 0x08, 0x04, 0x02, 0x01, 0x0f};
+static unsigned char helvetica8_91_bits[] = {
+0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03};
+static unsigned char helvetica8_92_bits[] = {
+0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_93_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03};
+static unsigned char helvetica8_94_bits[] = {
+0x04, 0x0a, 0x11};
+static unsigned char helvetica8_95_bits[] = {
+0x1f};
+static unsigned char helvetica8_96_bits[] = {
+0x01, 0x01, 0x01};
+static unsigned char helvetica8_97_bits[] = {
+0x03, 0x04, 0x07, 0x05, 0x0b};
+static unsigned char helvetica8_98_bits[] = {
+0x01, 0x01, 0x07, 0x09, 0x09, 0x09, 0x07};
+static unsigned char helvetica8_99_bits[] = {
+0x06, 0x01, 0x01, 0x01, 0x06};
+static unsigned char helvetica8_100_bits[] = {
+0x08, 0x08, 0x0e, 0x09, 0x09, 0x09, 0x0e};
+static unsigned char helvetica8_101_bits[] = {
+0x02, 0x05, 0x07, 0x01, 0x06};
+static unsigned char helvetica8_102_bits[] = {
+0x04, 0x02, 0x07, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_103_bits[] = {
+0x0e, 0x09, 0x09, 0x0e, 0x08, 0x06};
+static unsigned char helvetica8_104_bits[] = {
+0x01, 0x01, 0x07, 0x09, 0x09, 0x09, 0x09};
+static unsigned char helvetica8_105_bits[] = {
+0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_106_bits[] = {
+0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char helvetica8_107_bits[] = {
+0x01, 0x01, 0x05, 0x03, 0x03, 0x05, 0x05};
+static unsigned char helvetica8_108_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_109_bits[] = {
+0x0f, 0x15, 0x15, 0x15, 0x15};
+static unsigned char helvetica8_110_bits[] = {
+0x07, 0x09, 0x09, 0x09, 0x09};
+static unsigned char helvetica8_111_bits[] = {
+0x06, 0x09, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_112_bits[] = {
+0x07, 0x09, 0x09, 0x09, 0x07, 0x01};
+static unsigned char helvetica8_113_bits[] = {
+0x0e, 0x09, 0x09, 0x09, 0x0e, 0x08};
+static unsigned char helvetica8_114_bits[] = {
+0x05, 0x03, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_115_bits[] = {
+0x06, 0x01, 0x06, 0x04, 0x03};
+static unsigned char helvetica8_116_bits[] = {
+0x02, 0x02, 0x07, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_117_bits[] = {
+0x05, 0x05, 0x05, 0x05, 0x06};
+static unsigned char helvetica8_118_bits[] = {
+0x09, 0x09, 0x09, 0x05, 0x02};
+static unsigned char helvetica8_119_bits[] = {
+0x15, 0x15, 0x15, 0x0a, 0x0a};
+static unsigned char helvetica8_120_bits[] = {
+0x09, 0x09, 0x06, 0x09, 0x09};
+static unsigned char helvetica8_121_bits[] = {
+0x09, 0x09, 0x09, 0x06, 0x02, 0x01};
+static unsigned char helvetica8_122_bits[] = {
+0x07, 0x04, 0x02, 0x01, 0x07};
+static unsigned char helvetica8_123_bits[] = {
+0x04, 0x02, 0x02, 0x03, 0x02, 0x02, 0x04};
+static unsigned char helvetica8_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_125_bits[] = {
+0x01, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01};
+static unsigned char helvetica8_126_bits[] = {
+0x12, 0x0d};
+static unsigned char helvetica8_127_bits[] = {
+0x00};
+static unsigned char helvetica8_128_bits[] = {
+0x00};
+static unsigned char helvetica8_129_bits[] = {
+0x00};
+static unsigned char helvetica8_130_bits[] = {
+0x00};
+static unsigned char helvetica8_131_bits[] = {
+0x00};
+static unsigned char helvetica8_132_bits[] = {
+0x00};
+static unsigned char helvetica8_133_bits[] = {
+0x00};
+static unsigned char helvetica8_134_bits[] = {
+0x00};
+static unsigned char helvetica8_135_bits[] = {
+0x00};
+static unsigned char helvetica8_136_bits[] = {
+0x00};
+static unsigned char helvetica8_137_bits[] = {
+0x00};
+static unsigned char helvetica8_138_bits[] = {
+0x00};
+static unsigned char helvetica8_139_bits[] = {
+0x00};
+static unsigned char helvetica8_140_bits[] = {
+0x00};
+static unsigned char helvetica8_141_bits[] = {
+0x00};
+static unsigned char helvetica8_142_bits[] = {
+0x00};
+static unsigned char helvetica8_143_bits[] = {
+0x00};
+static unsigned char helvetica8_144_bits[] = {
+0x00};
+static unsigned char helvetica8_145_bits[] = {
+0x00};
+static unsigned char helvetica8_146_bits[] = {
+0x00};
+static unsigned char helvetica8_147_bits[] = {
+0x00};
+static unsigned char helvetica8_148_bits[] = {
+0x00};
+static unsigned char helvetica8_149_bits[] = {
+0x00};
+static unsigned char helvetica8_150_bits[] = {
+0x00};
+static unsigned char helvetica8_151_bits[] = {
+0x00};
+static unsigned char helvetica8_152_bits[] = {
+0x00};
+static unsigned char helvetica8_153_bits[] = {
+0x00};
+static unsigned char helvetica8_154_bits[] = {
+0x00};
+static unsigned char helvetica8_155_bits[] = {
+0x00};
+static unsigned char helvetica8_156_bits[] = {
+0x00};
+static unsigned char helvetica8_157_bits[] = {
+0x00};
+static unsigned char helvetica8_158_bits[] = {
+0x00};
+static unsigned char helvetica8_159_bits[] = {
+0x00};
+static unsigned char helvetica8_160_bits[] = {
+0x00};
+static unsigned char helvetica8_161_bits[] = {
+0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_162_bits[] = {
+0x02, 0x02, 0x05, 0x01, 0x05, 0x02, 0x02};
+static unsigned char helvetica8_163_bits[] = {
+0x0c, 0x02, 0x07, 0x02, 0x02, 0x0f};
+static unsigned char helvetica8_164_bits[] = {
+0x11, 0x0e, 0x0a, 0x0e, 0x11};
+static unsigned char helvetica8_165_bits[] = {
+0x11, 0x0a, 0x1f, 0x04, 0x04};
+static unsigned char helvetica8_166_bits[] = {
+0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_167_bits[] = {
+0x0e, 0x01, 0x06, 0x09, 0x06, 0x0c, 0x08, 0x07};
+static unsigned char helvetica8_168_bits[] = {
+0x09};
+static unsigned char helvetica8_169_bits[] = {
+0x1e, 0x21, 0x2d, 0x25, 0x2d, 0x21, 0x1e};
+static unsigned char helvetica8_170_bits[] = {
+0x03, 0x04, 0x07, 0x00, 0x07};
+static unsigned char helvetica8_171_bits[] = {
+0x0a, 0x05, 0x0a};
+static unsigned char helvetica8_172_bits[] = {
+0x0f, 0x08, 0x08};
+static unsigned char helvetica8_173_bits[] = {
+0x03};
+static unsigned char helvetica8_174_bits[] = {
+0x1e, 0x21, 0x2d, 0x2d, 0x35, 0x21, 0x1e};
+static unsigned char helvetica8_175_bits[] = {
+0x07};
+static unsigned char helvetica8_176_bits[] = {
+0x02, 0x05, 0x02};
+static unsigned char helvetica8_177_bits[] = {
+0x04, 0x0f, 0x04, 0x00, 0x0f};
+static unsigned char helvetica8_178_bits[] = {
+0x01, 0x02, 0x01, 0x03};
+static unsigned char helvetica8_179_bits[] = {
+0x07, 0x06, 0x04, 0x03};
+static unsigned char helvetica8_180_bits[] = {
+0x02, 0x01};
+static unsigned char helvetica8_181_bits[] = {
+0x05, 0x05, 0x05, 0x07, 0x01, 0x01};
+static unsigned char helvetica8_182_bits[] = {
+0x1e, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a};
+static unsigned char helvetica8_183_bits[] = {
+0x01, 0x01};
+static unsigned char helvetica8_184_bits[] = {
+0x02, 0x01};
+static unsigned char helvetica8_185_bits[] = {
+0x02, 0x03, 0x02, 0x02};
+static unsigned char helvetica8_186_bits[] = {
+0x07, 0x05, 0x07, 0x00, 0x07};
+static unsigned char helvetica8_187_bits[] = {
+0x05, 0x0a, 0x05};
+static unsigned char helvetica8_188_bits[] = {
+0x02, 0x23, 0x12, 0x2a, 0x34, 0x7a, 0x20};
+static unsigned char helvetica8_189_bits[] = {
+0x02, 0x23, 0x12, 0x3a, 0x44, 0x22, 0x70};
+static unsigned char helvetica8_190_bits[] = {
+0x07, 0x26, 0x14, 0x2b, 0x34, 0x7a, 0x20};
+static unsigned char helvetica8_191_bits[] = {
+0x04, 0x00, 0x04, 0x02, 0x09, 0x06};
+static unsigned char helvetica8_192_bits[] = {
+0x02, 0x04, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x11, 0x11};
+static unsigned char helvetica8_193_bits[] = {
+0x08, 0x04, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x11, 0x11};
+static unsigned char helvetica8_194_bits[] = {
+0x04, 0x0a, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x11, 0x11};
+static unsigned char helvetica8_195_bits[] = {
+0x14, 0x0a, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x11, 0x11};
+static unsigned char helvetica8_196_bits[] = {
+0x0a, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x11, 0x11};
+static unsigned char helvetica8_197_bits[] = {
+0x04, 0x0a, 0x04, 0x04, 0x04, 0x0a, 0x0e, 0x11, 0x11};
+static unsigned char helvetica8_198_bits[] = {
+0x7c, 0x0c, 0x0a, 0x3e, 0x09, 0x79};
+static unsigned char helvetica8_199_bits[] = {
+0x0e, 0x11, 0x11, 0x01, 0x11, 0x0e, 0x02, 0x01};
+static unsigned char helvetica8_200_bits[] = {
+0x02, 0x04, 0x00, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f};
+static unsigned char helvetica8_201_bits[] = {
+0x04, 0x02, 0x00, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f};
+static unsigned char helvetica8_202_bits[] = {
+0x02, 0x05, 0x00, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f};
+static unsigned char helvetica8_203_bits[] = {
+0x05, 0x00, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f};
+static unsigned char helvetica8_204_bits[] = {
+0x01, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_205_bits[] = {
+0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_206_bits[] = {
+0x02, 0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_207_bits[] = {
+0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_208_bits[] = {
+0x0e, 0x12, 0x17, 0x12, 0x12, 0x0e};
+static unsigned char helvetica8_209_bits[] = {
+0x14, 0x0a, 0x00, 0x11, 0x13, 0x15, 0x15, 0x19, 0x11};
+static unsigned char helvetica8_210_bits[] = {
+0x02, 0x04, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_211_bits[] = {
+0x08, 0x04, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_212_bits[] = {
+0x04, 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_213_bits[] = {
+0x14, 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_214_bits[] = {
+0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_215_bits[] = {
+0x09, 0x06, 0x06, 0x09};
+static unsigned char helvetica8_216_bits[] = {
+0x10, 0x1e, 0x11, 0x19, 0x15, 0x13, 0x0f, 0x01};
+static unsigned char helvetica8_217_bits[] = {
+0x02, 0x04, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_218_bits[] = {
+0x08, 0x04, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_219_bits[] = {
+0x04, 0x0a, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_220_bits[] = {
+0x0a, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_221_bits[] = {
+0x10, 0x08, 0x00, 0x13, 0x12, 0x12, 0x0c, 0x04, 0x04};
+static unsigned char helvetica8_222_bits[] = {
+0x01, 0x0f, 0x11, 0x11, 0x0f, 0x01};
+static unsigned char helvetica8_223_bits[] = {
+0x06, 0x09, 0x05, 0x09, 0x09, 0x05, 0x01};
+static unsigned char helvetica8_224_bits[] = {
+0x01, 0x02, 0x00, 0x03, 0x04, 0x07, 0x05, 0x0b};
+static unsigned char helvetica8_225_bits[] = {
+0x04, 0x02, 0x00, 0x03, 0x04, 0x07, 0x05, 0x0b};
+static unsigned char helvetica8_226_bits[] = {
+0x02, 0x05, 0x00, 0x03, 0x04, 0x07, 0x05, 0x0b};
+static unsigned char helvetica8_227_bits[] = {
+0x16, 0x0d, 0x00, 0x06, 0x08, 0x0e, 0x0a, 0x16};
+static unsigned char helvetica8_228_bits[] = {
+0x05, 0x00, 0x03, 0x04, 0x07, 0x05, 0x0b};
+static unsigned char helvetica8_229_bits[] = {
+0x02, 0x05, 0x02, 0x03, 0x04, 0x07, 0x05, 0x0b};
+static unsigned char helvetica8_230_bits[] = {
+0x0b, 0x14, 0x1f, 0x05, 0x1b};
+static unsigned char helvetica8_231_bits[] = {
+0x06, 0x01, 0x01, 0x01, 0x06, 0x02, 0x01};
+static unsigned char helvetica8_232_bits[] = {
+0x02, 0x04, 0x00, 0x02, 0x05, 0x07, 0x01, 0x06};
+static unsigned char helvetica8_233_bits[] = {
+0x04, 0x02, 0x00, 0x02, 0x05, 0x07, 0x01, 0x06};
+static unsigned char helvetica8_234_bits[] = {
+0x02, 0x05, 0x00, 0x02, 0x05, 0x07, 0x01, 0x06};
+static unsigned char helvetica8_235_bits[] = {
+0x05, 0x00, 0x02, 0x05, 0x07, 0x01, 0x06};
+static unsigned char helvetica8_236_bits[] = {
+0x01, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_237_bits[] = {
+0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_238_bits[] = {
+0x02, 0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_239_bits[] = {
+0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_240_bits[] = {
+0x09, 0x06, 0x05, 0x0e, 0x09, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_241_bits[] = {
+0x0a, 0x05, 0x00, 0x07, 0x09, 0x09, 0x09, 0x09};
+static unsigned char helvetica8_242_bits[] = {
+0x02, 0x04, 0x00, 0x06, 0x09, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_243_bits[] = {
+0x08, 0x04, 0x00, 0x06, 0x09, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_244_bits[] = {
+0x02, 0x05, 0x00, 0x06, 0x09, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_245_bits[] = {
+0x0a, 0x05, 0x00, 0x06, 0x09, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_246_bits[] = {
+0x09, 0x00, 0x06, 0x09, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_247_bits[] = {
+0x04, 0x00, 0x0f, 0x00, 0x04};
+static unsigned char helvetica8_248_bits[] = {
+0x40, 0x3c, 0x12, 0x1a, 0x16, 0x0e, 0x01};
+static unsigned char helvetica8_249_bits[] = {
+0x01, 0x02, 0x00, 0x05, 0x05, 0x05, 0x05, 0x06};
+static unsigned char helvetica8_250_bits[] = {
+0x04, 0x02, 0x00, 0x05, 0x05, 0x05, 0x05, 0x06};
+static unsigned char helvetica8_251_bits[] = {
+0x02, 0x05, 0x00, 0x05, 0x05, 0x05, 0x05, 0x06};
+static unsigned char helvetica8_252_bits[] = {
+0x05, 0x00, 0x05, 0x05, 0x05, 0x05, 0x06};
+static unsigned char helvetica8_253_bits[] = {
+0x08, 0x04, 0x00, 0x09, 0x09, 0x09, 0x06, 0x02, 0x01};
+static unsigned char helvetica8_254_bits[] = {
+0x01, 0x07, 0x09, 0x09, 0x09, 0x07, 0x01};
+static unsigned char helvetica8_255_bits[] = {
+0x0a, 0x00, 0x09, 0x09, 0x09, 0x06, 0x02, 0x01};
+static RotFont helvetica8font[] = {
+{5, 1, 1, helvetica8_0_bits},
+{5, 1, 1, helvetica8_1_bits},
+{5, 1, 1, helvetica8_2_bits},
+{5, 1, 1, helvetica8_3_bits},
+{5, 1, 1, helvetica8_4_bits},
+{5, 1, 1, helvetica8_5_bits},
+{5, 1, 1, helvetica8_6_bits},
+{5, 1, 1, helvetica8_7_bits},
+{5, 1, 1, helvetica8_8_bits},
+{5, 1, 1, helvetica8_9_bits},
+{5, 1, 1, helvetica8_10_bits},
+{5, 1, 1, helvetica8_11_bits},
+{5, 1, 1, helvetica8_12_bits},
+{5, 1, 1, helvetica8_13_bits},
+{5, 1, 1, helvetica8_14_bits},
+{5, 1, 1, helvetica8_15_bits},
+{5, 1, 1, helvetica8_16_bits},
+{5, 1, 1, helvetica8_17_bits},
+{5, 1, 1, helvetica8_18_bits},
+{5, 1, 1, helvetica8_19_bits},
+{5, 1, 1, helvetica8_20_bits},
+{5, 1, 1, helvetica8_21_bits},
+{5, 1, 1, helvetica8_22_bits},
+{5, 1, 1, helvetica8_23_bits},
+{5, 1, 1, helvetica8_24_bits},
+{5, 1, 1, helvetica8_25_bits},
+{5, 1, 1, helvetica8_26_bits},
+{5, 1, 1, helvetica8_27_bits},
+{5, 1, 1, helvetica8_28_bits},
+{5, 1, 1, helvetica8_29_bits},
+{5, 1, 1, helvetica8_30_bits},
+{5, 1, 1, helvetica8_31_bits},
+{4, 1, 1, helvetica8_32_bits},
+{1, 6, 6, helvetica8_33_bits},
+{3, 3, 6, helvetica8_34_bits},
+{5, 5, 5, helvetica8_35_bits},
+{4, 7, 6, helvetica8_36_bits},
+{6, 6, 6, helvetica8_37_bits},
+{5, 6, 6, helvetica8_38_bits},
+{1, 3, 6, helvetica8_39_bits},
+{2, 7, 6, helvetica8_40_bits},
+{2, 7, 6, helvetica8_41_bits},
+{3, 3, 5, helvetica8_42_bits},
+{5, 5, 5, helvetica8_43_bits},
+{2, 3, 1, helvetica8_44_bits},
+{4, 1, 3, helvetica8_45_bits},
+{1, 1, 1, helvetica8_46_bits},
+{2, 7, 6, helvetica8_47_bits},
+{4, 6, 6, helvetica8_48_bits},
+{2, 6, 6, helvetica8_49_bits},
+{4, 6, 6, helvetica8_50_bits},
+{3, 6, 6, helvetica8_51_bits},
+{4, 6, 6, helvetica8_52_bits},
+{3, 6, 6, helvetica8_53_bits},
+{4, 6, 6, helvetica8_54_bits},
+{4, 6, 6, helvetica8_55_bits},
+{4, 6, 6, helvetica8_56_bits},
+{4, 6, 6, helvetica8_57_bits},
+{1, 4, 4, helvetica8_58_bits},
+{2, 6, 4, helvetica8_59_bits},
+{3, 5, 5, helvetica8_60_bits},
+{3, 3, 4, helvetica8_61_bits},
+{3, 5, 5, helvetica8_62_bits},
+{3, 5, 5, helvetica8_63_bits},
+{8, 7, 6, helvetica8_64_bits},
+{5, 6, 6, helvetica8_65_bits},
+{4, 6, 6, helvetica8_66_bits},
+{5, 6, 6, helvetica8_67_bits},
+{5, 6, 6, helvetica8_68_bits},
+{4, 6, 6, helvetica8_69_bits},
+{4, 6, 6, helvetica8_70_bits},
+{5, 6, 6, helvetica8_71_bits},
+{5, 6, 6, helvetica8_72_bits},
+{1, 6, 6, helvetica8_73_bits},
+{3, 6, 6, helvetica8_74_bits},
+{4, 6, 6, helvetica8_75_bits},
+{3, 6, 6, helvetica8_76_bits},
+{5, 6, 6, helvetica8_77_bits},
+{5, 6, 6, helvetica8_78_bits},
+{5, 6, 6, helvetica8_79_bits},
+{4, 6, 6, helvetica8_80_bits},
+{5, 8, 6, helvetica8_81_bits},
+{4, 6, 6, helvetica8_82_bits},
+{4, 6, 6, helvetica8_83_bits},
+{3, 6, 6, helvetica8_84_bits},
+{5, 6, 6, helvetica8_85_bits},
+{4, 6, 6, helvetica8_86_bits},
+{7, 6, 6, helvetica8_87_bits},
+{4, 6, 6, helvetica8_88_bits},
+{5, 6, 6, helvetica8_89_bits},
+{4, 6, 6, helvetica8_90_bits},
+{2, 7, 6, helvetica8_91_bits},
+{2, 7, 6, helvetica8_92_bits},
+{2, 7, 6, helvetica8_93_bits},
+{5, 3, 5, helvetica8_94_bits},
+{5, 1, 0, helvetica8_95_bits},
+{1, 3, 6, helvetica8_96_bits},
+{4, 5, 5, helvetica8_97_bits},
+{4, 7, 7, helvetica8_98_bits},
+{3, 5, 5, helvetica8_99_bits},
+{4, 7, 7, helvetica8_100_bits},
+{3, 5, 5, helvetica8_101_bits},
+{3, 7, 7, helvetica8_102_bits},
+{4, 6, 5, helvetica8_103_bits},
+{4, 7, 7, helvetica8_104_bits},
+{1, 7, 7, helvetica8_105_bits},
+{2, 9, 7, helvetica8_106_bits},
+{3, 7, 7, helvetica8_107_bits},
+{1, 7, 7, helvetica8_108_bits},
+{5, 5, 5, helvetica8_109_bits},
+{4, 5, 5, helvetica8_110_bits},
+{4, 5, 5, helvetica8_111_bits},
+{4, 6, 5, helvetica8_112_bits},
+{4, 6, 5, helvetica8_113_bits},
+{3, 5, 5, helvetica8_114_bits},
+{3, 5, 5, helvetica8_115_bits},
+{3, 7, 7, helvetica8_116_bits},
+{3, 5, 5, helvetica8_117_bits},
+{4, 5, 5, helvetica8_118_bits},
+{5, 5, 5, helvetica8_119_bits},
+{4, 5, 5, helvetica8_120_bits},
+{4, 6, 5, helvetica8_121_bits},
+{3, 5, 5, helvetica8_122_bits},
+{3, 7, 6, helvetica8_123_bits},
+{1, 7, 6, helvetica8_124_bits},
+{3, 7, 6, helvetica8_125_bits},
+{5, 2, 4, helvetica8_126_bits},
+{5, 1, 1, helvetica8_127_bits},
+{5, 1, 1, helvetica8_128_bits},
+{5, 1, 1, helvetica8_129_bits},
+{5, 1, 1, helvetica8_130_bits},
+{5, 1, 1, helvetica8_131_bits},
+{5, 1, 1, helvetica8_132_bits},
+{5, 1, 1, helvetica8_133_bits},
+{5, 1, 1, helvetica8_134_bits},
+{5, 1, 1, helvetica8_135_bits},
+{5, 1, 1, helvetica8_136_bits},
+{5, 1, 1, helvetica8_137_bits},
+{5, 1, 1, helvetica8_138_bits},
+{5, 1, 1, helvetica8_139_bits},
+{5, 1, 1, helvetica8_140_bits},
+{5, 1, 1, helvetica8_141_bits},
+{5, 1, 1, helvetica8_142_bits},
+{5, 1, 1, helvetica8_143_bits},
+{5, 1, 1, helvetica8_144_bits},
+{5, 1, 1, helvetica8_145_bits},
+{5, 1, 1, helvetica8_146_bits},
+{5, 1, 1, helvetica8_147_bits},
+{5, 1, 1, helvetica8_148_bits},
+{5, 1, 1, helvetica8_149_bits},
+{5, 1, 1, helvetica8_150_bits},
+{5, 1, 1, helvetica8_151_bits},
+{5, 1, 1, helvetica8_152_bits},
+{5, 1, 1, helvetica8_153_bits},
+{5, 1, 1, helvetica8_154_bits},
+{5, 1, 1, helvetica8_155_bits},
+{5, 1, 1, helvetica8_156_bits},
+{5, 1, 1, helvetica8_157_bits},
+{5, 1, 1, helvetica8_158_bits},
+{5, 1, 1, helvetica8_159_bits},
+{1, 1, 1, helvetica8_160_bits},
+{1, 7, 5, helvetica8_161_bits},
+{3, 7, 6, helvetica8_162_bits},
+{4, 6, 6, helvetica8_163_bits},
+{5, 5, 5, helvetica8_164_bits},
+{5, 5, 5, helvetica8_165_bits},
+{1, 7, 6, helvetica8_166_bits},
+{4, 8, 6, helvetica8_167_bits},
+{4, 1, 6, helvetica8_168_bits},
+{6, 7, 6, helvetica8_169_bits},
+{3, 5, 6, helvetica8_170_bits},
+{4, 3, 4, helvetica8_171_bits},
+{4, 3, 4, helvetica8_172_bits},
+{2, 1, 3, helvetica8_173_bits},
+{6, 7, 6, helvetica8_174_bits},
+{3, 1, 6, helvetica8_175_bits},
+{3, 3, 6, helvetica8_176_bits},
+{4, 5, 5, helvetica8_177_bits},
+{2, 4, 6, helvetica8_178_bits},
+{3, 4, 6, helvetica8_179_bits},
+{2, 2, 6, helvetica8_180_bits},
+{3, 6, 4, helvetica8_181_bits},
+{5, 8, 6, helvetica8_182_bits},
+{1, 2, 3, helvetica8_183_bits},
+{2, 2, 0, helvetica8_184_bits},
+{2, 4, 6, helvetica8_185_bits},
+{3, 5, 6, helvetica8_186_bits},
+{4, 3, 4, helvetica8_187_bits},
+{7, 7, 6, helvetica8_188_bits},
+{7, 7, 6, helvetica8_189_bits},
+{7, 7, 6, helvetica8_190_bits},
+{4, 6, 5, helvetica8_191_bits},
+{5, 9, 9, helvetica8_192_bits},
+{5, 9, 9, helvetica8_193_bits},
+{5, 9, 9, helvetica8_194_bits},
+{5, 9, 9, helvetica8_195_bits},
+{5, 8, 8, helvetica8_196_bits},
+{5, 9, 9, helvetica8_197_bits},
+{7, 6, 6, helvetica8_198_bits},
+{5, 8, 6, helvetica8_199_bits},
+{4, 9, 9, helvetica8_200_bits},
+{4, 9, 9, helvetica8_201_bits},
+{4, 9, 9, helvetica8_202_bits},
+{4, 8, 8, helvetica8_203_bits},
+{2, 9, 9, helvetica8_204_bits},
+{2, 9, 9, helvetica8_205_bits},
+{3, 9, 9, helvetica8_206_bits},
+{3, 8, 8, helvetica8_207_bits},
+{5, 6, 6, helvetica8_208_bits},
+{5, 9, 9, helvetica8_209_bits},
+{5, 9, 9, helvetica8_210_bits},
+{5, 9, 9, helvetica8_211_bits},
+{5, 9, 9, helvetica8_212_bits},
+{5, 9, 9, helvetica8_213_bits},
+{5, 8, 8, helvetica8_214_bits},
+{4, 4, 4, helvetica8_215_bits},
+{5, 8, 7, helvetica8_216_bits},
+{5, 9, 9, helvetica8_217_bits},
+{5, 9, 9, helvetica8_218_bits},
+{5, 9, 9, helvetica8_219_bits},
+{5, 8, 8, helvetica8_220_bits},
+{5, 9, 9, helvetica8_221_bits},
+{5, 6, 6, helvetica8_222_bits},
+{4, 7, 6, helvetica8_223_bits},
+{4, 8, 8, helvetica8_224_bits},
+{4, 8, 8, helvetica8_225_bits},
+{4, 8, 8, helvetica8_226_bits},
+{5, 8, 8, helvetica8_227_bits},
+{4, 7, 7, helvetica8_228_bits},
+{4, 8, 8, helvetica8_229_bits},
+{5, 5, 5, helvetica8_230_bits},
+{3, 7, 5, helvetica8_231_bits},
+{3, 8, 8, helvetica8_232_bits},
+{3, 8, 8, helvetica8_233_bits},
+{3, 8, 8, helvetica8_234_bits},
+{3, 7, 7, helvetica8_235_bits},
+{2, 8, 8, helvetica8_236_bits},
+{2, 8, 8, helvetica8_237_bits},
+{3, 8, 8, helvetica8_238_bits},
+{3, 7, 7, helvetica8_239_bits},
+{4, 8, 8, helvetica8_240_bits},
+{4, 8, 8, helvetica8_241_bits},
+{4, 8, 8, helvetica8_242_bits},
+{4, 8, 8, helvetica8_243_bits},
+{4, 8, 8, helvetica8_244_bits},
+{4, 8, 8, helvetica8_245_bits},
+{4, 7, 7, helvetica8_246_bits},
+{4, 5, 5, helvetica8_247_bits},
+{7, 7, 6, helvetica8_248_bits},
+{3, 8, 8, helvetica8_249_bits},
+{3, 8, 8, helvetica8_250_bits},
+{3, 8, 8, helvetica8_251_bits},
+{3, 7, 7, helvetica8_252_bits},
+{4, 9, 8, helvetica8_253_bits},
+{4, 7, 6, helvetica8_254_bits},
+{4, 8, 7, helvetica8_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/symbol12.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/symbol12.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/symbol12.bdf	(revision 12606)
@@ -0,0 +1,3022 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Symbol-Medium-R-Normal--12-120-75-75-P-74-Adobe-FontSpecific
+SIZE 12 75 75
+FONTBOUNDINGBOX 14 16 -1 -4
+STARTPROPERTIES 31
+FOUNDRY "Adobe"
+FAMILY_NAME "Symbol"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 74
+CHARSET_REGISTRY "Adobe"
+CHARSET_ENCODING "FontSpecific"
+CAP_HEIGHT 9
+X_HEIGHT 6
+FACE_NAME "Symbol"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "No mark"
+_DEC_DEVICE_FONTNAMES "PS=Symbol"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2-1, 18-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+FULL_NAME "Symbol"
+FONT "-Adobe-Symbol-Medium-R-Normal--12-120-75-75-P-74-Adobe-FontSpecific"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 8
+DEFAULT_CHAR 32
+FONT_ASCENT 11
+FONT_DESCENT 3
+ENDPROPERTIES
+CHARS 188
+STARTCHAR space
+ENCODING 32
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+8080
+4100
+4100
+3e00
+2200
+1400
+1400
+0800
+0800
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+28
+28
+28
+fc
+50
+f8
+50
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+f8
+08
+08
+08
+f8
+08
+08
+08
+f8
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+7900
+9700
+9200
+6400
+0800
+1300
+1480
+2480
+6300
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 1 0
+BITMAP
+3000
+4800
+4800
+3700
+7200
+9a00
+8c00
+8c80
+7300
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 6 1 0
+BITMAP
+e0
+10
+f0
+10
+10
+e0
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 12 1 -3
+BITMAP
+20
+40
+40
+80
+80
+80
+80
+80
+80
+40
+40
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 12 0 -3
+BITMAP
+80
+40
+40
+20
+20
+20
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 5 0 2
+BITMAP
+20
+a8
+70
+a8
+20
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+20
+f8
+20
+20
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 3 0 -2
+BITMAP
+40
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 1 1 3
+BITMAP
+f8
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 1 1 0
+BITMAP
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+20
+20
+20
+40
+40
+40
+80
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+88
+88
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 3 9 1 0
+BITMAP
+40
+c0
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+88
+88
+08
+10
+20
+40
+88
+f8
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+88
+88
+08
+30
+08
+08
+88
+70
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+18
+28
+28
+48
+48
+88
+fc
+08
+08
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+78
+40
+80
+f0
+18
+08
+08
+88
+f0
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+38
+40
+80
+b0
+c8
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+f8
+88
+10
+10
+20
+20
+40
+40
+40
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+88
+88
+c8
+70
+98
+88
+88
+70
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+88
+88
+88
+78
+10
+10
+20
+40
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 6 2 0
+BITMAP
+80
+00
+00
+00
+00
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 8 0 -2
+BITMAP
+40
+00
+00
+00
+00
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+0c
+30
+c0
+30
+0c
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 3 1 2
+BITMAP
+f8
+00
+f8
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+c0
+30
+0c
+30
+c0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+88
+88
+08
+10
+20
+20
+00
+20
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 6 1 0
+BITMAP
+68
+b0
+00
+f8
+00
+f8
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+0800
+1c00
+1400
+1400
+2200
+3e00
+2200
+4100
+e380
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+fc
+46
+42
+46
+7c
+46
+42
+46
+fc
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+e7
+42
+24
+18
+18
+24
+24
+42
+e7
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+10
+10
+28
+28
+44
+44
+44
+82
+fe
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+fe
+42
+40
+44
+7c
+44
+40
+42
+fe
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+1c00
+0800
+7f00
+c980
+8880
+c980
+7f00
+0800
+1c00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+fe
+42
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+e7
+42
+42
+42
+7e
+42
+42
+42
+e7
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 9 0 0
+BITMAP
+e0
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+04
+0a
+0a
+66
+a3
+22
+22
+26
+1c
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+ee
+44
+48
+50
+70
+48
+44
+42
+e7
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+0800
+0800
+1400
+1400
+2200
+2200
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 11 9 0 0
+BITMAP
+e0e0
+60c0
+5140
+5140
+5140
+4a40
+4a40
+4440
+e4e0
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+e7
+62
+52
+52
+4a
+4a
+46
+46
+e2
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3c
+66
+42
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+ff
+42
+42
+42
+42
+42
+42
+42
+e7
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3c
+66
+42
+a5
+bd
+a5
+42
+66
+3c
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+f8
+4c
+44
+4c
+78
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+fc
+84
+c0
+60
+30
+20
+40
+82
+fe
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+fe
+92
+92
+10
+10
+10
+10
+10
+38
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+e380
+4100
+2200
+1400
+0800
+0800
+0800
+0800
+1c00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 -3
+BITMAP
+78
+80
+80
+80
+c0
+70
+08
+48
+70
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 10 9 0 0
+BITMAP
+1e00
+3300
+2100
+4080
+4080
+4080
+2100
+9240
+f3c0
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+7e
+42
+00
+24
+3c
+24
+00
+81
+ff
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+dd80
+4900
+4900
+6b00
+3e00
+0800
+0800
+0800
+1c00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+fc
+84
+08
+10
+20
+20
+40
+84
+fc
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 12 1 -3
+BITMAP
+e0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+e0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 6 1 0
+BITMAP
+10
+10
+00
+00
+82
+82
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 12 0 -3
+BITMAP
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+e0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+10
+10
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 1 0 -3
+BITMAP
+fc
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 7 1 0 11
+BITMAP
+fe
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 6 1 0
+BITMAP
+74
+d4
+88
+88
+d4
+66
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+70
+88
+88
+88
+b0
+88
+88
+88
+c8
+b0
+80
+80
+80
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 -3
+BITMAP
+c6
+ac
+28
+18
+30
+28
+68
+4a
+c6
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+70
+98
+80
+40
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 6 1 0
+BITMAP
+70
+80
+e0
+80
+90
+70
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 11 0 -3
+BITMAP
+10
+10
+38
+54
+92
+92
+54
+38
+10
+10
+10
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 0 -3
+BITMAP
+c4
+a4
+24
+24
+28
+18
+10
+30
+20
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 -3
+BITMAP
+6c
+b2
+22
+22
+22
+22
+02
+02
+02
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 6 0 0
+BITMAP
+c0
+40
+40
+40
+40
+60
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 -3
+BITMAP
+18
+54
+92
+92
+54
+38
+10
+10
+10
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 6 0 0
+BITMAP
+4c
+d4
+60
+70
+58
+4c
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+60
+50
+10
+30
+28
+48
+48
+8a
+86
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 1 -3
+BITMAP
+88
+88
+88
+88
+9a
+ec
+80
+80
+c0
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 6 0 0
+BITMAP
+cc
+44
+44
+28
+28
+30
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 6 1 0
+BITMAP
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 6 0 0
+BITMAP
+7e
+a4
+24
+24
+26
+64
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+88
+f8
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 -3
+BITMAP
+70
+88
+88
+88
+c8
+b0
+80
+80
+80
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 6 1 0
+BITMAP
+7c
+90
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+78
+a0
+20
+20
+28
+30
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 6 0 0
+BITMAP
+64
+a2
+22
+22
+26
+1c
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+7f
+a2
+49
+49
+49
+49
+36
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 6 1 0
+BITMAP
+44
+92
+92
+92
+92
+6c
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 14 1 -3
+BITMAP
+40
+80
+70
+c0
+80
+f0
+40
+80
+80
+c0
+70
+08
+48
+70
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 -3
+BITMAP
+8880
+4900
+4900
+4900
+6b00
+3e00
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 13 1 -3
+BITMAP
+40
+98
+70
+40
+80
+80
+80
+80
+c0
+70
+08
+48
+70
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 12 0 -3
+BITMAP
+18
+20
+20
+20
+40
+80
+40
+20
+20
+20
+20
+18
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 12 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 12 0 -3
+BITMAP
+c0
+20
+20
+20
+10
+08
+10
+20
+20
+20
+20
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 3 0 2
+BITMAP
+62
+92
+8c
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 3 1 6
+BITMAP
+00
+00
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 5 9 -1 0
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 4 0 1
+BITMAP
+0000
+0000
+0000
+c600
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+28
+10
+10
+10
+10
+10
+38
+20
+40
+80
+0c
+30
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 7 1 -1
+BITMAP
+c0
+30
+0c
+00
+fc
+08
+10
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 6 1 0
+BITMAP
+10
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 6 1 0
+BITMAP
+80
+76
+00
+98
+80
+8c
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 7 1 -1
+BITMAP
+80
+76
+00
+0c
+14
+10
+7c
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 1040 0
+DWIDTH 13 0
+BBX 11 5 1 1
+BITMAP
+1000
+1020
+2020
+a0c0
+3820
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 960 0
+DWIDTH 12 0
+BBX 12 5 0 1
+BITMAP
+d6f0
+d610
+1020
+70f0
+f870
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 16 1 -4
+BITMAP
+20
+68
+f8
+f8
+78
+38
+10
+10
+38
+78
+f8
+d0
+10
+10
+20
+80
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 960 0
+DWIDTH 12 0
+BBX 12 5 0 1
+BITMAP
+4040
+ffe0
+4040
+2080
+2000
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 15 1 -3
+BITMAP
+40
+00
+f8
+f0
+40
+00
+20
+00
+20
+70
+a8
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 4 0 5
+BITMAP
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+20
+20
+20
+20
+20
+00
+40
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 5 3 0 6
+BITMAP
+00
+20
+f8
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+f0
+00
+20
+00
+40
+20
+20
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 4 0 1
+BITMAP
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 10 0 0
+BITMAP
+20
+a8
+70
+20
+60
+90
+90
+60
+20
+20
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 4 1 1
+BITMAP
+f0
+20
+20
+00
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+f8
+28
+50
+a0
+c0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+30
+08
+30
+c0
+00
+f8
+88
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+50
+20
+50
+88
+70
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+88
+88
+74
+60
+90
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 1 1 0
+BITMAP
+0800
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 1 16 3 -4
+BITMAP
+00
+80
+80
+80
+80
+00
+00
+80
+80
+00
+00
+00
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 1040 0
+DWIDTH 13 0
+BBX 13 1 0 3
+BITMAP
+10f8
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 8 0 0
+BITMAP
+20
+f8
+40
+80
+f8
+00
+f8
+00
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 7 9 1 0
+BITMAP
+f8
+64
+98
+00
+64
+98
+88
+80
+80
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 11 0 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 10 0 0
+BITMAP
+8080
+8080
+ff80
+0200
+0200
+0200
+fe00
+8880
+6600
+d480
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 11 1 -3
+BITMAP
+4c
+66
+e2
+3f
+61
+42
+64
+0c
+06
+03
+01
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+6180
+1c00
+0080
+0080
+0080
+0000
+0000
+0000
+0000
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+0000
+0080
+8000
+2600
+9180
+ab80
+6480
+9000
+1c00
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+6300
+6300
+9480
+8880
+9480
+6300
+6300
+1c00
+1c00
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 6 1 0
+BITMAP
+63
+00
+49
+00
+88
+80
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 6 1 0
+BITMAP
+be
+80
+88
+80
+49
+00
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 6 1 0
+BITMAP
+63
+00
+1c
+00
+1c
+80
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 8 1 -2
+BITMAP
+63
+00
+43
+00
+84
+80
+88
+80
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 8 0 -1
+BITMAP
+90
+80
+61
+00
+63
+00
+9c
+00
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 6 0 0
+BITMAP
+3c
+42
+81
+81
+81
+81
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 8 0 -2
+BITMAP
+81
+81
+81
+81
+42
+3c
+fc
+02
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 6 1 0
+BITMAP
+00
+00
+00
+fc
+fc
+00
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 8 1 -1
+BITMAP
+00
+00
+00
+fc
+00
+fc
+00
+3c
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+4480
+8800
+3f00
+3f00
+8080
+4000
+3f00
+8080
+4000
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+00
+ff
+7c
+80
+fc
+80
+80
+7c
+04
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+7c
+88
+fc
+90
+a0
+7c
+40
+00
+80
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+01
+00
+02
+00
+04
+00
+08
+00
+10
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 11 6 0 3
+BITMAP
+0020
+0040
+00e0
+80e0
+8140
+4220
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 11 0 -1
+BITMAP
+2400
+1800
+3c00
+f980
+b980
+ed00
+3c00
+4280
+a980
+a580
+4200
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 12 0 0
+BITMAP
+fa
+80
+aa
+80
+24
+40
+24
+40
+24
+40
+76
+60
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 1 1 3
+BITMAP
+c0
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 4 1 0
+BITMAP
+80
+40
+00
+40
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 6 1 0
+BITMAP
+00
+40
+00
+40
+00
+40
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 6 1 0
+BITMAP
+00
+40
+00
+40
+00
+40
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 1040 0
+DWIDTH 13 0
+BBX 11 5 1 1
+BITMAP
+0040
+00e0
+8000
+0200
+0400
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 960 0
+DWIDTH 12 0
+BBX 11 5 0 1
+BITMAP
+0460
+a820
+2800
+10c0
+fe00
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 5 12 1 -1
+BITMAP
+00
+00
+30
+30
+48
+48
+80
+80
+80
+80
+48
+48
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 960 0
+DWIDTH 12 0
+BBX 11 5 1 1
+BITMAP
+3020
+2080
+7fc0
+c060
+7fc0
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 5 12 1 0
+BITMAP
+20
+80
+20
+00
+78
+e0
+c0
+00
+78
+e0
+20
+00
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+20
+70
+d8
+50
+50
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 11 0 -1
+BITMAP
+50
+50
+50
+00
+80
+f0
+c0
+00
+60
+f0
+c0
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+00
+80
+50
+50
+50
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+50
+50
+d8
+70
+20
+30
+30
+48
+84
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 10 6 0 3
+BITMAP
+8440
+4800
+3000
+2000
+4040
+8040
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 11 0 -1
+BITMAP
+40
+20
+20
+10
+3c
+42
+b9
+a5
+b9
+a5
+a5
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 16 1 -4
+BITMAP
+40
+30
+30
+40
+90
+a0
+a0
+a0
+90
+40
+30
+f0
+80
+20
+80
+20
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 1 16 1 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+80
+80
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 16 1 -4
+BITMAP
+80
+f0
+10
+20
+20
+40
+40
+40
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 16 1 -4
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 1 16 1 -4
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 15 1 -3
+BITMAP
+20
+00
+e0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 3 16 2 -4
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 3 16 0 -4
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 3 15 2 -3
+BITMAP
+80
+e0
+60
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 1 16 2 -4
+BITMAP
+80
+80
+80
+00
+00
+00
+00
+00
+00
+00
+80
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 12 0 -2
+BITMAP
+20
+20
+20
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 5 15 0 -3
+BITMAP
+80
+80
+80
+80
+80
+60
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 5 16 4 -4
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+00
+80
+40
+40
+20
+20
+10
+10
+20
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 1 16 1 -4
+BITMAP
+00
+00
+00
+80
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 5 15 0 -3
+BITMAP
+20
+a0
+c0
+38
+58
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 16 0 -4
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 1 16 3 -4
+BITMAP
+80
+80
+80
+80
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 16 0 -4
+BITMAP
+00
+d0
+e0
+80
+40
+40
+20
+20
+20
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 16 1 -4
+BITMAP
+00
+00
+00
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 1 16 3 -4
+BITMAP
+80
+80
+80
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 15 1 -3
+BITMAP
+40
+40
+80
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 3 16 0 -4
+BITMAP
+20
+20
+20
+20
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 3 16 2 -4
+BITMAP
+80
+80
+80
+80
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 3 15 0 -3
+BITMAP
+20
+20
+e0
+c0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/symbol12.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/symbol12.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/symbol12.h	(revision 12606)
@@ -0,0 +1,815 @@
+static unsigned char symbol12_0_bits[] = {
+0x00};
+static unsigned char symbol12_1_bits[] = {
+0x00};
+static unsigned char symbol12_2_bits[] = {
+0x00};
+static unsigned char symbol12_3_bits[] = {
+0x00};
+static unsigned char symbol12_4_bits[] = {
+0x00};
+static unsigned char symbol12_5_bits[] = {
+0x00};
+static unsigned char symbol12_6_bits[] = {
+0x00};
+static unsigned char symbol12_7_bits[] = {
+0x00};
+static unsigned char symbol12_8_bits[] = {
+0x00};
+static unsigned char symbol12_9_bits[] = {
+0x00};
+static unsigned char symbol12_10_bits[] = {
+0x00};
+static unsigned char symbol12_11_bits[] = {
+0x00};
+static unsigned char symbol12_12_bits[] = {
+0x00};
+static unsigned char symbol12_13_bits[] = {
+0x00};
+static unsigned char symbol12_14_bits[] = {
+0x00};
+static unsigned char symbol12_15_bits[] = {
+0x00};
+static unsigned char symbol12_16_bits[] = {
+0x00};
+static unsigned char symbol12_17_bits[] = {
+0x00};
+static unsigned char symbol12_18_bits[] = {
+0x00};
+static unsigned char symbol12_19_bits[] = {
+0x00};
+static unsigned char symbol12_20_bits[] = {
+0x00};
+static unsigned char symbol12_21_bits[] = {
+0x00};
+static unsigned char symbol12_22_bits[] = {
+0x00};
+static unsigned char symbol12_23_bits[] = {
+0x00};
+static unsigned char symbol12_24_bits[] = {
+0x00};
+static unsigned char symbol12_25_bits[] = {
+0x00};
+static unsigned char symbol12_26_bits[] = {
+0x00};
+static unsigned char symbol12_27_bits[] = {
+0x00};
+static unsigned char symbol12_28_bits[] = {
+0x00};
+static unsigned char symbol12_29_bits[] = {
+0x00};
+static unsigned char symbol12_30_bits[] = {
+0x00};
+static unsigned char symbol12_31_bits[] = {
+0x00};
+static unsigned char symbol12_32_bits[] = {
+0x00};
+static unsigned char symbol12_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01};
+static unsigned char symbol12_34_bits[] = {
+0x01, 0x01, 0x82, 0x00, 0x82, 0x00, 0x7c, 0x00, 0x44, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char symbol12_35_bits[] = {
+0x14, 0x14, 0x14, 0x3f, 0x0a, 0x1f, 0x0a, 0x0a, 0x0a};
+static unsigned char symbol12_36_bits[] = {
+0x1f, 0x10, 0x10, 0x10, 0x1f, 0x10, 0x10, 0x10, 0x1f};
+static unsigned char symbol12_37_bits[] = {
+0x9e, 0x00, 0xe9, 0x00, 0x49, 0x00, 0x26, 0x00, 0x10, 0x00, 0xc8, 0x00, 
+0x28, 0x01, 0x24, 0x01, 0xc6, 0x00};
+static unsigned char symbol12_38_bits[] = {
+0x0c, 0x00, 0x12, 0x00, 0x12, 0x00, 0xec, 0x00, 0x4e, 0x00, 0x59, 0x00, 
+0x31, 0x00, 0x31, 0x01, 0xce, 0x00};
+static unsigned char symbol12_39_bits[] = {
+0x07, 0x08, 0x0f, 0x08, 0x08, 0x07};
+static unsigned char symbol12_40_bits[] = {
+0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x04};
+static unsigned char symbol12_41_bits[] = {
+0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01};
+static unsigned char symbol12_42_bits[] = {
+0x04, 0x15, 0x0e, 0x15, 0x04};
+static unsigned char symbol12_43_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x04};
+static unsigned char symbol12_44_bits[] = {
+0x02, 0x02, 0x01};
+static unsigned char symbol12_45_bits[] = {
+0x1f};
+static unsigned char symbol12_46_bits[] = {
+0x01};
+static unsigned char symbol12_47_bits[] = {
+0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01};
+static unsigned char symbol12_48_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char symbol12_49_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char symbol12_50_bits[] = {
+0x0e, 0x11, 0x11, 0x10, 0x08, 0x04, 0x02, 0x11, 0x1f};
+static unsigned char symbol12_51_bits[] = {
+0x0e, 0x11, 0x11, 0x10, 0x0c, 0x10, 0x10, 0x11, 0x0e};
+static unsigned char symbol12_52_bits[] = {
+0x18, 0x14, 0x14, 0x12, 0x12, 0x11, 0x3f, 0x10, 0x10};
+static unsigned char symbol12_53_bits[] = {
+0x1e, 0x02, 0x01, 0x0f, 0x18, 0x10, 0x10, 0x11, 0x0f};
+static unsigned char symbol12_54_bits[] = {
+0x1c, 0x02, 0x01, 0x0d, 0x13, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char symbol12_55_bits[] = {
+0x1f, 0x11, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x02};
+static unsigned char symbol12_56_bits[] = {
+0x0e, 0x11, 0x11, 0x13, 0x0e, 0x19, 0x11, 0x11, 0x0e};
+static unsigned char symbol12_57_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x1e, 0x08, 0x08, 0x04, 0x02};
+static unsigned char symbol12_58_bits[] = {
+0x01, 0x00, 0x00, 0x00, 0x00, 0x01};
+static unsigned char symbol12_59_bits[] = {
+0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01};
+static unsigned char symbol12_60_bits[] = {
+0x30, 0x0c, 0x03, 0x0c, 0x30};
+static unsigned char symbol12_61_bits[] = {
+0x1f, 0x00, 0x1f};
+static unsigned char symbol12_62_bits[] = {
+0x03, 0x0c, 0x30, 0x0c, 0x03};
+static unsigned char symbol12_63_bits[] = {
+0x0e, 0x11, 0x11, 0x10, 0x08, 0x04, 0x04, 0x00, 0x04};
+static unsigned char symbol12_64_bits[] = {
+0x16, 0x0d, 0x00, 0x1f, 0x00, 0x1f};
+static unsigned char symbol12_65_bits[] = {
+0x10, 0x00, 0x38, 0x00, 0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 
+0x44, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char symbol12_66_bits[] = {
+0x3f, 0x62, 0x42, 0x62, 0x3e, 0x62, 0x42, 0x62, 0x3f};
+static unsigned char symbol12_67_bits[] = {
+0xe7, 0x42, 0x24, 0x18, 0x18, 0x24, 0x24, 0x42, 0xe7};
+static unsigned char symbol12_68_bits[] = {
+0x08, 0x08, 0x14, 0x14, 0x22, 0x22, 0x22, 0x41, 0x7f};
+static unsigned char symbol12_69_bits[] = {
+0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 0x7f};
+static unsigned char symbol12_70_bits[] = {
+0x38, 0x00, 0x10, 0x00, 0xfe, 0x00, 0x93, 0x01, 0x11, 0x01, 0x93, 0x01, 
+0xfe, 0x00, 0x10, 0x00, 0x38, 0x00};
+static unsigned char symbol12_71_bits[] = {
+0x7f, 0x42, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char symbol12_72_bits[] = {
+0xe7, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0xe7};
+static unsigned char symbol12_73_bits[] = {
+0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char symbol12_74_bits[] = {
+0x20, 0x50, 0x50, 0x66, 0xc5, 0x44, 0x44, 0x64, 0x38};
+static unsigned char symbol12_75_bits[] = {
+0x77, 0x22, 0x12, 0x0a, 0x0e, 0x12, 0x22, 0x42, 0xe7};
+static unsigned char symbol12_76_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char symbol12_77_bits[] = {
+0x07, 0x07, 0x06, 0x03, 0x8a, 0x02, 0x8a, 0x02, 0x8a, 0x02, 0x52, 0x02, 
+0x52, 0x02, 0x22, 0x02, 0x27, 0x07};
+static unsigned char symbol12_78_bits[] = {
+0xe7, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x62, 0x47};
+static unsigned char symbol12_79_bits[] = {
+0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char symbol12_80_bits[] = {
+0xff, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0xe7};
+static unsigned char symbol12_81_bits[] = {
+0x3c, 0x66, 0x42, 0xa5, 0xbd, 0xa5, 0x42, 0x66, 0x3c};
+static unsigned char symbol12_82_bits[] = {
+0x1f, 0x32, 0x22, 0x32, 0x1e, 0x02, 0x02, 0x02, 0x07};
+static unsigned char symbol12_83_bits[] = {
+0x3f, 0x21, 0x03, 0x06, 0x0c, 0x04, 0x02, 0x41, 0x7f};
+static unsigned char symbol12_84_bits[] = {
+0x7f, 0x49, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c};
+static unsigned char symbol12_85_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x38, 0x00};
+static unsigned char symbol12_86_bits[] = {
+0x1e, 0x01, 0x01, 0x01, 0x03, 0x0e, 0x10, 0x12, 0x0e};
+static unsigned char symbol12_87_bits[] = {
+0x78, 0x00, 0xcc, 0x00, 0x84, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 
+0x84, 0x00, 0x49, 0x02, 0xcf, 0x03};
+static unsigned char symbol12_88_bits[] = {
+0x7e, 0x42, 0x00, 0x24, 0x3c, 0x24, 0x00, 0x81, 0xff};
+static unsigned char symbol12_89_bits[] = {
+0xbb, 0x01, 0x92, 0x00, 0x92, 0x00, 0xd6, 0x00, 0x7c, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x38, 0x00};
+static unsigned char symbol12_90_bits[] = {
+0x3f, 0x21, 0x10, 0x08, 0x04, 0x04, 0x02, 0x21, 0x3f};
+static unsigned char symbol12_91_bits[] = {
+0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07};
+static unsigned char symbol12_92_bits[] = {
+0x08, 0x08, 0x00, 0x00, 0x41, 0x41};
+static unsigned char symbol12_93_bits[] = {
+0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07};
+static unsigned char symbol12_94_bits[] = {
+0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f};
+static unsigned char symbol12_95_bits[] = {
+0x3f};
+static unsigned char symbol12_96_bits[] = {
+0x7f};
+static unsigned char symbol12_97_bits[] = {
+0x2e, 0x2b, 0x11, 0x11, 0x2b, 0x66};
+static unsigned char symbol12_98_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x0d, 0x11, 0x11, 0x11, 0x13, 0x0d, 0x01, 0x01, 
+0x01};
+static unsigned char symbol12_99_bits[] = {
+0x63, 0x35, 0x14, 0x18, 0x0c, 0x14, 0x16, 0x52, 0x63};
+static unsigned char symbol12_100_bits[] = {
+0x0e, 0x19, 0x01, 0x02, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char symbol12_101_bits[] = {
+0x0e, 0x01, 0x07, 0x01, 0x09, 0x0e};
+static unsigned char symbol12_102_bits[] = {
+0x08, 0x08, 0x1c, 0x2a, 0x49, 0x49, 0x2a, 0x1c, 0x08, 0x08, 0x08};
+static unsigned char symbol12_103_bits[] = {
+0x23, 0x25, 0x24, 0x24, 0x14, 0x18, 0x08, 0x0c, 0x04};
+static unsigned char symbol12_104_bits[] = {
+0x36, 0x4d, 0x44, 0x44, 0x44, 0x44, 0x40, 0x40, 0x40};
+static unsigned char symbol12_105_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x02, 0x06};
+static unsigned char symbol12_106_bits[] = {
+0x18, 0x2a, 0x49, 0x49, 0x2a, 0x1c, 0x08, 0x08, 0x08};
+static unsigned char symbol12_107_bits[] = {
+0x32, 0x2b, 0x06, 0x0e, 0x1a, 0x32};
+static unsigned char symbol12_108_bits[] = {
+0x06, 0x0a, 0x08, 0x0c, 0x14, 0x12, 0x12, 0x51, 0x61};
+static unsigned char symbol12_109_bits[] = {
+0x11, 0x11, 0x11, 0x11, 0x59, 0x37, 0x01, 0x01, 0x03};
+static unsigned char symbol12_110_bits[] = {
+0x33, 0x22, 0x22, 0x14, 0x14, 0x0c};
+static unsigned char symbol12_111_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char symbol12_112_bits[] = {
+0x7e, 0x25, 0x24, 0x24, 0x64, 0x26};
+static unsigned char symbol12_113_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char symbol12_114_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x13, 0x0d, 0x01, 0x01, 0x01};
+static unsigned char symbol12_115_bits[] = {
+0x3e, 0x09, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char symbol12_116_bits[] = {
+0x1e, 0x05, 0x04, 0x04, 0x14, 0x0c};
+static unsigned char symbol12_117_bits[] = {
+0x26, 0x45, 0x44, 0x44, 0x64, 0x38};
+static unsigned char symbol12_118_bits[] = {
+0xfe, 0x45, 0x92, 0x92, 0x92, 0x92, 0x6c};
+static unsigned char symbol12_119_bits[] = {
+0x22, 0x49, 0x49, 0x49, 0x49, 0x36};
+static unsigned char symbol12_120_bits[] = {
+0x02, 0x01, 0x0e, 0x03, 0x01, 0x0f, 0x02, 0x01, 0x01, 0x03, 0x0e, 0x10, 
+0x12, 0x0e};
+static unsigned char symbol12_121_bits[] = {
+0x11, 0x01, 0x92, 0x00, 0x92, 0x00, 0x92, 0x00, 0xd6, 0x00, 0x7c, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char symbol12_122_bits[] = {
+0x02, 0x19, 0x0e, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x0e, 0x10, 0x12, 
+0x0e};
+static unsigned char symbol12_123_bits[] = {
+0x18, 0x04, 0x04, 0x04, 0x02, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 0x18};
+static unsigned char symbol12_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_125_bits[] = {
+0x03, 0x04, 0x04, 0x04, 0x08, 0x10, 0x08, 0x04, 0x04, 0x04, 0x04, 0x03};
+static unsigned char symbol12_126_bits[] = {
+0x46, 0x49, 0x31};
+static unsigned char symbol12_127_bits[] = {
+0x00};
+static unsigned char symbol12_128_bits[] = {
+0x00};
+static unsigned char symbol12_129_bits[] = {
+0x00};
+static unsigned char symbol12_130_bits[] = {
+0x00};
+static unsigned char symbol12_131_bits[] = {
+0x00};
+static unsigned char symbol12_132_bits[] = {
+0x00};
+static unsigned char symbol12_133_bits[] = {
+0x00};
+static unsigned char symbol12_134_bits[] = {
+0x00};
+static unsigned char symbol12_135_bits[] = {
+0x00};
+static unsigned char symbol12_136_bits[] = {
+0x00};
+static unsigned char symbol12_137_bits[] = {
+0x00};
+static unsigned char symbol12_138_bits[] = {
+0x00};
+static unsigned char symbol12_139_bits[] = {
+0x00};
+static unsigned char symbol12_140_bits[] = {
+0x00};
+static unsigned char symbol12_141_bits[] = {
+0x00};
+static unsigned char symbol12_142_bits[] = {
+0x00};
+static unsigned char symbol12_143_bits[] = {
+0x00};
+static unsigned char symbol12_144_bits[] = {
+0x00};
+static unsigned char symbol12_145_bits[] = {
+0x00};
+static unsigned char symbol12_146_bits[] = {
+0x00};
+static unsigned char symbol12_147_bits[] = {
+0x00};
+static unsigned char symbol12_148_bits[] = {
+0x00};
+static unsigned char symbol12_149_bits[] = {
+0x00};
+static unsigned char symbol12_150_bits[] = {
+0x00};
+static unsigned char symbol12_151_bits[] = {
+0x00};
+static unsigned char symbol12_152_bits[] = {
+0x00};
+static unsigned char symbol12_153_bits[] = {
+0x00};
+static unsigned char symbol12_154_bits[] = {
+0x00};
+static unsigned char symbol12_155_bits[] = {
+0x00};
+static unsigned char symbol12_156_bits[] = {
+0x00};
+static unsigned char symbol12_157_bits[] = {
+0x00};
+static unsigned char symbol12_158_bits[] = {
+0x00};
+static unsigned char symbol12_159_bits[] = {
+0x00};
+static unsigned char symbol12_160_bits[] = {
+0x00};
+static unsigned char symbol12_161_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_162_bits[] = {
+0x00, 0x00, 0x00};
+static unsigned char symbol12_163_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_164_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_165_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00};
+static unsigned char symbol12_166_bits[] = {
+0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x04, 0x02, 0x01, 0x30, 0x0c};
+static unsigned char symbol12_167_bits[] = {
+0x03, 0x0c, 0x30, 0x00, 0x3f, 0x10, 0x08};
+static unsigned char symbol12_168_bits[] = {
+0x08, 0x04, 0x04, 0x02, 0x02, 0x01};
+static unsigned char symbol12_169_bits[] = {
+0x01, 0x6e, 0x00, 0x19, 0x01, 0x31};
+static unsigned char symbol12_170_bits[] = {
+0x01, 0x6e, 0x00, 0x30, 0x28, 0x08, 0x3e};
+static unsigned char symbol12_171_bits[] = {
+0x08, 0x00, 0x08, 0x04, 0x04, 0x04, 0x05, 0x03, 0x1c, 0x04};
+static unsigned char symbol12_172_bits[] = {
+0x6b, 0x0f, 0x6b, 0x08, 0x08, 0x04, 0x0e, 0x0f, 0x1f, 0x0e};
+static unsigned char symbol12_173_bits[] = {
+0x04, 0x16, 0x1f, 0x1f, 0x1e, 0x1c, 0x08, 0x08, 0x1c, 0x1e, 0x1f, 0x0b, 
+0x08, 0x08, 0x04, 0x01};
+static unsigned char symbol12_174_bits[] = {
+0x02, 0x02, 0xff, 0x07, 0x02, 0x02, 0x04, 0x01, 0x04, 0x00};
+static unsigned char symbol12_175_bits[] = {
+0x02, 0x00, 0x1f, 0x0f, 0x02, 0x00, 0x04, 0x00, 0x04, 0x0e, 0x15, 0x04, 
+0x04, 0x04, 0x04};
+static unsigned char symbol12_176_bits[] = {
+0x04, 0x04, 0x04, 0x04};
+static unsigned char symbol12_177_bits[] = {
+0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x02};
+static unsigned char symbol12_178_bits[] = {
+0x00, 0x04, 0x1f};
+static unsigned char symbol12_179_bits[] = {
+0x0f, 0x00, 0x04, 0x00, 0x02, 0x04, 0x04};
+static unsigned char symbol12_180_bits[] = {
+0x04, 0x04, 0x04, 0x04, 0x04};
+static unsigned char symbol12_181_bits[] = {
+0x04, 0x04, 0x04, 0x04};
+static unsigned char symbol12_182_bits[] = {
+0x04, 0x15, 0x0e, 0x04, 0x06, 0x09, 0x09, 0x06, 0x04, 0x04};
+static unsigned char symbol12_183_bits[] = {
+0x0f, 0x04, 0x04, 0x00};
+static unsigned char symbol12_184_bits[] = {
+0x1f, 0x14, 0x0a, 0x05, 0x03};
+static unsigned char symbol12_185_bits[] = {
+0x0c, 0x10, 0x0c, 0x03, 0x00, 0x1f, 0x11};
+static unsigned char symbol12_186_bits[] = {
+0x0a, 0x04, 0x0a, 0x11, 0x0e};
+static unsigned char symbol12_187_bits[] = {
+0x11, 0x11, 0x2e, 0x06, 0x09};
+static unsigned char symbol12_188_bits[] = {
+0x10, 0x00};
+static unsigned char symbol12_189_bits[] = {
+0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 
+0x01, 0x00, 0x00, 0x00};
+static unsigned char symbol12_190_bits[] = {
+0x08, 0x1f};
+static unsigned char symbol12_191_bits[] = {
+0x04, 0x1f, 0x02, 0x01, 0x1f, 0x00, 0x1f, 0x00};
+static unsigned char symbol12_192_bits[] = {
+0x1f, 0x26, 0x19, 0x00, 0x26, 0x19, 0x11, 0x01, 0x01};
+static unsigned char symbol12_193_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_194_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0xff, 0x01, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 
+0x7f, 0x00, 0x11, 0x01, 0x66, 0x00, 0x2b, 0x01};
+static unsigned char symbol12_195_bits[] = {
+0x32, 0x66, 0x47, 0xfc, 0x86, 0x42, 0x26, 0x30, 0x60, 0xc0, 0x80};
+static unsigned char symbol12_196_bits[] = {
+0x86, 0x01, 0x38, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_197_bits[] = {
+0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x64, 0x00, 0x89, 0x01, 0xd5, 0x01, 
+0x26, 0x01, 0x09, 0x00, 0x38, 0x00};
+static unsigned char symbol12_198_bits[] = {
+0xc6, 0x00, 0xc6, 0x00, 0x29, 0x01, 0x11, 0x01, 0x29, 0x01, 0xc6, 0x00, 
+0xc6, 0x00, 0x38, 0x00, 0x38, 0x00};
+static unsigned char symbol12_199_bits[] = {
+0xc6, 0x00, 0x92, 0x00, 0x11, 0x01};
+static unsigned char symbol12_200_bits[] = {
+0x7d, 0x01, 0x11, 0x01, 0x92, 0x00};
+static unsigned char symbol12_201_bits[] = {
+0xc6, 0x00, 0x38, 0x00, 0x38, 0x01};
+static unsigned char symbol12_202_bits[] = {
+0xc6, 0x00, 0xc2, 0x00, 0x21, 0x01, 0x11, 0x01};
+static unsigned char symbol12_203_bits[] = {
+0x09, 0x01, 0x86, 0x00, 0xc6, 0x00, 0x39, 0x00};
+static unsigned char symbol12_204_bits[] = {
+0x3c, 0x42, 0x81, 0x81, 0x81, 0x81};
+static unsigned char symbol12_205_bits[] = {
+0x81, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x3f, 0x40};
+static unsigned char symbol12_206_bits[] = {
+0x00, 0x00, 0x00, 0x3f, 0x3f, 0x00};
+static unsigned char symbol12_207_bits[] = {
+0x00, 0x00, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3c};
+static unsigned char symbol12_208_bits[] = {
+0x22, 0x01, 0x11, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x01, 0x01, 0x02, 0x00, 
+0xfc, 0x00, 0x01, 0x01, 0x02, 0x00};
+static unsigned char symbol12_209_bits[] = {
+0x00, 0xff, 0x3e, 0x01, 0x3f, 0x01, 0x01, 0x3e, 0x20};
+static unsigned char symbol12_210_bits[] = {
+0x3e, 0x11, 0x3f, 0x09, 0x05, 0x3e, 0x02, 0x00, 0x01};
+static unsigned char symbol12_211_bits[] = {
+0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08};
+static unsigned char symbol12_212_bits[] = {
+0x00, 0x04, 0x00, 0x02, 0x00, 0x07, 0x01, 0x07, 0x81, 0x02, 0x42, 0x04};
+static unsigned char symbol12_213_bits[] = {
+0x24, 0x00, 0x18, 0x00, 0x3c, 0x00, 0x9f, 0x01, 0x9d, 0x01, 0xb7, 0x00, 
+0x3c, 0x00, 0x42, 0x01, 0x95, 0x01, 0xa5, 0x01, 0x42, 0x00};
+static unsigned char symbol12_214_bits[] = {
+0x5f, 0x01, 0x55, 0x01, 0x24, 0x02, 0x24, 0x02, 0x24, 0x02, 0x6e, 0x06};
+static unsigned char symbol12_215_bits[] = {
+0x03};
+static unsigned char symbol12_216_bits[] = {
+0x01, 0x02, 0x00, 0x02};
+static unsigned char symbol12_217_bits[] = {
+0x00, 0x02, 0x00, 0x02, 0x00, 0x02};
+static unsigned char symbol12_218_bits[] = {
+0x00, 0x02, 0x00, 0x02, 0x00, 0x02};
+static unsigned char symbol12_219_bits[] = {
+0x00, 0x02, 0x00, 0x07, 0x01, 0x00, 0x40, 0x00, 0x20, 0x00};
+static unsigned char symbol12_220_bits[] = {
+0x20, 0x06, 0x15, 0x04, 0x14, 0x00, 0x08, 0x03, 0x7f, 0x00};
+static unsigned char symbol12_221_bits[] = {
+0x00, 0x00, 0x0c, 0x0c, 0x12, 0x12, 0x01, 0x01, 0x01, 0x01, 0x12, 0x12};
+static unsigned char symbol12_222_bits[] = {
+0x0c, 0x04, 0x04, 0x01, 0xfe, 0x03, 0x03, 0x06, 0xfe, 0x03};
+static unsigned char symbol12_223_bits[] = {
+0x04, 0x01, 0x04, 0x00, 0x1e, 0x07, 0x03, 0x00, 0x1e, 0x07, 0x04, 0x00};
+static unsigned char symbol12_224_bits[] = {
+0x04, 0x0e, 0x1b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a};
+static unsigned char symbol12_225_bits[] = {
+0x0a, 0x0a, 0x0a, 0x00, 0x01, 0x0f, 0x03, 0x00, 0x06, 0x0f, 0x03};
+static unsigned char symbol12_226_bits[] = {
+0x00, 0x01, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a};
+static unsigned char symbol12_227_bits[] = {
+0x0a, 0x0a, 0x1b, 0x0e, 0x04, 0x0c, 0x0c, 0x12, 0x21};
+static unsigned char symbol12_228_bits[] = {
+0x21, 0x02, 0x12, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x02, 0x02, 0x01, 0x02};
+static unsigned char symbol12_229_bits[] = {
+0x02, 0x04, 0x04, 0x08, 0x3c, 0x42, 0x9d, 0xa5, 0x9d, 0xa5, 0xa5};
+static unsigned char symbol12_230_bits[] = {
+0x02, 0x0c, 0x0c, 0x02, 0x09, 0x05, 0x05, 0x05, 0x09, 0x02, 0x0c, 0x0f, 
+0x01, 0x04, 0x01, 0x04};
+static unsigned char symbol12_231_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_232_bits[] = {
+0x01, 0x0f, 0x08, 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_233_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_234_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_235_bits[] = {
+0x04, 0x00, 0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01};
+static unsigned char symbol12_236_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_237_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_238_bits[] = {
+0x01, 0x07, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01};
+static unsigned char symbol12_239_bits[] = {
+0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 
+0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_240_bits[] = {
+0x00};
+static unsigned char symbol12_241_bits[] = {
+0x04, 0x04, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_242_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01};
+static unsigned char symbol12_243_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x02, 0x02, 0x04, 
+0x04, 0x08, 0x08, 0x04};
+static unsigned char symbol12_244_bits[] = {
+0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_245_bits[] = {
+0x04, 0x05, 0x03, 0x1c, 0x1a, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01};
+static unsigned char symbol12_246_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_247_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_248_bits[] = {
+0x00, 0x0b, 0x07, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x08};
+static unsigned char symbol12_249_bits[] = {
+0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_250_bits[] = {
+0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_251_bits[] = {
+0x02, 0x02, 0x01, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x04};
+static unsigned char symbol12_252_bits[] = {
+0x04, 0x04, 0x04, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_253_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x04, 0x04};
+static unsigned char symbol12_254_bits[] = {
+0x04, 0x04, 0x07, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x04};
+static unsigned char symbol12_255_bits[] = {
+0x00};
+static RotFont symbol12font[] = {
+{5, 1, 1, symbol12_0_bits},
+{5, 1, 1, symbol12_1_bits},
+{5, 1, 1, symbol12_2_bits},
+{5, 1, 1, symbol12_3_bits},
+{5, 1, 1, symbol12_4_bits},
+{5, 1, 1, symbol12_5_bits},
+{5, 1, 1, symbol12_6_bits},
+{5, 1, 1, symbol12_7_bits},
+{5, 1, 1, symbol12_8_bits},
+{5, 1, 1, symbol12_9_bits},
+{5, 1, 1, symbol12_10_bits},
+{5, 1, 1, symbol12_11_bits},
+{5, 1, 1, symbol12_12_bits},
+{5, 1, 1, symbol12_13_bits},
+{5, 1, 1, symbol12_14_bits},
+{5, 1, 1, symbol12_15_bits},
+{5, 1, 1, symbol12_16_bits},
+{5, 1, 1, symbol12_17_bits},
+{5, 1, 1, symbol12_18_bits},
+{5, 1, 1, symbol12_19_bits},
+{5, 1, 1, symbol12_20_bits},
+{5, 1, 1, symbol12_21_bits},
+{5, 1, 1, symbol12_22_bits},
+{5, 1, 1, symbol12_23_bits},
+{5, 1, 1, symbol12_24_bits},
+{5, 1, 1, symbol12_25_bits},
+{5, 1, 1, symbol12_26_bits},
+{5, 1, 1, symbol12_27_bits},
+{5, 1, 1, symbol12_28_bits},
+{5, 1, 1, symbol12_29_bits},
+{5, 1, 1, symbol12_30_bits},
+{5, 1, 1, symbol12_31_bits},
+{1, 1, 1, symbol12_32_bits},
+{1, 9, 9, symbol12_33_bits},
+{9, 9, 9, symbol12_34_bits},
+{6, 9, 9, symbol12_35_bits},
+{5, 9, 9, symbol12_36_bits},
+{9, 9, 9, symbol12_37_bits},
+{9, 9, 9, symbol12_38_bits},
+{4, 6, 6, symbol12_39_bits},
+{3, 12, 9, symbol12_40_bits},
+{3, 12, 9, symbol12_41_bits},
+{5, 5, 7, symbol12_42_bits},
+{5, 5, 6, symbol12_43_bits},
+{2, 3, 1, symbol12_44_bits},
+{5, 1, 4, symbol12_45_bits},
+{1, 1, 1, symbol12_46_bits},
+{3, 9, 9, symbol12_47_bits},
+{5, 9, 9, symbol12_48_bits},
+{3, 9, 9, symbol12_49_bits},
+{5, 9, 9, symbol12_50_bits},
+{5, 9, 9, symbol12_51_bits},
+{6, 9, 9, symbol12_52_bits},
+{5, 9, 9, symbol12_53_bits},
+{5, 9, 9, symbol12_54_bits},
+{5, 9, 9, symbol12_55_bits},
+{5, 9, 9, symbol12_56_bits},
+{5, 9, 9, symbol12_57_bits},
+{1, 6, 6, symbol12_58_bits},
+{2, 8, 6, symbol12_59_bits},
+{6, 5, 6, symbol12_60_bits},
+{5, 3, 5, symbol12_61_bits},
+{6, 5, 6, symbol12_62_bits},
+{5, 9, 9, symbol12_63_bits},
+{5, 6, 6, symbol12_64_bits},
+{9, 9, 9, symbol12_65_bits},
+{7, 9, 9, symbol12_66_bits},
+{8, 9, 9, symbol12_67_bits},
+{7, 9, 9, symbol12_68_bits},
+{7, 9, 9, symbol12_69_bits},
+{9, 9, 9, symbol12_70_bits},
+{7, 9, 9, symbol12_71_bits},
+{8, 9, 9, symbol12_72_bits},
+{3, 9, 9, symbol12_73_bits},
+{8, 9, 9, symbol12_74_bits},
+{8, 9, 9, symbol12_75_bits},
+{9, 9, 9, symbol12_76_bits},
+{11, 9, 9, symbol12_77_bits},
+{8, 9, 9, symbol12_78_bits},
+{8, 9, 9, symbol12_79_bits},
+{8, 9, 9, symbol12_80_bits},
+{8, 9, 9, symbol12_81_bits},
+{6, 9, 9, symbol12_82_bits},
+{7, 9, 9, symbol12_83_bits},
+{7, 9, 9, symbol12_84_bits},
+{9, 9, 9, symbol12_85_bits},
+{5, 9, 6, symbol12_86_bits},
+{10, 9, 9, symbol12_87_bits},
+{8, 9, 9, symbol12_88_bits},
+{9, 9, 9, symbol12_89_bits},
+{6, 9, 9, symbol12_90_bits},
+{3, 12, 9, symbol12_91_bits},
+{7, 6, 6, symbol12_92_bits},
+{3, 12, 9, symbol12_93_bits},
+{7, 9, 9, symbol12_94_bits},
+{6, 1, -2, symbol12_95_bits},
+{7, 1, 12, symbol12_96_bits},
+{7, 6, 6, symbol12_97_bits},
+{5, 13, 10, symbol12_98_bits},
+{7, 9, 6, symbol12_99_bits},
+{5, 10, 10, symbol12_100_bits},
+{4, 6, 6, symbol12_101_bits},
+{7, 11, 8, symbol12_102_bits},
+{6, 9, 6, symbol12_103_bits},
+{7, 9, 6, symbol12_104_bits},
+{3, 6, 6, symbol12_105_bits},
+{7, 9, 6, symbol12_106_bits},
+{6, 6, 6, symbol12_107_bits},
+{7, 9, 9, symbol12_108_bits},
+{7, 9, 6, symbol12_109_bits},
+{6, 6, 6, symbol12_110_bits},
+{5, 6, 6, symbol12_111_bits},
+{7, 6, 6, symbol12_112_bits},
+{5, 9, 9, symbol12_113_bits},
+{5, 9, 6, symbol12_114_bits},
+{6, 6, 6, symbol12_115_bits},
+{5, 6, 6, symbol12_116_bits},
+{7, 6, 6, symbol12_117_bits},
+{8, 7, 7, symbol12_118_bits},
+{7, 6, 6, symbol12_119_bits},
+{5, 14, 11, symbol12_120_bits},
+{9, 9, 6, symbol12_121_bits},
+{5, 13, 10, symbol12_122_bits},
+{5, 12, 9, symbol12_123_bits},
+{1, 12, 9, symbol12_124_bits},
+{5, 12, 9, symbol12_125_bits},
+{7, 3, 5, symbol12_126_bits},
+{5, 1, 1, symbol12_127_bits},
+{5, 1, 1, symbol12_128_bits},
+{5, 1, 1, symbol12_129_bits},
+{5, 1, 1, symbol12_130_bits},
+{5, 1, 1, symbol12_131_bits},
+{5, 1, 1, symbol12_132_bits},
+{5, 1, 1, symbol12_133_bits},
+{5, 1, 1, symbol12_134_bits},
+{5, 1, 1, symbol12_135_bits},
+{5, 1, 1, symbol12_136_bits},
+{5, 1, 1, symbol12_137_bits},
+{5, 1, 1, symbol12_138_bits},
+{5, 1, 1, symbol12_139_bits},
+{5, 1, 1, symbol12_140_bits},
+{5, 1, 1, symbol12_141_bits},
+{5, 1, 1, symbol12_142_bits},
+{5, 1, 1, symbol12_143_bits},
+{5, 1, 1, symbol12_144_bits},
+{5, 1, 1, symbol12_145_bits},
+{5, 1, 1, symbol12_146_bits},
+{5, 1, 1, symbol12_147_bits},
+{5, 1, 1, symbol12_148_bits},
+{5, 1, 1, symbol12_149_bits},
+{5, 1, 1, symbol12_150_bits},
+{5, 1, 1, symbol12_151_bits},
+{5, 1, 1, symbol12_152_bits},
+{5, 1, 1, symbol12_153_bits},
+{5, 1, 1, symbol12_154_bits},
+{5, 1, 1, symbol12_155_bits},
+{5, 1, 1, symbol12_156_bits},
+{5, 1, 1, symbol12_157_bits},
+{5, 1, 1, symbol12_158_bits},
+{5, 1, 1, symbol12_159_bits},
+{5, 1, 1, symbol12_160_bits},
+{8, 9, 9, symbol12_161_bits},
+{3, 3, 9, symbol12_162_bits},
+{6, 7, 7, symbol12_163_bits},
+{5, 9, 9, symbol12_164_bits},
+{9, 4, 5, symbol12_165_bits},
+{6, 12, 9, symbol12_166_bits},
+{7, 7, 6, symbol12_167_bits},
+{5, 6, 6, symbol12_168_bits},
+{7, 6, 6, symbol12_169_bits},
+{7, 7, 6, symbol12_170_bits},
+{11, 5, 6, symbol12_171_bits},
+{12, 5, 6, symbol12_172_bits},
+{5, 16, 12, symbol12_173_bits},
+{12, 5, 6, symbol12_174_bits},
+{5, 15, 12, symbol12_175_bits},
+{4, 4, 9, symbol12_176_bits},
+{5, 7, 7, symbol12_177_bits},
+{5, 3, 9, symbol12_178_bits},
+{6, 7, 7, symbol12_179_bits},
+{5, 5, 6, symbol12_180_bits},
+{8, 4, 5, symbol12_181_bits},
+{5, 10, 10, symbol12_182_bits},
+{4, 4, 5, symbol12_183_bits},
+{5, 5, 6, symbol12_184_bits},
+{5, 7, 7, symbol12_185_bits},
+{5, 5, 6, symbol12_186_bits},
+{6, 5, 6, symbol12_187_bits},
+{9, 1, 1, symbol12_188_bits},
+{1, 16, 12, symbol12_189_bits},
+{13, 1, 4, symbol12_190_bits},
+{7, 8, 8, symbol12_191_bits},
+{7, 9, 9, symbol12_192_bits},
+{8, 11, 10, symbol12_193_bits},
+{9, 10, 10, symbol12_194_bits},
+{8, 11, 8, symbol12_195_bits},
+{9, 9, 9, symbol12_196_bits},
+{9, 9, 9, symbol12_197_bits},
+{9, 9, 9, symbol12_198_bits},
+{8, 6, 6, symbol12_199_bits},
+{8, 6, 6, symbol12_200_bits},
+{8, 6, 6, symbol12_201_bits},
+{8, 8, 6, symbol12_202_bits},
+{8, 8, 7, symbol12_203_bits},
+{8, 6, 6, symbol12_204_bits},
+{8, 8, 6, symbol12_205_bits},
+{6, 6, 6, symbol12_206_bits},
+{6, 8, 7, symbol12_207_bits},
+{9, 9, 9, symbol12_208_bits},
+{8, 9, 9, symbol12_209_bits},
+{8, 9, 9, symbol12_210_bits},
+{8, 9, 9, symbol12_211_bits},
+{11, 6, 9, symbol12_212_bits},
+{9, 11, 10, symbol12_213_bits},
+{7, 12, 12, symbol12_214_bits},
+{2, 1, 4, symbol12_215_bits},
+{7, 4, 4, symbol12_216_bits},
+{6, 6, 6, symbol12_217_bits},
+{6, 6, 6, symbol12_218_bits},
+{11, 5, 6, symbol12_219_bits},
+{11, 5, 6, symbol12_220_bits},
+{5, 12, 11, symbol12_221_bits},
+{11, 5, 6, symbol12_222_bits},
+{5, 12, 12, symbol12_223_bits},
+{6, 9, 9, symbol12_224_bits},
+{4, 11, 10, symbol12_225_bits},
+{8, 9, 9, symbol12_226_bits},
+{8, 9, 9, symbol12_227_bits},
+{10, 6, 9, symbol12_228_bits},
+{8, 11, 10, symbol12_229_bits},
+{4, 16, 12, symbol12_230_bits},
+{1, 16, 12, symbol12_231_bits},
+{4, 16, 12, symbol12_232_bits},
+{3, 16, 12, symbol12_233_bits},
+{1, 16, 12, symbol12_234_bits},
+{3, 15, 12, symbol12_235_bits},
+{3, 16, 12, symbol12_236_bits},
+{3, 16, 12, symbol12_237_bits},
+{3, 15, 12, symbol12_238_bits},
+{1, 16, 12, symbol12_239_bits},
+{5, 1, 1, symbol12_240_bits},
+{4, 12, 10, symbol12_241_bits},
+{5, 15, 12, symbol12_242_bits},
+{5, 16, 12, symbol12_243_bits},
+{1, 16, 12, symbol12_244_bits},
+{5, 15, 12, symbol12_245_bits},
+{4, 16, 12, symbol12_246_bits},
+{1, 16, 12, symbol12_247_bits},
+{4, 16, 12, symbol12_248_bits},
+{3, 16, 12, symbol12_249_bits},
+{1, 16, 12, symbol12_250_bits},
+{3, 15, 12, symbol12_251_bits},
+{3, 16, 12, symbol12_252_bits},
+{3, 16, 12, symbol12_253_bits},
+{3, 15, 12, symbol12_254_bits},
+{5, 1, 1, symbol12_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/symbol14.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/symbol14.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/symbol14.bdf	(revision 12606)
@@ -0,0 +1,3274 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Symbol-Medium-R-Normal--14-140-75-75-P-85-Adobe-FontSpecific
+SIZE 14 75 75
+FONTBOUNDINGBOX 16 20 -1 -6
+STARTPROPERTIES 31
+FOUNDRY "Adobe"
+FAMILY_NAME "Symbol"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 14
+POINT_SIZE 140
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 85
+CHARSET_REGISTRY "Adobe"
+CHARSET_ENCODING "FontSpecific"
+CAP_HEIGHT 10
+X_HEIGHT 7
+FACE_NAME "Symbol"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "No mark"
+_DEC_DEVICE_FONTNAMES "PS=Symbol"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2-1, 18-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+FULL_NAME "Symbol"
+FONT "-Adobe-Symbol-Medium-R-Normal--14-140-75-75-P-85-Adobe-FontSpecific"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 9
+DEFAULT_CHAR 32
+FONT_ASCENT 12
+FONT_DESCENT 3
+ENDPROPERTIES
+CHARS 188
+STARTCHAR space
+ENCODING 32
+SWIDTH 274 0
+DWIDTH 4 0
+BBX 1 1 1 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 342 0
+DWIDTH 5 0
+BBX 1 10 2 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+00
+80
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+8080
+4100
+4100
+3e00
+2200
+2200
+1400
+1400
+0800
+0800
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+14
+14
+14
+7e
+28
+28
+fc
+50
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 6 10 1 0
+BITMAP
+fc
+04
+04
+04
+fc
+04
+04
+04
+04
+fc
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 9 10 1 0
+BITMAP
+7980
+9700
+9200
+9400
+6c00
+1b00
+1480
+2480
+4480
+c300
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+3000
+4800
+4800
+7000
+2700
+7200
+ca00
+8400
+ce80
+7b00
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+e0
+10
+08
+78
+08
+10
+e0
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 342 0
+DWIDTH 5 0
+BBX 3 13 1 -3
+BITMAP
+20
+40
+40
+80
+80
+80
+80
+80
+80
+80
+40
+40
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 342 0
+DWIDTH 5 0
+BBX 3 13 1 -3
+BITMAP
+80
+40
+40
+20
+20
+20
+20
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 5 6 1 2
+BITMAP
+20
+a8
+70
+70
+a8
+20
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+10
+10
+10
+fe
+10
+10
+10
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 205 0
+DWIDTH 3 0
+BBX 2 4 0 -2
+BITMAP
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 1 0 3
+BITMAP
+fe
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 205 0
+DWIDTH 3 0
+BBX 1 2 1 0
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 274 0
+DWIDTH 4 0
+BBX 4 10 0 0
+BITMAP
+10
+10
+20
+20
+20
+40
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+cc
+84
+84
+84
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+20
+e0
+20
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+70
+d8
+88
+08
+18
+10
+20
+40
+c4
+fc
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+cc
+84
+0c
+38
+0c
+04
+04
+cc
+78
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+08
+18
+18
+28
+68
+48
+88
+fc
+08
+08
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+78
+40
+80
+e0
+30
+18
+08
+08
+90
+e0
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+1c
+30
+40
+40
+f8
+8c
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+fc
+84
+08
+08
+10
+10
+20
+20
+40
+40
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+70
+d8
+88
+88
+70
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+cc
+84
+84
+c4
+78
+18
+10
+60
+c0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 274 0
+DWIDTH 4 0
+BBX 1 7 2 0
+BITMAP
+80
+80
+00
+00
+00
+80
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 274 0
+DWIDTH 4 0
+BBX 2 9 1 -2
+BITMAP
+40
+40
+00
+00
+00
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 1 0
+BITMAP
+02
+0c
+30
+c0
+30
+0c
+02
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 3 0 2
+BITMAP
+fe
+00
+fe
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+80
+60
+18
+06
+18
+60
+80
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 5 10 0 0
+BITMAP
+70
+88
+88
+08
+10
+20
+20
+00
+20
+20
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+72
+9c
+00
+fe
+00
+00
+fe
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+0800
+1c00
+1400
+1400
+2200
+2200
+3e00
+6300
+4100
+e380
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+fc
+46
+42
+46
+7c
+46
+42
+42
+46
+fc
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+e380
+4100
+2200
+3600
+1c00
+1400
+2200
+6300
+4100
+e380
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+10
+10
+28
+28
+28
+44
+44
+44
+82
+fe
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+fe
+42
+40
+44
+7c
+44
+40
+42
+42
+fe
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+1c00
+0800
+7f00
+c980
+8880
+8880
+c980
+7f00
+0800
+1c00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+fe
+42
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+e380
+4100
+4100
+4100
+7f00
+4100
+4100
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 342 0
+DWIDTH 5 0
+BBX 3 10 1 0
+BITMAP
+e0
+40
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+0c
+0a
+0a
+66
+a3
+22
+22
+22
+36
+1c
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+ee
+44
+48
+50
+70
+50
+48
+44
+42
+e7
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 10 0 0
+BITMAP
+0800
+0800
+1400
+3600
+2200
+2200
+6300
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 891 0
+DWIDTH 13 0
+BBX 11 10 1 0
+BITMAP
+e0e0
+60c0
+5140
+5140
+5b40
+4a40
+4a40
+4e40
+4440
+e4e0
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+e380
+6100
+5100
+5900
+4900
+4d00
+4500
+4700
+4300
+e100
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+3c
+66
+42
+81
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+ff80
+4100
+4100
+4100
+4100
+4100
+4100
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+3c
+66
+42
+a5
+bd
+a5
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 6 10 1 0
+BITMAP
+f8
+4c
+44
+44
+4c
+78
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 8 10 1 0
+BITMAP
+fe
+c2
+60
+30
+18
+10
+20
+40
+c1
+ff
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+fe
+92
+92
+10
+10
+10
+10
+10
+10
+38
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+e380
+4100
+2200
+2200
+1400
+0800
+0800
+0800
+0800
+1c00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 10 1 -3
+BITMAP
+38
+c0
+80
+80
+80
+60
+38
+04
+24
+38
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 10 10 0 0
+BITMAP
+0c00
+3300
+2100
+4080
+4080
+4080
+4080
+2100
+9240
+f3c0
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+7f00
+4100
+0000
+2200
+3e00
+2200
+0000
+0000
+8080
+ff80
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 11 10 0 0
+BITMAP
+ce60
+64c0
+2480
+2480
+1f00
+0400
+0400
+0400
+0400
+0e00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+fe
+82
+04
+08
+10
+10
+20
+40
+82
+fe
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 342 0
+DWIDTH 5 0
+BBX 3 13 1 -3
+BITMAP
+e0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+e0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 8 7 1 0
+BITMAP
+18
+18
+00
+00
+00
+c3
+c3
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 342 0
+DWIDTH 5 0
+BBX 3 13 1 -3
+BITMAP
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+e0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 10 0 0
+BITMAP
+0800
+0800
+0800
+0800
+0800
+0800
+0800
+0800
+0800
+ff80
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 7 1 0 -3
+BITMAP
+fe
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 8 1 0 13
+BITMAP
+ff
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 8 7 1 0
+BITMAP
+76
+d4
+88
+88
+88
+d5
+66
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 6 14 1 -3
+BITMAP
+78
+cc
+84
+8c
+98
+8c
+84
+84
+84
+cc
+b8
+80
+80
+80
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 8 10 0 -3
+BITMAP
+c3
+a6
+24
+3c
+18
+38
+28
+64
+45
+c3
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+70
+98
+80
+40
+70
+98
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 5 7 1 0
+BITMAP
+78
+c8
+80
+60
+80
+c8
+70
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 13 1 -3
+BITMAP
+10
+10
+10
+38
+54
+92
+92
+92
+54
+38
+10
+10
+10
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 6 10 0 -3
+BITMAP
+c4
+a4
+24
+28
+28
+18
+18
+10
+30
+30
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 10 0 -3
+BITMAP
+6c
+b2
+22
+22
+22
+22
+22
+02
+02
+02
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 342 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+60
+a0
+20
+20
+20
+28
+30
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 10 1 -3
+BITMAP
+18
+54
+d2
+92
+92
+54
+38
+10
+10
+10
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+46
+ca
+50
+70
+58
+4c
+46
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 8 10 1 0
+BITMAP
+60
+50
+10
+10
+28
+28
+48
+44
+85
+83
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 9 1 -2
+BITMAP
+88
+88
+88
+88
+88
+9a
+f6
+80
+c0
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+c6
+42
+22
+22
+14
+14
+08
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 6 7 1 0
+BITMAP
+78
+cc
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 8 7 0 0
+BITMAP
+7e
+a4
+24
+24
+24
+25
+66
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+70
+d8
+88
+88
+f8
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 6 10 1 -3
+BITMAP
+78
+cc
+84
+84
+84
+cc
+b8
+80
+80
+80
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 1 0
+BITMAP
+7e
+c8
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+78
+a0
+20
+20
+20
+28
+30
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+64
+a2
+22
+22
+22
+26
+1c
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 10 8 0 0
+BITMAP
+7fc0
+a080
+4440
+4440
+4440
+4440
+64c0
+3b80
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 7 1 0
+BITMAP
+6300
+8880
+8880
+8880
+8880
+c980
+7700
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 15 1 -3
+BITMAP
+20
+40
+38
+20
+40
+78
+20
+40
+80
+80
+c0
+78
+04
+24
+38
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 9 10 0 -3
+BITMAP
+8880
+4900
+4900
+4900
+6b00
+3e00
+0800
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 14 1 -3
+BITMAP
+20
+44
+3c
+10
+20
+40
+40
+80
+80
+c0
+78
+04
+24
+38
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+18
+20
+20
+20
+20
+40
+80
+40
+20
+20
+20
+20
+18
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 205 0
+DWIDTH 3 0
+BBX 1 13 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+c0
+20
+20
+20
+20
+10
+08
+10
+20
+20
+20
+20
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 3 1 2
+BITMAP
+62
+92
+8c
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 274 0
+DWIDTH 4 0
+BBX 4 3 0 7
+BITMAP
+00
+00
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 274 0
+DWIDTH 4 0
+BBX 5 10 -1 0
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 4 0 2
+BITMAP
+0000
+c600
+2b00
+1000
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 7 13 0 -3
+BITMAP
+10
+10
+10
+38
+30
+60
+80
+02
+0c
+30
+c0
+30
+0c
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 8 1 -1
+BITMAP
+0200
+fe00
+0800
+1000
+2000
+4080
+8000
+0080
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 7 7 2 0
+BITMAP
+80
+8c
+80
+76
+00
+06
+0a
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 7 7 2 0
+BITMAP
+08
+08
+3c
+10
+10
+10
+20
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 8 1 -1
+BITMAP
+2000
+a080
+1c00
+1c00
+1c00
+eb80
+ff80
+eb80
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 1028 0
+DWIDTH 15 0
+BBX 13 7 1 0
+BITMAP
+0800
+0800
+1038
+7cf8
+7c38
+1068
+fef8
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 960 0
+DWIDTH 14 0
+BBX 14 7 0 0
+BITMAP
+fe7c
+3810
+0800
+1c00
+3e00
+7f00
+ff80
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 20 1 -6
+BITMAP
+6a
+00
+08
+00
+08
+00
+10
+40
+20
+20
+40
+10
+fe
+f8
+40
+10
+20
+20
+10
+40
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 960 0
+DWIDTH 14 0
+BBX 14 7 0 0
+BITMAP
+1000
+2000
+4000
+fffc
+4000
+2000
+1000
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 17 1 -3
+BITMAP
+10
+38
+54
+92
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 4 4 1 6
+BITMAP
+10
+10
+10
+00
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+20
+00
+10
+00
+08
+fe
+fc
+00
+08
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 7 3 -1 7
+BITMAP
+00
+10
+00
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+20
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+10
+10
+10
+10
+10
+92
+54
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 8 4 0 2
+BITMAP
+38
+10
+60
+90
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 11 0 0
+BITMAP
+90
+60
+10
+10
+10
+fc
+10
+10
+10
+00
+fc
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+30
+68
+90
+80
+60
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+18
+06
+18
+60
+80
+00
+fe
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+82
+44
+28
+10
+28
+44
+82
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 5 0 1
+BITMAP
+76
+88
+88
+76
+70
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 5 0 1
+BITMAP
+88
+04
+04
+04
+74
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 891 0
+DWIDTH 13 0
+BBX 9 2 2 0
+BITMAP
+cc80
+8480
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 1 20 4 -6
+BITMAP
+00
+00
+80
+80
+80
+00
+00
+00
+00
+80
+00
+00
+00
+00
+00
+80
+00
+80
+00
+00
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 1028 0
+DWIDTH 15 0
+BBX 15 1 0 3
+BITMAP
+fe00
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 8 9 0 0
+BITMAP
+fe
+00
+fe
+72
+9c
+00
+72
+9c
+88
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 8 10 2 0
+BITMAP
+80
+88
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 8 12 1 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 10 11 1 0
+BITMAP
+80c0
+fe00
+0100
+0100
+0140
+ff40
+88c0
+6600
+7480
+8c40
+63c0
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 9 12 1 -3
+BITMAP
+3f00
+4200
+2400
+0300
+6180
+1a00
+7300
+9d80
+8980
+8b00
+ce00
+6a00
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+2900
+0900
+0900
+6900
+b080
+1000
+2300
+4580
+8880
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+9080
+d480
+6900
+6b00
+b600
+9000
+9000
+6000
+1c00
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 11 11 0 0
+BITMAP
+6300
+6300
+9480
+8880
+9480
+6300
+6300
+1c00
+1c00
+6300
+4900
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 10 7 0 0
+BITMAP
+8880
+be80
+8880
+4900
+6300
+1c00
+1f00
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 10 7 0 0
+BITMAP
+60c0
+40c0
+8100
+8200
+8400
+8800
+9000
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 7 0 0
+BITMAP
+6000
+6080
+9f00
+1e00
+6180
+4080
+8000
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 9 1 -2
+BITMAP
+8000
+8000
+8000
+8000
+8000
+8000
+8000
+4080
+6180
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 9 0 -1
+BITMAP
+1e00
+fe00
+0100
+0080
+0080
+0080
+0100
+fe00
+fe00
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 7 1 0
+BITMAP
+0100
+0080
+0080
+0080
+0100
+fe00
+0000
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 9 0 -2
+BITMAP
+ff80
+0100
+3f80
+4200
+8200
+8400
+8400
+4800
+3f80
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 7 7 1 0
+BITMAP
+10
+00
+3e
+80
+40
+00
+80
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 7 9 0 -1
+BITMAP
+00
+80
+00
+80
+00
+40
+00
+3e
+80
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 11 10 0 0
+BITMAP
+3f80
+4000
+8000
+8000
+8000
+4000
+3f80
+0000
+ff80
+3e40
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 11 0 0
+BITMAP
+8080
+8000
+3e00
+3e00
+9080
+9000
+3e00
+0000
+0080
+0100
+0200
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 10 10 1 0
+BITMAP
+0400
+0800
+1000
+2000
+4000
+ffc0
+ff80
+8080
+4100
+4100
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 10 10 1 0
+BITMAP
+2200
+2200
+2200
+1400
+1400
+0800
+0800
+1e00
+2100
+7c80
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 11 6 0 4
+BITMAP
+9240
+9240
+9c40
+9240
+7980
+2100
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 10 12 1 -1
+BITMAP
+1e00
+1e00
+2100
+4e80
+9240
+9040
+9040
+9240
+4c80
+2100
+1e00
+fa80
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 8 14 0 0
+BITMAP
+aa
+80
+26
+c0
+25
+40
+25
+40
+76
+e0
+ff
+c0
+40
+80
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 274 0
+DWIDTH 4 0
+BBX 1 2 1 3
+BITMAP
+00
+80
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 5 0 0
+BITMAP
+4080
+4080
+4080
+4080
+4080
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+40
+80
+40
+80
+40
+80
+e1
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+c0
+01
+01
+01
+02
+02
+02
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 1028 0
+DWIDTH 15 0
+BBX 13 7 1 0
+BITMAP
+0260
+a420
+1410
+0808
+8080
+ff80
+0080
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 960 0
+DWIDTH 14 0
+BBX 13 7 0 0
+BITMAP
+0080
+0080
+0080
+1818
+2420
+4240
+8180
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+42
+42
+24
+24
+18
+18
+10
+40
+20
+20
+7e
+f0
+c0
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 960 0
+DWIDTH 14 0
+BBX 13 7 1 0
+BITMAP
+1878
+f020
+2010
+4010
+0020
+0078
+f8c0
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+00
+7e
+f8
+20
+00
+10
+00
+10
+38
+6c
+aa
+28
+28
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+28
+28
+28
+28
+28
+28
+28
+00
+40
+00
+20
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 342 0
+DWIDTH 5 0
+BBX 4 15 0 -4
+BITMAP
+f0
+f0
+00
+10
+f0
+f0
+00
+20
+00
+40
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 10 10 1 0
+BITMAP
+2800
+2800
+aa40
+3800
+1000
+2840
+4480
+4440
+2800
+1000
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 10 10 1 0
+BITMAP
+2000
+4040
+4080
+8080
+4040
+4000
+2000
+1e00
+2100
+5c80
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 10 6 0 4
+BITMAP
+9240
+9240
+9c40
+9240
+5280
+2100
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 12 0 -1
+BITMAP
+1e00
+1e00
+2100
+4c80
+9200
+9000
+9000
+9200
+4c80
+2100
+1e00
+fa80
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 4 20 1 -6
+BITMAP
+20
+80
+20
+c0
+20
+40
+20
+40
+20
+40
+f0
+00
+80
+00
+40
+00
+20
+00
+10
+00
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 1 20 1 -6
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+80
+80
+80
+80
+00
+00
+00
+00
+80
+80
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 4 20 1 -6
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 4 20 1 -6
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 1 20 1 -6
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+00
+00
+00
+00
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 4 17 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 4 20 3 -6
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 3 20 1 -6
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+e0
+20
+40
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 4 17 3 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+20
+20
+20
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 1 20 3 -6
+BITMAP
+00
+00
+00
+00
+00
+00
+80
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+80
+80
+80
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 342 0
+DWIDTH 5 0
+BBX 4 15 1 -4
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+40
+30
+80
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 274 0
+DWIDTH 4 0
+BBX 5 13 0 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 5 20 5 -6
+BITMAP
+80
+80
+80
+80
+80
+80
+00
+80
+40
+40
+20
+20
+20
+10
+10
+10
+20
+20
+20
+40
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 1 20 1 -6
+BITMAP
+00
+80
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+80
+80
+00
+00
+00
+80
+80
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 5 17 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 4 20 1 -6
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+00
+00
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 1 20 4 -6
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+80
+80
+80
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 4 20 1 -6
+BITMAP
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 4 20 1 -6
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 1 20 4 -6
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+80
+80
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 4 17 1 -3
+BITMAP
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+80
+80
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 4 20 0 -6
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+10
+10
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 3 20 3 -6
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+e0
+c0
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 4 17 0 -3
+BITMAP
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+80
+80
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/symbol14.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/symbol14.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/symbol14.h	(revision 12606)
@@ -0,0 +1,859 @@
+static unsigned char symbol14_0_bits[] = {
+0x00};
+static unsigned char symbol14_1_bits[] = {
+0x00};
+static unsigned char symbol14_2_bits[] = {
+0x00};
+static unsigned char symbol14_3_bits[] = {
+0x00};
+static unsigned char symbol14_4_bits[] = {
+0x00};
+static unsigned char symbol14_5_bits[] = {
+0x00};
+static unsigned char symbol14_6_bits[] = {
+0x00};
+static unsigned char symbol14_7_bits[] = {
+0x00};
+static unsigned char symbol14_8_bits[] = {
+0x00};
+static unsigned char symbol14_9_bits[] = {
+0x00};
+static unsigned char symbol14_10_bits[] = {
+0x00};
+static unsigned char symbol14_11_bits[] = {
+0x00};
+static unsigned char symbol14_12_bits[] = {
+0x00};
+static unsigned char symbol14_13_bits[] = {
+0x00};
+static unsigned char symbol14_14_bits[] = {
+0x00};
+static unsigned char symbol14_15_bits[] = {
+0x00};
+static unsigned char symbol14_16_bits[] = {
+0x00};
+static unsigned char symbol14_17_bits[] = {
+0x00};
+static unsigned char symbol14_18_bits[] = {
+0x00};
+static unsigned char symbol14_19_bits[] = {
+0x00};
+static unsigned char symbol14_20_bits[] = {
+0x00};
+static unsigned char symbol14_21_bits[] = {
+0x00};
+static unsigned char symbol14_22_bits[] = {
+0x00};
+static unsigned char symbol14_23_bits[] = {
+0x00};
+static unsigned char symbol14_24_bits[] = {
+0x00};
+static unsigned char symbol14_25_bits[] = {
+0x00};
+static unsigned char symbol14_26_bits[] = {
+0x00};
+static unsigned char symbol14_27_bits[] = {
+0x00};
+static unsigned char symbol14_28_bits[] = {
+0x00};
+static unsigned char symbol14_29_bits[] = {
+0x00};
+static unsigned char symbol14_30_bits[] = {
+0x00};
+static unsigned char symbol14_31_bits[] = {
+0x00};
+static unsigned char symbol14_32_bits[] = {
+0x00};
+static unsigned char symbol14_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01};
+static unsigned char symbol14_34_bits[] = {
+0x01, 0x01, 0x82, 0x00, 0x82, 0x00, 0x7c, 0x00, 0x44, 0x00, 0x44, 0x00, 
+0x28, 0x00, 0x28, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char symbol14_35_bits[] = {
+0x28, 0x28, 0x28, 0x7e, 0x14, 0x14, 0x3f, 0x0a, 0x0a, 0x0a};
+static unsigned char symbol14_36_bits[] = {
+0x3f, 0x20, 0x20, 0x20, 0x3f, 0x20, 0x20, 0x20, 0x20, 0x3f};
+static unsigned char symbol14_37_bits[] = {
+0x9e, 0x01, 0xe9, 0x00, 0x49, 0x00, 0x29, 0x00, 0x36, 0x00, 0xd8, 0x00, 
+0x28, 0x01, 0x24, 0x01, 0x22, 0x01, 0xc3, 0x00};
+static unsigned char symbol14_38_bits[] = {
+0x0c, 0x00, 0x12, 0x00, 0x12, 0x00, 0x0e, 0x00, 0xe4, 0x00, 0x4e, 0x00, 
+0x53, 0x00, 0x21, 0x00, 0x73, 0x01, 0xde, 0x00};
+static unsigned char symbol14_39_bits[] = {
+0x07, 0x08, 0x10, 0x1e, 0x10, 0x08, 0x07};
+static unsigned char symbol14_40_bits[] = {
+0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 
+0x04};
+static unsigned char symbol14_41_bits[] = {
+0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 
+0x01};
+static unsigned char symbol14_42_bits[] = {
+0x04, 0x15, 0x0e, 0x0e, 0x15, 0x04};
+static unsigned char symbol14_43_bits[] = {
+0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08};
+static unsigned char symbol14_44_bits[] = {
+0x02, 0x02, 0x02, 0x01};
+static unsigned char symbol14_45_bits[] = {
+0x7f};
+static unsigned char symbol14_46_bits[] = {
+0x01, 0x01};
+static unsigned char symbol14_47_bits[] = {
+0x08, 0x08, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01};
+static unsigned char symbol14_48_bits[] = {
+0x1e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char symbol14_49_bits[] = {
+0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char symbol14_50_bits[] = {
+0x0e, 0x1b, 0x11, 0x10, 0x18, 0x08, 0x04, 0x02, 0x23, 0x3f};
+static unsigned char symbol14_51_bits[] = {
+0x1e, 0x33, 0x21, 0x30, 0x1c, 0x30, 0x20, 0x20, 0x33, 0x1e};
+static unsigned char symbol14_52_bits[] = {
+0x10, 0x18, 0x18, 0x14, 0x16, 0x12, 0x11, 0x3f, 0x10, 0x10};
+static unsigned char symbol14_53_bits[] = {
+0x1e, 0x02, 0x01, 0x07, 0x0c, 0x18, 0x10, 0x10, 0x09, 0x07};
+static unsigned char symbol14_54_bits[] = {
+0x38, 0x0c, 0x02, 0x02, 0x1f, 0x31, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char symbol14_55_bits[] = {
+0x3f, 0x21, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02};
+static unsigned char symbol14_56_bits[] = {
+0x0e, 0x1b, 0x11, 0x11, 0x0e, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char symbol14_57_bits[] = {
+0x1e, 0x33, 0x21, 0x21, 0x23, 0x1e, 0x18, 0x08, 0x06, 0x03};
+static unsigned char symbol14_58_bits[] = {
+0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01};
+static unsigned char symbol14_59_bits[] = {
+0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x01};
+static unsigned char symbol14_60_bits[] = {
+0x40, 0x30, 0x0c, 0x03, 0x0c, 0x30, 0x40};
+static unsigned char symbol14_61_bits[] = {
+0x7f, 0x00, 0x7f};
+static unsigned char symbol14_62_bits[] = {
+0x01, 0x06, 0x18, 0x60, 0x18, 0x06, 0x01};
+static unsigned char symbol14_63_bits[] = {
+0x0e, 0x11, 0x11, 0x10, 0x08, 0x04, 0x04, 0x00, 0x04, 0x04};
+static unsigned char symbol14_64_bits[] = {
+0x4e, 0x39, 0x00, 0x7f, 0x00, 0x00, 0x7f};
+static unsigned char symbol14_65_bits[] = {
+0x10, 0x00, 0x38, 0x00, 0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 
+0x7c, 0x00, 0xc6, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char symbol14_66_bits[] = {
+0x3f, 0x62, 0x42, 0x62, 0x3e, 0x62, 0x42, 0x42, 0x62, 0x3f};
+static unsigned char symbol14_67_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x6c, 0x00, 0x38, 0x00, 0x28, 0x00, 
+0x44, 0x00, 0xc6, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char symbol14_68_bits[] = {
+0x08, 0x08, 0x14, 0x14, 0x14, 0x22, 0x22, 0x22, 0x41, 0x7f};
+static unsigned char symbol14_69_bits[] = {
+0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 0x42, 0x7f};
+static unsigned char symbol14_70_bits[] = {
+0x38, 0x00, 0x10, 0x00, 0xfe, 0x00, 0x93, 0x01, 0x11, 0x01, 0x11, 0x01, 
+0x93, 0x01, 0xfe, 0x00, 0x10, 0x00, 0x38, 0x00};
+static unsigned char symbol14_71_bits[] = {
+0x7f, 0x42, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char symbol14_72_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xfe, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char symbol14_73_bits[] = {
+0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char symbol14_74_bits[] = {
+0x30, 0x50, 0x50, 0x66, 0xc5, 0x44, 0x44, 0x44, 0x6c, 0x38};
+static unsigned char symbol14_75_bits[] = {
+0x77, 0x22, 0x12, 0x0a, 0x0e, 0x0a, 0x12, 0x22, 0x42, 0xe7};
+static unsigned char symbol14_76_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 0x6c, 0x00, 0x44, 0x00, 0x44, 0x00, 
+0xc6, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char symbol14_77_bits[] = {
+0x07, 0x07, 0x06, 0x03, 0x8a, 0x02, 0x8a, 0x02, 0xda, 0x02, 0x52, 0x02, 
+0x52, 0x02, 0x72, 0x02, 0x22, 0x02, 0x27, 0x07};
+static unsigned char symbol14_78_bits[] = {
+0xc7, 0x01, 0x86, 0x00, 0x8a, 0x00, 0x9a, 0x00, 0x92, 0x00, 0xb2, 0x00, 
+0xa2, 0x00, 0xe2, 0x00, 0xc2, 0x00, 0x87, 0x00};
+static unsigned char symbol14_79_bits[] = {
+0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char symbol14_80_bits[] = {
+0xff, 0x01, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char symbol14_81_bits[] = {
+0x3c, 0x66, 0x42, 0xa5, 0xbd, 0xa5, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char symbol14_82_bits[] = {
+0x1f, 0x32, 0x22, 0x22, 0x32, 0x1e, 0x02, 0x02, 0x02, 0x07};
+static unsigned char symbol14_83_bits[] = {
+0x7f, 0x43, 0x06, 0x0c, 0x18, 0x08, 0x04, 0x02, 0x83, 0xff};
+static unsigned char symbol14_84_bits[] = {
+0x7f, 0x49, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c};
+static unsigned char symbol14_85_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x38, 0x00};
+static unsigned char symbol14_86_bits[] = {
+0x1c, 0x03, 0x01, 0x01, 0x01, 0x06, 0x1c, 0x20, 0x24, 0x1c};
+static unsigned char symbol14_87_bits[] = {
+0x30, 0x00, 0xcc, 0x00, 0x84, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 
+0x02, 0x01, 0x84, 0x00, 0x49, 0x02, 0xcf, 0x03};
+static unsigned char symbol14_88_bits[] = {
+0xfe, 0x00, 0x82, 0x00, 0x00, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x44, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xff, 0x01};
+static unsigned char symbol14_89_bits[] = {
+0x73, 0x06, 0x26, 0x03, 0x24, 0x01, 0x24, 0x01, 0xf8, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x70, 0x00};
+static unsigned char symbol14_90_bits[] = {
+0x7f, 0x41, 0x20, 0x10, 0x08, 0x08, 0x04, 0x02, 0x41, 0x7f};
+static unsigned char symbol14_91_bits[] = {
+0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x07};
+static unsigned char symbol14_92_bits[] = {
+0x18, 0x18, 0x00, 0x00, 0x00, 0xc3, 0xc3};
+static unsigned char symbol14_93_bits[] = {
+0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x07};
+static unsigned char symbol14_94_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0xff, 0x01};
+static unsigned char symbol14_95_bits[] = {
+0x7f};
+static unsigned char symbol14_96_bits[] = {
+0xff};
+static unsigned char symbol14_97_bits[] = {
+0x6e, 0x2b, 0x11, 0x11, 0x11, 0xab, 0x66};
+static unsigned char symbol14_98_bits[] = {
+0x1e, 0x33, 0x21, 0x31, 0x19, 0x31, 0x21, 0x21, 0x21, 0x33, 0x1d, 0x01, 
+0x01, 0x01};
+static unsigned char symbol14_99_bits[] = {
+0xc3, 0x65, 0x24, 0x3c, 0x18, 0x1c, 0x14, 0x26, 0xa2, 0xc3};
+static unsigned char symbol14_100_bits[] = {
+0x0e, 0x19, 0x01, 0x02, 0x0e, 0x19, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char symbol14_101_bits[] = {
+0x1e, 0x13, 0x01, 0x06, 0x01, 0x13, 0x0e};
+static unsigned char symbol14_102_bits[] = {
+0x08, 0x08, 0x08, 0x1c, 0x2a, 0x49, 0x49, 0x49, 0x2a, 0x1c, 0x08, 0x08, 
+0x08};
+static unsigned char symbol14_103_bits[] = {
+0x23, 0x25, 0x24, 0x14, 0x14, 0x18, 0x18, 0x08, 0x0c, 0x0c};
+static unsigned char symbol14_104_bits[] = {
+0x36, 0x4d, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, 0x40, 0x40};
+static unsigned char symbol14_105_bits[] = {
+0x06, 0x05, 0x04, 0x04, 0x04, 0x14, 0x0c};
+static unsigned char symbol14_106_bits[] = {
+0x18, 0x2a, 0x4b, 0x49, 0x49, 0x2a, 0x1c, 0x08, 0x08, 0x08};
+static unsigned char symbol14_107_bits[] = {
+0x62, 0x53, 0x0a, 0x0e, 0x1a, 0x32, 0x62};
+static unsigned char symbol14_108_bits[] = {
+0x06, 0x0a, 0x08, 0x08, 0x14, 0x14, 0x12, 0x22, 0xa1, 0xc1};
+static unsigned char symbol14_109_bits[] = {
+0x11, 0x11, 0x11, 0x11, 0x11, 0x59, 0x6f, 0x01, 0x03};
+static unsigned char symbol14_110_bits[] = {
+0x63, 0x42, 0x44, 0x44, 0x28, 0x28, 0x10};
+static unsigned char symbol14_111_bits[] = {
+0x1e, 0x33, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char symbol14_112_bits[] = {
+0x7e, 0x25, 0x24, 0x24, 0x24, 0xa4, 0x66};
+static unsigned char symbol14_113_bits[] = {
+0x0e, 0x1b, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char symbol14_114_bits[] = {
+0x1e, 0x33, 0x21, 0x21, 0x21, 0x33, 0x1d, 0x01, 0x01, 0x01};
+static unsigned char symbol14_115_bits[] = {
+0x7e, 0x13, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char symbol14_116_bits[] = {
+0x1e, 0x05, 0x04, 0x04, 0x04, 0x14, 0x0c};
+static unsigned char symbol14_117_bits[] = {
+0x26, 0x45, 0x44, 0x44, 0x44, 0x64, 0x38};
+static unsigned char symbol14_118_bits[] = {
+0xfe, 0x03, 0x05, 0x01, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 
+0x26, 0x03, 0xdc, 0x01};
+static unsigned char symbol14_119_bits[] = {
+0xc6, 0x00, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x93, 0x01, 
+0xee, 0x00};
+static unsigned char symbol14_120_bits[] = {
+0x04, 0x02, 0x1c, 0x04, 0x02, 0x1e, 0x04, 0x02, 0x01, 0x01, 0x03, 0x1e, 
+0x20, 0x24, 0x1c};
+static unsigned char symbol14_121_bits[] = {
+0x11, 0x01, 0x92, 0x00, 0x92, 0x00, 0x92, 0x00, 0xd6, 0x00, 0x7c, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char symbol14_122_bits[] = {
+0x04, 0x22, 0x3c, 0x08, 0x04, 0x02, 0x02, 0x01, 0x01, 0x03, 0x1e, 0x20, 
+0x24, 0x1c};
+static unsigned char symbol14_123_bits[] = {
+0x18, 0x04, 0x04, 0x04, 0x04, 0x02, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 
+0x18};
+static unsigned char symbol14_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01};
+static unsigned char symbol14_125_bits[] = {
+0x03, 0x04, 0x04, 0x04, 0x04, 0x08, 0x10, 0x08, 0x04, 0x04, 0x04, 0x04, 
+0x03};
+static unsigned char symbol14_126_bits[] = {
+0x46, 0x49, 0x31};
+static unsigned char symbol14_127_bits[] = {
+0x00};
+static unsigned char symbol14_128_bits[] = {
+0x00};
+static unsigned char symbol14_129_bits[] = {
+0x00};
+static unsigned char symbol14_130_bits[] = {
+0x00};
+static unsigned char symbol14_131_bits[] = {
+0x00};
+static unsigned char symbol14_132_bits[] = {
+0x00};
+static unsigned char symbol14_133_bits[] = {
+0x00};
+static unsigned char symbol14_134_bits[] = {
+0x00};
+static unsigned char symbol14_135_bits[] = {
+0x00};
+static unsigned char symbol14_136_bits[] = {
+0x00};
+static unsigned char symbol14_137_bits[] = {
+0x00};
+static unsigned char symbol14_138_bits[] = {
+0x00};
+static unsigned char symbol14_139_bits[] = {
+0x00};
+static unsigned char symbol14_140_bits[] = {
+0x00};
+static unsigned char symbol14_141_bits[] = {
+0x00};
+static unsigned char symbol14_142_bits[] = {
+0x00};
+static unsigned char symbol14_143_bits[] = {
+0x00};
+static unsigned char symbol14_144_bits[] = {
+0x00};
+static unsigned char symbol14_145_bits[] = {
+0x00};
+static unsigned char symbol14_146_bits[] = {
+0x00};
+static unsigned char symbol14_147_bits[] = {
+0x00};
+static unsigned char symbol14_148_bits[] = {
+0x00};
+static unsigned char symbol14_149_bits[] = {
+0x00};
+static unsigned char symbol14_150_bits[] = {
+0x00};
+static unsigned char symbol14_151_bits[] = {
+0x00};
+static unsigned char symbol14_152_bits[] = {
+0x00};
+static unsigned char symbol14_153_bits[] = {
+0x00};
+static unsigned char symbol14_154_bits[] = {
+0x00};
+static unsigned char symbol14_155_bits[] = {
+0x00};
+static unsigned char symbol14_156_bits[] = {
+0x00};
+static unsigned char symbol14_157_bits[] = {
+0x00};
+static unsigned char symbol14_158_bits[] = {
+0x00};
+static unsigned char symbol14_159_bits[] = {
+0x00};
+static unsigned char symbol14_160_bits[] = {
+0x00};
+static unsigned char symbol14_161_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol14_162_bits[] = {
+0x00, 0x00, 0x00};
+static unsigned char symbol14_163_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol14_164_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol14_165_bits[] = {
+0x00, 0x00, 0x63, 0x00, 0xd4, 0x00, 0x08, 0x00};
+static unsigned char symbol14_166_bits[] = {
+0x08, 0x08, 0x08, 0x1c, 0x0c, 0x06, 0x01, 0x40, 0x30, 0x0c, 0x03, 0x0c, 
+0x30};
+static unsigned char symbol14_167_bits[] = {
+0x40, 0x00, 0x7f, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x01, 
+0x01, 0x00, 0x00, 0x01};
+static unsigned char symbol14_168_bits[] = {
+0x01, 0x31, 0x01, 0x6e, 0x00, 0x60, 0x50};
+static unsigned char symbol14_169_bits[] = {
+0x10, 0x10, 0x3c, 0x08, 0x08, 0x08, 0x04};
+static unsigned char symbol14_170_bits[] = {
+0x04, 0x00, 0x05, 0x01, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0xd7, 0x01, 
+0xff, 0x01, 0xd7, 0x01};
+static unsigned char symbol14_171_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x08, 0x1c, 0x3e, 0x1f, 0x3e, 0x1c, 0x08, 0x16, 
+0x7f, 0x1f};
+static unsigned char symbol14_172_bits[] = {
+0x7f, 0x3e, 0x1c, 0x08, 0x10, 0x00, 0x38, 0x00, 0x7c, 0x00, 0xfe, 0x00, 
+0xff, 0x01};
+static unsigned char symbol14_173_bits[] = {
+0x56, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x02, 0x04, 0x04, 0x02, 0x08, 
+0x7f, 0x1f, 0x02, 0x08, 0x04, 0x04, 0x08, 0x02};
+static unsigned char symbol14_174_bits[] = {
+0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0xff, 0x3f, 0x02, 0x00, 0x04, 0x00, 
+0x08, 0x00};
+static unsigned char symbol14_175_bits[] = {
+0x08, 0x1c, 0x2a, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x08, 0x08};
+static unsigned char symbol14_176_bits[] = {
+0x08, 0x08, 0x08, 0x00};
+static unsigned char symbol14_177_bits[] = {
+0x04, 0x00, 0x08, 0x00, 0x10, 0x7f, 0x3f, 0x00, 0x10};
+static unsigned char symbol14_178_bits[] = {
+0x00, 0x08, 0x00};
+static unsigned char symbol14_179_bits[] = {
+0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
+static unsigned char symbol14_180_bits[] = {
+0x08, 0x08, 0x08, 0x08, 0x08, 0x49, 0x2a};
+static unsigned char symbol14_181_bits[] = {
+0x1c, 0x08, 0x06, 0x09};
+static unsigned char symbol14_182_bits[] = {
+0x09, 0x06, 0x08, 0x08, 0x08, 0x3f, 0x08, 0x08, 0x08, 0x00, 0x3f};
+static unsigned char symbol14_183_bits[] = {
+0x0c, 0x16, 0x09, 0x01, 0x06};
+static unsigned char symbol14_184_bits[] = {
+0x18, 0x60, 0x18, 0x06, 0x01, 0x00, 0x7f};
+static unsigned char symbol14_185_bits[] = {
+0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41};
+static unsigned char symbol14_186_bits[] = {
+0x6e, 0x11, 0x11, 0x6e, 0x0e};
+static unsigned char symbol14_187_bits[] = {
+0x11, 0x20, 0x20, 0x20, 0x2e};
+static unsigned char symbol14_188_bits[] = {
+0x33, 0x01, 0x21, 0x01};
+static unsigned char symbol14_189_bits[] = {
+0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00};
+static unsigned char symbol14_190_bits[] = {
+0x7f, 0x00};
+static unsigned char symbol14_191_bits[] = {
+0x7f, 0x00, 0x7f, 0x4e, 0x39, 0x00, 0x4e, 0x39, 0x11};
+static unsigned char symbol14_192_bits[] = {
+0x01, 0x11, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_193_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_194_bits[] = {
+0x01, 0x03, 0x7f, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x02, 0xff, 0x02, 
+0x11, 0x03, 0x66, 0x00, 0x2e, 0x01, 0x31, 0x02, 0xc6, 0x03};
+static unsigned char symbol14_195_bits[] = {
+0xfc, 0x00, 0x42, 0x00, 0x24, 0x00, 0xc0, 0x00, 0x86, 0x01, 0x58, 0x00, 
+0xce, 0x00, 0xb9, 0x01, 0x91, 0x01, 0xd1, 0x00, 0x73, 0x00, 0x56, 0x00};
+static unsigned char symbol14_196_bits[] = {
+0x94, 0x00, 0x90, 0x00, 0x90, 0x00, 0x96, 0x00, 0x0d, 0x01, 0x08, 0x00, 
+0xc4, 0x00, 0xa2, 0x01, 0x11, 0x01};
+static unsigned char symbol14_197_bits[] = {
+0x09, 0x01, 0x2b, 0x01, 0x96, 0x00, 0xd6, 0x00, 0x6d, 0x00, 0x09, 0x00, 
+0x09, 0x00, 0x06, 0x00, 0x38, 0x00};
+static unsigned char symbol14_198_bits[] = {
+0xc6, 0x00, 0xc6, 0x00, 0x29, 0x01, 0x11, 0x01, 0x29, 0x01, 0xc6, 0x00, 
+0xc6, 0x00, 0x38, 0x00, 0x38, 0x00, 0xc6, 0x00, 0x92, 0x00};
+static unsigned char symbol14_199_bits[] = {
+0x11, 0x01, 0x7d, 0x01, 0x11, 0x01, 0x92, 0x00, 0xc6, 0x00, 0x38, 0x00, 
+0xf8, 0x00};
+static unsigned char symbol14_200_bits[] = {
+0x06, 0x03, 0x02, 0x03, 0x81, 0x00, 0x41, 0x00, 0x21, 0x00, 0x11, 0x00, 
+0x09, 0x00};
+static unsigned char symbol14_201_bits[] = {
+0x06, 0x00, 0x06, 0x01, 0xf9, 0x00, 0x78, 0x00, 0x86, 0x01, 0x02, 0x01, 
+0x01, 0x00};
+static unsigned char symbol14_202_bits[] = {
+0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x02, 0x01, 0x86, 0x01};
+static unsigned char symbol14_203_bits[] = {
+0x78, 0x00, 0x7f, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 
+0x80, 0x00, 0x7f, 0x00, 0x7f, 0x00};
+static unsigned char symbol14_204_bits[] = {
+0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x80, 0x00, 0x7f, 0x00, 
+0x00, 0x00};
+static unsigned char symbol14_205_bits[] = {
+0xff, 0x01, 0x80, 0x00, 0xfc, 0x01, 0x42, 0x00, 0x41, 0x00, 0x21, 0x00, 
+0x21, 0x00, 0x12, 0x00, 0xfc, 0x01};
+static unsigned char symbol14_206_bits[] = {
+0x08, 0x00, 0x7c, 0x01, 0x02, 0x00, 0x01};
+static unsigned char symbol14_207_bits[] = {
+0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x7c, 0x01};
+static unsigned char symbol14_208_bits[] = {
+0xfc, 0x01, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 
+0xfc, 0x01, 0x00, 0x00, 0xff, 0x01, 0x7c, 0x02};
+static unsigned char symbol14_209_bits[] = {
+0x01, 0x01, 0x01, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x09, 0x01, 0x09, 0x00, 
+0x7c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x40, 0x00};
+static unsigned char symbol14_210_bits[] = {
+0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0xff, 0x03, 
+0xff, 0x01, 0x01, 0x01, 0x82, 0x00, 0x82, 0x00};
+static unsigned char symbol14_211_bits[] = {
+0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x78, 0x00, 0x84, 0x00, 0x3e, 0x01};
+static unsigned char symbol14_212_bits[] = {
+0x49, 0x02, 0x49, 0x02, 0x39, 0x02, 0x49, 0x02, 0x9e, 0x01, 0x84, 0x00};
+static unsigned char symbol14_213_bits[] = {
+0x78, 0x00, 0x78, 0x00, 0x84, 0x00, 0x72, 0x01, 0x49, 0x02, 0x09, 0x02, 
+0x09, 0x02, 0x49, 0x02, 0x32, 0x01, 0x84, 0x00, 0x78, 0x00, 0x5f, 0x01};
+static unsigned char symbol14_214_bits[] = {
+0x55, 0x01, 0x64, 0x03, 0xa4, 0x02, 0xa4, 0x02, 0x6e, 0x07, 0xff, 0x03, 
+0x02, 0x01};
+static unsigned char symbol14_215_bits[] = {
+0x00, 0x01};
+static unsigned char symbol14_216_bits[] = {
+0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01};
+static unsigned char symbol14_217_bits[] = {
+0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x87};
+static unsigned char symbol14_218_bits[] = {
+0x03, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40};
+static unsigned char symbol14_219_bits[] = {
+0x40, 0x06, 0x25, 0x04, 0x28, 0x08, 0x10, 0x10, 0x01, 0x01, 0xff, 0x01, 
+0x00, 0x01};
+static unsigned char symbol14_220_bits[] = {
+0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x18, 0x18, 0x24, 0x04, 0x42, 0x02, 
+0x81, 0x01};
+static unsigned char symbol14_221_bits[] = {
+0x42, 0x42, 0x24, 0x24, 0x18, 0x18, 0x08, 0x02, 0x04, 0x04, 0x7e, 0x0f, 
+0x03};
+static unsigned char symbol14_222_bits[] = {
+0x18, 0x1e, 0x0f, 0x04, 0x04, 0x08, 0x02, 0x08, 0x00, 0x04, 0x00, 0x1e, 
+0x1f, 0x03};
+static unsigned char symbol14_223_bits[] = {
+0x00, 0x7e, 0x1f, 0x04, 0x00, 0x08, 0x00, 0x08, 0x1c, 0x36, 0x55, 0x14, 
+0x14};
+static unsigned char symbol14_224_bits[] = {
+0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x02, 0x00, 0x04};
+static unsigned char symbol14_225_bits[] = {
+0x0f, 0x0f, 0x00, 0x08, 0x0f, 0x0f, 0x00, 0x04, 0x00, 0x02, 0x04, 0x04, 
+0x04, 0x04, 0x04};
+static unsigned char symbol14_226_bits[] = {
+0x14, 0x00, 0x14, 0x00, 0x55, 0x02, 0x1c, 0x00, 0x08, 0x00, 0x14, 0x02, 
+0x22, 0x01, 0x22, 0x02, 0x14, 0x00, 0x08, 0x00};
+static unsigned char symbol14_227_bits[] = {
+0x04, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 
+0x04, 0x00, 0x78, 0x00, 0x84, 0x00, 0x3a, 0x01};
+static unsigned char symbol14_228_bits[] = {
+0x49, 0x02, 0x49, 0x02, 0x39, 0x02, 0x49, 0x02, 0x4a, 0x01, 0x84, 0x00};
+static unsigned char symbol14_229_bits[] = {
+0x78, 0x00, 0x78, 0x00, 0x84, 0x00, 0x32, 0x01, 0x49, 0x00, 0x09, 0x00, 
+0x09, 0x00, 0x49, 0x00, 0x32, 0x01, 0x84, 0x00, 0x78, 0x00, 0x5f, 0x01};
+static unsigned char symbol14_230_bits[] = {
+0x04, 0x01, 0x04, 0x03, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x0f, 0x00, 
+0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00};
+static unsigned char symbol14_231_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 
+0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01};
+static unsigned char symbol14_232_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_233_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_234_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 
+0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_235_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_236_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_237_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x07, 0x04, 0x02, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_238_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x04, 0x04, 0x04};
+static unsigned char symbol14_239_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01};
+static unsigned char symbol14_240_bits[] = {
+0x00};
+static unsigned char symbol14_241_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x02, 0x0c, 0x01};
+static unsigned char symbol14_242_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01};
+static unsigned char symbol14_243_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x02, 0x02, 0x04, 0x04, 
+0x04, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x02};
+static unsigned char symbol14_244_bits[] = {
+0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01};
+static unsigned char symbol14_245_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_246_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00};
+static unsigned char symbol14_247_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol14_248_bits[] = {
+0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_249_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x08, 0x08, 0x08, 0x08, 0x08};
+static unsigned char symbol14_250_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol14_251_bits[] = {
+0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x01, 0x01};
+static unsigned char symbol14_252_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x08};
+static unsigned char symbol14_253_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x07, 0x03, 0x04, 0x00, 0x00, 0x00};
+static unsigned char symbol14_254_bits[] = {
+0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x01, 0x01};
+static unsigned char symbol14_255_bits[] = {
+0x00};
+static RotFont symbol14font[] = {
+{5, 1, 1, symbol14_0_bits},
+{5, 1, 1, symbol14_1_bits},
+{5, 1, 1, symbol14_2_bits},
+{5, 1, 1, symbol14_3_bits},
+{5, 1, 1, symbol14_4_bits},
+{5, 1, 1, symbol14_5_bits},
+{5, 1, 1, symbol14_6_bits},
+{5, 1, 1, symbol14_7_bits},
+{5, 1, 1, symbol14_8_bits},
+{5, 1, 1, symbol14_9_bits},
+{5, 1, 1, symbol14_10_bits},
+{5, 1, 1, symbol14_11_bits},
+{5, 1, 1, symbol14_12_bits},
+{5, 1, 1, symbol14_13_bits},
+{5, 1, 1, symbol14_14_bits},
+{5, 1, 1, symbol14_15_bits},
+{5, 1, 1, symbol14_16_bits},
+{5, 1, 1, symbol14_17_bits},
+{5, 1, 1, symbol14_18_bits},
+{5, 1, 1, symbol14_19_bits},
+{5, 1, 1, symbol14_20_bits},
+{5, 1, 1, symbol14_21_bits},
+{5, 1, 1, symbol14_22_bits},
+{5, 1, 1, symbol14_23_bits},
+{5, 1, 1, symbol14_24_bits},
+{5, 1, 1, symbol14_25_bits},
+{5, 1, 1, symbol14_26_bits},
+{5, 1, 1, symbol14_27_bits},
+{5, 1, 1, symbol14_28_bits},
+{5, 1, 1, symbol14_29_bits},
+{5, 1, 1, symbol14_30_bits},
+{5, 1, 1, symbol14_31_bits},
+{1, 1, 1, symbol14_32_bits},
+{1, 10, 10, symbol14_33_bits},
+{9, 10, 10, symbol14_34_bits},
+{7, 10, 10, symbol14_35_bits},
+{6, 10, 10, symbol14_36_bits},
+{9, 10, 10, symbol14_37_bits},
+{9, 10, 10, symbol14_38_bits},
+{5, 7, 7, symbol14_39_bits},
+{3, 13, 10, symbol14_40_bits},
+{3, 13, 10, symbol14_41_bits},
+{5, 6, 8, symbol14_42_bits},
+{7, 7, 7, symbol14_43_bits},
+{2, 4, 2, symbol14_44_bits},
+{7, 1, 4, symbol14_45_bits},
+{1, 2, 2, symbol14_46_bits},
+{4, 10, 10, symbol14_47_bits},
+{6, 10, 10, symbol14_48_bits},
+{5, 10, 10, symbol14_49_bits},
+{6, 10, 10, symbol14_50_bits},
+{6, 10, 10, symbol14_51_bits},
+{6, 10, 10, symbol14_52_bits},
+{5, 10, 10, symbol14_53_bits},
+{6, 10, 10, symbol14_54_bits},
+{6, 10, 10, symbol14_55_bits},
+{5, 10, 10, symbol14_56_bits},
+{6, 10, 10, symbol14_57_bits},
+{1, 7, 7, symbol14_58_bits},
+{2, 9, 7, symbol14_59_bits},
+{7, 7, 7, symbol14_60_bits},
+{7, 3, 5, symbol14_61_bits},
+{7, 7, 7, symbol14_62_bits},
+{5, 10, 10, symbol14_63_bits},
+{7, 7, 7, symbol14_64_bits},
+{9, 10, 10, symbol14_65_bits},
+{7, 10, 10, symbol14_66_bits},
+{9, 10, 10, symbol14_67_bits},
+{7, 10, 10, symbol14_68_bits},
+{7, 10, 10, symbol14_69_bits},
+{9, 10, 10, symbol14_70_bits},
+{7, 10, 10, symbol14_71_bits},
+{9, 10, 10, symbol14_72_bits},
+{3, 10, 10, symbol14_73_bits},
+{8, 10, 10, symbol14_74_bits},
+{8, 10, 10, symbol14_75_bits},
+{9, 10, 10, symbol14_76_bits},
+{11, 10, 10, symbol14_77_bits},
+{9, 10, 10, symbol14_78_bits},
+{8, 10, 10, symbol14_79_bits},
+{9, 10, 10, symbol14_80_bits},
+{8, 10, 10, symbol14_81_bits},
+{6, 10, 10, symbol14_82_bits},
+{8, 10, 10, symbol14_83_bits},
+{7, 10, 10, symbol14_84_bits},
+{9, 10, 10, symbol14_85_bits},
+{6, 10, 7, symbol14_86_bits},
+{10, 10, 10, symbol14_87_bits},
+{9, 10, 10, symbol14_88_bits},
+{11, 10, 10, symbol14_89_bits},
+{7, 10, 10, symbol14_90_bits},
+{3, 13, 10, symbol14_91_bits},
+{8, 7, 7, symbol14_92_bits},
+{3, 13, 10, symbol14_93_bits},
+{9, 10, 10, symbol14_94_bits},
+{7, 1, -2, symbol14_95_bits},
+{8, 1, 14, symbol14_96_bits},
+{8, 7, 7, symbol14_97_bits},
+{6, 14, 11, symbol14_98_bits},
+{8, 10, 7, symbol14_99_bits},
+{5, 11, 11, symbol14_100_bits},
+{5, 7, 7, symbol14_101_bits},
+{7, 13, 10, symbol14_102_bits},
+{6, 10, 7, symbol14_103_bits},
+{7, 10, 7, symbol14_104_bits},
+{5, 7, 7, symbol14_105_bits},
+{7, 10, 7, symbol14_106_bits},
+{7, 7, 7, symbol14_107_bits},
+{8, 10, 10, symbol14_108_bits},
+{7, 9, 7, symbol14_109_bits},
+{7, 7, 7, symbol14_110_bits},
+{6, 7, 7, symbol14_111_bits},
+{8, 7, 7, symbol14_112_bits},
+{5, 10, 10, symbol14_113_bits},
+{6, 10, 7, symbol14_114_bits},
+{7, 7, 7, symbol14_115_bits},
+{5, 7, 7, symbol14_116_bits},
+{7, 7, 7, symbol14_117_bits},
+{10, 8, 8, symbol14_118_bits},
+{9, 7, 7, symbol14_119_bits},
+{6, 15, 12, symbol14_120_bits},
+{9, 10, 7, symbol14_121_bits},
+{6, 14, 11, symbol14_122_bits},
+{5, 13, 10, symbol14_123_bits},
+{1, 13, 10, symbol14_124_bits},
+{5, 13, 10, symbol14_125_bits},
+{7, 3, 5, symbol14_126_bits},
+{5, 1, 1, symbol14_127_bits},
+{5, 1, 1, symbol14_128_bits},
+{5, 1, 1, symbol14_129_bits},
+{5, 1, 1, symbol14_130_bits},
+{5, 1, 1, symbol14_131_bits},
+{5, 1, 1, symbol14_132_bits},
+{5, 1, 1, symbol14_133_bits},
+{5, 1, 1, symbol14_134_bits},
+{5, 1, 1, symbol14_135_bits},
+{5, 1, 1, symbol14_136_bits},
+{5, 1, 1, symbol14_137_bits},
+{5, 1, 1, symbol14_138_bits},
+{5, 1, 1, symbol14_139_bits},
+{5, 1, 1, symbol14_140_bits},
+{5, 1, 1, symbol14_141_bits},
+{5, 1, 1, symbol14_142_bits},
+{5, 1, 1, symbol14_143_bits},
+{5, 1, 1, symbol14_144_bits},
+{5, 1, 1, symbol14_145_bits},
+{5, 1, 1, symbol14_146_bits},
+{5, 1, 1, symbol14_147_bits},
+{5, 1, 1, symbol14_148_bits},
+{5, 1, 1, symbol14_149_bits},
+{5, 1, 1, symbol14_150_bits},
+{5, 1, 1, symbol14_151_bits},
+{5, 1, 1, symbol14_152_bits},
+{5, 1, 1, symbol14_153_bits},
+{5, 1, 1, symbol14_154_bits},
+{5, 1, 1, symbol14_155_bits},
+{5, 1, 1, symbol14_156_bits},
+{5, 1, 1, symbol14_157_bits},
+{5, 1, 1, symbol14_158_bits},
+{5, 1, 1, symbol14_159_bits},
+{5, 1, 1, symbol14_160_bits},
+{8, 10, 10, symbol14_161_bits},
+{4, 3, 10, symbol14_162_bits},
+{7, 9, 9, symbol14_163_bits},
+{5, 10, 10, symbol14_164_bits},
+{9, 4, 6, symbol14_165_bits},
+{7, 13, 10, symbol14_166_bits},
+{9, 8, 7, symbol14_167_bits},
+{7, 7, 7, symbol14_168_bits},
+{7, 7, 7, symbol14_169_bits},
+{9, 8, 7, symbol14_170_bits},
+{13, 7, 7, symbol14_171_bits},
+{14, 7, 7, symbol14_172_bits},
+{7, 20, 14, symbol14_173_bits},
+{14, 7, 7, symbol14_174_bits},
+{7, 17, 14, symbol14_175_bits},
+{4, 4, 10, symbol14_176_bits},
+{7, 9, 9, symbol14_177_bits},
+{7, 3, 10, symbol14_178_bits},
+{7, 9, 9, symbol14_179_bits},
+{7, 7, 7, symbol14_180_bits},
+{8, 4, 6, symbol14_181_bits},
+{6, 11, 11, symbol14_182_bits},
+{5, 5, 6, symbol14_183_bits},
+{7, 7, 7, symbol14_184_bits},
+{7, 7, 7, symbol14_185_bits},
+{7, 5, 6, symbol14_186_bits},
+{7, 5, 6, symbol14_187_bits},
+{9, 2, 2, symbol14_188_bits},
+{1, 20, 14, symbol14_189_bits},
+{15, 1, 4, symbol14_190_bits},
+{8, 9, 9, symbol14_191_bits},
+{8, 10, 10, symbol14_192_bits},
+{8, 12, 11, symbol14_193_bits},
+{10, 11, 11, symbol14_194_bits},
+{9, 12, 9, symbol14_195_bits},
+{9, 9, 9, symbol14_196_bits},
+{9, 9, 9, symbol14_197_bits},
+{11, 11, 11, symbol14_198_bits},
+{10, 7, 7, symbol14_199_bits},
+{10, 7, 7, symbol14_200_bits},
+{9, 7, 7, symbol14_201_bits},
+{9, 9, 7, symbol14_202_bits},
+{9, 9, 8, symbol14_203_bits},
+{9, 7, 7, symbol14_204_bits},
+{9, 9, 7, symbol14_205_bits},
+{7, 7, 7, symbol14_206_bits},
+{7, 9, 8, symbol14_207_bits},
+{11, 10, 10, symbol14_208_bits},
+{9, 11, 11, symbol14_209_bits},
+{10, 10, 10, symbol14_210_bits},
+{10, 10, 10, symbol14_211_bits},
+{11, 6, 10, symbol14_212_bits},
+{10, 12, 11, symbol14_213_bits},
+{8, 14, 14, symbol14_214_bits},
+{1, 2, 5, symbol14_215_bits},
+{9, 5, 5, symbol14_216_bits},
+{8, 7, 7, symbol14_217_bits},
+{8, 7, 7, symbol14_218_bits},
+{13, 7, 7, symbol14_219_bits},
+{13, 7, 7, symbol14_220_bits},
+{7, 13, 13, symbol14_221_bits},
+{13, 7, 7, symbol14_222_bits},
+{7, 13, 13, symbol14_223_bits},
+{7, 11, 11, symbol14_224_bits},
+{4, 15, 11, symbol14_225_bits},
+{10, 10, 10, symbol14_226_bits},
+{10, 10, 10, symbol14_227_bits},
+{10, 6, 10, symbol14_228_bits},
+{9, 12, 11, symbol14_229_bits},
+{4, 20, 14, symbol14_230_bits},
+{1, 20, 14, symbol14_231_bits},
+{4, 20, 14, symbol14_232_bits},
+{4, 20, 14, symbol14_233_bits},
+{1, 20, 14, symbol14_234_bits},
+{4, 17, 14, symbol14_235_bits},
+{4, 20, 14, symbol14_236_bits},
+{3, 20, 14, symbol14_237_bits},
+{4, 17, 14, symbol14_238_bits},
+{1, 20, 14, symbol14_239_bits},
+{5, 1, 1, symbol14_240_bits},
+{4, 15, 11, symbol14_241_bits},
+{5, 13, 12, symbol14_242_bits},
+{5, 20, 14, symbol14_243_bits},
+{1, 20, 14, symbol14_244_bits},
+{5, 17, 14, symbol14_245_bits},
+{4, 20, 14, symbol14_246_bits},
+{1, 20, 14, symbol14_247_bits},
+{4, 20, 14, symbol14_248_bits},
+{4, 20, 14, symbol14_249_bits},
+{1, 20, 14, symbol14_250_bits},
+{4, 17, 14, symbol14_251_bits},
+{4, 20, 14, symbol14_252_bits},
+{3, 20, 14, symbol14_253_bits},
+{4, 17, 14, symbol14_254_bits},
+{5, 1, 1, symbol14_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/symbol18.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/symbol18.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/symbol18.bdf	(revision 12606)
@@ -0,0 +1,3822 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Symbol-Medium-R-Normal--18-180-75-75-P-107-Adobe-FontSpecific
+SIZE 18 75 75
+FONTBOUNDINGBOX 20 25 -1 -7
+STARTPROPERTIES 31
+FOUNDRY "Adobe"
+FAMILY_NAME "Symbol"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 18
+POINT_SIZE 180
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 107
+CHARSET_REGISTRY "Adobe"
+CHARSET_ENCODING "FontSpecific"
+CAP_HEIGHT 13
+X_HEIGHT 9
+FACE_NAME "Symbol"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "No mark"
+_DEC_DEVICE_FONTNAMES "PS=Symbol"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2-1, 18-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+FULL_NAME "Symbol"
+FONT "-Adobe-Symbol-Medium-R-Normal--18-180-75-75-P-107-Adobe-FontSpecific"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 11
+DEFAULT_CHAR 32
+FONT_ASCENT 16
+FONT_DESCENT 4
+ENDPROPERTIES
+CHARS 188
+STARTCHAR space
+ENCODING 32
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 1 1 1 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 2 13 2 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+40
+40
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 13 13 0 0
+BITMAP
+c018
+c018
+6030
+6030
+3fe0
+3060
+18c0
+18c0
+0880
+0d80
+0500
+0700
+0200
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 10 13 -1 0
+BITMAP
+0900
+0900
+0900
+0900
+7fc0
+1200
+1200
+1200
+ff80
+2400
+2400
+2400
+2400
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+ff
+03
+03
+03
+03
+03
+7f
+03
+03
+03
+03
+03
+ff
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+3860
+67e0
+c4c0
+c580
+e980
+7300
+0600
+0670
+0cc8
+1988
+1988
+31d0
+30e0
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 13 1 0
+BITMAP
+1c00
+3600
+2200
+2600
+3c00
+39e0
+7cc0
+ee80
+c780
+c300
+c390
+67f0
+3ce0
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+f0
+38
+1c
+0c
+7c
+0c
+1c
+38
+f0
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 17 1 -4
+BITMAP
+10
+30
+60
+60
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+60
+60
+30
+10
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 17 1 -4
+BITMAP
+80
+c0
+60
+60
+30
+30
+30
+30
+30
+30
+30
+30
+30
+60
+60
+c0
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 7 1 3
+BITMAP
+10
+d6
+7c
+38
+7c
+d6
+10
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 8 1 1
+BITMAP
+18
+18
+18
+ff
+ff
+18
+18
+18
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 3 5 1 -3
+BITMAP
+60
+60
+20
+60
+c0
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 2 1 4
+BITMAP
+fe
+fe
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 2 1 0
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 13 0 0
+BITMAP
+18
+18
+18
+30
+30
+30
+60
+60
+60
+60
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+3c
+66
+66
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+66
+66
+3c
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 6 13 1 0
+BITMAP
+10
+30
+f0
+30
+30
+30
+30
+30
+30
+30
+30
+30
+fc
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+3c
+7e
+ce
+86
+06
+06
+0c
+18
+30
+60
+c2
+fe
+fe
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+7c
+ce
+86
+06
+0c
+38
+1c
+0e
+06
+06
+06
+cc
+f8
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+06
+0e
+0e
+1e
+36
+36
+66
+c6
+c6
+ff
+06
+06
+06
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+7e
+7c
+c0
+c0
+f0
+3c
+0c
+0e
+06
+06
+0c
+dc
+f0
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+0e
+38
+30
+60
+60
+fc
+c6
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+7f
+ff
+86
+06
+0c
+0c
+0c
+18
+18
+18
+30
+30
+30
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+3c
+66
+62
+62
+76
+3c
+3e
+67
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+3c
+6e
+c7
+c3
+c3
+c3
+e3
+7f
+3a
+06
+0c
+38
+e0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 2 9 2 0
+BITMAP
+c0
+c0
+00
+00
+00
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 3 12 1 -3
+BITMAP
+60
+60
+00
+00
+00
+00
+00
+60
+60
+20
+60
+c0
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+0380
+0f00
+3c00
+f000
+c000
+f000
+3c00
+0f00
+0380
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 6 1 2
+BITMAP
+ff
+ff
+00
+00
+ff
+ff
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+e000
+7800
+1e00
+0780
+0180
+0780
+1e00
+7800
+e000
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 6 13 1 0
+BITMAP
+78
+dc
+cc
+cc
+0c
+0c
+18
+30
+20
+20
+00
+60
+60
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+73
+ff
+ce
+00
+ff
+ff
+00
+ff
+ff
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+0400
+0e00
+0e00
+0b00
+1b00
+1300
+1180
+3180
+3fc0
+20c0
+60c0
+60e0
+f1f0
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+fc00
+6600
+6300
+6300
+6300
+6600
+7e00
+6300
+6180
+6180
+6180
+6380
+ff00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+f070
+7060
+38c0
+18c0
+1d80
+0f00
+0600
+0f00
+1b80
+3180
+31c0
+60e0
+e0f0
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 13 0 0
+BITMAP
+0400
+0600
+0e00
+0b00
+1300
+1300
+1180
+2180
+21c0
+40c0
+40c0
+8060
+ffe0
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+ff80
+6180
+6080
+6000
+6000
+6100
+7f00
+6100
+6000
+6000
+6080
+6180
+ff80
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+0f00
+0600
+1f80
+6660
+c630
+c630
+c630
+c630
+c630
+6660
+1f80
+0600
+0f00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 13 0 0
+BITMAP
+ffc0
+70c0
+3040
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+7800
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+f1e0
+60c0
+60c0
+60c0
+60c0
+60c0
+7fc0
+60c0
+60c0
+60c0
+60c0
+60c0
+f1e0
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 13 1 0
+BITMAP
+f0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 11 13 1 0
+BITMAP
+0600
+0b00
+0980
+0580
+6380
+f180
+b1c0
+31a0
+3180
+3180
+3180
+3b00
+1e00
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 11 13 2 0
+BITMAP
+f3c0
+6180
+6300
+6600
+6c00
+7800
+7800
+6c00
+6600
+6300
+6380
+61c0
+f1e0
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 13 0 0
+BITMAP
+0600
+0600
+0f00
+0b00
+0b00
+1980
+1180
+1180
+30c0
+20c0
+2060
+6060
+f0f0
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 853 0
+DWIDTH 16 0
+BBX 14 13 1 0
+BITMAP
+e01c
+7038
+7038
+5878
+5858
+58d8
+4c98
+4c98
+4d98
+4718
+4718
+4318
+e23c
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+e0e0
+7040
+7040
+5840
+4c40
+4c40
+4640
+4340
+43c0
+41c0
+40c0
+40c0
+e040
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+0e00
+3180
+60c0
+e0e0
+c060
+c060
+c060
+c060
+c060
+e0e0
+60c0
+3180
+0e00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+ffe0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+f1e0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+0e00
+3180
+60c0
+e0e0
+c060
+d160
+df60
+d160
+c060
+e0e0
+60c0
+3180
+0e00
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+fe
+67
+63
+63
+63
+67
+7e
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 13 1 0
+BITMAP
+ff80
+c180
+6080
+3000
+1800
+0c00
+0c00
+0800
+1000
+2040
+40c0
+ff80
+ff80
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 13 1 0
+BITMAP
+ffc0
+ccc0
+8c40
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+1e00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 13 0 0
+BITMAP
+f8f0
+7060
+30c0
+18c0
+1d80
+0f00
+0f00
+0600
+0600
+0600
+0600
+0600
+0f00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 6 13 1 -4
+BITMAP
+3c
+7c
+c0
+80
+80
+80
+c0
+78
+3c
+04
+04
+3c
+38
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 13 13 0 0
+BITMAP
+0700
+18c0
+3060
+7070
+6030
+6030
+6030
+6030
+3060
+18c0
+8888
+f8f8
+f8f8
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 13 1 0
+BITMAP
+7f80
+7f80
+4080
+0000
+2100
+3f00
+3f00
+2100
+0000
+8040
+8040
+ffc0
+ffc0
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 14 13 0 0
+BITMAP
+c78c
+6318
+6318
+6318
+6318
+3330
+1fe0
+0300
+0300
+0300
+0300
+0300
+0780
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+ff80
+c380
+8300
+0700
+0600
+0e00
+1c00
+1800
+3800
+7000
+6080
+e180
+ff80
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 17 1 -4
+BITMAP
+f0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+f0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 10 9 2 0
+BITMAP
+0c00
+0c00
+0000
+0000
+0000
+0000
+0000
+c0c0
+c0c0
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 17 1 -4
+BITMAP
+f0
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+f0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 13 1 0
+BITMAP
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+ffc0
+ffc0
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 2 0 -4
+BITMAP
+ff80
+ff80
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 10 1 0 16
+BITMAP
+ffc0
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 11 9 1 0
+BITMAP
+3cc0
+6580
+c300
+c300
+c300
+c300
+c300
+6520
+38c0
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 18 1 -4
+BITMAP
+3c
+46
+c6
+c6
+c6
+cc
+c6
+c3
+c3
+c3
+c3
+c3
+e6
+dc
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 10 13 0 -4
+BITMAP
+60c0
+f1c0
+9180
+1300
+1700
+0e00
+0c00
+1c00
+1a00
+3200
+6240
+e3c0
+c180
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+38
+4c
+40
+60
+30
+38
+6c
+c6
+c6
+c6
+c6
+c6
+6c
+38
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+78
+ec
+cc
+c0
+70
+c0
+c0
+e4
+78
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 16 1 -4
+BITMAP
+0800
+0800
+0800
+3e00
+6b00
+c980
+c980
+c980
+c980
+c980
+6b00
+3e00
+0800
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 8 13 0 -4
+BITMAP
+c3
+e3
+a3
+26
+26
+16
+14
+1c
+0c
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 -4
+BITMAP
+6700
+e980
+b180
+3180
+3180
+3180
+3180
+3180
+3180
+0180
+0180
+0180
+0180
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+60
+e0
+60
+60
+60
+60
+60
+68
+70
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 -4
+BITMAP
+6600
+cf00
+c980
+c980
+c980
+c980
+4900
+6b00
+3e00
+0800
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+6380
+e580
+6800
+7800
+7c00
+6e00
+6700
+6380
+6180
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 10 14 0 0
+BITMAP
+3000
+7800
+4800
+0800
+0800
+0800
+1c00
+1c00
+3400
+3400
+6600
+6240
+c3c0
+c180
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 2 -4
+BITMAP
+4200
+c600
+c600
+c600
+c600
+c600
+c680
+fb80
+7b00
+4000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+c3
+c3
+61
+62
+32
+34
+1c
+18
+08
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3c
+66
+c3
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+7f80
+ff80
+9200
+1200
+1200
+1200
+3280
+7380
+6300
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3c
+66
+c3
+c3
+c3
+c3
+ff
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 -4
+BITMAP
+3c
+46
+c3
+c3
+c3
+c3
+c3
+e6
+dc
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 9 1 0
+BITMAP
+1fc0
+7fc0
+6600
+c300
+c300
+c300
+c300
+6600
+3c00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+7e
+fe
+90
+10
+10
+10
+12
+1e
+1c
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+6300
+f180
+b180
+3180
+3180
+3180
+3180
+3b00
+1e00
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 11 11 0 0
+BITMAP
+3fe0
+7fe0
+9980
+30c0
+2040
+6660
+6660
+6660
+6660
+36c0
+39c0
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 9 1 0
+BITMAP
+3300
+6180
+4080
+ccc0
+ccc0
+ccc0
+ccc0
+6d80
+7380
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 19 1 -4
+BITMAP
+60
+8e
+fc
+20
+40
+40
+7c
+78
+c0
+80
+80
+80
+c0
+fc
+7e
+02
+02
+1e
+1c
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 13 13 0 -4
+BITMAP
+e238
+7270
+3260
+3260
+3260
+3260
+1ac0
+1ac0
+0f80
+0200
+0200
+0200
+0200
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 19 1 -4
+BITMAP
+60
+86
+9e
+78
+60
+40
+80
+80
+80
+80
+80
+80
+c0
+fc
+7e
+02
+02
+1e
+1c
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 17 1 -4
+BITMAP
+0e
+18
+30
+30
+30
+30
+30
+60
+c0
+60
+30
+30
+30
+30
+30
+18
+0e
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 17 1 -4
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 17 1 -4
+BITMAP
+e0
+30
+18
+18
+18
+18
+18
+0c
+06
+0c
+18
+18
+18
+18
+18
+30
+e0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 3 1 4
+BITMAP
+73
+ff
+ce
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 11 13 0 0
+BITMAP
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 4 5 1 9
+BITMAP
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 12 0 0
+BITMAP
+0000
+0080
+c000
+2000
+6000
+6000
+0000
+0000
+0000
+0000
+0000
+0000
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 8 13 -1 0
+BITMAP
+00
+0c
+00
+1e
+00
+30
+70
+60
+c0
+80
+03
+80
+0f
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 5 0 3
+BITMAP
+0030
+00f0
+00c0
+00f0
+0030
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 17 0 -4
+BITMAP
+0000
+0000
+8000
+0080
+8080
+8000
+0600
+0c00
+1800
+3000
+6000
+c080
+7980
+cf00
+8600
+cf00
+7980
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 10 9 2 0
+BITMAP
+0380
+0580
+0c00
+0c00
+0c00
+7f00
+1800
+1800
+1800
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 9 9 2 0
+BITMAP
+1800
+1800
+1800
+1800
+1800
+1800
+d000
+e000
+0c00
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 9 9 2 0
+BITMAP
+1e00
+1e00
+1e00
+6d80
+ff80
+ff80
+6d80
+0c00
+0800
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 10 9 2 0
+BITMAP
+1c00
+3e00
+7f00
+ff80
+7f00
+3e00
+1c00
+0800
+6300
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 1013 0
+DWIDTH 19 0
+BBX 17 8 1 1
+BITMAP
+f78080
+80ff80
+7f0000
+003e00
+1c0000
+000c00
+1e0000
+007f80
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 18 8 0 1
+BITMAP
+ffc0c0
+c06d80
+0c0000
+001800
+003000
+006000
+00ffc0
+80ffc0
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 25 1 -7
+BITMAP
+80
+60
+03
+00
+30
+06
+00
+18
+0c
+00
+18
+00
+00
+30
+00
+00
+60
+00
+00
+ff
+ff
+c0
+ff
+ff
+c0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 18 8 0 1
+BITMAP
+600000
+300000
+180000
+183c40
+db9900
+181800
+181800
+181800
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 22 1 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+00
+06
+00
+00
+03
+00
+00
+01
+80
+ff
+ff
+c0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 6 1 7
+BITMAP
+f8
+f8
+c0
+00
+00
+80
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+00
+03
+00
+00
+06
+00
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 8 5 0 9
+BITMAP
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 12 0 0
+BITMAP
+1800
+1800
+1800
+1880
+db00
+3c00
+7080
+8880
+d800
+1800
+1880
+ff00
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 10 9 0 0
+BITMAP
+1800
+00c0
+ff00
+7740
+cc80
+e000
+7800
+1e00
+0780
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 11 5 0 3
+BITMAP
+0180
+0780
+1e00
+7800
+e000
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+00
+00
+fe
+80
+fe
+80
+e0
+c0
+72
+80
+32
+00
+1e
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 5 6 2 2
+BITMAP
+08
+00
+18
+00
+30
+00
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 8 1 1
+BITMAP
+73
+80
+e1
+c0
+79
+e0
+cf
+00
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+86
+00
+cf
+00
+79
+e0
+78
+cc
+86
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 8 1 1
+BITMAP
+06
+06
+06
+3e
+66
+c6
+c6
+c6
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 7 1 2
+BITMAP
+c4
+ec
+78
+70
+f8
+f8
+f8
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 14 2 2 0
+BITMAP
+f870
+1818
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 2 25 4 -7
+BITMAP
+00
+c0
+c0
+00
+00
+00
+00
+00
+c0
+c0
+00
+c0
+c0
+00
+00
+c0
+c0
+00
+c0
+c0
+00
+c0
+c0
+40
+c0
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 1013 0
+DWIDTH 19 0
+BBX 19 2 0 4
+BITMAP
+ce0060
+ffcec0
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 9 12 1 0
+BITMAP
+0c80
+0c80
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+c0c0
+c0c0
+ffe0
+e0e0
+ffe0
+0180
+0180
+0180
+0180
+0180
+0180
+2180
+6180
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 10 15 1 -1
+BITMAP
+ff80
+ff80
+6000
+2000
+c200
+e3c0
+71c0
+38c0
+3980
+7d00
+cf00
+c700
+e300
+7380
+31c0
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 14 1 0
+BITMAP
+70c0
+f040
+1fc0
+3fc0
+6080
+4100
+4200
+2200
+1300
+0380
+01c0
+00c0
+00c0
+70c0
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 15 1 -4
+BITMAP
+f880
+1f00
+0e00
+79c0
+fee0
+8e70
+8630
+c660
+7680
+3640
+2660
+0660
+0660
+0660
+0660
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+6c70
+b830
+0c00
+1800
+31e0
+6730
+cc30
+d830
+d630
+f660
+64e0
+77c0
+b380
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+9800
+9800
+d800
+7000
+1f80
+39c0
+6060
+d9b0
+ddb0
+8f10
+8610
+8f10
+dbb0
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+d9b0
+6060
+39c0
+1f80
+1f80
+39c0
+6660
+c630
+c630
+bfd0
+bfd0
+8610
+c630
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 9 1 0
+BITMAP
+c630
+6060
+39c0
+1f80
+1fb0
+39f0
+6060
+c0f0
+c1b0
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 9 1 0
+BITMAP
+8310
+8610
+8c10
+d830
+f030
+6060
+f9c0
+df80
+1f80
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 9 1 0
+BITMAP
+39c0
+6060
+e070
+c030
+c030
+c030
+c030
+c030
+c030
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 12 0 -3
+BITMAP
+c030
+c030
+c030
+c030
+e070
+6060
+39c0
+1f80
+ff80
+ffe0
+0060
+0030
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 13 0 -2
+BITMAP
+0030
+0030
+0060
+ffe0
+ff80
+ff80
+ffe0
+0060
+0030
+0030
+0030
+0060
+ffe0
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 9 0 0
+BITMAP
+ff80
+0000
+fff0
+fff0
+0060
+00c0
+1ff0
+7ff0
+6180
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 12 0 -3
+BITMAP
+c300
+c300
+c600
+6600
+7ff0
+1ff0
+1800
+3000
+1ff0
+7ff0
+6000
+c000
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 9 9 1 0
+BITMAP
+c000
+c000
+6000
+7f80
+1f80
+1f80
+7f80
+6000
+c000
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 11 1 -1
+BITMAP
+c000
+c000
+6000
+7fc0
+1fc0
+0000
+ffc0
+ffc0
+1f80
+7f80
+e000
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 13 13 0 0
+BITMAP
+c000
+ff80
+c000
+e000
+7f80
+1f80
+0080
+1fc0
+7fc0
+e200
+c400
+ff80
+c800
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 13 1 0
+BITMAP
+f000
+7fc0
+3fc0
+4000
+0010
+0030
+0060
+00c0
+0180
+0300
+0600
+0c00
+1800
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+3000
+6000
+c000
+fff8
+fff0
+e020
+6060
+6040
+70c0
+3080
+3080
+3980
+1900
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+1b00
+0e00
+0e00
+0400
+1fc0
+38e0
+6030
+df18
+cd98
+cd98
+cd98
+cf18
+cd98
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 853 0
+DWIDTH 16 0
+BBX 14 8 1 5
+BITMAP
+dcd8
+6030
+38e0
+1fc0
+1fc0
+38e0
+6030
+c798
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 14 16 0 -2
+BITMAP
+cd98
+cc98
+cc18
+cc18
+cc98
+c718
+6030
+38e0
+1fc0
+ff1c
+ab18
+2318
+22a8
+22a8
+22a8
+2248
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 10 17 0 0
+BITMAP
+7740
+ffc0
+7000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+fcc0
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 2 1 4
+BITMAP
+00
+40
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 6 1 0
+BITMAP
+0040
+0040
+0080
+0080
+0080
+0080
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 9 0 0
+BITMAP
+3080
+7100
+d900
+1900
+1900
+0d00
+0d00
+0600
+0600
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 9 0 0
+BITMAP
+0600
+c0c0
+ffc0
+ffc0
+0040
+0040
+0040
+0040
+0c00
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 18 9 0 0
+BITMAP
+0c0000
+003300
+330040
+806180
+c0c0c0
+c0c0c0
+c0c040
+806180
+330000
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 16 9 1 0
+BITMAP
+001e
+000c
+000c
+0008
+0400
+1806
+003f
+ff00
+7fff
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+8080
+0180
+7f80
+8000
+ff00
+1800
+0000
+0400
+0800
+1800
+3f80
+7f80
+e000
+7f80
+3f80
+1800
+0800
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 16 9 1 0
+BITMAP
+0800
+1c00
+3600
+7700
+f780
+3600
+3600
+3600
+3600
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+3600
+3600
+3600
+3600
+3600
+3600
+3600
+3600
+0000
+0000
+ff80
+ff80
+0000
+ff80
+ff80
+0000
+0000
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 14 0 0
+BITMAP
+3600
+3600
+3600
+3600
+3600
+3600
+3600
+3600
+3600
+3600
+3600
+3600
+f780
+7700
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 17 0 -3
+BITMAP
+30
+00
+18
+00
+08
+00
+08
+00
+18
+00
+30
+00
+30
+00
+60
+00
+60
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+00c0
+80c0
+8060
+0060
+0030
+0030
+0018
+0008
+0018
+1830
+3060
+60c0
+c080
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+c0c0
+6060
+3030
+1818
+1fc0
+38e0
+6030
+cf18
+cd98
+cd98
+cf18
+cd98
+cd98
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 8 1 5
+BITMAP
+cd98
+6030
+38e0
+1fc0
+1fc0
+38e0
+6030
+c718
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 16 0 -2
+BITMAP
+cc90
+cc10
+cc10
+cc10
+cc90
+c710
+6030
+38e0
+1fc0
+fb10
+2310
+2310
+22a0
+22a0
+22a0
+2240
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 6 25 1 -7
+BITMAP
+20
+48
+fc
+e0
+e0
+60
+70
+20
+38
+00
+1c
+00
+0c
+00
+04
+00
+00
+00
+04
+00
+0c
+00
+18
+00
+30
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 2 25 1 -7
+BITMAP
+00
+40
+00
+c0
+00
+c0
+c0
+c0
+c0
+00
+00
+00
+00
+00
+00
+40
+40
+40
+40
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 6 25 1 -7
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 25 1 -7
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+e0
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 2 25 1 -7
+BITMAP
+40
+40
+40
+00
+00
+00
+00
+00
+00
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 22 1 -4
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 5 25 4 -7
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 5 25 1 -7
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+f8
+38
+60
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 5 22 4 -4
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+30
+e0
+e0
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 2 25 4 -7
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 17 0 -3
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+60
+38
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 22 0 -4
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+00
+c0
+c0
+60
+60
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 7 25 5 -7
+BITMAP
+30
+30
+18
+18
+08
+18
+18
+30
+30
+60
+60
+c0
+c0
+1c
+1c
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 2 25 0 -7
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+c0
+c0
+00
+40
+40
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 7 22 0 -4
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 6 25 0 -7
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+04
+04
+04
+04
+04
+04
+04
+04
+04
+04
+04
+04
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 2 25 4 -7
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+c0
+c0
+40
+80
+c0
+40
+40
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 6 25 0 -7
+BITMAP
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 25 1 -7
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+08
+08
+08
+08
+08
+08
+08
+08
+08
+08
+08
+08
+08
+08
+08
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 2 25 4 -7
+BITMAP
+00
+00
+00
+00
+00
+00
+40
+40
+c0
+80
+c0
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 22 1 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 5 25 1 -7
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 5 25 4 -7
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+18
+18
+f8
+e0
+30
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 5 22 1 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+60
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/symbol18.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/symbol18.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/symbol18.h	(revision 12606)
@@ -0,0 +1,1000 @@
+static unsigned char symbol18_0_bits[] = {
+0x00};
+static unsigned char symbol18_1_bits[] = {
+0x00};
+static unsigned char symbol18_2_bits[] = {
+0x00};
+static unsigned char symbol18_3_bits[] = {
+0x00};
+static unsigned char symbol18_4_bits[] = {
+0x00};
+static unsigned char symbol18_5_bits[] = {
+0x00};
+static unsigned char symbol18_6_bits[] = {
+0x00};
+static unsigned char symbol18_7_bits[] = {
+0x00};
+static unsigned char symbol18_8_bits[] = {
+0x00};
+static unsigned char symbol18_9_bits[] = {
+0x00};
+static unsigned char symbol18_10_bits[] = {
+0x00};
+static unsigned char symbol18_11_bits[] = {
+0x00};
+static unsigned char symbol18_12_bits[] = {
+0x00};
+static unsigned char symbol18_13_bits[] = {
+0x00};
+static unsigned char symbol18_14_bits[] = {
+0x00};
+static unsigned char symbol18_15_bits[] = {
+0x00};
+static unsigned char symbol18_16_bits[] = {
+0x00};
+static unsigned char symbol18_17_bits[] = {
+0x00};
+static unsigned char symbol18_18_bits[] = {
+0x00};
+static unsigned char symbol18_19_bits[] = {
+0x00};
+static unsigned char symbol18_20_bits[] = {
+0x00};
+static unsigned char symbol18_21_bits[] = {
+0x00};
+static unsigned char symbol18_22_bits[] = {
+0x00};
+static unsigned char symbol18_23_bits[] = {
+0x00};
+static unsigned char symbol18_24_bits[] = {
+0x00};
+static unsigned char symbol18_25_bits[] = {
+0x00};
+static unsigned char symbol18_26_bits[] = {
+0x00};
+static unsigned char symbol18_27_bits[] = {
+0x00};
+static unsigned char symbol18_28_bits[] = {
+0x00};
+static unsigned char symbol18_29_bits[] = {
+0x00};
+static unsigned char symbol18_30_bits[] = {
+0x00};
+static unsigned char symbol18_31_bits[] = {
+0x00};
+static unsigned char symbol18_32_bits[] = {
+0x00};
+static unsigned char symbol18_33_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x00, 0x00, 0x03, 
+0x03};
+static unsigned char symbol18_34_bits[] = {
+0x03, 0x18, 0x03, 0x18, 0x06, 0x0c, 0x06, 0x0c, 0xfc, 0x07, 0x0c, 0x06, 
+0x18, 0x03, 0x18, 0x03, 0x10, 0x01, 0xb0, 0x01, 0xa0, 0x00, 0xe0, 0x00, 
+0x40, 0x00};
+static unsigned char symbol18_35_bits[] = {
+0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0xfe, 0x03, 0x48, 0x00, 
+0x48, 0x00, 0x48, 0x00, 0xff, 0x01, 0x24, 0x00, 0x24, 0x00, 0x24, 0x00, 
+0x24, 0x00};
+static unsigned char symbol18_36_bits[] = {
+0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 
+0xff};
+static unsigned char symbol18_37_bits[] = {
+0x1c, 0x06, 0xe6, 0x07, 0x23, 0x03, 0xa3, 0x01, 0x97, 0x01, 0xce, 0x00, 
+0x60, 0x00, 0x60, 0x0e, 0x30, 0x13, 0x98, 0x11, 0x98, 0x11, 0x8c, 0x0b, 
+0x0c, 0x07};
+static unsigned char symbol18_38_bits[] = {
+0x38, 0x00, 0x6c, 0x00, 0x44, 0x00, 0x64, 0x00, 0x3c, 0x00, 0x9c, 0x07, 
+0x3e, 0x03, 0x77, 0x01, 0xe3, 0x01, 0xc3, 0x00, 0xc3, 0x09, 0xe6, 0x0f, 
+0x3c, 0x07};
+static unsigned char symbol18_39_bits[] = {
+0x0f, 0x1c, 0x38, 0x30, 0x3e, 0x30, 0x38, 0x1c, 0x0f};
+static unsigned char symbol18_40_bits[] = {
+0x08, 0x0c, 0x06, 0x06, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x06, 0x06, 0x0c, 0x08};
+static unsigned char symbol18_41_bits[] = {
+0x01, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x06, 0x06, 0x03, 0x01};
+static unsigned char symbol18_42_bits[] = {
+0x08, 0x6b, 0x3e, 0x1c, 0x3e, 0x6b, 0x08};
+static unsigned char symbol18_43_bits[] = {
+0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18};
+static unsigned char symbol18_44_bits[] = {
+0x06, 0x06, 0x04, 0x06, 0x03};
+static unsigned char symbol18_45_bits[] = {
+0x7f, 0x7f};
+static unsigned char symbol18_46_bits[] = {
+0x03, 0x03};
+static unsigned char symbol18_47_bits[] = {
+0x18, 0x18, 0x18, 0x0c, 0x0c, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_48_bits[] = {
+0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x66, 
+0x3c};
+static unsigned char symbol18_49_bits[] = {
+0x08, 0x0c, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x3f};
+static unsigned char symbol18_50_bits[] = {
+0x3c, 0x7e, 0x73, 0x61, 0x60, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x43, 0x7f, 
+0x7f};
+static unsigned char symbol18_51_bits[] = {
+0x3e, 0x73, 0x61, 0x60, 0x30, 0x1c, 0x38, 0x70, 0x60, 0x60, 0x60, 0x33, 
+0x1f};
+static unsigned char symbol18_52_bits[] = {
+0x60, 0x70, 0x70, 0x78, 0x6c, 0x6c, 0x66, 0x63, 0x63, 0xff, 0x60, 0x60, 
+0x60};
+static unsigned char symbol18_53_bits[] = {
+0x7e, 0x3e, 0x03, 0x03, 0x0f, 0x3c, 0x30, 0x70, 0x60, 0x60, 0x30, 0x3b, 
+0x0f};
+static unsigned char symbol18_54_bits[] = {
+0x70, 0x1c, 0x0c, 0x06, 0x06, 0x3f, 0x63, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 
+0x3c};
+static unsigned char symbol18_55_bits[] = {
+0xfe, 0xff, 0x61, 0x60, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, 0x0c, 0x0c, 
+0x0c};
+static unsigned char symbol18_56_bits[] = {
+0x3c, 0x66, 0x46, 0x46, 0x6e, 0x3c, 0x7c, 0xe6, 0xc3, 0xc3, 0xc3, 0x66, 
+0x3c};
+static unsigned char symbol18_57_bits[] = {
+0x3c, 0x76, 0xe3, 0xc3, 0xc3, 0xc3, 0xc7, 0xfe, 0x5c, 0x60, 0x30, 0x1c, 
+0x07};
+static unsigned char symbol18_58_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03};
+static unsigned char symbol18_59_bits[] = {
+0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x04, 0x06, 0x03};
+static unsigned char symbol18_60_bits[] = {
+0xc0, 0x01, 0xf0, 0x00, 0x3c, 0x00, 0x0f, 0x00, 0x03, 0x00, 0x0f, 0x00, 
+0x3c, 0x00, 0xf0, 0x00, 0xc0, 0x01};
+static unsigned char symbol18_61_bits[] = {
+0xff, 0xff, 0x00, 0x00, 0xff, 0xff};
+static unsigned char symbol18_62_bits[] = {
+0x07, 0x00, 0x1e, 0x00, 0x78, 0x00, 0xe0, 0x01, 0x80, 0x01, 0xe0, 0x01, 
+0x78, 0x00, 0x1e, 0x00, 0x07, 0x00};
+static unsigned char symbol18_63_bits[] = {
+0x1e, 0x3b, 0x33, 0x33, 0x30, 0x30, 0x18, 0x0c, 0x04, 0x04, 0x00, 0x06, 
+0x06};
+static unsigned char symbol18_64_bits[] = {
+0xce, 0xff, 0x73, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff};
+static unsigned char symbol18_65_bits[] = {
+0x20, 0x00, 0x70, 0x00, 0x70, 0x00, 0xd0, 0x00, 0xd8, 0x00, 0xc8, 0x00, 
+0x88, 0x01, 0x8c, 0x01, 0xfc, 0x03, 0x04, 0x03, 0x06, 0x03, 0x06, 0x07, 
+0x8f, 0x0f};
+static unsigned char symbol18_66_bits[] = {
+0x3f, 0x00, 0x66, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0x66, 0x00, 
+0x7e, 0x00, 0xc6, 0x00, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 0xc6, 0x01, 
+0xff, 0x00};
+static unsigned char symbol18_67_bits[] = {
+0x0f, 0x0e, 0x0e, 0x06, 0x1c, 0x03, 0x18, 0x03, 0xb8, 0x01, 0xf0, 0x00, 
+0x60, 0x00, 0xf0, 0x00, 0xd8, 0x01, 0x8c, 0x01, 0x8c, 0x03, 0x06, 0x07, 
+0x07, 0x0f};
+static unsigned char symbol18_68_bits[] = {
+0x20, 0x00, 0x60, 0x00, 0x70, 0x00, 0xd0, 0x00, 0xc8, 0x00, 0xc8, 0x00, 
+0x88, 0x01, 0x84, 0x01, 0x84, 0x03, 0x02, 0x03, 0x02, 0x03, 0x01, 0x06, 
+0xff, 0x07};
+static unsigned char symbol18_69_bits[] = {
+0xff, 0x01, 0x86, 0x01, 0x06, 0x01, 0x06, 0x00, 0x06, 0x00, 0x86, 0x00, 
+0xfe, 0x00, 0x86, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x01, 0x86, 0x01, 
+0xff, 0x01};
+static unsigned char symbol18_70_bits[] = {
+0xf0, 0x00, 0x60, 0x00, 0xf8, 0x01, 0x66, 0x06, 0x63, 0x0c, 0x63, 0x0c, 
+0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x66, 0x06, 0xf8, 0x01, 0x60, 0x00, 
+0xf0, 0x00};
+static unsigned char symbol18_71_bits[] = {
+0xff, 0x03, 0x0e, 0x03, 0x0c, 0x02, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x1e, 0x00};
+static unsigned char symbol18_72_bits[] = {
+0x8f, 0x07, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0xfe, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x8f, 0x07};
+static unsigned char symbol18_73_bits[] = {
+0x0f, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char symbol18_74_bits[] = {
+0x60, 0x00, 0xd0, 0x00, 0x90, 0x01, 0xa0, 0x01, 0xc6, 0x01, 0x8f, 0x01, 
+0x8d, 0x03, 0x8c, 0x05, 0x8c, 0x01, 0x8c, 0x01, 0x8c, 0x01, 0xdc, 0x00, 
+0x78, 0x00};
+static unsigned char symbol18_75_bits[] = {
+0xcf, 0x03, 0x86, 0x01, 0xc6, 0x00, 0x66, 0x00, 0x36, 0x00, 0x1e, 0x00, 
+0x1e, 0x00, 0x36, 0x00, 0x66, 0x00, 0xc6, 0x00, 0xc6, 0x01, 0x86, 0x03, 
+0x8f, 0x07};
+static unsigned char symbol18_76_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x98, 0x01, 
+0x88, 0x01, 0x88, 0x01, 0x0c, 0x03, 0x04, 0x03, 0x04, 0x06, 0x06, 0x06, 
+0x0f, 0x0f};
+static unsigned char symbol18_77_bits[] = {
+0x07, 0x38, 0x0e, 0x1c, 0x0e, 0x1c, 0x1a, 0x1e, 0x1a, 0x1a, 0x1a, 0x1b, 
+0x32, 0x19, 0x32, 0x19, 0xb2, 0x19, 0xe2, 0x18, 0xe2, 0x18, 0xc2, 0x18, 
+0x47, 0x3c};
+static unsigned char symbol18_78_bits[] = {
+0x07, 0x07, 0x0e, 0x02, 0x0e, 0x02, 0x1a, 0x02, 0x32, 0x02, 0x32, 0x02, 
+0x62, 0x02, 0xc2, 0x02, 0xc2, 0x03, 0x82, 0x03, 0x02, 0x03, 0x02, 0x03, 
+0x07, 0x02};
+static unsigned char symbol18_79_bits[] = {
+0x70, 0x00, 0x8c, 0x01, 0x06, 0x03, 0x07, 0x07, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x07, 0x07, 0x06, 0x03, 0x8c, 0x01, 
+0x70, 0x00};
+static unsigned char symbol18_80_bits[] = {
+0xff, 0x07, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x8f, 0x07};
+static unsigned char symbol18_81_bits[] = {
+0x70, 0x00, 0x8c, 0x01, 0x06, 0x03, 0x07, 0x07, 0x03, 0x06, 0x8b, 0x06, 
+0xfb, 0x06, 0x8b, 0x06, 0x03, 0x06, 0x07, 0x07, 0x06, 0x03, 0x8c, 0x01, 
+0x70, 0x00};
+static unsigned char symbol18_82_bits[] = {
+0x7f, 0xe6, 0xc6, 0xc6, 0xc6, 0xe6, 0x7e, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char symbol18_83_bits[] = {
+0xff, 0x01, 0x83, 0x01, 0x06, 0x01, 0x0c, 0x00, 0x18, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x02, 0x02, 0x03, 0xff, 0x01, 
+0xff, 0x01};
+static unsigned char symbol18_84_bits[] = {
+0xff, 0x03, 0x33, 0x03, 0x31, 0x02, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x78, 0x00};
+static unsigned char symbol18_85_bits[] = {
+0x1f, 0x0f, 0x0e, 0x06, 0x0c, 0x03, 0x18, 0x03, 0xb8, 0x01, 0xf0, 0x00, 
+0xf0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0xf0, 0x00};
+static unsigned char symbol18_86_bits[] = {
+0x3c, 0x3e, 0x03, 0x01, 0x01, 0x01, 0x03, 0x1e, 0x3c, 0x20, 0x20, 0x3c, 
+0x1c};
+static unsigned char symbol18_87_bits[] = {
+0xe0, 0x00, 0x18, 0x03, 0x0c, 0x06, 0x0e, 0x0e, 0x06, 0x0c, 0x06, 0x0c, 
+0x06, 0x0c, 0x06, 0x0c, 0x0c, 0x06, 0x18, 0x03, 0x11, 0x11, 0x1f, 0x1f, 
+0x1f, 0x1f};
+static unsigned char symbol18_88_bits[] = {
+0xfe, 0x01, 0xfe, 0x01, 0x02, 0x01, 0x00, 0x00, 0x84, 0x00, 0xfc, 0x00, 
+0xfc, 0x00, 0x84, 0x00, 0x00, 0x00, 0x01, 0x02, 0x01, 0x02, 0xff, 0x03, 
+0xff, 0x03};
+static unsigned char symbol18_89_bits[] = {
+0xe3, 0x31, 0xc6, 0x18, 0xc6, 0x18, 0xc6, 0x18, 0xc6, 0x18, 0xcc, 0x0c, 
+0xf8, 0x07, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xe0, 0x01};
+static unsigned char symbol18_90_bits[] = {
+0xff, 0x01, 0xc3, 0x01, 0xc1, 0x00, 0xe0, 0x00, 0x60, 0x00, 0x70, 0x00, 
+0x38, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x0e, 0x00, 0x06, 0x01, 0x87, 0x01, 
+0xff, 0x01};
+static unsigned char symbol18_91_bits[] = {
+0x0f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x0f};
+static unsigned char symbol18_92_bits[] = {
+0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol18_93_bits[] = {
+0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0f};
+static unsigned char symbol18_94_bits[] = {
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xff, 0x03, 
+0xff, 0x03};
+static unsigned char symbol18_95_bits[] = {
+0xff, 0x01, 0xff, 0x01};
+static unsigned char symbol18_96_bits[] = {
+0xff, 0x03};
+static unsigned char symbol18_97_bits[] = {
+0x3c, 0x03, 0xa6, 0x01, 0xc3, 0x00, 0xc3, 0x00, 0xc3, 0x00, 0xc3, 0x00, 
+0xc3, 0x00, 0xa6, 0x04, 0x1c, 0x03};
+static unsigned char symbol18_98_bits[] = {
+0x3c, 0x62, 0x63, 0x63, 0x63, 0x33, 0x63, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 
+0x67, 0x3b, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol18_99_bits[] = {
+0x06, 0x03, 0x8f, 0x03, 0x89, 0x01, 0xc8, 0x00, 0xe8, 0x00, 0x70, 0x00, 
+0x30, 0x00, 0x38, 0x00, 0x58, 0x00, 0x4c, 0x00, 0x46, 0x02, 0xc7, 0x03, 
+0x83, 0x01};
+static unsigned char symbol18_100_bits[] = {
+0x1c, 0x32, 0x02, 0x06, 0x0c, 0x1c, 0x36, 0x63, 0x63, 0x63, 0x63, 0x63, 
+0x36, 0x1c};
+static unsigned char symbol18_101_bits[] = {
+0x1e, 0x37, 0x33, 0x03, 0x0e, 0x03, 0x03, 0x27, 0x1e};
+static unsigned char symbol18_102_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x7c, 0x00, 0xd6, 0x00, 0x93, 0x01, 
+0x93, 0x01, 0x93, 0x01, 0x93, 0x01, 0x93, 0x01, 0xd6, 0x00, 0x7c, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char symbol18_103_bits[] = {
+0xc3, 0xc7, 0xc5, 0x64, 0x64, 0x68, 0x28, 0x38, 0x30, 0x18, 0x18, 0x18, 
+0x18};
+static unsigned char symbol18_104_bits[] = {
+0xe6, 0x00, 0x97, 0x01, 0x8d, 0x01, 0x8c, 0x01, 0x8c, 0x01, 0x8c, 0x01, 
+0x8c, 0x01, 0x8c, 0x01, 0x8c, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 
+0x80, 0x01};
+static unsigned char symbol18_105_bits[] = {
+0x06, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x16, 0x0e};
+static unsigned char symbol18_106_bits[] = {
+0x66, 0x00, 0xf3, 0x00, 0x93, 0x01, 0x93, 0x01, 0x93, 0x01, 0x93, 0x01, 
+0x92, 0x00, 0xd6, 0x00, 0x7c, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x10, 0x00};
+static unsigned char symbol18_107_bits[] = {
+0xc6, 0x01, 0xa7, 0x01, 0x16, 0x00, 0x1e, 0x00, 0x3e, 0x00, 0x76, 0x00, 
+0xe6, 0x00, 0xc6, 0x01, 0x86, 0x01};
+static unsigned char symbol18_108_bits[] = {
+0x0c, 0x00, 0x1e, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x38, 0x00, 0x38, 0x00, 0x2c, 0x00, 0x2c, 0x00, 0x66, 0x00, 0x46, 0x02, 
+0xc3, 0x03, 0x83, 0x01};
+static unsigned char symbol18_109_bits[] = {
+0x42, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 
+0x63, 0x01, 0xdf, 0x01, 0xde, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00};
+static unsigned char symbol18_110_bits[] = {
+0xc3, 0xc3, 0x86, 0x46, 0x4c, 0x2c, 0x38, 0x18, 0x10};
+static unsigned char symbol18_111_bits[] = {
+0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c};
+static unsigned char symbol18_112_bits[] = {
+0xfe, 0x01, 0xff, 0x01, 0x49, 0x00, 0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 
+0x4c, 0x01, 0xce, 0x01, 0xc6, 0x00};
+static unsigned char symbol18_113_bits[] = {
+0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 
+0x3c};
+static unsigned char symbol18_114_bits[] = {
+0x3c, 0x62, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x67, 0x3b, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_115_bits[] = {
+0xf8, 0x03, 0xfe, 0x03, 0x66, 0x00, 0xc3, 0x00, 0xc3, 0x00, 0xc3, 0x00, 
+0xc3, 0x00, 0x66, 0x00, 0x3c, 0x00};
+static unsigned char symbol18_116_bits[] = {
+0x7e, 0x7f, 0x09, 0x08, 0x08, 0x08, 0x48, 0x78, 0x38};
+static unsigned char symbol18_117_bits[] = {
+0xc6, 0x00, 0x8f, 0x01, 0x8d, 0x01, 0x8c, 0x01, 0x8c, 0x01, 0x8c, 0x01, 
+0x8c, 0x01, 0xdc, 0x00, 0x78, 0x00};
+static unsigned char symbol18_118_bits[] = {
+0xfc, 0x07, 0xfe, 0x07, 0x99, 0x01, 0x0c, 0x03, 0x04, 0x02, 0x66, 0x06, 
+0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x6c, 0x03, 0x9c, 0x03};
+static unsigned char symbol18_119_bits[] = {
+0xcc, 0x00, 0x86, 0x01, 0x02, 0x01, 0x33, 0x03, 0x33, 0x03, 0x33, 0x03, 
+0x33, 0x03, 0xb6, 0x01, 0xce, 0x01};
+static unsigned char symbol18_120_bits[] = {
+0x06, 0x71, 0x3f, 0x04, 0x02, 0x02, 0x3e, 0x1e, 0x03, 0x01, 0x01, 0x01, 
+0x03, 0x3f, 0x7e, 0x40, 0x40, 0x78, 0x38};
+static unsigned char symbol18_121_bits[] = {
+0x47, 0x1c, 0x4e, 0x0e, 0x4c, 0x06, 0x4c, 0x06, 0x4c, 0x06, 0x4c, 0x06, 
+0x58, 0x03, 0x58, 0x03, 0xf0, 0x01, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 
+0x40, 0x00};
+static unsigned char symbol18_122_bits[] = {
+0x06, 0x61, 0x79, 0x1e, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x03, 0x3f, 0x7e, 0x40, 0x40, 0x78, 0x38};
+static unsigned char symbol18_123_bits[] = {
+0x70, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x18, 0x70};
+static unsigned char symbol18_124_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol18_125_bits[] = {
+0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x60, 0x30, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x0c, 0x07};
+static unsigned char symbol18_126_bits[] = {
+0xce, 0xff, 0x73};
+static unsigned char symbol18_127_bits[] = {
+0x00};
+static unsigned char symbol18_128_bits[] = {
+0x00};
+static unsigned char symbol18_129_bits[] = {
+0x00};
+static unsigned char symbol18_130_bits[] = {
+0x00};
+static unsigned char symbol18_131_bits[] = {
+0x00};
+static unsigned char symbol18_132_bits[] = {
+0x00};
+static unsigned char symbol18_133_bits[] = {
+0x00};
+static unsigned char symbol18_134_bits[] = {
+0x00};
+static unsigned char symbol18_135_bits[] = {
+0x00};
+static unsigned char symbol18_136_bits[] = {
+0x00};
+static unsigned char symbol18_137_bits[] = {
+0x00};
+static unsigned char symbol18_138_bits[] = {
+0x00};
+static unsigned char symbol18_139_bits[] = {
+0x00};
+static unsigned char symbol18_140_bits[] = {
+0x00};
+static unsigned char symbol18_141_bits[] = {
+0x00};
+static unsigned char symbol18_142_bits[] = {
+0x00};
+static unsigned char symbol18_143_bits[] = {
+0x00};
+static unsigned char symbol18_144_bits[] = {
+0x00};
+static unsigned char symbol18_145_bits[] = {
+0x00};
+static unsigned char symbol18_146_bits[] = {
+0x00};
+static unsigned char symbol18_147_bits[] = {
+0x00};
+static unsigned char symbol18_148_bits[] = {
+0x00};
+static unsigned char symbol18_149_bits[] = {
+0x00};
+static unsigned char symbol18_150_bits[] = {
+0x00};
+static unsigned char symbol18_151_bits[] = {
+0x00};
+static unsigned char symbol18_152_bits[] = {
+0x00};
+static unsigned char symbol18_153_bits[] = {
+0x00};
+static unsigned char symbol18_154_bits[] = {
+0x00};
+static unsigned char symbol18_155_bits[] = {
+0x00};
+static unsigned char symbol18_156_bits[] = {
+0x00};
+static unsigned char symbol18_157_bits[] = {
+0x00};
+static unsigned char symbol18_158_bits[] = {
+0x00};
+static unsigned char symbol18_159_bits[] = {
+0x00};
+static unsigned char symbol18_160_bits[] = {
+0x00};
+static unsigned char symbol18_161_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00};
+static unsigned char symbol18_162_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol18_163_bits[] = {
+0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x04, 0x00, 0x06, 0x00, 0x06, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol18_164_bits[] = {
+0x00, 0x30, 0x00, 0x78, 0x00, 0x0c, 0x0e, 0x06, 0x03, 0x01, 0xc0, 0x01, 
+0xf0};
+static unsigned char symbol18_165_bits[] = {
+0x00, 0x0c, 0x00, 0x0f, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x0c};
+static unsigned char symbol18_166_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 
+0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x03, 0x01, 
+0x9e, 0x01, 0xf3, 0x00, 0x61, 0x00, 0xf3, 0x00, 0x9e, 0x01};
+static unsigned char symbol18_167_bits[] = {
+0xc0, 0x01, 0xa0, 0x01, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xfe, 0x00, 
+0x18, 0x00, 0x18, 0x00, 0x18, 0x00};
+static unsigned char symbol18_168_bits[] = {
+0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 
+0x0b, 0x00, 0x07, 0x00, 0x30, 0x00};
+static unsigned char symbol18_169_bits[] = {
+0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0xb6, 0x01, 0xff, 0x01, 0xff, 0x01, 
+0xb6, 0x01, 0x30, 0x00, 0x10, 0x00};
+static unsigned char symbol18_170_bits[] = {
+0x38, 0x00, 0x7c, 0x00, 0xfe, 0x00, 0xff, 0x01, 0xfe, 0x00, 0x7c, 0x00, 
+0x38, 0x00, 0x10, 0x00, 0xc6, 0x00};
+static unsigned char symbol18_171_bits[] = {
+0xef, 0x01, 0x01, 0x01, 0xff, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x7c, 0x00, 
+0x38, 0x00, 0x00, 0x00, 0x30, 0x00, 0x78, 0x00, 0x00, 0x00, 0xfe, 0x01};
+static unsigned char symbol18_172_bits[] = {
+0xff, 0x03, 0x03, 0x03, 0xb6, 0x01, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 
+0x00, 0x0c, 0x00, 0x00, 0x06, 0x00, 0x00, 0xff, 0x03, 0x01, 0xff, 0x03};
+static unsigned char symbol18_173_bits[] = {
+0x01, 0x06, 0xc0, 0x00, 0x0c, 0x60, 0x00, 0x18, 0x30, 0x00, 0x18, 0x00, 
+0x00, 0x0c, 0x00, 0x00, 0x06, 0x00, 0x00, 0xff, 0xff, 0x03, 0xff, 0xff, 
+0x03};
+static unsigned char symbol18_174_bits[] = {
+0x06, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x3c, 0x02, 
+0xdb, 0x99, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00};
+static unsigned char symbol18_175_bits[] = {
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x60, 
+0x00, 0x00, 0xc0, 0x00, 0x00, 0x80, 0x01, 0xff, 0xff, 0x03};
+static unsigned char symbol18_176_bits[] = {
+0x1f, 0x1f, 0x03, 0x00, 0x00, 0x01};
+static unsigned char symbol18_177_bits[] = {
+0x00, 0xc0, 0x00, 0x00, 0x60, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18};
+static unsigned char symbol18_178_bits[] = {
+0x18, 0x18, 0x18, 0x18, 0x18};
+static unsigned char symbol18_179_bits[] = {
+0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x01, 0xdb, 0x00, 0x3c, 0x00, 
+0x0e, 0x01, 0x11, 0x01, 0x1b, 0x00, 0x18, 0x00, 0x18, 0x01, 0xff, 0x00};
+static unsigned char symbol18_180_bits[] = {
+0x18, 0x00, 0x00, 0x03, 0xff, 0x00, 0xee, 0x02, 0x33, 0x01, 0x07, 0x00, 
+0x1e, 0x00, 0x78, 0x00, 0xe0, 0x01};
+static unsigned char symbol18_181_bits[] = {
+0x80, 0x01, 0xe0, 0x01, 0x78, 0x00, 0x1e, 0x00, 0x07, 0x00};
+static unsigned char symbol18_182_bits[] = {
+0x00, 0x00, 0x7f, 0x01, 0x7f, 0x01, 0x07, 0x03, 0x4e, 0x01, 0x4c, 0x00, 
+0x78, 0x00};
+static unsigned char symbol18_183_bits[] = {
+0x10, 0x00, 0x18, 0x00, 0x0c, 0x00};
+static unsigned char symbol18_184_bits[] = {
+0xce, 0x01, 0x87, 0x03, 0x9e, 0x07, 0xf3, 0x00};
+static unsigned char symbol18_185_bits[] = {
+0x61, 0x00, 0xf3, 0x00, 0x9e, 0x07, 0x1e, 0x33, 0x61};
+static unsigned char symbol18_186_bits[] = {
+0x60, 0x60, 0x60, 0x7c, 0x66, 0x63, 0x63, 0x63};
+static unsigned char symbol18_187_bits[] = {
+0x23, 0x37, 0x1e, 0x0e, 0x1f, 0x1f, 0x1f};
+static unsigned char symbol18_188_bits[] = {
+0x1f, 0x0e, 0x18, 0x18};
+static unsigned char symbol18_189_bits[] = {
+0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 
+0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x02, 
+0x03};
+static unsigned char symbol18_190_bits[] = {
+0x73, 0x00, 0x06, 0xff, 0x73, 0x03};
+static unsigned char symbol18_191_bits[] = {
+0x30, 0x01, 0x30, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 
+0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01};
+static unsigned char symbol18_192_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0xff, 0x07, 0x07, 0x07, 0xff, 0x07, 0x80, 0x01, 
+0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x84, 0x01, 
+0x86, 0x01};
+static unsigned char symbol18_193_bits[] = {
+0xff, 0x01, 0xff, 0x01, 0x06, 0x00, 0x04, 0x00, 0x43, 0x00, 0xc7, 0x03, 
+0x8e, 0x03, 0x1c, 0x03, 0x9c, 0x01, 0xbe, 0x00, 0xf3, 0x00, 0xe3, 0x00, 
+0xc7, 0x00, 0xce, 0x01, 0x8c, 0x03};
+static unsigned char symbol18_194_bits[] = {
+0x0e, 0x03, 0x0f, 0x02, 0xf8, 0x03, 0xfc, 0x03, 0x06, 0x01, 0x82, 0x00, 
+0x42, 0x00, 0x44, 0x00, 0xc8, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x03, 
+0x00, 0x03, 0x0e, 0x03};
+static unsigned char symbol18_195_bits[] = {
+0x1f, 0x01, 0xf8, 0x00, 0x70, 0x00, 0x9e, 0x03, 0x7f, 0x07, 0x71, 0x0e, 
+0x61, 0x0c, 0x63, 0x06, 0x6e, 0x01, 0x6c, 0x02, 0x64, 0x06, 0x60, 0x06, 
+0x60, 0x06, 0x60, 0x06, 0x60, 0x06};
+static unsigned char symbol18_196_bits[] = {
+0x36, 0x0e, 0x1d, 0x0c, 0x30, 0x00, 0x18, 0x00, 0x8c, 0x07, 0xe6, 0x0c, 
+0x33, 0x0c, 0x1b, 0x0c, 0x6b, 0x0c, 0x6f, 0x06, 0x26, 0x07, 0xee, 0x03, 
+0xcd, 0x01};
+static unsigned char symbol18_197_bits[] = {
+0x19, 0x00, 0x19, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0xf8, 0x01, 0x9c, 0x03, 
+0x06, 0x06, 0x9b, 0x0d, 0xbb, 0x0d, 0xf1, 0x08, 0x61, 0x08, 0xf1, 0x08, 
+0xdb, 0x0d};
+static unsigned char symbol18_198_bits[] = {
+0x9b, 0x0d, 0x06, 0x06, 0x9c, 0x03, 0xf8, 0x01, 0xf8, 0x01, 0x9c, 0x03, 
+0x66, 0x06, 0x63, 0x0c, 0x63, 0x0c, 0xfd, 0x0b, 0xfd, 0x0b, 0x61, 0x08, 
+0x63, 0x0c};
+static unsigned char symbol18_199_bits[] = {
+0x63, 0x0c, 0x06, 0x06, 0x9c, 0x03, 0xf8, 0x01, 0xf8, 0x0d, 0x9c, 0x0f, 
+0x06, 0x06, 0x03, 0x0f, 0x83, 0x0d};
+static unsigned char symbol18_200_bits[] = {
+0xc1, 0x08, 0x61, 0x08, 0x31, 0x08, 0x1b, 0x0c, 0x0f, 0x0c, 0x06, 0x06, 
+0x9f, 0x03, 0xfb, 0x01, 0xf8, 0x01};
+static unsigned char symbol18_201_bits[] = {
+0x9c, 0x03, 0x06, 0x06, 0x07, 0x0e, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 
+0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c};
+static unsigned char symbol18_202_bits[] = {
+0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x07, 0x0e, 0x06, 0x06, 
+0x9c, 0x03, 0xf8, 0x01, 0xff, 0x01, 0xff, 0x07, 0x00, 0x06, 0x00, 0x0c};
+static unsigned char symbol18_203_bits[] = {
+0x00, 0x0c, 0x00, 0x0c, 0x00, 0x06, 0xff, 0x07, 0xff, 0x01, 0xff, 0x01, 
+0xff, 0x07, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x06, 
+0xff, 0x07};
+static unsigned char symbol18_204_bits[] = {
+0xff, 0x01, 0x00, 0x00, 0xff, 0x0f, 0xff, 0x0f, 0x00, 0x06, 0x00, 0x03, 
+0xf8, 0x0f, 0xfe, 0x0f, 0x86, 0x01};
+static unsigned char symbol18_205_bits[] = {
+0xc3, 0x00, 0xc3, 0x00, 0x63, 0x00, 0x66, 0x00, 0xfe, 0x0f, 0xf8, 0x0f, 
+0x18, 0x00, 0x0c, 0x00, 0xf8, 0x0f, 0xfe, 0x0f, 0x06, 0x00, 0x03, 0x00};
+static unsigned char symbol18_206_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0xfe, 0x01, 0xf8, 0x01, 0xf8, 0x01, 
+0xfe, 0x01, 0x06, 0x00, 0x03, 0x00};
+static unsigned char symbol18_207_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0xfe, 0x03, 0xf8, 0x03, 0x00, 0x00, 
+0xff, 0x03, 0xff, 0x03, 0xf8, 0x01, 0xfe, 0x01, 0x07, 0x00};
+static unsigned char symbol18_208_bits[] = {
+0x03, 0x00, 0xff, 0x01, 0x03, 0x00, 0x07, 0x00, 0xfe, 0x01, 0xf8, 0x01, 
+0x00, 0x01, 0xf8, 0x03, 0xfe, 0x03, 0x47, 0x00, 0x23, 0x00, 0xff, 0x01, 
+0x13, 0x00};
+static unsigned char symbol18_209_bits[] = {
+0x0f, 0x00, 0xfe, 0x03, 0xfc, 0x03, 0x02, 0x00, 0x00, 0x08, 0x00, 0x0c, 
+0x00, 0x06, 0x00, 0x03, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 
+0x18, 0x00};
+static unsigned char symbol18_210_bits[] = {
+0x0c, 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x1f, 0xff, 0x0f, 0x07, 0x04, 
+0x06, 0x06, 0x06, 0x02, 0x0e, 0x03, 0x0c, 0x01, 0x0c, 0x01, 0x9c, 0x01, 
+0x98, 0x00};
+static unsigned char symbol18_211_bits[] = {
+0xd8, 0x00, 0x70, 0x00, 0x70, 0x00, 0x20, 0x00, 0xf8, 0x03, 0x1c, 0x07, 
+0x06, 0x0c, 0xfb, 0x18, 0xb3, 0x19, 0xb3, 0x19, 0xb3, 0x19, 0xf3, 0x18, 
+0xb3, 0x19};
+static unsigned char symbol18_212_bits[] = {
+0x3b, 0x1b, 0x06, 0x0c, 0x1c, 0x07, 0xf8, 0x03, 0xf8, 0x03, 0x1c, 0x07, 
+0x06, 0x0c, 0xe3, 0x19};
+static unsigned char symbol18_213_bits[] = {
+0xb3, 0x19, 0x33, 0x19, 0x33, 0x18, 0x33, 0x18, 0x33, 0x19, 0xe3, 0x18, 
+0x06, 0x0c, 0x1c, 0x07, 0xf8, 0x03, 0xff, 0x38, 0xd5, 0x18, 0xc4, 0x18, 
+0x44, 0x15, 0x44, 0x15, 0x44, 0x15, 0x44, 0x12};
+static unsigned char symbol18_214_bits[] = {
+0xee, 0x02, 0xff, 0x03, 0x0e, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x3f, 0x03};
+static unsigned char symbol18_215_bits[] = {
+0x00, 0x02};
+static unsigned char symbol18_216_bits[] = {
+0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01};
+static unsigned char symbol18_217_bits[] = {
+0x0c, 0x01, 0x8e, 0x00, 0x9b, 0x00, 0x98, 0x00, 0x98, 0x00, 0xb0, 0x00, 
+0xb0, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char symbol18_218_bits[] = {
+0x60, 0x00, 0x03, 0x03, 0xff, 0x03, 0xff, 0x03, 0x00, 0x02, 0x00, 0x02, 
+0x00, 0x02, 0x00, 0x02, 0x30, 0x00};
+static unsigned char symbol18_219_bits[] = {
+0x30, 0x00, 0x00, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0x02, 0x01, 0x86, 0x01, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x01, 0x86, 0x01, 
+0xcc, 0x00, 0x00};
+static unsigned char symbol18_220_bits[] = {
+0x00, 0x78, 0x00, 0x30, 0x00, 0x30, 0x00, 0x10, 0x20, 0x00, 0x18, 0x60, 
+0x00, 0xfc, 0xff, 0x00, 0xfe, 0xff};
+static unsigned char symbol18_221_bits[] = {
+0x01, 0x01, 0x80, 0x01, 0xfe, 0x01, 0x01, 0x00, 0xff, 0x00, 0x18, 0x00, 
+0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x18, 0x00, 0xfc, 0x01, 0xfe, 0x01, 
+0x07, 0x00, 0xfe, 0x01, 0xfc, 0x01, 0x18, 0x00, 0x10, 0x00};
+static unsigned char symbol18_222_bits[] = {
+0x10, 0x00, 0x38, 0x00, 0x6c, 0x00, 0xee, 0x00, 0xef, 0x01, 0x6c, 0x00, 
+0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00};
+static unsigned char symbol18_223_bits[] = {
+0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 
+0x6c, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0xff, 0x01, 
+0x00, 0x00, 0xff, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol18_224_bits[] = {
+0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 
+0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 
+0xef, 0x01, 0xee, 0x00};
+static unsigned char symbol18_225_bits[] = {
+0x0c, 0x00, 0x18, 0x00, 0x10, 0x00, 0x10, 0x00, 0x18, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x06, 0x00, 0x06};
+static unsigned char symbol18_226_bits[] = {
+0x00, 0x03, 0x01, 0x03, 0x01, 0x06, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x0c, 
+0x00, 0x18, 0x00, 0x10, 0x00, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 
+0x03, 0x01};
+static unsigned char symbol18_227_bits[] = {
+0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0xf8, 0x03, 0x1c, 0x07, 
+0x06, 0x0c, 0xf3, 0x18, 0xb3, 0x19, 0xb3, 0x19, 0xf3, 0x18, 0xb3, 0x19, 
+0xb3, 0x19};
+static unsigned char symbol18_228_bits[] = {
+0xb3, 0x19, 0x06, 0x0c, 0x1c, 0x07, 0xf8, 0x03, 0xf8, 0x03, 0x1c, 0x07, 
+0x06, 0x0c, 0xe3, 0x18};
+static unsigned char symbol18_229_bits[] = {
+0x33, 0x09, 0x33, 0x08, 0x33, 0x08, 0x33, 0x08, 0x33, 0x09, 0xe3, 0x08, 
+0x06, 0x0c, 0x1c, 0x07, 0xf8, 0x03, 0xdf, 0x08, 0xc4, 0x08, 0xc4, 0x08, 
+0x44, 0x05, 0x44, 0x05, 0x44, 0x05, 0x44, 0x02};
+static unsigned char symbol18_230_bits[] = {
+0x04, 0x12, 0x3f, 0x07, 0x07, 0x06, 0x0e, 0x04, 0x1c, 0x00, 0x38, 0x00, 
+0x30, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x00, 0x18, 0x00, 
+0x0c};
+static unsigned char symbol18_231_bits[] = {
+0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_232_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_233_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x07};
+static unsigned char symbol18_234_bits[] = {
+0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_235_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol18_236_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_237_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x1f, 0x1c, 0x06, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_238_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x07, 0x07};
+static unsigned char symbol18_239_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_240_bits[] = {
+0x00};
+static unsigned char symbol18_241_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x1c, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol18_242_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x03, 0x03, 0x06, 0x06};
+static unsigned char symbol18_243_bits[] = {
+0x0c, 0x0c, 0x18, 0x18, 0x10, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 
+0x03, 0x38, 0x38, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c};
+static unsigned char symbol18_244_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x02, 
+0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_245_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol18_246_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+0x20};
+static unsigned char symbol18_247_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x02, 0x01, 0x03, 
+0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00};
+static unsigned char symbol18_248_bits[] = {
+0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_249_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x10, 0x10, 
+0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 
+0x10};
+static unsigned char symbol18_250_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x01, 0x03, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00};
+static unsigned char symbol18_251_bits[] = {
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol18_252_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18};
+static unsigned char symbol18_253_bits[] = {
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x07, 0x0c, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18};
+static unsigned char symbol18_254_bits[] = {
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x06};
+static unsigned char symbol18_255_bits[] = {
+0x00};
+static RotFont symbol18font[] = {
+{5, 1, 1, symbol18_0_bits},
+{5, 1, 1, symbol18_1_bits},
+{5, 1, 1, symbol18_2_bits},
+{5, 1, 1, symbol18_3_bits},
+{5, 1, 1, symbol18_4_bits},
+{5, 1, 1, symbol18_5_bits},
+{5, 1, 1, symbol18_6_bits},
+{5, 1, 1, symbol18_7_bits},
+{5, 1, 1, symbol18_8_bits},
+{5, 1, 1, symbol18_9_bits},
+{5, 1, 1, symbol18_10_bits},
+{5, 1, 1, symbol18_11_bits},
+{5, 1, 1, symbol18_12_bits},
+{5, 1, 1, symbol18_13_bits},
+{5, 1, 1, symbol18_14_bits},
+{5, 1, 1, symbol18_15_bits},
+{5, 1, 1, symbol18_16_bits},
+{5, 1, 1, symbol18_17_bits},
+{5, 1, 1, symbol18_18_bits},
+{5, 1, 1, symbol18_19_bits},
+{5, 1, 1, symbol18_20_bits},
+{5, 1, 1, symbol18_21_bits},
+{5, 1, 1, symbol18_22_bits},
+{5, 1, 1, symbol18_23_bits},
+{5, 1, 1, symbol18_24_bits},
+{5, 1, 1, symbol18_25_bits},
+{5, 1, 1, symbol18_26_bits},
+{5, 1, 1, symbol18_27_bits},
+{5, 1, 1, symbol18_28_bits},
+{5, 1, 1, symbol18_29_bits},
+{5, 1, 1, symbol18_30_bits},
+{5, 1, 1, symbol18_31_bits},
+{1, 1, 1, symbol18_32_bits},
+{2, 13, 13, symbol18_33_bits},
+{13, 13, 13, symbol18_34_bits},
+{10, 13, 13, symbol18_35_bits},
+{8, 13, 13, symbol18_36_bits},
+{13, 13, 13, symbol18_37_bits},
+{12, 13, 13, symbol18_38_bits},
+{6, 9, 9, symbol18_39_bits},
+{4, 17, 13, symbol18_40_bits},
+{4, 17, 13, symbol18_41_bits},
+{7, 7, 10, symbol18_42_bits},
+{8, 8, 9, symbol18_43_bits},
+{3, 5, 2, symbol18_44_bits},
+{7, 2, 6, symbol18_45_bits},
+{2, 2, 2, symbol18_46_bits},
+{5, 13, 13, symbol18_47_bits},
+{8, 13, 13, symbol18_48_bits},
+{6, 13, 13, symbol18_49_bits},
+{7, 13, 13, symbol18_50_bits},
+{7, 13, 13, symbol18_51_bits},
+{8, 13, 13, symbol18_52_bits},
+{7, 13, 13, symbol18_53_bits},
+{8, 13, 13, symbol18_54_bits},
+{8, 13, 13, symbol18_55_bits},
+{8, 13, 13, symbol18_56_bits},
+{8, 13, 13, symbol18_57_bits},
+{2, 9, 9, symbol18_58_bits},
+{3, 12, 9, symbol18_59_bits},
+{9, 9, 9, symbol18_60_bits},
+{8, 6, 8, symbol18_61_bits},
+{9, 9, 9, symbol18_62_bits},
+{6, 13, 13, symbol18_63_bits},
+{8, 9, 9, symbol18_64_bits},
+{12, 13, 13, symbol18_65_bits},
+{9, 13, 13, symbol18_66_bits},
+{12, 13, 13, symbol18_67_bits},
+{11, 13, 13, symbol18_68_bits},
+{9, 13, 13, symbol18_69_bits},
+{12, 13, 13, symbol18_70_bits},
+{10, 13, 13, symbol18_71_bits},
+{11, 13, 13, symbol18_72_bits},
+{4, 13, 13, symbol18_73_bits},
+{11, 13, 13, symbol18_74_bits},
+{11, 13, 13, symbol18_75_bits},
+{12, 13, 13, symbol18_76_bits},
+{14, 13, 13, symbol18_77_bits},
+{11, 13, 13, symbol18_78_bits},
+{11, 13, 13, symbol18_79_bits},
+{11, 13, 13, symbol18_80_bits},
+{11, 13, 13, symbol18_81_bits},
+{8, 13, 13, symbol18_82_bits},
+{10, 13, 13, symbol18_83_bits},
+{10, 13, 13, symbol18_84_bits},
+{12, 13, 13, symbol18_85_bits},
+{6, 13, 9, symbol18_86_bits},
+{13, 13, 13, symbol18_87_bits},
+{10, 13, 13, symbol18_88_bits},
+{14, 13, 13, symbol18_89_bits},
+{9, 13, 13, symbol18_90_bits},
+{4, 17, 13, symbol18_91_bits},
+{10, 9, 9, symbol18_92_bits},
+{4, 17, 13, symbol18_93_bits},
+{10, 13, 13, symbol18_94_bits},
+{9, 2, -2, symbol18_95_bits},
+{10, 1, 17, symbol18_96_bits},
+{11, 9, 9, symbol18_97_bits},
+{8, 18, 14, symbol18_98_bits},
+{10, 13, 9, symbol18_99_bits},
+{7, 14, 14, symbol18_100_bits},
+{6, 9, 9, symbol18_101_bits},
+{9, 16, 12, symbol18_102_bits},
+{8, 13, 9, symbol18_103_bits},
+{9, 13, 9, symbol18_104_bits},
+{5, 9, 9, symbol18_105_bits},
+{9, 13, 9, symbol18_106_bits},
+{9, 9, 9, symbol18_107_bits},
+{10, 14, 14, symbol18_108_bits},
+{9, 13, 9, symbol18_109_bits},
+{8, 9, 9, symbol18_110_bits},
+{8, 9, 9, symbol18_111_bits},
+{9, 9, 9, symbol18_112_bits},
+{8, 13, 13, symbol18_113_bits},
+{8, 13, 9, symbol18_114_bits},
+{10, 9, 9, symbol18_115_bits},
+{7, 9, 9, symbol18_116_bits},
+{9, 9, 9, symbol18_117_bits},
+{11, 11, 11, symbol18_118_bits},
+{10, 9, 9, symbol18_119_bits},
+{7, 19, 15, symbol18_120_bits},
+{13, 13, 9, symbol18_121_bits},
+{7, 19, 15, symbol18_122_bits},
+{7, 17, 13, symbol18_123_bits},
+{2, 17, 13, symbol18_124_bits},
+{7, 17, 13, symbol18_125_bits},
+{8, 3, 7, symbol18_126_bits},
+{5, 1, 1, symbol18_127_bits},
+{5, 1, 1, symbol18_128_bits},
+{5, 1, 1, symbol18_129_bits},
+{5, 1, 1, symbol18_130_bits},
+{5, 1, 1, symbol18_131_bits},
+{5, 1, 1, symbol18_132_bits},
+{5, 1, 1, symbol18_133_bits},
+{5, 1, 1, symbol18_134_bits},
+{5, 1, 1, symbol18_135_bits},
+{5, 1, 1, symbol18_136_bits},
+{5, 1, 1, symbol18_137_bits},
+{5, 1, 1, symbol18_138_bits},
+{5, 1, 1, symbol18_139_bits},
+{5, 1, 1, symbol18_140_bits},
+{5, 1, 1, symbol18_141_bits},
+{5, 1, 1, symbol18_142_bits},
+{5, 1, 1, symbol18_143_bits},
+{5, 1, 1, symbol18_144_bits},
+{5, 1, 1, symbol18_145_bits},
+{5, 1, 1, symbol18_146_bits},
+{5, 1, 1, symbol18_147_bits},
+{5, 1, 1, symbol18_148_bits},
+{5, 1, 1, symbol18_149_bits},
+{5, 1, 1, symbol18_150_bits},
+{5, 1, 1, symbol18_151_bits},
+{5, 1, 1, symbol18_152_bits},
+{5, 1, 1, symbol18_153_bits},
+{5, 1, 1, symbol18_154_bits},
+{5, 1, 1, symbol18_155_bits},
+{5, 1, 1, symbol18_156_bits},
+{5, 1, 1, symbol18_157_bits},
+{5, 1, 1, symbol18_158_bits},
+{5, 1, 1, symbol18_159_bits},
+{5, 1, 1, symbol18_160_bits},
+{11, 13, 13, symbol18_161_bits},
+{4, 5, 14, symbol18_162_bits},
+{9, 12, 12, symbol18_163_bits},
+{8, 13, 13, symbol18_164_bits},
+{12, 5, 8, symbol18_165_bits},
+{9, 17, 13, symbol18_166_bits},
+{10, 9, 9, symbol18_167_bits},
+{9, 9, 9, symbol18_168_bits},
+{9, 9, 9, symbol18_169_bits},
+{10, 9, 9, symbol18_170_bits},
+{17, 8, 9, symbol18_171_bits},
+{18, 8, 9, symbol18_172_bits},
+{8, 25, 18, symbol18_173_bits},
+{18, 8, 9, symbol18_174_bits},
+{8, 22, 18, symbol18_175_bits},
+{5, 6, 13, symbol18_176_bits},
+{8, 11, 11, symbol18_177_bits},
+{8, 5, 14, symbol18_178_bits},
+{9, 12, 12, symbol18_179_bits},
+{10, 9, 9, symbol18_180_bits},
+{11, 5, 8, symbol18_181_bits},
+{7, 14, 14, symbol18_182_bits},
+{5, 6, 8, symbol18_183_bits},
+{8, 8, 9, symbol18_184_bits},
+{8, 9, 9, symbol18_185_bits},
+{8, 8, 9, symbol18_186_bits},
+{8, 7, 9, symbol18_187_bits},
+{14, 2, 2, symbol18_188_bits},
+{2, 25, 18, symbol18_189_bits},
+{19, 2, 6, symbol18_190_bits},
+{9, 12, 12, symbol18_191_bits},
+{11, 13, 13, symbol18_192_bits},
+{10, 15, 14, symbol18_193_bits},
+{13, 14, 14, symbol18_194_bits},
+{12, 15, 11, symbol18_195_bits},
+{12, 13, 13, symbol18_196_bits},
+{12, 13, 13, symbol18_197_bits},
+{12, 13, 13, symbol18_198_bits},
+{12, 9, 9, symbol18_199_bits},
+{12, 9, 9, symbol18_200_bits},
+{12, 9, 9, symbol18_201_bits},
+{12, 12, 9, symbol18_202_bits},
+{12, 13, 11, symbol18_203_bits},
+{12, 9, 9, symbol18_204_bits},
+{12, 12, 9, symbol18_205_bits},
+{9, 9, 9, symbol18_206_bits},
+{10, 11, 10, symbol18_207_bits},
+{13, 13, 13, symbol18_208_bits},
+{12, 13, 13, symbol18_209_bits},
+{13, 13, 13, symbol18_210_bits},
+{13, 13, 13, symbol18_211_bits},
+{14, 8, 13, symbol18_212_bits},
+{14, 16, 14, symbol18_213_bits},
+{10, 17, 17, symbol18_214_bits},
+{2, 2, 6, symbol18_215_bits},
+{11, 6, 6, symbol18_216_bits},
+{10, 9, 9, symbol18_217_bits},
+{10, 9, 9, symbol18_218_bits},
+{18, 9, 9, symbol18_219_bits},
+{16, 9, 9, symbol18_220_bits},
+{9, 17, 17, symbol18_221_bits},
+{16, 9, 9, symbol18_222_bits},
+{9, 17, 17, symbol18_223_bits},
+{9, 14, 14, symbol18_224_bits},
+{5, 17, 14, symbol18_225_bits},
+{13, 13, 13, symbol18_226_bits},
+{13, 13, 13, symbol18_227_bits},
+{13, 8, 13, symbol18_228_bits},
+{12, 16, 14, symbol18_229_bits},
+{6, 25, 18, symbol18_230_bits},
+{2, 25, 18, symbol18_231_bits},
+{6, 25, 18, symbol18_232_bits},
+{5, 25, 18, symbol18_233_bits},
+{2, 25, 18, symbol18_234_bits},
+{5, 22, 18, symbol18_235_bits},
+{5, 25, 18, symbol18_236_bits},
+{5, 25, 18, symbol18_237_bits},
+{5, 22, 18, symbol18_238_bits},
+{2, 25, 18, symbol18_239_bits},
+{5, 1, 1, symbol18_240_bits},
+{5, 17, 14, symbol18_241_bits},
+{6, 22, 18, symbol18_242_bits},
+{7, 25, 18, symbol18_243_bits},
+{2, 25, 18, symbol18_244_bits},
+{7, 22, 18, symbol18_245_bits},
+{6, 25, 18, symbol18_246_bits},
+{2, 25, 18, symbol18_247_bits},
+{6, 25, 18, symbol18_248_bits},
+{5, 25, 18, symbol18_249_bits},
+{2, 25, 18, symbol18_250_bits},
+{5, 22, 18, symbol18_251_bits},
+{5, 25, 18, symbol18_252_bits},
+{5, 25, 18, symbol18_253_bits},
+{5, 22, 18, symbol18_254_bits},
+{5, 1, 1, symbol18_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/symbol24.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/symbol24.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/symbol24.bdf	(revision 12606)
@@ -0,0 +1,4576 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Symbol-Medium-R-Normal--24-240-75-75-P-142-Adobe-FontSpecific
+SIZE 24 75 75
+FONTBOUNDINGBOX 26 32 -1 -8
+STARTPROPERTIES 31
+FOUNDRY "Adobe"
+FAMILY_NAME "Symbol"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 24
+POINT_SIZE 240
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 142
+CHARSET_REGISTRY "Adobe"
+CHARSET_ENCODING "FontSpecific"
+CAP_HEIGHT 17
+X_HEIGHT 13
+FACE_NAME "Symbol"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "No mark"
+_DEC_DEVICE_FONTNAMES "PS=Symbol"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2-1, 18-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+FULL_NAME "Symbol"
+FONT "-Adobe-Symbol-Medium-R-Normal--24-240-75-75-P-142-Adobe-FontSpecific"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 15
+DEFAULT_CHAR 32
+FONT_ASCENT 20
+FONT_DESCENT 5
+ENDPROPERTIES
+CHARS 188
+STARTCHAR space
+ENCODING 32
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 1 1 1 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 3 17 2 0
+BITMAP
+40
+e0
+e0
+e0
+e0
+e0
+e0
+e0
+40
+40
+40
+40
+00
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 17 1 0
+BITMAP
+c006
+c006
+600c
+600c
+3ff8
+3ff8
+3018
+1830
+1830
+0c60
+0c60
+0c60
+06c0
+06c0
+0380
+0380
+0380
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+0880
+0880
+0880
+0880
+0880
+0880
+7fe0
+1100
+1100
+1100
+ffc0
+2200
+2200
+2200
+2200
+2200
+2200
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+ffe0
+ffe0
+0060
+0060
+0060
+0060
+0060
+ffe0
+ffe0
+0060
+0060
+0060
+0060
+0060
+0060
+ffe0
+ffe0
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 800 0
+DWIDTH 20 0
+BBX 18 17 1 0
+BITMAP
+1f0600
+39fe00
+710c00
+611800
+e31800
+c23000
+c66000
+cc6000
+78c780
+018ec0
+019c40
+033840
+0630c0
+063080
+0c3180
+183300
+181e00
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 17 1 0
+BITMAP
+0780
+0cc0
+1840
+1840
+18c0
+1d80
+0f3e
+1e1c
+3e18
+6730
+c3a0
+c1e0
+c0c0
+c1e0
+e372
+7e3e
+3c1c
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 8 13 2 0
+BITMAP
+f0
+3c
+0e
+07
+03
+03
+7f
+03
+03
+07
+0e
+3c
+f0
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 22 1 -5
+BITMAP
+0c
+18
+30
+20
+60
+60
+40
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+40
+60
+60
+20
+30
+18
+0c
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 22 1 -5
+BITMAP
+c0
+60
+30
+10
+18
+18
+08
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+08
+18
+18
+10
+30
+60
+c0
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 8 10 2 7
+BITMAP
+18
+18
+c3
+e7
+18
+18
+e7
+c3
+18
+18
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 10 1 2
+BITMAP
+0c00
+0c00
+0c00
+0c00
+ffc0
+ffc0
+0c00
+0c00
+0c00
+0c00
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 3 6 1 -4
+BITMAP
+60
+60
+20
+60
+c0
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 2 1 6
+BITMAP
+ffe0
+ffe0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 3 2 0
+BITMAP
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 7 17 0 0
+BITMAP
+06
+06
+06
+0c
+0c
+0c
+18
+18
+30
+30
+30
+60
+60
+60
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1e00
+3300
+6180
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+6180
+3300
+1e00
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 6 17 3 0
+BITMAP
+30
+70
+f0
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+fc
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1c00
+7f00
+6700
+8380
+8180
+0180
+0180
+0380
+0300
+0700
+0c00
+0c00
+1800
+3000
+6040
+ffc0
+ff80
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 9 17 1 0
+BITMAP
+1c00
+7e00
+4700
+8300
+8300
+0600
+0c00
+1e00
+0700
+0300
+0180
+0180
+0180
+0300
+c700
+fe00
+7800
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+0300
+0700
+0700
+0f00
+0b00
+1b00
+1300
+3300
+2300
+6300
+4300
+ffc0
+ffc0
+0300
+0300
+0300
+0300
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 9 17 1 0
+BITMAP
+3f80
+3f00
+6000
+4000
+c000
+f000
+fc00
+1e00
+0700
+0380
+0180
+0180
+0180
+0180
+c300
+fe00
+7c00
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+03c0
+0e00
+3800
+7000
+6000
+e000
+cf00
+f380
+e180
+c0c0
+c0c0
+c0c0
+c0c0
+e0c0
+61c0
+7380
+1f00
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+7fc0
+ffc0
+c0c0
+8180
+0180
+0300
+0300
+0300
+0600
+0600
+0600
+0c00
+0c00
+0c00
+1800
+1800
+1800
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1e00
+3300
+6180
+6180
+6180
+7300
+3e00
+1c00
+3f00
+6380
+c1c0
+c0c0
+c0c0
+c0c0
+c1c0
+6380
+3e00
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1e00
+7380
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+61c0
+73c0
+1ec0
+0180
+0380
+0700
+0e00
+3c00
+f000
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 11 2 0
+BITMAP
+c0
+c0
+c0
+00
+00
+00
+00
+00
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 3 15 1 -4
+BITMAP
+60
+60
+60
+00
+00
+00
+00
+00
+00
+60
+60
+20
+60
+c0
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 12 12 0 1
+BITMAP
+0070
+01e0
+0780
+1e00
+7800
+e000
+e000
+7800
+1e00
+0780
+01e0
+0070
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 6 1 4
+BITMAP
+ffc0
+ffc0
+0000
+0000
+ffc0
+ffc0
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 12 12 0 1
+BITMAP
+e000
+7800
+1e00
+0780
+01e0
+0070
+0070
+01e0
+0780
+1e00
+7800
+e000
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 8 17 2 0
+BITMAP
+7c
+c6
+83
+c3
+c7
+06
+0e
+0c
+18
+18
+10
+10
+10
+00
+00
+30
+30
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 12 1 1
+BITMAP
+3820
+7c60
+c7c0
+8380
+0000
+0000
+ffe0
+ffe0
+0000
+0000
+ffe0
+ffe0
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 17 17 0 0
+BITMAP
+008000
+01c000
+01c000
+014000
+036000
+026000
+023000
+063000
+043000
+0c1800
+081800
+0ffc00
+180c00
+100c00
+300600
+300600
+f80f80
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+ffc0
+30e0
+3070
+3030
+3030
+3030
+3030
+3060
+3fc0
+3070
+3038
+3018
+3018
+3018
+3038
+3070
+ffc0
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 17 17 1 0
+BITMAP
+f81f80
+700e00
+380c00
+1c1800
+0c3000
+066000
+07c000
+038000
+018000
+03c000
+06e000
+0c7000
+083800
+181800
+301c00
+700e00
+f81f80
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 16 17 0 0
+BITMAP
+0300
+0300
+0780
+0480
+04c0
+0cc0
+0860
+0860
+1830
+1030
+3018
+2018
+200c
+600c
+4006
+c006
+ffff
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+fff0
+3030
+3010
+3000
+3000
+3000
+3020
+3020
+3fe0
+3020
+3020
+3000
+3000
+3008
+3008
+3018
+fff8
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 16 17 1 0
+BITMAP
+07e0
+0180
+0180
+0ff0
+399c
+6186
+e187
+c183
+c183
+c183
+e187
+6186
+399c
+0ff0
+0180
+0180
+07e0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+fff8
+3018
+3008
+3008
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+fc00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+fc3f
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+3ffc
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+fc3f
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 17 1 0
+BITMAP
+fc
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+fc
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 17 1 0
+BITMAP
+03c0
+06e0
+0460
+0660
+0330
+71b0
+f8f0
+983c
+1830
+1830
+3030
+3030
+3030
+3060
+3860
+1cc0
+0f80
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 17 1 0
+BITMAP
+fc7c
+3030
+3060
+30c0
+3180
+3300
+3600
+3e00
+3f00
+3380
+3180
+31c0
+30e0
+3070
+3038
+301c
+fc3e
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 17 1 0
+BITMAP
+0300
+0300
+0780
+0480
+04c0
+04c0
+0cc0
+0860
+0860
+1860
+1030
+1030
+3030
+2018
+2018
+601c
+f83e
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 880 0
+DWIDTH 22 0
+BBX 20 17 1 0
+BITMAP
+f001f0
+3801c0
+3803c0
+3c02c0
+2c02c0
+2e06c0
+2604c0
+270cc0
+2308c0
+2388c0
+2198c0
+21d0c0
+20d0c0
+20f0c0
+2060c0
+2060c0
+f803f0
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+f01f
+3804
+3804
+2c04
+2e04
+2604
+2304
+2304
+2184
+21c4
+20c4
+2064
+2064
+2034
+203c
+201c
+f80c
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+07e0
+1c38
+300c
+6006
+6006
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+6006
+6006
+300c
+1c38
+07e0
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+ffff
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+fc3f
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+07e0
+1c38
+300c
+6006
+6006
+c813
+c813
+cff3
+cff3
+c813
+c813
+c003
+4002
+6006
+300c
+1c38
+07e0
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 17 1 0
+BITMAP
+ff80
+30e0
+3060
+3030
+3030
+3030
+3060
+30e0
+3f80
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+fc00
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 17 1 0
+BITMAP
+fff0
+e030
+7010
+3800
+1c00
+0e00
+0700
+0380
+0300
+0600
+0c00
+1800
+3010
+6010
+c030
+fff0
+fff0
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 17 1 0
+BITMAP
+fffc
+c30c
+8304
+8304
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0fc0
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 16 17 0 0
+BITMAP
+f81f
+700e
+300c
+1818
+1c10
+0c30
+0e60
+0660
+03c0
+03c0
+0180
+0180
+0180
+0180
+0180
+0180
+07e0
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 18 1 -5
+BITMAP
+1f80
+3f80
+6000
+6000
+c000
+c000
+c000
+c000
+c000
+c000
+6000
+7f00
+1f80
+0080
+0080
+0180
+0f00
+0e00
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+07e0
+1c38
+300c
+6006
+6006
+c003
+c003
+c003
+c003
+e007
+6006
+300c
+1818
+8c31
+8421
+fc3f
+fc3f
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 17 1 0
+BITMAP
+7ff8
+7ff8
+6018
+4008
+0000
+1020
+1020
+1fe0
+1fe0
+1020
+1020
+0000
+8004
+8004
+c00c
+fffc
+fffc
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 800 0
+DWIDTH 20 0
+BBX 18 17 1 0
+BITMAP
+e3f1c0
+70c380
+30c300
+30c300
+38c700
+38c700
+18c600
+1cce00
+07f800
+00c000
+00c000
+00c000
+00c000
+00c000
+00c000
+00c000
+03f000
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 12 17 1 0
+BITMAP
+fff0
+c070
+8060
+00e0
+01c0
+0180
+0380
+0700
+0600
+0e00
+1c00
+3800
+3800
+7000
+6010
+e030
+fff0
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 5 22 2 -5
+BITMAP
+f8
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+f8
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 12 10 3 0
+BITMAP
+0600
+0600
+0600
+0000
+0000
+0000
+0000
+c030
+c030
+c030
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 5 22 1 -5
+BITMAP
+f8
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+f8
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 17 1 0
+BITMAP
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+fffc
+fffc
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 13 2 0 -5
+BITMAP
+fff8
+fff8
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 13 2 0 21
+BITMAP
+fff8
+fff8
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 13 1 0
+BITMAP
+1f18
+71b8
+60b0
+e0f0
+c060
+c060
+c060
+c060
+c060
+e0e0
+60e4
+71fc
+1f38
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 24 1 -5
+BITMAP
+3e00
+6700
+c380
+c180
+c180
+c380
+c300
+ce00
+cf00
+c380
+c180
+c1c0
+c0c0
+c0c0
+c0c0
+c1c0
+e180
+f380
+df00
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 18 1 -5
+BITMAP
+7060
+f860
+d8c0
+88c0
+0980
+0980
+0b00
+0700
+0600
+0600
+0e00
+0e00
+1900
+1900
+3110
+31b0
+61f0
+60e0
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 18 1 0
+BITMAP
+1f00
+3380
+2180
+3000
+3800
+1c00
+0e00
+3f00
+7380
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+7380
+1e00
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+3e00
+7300
+e300
+c300
+e000
+6000
+3c00
+6000
+e000
+c000
+e080
+7180
+3f00
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 22 1 -5
+BITMAP
+0600
+0600
+0600
+0600
+1f80
+36c0
+6660
+e670
+c630
+c630
+c630
+c630
+c630
+e670
+6660
+36c0
+1f80
+0600
+0600
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 11 18 0 -5
+BITMAP
+7060
+f860
+9860
+98c0
+18c0
+0cc0
+0d80
+0d80
+0580
+0700
+0700
+0300
+0600
+0600
+0600
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 12 18 1 -5
+BITMAP
+71c0
+fbe0
+9e30
+1c30
+1830
+1830
+1830
+1830
+1830
+1830
+1830
+1830
+1830
+0030
+0030
+0030
+0030
+0030
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 7 13 1 0
+BITMAP
+30
+70
+f0
+30
+30
+30
+30
+30
+30
+30
+32
+3e
+1c
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 18 1 -5
+BITMAP
+3380
+73c0
+6660
+c670
+c630
+c630
+c630
+c630
+c630
+e670
+6660
+36c0
+1f80
+0600
+0600
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+3070
+70f0
+f1b0
+3300
+3600
+3c00
+3c00
+3e00
+3700
+3380
+31c0
+30e0
+31f0
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 19 1 0
+BITMAP
+7000
+f800
+8800
+0800
+0800
+0c00
+0c00
+0c00
+1c00
+1e00
+1a00
+3200
+3200
+3300
+6100
+6100
+6190
+c1f0
+c0e0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 18 2 -5
+BITMAP
+c180
+c180
+c180
+c180
+c180
+c180
+c180
+c180
+c180
+c180
+e390
+fff0
+de60
+c000
+c000
+e000
+e000
+e000
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+c0e0
+c0e0
+c060
+6040
+60c0
+6080
+3180
+3100
+3300
+1a00
+1a00
+0e00
+0c00
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+1f00
+71c0
+60c0
+e0e0
+c060
+c060
+c060
+c060
+c060
+e0e0
+60c0
+71c0
+1f00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 13 13 0 0
+BITMAP
+7ff8
+fff8
+98c0
+18c0
+18c0
+18c0
+18c0
+18c0
+18c0
+18c0
+18c8
+38f8
+30f0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1e00
+3300
+6180
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+ffc0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+6180
+3300
+1e00
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 18 1 -5
+BITMAP
+3e00
+6380
+c180
+c1c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c1c0
+c180
+e380
+de00
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 14 13 1 0
+BITMAP
+1ffc
+71fc
+60c0
+e0e0
+c060
+c060
+c060
+c060
+c060
+e0e0
+60c0
+71c0
+1f00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 10 13 0 0
+BITMAP
+3fc0
+7fc0
+cc00
+8c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c80
+0f80
+0700
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 13 13 0 0
+BITMAP
+30e0
+7830
+d818
+9818
+1818
+1818
+1818
+1818
+1818
+1830
+0c30
+0ee0
+07c0
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 14 1 0
+BITMAP
+7fff
+ffff
+9818
+300c
+318c
+6186
+6186
+6186
+6186
+6186
+6186
+318c
+3bdc
+1e78
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 13 1 0
+BITMAP
+1860
+3030
+6018
+6318
+c30c
+c30c
+c30c
+c30c
+c30c
+c30c
+6318
+77b8
+3cf0
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 24 1 -5
+BITMAP
+3000
+6380
+6780
+3f00
+3000
+2000
+3780
+1f80
+3000
+6000
+c000
+8000
+8000
+8000
+c000
+f000
+7c00
+3f80
+0fc0
+00c0
+0040
+00c0
+0f80
+0f00
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 18 1 -5
+BITMAP
+c183
+718e
+318c
+399c
+399c
+399c
+399c
+399c
+399c
+1998
+1998
+0db0
+07e0
+0180
+0180
+0180
+0180
+0180
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 24 1 -5
+BITMAP
+3000
+6380
+6780
+3f00
+1800
+3000
+2000
+6000
+4000
+c000
+8000
+8000
+8000
+8000
+c000
+f000
+7c00
+3f80
+0fc0
+00c0
+0040
+00c0
+0f80
+0f00
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 8 22 1 -5
+BITMAP
+07
+0c
+18
+18
+18
+18
+18
+10
+30
+20
+c0
+20
+30
+10
+18
+18
+18
+18
+18
+18
+0c
+07
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 160 0
+DWIDTH 4 0
+BBX 2 22 1 -5
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 8 22 1 -5
+BITMAP
+e0
+30
+18
+18
+18
+18
+18
+08
+0c
+04
+03
+04
+0c
+08
+18
+18
+18
+18
+18
+18
+30
+e0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 4 1 5
+BITMAP
+3820
+7c60
+c7c0
+8380
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 5 6 1 12
+BITMAP
+e0
+70
+70
+d8
+38
+b8
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 15 0 0
+BITMAP
+1b30
+0e00
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+1f80
+1830
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 160 0
+DWIDTH 4 0
+BBX 8 17 -1 0
+BITMAP
+70
+60
+c0
+80
+00
+70
+01
+e0
+07
+80
+1e
+00
+78
+00
+e0
+00
+e0
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 7 1 4
+BITMAP
+0078
+001e
+0002
+c000
+f000
+3000
+00fe
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 13 22 0 -5
+BITMAP
+f0f8
+f000
+0300
+0608
+0c18
+1818
+3030
+6060
+60c0
+c0c0
+3838
+7e78
+c7c0
+c380
+c6c0
+7c78
+3838
+00f0
+0198
+0198
+0300
+0300
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 13 2 0
+BITMAP
+0300
+1fe0
+0300
+0300
+0300
+0600
+0600
+0600
+0600
+0600
+0600
+0c00
+0c00
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 10 13 4 0
+BITMAP
+cc00
+cc00
+d800
+7000
+0780
+0fc0
+0fc0
+0fc0
+0fc0
+7780
+fb40
+ffc0
+ffc0
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 12 13 3 0
+BITMAP
+fb70
+7330
+0300
+0780
+0c00
+0c00
+1e00
+3f00
+3f00
+7f80
+ffc0
+7f80
+3f00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 12 13 3 0
+BITMAP
+3f00
+1e00
+0c00
+0c00
+70e0
+f9f0
+f9f0
+fff0
+fff0
+fff0
+7fe0
+7fe0
+3fc0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 1040 0
+DWIDTH 26 0
+BBX 24 12 1 1
+BITMAP
+1f800f
+000f00
+060006
+000600
+0f001f
+803fc0
+7fe07f
+e0fff0
+fff0f6
+f06660
+06000f
+000600
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 1000 0
+DWIDTH 25 0
+BBX 25 12 0 1
+BITMAP
+600c0000
+18001800
+000c6000
+06ffff80
+ffffff00
+00063000
+0c180000
+0c003000
+00600600
+00000c00
+00001800
+00003000
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 31 1 -8
+BITMAP
+0000
+6000
+0000
+fff0
+ff80
+fff0
+ff80
+6000
+0000
+3000
+0000
+1800
+0000
+0c00
+0000
+0600
+0000
+0600
+0f00
+1f80
+36c0
+6660
+c630
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 1000 0
+DWIDTH 25 0
+BBX 25 12 0 1
+BITMAP
+06000600
+06000600
+06000600
+06000600
+06000600
+06000600
+06000600
+06000600
+06000000
+30000000
+18000000
+0c000000
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 29 1 -5
+BITMAP
+0600
+0000
+0300
+fff0
+ff80
+fff0
+ff80
+0000
+0300
+0000
+0600
+0000
+0c00
+0000
+1800
+0000
+3000
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 360 0
+DWIDTH 9 0
+BBX 7 7 1 10
+BITMAP
+06
+00
+06
+00
+06
+00
+06
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+00c0
+3040
+6000
+c000
+8000
+0000
+0000
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 9 6 1 12
+BITMAP
+6c80
+8280
+6c00
+0c00
+0c00
+0c00
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 15 0 0
+BITMAP
+0c00
+ffc0
+ffc0
+0c00
+0c00
+0c00
+0c00
+0000
+0000
+ffc0
+ffc0
+1980
+3b80
+7700
+6600
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 10 1 2
+BITMAP
+cc00
+8800
+e000
+7800
+1e00
+0780
+01e0
+0060
+0060
+01e0
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 7 1 4
+BITMAP
+0780
+3e00
+f000
+c000
+0000
+fff0
+fff0
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 19 1 0
+BITMAP
+c040
+60c0
+3180
+1b00
+0e00
+0e00
+1b00
+3180
+60c0
+c040
+3800
+7c40
+c6c0
+c380
+c7c0
+7c40
+3800
+3e00
+6300
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 8 8 2 3
+BITMAP
+c1
+80
+01
+80
+00
+c0
+00
+c0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 8 1 3
+BITMAP
+00c0
+00c0
+1ec0
+73c0
+61c0
+c0c0
+c0c0
+c180
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 13 2 0
+BITMAP
+c180
+c180
+c300
+6700
+3c00
+3c40
+ffc0
+ffc0
+7e00
+0c00
+0c00
+0000
+ffc0
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 8 1 3
+BITMAP
+ffc0
+0000
+0c00
+0c00
+0180
+0180
+0300
+0300
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 8 1 3
+BITMAP
+ffc0
+ffc0
+0c00
+ffc0
+ffc0
+3000
+3000
+6000
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 960 0
+DWIDTH 24 0
+BBX 18 3 3 0
+BITMAP
+6000c0
+e0ffc0
+0000c0
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 2 32 6 -8
+BITMAP
+c0
+c0
+c0
+00
+00
+c0
+c0
+c0
+c0
+00
+00
+40
+40
+c0
+c0
+80
+80
+00
+00
+40
+40
+c0
+c0
+80
+80
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 1000 0
+DWIDTH 25 0
+BBX 25 2 0 6
+BITMAP
+c0c0c080
+c0c0c080
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 16 1 0
+BITMAP
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+fffc
+ff80
+fffc
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 16 1 0
+BITMAP
+ff80
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+2000
+6000
+fff0
+fff0
+6000
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 19 1 -1
+BITMAP
+2000
+8180
+c300
+e3f0
+71f0
+3860
+1cc0
+3c80
+6e80
+c780
+c380
+e380
+f1c0
+70e0
+3070
+7030
+e010
+0f80
+3ffc
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 17 18 1 0
+BITMAP
+70f800
+304000
+40c000
+c03080
+1c7000
+380000
+001c00
+1c0000
+300c00
+0cde00
+0ff000
+c01e00
+003f00
+006380
+00c180
+008180
+00c180
+00e180
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 15 20 2 -5
+BITMAP
+0070
+b800
+39b0
+0018
+9800
+1198
+0000
+9800
+019c
+0000
+8c00
+018c
+0018
+8680
+3f06
+804e
+0700
+0600
+0c00
+183c
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+30fe
+3186
+6306
+6606
+6c06
+680c
+799c
+7398
+7230
+7a70
+5be0
+dd80
+8c00
+8c00
+8c00
+d800
+7000
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+07e0
+1e78
+381c
+6006
+6816
+cc33
+c663
+c3c3
+c183
+c3c3
+c663
+cc33
+6816
+6006
+381c
+1e78
+07e0
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 800 0
+DWIDTH 20 0
+BBX 18 17 1 0
+BITMAP
+07e000
+783800
+618640
+86c180
+c183c0
+fbdfc0
+c183c0
+83c180
+618640
+063800
+1e7800
+e003c0
+c00fc0
+801c00
+003000
+003000
+006000
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 13 1 0
+BITMAP
+8060
+3180
+6061
+8060
+c180
+6181
+8063
+0180
+6601
+803c
+0300
+3803
+003c
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 13 1 0
+BITMAP
+0e00
+6ffc
+00c3
+f000
+07e0
+1ff8
+381c
+6006
+6006
+c003
+c003
+c003
+c003
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 12 1 0
+BITMAP
+c002
+c002
+c002
+c002
+c002
+c002
+c002
+c002
+c002
+c002
+c002
+c002
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 15 1 -3
+BITMAP
+6006
+6006
+381c
+1ff8
+07e0
+ffe0
+fff8
+001c
+000c
+0006
+0006
+0006
+0006
+000c
+001c
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 16 1 -2
+BITMAP
+fff8
+ffe0
+ffe0
+fff8
+001c
+000c
+0006
+0006
+0006
+0006
+000c
+001c
+fff8
+ffe0
+0000
+fffe
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 12 1 0
+BITMAP
+fffe
+000c
+000c
+0ffe
+3ffe
+7030
+6030
+c060
+c060
+c0c0
+c0c0
+6180
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 15 1 -3
+BITMAP
+7180
+3ffe
+0ffe
+0600
+0600
+0ffe
+3ffe
+7000
+6000
+c000
+c000
+c000
+c000
+6000
+7000
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 12 13 2 0
+BITMAP
+3ff0
+0ff0
+0ff0
+3ff0
+7000
+6000
+c000
+c000
+c000
+c000
+6000
+7000
+3ff0
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 12 17 2 -2
+BITMAP
+0ff0
+0000
+fff0
+fff0
+1ff0
+7ff0
+6000
+c000
+c000
+fff0
+fff0
+c000
+c000
+c000
+6000
+7ff0
+1ff0
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 17 16 1 0
+BITMAP
+00c000
+c01f80
+7ff000
+80c180
+c30080
+f0ff80
+c60080
+00cc00
+6c0000
+f01f80
+180000
+000000
+800000
+000000
+000000
+000000
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 18 1 0
+BITMAP
+0000
+3000
+0060
+0000
+c000
+0180
+0003
+0000
+0600
+000c
+0000
+1800
+0030
+0000
+7fff
+80ff
+ff80
+ffff
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+c003
+c002
+6006
+6004
+300c
+3008
+3018
+1810
+1830
+0c20
+0c20
+0660
+0640
+03c0
+03c0
+0180
+0180
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+07e0
+1e78
+381c
+6006
+6fe6
+c673
+c633
+c673
+c7e3
+c6c3
+c663
+c633
+6f3e
+6006
+381c
+1e78
+07e0
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 880 0
+DWIDTH 22 0
+BBX 20 10 1 7
+BITMAP
+07e010
+783810
+600660
+c6c660
+cc23c0
+03cc00
+cc03c0
+23c660
+63c660
+063810
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 17 21 1 -3
+BITMAP
+1e7800
+e0ff80
+709900
+601800
+e01800
+e01800
+601800
+601800
+601800
+601800
+603c80
+f0ff80
+803000
+003000
+003000
+003000
+003000
+003000
+003000
+003000
+003000
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 14 23 0 0
+BITMAP
+0030
+0600
+3004
+0030
+0600
+3004
+0030
+0600
+3004
+0030
+0600
+3004
+0030
+0600
+3004
+00fc
+1f80
+0004
+0004
+0004
+000c
+000c
+0008
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 3 2 6
+BITMAP
+00
+00
+00
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 8 1 0
+BITMAP
+0800
+1830
+1870
+10d8
+1018
+100c
+300c
+3006
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 12 1 0
+BITMAP
+2000
+2000
+2000
+6000
+c000
+c000
+c000
+c0c0
+c0c0
+fff8
+fff8
+0000
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 12 1 0
+BITMAP
+0000
+0000
+0000
+0000
+0000
+0700
+0700
+0d80
+0d80
+18c0
+18c0
+3060
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 1000 0
+DWIDTH 25 0
+BBX 23 12 1 0
+BITMAP
+306060
+306030
+c018c0
+18c018
+c01860
+306030
+306030
+6018c0
+18c00c
+800d80
+070006
+000600
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 1000 0
+DWIDTH 25 0
+BBX 23 12 1 0
+BITMAP
+c00c00
+601800
+303ffe
+f87ffe
+fce000
+0ee000
+0e7ffe
+fc3ffe
+f81800
+300c00
+600600
+c00600
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 23 1 0
+BITMAP
+0000
+0000
+1800
+0030
+fff0
+7ff0
+fee0
+0000
+e000
+0070
+fff0
+3ff0
+fe10
+0000
+0c00
+0000
+0000
+0600
+0f00
+1f80
+39c0
+79e0
+d9b0
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 1000 0
+DWIDTH 25 0
+BBX 23 12 1 0
+BITMAP
+198018
+801980
+198018
+801980
+198018
+801980
+198018
+801980
+198018
+801980
+198018
+800000
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 23 1 0
+BITMAP
+c000
+0060
+0000
+30f0
+fff0
+fff0
+fc00
+0000
+0000
+0ef0
+fff0
+fff0
+f800
+0030
+0000
+6000
+00c0
+1980
+1980
+1980
+1980
+1980
+1980
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 18 1 0
+BITMAP
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+d980
+79c0
+39c0
+1f80
+0f00
+0600
+0c00
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 7 22 0 -5
+BITMAP
+0c
+00
+1e
+00
+32
+00
+32
+00
+60
+80
+60
+80
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+60
+80
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+6180
+3300
+3300
+1e00
+0c00
+0c00
+0606
+0c0c
+1818
+3030
+6060
+c0c0
+6060
+3030
+1818
+0c0c
+0606
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+07e0
+1e78
+381c
+6006
+67e6
+c633
+c633
+c633
+c7e3
+c663
+c633
+c633
+6632
+6006
+381c
+1e78
+07e0
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 800 0
+DWIDTH 20 0
+BBX 18 10 1 7
+BITMAP
+07e000
+783800
+600640
+c6c7c0
+ce63c0
+03cc00
+cc03c0
+63c7c0
+63c640
+063800
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 20 2 -2
+BITMAP
+1e78
+07e0
+fec0
+c018
+c0c0
+18e0
+c018
+e1c0
+18f0
+c018
+d2c0
+18dc
+c018
+ccc0
+18cc
+c018
+ccc0
+fff8
+e018
+7008
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 9 31 1 -8
+BITMAP
+3800
+1c00
+0e00
+0700
+0380
+0180
+0080
+0180
+0300
+0600
+0c00
+1800
+3000
+6000
+c000
+ff80
+ff80
+0180
+0300
+0600
+0c00
+1800
+1800
+3000
+3000
+6000
+6000
+6000
+6000
+c000
+c000
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 2 32 1 -8
+BITMAP
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 9 32 1 -8
+BITMAP
+c000
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 7 31 1 -8
+BITMAP
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+60
+00
+60
+00
+60
+00
+60
+00
+30
+00
+30
+00
+18
+00
+18
+00
+0c
+00
+06
+00
+02
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 2 32 1 -8
+BITMAP
+00
+00
+80
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 7 29 1 -5
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 7 31 5 -8
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 5 32 2 -8
+BITMAP
+c0
+c0
+f8
+18
+30
+60
+60
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 7 29 5 -5
+BITMAP
+c0
+c0
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+10
+30
+60
+c0
+60
+30
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 2 32 5 -8
+BITMAP
+00
+00
+00
+00
+00
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+40
+40
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 7 22 1 -5
+BITMAP
+30
+1e
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 8 28 0 -5
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+00
+c0
+c0
+60
+60
+30
+30
+18
+18
+0c
+0c
+06
+06
+0c
+0c
+18
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 8 31 8 -8
+BITMAP
+18
+30
+30
+60
+60
+c0
+c0
+07
+0f
+1b
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 2 32 2 -8
+BITMAP
+00
+c0
+c0
+c0
+00
+00
+00
+00
+40
+40
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 8 26 2 -2
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 9 31 0 -8
+BITMAP
+c080
+c080
+c080
+c080
+c000
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0200
+cc80
+7080
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+8000
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 2 32 7 -8
+BITMAP
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 9 32 0 -8
+BITMAP
+8000
+8080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c000
+8000
+8000
+8000
+8000
+8000
+8000
+8000
+8000
+8000
+8000
+8000
+8000
+8000
+8000
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 7 31 2 -8
+BITMAP
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+02
+00
+02
+00
+02
+00
+02
+00
+06
+00
+06
+00
+0c
+00
+0c
+00
+18
+00
+30
+00
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 2 32 7 -8
+BITMAP
+40
+00
+c0
+00
+c0
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 7 29 2 -5
+BITMAP
+06
+06
+06
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 7 31 0 -8
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 5 32 5 -8
+BITMAP
+00
+00
+00
+f8
+f0
+18
+08
+08
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 7 29 0 -5
+BITMAP
+06
+06
+06
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+40
+60
+30
+18
+30
+60
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/symbol24.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/symbol24.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/symbol24.h	(revision 12606)
@@ -0,0 +1,1127 @@
+static unsigned char symbol24_0_bits[] = {
+0x00};
+static unsigned char symbol24_1_bits[] = {
+0x00};
+static unsigned char symbol24_2_bits[] = {
+0x00};
+static unsigned char symbol24_3_bits[] = {
+0x00};
+static unsigned char symbol24_4_bits[] = {
+0x00};
+static unsigned char symbol24_5_bits[] = {
+0x00};
+static unsigned char symbol24_6_bits[] = {
+0x00};
+static unsigned char symbol24_7_bits[] = {
+0x00};
+static unsigned char symbol24_8_bits[] = {
+0x00};
+static unsigned char symbol24_9_bits[] = {
+0x00};
+static unsigned char symbol24_10_bits[] = {
+0x00};
+static unsigned char symbol24_11_bits[] = {
+0x00};
+static unsigned char symbol24_12_bits[] = {
+0x00};
+static unsigned char symbol24_13_bits[] = {
+0x00};
+static unsigned char symbol24_14_bits[] = {
+0x00};
+static unsigned char symbol24_15_bits[] = {
+0x00};
+static unsigned char symbol24_16_bits[] = {
+0x00};
+static unsigned char symbol24_17_bits[] = {
+0x00};
+static unsigned char symbol24_18_bits[] = {
+0x00};
+static unsigned char symbol24_19_bits[] = {
+0x00};
+static unsigned char symbol24_20_bits[] = {
+0x00};
+static unsigned char symbol24_21_bits[] = {
+0x00};
+static unsigned char symbol24_22_bits[] = {
+0x00};
+static unsigned char symbol24_23_bits[] = {
+0x00};
+static unsigned char symbol24_24_bits[] = {
+0x00};
+static unsigned char symbol24_25_bits[] = {
+0x00};
+static unsigned char symbol24_26_bits[] = {
+0x00};
+static unsigned char symbol24_27_bits[] = {
+0x00};
+static unsigned char symbol24_28_bits[] = {
+0x00};
+static unsigned char symbol24_29_bits[] = {
+0x00};
+static unsigned char symbol24_30_bits[] = {
+0x00};
+static unsigned char symbol24_31_bits[] = {
+0x00};
+static unsigned char symbol24_32_bits[] = {
+0x00};
+static unsigned char symbol24_33_bits[] = {
+0x02, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x02, 0x02, 0x02, 0x02, 
+0x00, 0x00, 0x00, 0x03, 0x03};
+static unsigned char symbol24_34_bits[] = {
+0x03, 0x60, 0x03, 0x60, 0x06, 0x30, 0x06, 0x30, 0xfc, 0x1f, 0xfc, 0x1f, 
+0x0c, 0x18, 0x18, 0x0c, 0x18, 0x0c, 0x30, 0x06, 0x30, 0x06, 0x30, 0x06, 
+0x60, 0x03, 0x60, 0x03, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01};
+static unsigned char symbol24_35_bits[] = {
+0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 
+0xfe, 0x07, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0xff, 0x03, 0x44, 0x00, 
+0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0x44, 0x00};
+static unsigned char symbol24_36_bits[] = {
+0xff, 0x07, 0xff, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 
+0x00, 0x06, 0xff, 0x07, 0xff, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 
+0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0xff, 0x07, 0xff, 0x07};
+static unsigned char symbol24_37_bits[] = {
+0xf8, 0x60, 0x00, 0x9c, 0x7f, 0x00, 0x8e, 0x30, 0x00, 0x86, 0x18, 0x00, 
+0xc7, 0x18, 0x00, 0x43, 0x0c, 0x00, 0x63, 0x06, 0x00, 0x33, 0x06, 0x00, 
+0x1e, 0xe3, 0x01, 0x80, 0x71, 0x03, 0x80, 0x39, 0x02, 0xc0, 0x1c, 0x02, 
+0x60, 0x0c, 0x03, 0x60, 0x0c, 0x01, 0x30, 0x8c, 0x01, 0x18, 0xcc, 0x00, 
+0x18, 0x78, 0x00};
+static unsigned char symbol24_38_bits[] = {
+0xe0, 0x01, 0x30, 0x03, 0x18, 0x02, 0x18, 0x02, 0x18, 0x03, 0xb8, 0x01, 
+0xf0, 0x7c, 0x78, 0x38, 0x7c, 0x18, 0xe6, 0x0c, 0xc3, 0x05, 0x83, 0x07, 
+0x03, 0x03, 0x83, 0x07, 0xc7, 0x4e, 0x7e, 0x7c, 0x3c, 0x38};
+static unsigned char symbol24_39_bits[] = {
+0x0f, 0x3c, 0x70, 0xe0, 0xc0, 0xc0, 0xfe, 0xc0, 0xc0, 0xe0, 0x70, 0x3c, 
+0x0f};
+static unsigned char symbol24_40_bits[] = {
+0x30, 0x18, 0x0c, 0x04, 0x06, 0x06, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x02, 0x06, 0x06, 0x04, 0x0c, 0x18, 0x30};
+static unsigned char symbol24_41_bits[] = {
+0x03, 0x06, 0x0c, 0x08, 0x18, 0x18, 0x10, 0x30, 0x30, 0x30, 0x30, 0x30, 
+0x30, 0x30, 0x30, 0x10, 0x18, 0x18, 0x08, 0x0c, 0x06, 0x03};
+static unsigned char symbol24_42_bits[] = {
+0x18, 0x18, 0xc3, 0xe7, 0x18, 0x18, 0xe7, 0xc3, 0x18, 0x18};
+static unsigned char symbol24_43_bits[] = {
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xff, 0x03, 0xff, 0x03, 
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00};
+static unsigned char symbol24_44_bits[] = {
+0x06, 0x06, 0x04, 0x06, 0x03, 0x01};
+static unsigned char symbol24_45_bits[] = {
+0xff, 0x07, 0xff, 0x07};
+static unsigned char symbol24_46_bits[] = {
+0x03, 0x03, 0x03};
+static unsigned char symbol24_47_bits[] = {
+0x60, 0x60, 0x60, 0x30, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x0c, 0x06, 
+0x06, 0x06, 0x03, 0x03, 0x03};
+static unsigned char symbol24_48_bits[] = {
+0x78, 0x00, 0xcc, 0x00, 0x86, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x86, 0x01, 0x86, 0x01, 0xcc, 0x00, 0x78, 0x00};
+static unsigned char symbol24_49_bits[] = {
+0x0c, 0x0e, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x3f};
+static unsigned char symbol24_50_bits[] = {
+0x38, 0x00, 0xfe, 0x00, 0xe6, 0x00, 0xc1, 0x01, 0x81, 0x01, 0x80, 0x01, 
+0x80, 0x01, 0xc0, 0x01, 0xc0, 0x00, 0xe0, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x18, 0x00, 0x0c, 0x00, 0x06, 0x02, 0xff, 0x03, 0xff, 0x01};
+static unsigned char symbol24_51_bits[] = {
+0x38, 0x00, 0x7e, 0x00, 0xe2, 0x00, 0xc1, 0x00, 0xc1, 0x00, 0x60, 0x00, 
+0x30, 0x00, 0x78, 0x00, 0xe0, 0x00, 0xc0, 0x00, 0x80, 0x01, 0x80, 0x01, 
+0x80, 0x01, 0xc0, 0x00, 0xe3, 0x00, 0x7f, 0x00, 0x1e, 0x00};
+static unsigned char symbol24_52_bits[] = {
+0xc0, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd8, 0x00, 
+0xc8, 0x00, 0xcc, 0x00, 0xc4, 0x00, 0xc6, 0x00, 0xc2, 0x00, 0xff, 0x03, 
+0xff, 0x03, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00};
+static unsigned char symbol24_53_bits[] = {
+0xfc, 0x01, 0xfc, 0x00, 0x06, 0x00, 0x02, 0x00, 0x03, 0x00, 0x0f, 0x00, 
+0x3f, 0x00, 0x78, 0x00, 0xe0, 0x00, 0xc0, 0x01, 0x80, 0x01, 0x80, 0x01, 
+0x80, 0x01, 0x80, 0x01, 0xc3, 0x00, 0x7f, 0x00, 0x3e, 0x00};
+static unsigned char symbol24_54_bits[] = {
+0xc0, 0x03, 0x70, 0x00, 0x1c, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x07, 0x00, 
+0xf3, 0x00, 0xcf, 0x01, 0x87, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x07, 0x03, 0x86, 0x03, 0xce, 0x01, 0xf8, 0x00};
+static unsigned char symbol24_55_bits[] = {
+0xfe, 0x03, 0xff, 0x03, 0x03, 0x03, 0x81, 0x01, 0x80, 0x01, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00};
+static unsigned char symbol24_56_bits[] = {
+0x78, 0x00, 0xcc, 0x00, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 0xce, 0x00, 
+0x7c, 0x00, 0x38, 0x00, 0xfc, 0x00, 0xc6, 0x01, 0x83, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc6, 0x01, 0x7c, 0x00};
+static unsigned char symbol24_57_bits[] = {
+0x78, 0x00, 0xce, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x86, 0x03, 0xce, 0x03, 0x78, 0x03, 0x80, 0x01, 
+0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x3c, 0x00, 0x0f, 0x00};
+static unsigned char symbol24_58_bits[] = {
+0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03};
+static unsigned char symbol24_59_bits[] = {
+0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x04, 
+0x06, 0x03, 0x01};
+static unsigned char symbol24_60_bits[] = {
+0x00, 0x0e, 0x80, 0x07, 0xe0, 0x01, 0x78, 0x00, 0x1e, 0x00, 0x07, 0x00, 
+0x07, 0x00, 0x1e, 0x00, 0x78, 0x00, 0xe0, 0x01, 0x80, 0x07, 0x00, 0x0e};
+static unsigned char symbol24_61_bits[] = {
+0xff, 0x03, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xff, 0x03};
+static unsigned char symbol24_62_bits[] = {
+0x07, 0x00, 0x1e, 0x00, 0x78, 0x00, 0xe0, 0x01, 0x80, 0x07, 0x00, 0x0e, 
+0x00, 0x0e, 0x80, 0x07, 0xe0, 0x01, 0x78, 0x00, 0x1e, 0x00, 0x07, 0x00};
+static unsigned char symbol24_63_bits[] = {
+0x3e, 0x63, 0xc1, 0xc3, 0xe3, 0x60, 0x70, 0x30, 0x18, 0x18, 0x08, 0x08, 
+0x08, 0x00, 0x00, 0x0c, 0x0c};
+static unsigned char symbol24_64_bits[] = {
+0x1c, 0x04, 0x3e, 0x06, 0xe3, 0x03, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 
+0xff, 0x07, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0xff, 0x07};
+static unsigned char symbol24_65_bits[] = {
+0x00, 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 
+0xc0, 0x06, 0x00, 0x40, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x60, 0x0c, 0x00, 
+0x20, 0x0c, 0x00, 0x30, 0x18, 0x00, 0x10, 0x18, 0x00, 0xf0, 0x3f, 0x00, 
+0x18, 0x30, 0x00, 0x08, 0x30, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 
+0x1f, 0xf0, 0x01};
+static unsigned char symbol24_66_bits[] = {
+0xff, 0x03, 0x0c, 0x07, 0x0c, 0x0e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x06, 0xfc, 0x03, 0x0c, 0x0e, 0x0c, 0x1c, 0x0c, 0x18, 
+0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x1c, 0x0c, 0x0e, 0xff, 0x03};
+static unsigned char symbol24_67_bits[] = {
+0x1f, 0xf8, 0x01, 0x0e, 0x70, 0x00, 0x1c, 0x30, 0x00, 0x38, 0x18, 0x00, 
+0x30, 0x0c, 0x00, 0x60, 0x06, 0x00, 0xe0, 0x03, 0x00, 0xc0, 0x01, 0x00, 
+0x80, 0x01, 0x00, 0xc0, 0x03, 0x00, 0x60, 0x07, 0x00, 0x30, 0x0e, 0x00, 
+0x10, 0x1c, 0x00, 0x18, 0x18, 0x00, 0x0c, 0x38, 0x00, 0x0e, 0x70, 0x00, 
+0x1f, 0xf8, 0x01};
+static unsigned char symbol24_68_bits[] = {
+0xc0, 0x00, 0xc0, 0x00, 0xe0, 0x01, 0x20, 0x01, 0x20, 0x03, 0x30, 0x03, 
+0x10, 0x06, 0x10, 0x06, 0x18, 0x0c, 0x08, 0x0c, 0x0c, 0x18, 0x04, 0x18, 
+0x04, 0x30, 0x06, 0x30, 0x02, 0x60, 0x03, 0x60, 0xff, 0xff};
+static unsigned char symbol24_69_bits[] = {
+0xff, 0x0f, 0x0c, 0x0c, 0x0c, 0x08, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x04, 0x0c, 0x04, 0xfc, 0x07, 0x0c, 0x04, 0x0c, 0x04, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x10, 0x0c, 0x10, 0x0c, 0x18, 0xff, 0x1f};
+static unsigned char symbol24_70_bits[] = {
+0xe0, 0x07, 0x80, 0x01, 0x80, 0x01, 0xf0, 0x0f, 0x9c, 0x39, 0x86, 0x61, 
+0x87, 0xe1, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0x87, 0xe1, 0x86, 0x61, 
+0x9c, 0x39, 0xf0, 0x0f, 0x80, 0x01, 0x80, 0x01, 0xe0, 0x07};
+static unsigned char symbol24_71_bits[] = {
+0xff, 0x1f, 0x0c, 0x18, 0x0c, 0x10, 0x0c, 0x10, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x3f, 0x00};
+static unsigned char symbol24_72_bits[] = {
+0x3f, 0xfc, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 
+0x0c, 0x30, 0x0c, 0x30, 0xfc, 0x3f, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 
+0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x3f, 0xfc};
+static unsigned char symbol24_73_bits[] = {
+0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x3f};
+static unsigned char symbol24_74_bits[] = {
+0xc0, 0x03, 0x60, 0x07, 0x20, 0x06, 0x60, 0x06, 0xc0, 0x0c, 0x8e, 0x0d, 
+0x1f, 0x0f, 0x19, 0x3c, 0x18, 0x0c, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x06, 0x1c, 0x06, 0x38, 0x03, 0xf0, 0x01};
+static unsigned char symbol24_75_bits[] = {
+0x3f, 0x3e, 0x0c, 0x0c, 0x0c, 0x06, 0x0c, 0x03, 0x8c, 0x01, 0xcc, 0x00, 
+0x6c, 0x00, 0x7c, 0x00, 0xfc, 0x00, 0xcc, 0x01, 0x8c, 0x01, 0x8c, 0x03, 
+0x0c, 0x07, 0x0c, 0x0e, 0x0c, 0x1c, 0x0c, 0x38, 0x3f, 0x7c};
+static unsigned char symbol24_76_bits[] = {
+0xc0, 0x00, 0xc0, 0x00, 0xe0, 0x01, 0x20, 0x01, 0x20, 0x03, 0x20, 0x03, 
+0x30, 0x03, 0x10, 0x06, 0x10, 0x06, 0x18, 0x06, 0x08, 0x0c, 0x08, 0x0c, 
+0x0c, 0x0c, 0x04, 0x18, 0x04, 0x18, 0x06, 0x38, 0x1f, 0x7c};
+static unsigned char symbol24_77_bits[] = {
+0x0f, 0x80, 0x0f, 0x1c, 0x80, 0x03, 0x1c, 0xc0, 0x03, 0x3c, 0x40, 0x03, 
+0x34, 0x40, 0x03, 0x74, 0x60, 0x03, 0x64, 0x20, 0x03, 0xe4, 0x30, 0x03, 
+0xc4, 0x10, 0x03, 0xc4, 0x11, 0x03, 0x84, 0x19, 0x03, 0x84, 0x0b, 0x03, 
+0x04, 0x0b, 0x03, 0x04, 0x0f, 0x03, 0x04, 0x06, 0x03, 0x04, 0x06, 0x03, 
+0x1f, 0xc0, 0x0f};
+static unsigned char symbol24_78_bits[] = {
+0x0f, 0xf8, 0x1c, 0x20, 0x1c, 0x20, 0x34, 0x20, 0x74, 0x20, 0x64, 0x20, 
+0xc4, 0x20, 0xc4, 0x20, 0x84, 0x21, 0x84, 0x23, 0x04, 0x23, 0x04, 0x26, 
+0x04, 0x26, 0x04, 0x2c, 0x04, 0x3c, 0x04, 0x38, 0x1f, 0x30};
+static unsigned char symbol24_79_bits[] = {
+0xe0, 0x07, 0x38, 0x1c, 0x0c, 0x30, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x06, 0x60, 0x06, 0x60, 0x0c, 0x30, 0x38, 0x1c, 0xe0, 0x07};
+static unsigned char symbol24_80_bits[] = {
+0xff, 0xff, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 
+0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 
+0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x3f, 0xfc};
+static unsigned char symbol24_81_bits[] = {
+0xe0, 0x07, 0x38, 0x1c, 0x0c, 0x30, 0x06, 0x60, 0x06, 0x60, 0x13, 0xc8, 
+0x13, 0xc8, 0xf3, 0xcf, 0xf3, 0xcf, 0x13, 0xc8, 0x13, 0xc8, 0x03, 0xc0, 
+0x02, 0x40, 0x06, 0x60, 0x0c, 0x30, 0x38, 0x1c, 0xe0, 0x07};
+static unsigned char symbol24_82_bits[] = {
+0xff, 0x01, 0x0c, 0x07, 0x0c, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x06, 0x0c, 0x07, 0xfc, 0x01, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x3f, 0x00};
+static unsigned char symbol24_83_bits[] = {
+0xff, 0x0f, 0x07, 0x0c, 0x0e, 0x08, 0x1c, 0x00, 0x38, 0x00, 0x70, 0x00, 
+0xe0, 0x00, 0xc0, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 
+0x0c, 0x08, 0x06, 0x08, 0x03, 0x0c, 0xff, 0x0f, 0xff, 0x0f};
+static unsigned char symbol24_84_bits[] = {
+0xff, 0x3f, 0xc3, 0x30, 0xc1, 0x20, 0xc1, 0x20, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xf0, 0x03};
+static unsigned char symbol24_85_bits[] = {
+0x1f, 0xf8, 0x0e, 0x70, 0x0c, 0x30, 0x18, 0x18, 0x38, 0x08, 0x30, 0x0c, 
+0x70, 0x06, 0x60, 0x06, 0xc0, 0x03, 0xc0, 0x03, 0x80, 0x01, 0x80, 0x01, 
+0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xe0, 0x07};
+static unsigned char symbol24_86_bits[] = {
+0xf8, 0x01, 0xfc, 0x01, 0x06, 0x00, 0x06, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0xfe, 0x00, 
+0xf8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x80, 0x01, 0xf0, 0x00, 0x70, 0x00};
+static unsigned char symbol24_87_bits[] = {
+0xe0, 0x07, 0x38, 0x1c, 0x0c, 0x30, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x07, 0xe0, 0x06, 0x60, 0x0c, 0x30, 
+0x18, 0x18, 0x31, 0x8c, 0x21, 0x84, 0x3f, 0xfc, 0x3f, 0xfc};
+static unsigned char symbol24_88_bits[] = {
+0xfe, 0x1f, 0xfe, 0x1f, 0x06, 0x18, 0x02, 0x10, 0x00, 0x00, 0x08, 0x04, 
+0x08, 0x04, 0xf8, 0x07, 0xf8, 0x07, 0x08, 0x04, 0x08, 0x04, 0x00, 0x00, 
+0x01, 0x20, 0x01, 0x20, 0x03, 0x30, 0xff, 0x3f, 0xff, 0x3f};
+static unsigned char symbol24_89_bits[] = {
+0xc7, 0x8f, 0x03, 0x0e, 0xc3, 0x01, 0x0c, 0xc3, 0x00, 0x0c, 0xc3, 0x00, 
+0x1c, 0xe3, 0x00, 0x1c, 0xe3, 0x00, 0x18, 0x63, 0x00, 0x38, 0x73, 0x00, 
+0xe0, 0x1f, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 
+0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 
+0xc0, 0x0f, 0x00};
+static unsigned char symbol24_90_bits[] = {
+0xff, 0x0f, 0x03, 0x0e, 0x01, 0x06, 0x00, 0x07, 0x80, 0x03, 0x80, 0x01, 
+0xc0, 0x01, 0xe0, 0x00, 0x60, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00, 
+0x1c, 0x00, 0x0e, 0x00, 0x06, 0x08, 0x07, 0x0c, 0xff, 0x0f};
+static unsigned char symbol24_91_bits[] = {
+0x1f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x1f};
+static unsigned char symbol24_92_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c};
+static unsigned char symbol24_93_bits[] = {
+0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f};
+static unsigned char symbol24_94_bits[] = {
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xff, 0x3f, 0xff, 0x3f};
+static unsigned char symbol24_95_bits[] = {
+0xff, 0x1f, 0xff, 0x1f};
+static unsigned char symbol24_96_bits[] = {
+0xff, 0x1f, 0xff, 0x1f};
+static unsigned char symbol24_97_bits[] = {
+0xf8, 0x18, 0x8e, 0x1d, 0x06, 0x0d, 0x07, 0x0f, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x07, 0x07, 0x06, 0x27, 0x8e, 0x3f, 
+0xf8, 0x1c};
+static unsigned char symbol24_98_bits[] = {
+0x7c, 0x00, 0xe6, 0x00, 0xc3, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc3, 0x01, 
+0xc3, 0x00, 0x73, 0x00, 0xf3, 0x00, 0xc3, 0x01, 0x83, 0x01, 0x83, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0x87, 0x01, 0xcf, 0x01, 
+0xfb, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00};
+static unsigned char symbol24_99_bits[] = {
+0x0e, 0x06, 0x1f, 0x06, 0x1b, 0x03, 0x11, 0x03, 0x90, 0x01, 0x90, 0x01, 
+0xd0, 0x00, 0xe0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x70, 0x00, 0x70, 0x00, 
+0x98, 0x00, 0x98, 0x00, 0x8c, 0x08, 0x8c, 0x0d, 0x86, 0x0f, 0x06, 0x07};
+static unsigned char symbol24_100_bits[] = {
+0xf8, 0x00, 0xcc, 0x01, 0x84, 0x01, 0x0c, 0x00, 0x1c, 0x00, 0x38, 0x00, 
+0x70, 0x00, 0xfc, 0x00, 0xce, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x86, 0x01, 0xce, 0x01, 0x78, 0x00};
+static unsigned char symbol24_101_bits[] = {
+0x7c, 0x00, 0xce, 0x00, 0xc7, 0x00, 0xc3, 0x00, 0x07, 0x00, 0x06, 0x00, 
+0x3c, 0x00, 0x06, 0x00, 0x07, 0x00, 0x03, 0x00, 0x07, 0x01, 0x8e, 0x01, 
+0xfc, 0x00};
+static unsigned char symbol24_102_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xf8, 0x01, 0x6c, 0x03, 
+0x66, 0x06, 0x67, 0x0e, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 
+0x63, 0x0c, 0x67, 0x0e, 0x66, 0x06, 0x6c, 0x03, 0xf8, 0x01, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char symbol24_103_bits[] = {
+0x0e, 0x06, 0x1f, 0x06, 0x19, 0x06, 0x19, 0x03, 0x18, 0x03, 0x30, 0x03, 
+0xb0, 0x01, 0xb0, 0x01, 0xa0, 0x01, 0xe0, 0x00, 0xe0, 0x00, 0xc0, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char symbol24_104_bits[] = {
+0x8e, 0x03, 0xdf, 0x07, 0x79, 0x0c, 0x38, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 
+0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 
+0x18, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c};
+static unsigned char symbol24_105_bits[] = {
+0x0c, 0x0e, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x4c, 0x7c, 
+0x38};
+static unsigned char symbol24_106_bits[] = {
+0xcc, 0x01, 0xce, 0x03, 0x66, 0x06, 0x63, 0x0e, 0x63, 0x0c, 0x63, 0x0c, 
+0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x67, 0x0e, 0x66, 0x06, 0x6c, 0x03, 
+0xf8, 0x01, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char symbol24_107_bits[] = {
+0x0c, 0x0e, 0x0e, 0x0f, 0x8f, 0x0d, 0xcc, 0x00, 0x6c, 0x00, 0x3c, 0x00, 
+0x3c, 0x00, 0x7c, 0x00, 0xec, 0x00, 0xcc, 0x01, 0x8c, 0x03, 0x0c, 0x07, 
+0x8c, 0x0f};
+static unsigned char symbol24_108_bits[] = {
+0x0e, 0x00, 0x1f, 0x00, 0x11, 0x00, 0x10, 0x00, 0x10, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x78, 0x00, 0x58, 0x00, 0x4c, 0x00, 
+0x4c, 0x00, 0xcc, 0x00, 0x86, 0x00, 0x86, 0x00, 0x86, 0x09, 0x83, 0x0f, 
+0x03, 0x07};
+static unsigned char symbol24_109_bits[] = {
+0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 
+0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc7, 0x09, 0xff, 0x0f, 
+0x7b, 0x06, 0x03, 0x00, 0x03, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00};
+static unsigned char symbol24_110_bits[] = {
+0x03, 0x07, 0x03, 0x07, 0x03, 0x06, 0x06, 0x02, 0x06, 0x03, 0x06, 0x01, 
+0x8c, 0x01, 0x8c, 0x00, 0xcc, 0x00, 0x58, 0x00, 0x58, 0x00, 0x70, 0x00, 
+0x30, 0x00};
+static unsigned char symbol24_111_bits[] = {
+0xf8, 0x00, 0x8e, 0x03, 0x06, 0x03, 0x07, 0x07, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x07, 0x07, 0x06, 0x03, 0x8e, 0x03, 
+0xf8, 0x00};
+static unsigned char symbol24_112_bits[] = {
+0xfe, 0x1f, 0xff, 0x1f, 0x19, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 
+0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x13, 0x1c, 0x1f, 
+0x0c, 0x0f};
+static unsigned char symbol24_113_bits[] = {
+0x78, 0x00, 0xcc, 0x00, 0x86, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x86, 0x01, 0x86, 0x01, 0xcc, 0x00, 0x78, 0x00};
+static unsigned char symbol24_114_bits[] = {
+0x7c, 0x00, 0xc6, 0x01, 0x83, 0x01, 0x83, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0x83, 0x01, 0xc7, 0x01, 
+0x7b, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00};
+static unsigned char symbol24_115_bits[] = {
+0xf8, 0x3f, 0x8e, 0x3f, 0x06, 0x03, 0x07, 0x07, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x07, 0x07, 0x06, 0x03, 0x8e, 0x03, 
+0xf8, 0x00};
+static unsigned char symbol24_116_bits[] = {
+0xfc, 0x03, 0xfe, 0x03, 0x33, 0x00, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x01, 0xf0, 0x01, 
+0xe0, 0x00};
+static unsigned char symbol24_117_bits[] = {
+0x0c, 0x07, 0x1e, 0x0c, 0x1b, 0x18, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x30, 0x0c, 0x70, 0x07, 
+0xe0, 0x03};
+static unsigned char symbol24_118_bits[] = {
+0xfe, 0xff, 0xff, 0xff, 0x19, 0x18, 0x0c, 0x30, 0x8c, 0x31, 0x86, 0x61, 
+0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x8c, 0x31, 
+0xdc, 0x3b, 0x78, 0x1e};
+static unsigned char symbol24_119_bits[] = {
+0x18, 0x06, 0x0c, 0x0c, 0x06, 0x18, 0xc6, 0x18, 0xc3, 0x30, 0xc3, 0x30, 
+0xc3, 0x30, 0xc3, 0x30, 0xc3, 0x30, 0xc3, 0x30, 0xc6, 0x18, 0xee, 0x1d, 
+0x3c, 0x0f};
+static unsigned char symbol24_120_bits[] = {
+0x0c, 0x00, 0xc6, 0x01, 0xe6, 0x01, 0xfc, 0x00, 0x0c, 0x00, 0x04, 0x00, 
+0xec, 0x01, 0xf8, 0x01, 0x0c, 0x00, 0x06, 0x00, 0x03, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x3e, 0x00, 0xfc, 0x01, 
+0xf0, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0xf0, 0x01, 0xf0, 0x00};
+static unsigned char symbol24_121_bits[] = {
+0x83, 0xc1, 0x8e, 0x71, 0x8c, 0x31, 0x9c, 0x39, 0x9c, 0x39, 0x9c, 0x39, 
+0x9c, 0x39, 0x9c, 0x39, 0x9c, 0x39, 0x98, 0x19, 0x98, 0x19, 0xb0, 0x0d, 
+0xe0, 0x07, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01};
+static unsigned char symbol24_122_bits[] = {
+0x0c, 0x00, 0xc6, 0x01, 0xe6, 0x01, 0xfc, 0x00, 0x18, 0x00, 0x0c, 0x00, 
+0x04, 0x00, 0x06, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x3e, 0x00, 0xfc, 0x01, 
+0xf0, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0xf0, 0x01, 0xf0, 0x00};
+static unsigned char symbol24_123_bits[] = {
+0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x08, 0x0c, 0x04, 0x03, 0x04, 
+0x0c, 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0};
+static unsigned char symbol24_124_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_125_bits[] = {
+0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x10, 0x30, 0x20, 0xc0, 0x20, 
+0x30, 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x07};
+static unsigned char symbol24_126_bits[] = {
+0x1c, 0x04, 0x3e, 0x06, 0xe3, 0x03, 0xc1, 0x01};
+static unsigned char symbol24_127_bits[] = {
+0x00};
+static unsigned char symbol24_128_bits[] = {
+0x00};
+static unsigned char symbol24_129_bits[] = {
+0x00};
+static unsigned char symbol24_130_bits[] = {
+0x00};
+static unsigned char symbol24_131_bits[] = {
+0x00};
+static unsigned char symbol24_132_bits[] = {
+0x00};
+static unsigned char symbol24_133_bits[] = {
+0x00};
+static unsigned char symbol24_134_bits[] = {
+0x00};
+static unsigned char symbol24_135_bits[] = {
+0x00};
+static unsigned char symbol24_136_bits[] = {
+0x00};
+static unsigned char symbol24_137_bits[] = {
+0x00};
+static unsigned char symbol24_138_bits[] = {
+0x00};
+static unsigned char symbol24_139_bits[] = {
+0x00};
+static unsigned char symbol24_140_bits[] = {
+0x00};
+static unsigned char symbol24_141_bits[] = {
+0x00};
+static unsigned char symbol24_142_bits[] = {
+0x00};
+static unsigned char symbol24_143_bits[] = {
+0x00};
+static unsigned char symbol24_144_bits[] = {
+0x00};
+static unsigned char symbol24_145_bits[] = {
+0x00};
+static unsigned char symbol24_146_bits[] = {
+0x00};
+static unsigned char symbol24_147_bits[] = {
+0x00};
+static unsigned char symbol24_148_bits[] = {
+0x00};
+static unsigned char symbol24_149_bits[] = {
+0x00};
+static unsigned char symbol24_150_bits[] = {
+0x00};
+static unsigned char symbol24_151_bits[] = {
+0x00};
+static unsigned char symbol24_152_bits[] = {
+0x00};
+static unsigned char symbol24_153_bits[] = {
+0x00};
+static unsigned char symbol24_154_bits[] = {
+0x00};
+static unsigned char symbol24_155_bits[] = {
+0x00};
+static unsigned char symbol24_156_bits[] = {
+0x00};
+static unsigned char symbol24_157_bits[] = {
+0x00};
+static unsigned char symbol24_158_bits[] = {
+0x00};
+static unsigned char symbol24_159_bits[] = {
+0x00};
+static unsigned char symbol24_160_bits[] = {
+0x00};
+static unsigned char symbol24_161_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol24_162_bits[] = {
+0x07, 0x0e, 0x0e, 0x1b, 0x1c, 0x1d};
+static unsigned char symbol24_163_bits[] = {
+0xd8, 0x0c, 0x70, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0xf8, 0x01, 0x18, 0x0c};
+static unsigned char symbol24_164_bits[] = {
+0x0e, 0x06, 0x03, 0x01, 0x00, 0x0e, 0x80, 0x07, 0xe0, 0x01, 0x78, 0x00, 
+0x1e, 0x00, 0x07, 0x00, 0x07};
+static unsigned char symbol24_165_bits[] = {
+0x00, 0x1e, 0x00, 0x78, 0x00, 0x40, 0x03, 0x00, 0x0f, 0x00, 0x0c, 0x00, 
+0x00, 0x7f};
+static unsigned char symbol24_166_bits[] = {
+0x0f, 0x1f, 0x0f, 0x00, 0xc0, 0x00, 0x60, 0x10, 0x30, 0x18, 0x18, 0x18, 
+0x0c, 0x0c, 0x06, 0x06, 0x06, 0x03, 0x03, 0x03, 0x1c, 0x1c, 0x7e, 0x1e, 
+0xe3, 0x03, 0xc3, 0x01, 0x63, 0x03, 0x3e, 0x1e, 0x1c, 0x1c, 0x00, 0x0f, 
+0x80, 0x19, 0x80, 0x19, 0xc0, 0x00, 0xc0, 0x00};
+static unsigned char symbol24_167_bits[] = {
+0xc0, 0x00, 0xf8, 0x07, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 
+0x30, 0x00};
+static unsigned char symbol24_168_bits[] = {
+0x33, 0x00, 0x33, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0xe0, 0x01, 0xf0, 0x03, 
+0xf0, 0x03, 0xf0, 0x03, 0xf0, 0x03, 0xee, 0x01, 0xdf, 0x02, 0xff, 0x03, 
+0xff, 0x03};
+static unsigned char symbol24_169_bits[] = {
+0xdf, 0x0e, 0xce, 0x0c, 0xc0, 0x00, 0xe0, 0x01, 0x30, 0x00, 0x30, 0x00, 
+0x78, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfe, 0x01, 0xff, 0x03, 0xfe, 0x01, 
+0xfc, 0x00};
+static unsigned char symbol24_170_bits[] = {
+0xfc, 0x00, 0x78, 0x00, 0x30, 0x00, 0x30, 0x00, 0x0e, 0x07, 0x9f, 0x0f, 
+0x9f, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 0xfe, 0x07, 0xfe, 0x07, 
+0xfc, 0x03};
+static unsigned char symbol24_171_bits[] = {
+0xf8, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0xf0, 0x00, 0xf8, 0x01, 0xfc, 0x03, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0x0f, 
+0xff, 0x0f, 0x6f, 0x0f, 0x66, 0x06, 0x60, 0x00, 0xf0, 0x00, 0x60, 0x00};
+static unsigned char symbol24_172_bits[] = {
+0x06, 0x30, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x30, 0x06, 0x00, 
+0x60, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0x00, 0x60, 0x0c, 0x00, 
+0x30, 0x18, 0x00, 0x00, 0x30, 0x00, 0x0c, 0x00, 0x00, 0x06, 0x60, 0x00, 
+0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00};
+static unsigned char symbol24_173_bits[] = {
+0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0x0f, 0xff, 0x01, 0xff, 0x0f, 
+0xff, 0x01, 0x06, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x18, 0x00, 
+0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 
+0xf0, 0x00, 0xf8, 0x01, 0x6c, 0x03, 0x66, 0x06, 0x63, 0x0c, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00};
+static unsigned char symbol24_174_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 
+0x0c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00};
+static unsigned char symbol24_175_bits[] = {
+0x60, 0x00, 0x00, 0x00, 0xc0, 0x00, 0xff, 0x0f, 0xff, 0x01, 0xff, 0x0f, 
+0xff, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 
+0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char symbol24_176_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60};
+static unsigned char symbol24_177_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x03, 0x0c, 0x02, 0x06, 0x00, 0x03, 0x00, 0x01, 0x00, 
+0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol24_178_bits[] = {
+0x36, 0x01, 0x41, 0x01, 0x36, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00};
+static unsigned char symbol24_179_bits[] = {
+0x30, 0x00, 0xff, 0x03, 0xff, 0x03, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xff, 0x03, 0x98, 0x01, 
+0xdc, 0x01, 0xee, 0x00, 0x66, 0x00};
+static unsigned char symbol24_180_bits[] = {
+0x33, 0x00, 0x11, 0x00, 0x07, 0x00, 0x1e, 0x00, 0x78, 0x00, 0xe0, 0x01, 
+0x80, 0x07, 0x00, 0x06, 0x00, 0x06, 0x80, 0x07};
+static unsigned char symbol24_181_bits[] = {
+0xe0, 0x01, 0x7c, 0x00, 0x0f, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0x0f, 
+0xff, 0x0f};
+static unsigned char symbol24_182_bits[] = {
+0x03, 0x02, 0x06, 0x03, 0x8c, 0x01, 0xd8, 0x00, 0x70, 0x00, 0x70, 0x00, 
+0xd8, 0x00, 0x8c, 0x01, 0x06, 0x03, 0x03, 0x02, 0x1c, 0x00, 0x3e, 0x02, 
+0x63, 0x03, 0xc3, 0x01, 0xe3, 0x03, 0x3e, 0x02, 0x1c, 0x00, 0x7c, 0x00, 
+0xc6, 0x00};
+static unsigned char symbol24_183_bits[] = {
+0x83, 0x01, 0x80, 0x01, 0x00, 0x03, 0x00, 0x03};
+static unsigned char symbol24_184_bits[] = {
+0x00, 0x03, 0x00, 0x03, 0x78, 0x03, 0xce, 0x03, 0x86, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x83, 0x01};
+static unsigned char symbol24_185_bits[] = {
+0x83, 0x01, 0x83, 0x01, 0xc3, 0x00, 0xe6, 0x00, 0x3c, 0x00, 0x3c, 0x02, 
+0xff, 0x03, 0xff, 0x03, 0x7e, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 
+0xff, 0x03};
+static unsigned char symbol24_186_bits[] = {
+0xff, 0x03, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x80, 0x01, 0x80, 0x01, 
+0xc0, 0x00, 0xc0, 0x00};
+static unsigned char symbol24_187_bits[] = {
+0xff, 0x03, 0xff, 0x03, 0x30, 0x00, 0xff, 0x03, 0xff, 0x03, 0x0c, 0x00, 
+0x0c, 0x00, 0x06, 0x00};
+static unsigned char symbol24_188_bits[] = {
+0x06, 0x00, 0x03, 0x07, 0xff, 0x03, 0x00, 0x00, 0x03};
+static unsigned char symbol24_189_bits[] = {
+0x03, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x02, 
+0x02, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x01, 
+0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_190_bits[] = {
+0x03, 0x03, 0x03, 0x01, 0x03, 0x03, 0x03, 0x01};
+static unsigned char symbol24_191_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0xff, 0x3f, 0xff, 0x01, 0xff, 0x3f};
+static unsigned char symbol24_192_bits[] = {
+0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 
+0x06, 0x00, 0xff, 0x0f, 0xff, 0x0f, 0x06, 0x00};
+static unsigned char symbol24_193_bits[] = {
+0x04, 0x00, 0x81, 0x01, 0xc3, 0x00, 0xc7, 0x0f, 0x8e, 0x0f, 0x1c, 0x06, 
+0x38, 0x03, 0x3c, 0x01, 0x76, 0x01, 0xe3, 0x01, 0xc3, 0x01, 0xc7, 0x01, 
+0x8f, 0x03, 0x0e, 0x07, 0x0c, 0x0e, 0x0e, 0x0c, 0x07, 0x08, 0xf0, 0x01, 
+0xfc, 0x3f};
+static unsigned char symbol24_194_bits[] = {
+0x0e, 0x1f, 0x00, 0x0c, 0x02, 0x00, 0x02, 0x03, 0x00, 0x03, 0x0c, 0x01, 
+0x38, 0x0e, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x38, 0x00, 0x00, 
+0x0c, 0x30, 0x00, 0x30, 0x7b, 0x00, 0xf0, 0x0f, 0x00, 0x03, 0x78, 0x00, 
+0x00, 0xfc, 0x00, 0x00, 0xc6, 0x01, 0x00, 0x83, 0x01, 0x00, 0x81, 0x01, 
+0x00, 0x83, 0x01, 0x00, 0x87, 0x01};
+static unsigned char symbol24_195_bits[] = {
+0x00, 0x0e, 0x1d, 0x00, 0x9c, 0x0d, 0x00, 0x18, 0x19, 0x00, 0x88, 0x19, 
+0x00, 0x00, 0x19, 0x00, 0x80, 0x39, 0x00, 0x00, 0x31, 0x00, 0x80, 0x31, 
+0x00, 0x18, 0x61, 0x01, 0xfc, 0x60, 0x01, 0x72, 0xe0, 0x00, 0x60, 0x00, 
+0x30, 0x00, 0x18, 0x3c};
+static unsigned char symbol24_196_bits[] = {
+0x0c, 0x7f, 0x8c, 0x61, 0xc6, 0x60, 0x66, 0x60, 0x36, 0x60, 0x16, 0x30, 
+0x9e, 0x39, 0xce, 0x19, 0x4e, 0x0c, 0x5e, 0x0e, 0xda, 0x07, 0xbb, 0x01, 
+0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00};
+static unsigned char symbol24_197_bits[] = {
+0xe0, 0x07, 0x78, 0x1e, 0x1c, 0x38, 0x06, 0x60, 0x16, 0x68, 0x33, 0xcc, 
+0x63, 0xc6, 0xc3, 0xc3, 0x83, 0xc1, 0xc3, 0xc3, 0x63, 0xc6, 0x33, 0xcc, 
+0x16, 0x68, 0x06, 0x60, 0x1c, 0x38, 0x78, 0x1e, 0xe0, 0x07};
+static unsigned char symbol24_198_bits[] = {
+0xe0, 0x07, 0x00, 0x1e, 0x1c, 0x00, 0x86, 0x61, 0x02, 0x61, 0x83, 0x01, 
+0x83, 0xc1, 0x03, 0xdf, 0xfb, 0x03, 0x83, 0xc1, 0x03, 0xc1, 0x83, 0x01, 
+0x86, 0x61, 0x02, 0x60, 0x1c, 0x00, 0x78, 0x1e, 0x00, 0x07, 0xc0, 0x03, 
+0x03, 0xf0, 0x03, 0x01, 0x38, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 
+0x00, 0x06, 0x00};
+static unsigned char symbol24_199_bits[] = {
+0x01, 0x06, 0x8c, 0x01, 0x06, 0x86, 0x01, 0x06, 0x83, 0x01, 0x86, 0x81, 
+0x01, 0xc6, 0x80, 0x01, 0x66, 0x80, 0x01, 0x3c, 0xc0, 0x00, 0x1c, 0xc0, 
+0x00, 0x3c};
+static unsigned char symbol24_200_bits[] = {
+0x70, 0x00, 0xf6, 0x3f, 0x00, 0xc3, 0x0f, 0x00, 0xe0, 0x07, 0xf8, 0x1f, 
+0x1c, 0x38, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0};
+static unsigned char symbol24_201_bits[] = {
+0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 
+0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40};
+static unsigned char symbol24_202_bits[] = {
+0x06, 0x60, 0x06, 0x60, 0x1c, 0x38, 0xf8, 0x1f, 0xe0, 0x07, 0xff, 0x07, 
+0xff, 0x1f, 0x00, 0x38, 0x00, 0x30, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 
+0x00, 0x60, 0x00, 0x30, 0x00, 0x38};
+static unsigned char symbol24_203_bits[] = {
+0xff, 0x1f, 0xff, 0x07, 0xff, 0x07, 0xff, 0x1f, 0x00, 0x38, 0x00, 0x30, 
+0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x38, 
+0xff, 0x1f, 0xff, 0x07, 0x00, 0x00, 0xff, 0x7f};
+static unsigned char symbol24_204_bits[] = {
+0xff, 0x7f, 0x00, 0x30, 0x00, 0x30, 0xf0, 0x7f, 0xfc, 0x7f, 0x0e, 0x0c, 
+0x06, 0x0c, 0x03, 0x06, 0x03, 0x06, 0x03, 0x03, 0x03, 0x03, 0x86, 0x01};
+static unsigned char symbol24_205_bits[] = {
+0x8e, 0x01, 0xfc, 0x7f, 0xf0, 0x7f, 0x60, 0x00, 0x60, 0x00, 0xf0, 0x7f, 
+0xfc, 0x7f, 0x0e, 0x00, 0x06, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x06, 0x00, 0x0e, 0x00};
+static unsigned char symbol24_206_bits[] = {
+0xfc, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xfc, 0x0f, 0x0e, 0x00, 0x06, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0x0e, 0x00, 
+0xfc, 0x0f};
+static unsigned char symbol24_207_bits[] = {
+0xf0, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0xff, 0x0f, 0xf8, 0x0f, 0xfe, 0x0f, 
+0x06, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x0f, 0xff, 0x0f, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0xfe, 0x0f, 0xf8, 0x0f};
+static unsigned char symbol24_208_bits[] = {
+0x00, 0x03, 0x00, 0x03, 0xf8, 0x01, 0xfe, 0x0f, 0x00, 0x01, 0x83, 0x01, 
+0xc3, 0x00, 0x01, 0x0f, 0xff, 0x01, 0x63, 0x00, 0x01, 0x00, 0x33, 0x00, 
+0x36, 0x00, 0x00, 0x0f, 0xf8, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol24_209_bits[] = {
+0x00, 0x00, 0x0c, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x80, 0x01, 
+0x00, 0xc0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, 
+0x00, 0x0c, 0x00, 0x00, 0xfe, 0xff, 0x01, 0xff, 0xff, 0x01, 0xff, 0xff};
+static unsigned char symbol24_210_bits[] = {
+0x03, 0xc0, 0x03, 0x40, 0x06, 0x60, 0x06, 0x20, 0x0c, 0x30, 0x0c, 0x10, 
+0x0c, 0x18, 0x18, 0x08, 0x18, 0x0c, 0x30, 0x04, 0x30, 0x04, 0x60, 0x06, 
+0x60, 0x02, 0xc0, 0x03, 0xc0, 0x03, 0x80, 0x01, 0x80, 0x01};
+static unsigned char symbol24_211_bits[] = {
+0xe0, 0x07, 0x78, 0x1e, 0x1c, 0x38, 0x06, 0x60, 0xf6, 0x67, 0x63, 0xce, 
+0x63, 0xcc, 0x63, 0xce, 0xe3, 0xc7, 0x63, 0xc3, 0x63, 0xc6, 0x63, 0xcc, 
+0xf6, 0x7c, 0x06, 0x60, 0x1c, 0x38, 0x78, 0x1e, 0xe0, 0x07};
+static unsigned char symbol24_212_bits[] = {
+0xe0, 0x07, 0x08, 0x1e, 0x1c, 0x08, 0x06, 0x60, 0x06, 0x63, 0x63, 0x06, 
+0x33, 0xc4, 0x03, 0xc0, 0x33, 0x00, 0x33, 0xc0, 0x03, 0xc4, 0x63, 0x06, 
+0xc6, 0x63, 0x06, 0x60, 0x1c, 0x08};
+static unsigned char symbol24_213_bits[] = {
+0x78, 0x1e, 0x00, 0x07, 0xff, 0x01, 0x0e, 0x99, 0x00, 0x06, 0x18, 0x00, 
+0x07, 0x18, 0x00, 0x07, 0x18, 0x00, 0x06, 0x18, 0x00, 0x06, 0x18, 0x00, 
+0x06, 0x18, 0x00, 0x06, 0x18, 0x00, 0x06, 0x3c, 0x01, 0x0f, 0xff, 0x01, 
+0x01, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 
+0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 
+0x00, 0x0c, 0x00};
+static unsigned char symbol24_214_bits[] = {
+0x00, 0x0c, 0x60, 0x00, 0x0c, 0x20, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x20, 
+0x00, 0x0c, 0x60, 0x00, 0x0c, 0x20, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x20, 
+0x00, 0x0c, 0x60, 0x00, 0x0c, 0x20, 0x00, 0x3f, 0xf8, 0x01, 0x00, 0x20, 
+0x00, 0x20, 0x00, 0x20, 0x00, 0x30, 0x00, 0x30, 0x00, 0x10};
+static unsigned char symbol24_215_bits[] = {
+0x00, 0x00, 0x00};
+static unsigned char symbol24_216_bits[] = {
+0x10, 0x00, 0x18, 0x0c, 0x18, 0x0e, 0x08, 0x1b, 0x08, 0x18, 0x08, 0x30, 
+0x0c, 0x30, 0x0c, 0x60};
+static unsigned char symbol24_217_bits[] = {
+0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x06, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x03, 0x03, 0x03, 0xff, 0x1f, 0xff, 0x1f, 0x00, 0x00};
+static unsigned char symbol24_218_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 
+0xe0, 0x00, 0xb0, 0x01, 0xb0, 0x01, 0x18, 0x03, 0x18, 0x03, 0x0c, 0x06};
+static unsigned char symbol24_219_bits[] = {
+0x0c, 0x06, 0x06, 0x0c, 0x06, 0x0c, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x03, 0x18, 0x06, 0x0c, 0x06, 0x0c, 0x0c, 0x06, 0x0c, 0x06, 0x18, 0x03, 
+0x18, 0x03, 0x30, 0x01, 0xb0, 0x01, 0xe0, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char symbol24_220_bits[] = {
+0x03, 0x30, 0x00, 0x06, 0x18, 0x00, 0x0c, 0xfc, 0x7f, 0x1f, 0xfe, 0x7f, 
+0x3f, 0x07, 0x00, 0x70, 0x07, 0x00, 0x70, 0xfe, 0x7f, 0x3f, 0xfc, 0x7f, 
+0x1f, 0x18, 0x00, 0x0c, 0x30, 0x00, 0x06, 0x60, 0x00, 0x03, 0x60, 0x00};
+static unsigned char symbol24_221_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x0c, 0xff, 0x0f, 0xfe, 0x0f, 
+0x7f, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0e, 0xff, 0x0f, 0xfc, 0x0f, 
+0x7f, 0x08, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 
+0xf0, 0x00, 0xf8, 0x01, 0x9c, 0x03, 0x9e, 0x07, 0x9b, 0x0d};
+static unsigned char symbol24_222_bits[] = {
+0x98, 0x01, 0x18, 0x01, 0x98, 0x01, 0x98, 0x01, 0x18, 0x01, 0x98, 0x01, 
+0x98, 0x01, 0x18, 0x01, 0x98, 0x01, 0x98, 0x01, 0x18, 0x01, 0x98, 0x01, 
+0x98, 0x01, 0x18, 0x01, 0x98, 0x01, 0x98, 0x01, 0x18, 0x01, 0x00, 0x00};
+static unsigned char symbol24_223_bits[] = {
+0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0c, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 
+0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 
+0x1f, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x98, 0x01, 
+0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01};
+static unsigned char symbol24_224_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 
+0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x9b, 0x01, 
+0x9e, 0x03, 0x9c, 0x03, 0xf8, 0x01, 0xf0, 0x00, 0x60, 0x00, 0x30, 0x00};
+static unsigned char symbol24_225_bits[] = {
+0x30, 0x00, 0x78, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x06, 0x01, 0x06, 0x01, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x01};
+static unsigned char symbol24_226_bits[] = {
+0x86, 0x01, 0xcc, 0x00, 0xcc, 0x00, 0x78, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03, 
+0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60};
+static unsigned char symbol24_227_bits[] = {
+0xe0, 0x07, 0x78, 0x1e, 0x1c, 0x38, 0x06, 0x60, 0xe6, 0x67, 0x63, 0xcc, 
+0x63, 0xcc, 0x63, 0xcc, 0xe3, 0xc7, 0x63, 0xc6, 0x63, 0xcc, 0x63, 0xcc, 
+0x66, 0x4c, 0x06, 0x60, 0x1c, 0x38, 0x78, 0x1e, 0xe0, 0x07};
+static unsigned char symbol24_228_bits[] = {
+0xe0, 0x07, 0x00, 0x1e, 0x1c, 0x00, 0x06, 0x60, 0x02, 0x63, 0xe3, 0x03, 
+0x73, 0xc6, 0x03, 0xc0, 0x33, 0x00, 0x33, 0xc0, 0x03, 0xc6, 0xe3, 0x03, 
+0xc6, 0x63, 0x02, 0x60, 0x1c, 0x00};
+static unsigned char symbol24_229_bits[] = {
+0x78, 0x1e, 0xe0, 0x07, 0x7f, 0x03, 0x03, 0x18, 0x03, 0x03, 0x18, 0x07, 
+0x03, 0x18, 0x87, 0x03, 0x18, 0x0f, 0x03, 0x18, 0x4b, 0x03, 0x18, 0x3b, 
+0x03, 0x18, 0x33, 0x03, 0x18, 0x33, 0x03, 0x18, 0x33, 0x03, 0xff, 0x1f, 
+0x07, 0x18, 0x0e, 0x10};
+static unsigned char symbol24_230_bits[] = {
+0x1c, 0x00, 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01, 0x80, 0x01, 
+0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 
+0x0c, 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x01, 0xff, 0x01, 0x80, 0x01, 
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x18, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x03, 0x00, 
+0x03, 0x00};
+static unsigned char symbol24_231_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00};
+static unsigned char symbol24_232_bits[] = {
+0x03, 0x00, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 
+0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 
+0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00};
+static unsigned char symbol24_233_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 
+0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x18, 0x00, 
+0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0x40};
+static unsigned char symbol24_234_bits[] = {
+0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_235_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_236_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_237_bits[] = {
+0x03, 0x03, 0x1f, 0x18, 0x0c, 0x06, 0x06, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_238_bits[] = {
+0x03, 0x03, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x08, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18};
+static unsigned char symbol24_239_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02};
+static unsigned char symbol24_240_bits[] = {
+0x00};
+static unsigned char symbol24_241_bits[] = {
+0x0c, 0x78, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_242_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 
+0x60, 0x30, 0x30, 0x18};
+static unsigned char symbol24_243_bits[] = {
+0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03, 0xe0, 0xf0, 0xd8, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18};
+static unsigned char symbol24_244_bits[] = {
+0x00, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_245_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03};
+static unsigned char symbol24_246_bits[] = {
+0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x40, 0x00, 0x33, 0x01, 0x0e, 0x01, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x01, 0x00};
+static unsigned char symbol24_247_bits[] = {
+0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00};
+static unsigned char symbol24_248_bits[] = {
+0x01, 0x00, 0x01, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 
+0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 
+0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00};
+static unsigned char symbol24_249_bits[] = {
+0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x40, 
+0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 
+0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x00};
+static unsigned char symbol24_250_bits[] = {
+0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol24_251_bits[] = {
+0x60, 0x60, 0x60, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_252_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 
+0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 
+0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60};
+static unsigned char symbol24_253_bits[] = {
+0x00, 0x00, 0x00, 0x1f, 0x0f, 0x18, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol24_254_bits[] = {
+0x60, 0x60, 0x60, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x02, 0x06, 0x0c, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_255_bits[] = {
+0x00};
+static RotFont symbol24font[] = {
+{5, 1, 1, symbol24_0_bits},
+{5, 1, 1, symbol24_1_bits},
+{5, 1, 1, symbol24_2_bits},
+{5, 1, 1, symbol24_3_bits},
+{5, 1, 1, symbol24_4_bits},
+{5, 1, 1, symbol24_5_bits},
+{5, 1, 1, symbol24_6_bits},
+{5, 1, 1, symbol24_7_bits},
+{5, 1, 1, symbol24_8_bits},
+{5, 1, 1, symbol24_9_bits},
+{5, 1, 1, symbol24_10_bits},
+{5, 1, 1, symbol24_11_bits},
+{5, 1, 1, symbol24_12_bits},
+{5, 1, 1, symbol24_13_bits},
+{5, 1, 1, symbol24_14_bits},
+{5, 1, 1, symbol24_15_bits},
+{5, 1, 1, symbol24_16_bits},
+{5, 1, 1, symbol24_17_bits},
+{5, 1, 1, symbol24_18_bits},
+{5, 1, 1, symbol24_19_bits},
+{5, 1, 1, symbol24_20_bits},
+{5, 1, 1, symbol24_21_bits},
+{5, 1, 1, symbol24_22_bits},
+{5, 1, 1, symbol24_23_bits},
+{5, 1, 1, symbol24_24_bits},
+{5, 1, 1, symbol24_25_bits},
+{5, 1, 1, symbol24_26_bits},
+{5, 1, 1, symbol24_27_bits},
+{5, 1, 1, symbol24_28_bits},
+{5, 1, 1, symbol24_29_bits},
+{5, 1, 1, symbol24_30_bits},
+{5, 1, 1, symbol24_31_bits},
+{1, 1, 1, symbol24_32_bits},
+{3, 17, 17, symbol24_33_bits},
+{15, 17, 17, symbol24_34_bits},
+{11, 17, 17, symbol24_35_bits},
+{11, 17, 17, symbol24_36_bits},
+{18, 17, 17, symbol24_37_bits},
+{15, 17, 17, symbol24_38_bits},
+{8, 13, 13, symbol24_39_bits},
+{6, 22, 17, symbol24_40_bits},
+{6, 22, 17, symbol24_41_bits},
+{8, 10, 17, symbol24_42_bits},
+{10, 10, 12, symbol24_43_bits},
+{3, 6, 2, symbol24_44_bits},
+{11, 2, 8, symbol24_45_bits},
+{2, 3, 3, symbol24_46_bits},
+{7, 17, 17, symbol24_47_bits},
+{10, 17, 17, symbol24_48_bits},
+{6, 17, 17, symbol24_49_bits},
+{10, 17, 17, symbol24_50_bits},
+{9, 17, 17, symbol24_51_bits},
+{10, 17, 17, symbol24_52_bits},
+{9, 17, 17, symbol24_53_bits},
+{10, 17, 17, symbol24_54_bits},
+{10, 17, 17, symbol24_55_bits},
+{10, 17, 17, symbol24_56_bits},
+{10, 17, 17, symbol24_57_bits},
+{2, 11, 11, symbol24_58_bits},
+{3, 15, 11, symbol24_59_bits},
+{12, 12, 13, symbol24_60_bits},
+{10, 6, 10, symbol24_61_bits},
+{12, 12, 13, symbol24_62_bits},
+{8, 17, 17, symbol24_63_bits},
+{11, 12, 13, symbol24_64_bits},
+{17, 17, 17, symbol24_65_bits},
+{13, 17, 17, symbol24_66_bits},
+{17, 17, 17, symbol24_67_bits},
+{16, 17, 17, symbol24_68_bits},
+{13, 17, 17, symbol24_69_bits},
+{16, 17, 17, symbol24_70_bits},
+{13, 17, 17, symbol24_71_bits},
+{16, 17, 17, symbol24_72_bits},
+{6, 17, 17, symbol24_73_bits},
+{14, 17, 17, symbol24_74_bits},
+{15, 17, 17, symbol24_75_bits},
+{15, 17, 17, symbol24_76_bits},
+{20, 17, 17, symbol24_77_bits},
+{16, 17, 17, symbol24_78_bits},
+{16, 17, 17, symbol24_79_bits},
+{16, 17, 17, symbol24_80_bits},
+{16, 17, 17, symbol24_81_bits},
+{12, 17, 17, symbol24_82_bits},
+{12, 17, 17, symbol24_83_bits},
+{14, 17, 17, symbol24_84_bits},
+{16, 17, 17, symbol24_85_bits},
+{9, 18, 13, symbol24_86_bits},
+{16, 17, 17, symbol24_87_bits},
+{14, 17, 17, symbol24_88_bits},
+{18, 17, 17, symbol24_89_bits},
+{12, 17, 17, symbol24_90_bits},
+{5, 22, 17, symbol24_91_bits},
+{12, 10, 10, symbol24_92_bits},
+{5, 22, 17, symbol24_93_bits},
+{14, 17, 17, symbol24_94_bits},
+{13, 2, -3, symbol24_95_bits},
+{13, 2, 23, symbol24_96_bits},
+{14, 13, 13, symbol24_97_bits},
+{10, 24, 19, symbol24_98_bits},
+{12, 18, 13, symbol24_99_bits},
+{10, 18, 18, symbol24_100_bits},
+{9, 13, 13, symbol24_101_bits},
+{12, 22, 17, symbol24_102_bits},
+{11, 18, 13, symbol24_103_bits},
+{12, 18, 13, symbol24_104_bits},
+{7, 13, 13, symbol24_105_bits},
+{12, 18, 13, symbol24_106_bits},
+{12, 13, 13, symbol24_107_bits},
+{12, 19, 19, symbol24_108_bits},
+{12, 18, 13, symbol24_109_bits},
+{11, 13, 13, symbol24_110_bits},
+{11, 13, 13, symbol24_111_bits},
+{13, 13, 13, symbol24_112_bits},
+{10, 17, 17, symbol24_113_bits},
+{10, 18, 13, symbol24_114_bits},
+{14, 13, 13, symbol24_115_bits},
+{10, 13, 13, symbol24_116_bits},
+{13, 13, 13, symbol24_117_bits},
+{16, 14, 14, symbol24_118_bits},
+{14, 13, 13, symbol24_119_bits},
+{10, 24, 19, symbol24_120_bits},
+{16, 18, 13, symbol24_121_bits},
+{10, 24, 19, symbol24_122_bits},
+{8, 22, 17, symbol24_123_bits},
+{2, 22, 17, symbol24_124_bits},
+{8, 22, 17, symbol24_125_bits},
+{11, 4, 9, symbol24_126_bits},
+{5, 1, 1, symbol24_127_bits},
+{5, 1, 1, symbol24_128_bits},
+{5, 1, 1, symbol24_129_bits},
+{5, 1, 1, symbol24_130_bits},
+{5, 1, 1, symbol24_131_bits},
+{5, 1, 1, symbol24_132_bits},
+{5, 1, 1, symbol24_133_bits},
+{5, 1, 1, symbol24_134_bits},
+{5, 1, 1, symbol24_135_bits},
+{5, 1, 1, symbol24_136_bits},
+{5, 1, 1, symbol24_137_bits},
+{5, 1, 1, symbol24_138_bits},
+{5, 1, 1, symbol24_139_bits},
+{5, 1, 1, symbol24_140_bits},
+{5, 1, 1, symbol24_141_bits},
+{5, 1, 1, symbol24_142_bits},
+{5, 1, 1, symbol24_143_bits},
+{5, 1, 1, symbol24_144_bits},
+{5, 1, 1, symbol24_145_bits},
+{5, 1, 1, symbol24_146_bits},
+{5, 1, 1, symbol24_147_bits},
+{5, 1, 1, symbol24_148_bits},
+{5, 1, 1, symbol24_149_bits},
+{5, 1, 1, symbol24_150_bits},
+{5, 1, 1, symbol24_151_bits},
+{5, 1, 1, symbol24_152_bits},
+{5, 1, 1, symbol24_153_bits},
+{5, 1, 1, symbol24_154_bits},
+{5, 1, 1, symbol24_155_bits},
+{5, 1, 1, symbol24_156_bits},
+{5, 1, 1, symbol24_157_bits},
+{5, 1, 1, symbol24_158_bits},
+{5, 1, 1, symbol24_159_bits},
+{5, 1, 1, symbol24_160_bits},
+{13, 17, 17, symbol24_161_bits},
+{5, 6, 18, symbol24_162_bits},
+{12, 15, 15, symbol24_163_bits},
+{8, 17, 17, symbol24_164_bits},
+{15, 7, 11, symbol24_165_bits},
+{13, 22, 17, symbol24_166_bits},
+{14, 13, 13, symbol24_167_bits},
+{10, 13, 13, symbol24_168_bits},
+{12, 13, 13, symbol24_169_bits},
+{12, 13, 13, symbol24_170_bits},
+{24, 12, 13, symbol24_171_bits},
+{25, 12, 13, symbol24_172_bits},
+{12, 31, 23, symbol24_173_bits},
+{25, 12, 13, symbol24_174_bits},
+{12, 29, 24, symbol24_175_bits},
+{7, 7, 17, symbol24_176_bits},
+{10, 14, 14, symbol24_177_bits},
+{9, 6, 18, symbol24_178_bits},
+{12, 15, 15, symbol24_179_bits},
+{11, 10, 12, symbol24_180_bits},
+{14, 7, 11, symbol24_181_bits},
+{10, 19, 19, symbol24_182_bits},
+{8, 8, 11, symbol24_183_bits},
+{10, 8, 11, symbol24_184_bits},
+{10, 13, 13, symbol24_185_bits},
+{11, 8, 11, symbol24_186_bits},
+{11, 8, 11, symbol24_187_bits},
+{18, 3, 3, symbol24_188_bits},
+{2, 32, 24, symbol24_189_bits},
+{25, 2, 8, symbol24_190_bits},
+{14, 16, 16, symbol24_191_bits},
+{12, 16, 16, symbol24_192_bits},
+{14, 19, 18, symbol24_193_bits},
+{17, 18, 18, symbol24_194_bits},
+{15, 20, 15, symbol24_195_bits},
+{16, 17, 17, symbol24_196_bits},
+{16, 17, 17, symbol24_197_bits},
+{18, 17, 17, symbol24_198_bits},
+{16, 13, 13, symbol24_199_bits},
+{16, 13, 13, symbol24_200_bits},
+{15, 12, 12, symbol24_201_bits},
+{15, 15, 12, symbol24_202_bits},
+{15, 16, 14, symbol24_203_bits},
+{15, 12, 12, symbol24_204_bits},
+{15, 15, 12, symbol24_205_bits},
+{12, 13, 13, symbol24_206_bits},
+{12, 17, 15, symbol24_207_bits},
+{17, 16, 16, symbol24_208_bits},
+{16, 18, 18, symbol24_209_bits},
+{16, 17, 17, symbol24_210_bits},
+{16, 17, 17, symbol24_211_bits},
+{20, 10, 17, symbol24_212_bits},
+{17, 21, 18, symbol24_213_bits},
+{14, 23, 23, symbol24_214_bits},
+{2, 3, 9, symbol24_215_bits},
+{15, 8, 8, symbol24_216_bits},
+{13, 12, 12, symbol24_217_bits},
+{13, 12, 12, symbol24_218_bits},
+{23, 12, 12, symbol24_219_bits},
+{23, 12, 12, symbol24_220_bits},
+{12, 23, 23, symbol24_221_bits},
+{23, 12, 12, symbol24_222_bits},
+{12, 23, 23, symbol24_223_bits},
+{10, 18, 18, symbol24_224_bits},
+{7, 22, 17, symbol24_225_bits},
+{16, 17, 17, symbol24_226_bits},
+{16, 17, 17, symbol24_227_bits},
+{18, 10, 17, symbol24_228_bits},
+{14, 20, 18, symbol24_229_bits},
+{9, 31, 23, symbol24_230_bits},
+{2, 32, 24, symbol24_231_bits},
+{9, 32, 24, symbol24_232_bits},
+{7, 31, 23, symbol24_233_bits},
+{2, 32, 24, symbol24_234_bits},
+{7, 29, 24, symbol24_235_bits},
+{7, 31, 23, symbol24_236_bits},
+{5, 32, 24, symbol24_237_bits},
+{7, 29, 24, symbol24_238_bits},
+{2, 32, 24, symbol24_239_bits},
+{5, 1, 1, symbol24_240_bits},
+{7, 22, 17, symbol24_241_bits},
+{8, 28, 23, symbol24_242_bits},
+{8, 31, 23, symbol24_243_bits},
+{2, 32, 24, symbol24_244_bits},
+{8, 26, 24, symbol24_245_bits},
+{9, 31, 23, symbol24_246_bits},
+{2, 32, 24, symbol24_247_bits},
+{9, 32, 24, symbol24_248_bits},
+{7, 31, 23, symbol24_249_bits},
+{2, 32, 24, symbol24_250_bits},
+{7, 29, 24, symbol24_251_bits},
+{7, 31, 23, symbol24_252_bits},
+{5, 32, 24, symbol24_253_bits},
+{7, 29, 24, symbol24_254_bits},
+{5, 1, 1, symbol24_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/symbol8.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/symbol8.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/symbol8.bdf	(revision 12606)
@@ -0,0 +1,2537 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Symbol-Medium-R-Normal--8-80-75-75-P-51-Adobe-FontSpecific
+SIZE 8 75 75
+FONTBOUNDINGBOX 9 11 -1 -3
+STARTPROPERTIES 31
+FOUNDRY "Adobe"
+FAMILY_NAME "Symbol"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 8
+POINT_SIZE 80
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 51
+CHARSET_REGISTRY "Adobe"
+CHARSET_ENCODING "FontSpecific"
+CAP_HEIGHT 6
+X_HEIGHT 4
+FACE_NAME "Symbol"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "No mark"
+_DEC_DEVICE_FONTNAMES "PS=Symbol"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2-1, 18-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+FULL_NAME "Symbol"
+FONT "-Adobe-Symbol-Medium-R-Normal--8-80-75-75-P-51-Adobe-FontSpecific"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 5
+DEFAULT_CHAR 32
+FONT_ASCENT 8
+FONT_DESCENT 2
+ENDPROPERTIES
+CHARS 188
+STARTCHAR space
+ENCODING 32
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 6 1 0
+BITMAP
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+88
+88
+70
+50
+20
+20
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 5 6 -1 0
+BITMAP
+50
+f8
+50
+50
+f8
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+f0
+10
+10
+70
+10
+f0
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+c8
+d0
+20
+58
+98
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+60
+50
+20
+f8
+a0
+58
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+c0
+60
+20
+c0
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 8 0 -2
+BITMAP
+40
+80
+80
+80
+80
+80
+80
+40
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 8 1 -2
+BITMAP
+80
+40
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 3 1 2
+BITMAP
+40
+e0
+a0
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+BITMAP
+20
+20
+f8
+20
+20
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 3 0 -2
+BITMAP
+40
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 1 0 2
+BITMAP
+f8
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 1 0
+BITMAP
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 6 0 0
+BITMAP
+40
+40
+40
+80
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+40
+a0
+a0
+a0
+a0
+40
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+40
+c0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+40
+a0
+20
+40
+80
+e0
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+40
+a0
+20
+60
+20
+c0
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 6 0 0
+BITMAP
+20
+60
+a0
+f0
+20
+20
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+e0
+80
+c0
+20
+20
+c0
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+60
+80
+c0
+a0
+a0
+40
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+e0
+a0
+20
+40
+40
+40
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+40
+a0
+40
+a0
+a0
+40
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+40
+a0
+a0
+e0
+20
+c0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 4 1 0
+BITMAP
+80
+00
+00
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 6 0 -2
+BITMAP
+40
+00
+00
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+18
+60
+c0
+60
+18
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 3 0 1
+BITMAP
+f0
+00
+f0
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+BITMAP
+c0
+30
+18
+30
+c0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+40
+a0
+20
+40
+00
+40
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+50
+a0
+00
+f0
+00
+f0
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+20
+70
+50
+70
+50
+d8
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+e0
+50
+60
+50
+50
+e0
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+88
+50
+20
+20
+50
+88
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+20
+50
+50
+88
+88
+f8
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+f0
+40
+70
+40
+40
+f0
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+70
+20
+a8
+a8
+20
+70
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+f0
+50
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+d8
+48
+78
+48
+48
+d8
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 6 0 0
+BITMAP
+c0
+40
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+60
+50
+38
+d0
+50
+60
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+d8
+50
+60
+60
+50
+d8
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 6 0 0
+BITMAP
+20
+30
+48
+48
+48
+cc
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 7 6 0 0
+BITMAP
+c6
+44
+6c
+54
+54
+d6
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+d8
+48
+68
+78
+58
+c8
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+70
+d8
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 6 0 0
+BITMAP
+fc
+48
+48
+48
+48
+d8
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+70
+d8
+a8
+a8
+d8
+70
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+e0
+50
+50
+60
+40
+e0
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+f0
+90
+40
+40
+90
+f0
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+f0
+50
+40
+40
+40
+60
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+d8
+48
+50
+20
+20
+70
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 -2
+BITMAP
+60
+80
+80
+40
+20
+40
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 5 6 1 0
+BITMAP
+20
+50
+88
+88
+50
+d8
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+70
+00
+70
+00
+88
+f8
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 7 6 0 0
+BITMAP
+d6
+54
+54
+7c
+10
+38
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+f0
+90
+20
+40
+90
+f0
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 8 0 -2
+BITMAP
+c0
+80
+80
+80
+80
+80
+80
+c0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 4 1 0
+BITMAP
+40
+00
+00
+90
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 8 1 -2
+BITMAP
+c0
+40
+40
+40
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 1 0
+BITMAP
+40
+40
+40
+40
+40
+f0
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 1 0 -2
+BITMAP
+f0
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 5 1 0 7
+BITMAP
+f8
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 4 0 0
+BITMAP
+50
+b0
+a0
+50
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 9 0 -2
+BITMAP
+40
+a0
+a0
+c0
+a0
+a0
+c0
+80
+80
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 -2
+BITMAP
+b0
+a0
+40
+40
+a0
+b0
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+40
+a0
+80
+40
+a0
+a0
+c0
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+60
+e0
+80
+60
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 0 -2
+BITMAP
+40
+40
+60
+d0
+d0
+60
+40
+40
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 -2
+BITMAP
+50
+d0
+60
+20
+40
+40
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 -2
+BITMAP
+60
+d0
+50
+50
+10
+10
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 4 0 0
+BITMAP
+c0
+40
+40
+40
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 -2
+BITMAP
+a0
+d0
+d0
+60
+40
+40
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+50
+f0
+60
+50
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+80
+c0
+40
+20
+60
+90
+98
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 -2
+BITMAP
+a0
+a0
+a0
+d0
+80
+c0
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+90
+90
+e0
+40
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+40
+a0
+a0
+40
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+f0
+50
+50
+d0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+40
+a0
+e0
+a0
+a0
+40
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 -2
+BITMAP
+40
+a0
+a0
+c0
+80
+80
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+70
+a0
+a0
+40
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+e0
+40
+40
+60
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+50
+d0
+50
+60
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+f8
+a8
+a8
+a8
+58
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 4 0 0
+BITMAP
+88
+a8
+a8
+58
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 9 0 -2
+BITMAP
+80
+e0
+40
+60
+80
+80
+40
+20
+60
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 -2
+BITMAP
+a8
+a8
+a8
+70
+20
+20
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 9 0 -2
+BITMAP
+80
+e0
+40
+80
+80
+80
+40
+20
+60
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 9 1 -2
+BITMAP
+20
+40
+40
+40
+80
+40
+40
+40
+20
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 8 0 -2
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 9 1 -2
+BITMAP
+80
+40
+40
+40
+20
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 2 0 1
+BITMAP
+50
+a0
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 3 0 4
+BITMAP
+00
+00
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 4 7 -1 0
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 3 0 1
+BITMAP
+00
+00
+00
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 8 0 -2
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 1 -1
+BITMAP
+00
+90
+a0
+40
+40
+40
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 -1
+BITMAP
+40
+40
+40
+80
+30
+40
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 -1
+BITMAP
+80
+70
+00
+f0
+10
+20
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 1 0
+BITMAP
+20
+40
+40
+40
+80
+50
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 8 5 0 0
+BITMAP
+a8
+50
+30
+40
+e0
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 8 5 0 0
+BITMAP
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 11 0 -3
+BITMAP
+60
+60
+f0
+f0
+40
+40
+20
+70
+f8
+f0
+60
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 8 5 0 0
+BITMAP
+40
+48
+d8
+f8
+f0
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 10 0 -2
+BITMAP
+60
+40
+20
+60
+f0
+f0
+50
+40
+20
+40
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 3 0 3
+BITMAP
+e0
+40
+20
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+20
+40
+f8
+40
+20
+20
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 4 3 0 4
+BITMAP
+70
+a0
+20
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+20
+00
+00
+f0
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 3 0 1
+BITMAP
+00
+00
+20
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+20
+20
+20
+20
+20
+20
+a0
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 3 0 1
+BITMAP
+60
+20
+40
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+a0
+40
+20
+20
+f0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 0 -2
+BITMAP
+20
+20
+f0
+50
+50
+a0
+c0
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+20
+10
+e0
+00
+f0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+90
+60
+60
+90
+50
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 5 1 1 0
+BITMAP
+a0
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 11 2 -3
+BITMAP
+00
+00
+80
+00
+00
+80
+80
+00
+00
+80
+00
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 8 1 0 2
+BITMAP
+60
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+00
+f0
+00
+60
+20
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+20
+f0
+20
+f0
+40
+40
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+f0
+00
+f0
+00
+f0
+50
+a0
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+00
+50
+a0
+a8
+80
+80
+80
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 5 7 1 -2
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+80
+f8
+08
+08
+48
+f8
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+40
+d8
+48
+68
+78
+d8
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 -1
+BITMAP
+c8
+78
+88
+90
+10
+08
+c8
+78
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 4 0 0
+BITMAP
+58
+a0
+a0
+38
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 4 0 0
+BITMAP
+28
+68
+c8
+40
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 4 0 0
+BITMAP
+98
+a8
+c8
+70
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 -2
+BITMAP
+c0
+40
+70
+d8
+a8
+a8
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 -1
+BITMAP
+d8
+70
+70
+a8
+f8
+a8
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 4 0 0
+BITMAP
+a8
+70
+08
+70
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 -2
+BITMAP
+98
+a8
+a8
+c8
+70
+80
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 4 1 0
+BITMAP
+70
+80
+80
+80
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 1 -1
+BITMAP
+80
+80
+80
+70
+f0
+00
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+08
+f0
+f0
+08
+08
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+f0
+00
+f8
+08
+78
+90
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 -1
+BITMAP
+a0
+78
+40
+78
+80
+80
+78
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 -1
+BITMAP
+78
+80
+80
+78
+00
+f8
+70
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 8 4 0 2
+BITMAP
+f0
+80
+70
+20
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 6 8 0 -1
+BITMAP
+70
+f0
+c0
+70
+40
+08
+10
+20
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 8 0 0
+BITMAP
+40
+f8
+f8
+88
+88
+50
+70
+20
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 1 2
+BITMAP
+00
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 3 0 0
+BITMAP
+c8
+b8
+b0
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+a0
+c0
+70
+70
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+80
+b0
+a0
+b0
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 1080 0
+DWIDTH 9 0
+BBX 8 4 0 0
+BITMAP
+88
+70
+fc
+5a
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 7 4 0 0
+BITMAP
+5a
+5a
+fc
+48
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 0 0
+BITMAP
+40
+40
+40
+40
+40
+c0
+00
+00
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 7 4 0 0
+BITMAP
+10
+10
+a0
+a0
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 0 0
+BITMAP
+40
+40
+80
+f0
+00
+00
+20
+50
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+90
+90
+90
+90
+a0
+40
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 8 0 -2
+BITMAP
+00
+40
+c0
+00
+00
+c0
+40
+00
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 -1
+BITMAP
+40
+60
+f0
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 -1
+BITMAP
+60
+08
+f8
+f8
+08
+60
+60
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 6 4 0 2
+BITMAP
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 -1
+BITMAP
+60
+40
+20
+50
+c8
+c8
+50
+20
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 11 1 -3
+BITMAP
+40
+40
+80
+80
+80
+80
+40
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 1 11 1 -3
+BITMAP
+80
+80
+80
+00
+00
+80
+80
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 11 1 -3
+BITMAP
+c0
+40
+40
+40
+c0
+80
+40
+40
+00
+40
+80
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 11 1 -3
+BITMAP
+e0
+40
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 1 11 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 11 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 2 11 1 -3
+BITMAP
+40
+c0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 2 11 0 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 2 11 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 1 11 1 -3
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 8 0 -2
+BITMAP
+80
+40
+40
+40
+40
+80
+40
+40
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 11 1 -3
+BITMAP
+40
+40
+40
+40
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 3 11 1 -3
+BITMAP
+80
+80
+80
+40
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 1 11 -1 -3
+BITMAP
+80
+80
+80
+80
+00
+80
+80
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 3 11 -1 -3
+BITMAP
+80
+80
+20
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 11 0 -3
+BITMAP
+40
+80
+40
+40
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 1 11 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 11 0 -3
+BITMAP
+80
+80
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 11 0 -3
+BITMAP
+c0
+c0
+80
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 1 11 1 -3
+BITMAP
+00
+00
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 11 0 -3
+BITMAP
+80
+80
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 2 11 0 -3
+BITMAP
+40
+80
+c0
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 2 11 1 -3
+BITMAP
+40
+40
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 2 11 0 -3
+BITMAP
+80
+80
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/symbol8.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/symbol8.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/symbol8.h	(revision 12606)
@@ -0,0 +1,769 @@
+static unsigned char symbol8_0_bits[] = {
+0x00};
+static unsigned char symbol8_1_bits[] = {
+0x00};
+static unsigned char symbol8_2_bits[] = {
+0x00};
+static unsigned char symbol8_3_bits[] = {
+0x00};
+static unsigned char symbol8_4_bits[] = {
+0x00};
+static unsigned char symbol8_5_bits[] = {
+0x00};
+static unsigned char symbol8_6_bits[] = {
+0x00};
+static unsigned char symbol8_7_bits[] = {
+0x00};
+static unsigned char symbol8_8_bits[] = {
+0x00};
+static unsigned char symbol8_9_bits[] = {
+0x00};
+static unsigned char symbol8_10_bits[] = {
+0x00};
+static unsigned char symbol8_11_bits[] = {
+0x00};
+static unsigned char symbol8_12_bits[] = {
+0x00};
+static unsigned char symbol8_13_bits[] = {
+0x00};
+static unsigned char symbol8_14_bits[] = {
+0x00};
+static unsigned char symbol8_15_bits[] = {
+0x00};
+static unsigned char symbol8_16_bits[] = {
+0x00};
+static unsigned char symbol8_17_bits[] = {
+0x00};
+static unsigned char symbol8_18_bits[] = {
+0x00};
+static unsigned char symbol8_19_bits[] = {
+0x00};
+static unsigned char symbol8_20_bits[] = {
+0x00};
+static unsigned char symbol8_21_bits[] = {
+0x00};
+static unsigned char symbol8_22_bits[] = {
+0x00};
+static unsigned char symbol8_23_bits[] = {
+0x00};
+static unsigned char symbol8_24_bits[] = {
+0x00};
+static unsigned char symbol8_25_bits[] = {
+0x00};
+static unsigned char symbol8_26_bits[] = {
+0x00};
+static unsigned char symbol8_27_bits[] = {
+0x00};
+static unsigned char symbol8_28_bits[] = {
+0x00};
+static unsigned char symbol8_29_bits[] = {
+0x00};
+static unsigned char symbol8_30_bits[] = {
+0x00};
+static unsigned char symbol8_31_bits[] = {
+0x00};
+static unsigned char symbol8_32_bits[] = {
+0x00};
+static unsigned char symbol8_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x00, 0x01};
+static unsigned char symbol8_34_bits[] = {
+0x11, 0x11, 0x0e, 0x0a, 0x04, 0x04};
+static unsigned char symbol8_35_bits[] = {
+0x0a, 0x1f, 0x0a, 0x0a, 0x1f, 0x0a};
+static unsigned char symbol8_36_bits[] = {
+0x0f, 0x08, 0x08, 0x0e, 0x08, 0x0f};
+static unsigned char symbol8_37_bits[] = {
+0x13, 0x0b, 0x04, 0x1a, 0x19};
+static unsigned char symbol8_38_bits[] = {
+0x06, 0x0a, 0x04, 0x1f, 0x05, 0x1a};
+static unsigned char symbol8_39_bits[] = {
+0x03, 0x06, 0x04, 0x03};
+static unsigned char symbol8_40_bits[] = {
+0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02};
+static unsigned char symbol8_41_bits[] = {
+0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char symbol8_42_bits[] = {
+0x02, 0x07, 0x05};
+static unsigned char symbol8_43_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x04};
+static unsigned char symbol8_44_bits[] = {
+0x02, 0x02, 0x01};
+static unsigned char symbol8_45_bits[] = {
+0x1f};
+static unsigned char symbol8_46_bits[] = {
+0x01};
+static unsigned char symbol8_47_bits[] = {
+0x02, 0x02, 0x02, 0x01, 0x01, 0x01};
+static unsigned char symbol8_48_bits[] = {
+0x02, 0x05, 0x05, 0x05, 0x05, 0x02};
+static unsigned char symbol8_49_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x02, 0x07};
+static unsigned char symbol8_50_bits[] = {
+0x02, 0x05, 0x04, 0x02, 0x01, 0x07};
+static unsigned char symbol8_51_bits[] = {
+0x02, 0x05, 0x04, 0x06, 0x04, 0x03};
+static unsigned char symbol8_52_bits[] = {
+0x04, 0x06, 0x05, 0x0f, 0x04, 0x04};
+static unsigned char symbol8_53_bits[] = {
+0x07, 0x01, 0x03, 0x04, 0x04, 0x03};
+static unsigned char symbol8_54_bits[] = {
+0x06, 0x01, 0x03, 0x05, 0x05, 0x02};
+static unsigned char symbol8_55_bits[] = {
+0x07, 0x05, 0x04, 0x02, 0x02, 0x02};
+static unsigned char symbol8_56_bits[] = {
+0x02, 0x05, 0x02, 0x05, 0x05, 0x02};
+static unsigned char symbol8_57_bits[] = {
+0x02, 0x05, 0x05, 0x07, 0x04, 0x03};
+static unsigned char symbol8_58_bits[] = {
+0x01, 0x00, 0x00, 0x01};
+static unsigned char symbol8_59_bits[] = {
+0x02, 0x00, 0x00, 0x02, 0x02, 0x01};
+static unsigned char symbol8_60_bits[] = {
+0x18, 0x06, 0x03, 0x06, 0x18};
+static unsigned char symbol8_61_bits[] = {
+0x0f, 0x00, 0x0f};
+static unsigned char symbol8_62_bits[] = {
+0x03, 0x0c, 0x18, 0x0c, 0x03};
+static unsigned char symbol8_63_bits[] = {
+0x02, 0x05, 0x04, 0x02, 0x00, 0x02};
+static unsigned char symbol8_64_bits[] = {
+0x0a, 0x05, 0x00, 0x0f, 0x00, 0x0f};
+static unsigned char symbol8_65_bits[] = {
+0x04, 0x0e, 0x0a, 0x0e, 0x0a, 0x1b};
+static unsigned char symbol8_66_bits[] = {
+0x07, 0x0a, 0x06, 0x0a, 0x0a, 0x07};
+static unsigned char symbol8_67_bits[] = {
+0x11, 0x0a, 0x04, 0x04, 0x0a, 0x11};
+static unsigned char symbol8_68_bits[] = {
+0x04, 0x0a, 0x0a, 0x11, 0x11, 0x1f};
+static unsigned char symbol8_69_bits[] = {
+0x0f, 0x02, 0x0e, 0x02, 0x02, 0x0f};
+static unsigned char symbol8_70_bits[] = {
+0x0e, 0x04, 0x15, 0x15, 0x04, 0x0e};
+static unsigned char symbol8_71_bits[] = {
+0x0f, 0x0a, 0x02, 0x02, 0x02, 0x03};
+static unsigned char symbol8_72_bits[] = {
+0x1b, 0x12, 0x1e, 0x12, 0x12, 0x1b};
+static unsigned char symbol8_73_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x02, 0x03};
+static unsigned char symbol8_74_bits[] = {
+0x06, 0x0a, 0x1c, 0x0b, 0x0a, 0x06};
+static unsigned char symbol8_75_bits[] = {
+0x1b, 0x0a, 0x06, 0x06, 0x0a, 0x1b};
+static unsigned char symbol8_76_bits[] = {
+0x04, 0x0c, 0x12, 0x12, 0x12, 0x33};
+static unsigned char symbol8_77_bits[] = {
+0x63, 0x22, 0x36, 0x2a, 0x2a, 0x6b};
+static unsigned char symbol8_78_bits[] = {
+0x1b, 0x12, 0x16, 0x1e, 0x1a, 0x13};
+static unsigned char symbol8_79_bits[] = {
+0x0e, 0x1b, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char symbol8_80_bits[] = {
+0x3f, 0x12, 0x12, 0x12, 0x12, 0x1b};
+static unsigned char symbol8_81_bits[] = {
+0x0e, 0x1b, 0x15, 0x15, 0x1b, 0x0e};
+static unsigned char symbol8_82_bits[] = {
+0x07, 0x0a, 0x0a, 0x06, 0x02, 0x07};
+static unsigned char symbol8_83_bits[] = {
+0x0f, 0x09, 0x02, 0x02, 0x09, 0x0f};
+static unsigned char symbol8_84_bits[] = {
+0x0f, 0x0a, 0x02, 0x02, 0x02, 0x06};
+static unsigned char symbol8_85_bits[] = {
+0x1b, 0x12, 0x0a, 0x04, 0x04, 0x0e};
+static unsigned char symbol8_86_bits[] = {
+0x06, 0x01, 0x01, 0x02, 0x04, 0x02};
+static unsigned char symbol8_87_bits[] = {
+0x04, 0x0a, 0x11, 0x11, 0x0a, 0x1b};
+static unsigned char symbol8_88_bits[] = {
+0x0e, 0x00, 0x0e, 0x00, 0x11, 0x1f};
+static unsigned char symbol8_89_bits[] = {
+0x6b, 0x2a, 0x2a, 0x3e, 0x08, 0x1c};
+static unsigned char symbol8_90_bits[] = {
+0x0f, 0x09, 0x04, 0x02, 0x09, 0x0f};
+static unsigned char symbol8_91_bits[] = {
+0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03};
+static unsigned char symbol8_92_bits[] = {
+0x02, 0x00, 0x00, 0x09};
+static unsigned char symbol8_93_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03};
+static unsigned char symbol8_94_bits[] = {
+0x02, 0x02, 0x02, 0x02, 0x02, 0x0f};
+static unsigned char symbol8_95_bits[] = {
+0x0f};
+static unsigned char symbol8_96_bits[] = {
+0x1f};
+static unsigned char symbol8_97_bits[] = {
+0x0a, 0x0d, 0x05, 0x0a};
+static unsigned char symbol8_98_bits[] = {
+0x02, 0x05, 0x05, 0x03, 0x05, 0x05, 0x03, 0x01, 0x01};
+static unsigned char symbol8_99_bits[] = {
+0x0d, 0x05, 0x02, 0x02, 0x05, 0x0d};
+static unsigned char symbol8_100_bits[] = {
+0x02, 0x05, 0x01, 0x02, 0x05, 0x05, 0x03};
+static unsigned char symbol8_101_bits[] = {
+0x06, 0x07, 0x01, 0x06};
+static unsigned char symbol8_102_bits[] = {
+0x02, 0x02, 0x06, 0x0b, 0x0b, 0x06, 0x02, 0x02};
+static unsigned char symbol8_103_bits[] = {
+0x0a, 0x0b, 0x06, 0x04, 0x02, 0x02};
+static unsigned char symbol8_104_bits[] = {
+0x06, 0x0b, 0x0a, 0x0a, 0x08, 0x08};
+static unsigned char symbol8_105_bits[] = {
+0x03, 0x02, 0x02, 0x02};
+static unsigned char symbol8_106_bits[] = {
+0x05, 0x0b, 0x0b, 0x06, 0x02, 0x02};
+static unsigned char symbol8_107_bits[] = {
+0x0a, 0x0f, 0x06, 0x0a};
+static unsigned char symbol8_108_bits[] = {
+0x01, 0x03, 0x02, 0x04, 0x06, 0x09, 0x19};
+static unsigned char symbol8_109_bits[] = {
+0x05, 0x05, 0x05, 0x0b, 0x01, 0x03};
+static unsigned char symbol8_110_bits[] = {
+0x09, 0x09, 0x07, 0x02};
+static unsigned char symbol8_111_bits[] = {
+0x02, 0x05, 0x05, 0x02};
+static unsigned char symbol8_112_bits[] = {
+0x0f, 0x0a, 0x0a, 0x0b};
+static unsigned char symbol8_113_bits[] = {
+0x02, 0x05, 0x07, 0x05, 0x05, 0x02};
+static unsigned char symbol8_114_bits[] = {
+0x02, 0x05, 0x05, 0x03, 0x01, 0x01};
+static unsigned char symbol8_115_bits[] = {
+0x0e, 0x05, 0x05, 0x02};
+static unsigned char symbol8_116_bits[] = {
+0x07, 0x02, 0x02, 0x06};
+static unsigned char symbol8_117_bits[] = {
+0x0a, 0x0b, 0x0a, 0x06};
+static unsigned char symbol8_118_bits[] = {
+0x1f, 0x15, 0x15, 0x15, 0x1a};
+static unsigned char symbol8_119_bits[] = {
+0x11, 0x15, 0x15, 0x1a};
+static unsigned char symbol8_120_bits[] = {
+0x01, 0x07, 0x02, 0x06, 0x01, 0x01, 0x02, 0x04, 0x06};
+static unsigned char symbol8_121_bits[] = {
+0x15, 0x15, 0x15, 0x0e, 0x04, 0x04};
+static unsigned char symbol8_122_bits[] = {
+0x01, 0x07, 0x02, 0x01, 0x01, 0x01, 0x02, 0x04, 0x06};
+static unsigned char symbol8_123_bits[] = {
+0x04, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x04};
+static unsigned char symbol8_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_125_bits[] = {
+0x01, 0x02, 0x02, 0x02, 0x04, 0x02, 0x02, 0x02, 0x01};
+static unsigned char symbol8_126_bits[] = {
+0x0a, 0x05};
+static unsigned char symbol8_127_bits[] = {
+0x00};
+static unsigned char symbol8_128_bits[] = {
+0x00};
+static unsigned char symbol8_129_bits[] = {
+0x00};
+static unsigned char symbol8_130_bits[] = {
+0x00};
+static unsigned char symbol8_131_bits[] = {
+0x00};
+static unsigned char symbol8_132_bits[] = {
+0x00};
+static unsigned char symbol8_133_bits[] = {
+0x00};
+static unsigned char symbol8_134_bits[] = {
+0x00};
+static unsigned char symbol8_135_bits[] = {
+0x00};
+static unsigned char symbol8_136_bits[] = {
+0x00};
+static unsigned char symbol8_137_bits[] = {
+0x00};
+static unsigned char symbol8_138_bits[] = {
+0x00};
+static unsigned char symbol8_139_bits[] = {
+0x00};
+static unsigned char symbol8_140_bits[] = {
+0x00};
+static unsigned char symbol8_141_bits[] = {
+0x00};
+static unsigned char symbol8_142_bits[] = {
+0x00};
+static unsigned char symbol8_143_bits[] = {
+0x00};
+static unsigned char symbol8_144_bits[] = {
+0x00};
+static unsigned char symbol8_145_bits[] = {
+0x00};
+static unsigned char symbol8_146_bits[] = {
+0x00};
+static unsigned char symbol8_147_bits[] = {
+0x00};
+static unsigned char symbol8_148_bits[] = {
+0x00};
+static unsigned char symbol8_149_bits[] = {
+0x00};
+static unsigned char symbol8_150_bits[] = {
+0x00};
+static unsigned char symbol8_151_bits[] = {
+0x00};
+static unsigned char symbol8_152_bits[] = {
+0x00};
+static unsigned char symbol8_153_bits[] = {
+0x00};
+static unsigned char symbol8_154_bits[] = {
+0x00};
+static unsigned char symbol8_155_bits[] = {
+0x00};
+static unsigned char symbol8_156_bits[] = {
+0x00};
+static unsigned char symbol8_157_bits[] = {
+0x00};
+static unsigned char symbol8_158_bits[] = {
+0x00};
+static unsigned char symbol8_159_bits[] = {
+0x00};
+static unsigned char symbol8_160_bits[] = {
+0x00};
+static unsigned char symbol8_161_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol8_162_bits[] = {
+0x00, 0x00, 0x00};
+static unsigned char symbol8_163_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol8_164_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol8_165_bits[] = {
+0x00, 0x00, 0x00};
+static unsigned char symbol8_166_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol8_167_bits[] = {
+0x00, 0x09, 0x05, 0x02, 0x02, 0x02};
+static unsigned char symbol8_168_bits[] = {
+0x02, 0x02, 0x02, 0x01, 0x0c, 0x02};
+static unsigned char symbol8_169_bits[] = {
+0x01, 0x0e, 0x00, 0x0f, 0x08, 0x04};
+static unsigned char symbol8_170_bits[] = {
+0x04, 0x02, 0x02, 0x02, 0x01, 0x0a};
+static unsigned char symbol8_171_bits[] = {
+0x15, 0x0a, 0x0c, 0x02, 0x07};
+static unsigned char symbol8_172_bits[] = {
+0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char symbol8_173_bits[] = {
+0x06, 0x06, 0x0f, 0x0f, 0x02, 0x02, 0x04, 0x0e, 0x1f, 0x0f, 0x06};
+static unsigned char symbol8_174_bits[] = {
+0x02, 0x12, 0x1b, 0x1f, 0x0f};
+static unsigned char symbol8_175_bits[] = {
+0x06, 0x02, 0x04, 0x06, 0x0f, 0x0f, 0x0a, 0x02, 0x04, 0x02};
+static unsigned char symbol8_176_bits[] = {
+0x07, 0x02, 0x04};
+static unsigned char symbol8_177_bits[] = {
+0x04, 0x02, 0x1f, 0x02, 0x04, 0x04};
+static unsigned char symbol8_178_bits[] = {
+0x0e, 0x05, 0x04};
+static unsigned char symbol8_179_bits[] = {
+0x04, 0x04, 0x04, 0x04, 0x04, 0x04};
+static unsigned char symbol8_180_bits[] = {
+0x04, 0x00, 0x00, 0x0f};
+static unsigned char symbol8_181_bits[] = {
+0x00, 0x00, 0x04};
+static unsigned char symbol8_182_bits[] = {
+0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05};
+static unsigned char symbol8_183_bits[] = {
+0x06, 0x04, 0x02};
+static unsigned char symbol8_184_bits[] = {
+0x05, 0x02, 0x04, 0x04, 0x0f};
+static unsigned char symbol8_185_bits[] = {
+0x04, 0x04, 0x0f, 0x0a, 0x0a, 0x05, 0x03};
+static unsigned char symbol8_186_bits[] = {
+0x04, 0x08, 0x07, 0x00, 0x0f};
+static unsigned char symbol8_187_bits[] = {
+0x09, 0x06, 0x06, 0x09, 0x0a};
+static unsigned char symbol8_188_bits[] = {
+0x05};
+static unsigned char symbol8_189_bits[] = {
+0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00};
+static unsigned char symbol8_190_bits[] = {
+0x06};
+static unsigned char symbol8_191_bits[] = {
+0x00, 0x0f, 0x00, 0x06, 0x04};
+static unsigned char symbol8_192_bits[] = {
+0x04, 0x0f, 0x04, 0x0f, 0x02, 0x02};
+static unsigned char symbol8_193_bits[] = {
+0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x0a, 0x05};
+static unsigned char symbol8_194_bits[] = {
+0x00, 0x0a, 0x05, 0x15, 0x01, 0x01, 0x01};
+static unsigned char symbol8_195_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_196_bits[] = {
+0x01, 0x1f, 0x10, 0x10, 0x12, 0x1f};
+static unsigned char symbol8_197_bits[] = {
+0x02, 0x1b, 0x12, 0x16, 0x1e, 0x1b};
+static unsigned char symbol8_198_bits[] = {
+0x13, 0x1e, 0x11, 0x09, 0x08, 0x10, 0x13, 0x1e};
+static unsigned char symbol8_199_bits[] = {
+0x1a, 0x05, 0x05, 0x1c};
+static unsigned char symbol8_200_bits[] = {
+0x14, 0x16, 0x13, 0x02};
+static unsigned char symbol8_201_bits[] = {
+0x19, 0x15, 0x13, 0x0e};
+static unsigned char symbol8_202_bits[] = {
+0x03, 0x02, 0x0e, 0x1b, 0x15, 0x15};
+static unsigned char symbol8_203_bits[] = {
+0x1b, 0x0e, 0x0e, 0x15, 0x1f, 0x15};
+static unsigned char symbol8_204_bits[] = {
+0x15, 0x0e, 0x10, 0x0e};
+static unsigned char symbol8_205_bits[] = {
+0x19, 0x15, 0x15, 0x13, 0x0e, 0x01};
+static unsigned char symbol8_206_bits[] = {
+0x0e, 0x01, 0x01, 0x01};
+static unsigned char symbol8_207_bits[] = {
+0x01, 0x01, 0x01, 0x0e, 0x0f, 0x00};
+static unsigned char symbol8_208_bits[] = {
+0x10, 0x0f, 0x0f, 0x10, 0x10};
+static unsigned char symbol8_209_bits[] = {
+0x0f, 0x00, 0x1f, 0x10, 0x1e, 0x09};
+static unsigned char symbol8_210_bits[] = {
+0x05, 0x1e, 0x02, 0x1e, 0x01, 0x01, 0x1e};
+static unsigned char symbol8_211_bits[] = {
+0x1e, 0x01, 0x01, 0x1e, 0x00, 0x1f, 0x0e};
+static unsigned char symbol8_212_bits[] = {
+0x0f, 0x01, 0x0e, 0x04};
+static unsigned char symbol8_213_bits[] = {
+0x0e, 0x0f, 0x03, 0x0e, 0x02, 0x10, 0x08, 0x04};
+static unsigned char symbol8_214_bits[] = {
+0x02, 0x1f, 0x1f, 0x11, 0x11, 0x0a, 0x0e, 0x04};
+static unsigned char symbol8_215_bits[] = {
+0x00};
+static unsigned char symbol8_216_bits[] = {
+0x13, 0x1d, 0x0d};
+static unsigned char symbol8_217_bits[] = {
+0x05, 0x03, 0x0e, 0x0e};
+static unsigned char symbol8_218_bits[] = {
+0x01, 0x0d, 0x05, 0x0d};
+static unsigned char symbol8_219_bits[] = {
+0x11, 0x0e, 0x3f, 0x5a};
+static unsigned char symbol8_220_bits[] = {
+0x5a, 0x5a, 0x3f, 0x12};
+static unsigned char symbol8_221_bits[] = {
+0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x00, 0x00};
+static unsigned char symbol8_222_bits[] = {
+0x08, 0x08, 0x05, 0x05};
+static unsigned char symbol8_223_bits[] = {
+0x02, 0x02, 0x01, 0x0f, 0x00, 0x00, 0x04, 0x0a};
+static unsigned char symbol8_224_bits[] = {
+0x09, 0x09, 0x09, 0x09, 0x05, 0x02};
+static unsigned char symbol8_225_bits[] = {
+0x00, 0x02, 0x03, 0x00, 0x00, 0x03, 0x02, 0x00};
+static unsigned char symbol8_226_bits[] = {
+0x02, 0x06, 0x0f, 0x06, 0x06, 0x06, 0x06};
+static unsigned char symbol8_227_bits[] = {
+0x06, 0x10, 0x1f, 0x1f, 0x10, 0x06, 0x06};
+static unsigned char symbol8_228_bits[] = {
+0x06, 0x06, 0x06, 0x0f};
+static unsigned char symbol8_229_bits[] = {
+0x06, 0x02, 0x04, 0x0a, 0x13, 0x13, 0x0a, 0x04};
+static unsigned char symbol8_230_bits[] = {
+0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01};
+static unsigned char symbol8_231_bits[] = {
+0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00};
+static unsigned char symbol8_232_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x00, 0x02, 0x01};
+static unsigned char symbol8_233_bits[] = {
+0x07, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_234_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_235_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_236_bits[] = {
+0x02, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_237_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_238_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_239_bits[] = {
+0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_240_bits[] = {
+0x00};
+static unsigned char symbol8_241_bits[] = {
+0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02};
+static unsigned char symbol8_242_bits[] = {
+0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_243_bits[] = {
+0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_244_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol8_245_bits[] = {
+0x01, 0x01, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char symbol8_246_bits[] = {
+0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_247_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_248_bits[] = {
+0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol8_249_bits[] = {
+0x03, 0x03, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char symbol8_250_bits[] = {
+0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_251_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char symbol8_252_bits[] = {
+0x02, 0x01, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char symbol8_253_bits[] = {
+0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_254_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char symbol8_255_bits[] = {
+0x00};
+static RotFont symbol8font[] = {
+{5, 1, 1, symbol8_0_bits},
+{5, 1, 1, symbol8_1_bits},
+{5, 1, 1, symbol8_2_bits},
+{5, 1, 1, symbol8_3_bits},
+{5, 1, 1, symbol8_4_bits},
+{5, 1, 1, symbol8_5_bits},
+{5, 1, 1, symbol8_6_bits},
+{5, 1, 1, symbol8_7_bits},
+{5, 1, 1, symbol8_8_bits},
+{5, 1, 1, symbol8_9_bits},
+{5, 1, 1, symbol8_10_bits},
+{5, 1, 1, symbol8_11_bits},
+{5, 1, 1, symbol8_12_bits},
+{5, 1, 1, symbol8_13_bits},
+{5, 1, 1, symbol8_14_bits},
+{5, 1, 1, symbol8_15_bits},
+{5, 1, 1, symbol8_16_bits},
+{5, 1, 1, symbol8_17_bits},
+{5, 1, 1, symbol8_18_bits},
+{5, 1, 1, symbol8_19_bits},
+{5, 1, 1, symbol8_20_bits},
+{5, 1, 1, symbol8_21_bits},
+{5, 1, 1, symbol8_22_bits},
+{5, 1, 1, symbol8_23_bits},
+{5, 1, 1, symbol8_24_bits},
+{5, 1, 1, symbol8_25_bits},
+{5, 1, 1, symbol8_26_bits},
+{5, 1, 1, symbol8_27_bits},
+{5, 1, 1, symbol8_28_bits},
+{5, 1, 1, symbol8_29_bits},
+{5, 1, 1, symbol8_30_bits},
+{5, 1, 1, symbol8_31_bits},
+{1, 1, 1, symbol8_32_bits},
+{1, 6, 6, symbol8_33_bits},
+{5, 6, 6, symbol8_34_bits},
+{5, 6, 6, symbol8_35_bits},
+{4, 6, 6, symbol8_36_bits},
+{5, 5, 5, symbol8_37_bits},
+{5, 6, 6, symbol8_38_bits},
+{3, 4, 4, symbol8_39_bits},
+{2, 8, 6, symbol8_40_bits},
+{2, 8, 6, symbol8_41_bits},
+{3, 3, 5, symbol8_42_bits},
+{5, 5, 5, symbol8_43_bits},
+{2, 3, 1, symbol8_44_bits},
+{5, 1, 3, symbol8_45_bits},
+{1, 1, 1, symbol8_46_bits},
+{2, 6, 6, symbol8_47_bits},
+{3, 6, 6, symbol8_48_bits},
+{3, 6, 6, symbol8_49_bits},
+{3, 6, 6, symbol8_50_bits},
+{3, 6, 6, symbol8_51_bits},
+{4, 6, 6, symbol8_52_bits},
+{3, 6, 6, symbol8_53_bits},
+{3, 6, 6, symbol8_54_bits},
+{3, 6, 6, symbol8_55_bits},
+{3, 6, 6, symbol8_56_bits},
+{3, 6, 6, symbol8_57_bits},
+{1, 4, 4, symbol8_58_bits},
+{2, 6, 4, symbol8_59_bits},
+{5, 5, 5, symbol8_60_bits},
+{4, 3, 4, symbol8_61_bits},
+{5, 5, 5, symbol8_62_bits},
+{3, 6, 6, symbol8_63_bits},
+{4, 6, 6, symbol8_64_bits},
+{5, 6, 6, symbol8_65_bits},
+{4, 6, 6, symbol8_66_bits},
+{5, 6, 6, symbol8_67_bits},
+{5, 6, 6, symbol8_68_bits},
+{4, 6, 6, symbol8_69_bits},
+{5, 6, 6, symbol8_70_bits},
+{4, 6, 6, symbol8_71_bits},
+{5, 6, 6, symbol8_72_bits},
+{2, 6, 6, symbol8_73_bits},
+{5, 6, 6, symbol8_74_bits},
+{5, 6, 6, symbol8_75_bits},
+{6, 6, 6, symbol8_76_bits},
+{7, 6, 6, symbol8_77_bits},
+{5, 6, 6, symbol8_78_bits},
+{5, 6, 6, symbol8_79_bits},
+{6, 6, 6, symbol8_80_bits},
+{5, 6, 6, symbol8_81_bits},
+{4, 6, 6, symbol8_82_bits},
+{4, 6, 6, symbol8_83_bits},
+{4, 6, 6, symbol8_84_bits},
+{5, 6, 6, symbol8_85_bits},
+{3, 6, 4, symbol8_86_bits},
+{5, 6, 6, symbol8_87_bits},
+{5, 6, 6, symbol8_88_bits},
+{7, 6, 6, symbol8_89_bits},
+{4, 6, 6, symbol8_90_bits},
+{2, 8, 6, symbol8_91_bits},
+{4, 4, 4, symbol8_92_bits},
+{2, 8, 6, symbol8_93_bits},
+{4, 6, 6, symbol8_94_bits},
+{4, 1, -1, symbol8_95_bits},
+{5, 1, 8, symbol8_96_bits},
+{4, 4, 4, symbol8_97_bits},
+{3, 9, 7, symbol8_98_bits},
+{4, 6, 4, symbol8_99_bits},
+{3, 7, 7, symbol8_100_bits},
+{3, 4, 4, symbol8_101_bits},
+{4, 8, 6, symbol8_102_bits},
+{4, 6, 4, symbol8_103_bits},
+{4, 6, 4, symbol8_104_bits},
+{2, 4, 4, symbol8_105_bits},
+{4, 6, 4, symbol8_106_bits},
+{4, 4, 4, symbol8_107_bits},
+{5, 7, 7, symbol8_108_bits},
+{4, 6, 4, symbol8_109_bits},
+{4, 4, 4, symbol8_110_bits},
+{3, 4, 4, symbol8_111_bits},
+{4, 4, 4, symbol8_112_bits},
+{3, 6, 6, symbol8_113_bits},
+{3, 6, 4, symbol8_114_bits},
+{4, 4, 4, symbol8_115_bits},
+{3, 4, 4, symbol8_116_bits},
+{4, 4, 4, symbol8_117_bits},
+{5, 5, 5, symbol8_118_bits},
+{5, 4, 4, symbol8_119_bits},
+{3, 9, 7, symbol8_120_bits},
+{5, 6, 4, symbol8_121_bits},
+{3, 9, 7, symbol8_122_bits},
+{3, 9, 7, symbol8_123_bits},
+{1, 8, 6, symbol8_124_bits},
+{3, 9, 7, symbol8_125_bits},
+{4, 2, 3, symbol8_126_bits},
+{5, 1, 1, symbol8_127_bits},
+{5, 1, 1, symbol8_128_bits},
+{5, 1, 1, symbol8_129_bits},
+{5, 1, 1, symbol8_130_bits},
+{5, 1, 1, symbol8_131_bits},
+{5, 1, 1, symbol8_132_bits},
+{5, 1, 1, symbol8_133_bits},
+{5, 1, 1, symbol8_134_bits},
+{5, 1, 1, symbol8_135_bits},
+{5, 1, 1, symbol8_136_bits},
+{5, 1, 1, symbol8_137_bits},
+{5, 1, 1, symbol8_138_bits},
+{5, 1, 1, symbol8_139_bits},
+{5, 1, 1, symbol8_140_bits},
+{5, 1, 1, symbol8_141_bits},
+{5, 1, 1, symbol8_142_bits},
+{5, 1, 1, symbol8_143_bits},
+{5, 1, 1, symbol8_144_bits},
+{5, 1, 1, symbol8_145_bits},
+{5, 1, 1, symbol8_146_bits},
+{5, 1, 1, symbol8_147_bits},
+{5, 1, 1, symbol8_148_bits},
+{5, 1, 1, symbol8_149_bits},
+{5, 1, 1, symbol8_150_bits},
+{5, 1, 1, symbol8_151_bits},
+{5, 1, 1, symbol8_152_bits},
+{5, 1, 1, symbol8_153_bits},
+{5, 1, 1, symbol8_154_bits},
+{5, 1, 1, symbol8_155_bits},
+{5, 1, 1, symbol8_156_bits},
+{5, 1, 1, symbol8_157_bits},
+{5, 1, 1, symbol8_158_bits},
+{5, 1, 1, symbol8_159_bits},
+{5, 1, 1, symbol8_160_bits},
+{5, 6, 6, symbol8_161_bits},
+{2, 3, 7, symbol8_162_bits},
+{4, 6, 6, symbol8_163_bits},
+{4, 7, 7, symbol8_164_bits},
+{5, 3, 4, symbol8_165_bits},
+{4, 8, 6, symbol8_166_bits},
+{4, 6, 5, symbol8_167_bits},
+{5, 6, 5, symbol8_168_bits},
+{5, 6, 5, symbol8_169_bits},
+{4, 6, 6, symbol8_170_bits},
+{8, 5, 5, symbol8_171_bits},
+{8, 5, 5, symbol8_172_bits},
+{5, 11, 8, symbol8_173_bits},
+{8, 5, 5, symbol8_174_bits},
+{5, 10, 8, symbol8_175_bits},
+{3, 3, 6, symbol8_176_bits},
+{5, 6, 6, symbol8_177_bits},
+{4, 3, 7, symbol8_178_bits},
+{4, 6, 6, symbol8_179_bits},
+{4, 4, 4, symbol8_180_bits},
+{5, 3, 4, symbol8_181_bits},
+{3, 7, 7, symbol8_182_bits},
+{3, 3, 4, symbol8_183_bits},
+{4, 5, 5, symbol8_184_bits},
+{4, 7, 5, symbol8_185_bits},
+{4, 5, 5, symbol8_186_bits},
+{4, 5, 5, symbol8_187_bits},
+{5, 1, 1, symbol8_188_bits},
+{1, 11, 8, symbol8_189_bits},
+{8, 1, 3, symbol8_190_bits},
+{5, 5, 5, symbol8_191_bits},
+{5, 6, 6, symbol8_192_bits},
+{5, 7, 7, symbol8_193_bits},
+{6, 7, 7, symbol8_194_bits},
+{5, 7, 5, symbol8_195_bits},
+{5, 6, 6, symbol8_196_bits},
+{5, 6, 6, symbol8_197_bits},
+{5, 8, 7, symbol8_198_bits},
+{5, 4, 4, symbol8_199_bits},
+{5, 4, 4, symbol8_200_bits},
+{5, 4, 4, symbol8_201_bits},
+{5, 6, 4, symbol8_202_bits},
+{5, 6, 5, symbol8_203_bits},
+{5, 4, 4, symbol8_204_bits},
+{5, 6, 4, symbol8_205_bits},
+{4, 4, 4, symbol8_206_bits},
+{4, 6, 5, symbol8_207_bits},
+{5, 5, 5, symbol8_208_bits},
+{5, 6, 6, symbol8_209_bits},
+{5, 7, 6, symbol8_210_bits},
+{5, 7, 6, symbol8_211_bits},
+{8, 4, 6, symbol8_212_bits},
+{6, 8, 7, symbol8_213_bits},
+{5, 8, 8, symbol8_214_bits},
+{1, 1, 3, symbol8_215_bits},
+{5, 3, 3, symbol8_216_bits},
+{4, 4, 4, symbol8_217_bits},
+{4, 4, 4, symbol8_218_bits},
+{8, 4, 4, symbol8_219_bits},
+{7, 4, 4, symbol8_220_bits},
+{4, 8, 8, symbol8_221_bits},
+{7, 4, 4, symbol8_222_bits},
+{4, 8, 8, symbol8_223_bits},
+{5, 6, 6, symbol8_224_bits},
+{2, 8, 6, symbol8_225_bits},
+{5, 7, 6, symbol8_226_bits},
+{5, 7, 6, symbol8_227_bits},
+{6, 4, 6, symbol8_228_bits},
+{5, 8, 7, symbol8_229_bits},
+{2, 11, 8, symbol8_230_bits},
+{1, 11, 8, symbol8_231_bits},
+{2, 11, 8, symbol8_232_bits},
+{3, 11, 8, symbol8_233_bits},
+{1, 11, 8, symbol8_234_bits},
+{2, 11, 8, symbol8_235_bits},
+{2, 11, 8, symbol8_236_bits},
+{2, 11, 8, symbol8_237_bits},
+{2, 11, 8, symbol8_238_bits},
+{1, 11, 8, symbol8_239_bits},
+{5, 1, 1, symbol8_240_bits},
+{2, 8, 6, symbol8_241_bits},
+{3, 11, 8, symbol8_242_bits},
+{3, 11, 8, symbol8_243_bits},
+{1, 11, 8, symbol8_244_bits},
+{3, 11, 8, symbol8_245_bits},
+{2, 11, 8, symbol8_246_bits},
+{1, 11, 8, symbol8_247_bits},
+{2, 11, 8, symbol8_248_bits},
+{2, 11, 8, symbol8_249_bits},
+{1, 11, 8, symbol8_250_bits},
+{2, 11, 8, symbol8_251_bits},
+{2, 11, 8, symbol8_252_bits},
+{2, 11, 8, symbol8_253_bits},
+{2, 11, 8, symbol8_254_bits},
+{5, 1, 1, symbol8_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/test.fn
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/test.fn	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/test.fn	(revision 12606)
@@ -0,0 +1,896 @@
+# define C000_width 0
+# define C000_height 0
+static unsigned char C000_bits[] = {
+};
+# define C001_width 5
+# define C001_height 7
+static unsigned char C001_bits[] = {
+ 0x00, 0x00, 0x00, 0x1f, 0x0e, 0x0e, 0x04};
+# define C002_width 5
+# define C002_height 7
+static unsigned char C002_bits[] = {
+ 0x00, 0x00, 0x00, 0x0a, 0x15, 0x0a, 0x15};
+# define C003_width 5
+# define C003_height 9
+static unsigned char C003_bits[] = {
+ 0x00, 0x00, 0x00, 0x09, 0x09, 0x1e, 0x08, 0x08, 0x08};
+# define C004_width 5
+# define C004_height 9
+static unsigned char C004_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x1d, 0x04, 0x0c, 0x04, 0x04};
+# define C005_width 5
+# define C005_height 9
+static unsigned char C005_bits[] = {
+ 0x00, 0x00, 0x00, 0x0e, 0x0e, 0x12, 0x0e, 0x12, 0x12};
+# define C006_width 5
+# define C006_height 9
+static unsigned char C006_bits[] = {
+ 0x00, 0x00, 0x00, 0x0f, 0x1e, 0x02, 0x0e, 0x02, 0x02};
+# define C007_width 3
+# define C007_height 3
+static unsigned char C007_bits[] = {
+ 0x00, 0x00, 0x02};
+# define C010_width 5
+# define C010_height 6
+static unsigned char C010_bits[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x04, 0x1f};
+# define C011_width 5
+# define C011_height 9
+static unsigned char C011_bits[] = {
+ 0x00, 0x00, 0x00, 0x0d, 0x09, 0x02, 0x02, 0x02, 0x1e};
+# define C012_width 5
+# define C012_height 9
+static unsigned char C012_bits[] = {
+ 0x00, 0x00, 0x00, 0x02, 0x1e, 0x08, 0x08, 0x08, 0x08};
+# define C013_width 4
+# define C013_height 5
+static unsigned char C013_bits[] = {
+ 0x00, 0x00, 0x00, 0x08, 0x0f};
+# define C014_width 4
+# define C014_height 6
+static unsigned char C014_bits[] = {
+ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08};
+# define C015_width 3
+# define C015_height 6
+static unsigned char C015_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01};
+# define C016_width 3
+# define C016_height 5
+static unsigned char C016_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x07};
+# define C017_width 6
+# define C017_height 10
+static unsigned char C017_bits[] = {
+ 0x00, 0x00, 0x00, 0x08, 0x3f, 0x08, 0x08, 0x08, 0x08, 0x08};
+# define C020_width 6
+# define C020_height 1
+static unsigned char C020_bits[] = {
+ 0x3f};
+# define C021_width 6
+# define C021_height 1
+static unsigned char C021_bits[] = {
+ 0x3f};
+# define C022_width 6
+# define C022_height 1
+static unsigned char C022_bits[] = {
+ 0x3f};
+# define C023_width 6
+# define C023_height 1
+static unsigned char C023_bits[] = {
+ 0x3f};
+# define C024_width 6
+# define C024_height 1
+static unsigned char C024_bits[] = {
+ 0x3f};
+# define C025_width 3
+# define C025_height 10
+static unsigned char C025_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x07, 0x01, 0x01, 0x01, 0x01, 0x01};
+# define C026_width 4
+# define C026_height 10
+static unsigned char C026_bits[] = {
+ 0x00, 0x00, 0x00, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08};
+# define C027_width 6
+# define C027_height 5
+static unsigned char C027_bits[] = {
+ 0x00, 0x00, 0x00, 0x08, 0x3f};
+# define C030_width 6
+# define C030_height 6
+static unsigned char C030_bits[] = {
+ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08};
+# define C031_width 1
+# define C031_height 10
+static unsigned char C031_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+# define C032_width 5
+# define C032_height 8
+static unsigned char C032_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x02, 0x08, 0x10, 0x1f};
+# define C033_width 5
+# define C033_height 8
+static unsigned char C033_bits[] = {
+ 0x00, 0x00, 0x00, 0x10, 0x08, 0x02, 0x01, 0x1f};
+# define C034_width 5
+# define C034_height 5
+static unsigned char C034_bits[] = {
+ 0x00, 0x00, 0x00, 0x0a, 0x0a};
+# define C035_width 5
+# define C035_height 7
+static unsigned char C035_bits[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x1f, 0x02, 0x01};
+# define C036_width 5
+# define C036_height 7
+static unsigned char C036_bits[] = {
+ 0x00, 0x00, 0x00, 0x07, 0x02, 0x12, 0x0d};
+# define C037_width 1
+# define C037_height 1
+static unsigned char C037_bits[] = {
+ 0x01};
+# define space_width 0
+# define space_height 0
+static unsigned char space_bits[] = {
+};
+# define exclam_width 1
+# define exclam_height 7
+static unsigned char exclam_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01};
+# define quotedbl_width 3
+# define quotedbl_height 3
+static unsigned char quotedbl_bits[] = {
+ 0x00, 0x00, 0x05};
+# define numbersign_width 5
+# define numbersign_height 7
+static unsigned char numbersign_bits[] = {
+ 0x00, 0x00, 0x00, 0x0a, 0x1f, 0x0a, 0x0a};
+# define dollar_width 5
+# define dollar_height 7
+static unsigned char dollar_bits[] = {
+ 0x00, 0x00, 0x00, 0x0e, 0x14, 0x0e, 0x04};
+# define percent_width 5
+# define percent_height 7
+static unsigned char percent_bits[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x0a, 0x15, 0x09};
+# define ampersand_width 5
+# define ampersand_height 7
+static unsigned char ampersand_bits[] = {
+ 0x00, 0x00, 0x00, 0x02, 0x15, 0x09, 0x16};
+# define apostrophe_width 3
+# define apostrophe_height 3
+static unsigned char apostrophe_bits[] = {
+ 0x00, 0x00, 0x01};
+# define parenleft_width 3
+# define parenleft_height 7
+static unsigned char parenleft_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x04};
+# define parenright_width 3
+# define parenright_height 7
+static unsigned char parenright_bits[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x04, 0x02, 0x01};
+# define asterisk_width 5
+# define asterisk_height 5
+static unsigned char asterisk_bits[] = {
+ 0x00, 0x00, 0x00, 0x0a, 0x11};
+# define plus_width 5
+# define plus_height 5
+static unsigned char plus_bits[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x04};
+# define comma_width 3
+# define comma_height 3
+static unsigned char comma_bits[] = {
+ 0x00, 0x00, 0x01};
+# define minus_width 5
+# define minus_height 1
+static unsigned char minus_bits[] = {
+ 0x1f};
+# define period_width 3
+# define period_height 3
+static unsigned char period_bits[] = {
+ 0x00, 0x00, 0x02};
+# define slash_width 5
+# define slash_height 7
+static unsigned char slash_bits[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x01};
+# define 0_width 5
+# define 0_height 7
+static unsigned char 0_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x0a, 0x04};
+# define 1_width 5
+# define 1_height 7
+static unsigned char 1_bits[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x1f};
+# define 2_width 5
+# define 2_height 7
+static unsigned char 2_bits[] = {
+ 0x00, 0x00, 0x00, 0x0c, 0x02, 0x01, 0x1f};
+# define 3_width 5
+# define 3_height 7
+static unsigned char 3_bits[] = {
+ 0x00, 0x00, 0x00, 0x0c, 0x10, 0x11, 0x0e};
+# define 4_width 5
+# define 4_height 7
+static unsigned char 4_bits[] = {
+ 0x00, 0x00, 0x00, 0x09, 0x1f, 0x08, 0x08};
+# define 5_width 5
+# define 5_height 7
+static unsigned char 5_bits[] = {
+ 0x00, 0x00, 0x00, 0x13, 0x10, 0x11, 0x0e};
+# define 6_width 5
+# define 6_height 7
+static unsigned char 6_bits[] = {
+ 0x00, 0x00, 0x00, 0x0d, 0x13, 0x11, 0x0e};
+# define 7_width 5
+# define 7_height 7
+static unsigned char 7_bits[] = {
+ 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x02};
+# define 8_width 5
+# define 8_height 7
+static unsigned char 8_bits[] = {
+ 0x00, 0x00, 0x00, 0x0e, 0x11, 0x11, 0x0e};
+# define 9_width 5
+# define 9_height 7
+static unsigned char 9_bits[] = {
+ 0x00, 0x00, 0x00, 0x16, 0x10, 0x08, 0x06};
+# define colon_width 3
+# define colon_height 7
+static unsigned char colon_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x07, 0x02};
+# define semicolon_width 3
+# define semicolon_height 7
+static unsigned char semicolon_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x02, 0x01};
+# define less_width 4
+# define less_height 7
+static unsigned char less_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08};
+# define equal_width 5
+# define equal_height 3
+static unsigned char equal_bits[] = {
+ 0x00, 0x00, 0x1f};
+# define greater_width 4
+# define greater_height 7
+static unsigned char greater_bits[] = {
+ 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x01};
+# define question_width 5
+# define question_height 7
+static unsigned char question_bits[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x04};
+# define at_width 5
+# define at_height 7
+static unsigned char at_bits[] = {
+ 0x00, 0x00, 0x00, 0x15, 0x0d, 0x01, 0x0e};
+# define A_width 5
+# define A_height 7
+static unsigned char A_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x1f, 0x11, 0x11};
+# define B_width 5
+# define B_height 7
+static unsigned char B_bits[] = {
+ 0x00, 0x00, 0x00, 0x0e, 0x12, 0x12, 0x0f};
+# define C_width 5
+# define C_height 7
+static unsigned char C_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x11, 0x0e};
+# define D_width 5
+# define D_height 7
+static unsigned char D_bits[] = {
+ 0x00, 0x00, 0x00, 0x12, 0x12, 0x12, 0x0f};
+# define E_width 5
+# define E_height 7
+static unsigned char E_bits[] = {
+ 0x00, 0x00, 0x00, 0x0f, 0x01, 0x01, 0x1f};
+# define F_width 5
+# define F_height 7
+static unsigned char F_bits[] = {
+ 0x00, 0x00, 0x00, 0x0f, 0x01, 0x01, 0x01};
+# define G_width 5
+# define G_height 7
+static unsigned char G_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x19, 0x11, 0x0e};
+# define H_width 5
+# define H_height 7
+static unsigned char H_bits[] = {
+ 0x00, 0x00, 0x00, 0x1f, 0x11, 0x11, 0x11};
+# define I_width 3
+# define I_height 7
+static unsigned char I_bits[] = {
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x07};
+# define J_width 5
+# define J_height 7
+static unsigned char J_bits[] = {
+ 0x00, 0x00, 0x00, 0x10, 0x10, 0x11, 0x0e};
+# define K_width 5
+# define K_height 7
+static unsigned char K_bits[] = {
+ 0x00, 0x00, 0x00, 0x03, 0x05, 0x09, 0x11};
+# define L_width 5
+# define L_height 7
+static unsigned char L_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x1f};
+# define M_width 5
+# define M_height 7
+static unsigned char M_bits[] = {
+ 0x00, 0x00, 0x00, 0x15, 0x11, 0x11, 0x11};
+# define N_width 5
+# define N_height 7
+static unsigned char N_bits[] = {
+ 0x00, 0x00, 0x00, 0x15, 0x19, 0x11, 0x11};
+# define O_width 5
+# define O_height 7
+static unsigned char O_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x0e};
+# define P_width 5
+# define P_height 7
+static unsigned char P_bits[] = {
+ 0x00, 0x00, 0x00, 0x0f, 0x01, 0x01, 0x01};
+# define Q_width 5
+# define Q_height 8
+static unsigned char Q_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x15, 0x0e, 0x10};
+# define R_width 5
+# define R_height 7
+static unsigned char R_bits[] = {
+ 0x00, 0x00, 0x00, 0x0f, 0x05, 0x09, 0x11};
+# define S_width 5
+# define S_height 7
+static unsigned char S_bits[] = {
+ 0x00, 0x00, 0x00, 0x0e, 0x10, 0x11, 0x0e};
+# define T_width 5
+# define T_height 7
+static unsigned char T_bits[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04};
+# define U_width 5
+# define U_height 7
+static unsigned char U_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x0e};
+# define V_width 5
+# define V_height 7
+static unsigned char V_bits[] = {
+ 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x04};
+# define W_width 5
+# define W_height 7
+static unsigned char W_bits[] = {
+ 0x00, 0x00, 0x00, 0x15, 0x15, 0x1b, 0x11};
+# define X_width 5
+# define X_height 7
+static unsigned char X_bits[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x0a, 0x11, 0x11};
+# define Y_width 5
+# define Y_height 7
+static unsigned char Y_bits[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04};
+# define Z_width 5
+# define Z_height 7
+static unsigned char Z_bits[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x1f};
+# define bracketleft_width 3
+# define bracketleft_height 7
+static unsigned char bracketleft_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x07};
+# define backslash_width 5
+# define backslash_height 7
+static unsigned char backslash_bits[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x10};
+# define bracketright_width 3
+# define bracketright_height 7
+static unsigned char bracketright_bits[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x07};
+# define asciicircum_width 5
+# define asciicircum_height 3
+static unsigned char asciicircum_bits[] = {
+ 0x00, 0x00, 0x11};
+# define underscore_width 5
+# define underscore_height 1
+static unsigned char underscore_bits[] = {
+ 0x1f};
+# define grave_width 3
+# define grave_height 3
+static unsigned char grave_bits[] = {
+ 0x00, 0x00, 0x04};
+# define a_width 5
+# define a_height 5
+static unsigned char a_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x1e};
+# define b_width 5
+# define b_height 7
+static unsigned char b_bits[] = {
+ 0x00, 0x00, 0x00, 0x13, 0x11, 0x13, 0x0d};
+# define c_width 5
+# define c_height 5
+static unsigned char c_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x0e};
+# define d_width 5
+# define d_height 7
+static unsigned char d_bits[] = {
+ 0x00, 0x00, 0x00, 0x19, 0x11, 0x19, 0x16};
+# define e_width 5
+# define e_height 5
+static unsigned char e_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x0e};
+# define f_width 5
+# define f_height 7
+static unsigned char f_bits[] = {
+ 0x00, 0x00, 0x00, 0x0f, 0x02, 0x02, 0x02};
+# define g_width 5
+# define g_height 7
+static unsigned char g_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x0e, 0x11, 0x0e};
+# define h_width 5
+# define h_height 7
+static unsigned char h_bits[] = {
+ 0x00, 0x00, 0x00, 0x13, 0x11, 0x11, 0x11};
+# define i_width 3
+# define i_height 7
+static unsigned char i_bits[] = {
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x07};
+# define j_width 4
+# define j_height 9
+static unsigned char j_bits[] = {
+ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x09, 0x09, 0x06};
+# define k_width 5
+# define k_height 7
+static unsigned char k_bits[] = {
+ 0x00, 0x00, 0x00, 0x09, 0x07, 0x09, 0x11};
+# define l_width 3
+# define l_height 7
+static unsigned char l_bits[] = {
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x07};
+# define m_width 5
+# define m_height 5
+static unsigned char m_bits[] = {
+ 0x00, 0x00, 0x00, 0x15, 0x11};
+# define n_width 5
+# define n_height 5
+static unsigned char n_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11};
+# define o_width 5
+# define o_height 5
+static unsigned char o_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x0e};
+# define p_width 5
+# define p_height 7
+static unsigned char p_bits[] = {
+ 0x00, 0x00, 0x00, 0x0d, 0x01, 0x01, 0x01};
+# define q_width 5
+# define q_height 7
+static unsigned char q_bits[] = {
+ 0x00, 0x00, 0x00, 0x16, 0x10, 0x10, 0x10};
+# define r_width 5
+# define r_height 5
+static unsigned char r_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x01};
+# define s_width 5
+# define s_height 5
+static unsigned char s_bits[] = {
+ 0x00, 0x00, 0x00, 0x10, 0x0f};
+# define t_width 5
+# define t_height 7
+static unsigned char t_bits[] = {
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x12, 0x0c};
+# define u_width 5
+# define u_height 5
+static unsigned char u_bits[] = {
+ 0x00, 0x00, 0x00, 0x19, 0x16};
+# define v_width 5
+# define v_height 5
+static unsigned char v_bits[] = {
+ 0x00, 0x00, 0x00, 0x0a, 0x04};
+# define w_width 5
+# define w_height 5
+static unsigned char w_bits[] = {
+ 0x00, 0x00, 0x00, 0x15, 0x0a};
+# define x_width 5
+# define x_height 5
+static unsigned char x_bits[] = {
+ 0x00, 0x00, 0x00, 0x0a, 0x11};
+# define y_width 5
+# define y_height 7
+static unsigned char y_bits[] = {
+ 0x00, 0x00, 0x00, 0x16, 0x10, 0x11, 0x0e};
+# define z_width 5
+# define z_height 5
+static unsigned char z_bits[] = {
+ 0x00, 0x00, 0x00, 0x02, 0x1f};
+# define braceleft_width 4
+# define braceleft_height 7
+static unsigned char braceleft_bits[] = {
+ 0x00, 0x00, 0x00, 0x03, 0x04, 0x02, 0x0c};
+# define bar_width 1
+# define bar_height 7
+static unsigned char bar_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01};
+# define braceright_width 4
+# define braceright_height 7
+static unsigned char braceright_bits[] = {
+ 0x00, 0x00, 0x00, 0x0c, 0x02, 0x04, 0x03};
+# define asciitilde_width 5
+# define asciitilde_height 3
+static unsigned char asciitilde_bits[] = {
+ 0x00, 0x00, 0x09};
+# define C177_width 0
+# define C177_height 0
+static unsigned char C177_bits[] = {
+};
+# define nobreakspace_width 0
+# define nobreakspace_height 0
+static unsigned char nobreakspace_bits[] = {
+};
+# define exclamdown_width 1
+# define exclamdown_height 7
+static unsigned char exclamdown_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01};
+# define cent_width 5
+# define cent_height 7
+static unsigned char cent_bits[] = {
+ 0x00, 0x00, 0x00, 0x05, 0x05, 0x1e, 0x04};
+# define sterling_width 5
+# define sterling_height 7
+static unsigned char sterling_bits[] = {
+ 0x00, 0x00, 0x00, 0x07, 0x02, 0x12, 0x0d};
+# define currency_width 5
+# define currency_height 5
+static unsigned char currency_bits[] = {
+ 0x00, 0x00, 0x00, 0x0e, 0x11};
+# define yen_width 5
+# define yen_height 8
+static unsigned char yen_bits[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x1f, 0x04, 0x04, 0x04};
+# define brokenbar_width 1
+# define brokenbar_height 7
+static unsigned char brokenbar_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01};
+# define section_width 5
+# define section_height 8
+static unsigned char section_bits[] = {
+ 0x00, 0x00, 0x00, 0x09, 0x12, 0x1c, 0x10, 0x0e};
+# define diaeresis_width 3
+# define diaeresis_height 1
+static unsigned char diaeresis_bits[] = {
+ 0x05};
+# define copyright_width 5
+# define copyright_height 7
+static unsigned char copyright_bits[] = {
+ 0x00, 0x00, 0x00, 0x13, 0x15, 0x11, 0x0e};
+# define ordfeminine_width 4
+# define ordfeminine_height 6
+static unsigned char ordfeminine_bits[] = {
+ 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0f};
+# define guillemotleft_width 6
+# define guillemotleft_height 5
+static unsigned char guillemotleft_bits[] = {
+ 0x00, 0x00, 0x00, 0x12, 0x24};
+# define notsign_width 4
+# define notsign_height 2
+static unsigned char notsign_bits[] = {
+ 0x00, 0x08};
+# define hyphen_width 5
+# define hyphen_height 1
+static unsigned char hyphen_bits[] = {
+ 0x1f};
+# define registered_width 5
+# define registered_height 7
+static unsigned char registered_bits[] = {
+ 0x00, 0x00, 0x00, 0x13, 0x13, 0x11, 0x0e};
+# define macron_width 5
+# define macron_height 1
+static unsigned char macron_bits[] = {
+ 0x1f};
+# define degree_width 3
+# define degree_height 3
+static unsigned char degree_bits[] = {
+ 0x00, 0x00, 0x02};
+# define plusminus_width 5
+# define plusminus_height 6
+static unsigned char plusminus_bits[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x04, 0x1f};
+# define twosuperior_width 4
+# define twosuperior_height 5
+static unsigned char twosuperior_bits[] = {
+ 0x00, 0x00, 0x00, 0x02, 0x0f};
+# define threesuperior_width 4
+# define threesuperior_height 5
+static unsigned char threesuperior_bits[] = {
+ 0x00, 0x00, 0x00, 0x08, 0x07};
+# define acute_width 3
+# define acute_height 2
+static unsigned char acute_bits[] = {
+ 0x00, 0x03};
+# define mu_width 5
+# define mu_height 6
+static unsigned char mu_bits[] = {
+ 0x00, 0x00, 0x00, 0x13, 0x0d, 0x01};
+# define paragraph_width 5
+# define paragraph_height 7
+static unsigned char paragraph_bits[] = {
+ 0x00, 0x00, 0x00, 0x16, 0x14, 0x14, 0x14};
+# define periodcentered_width 1
+# define periodcentered_height 1
+static unsigned char periodcentered_bits[] = {
+ 0x01};
+# define cedilla_width 2
+# define cedilla_height 2
+static unsigned char cedilla_bits[] = {
+ 0x00, 0x01};
+# define onesuperior_width 3
+# define onesuperior_height 5
+static unsigned char onesuperior_bits[] = {
+ 0x00, 0x00, 0x00, 0x02, 0x07};
+# define masculine_width 4
+# define masculine_height 6
+static unsigned char masculine_bits[] = {
+ 0x00, 0x00, 0x00, 0x06, 0x00, 0x0f};
+# define guillemotright_width 6
+# define guillemotright_height 5
+static unsigned char guillemotright_bits[] = {
+ 0x00, 0x00, 0x00, 0x12, 0x09};
+# define onequarter_width 6
+# define onequarter_height 9
+static unsigned char onequarter_bits[] = {
+ 0x00, 0x00, 0x00, 0x02, 0x27, 0x30, 0x28, 0x3c, 0x20};
+# define onehalf_width 6
+# define onehalf_height 9
+static unsigned char onehalf_bits[] = {
+ 0x00, 0x00, 0x00, 0x02, 0x17, 0x28, 0x20, 0x10, 0x38};
+# define threequarters_width 5
+# define threequarters_height 9
+static unsigned char threequarters_bits[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x13, 0x18, 0x14, 0x1e, 0x10};
+# define questiondown_width 5
+# define questiondown_height 7
+static unsigned char questiondown_bits[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x02, 0x11, 0x0e};
+# define Agrave_width 5
+# define Agrave_height 8
+static unsigned char Agrave_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x1f, 0x11, 0x11};
+# define Aacute_width 5
+# define Aacute_height 8
+static unsigned char Aacute_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x1f, 0x11, 0x11};
+# define Acircumflex_width 5
+# define Acircumflex_height 8
+static unsigned char Acircumflex_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x1f, 0x11, 0x11};
+# define Atilde_width 5
+# define Atilde_height 8
+static unsigned char Atilde_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x1f, 0x11, 0x11};
+# define Adiaeresis_width 5
+# define Adiaeresis_height 8
+static unsigned char Adiaeresis_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x1f, 0x11, 0x11};
+# define Aring_width 5
+# define Aring_height 8
+static unsigned char Aring_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x1f, 0x11, 0x11};
+# define AE_width 6
+# define AE_height 7
+static unsigned char AE_bits[] = {
+ 0x00, 0x00, 0x00, 0x39, 0x0f, 0x09, 0x39};
+# define Ccedilla_width 5
+# define Ccedilla_height 9
+static unsigned char Ccedilla_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x11, 0x0e, 0x04, 0x02};
+# define Egrave_width 5
+# define Egrave_height 8
+static unsigned char Egrave_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x01, 0x1f};
+# define Eacute_width 5
+# define Eacute_height 8
+static unsigned char Eacute_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x01, 0x1f};
+# define Ecircumflex_width 5
+# define Ecircumflex_height 8
+static unsigned char Ecircumflex_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x01, 0x1f};
+# define Ediaeresis_width 5
+# define Ediaeresis_height 8
+static unsigned char Ediaeresis_bits[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x0f, 0x01, 0x01, 0x1f};
+# define Igrave_width 3
+# define Igrave_height 8
+static unsigned char Igrave_bits[] = {
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x07};
+# define Iacute_width 3
+# define Iacute_height 8
+static unsigned char Iacute_bits[] = {
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x07};
+# define Icircumflex_width 3
+# define Icircumflex_height 8
+static unsigned char Icircumflex_bits[] = {
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x07};
+# define Idiaeresis_width 3
+# define Idiaeresis_height 8
+static unsigned char Idiaeresis_bits[] = {
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x07};
+# define ETH_width 5
+# define ETH_height 7
+static unsigned char ETH_bits[] = {
+ 0x00, 0x00, 0x00, 0x17, 0x12, 0x12, 0x0f};
+# define Ntilde_width 5
+# define Ntilde_height 8
+static unsigned char Ntilde_bits[] = {
+ 0x00, 0x00, 0x00, 0x13, 0x15, 0x19, 0x11, 0x11};
+# define Ograve_width 5
+# define Ograve_height 8
+static unsigned char Ograve_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x0e};
+# define Oacute_width 5
+# define Oacute_height 8
+static unsigned char Oacute_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x0e};
+# define Ocircumflex_width 5
+# define Ocircumflex_height 8
+static unsigned char Ocircumflex_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x0e};
+# define Otilde_width 5
+# define Otilde_height 8
+static unsigned char Otilde_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x0e};
+# define Odiaeresis_width 5
+# define Odiaeresis_height 8
+static unsigned char Odiaeresis_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x0e};
+# define multiply_width 5
+# define multiply_height 5
+static unsigned char multiply_bits[] = {
+ 0x00, 0x00, 0x00, 0x0a, 0x11};
+# define Ooblique_width 5
+# define Ooblique_height 7
+static unsigned char Ooblique_bits[] = {
+ 0x00, 0x00, 0x00, 0x15, 0x13, 0x13, 0x0e};
+# define Ugrave_width 5
+# define Ugrave_height 8
+static unsigned char Ugrave_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x0e};
+# define Uacute_width 5
+# define Uacute_height 8
+static unsigned char Uacute_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x0e};
+# define Ucircumflex_width 5
+# define Ucircumflex_height 8
+static unsigned char Ucircumflex_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x0e};
+# define Udiaeresis_width 5
+# define Udiaeresis_height 8
+static unsigned char Udiaeresis_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x0e};
+# define Yacute_width 5
+# define Yacute_height 8
+static unsigned char Yacute_bits[] = {
+ 0x00, 0x00, 0x00, 0x0a, 0x04, 0x04, 0x04, 0x04};
+# define THORN_width 5
+# define THORN_height 7
+static unsigned char THORN_bits[] = {
+ 0x00, 0x00, 0x00, 0x0f, 0x01, 0x01, 0x01};
+# define ssharp_width 5
+# define ssharp_height 8
+static unsigned char ssharp_bits[] = {
+ 0x00, 0x00, 0x00, 0x0f, 0x11, 0x11, 0x0f, 0x01};
+# define agrave_width 5
+# define agrave_height 7
+static unsigned char agrave_bits[] = {
+ 0x00, 0x00, 0x00, 0x10, 0x1e, 0x11, 0x1e};
+# define aacute_width 5
+# define aacute_height 7
+static unsigned char aacute_bits[] = {
+ 0x00, 0x00, 0x00, 0x10, 0x1e, 0x11, 0x1e};
+# define acircumflex_width 5
+# define acircumflex_height 7
+static unsigned char acircumflex_bits[] = {
+ 0x00, 0x00, 0x00, 0x10, 0x1e, 0x11, 0x1e};
+# define atilde_width 5
+# define atilde_height 7
+static unsigned char atilde_bits[] = {
+ 0x00, 0x00, 0x00, 0x10, 0x1e, 0x11, 0x1e};
+# define adiaeresis_width 5
+# define adiaeresis_height 7
+static unsigned char adiaeresis_bits[] = {
+ 0x00, 0x00, 0x00, 0x10, 0x1e, 0x11, 0x1e};
+# define aring_width 5
+# define aring_height 8
+static unsigned char aring_bits[] = {
+ 0x00, 0x00, 0x00, 0x0e, 0x10, 0x1e, 0x11, 0x1e};
+# define ae_width 6
+# define ae_height 5
+static unsigned char ae_bits[] = {
+ 0x00, 0x00, 0x00, 0x09, 0x3e};
+# define ccedilla_width 5
+# define ccedilla_height 7
+static unsigned char ccedilla_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x0e, 0x04, 0x02};
+# define egrave_width 5
+# define egrave_height 7
+static unsigned char egrave_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x1f, 0x01, 0x0e};
+# define eacute_width 5
+# define eacute_height 7
+static unsigned char eacute_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x1f, 0x01, 0x0e};
+# define ecircumflex_width 5
+# define ecircumflex_height 7
+static unsigned char ecircumflex_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x1f, 0x01, 0x0e};
+# define ediaeresis_width 5
+# define ediaeresis_height 7
+static unsigned char ediaeresis_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x1f, 0x01, 0x0e};
+# define igrave_width 3
+# define igrave_height 8
+static unsigned char igrave_bits[] = {
+ 0x00, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x07};
+# define iacute_width 3
+# define iacute_height 8
+static unsigned char iacute_bits[] = {
+ 0x00, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x07};
+# define icircumflex_width 3
+# define icircumflex_height 8
+static unsigned char icircumflex_bits[] = {
+ 0x00, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x07};
+# define idiaeresis_width 3
+# define idiaeresis_height 7
+static unsigned char idiaeresis_bits[] = {
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x07};
+# define eth_width 5
+# define eth_height 7
+static unsigned char eth_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x0e};
+# define ntilde_width 5
+# define ntilde_height 7
+static unsigned char ntilde_bits[] = {
+ 0x00, 0x00, 0x00, 0x13, 0x11, 0x11, 0x11};
+# define ograve_width 5
+# define ograve_height 7
+static unsigned char ograve_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x0e};
+# define oacute_width 5
+# define oacute_height 7
+static unsigned char oacute_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x0e};
+# define ocircumflex_width 5
+# define ocircumflex_height 7
+static unsigned char ocircumflex_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x0e};
+# define otilde_width 5
+# define otilde_height 7
+static unsigned char otilde_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x0e};
+# define odiaeresis_width 5
+# define odiaeresis_height 7
+static unsigned char odiaeresis_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x0e};
+# define division_width 5
+# define division_height 5
+static unsigned char division_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x04};
+# define oslash_width 5
+# define oslash_height 5
+static unsigned char oslash_bits[] = {
+ 0x00, 0x00, 0x00, 0x13, 0x0f};
+# define ugrave_width 5
+# define ugrave_height 7
+static unsigned char ugrave_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x19, 0x16};
+# define uacute_width 5
+# define uacute_height 7
+static unsigned char uacute_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x19, 0x16};
+# define ucircumflex_width 5
+# define ucircumflex_height 7
+static unsigned char ucircumflex_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x19, 0x16};
+# define udiaeresis_width 5
+# define udiaeresis_height 7
+static unsigned char udiaeresis_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x19, 0x16};
+# define yacute_width 5
+# define yacute_height 9
+static unsigned char yacute_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x19, 0x16, 0x10, 0x11, 0x0e};
+# define thorn_width 5
+# define thorn_height 8
+static unsigned char thorn_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x0f, 0x01, 0x01};
+# define ydiaeresis_width 5
+# define ydiaeresis_height 9
+static unsigned char ydiaeresis_bits[] = {
+ 0x00, 0x00, 0x00, 0x11, 0x19, 0x16, 0x10, 0x11, 0x0e};
Index: /tags/start/Ohana/src/kapa/rotfont/test.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/test.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/test.h	(revision 12606)
@@ -0,0 +1,7 @@
+#define g_width 16
+#define g_height 22
+static unsigned char g_bits[] = {
+0xe0, 0x07, 0x38, 0x1c, 0x1c, 0x38, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x06, 0x60, 0x06, 0x60, 0x1c, 0x38, 0x38, 0x1c, 0xe0, 0x07, 0x80, 0x03, 
+0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c, 0x00, 0xf0};
Index: /tags/start/Ohana/src/kapa/rotfont/times12.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/times12.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/times12.bdf	(revision 12606)
@@ -0,0 +1,2973 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Times-Medium-R-Normal--12-120-75-75-P-64-ISO8859-1
+SIZE 12 75 75
+FONTBOUNDINGBOX 12 15 0 -3
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Times"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 64
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 9
+X_HEIGHT 6
+FACE_NAME "Times Roman"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Times is a trademark of Linotype-Hell AG and/or its subsidiaries."
+_DEC_DEVICE_FONTNAMES "PS=Times-Roman"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Times Roman"
+FONT "-Adobe-Times-Medium-R-Normal--12-120-75-75-P-64-ISO8859-1"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 7
+DEFAULT_CHAR 32
+FONT_ASCENT 11
+FONT_DESCENT 3
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 3 1 6
+BITMAP
+a0
+a0
+a0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+50
+50
+f8
+50
+50
+f8
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 11 0 -1
+BITMAP
+20
+70
+a8
+a0
+60
+30
+28
+28
+a8
+70
+20
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+63
+9e
+94
+68
+10
+36
+29
+49
+46
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+1800
+2400
+2400
+1b80
+7900
+ce00
+8400
+ce80
+7b00
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 3 1 6
+BITMAP
+c0
+40
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 12 1 -3
+BITMAP
+20
+40
+40
+80
+80
+80
+80
+80
+80
+40
+40
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 12 0 -3
+BITMAP
+80
+40
+40
+20
+20
+20
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 5 0 4
+BITMAP
+20
+a8
+70
+a8
+20
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+20
+f8
+20
+20
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 3 0 -2
+BITMAP
+40
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 1 1 3
+BITMAP
+f8
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 1 1 0
+BITMAP
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+20
+20
+20
+40
+40
+40
+80
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+d8
+88
+88
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 9 0 0
+BITMAP
+20
+60
+a0
+20
+20
+20
+20
+20
+70
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+88
+08
+08
+10
+20
+40
+88
+f8
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+88
+08
+10
+70
+08
+08
+88
+70
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+10
+30
+30
+50
+50
+90
+f8
+10
+10
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+38
+40
+40
+70
+18
+08
+08
+98
+70
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+18
+60
+40
+f0
+98
+88
+88
+c8
+70
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+f8
+88
+10
+10
+20
+20
+40
+40
+40
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+88
+88
+c8
+70
+98
+88
+88
+70
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+98
+88
+88
+c8
+78
+10
+30
+c0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 6 1 0
+BITMAP
+80
+00
+00
+00
+00
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 8 0 -2
+BITMAP
+40
+00
+00
+00
+00
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+0c
+30
+c0
+30
+0c
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 3 1 2
+BITMAP
+f8
+00
+f8
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 1 1
+BITMAP
+c0
+30
+0c
+30
+c0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 9 0 0
+BITMAP
+60
+90
+10
+20
+40
+40
+40
+00
+40
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 10 11 1 -2
+BITMAP
+0f00
+3080
+6040
+4d40
+9240
+a240
+a480
+a480
+9b00
+4000
+3e00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+0800
+0800
+1400
+1400
+2200
+3e00
+2200
+4100
+e380
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+fc
+46
+42
+46
+7c
+42
+42
+46
+fc
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+3a
+66
+42
+80
+80
+80
+42
+66
+3c
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 1 0
+BITMAP
+fc
+46
+42
+41
+41
+41
+42
+46
+fc
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+fe
+42
+40
+44
+7c
+44
+40
+42
+fe
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+fe
+42
+40
+44
+7c
+44
+40
+40
+f0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3a
+66
+42
+80
+87
+82
+42
+66
+3c
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+e7
+42
+42
+42
+7e
+42
+42
+42
+e7
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 9 0 0
+BITMAP
+e0
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 9 1 0
+BITMAP
+70
+20
+20
+20
+20
+20
+20
+a0
+c0
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+ee
+44
+48
+50
+70
+58
+4c
+46
+e7
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+e0
+40
+40
+40
+40
+40
+40
+44
+fc
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 11 9 0 0
+BITMAP
+c060
+60c0
+60c0
+5140
+5140
+4a40
+4a40
+4440
+e4e0
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+c380
+6100
+6100
+5100
+4900
+4900
+4500
+4300
+e100
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3c
+66
+42
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+fc
+46
+42
+46
+7c
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 11 0 -2
+BITMAP
+3c
+66
+42
+81
+81
+81
+42
+66
+3c
+0c
+03
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+fc
+46
+42
+46
+7c
+48
+44
+42
+e3
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+74
+8c
+84
+60
+38
+0c
+84
+cc
+b8
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+fe
+92
+10
+10
+10
+10
+10
+10
+38
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 1 0
+BITMAP
+e7
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+e380
+4100
+2200
+2200
+1400
+1400
+1c00
+0800
+0800
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 960 0
+DWIDTH 12 0
+BBX 12 9 0 0
+BITMAP
+ee70
+4420
+6620
+2240
+3740
+1540
+1980
+0880
+0880
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 1 0
+BITMAP
+e7
+42
+24
+38
+18
+2c
+24
+42
+e7
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+e380
+4100
+2200
+1200
+1c00
+0800
+0800
+0800
+1c00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+fe
+86
+0c
+18
+30
+60
+c0
+82
+fe
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 12 1 -3
+BITMAP
+e0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+e0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+80
+80
+80
+40
+40
+40
+20
+20
+20
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 12 0 -3
+BITMAP
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+e0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 5 0 4
+BITMAP
+20
+50
+50
+88
+88
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 1 0 -3
+BITMAP
+fc
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 3 1 6
+BITMAP
+40
+80
+c0
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+60
+90
+70
+90
+90
+68
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+c0
+40
+40
+70
+48
+48
+48
+48
+70
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 6 1 0
+BITMAP
+60
+90
+80
+80
+90
+60
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+30
+10
+10
+70
+90
+90
+90
+90
+68
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+60
+90
+f0
+80
+c8
+70
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 9 0 0
+BITMAP
+20
+40
+40
+e0
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 -3
+BITMAP
+78
+90
+90
+e0
+40
+70
+88
+88
+70
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+c0
+40
+40
+70
+48
+48
+48
+48
+ec
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+40
+00
+00
+c0
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 12 0 -3
+BITMAP
+40
+00
+00
+c0
+40
+40
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+c0
+40
+40
+48
+50
+60
+50
+48
+4c
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+c0
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 6 0 0
+BITMAP
+b600
+4900
+4900
+4900
+4900
+ed80
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 6 0 0
+BITMAP
+b0
+48
+48
+48
+48
+ec
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 6 1 0
+BITMAP
+60
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 -3
+BITMAP
+f0
+48
+48
+48
+48
+70
+40
+40
+e0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 -3
+BITMAP
+70
+90
+90
+90
+90
+70
+10
+10
+38
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 6 0 0
+BITMAP
+b0
+60
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 6 1 0
+BITMAP
+70
+90
+c0
+30
+90
+e0
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 7 0 0
+BITMAP
+40
+f0
+40
+40
+40
+40
+30
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 6 0 0
+BITMAP
+d8
+48
+48
+48
+48
+34
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 6 0 0
+BITMAP
+cc
+48
+58
+50
+30
+20
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 6 0 0
+BITMAP
+ed80
+4900
+6b00
+2a00
+3400
+2400
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+d8
+50
+20
+20
+50
+d8
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 -3
+BITMAP
+cc
+48
+58
+50
+30
+20
+20
+40
+c0
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 6 1 0
+BITMAP
+f0
+90
+20
+40
+90
+f0
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 12 1 -3
+BITMAP
+30
+40
+40
+40
+40
+80
+40
+40
+40
+40
+40
+30
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 12 0 -3
+BITMAP
+c0
+20
+20
+20
+20
+10
+20
+20
+20
+20
+20
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 2 0 3
+BITMAP
+64
+98
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 1 9 1 -3
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 8 1 -1
+BITMAP
+08
+70
+98
+a0
+a0
+c8
+70
+80
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+30
+48
+40
+40
+f0
+40
+40
+e8
+d8
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 1
+BITMAP
+84
+78
+48
+48
+48
+78
+84
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+88
+88
+50
+50
+f8
+20
+f8
+20
+70
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+00
+00
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 12 1 -3
+BITMAP
+70
+90
+c0
+60
+b0
+90
+90
+d0
+60
+30
+90
+e0
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 1 0 7
+BITMAP
+a0
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 1 0
+BITMAP
+1c00
+6300
+5d00
+a480
+a080
+a480
+5d00
+6300
+1c00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 6 1 3
+BITMAP
+c0
+20
+e0
+a0
+00
+e0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 0
+BITMAP
+28
+50
+a0
+50
+28
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 4 1 1
+BITMAP
+fc
+04
+04
+04
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 1 0 3
+BITMAP
+f0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+1c00
+6300
+5d00
+9280
+9c80
+9480
+d500
+6300
+3c00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 1 0 7
+BITMAP
+f0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 4 0 5
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+20
+20
+f8
+20
+20
+00
+f8
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 5 0 4
+BITMAP
+60
+90
+20
+40
+f0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 5 0 4
+BITMAP
+e0
+20
+40
+20
+c0
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 2 1 7
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 -3
+BITMAP
+d8
+48
+48
+48
+48
+74
+40
+40
+60
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+7c
+e8
+e8
+e8
+e8
+68
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 1 1 3
+BITMAP
+80
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 3 0 -3
+BITMAP
+40
+20
+e0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 5 0 4
+BITMAP
+40
+c0
+40
+40
+e0
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 6 1 3
+BITMAP
+40
+a0
+a0
+40
+00
+e0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 0 0
+BITMAP
+a0
+50
+28
+50
+a0
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+4200
+c400
+4400
+4800
+e900
+1300
+1500
+2780
+2100
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+4200
+c400
+4400
+4800
+eb00
+1480
+1100
+2200
+2780
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+e200
+2400
+4400
+2800
+c900
+1300
+1500
+2780
+2100
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 9 0 -3
+BITMAP
+20
+00
+20
+20
+20
+40
+80
+90
+60
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+1000
+0800
+0000
+0800
+0800
+1400
+1400
+2200
+3e00
+2200
+4100
+e380
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+0400
+0800
+0000
+0800
+0800
+1400
+1400
+2200
+3e00
+2200
+4100
+e380
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+0800
+1400
+0000
+0800
+0800
+1400
+1400
+2200
+3e00
+2200
+4100
+e380
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+0a00
+1400
+0000
+0800
+0800
+1400
+1400
+2200
+3e00
+2200
+4100
+e380
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 11 0 0
+BITMAP
+1400
+0000
+0800
+0800
+1400
+1400
+2200
+3e00
+2200
+4100
+e380
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+0800
+1400
+0800
+0800
+0800
+1400
+1400
+2200
+3e00
+2200
+4100
+e380
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 10 9 0 0
+BITMAP
+3fc0
+1840
+2800
+2880
+4f80
+7880
+4800
+8840
+cfc0
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 12 0 -3
+BITMAP
+3a
+66
+42
+80
+80
+80
+42
+66
+3c
+10
+08
+38
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 12 0 0
+BITMAP
+20
+10
+00
+fe
+42
+40
+44
+7c
+44
+40
+42
+fe
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 12 0 0
+BITMAP
+08
+10
+00
+fe
+42
+40
+44
+7c
+44
+40
+42
+fe
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 12 0 0
+BITMAP
+10
+28
+00
+fe
+42
+40
+44
+7c
+44
+40
+42
+fe
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 11 0 0
+BITMAP
+28
+00
+fe
+42
+40
+44
+7c
+44
+40
+42
+fe
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 12 0 0
+BITMAP
+80
+40
+00
+e0
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 12 0 0
+BITMAP
+20
+40
+00
+e0
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 12 0 0
+BITMAP
+40
+a0
+00
+e0
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 11 0 0
+BITMAP
+a0
+00
+e0
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+fc
+46
+42
+41
+e1
+41
+42
+46
+fc
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+0a00
+1400
+0000
+c380
+6100
+6100
+5100
+4900
+4900
+4500
+4300
+e100
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+20
+10
+00
+3c
+66
+42
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+04
+08
+00
+3c
+66
+42
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+10
+28
+00
+3c
+66
+42
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+14
+28
+00
+3c
+66
+42
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 11 0 0
+BITMAP
+24
+00
+3c
+66
+42
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+88
+50
+20
+50
+88
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+0080
+3d00
+6600
+4600
+8900
+8900
+9100
+6200
+6600
+bc00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+10
+08
+00
+e7
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+04
+08
+00
+e7
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+10
+28
+00
+e7
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 11 0 0
+BITMAP
+24
+00
+e7
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+0400
+0800
+0000
+e380
+4100
+2200
+1200
+1c00
+0800
+0800
+0800
+1c00
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+e0
+40
+7c
+46
+42
+46
+7c
+40
+e0
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+30
+48
+48
+50
+70
+48
+44
+44
+d8
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+40
+20
+00
+60
+90
+70
+90
+90
+68
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+10
+20
+00
+60
+90
+70
+90
+90
+68
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+20
+50
+00
+60
+90
+70
+90
+90
+68
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+50
+a0
+00
+60
+90
+70
+90
+90
+68
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 8 1 0
+BITMAP
+50
+00
+60
+90
+70
+90
+90
+68
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+20
+50
+20
+60
+90
+70
+90
+90
+68
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 6 1 0
+BITMAP
+6c
+92
+7e
+90
+99
+6e
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 9 1 -3
+BITMAP
+60
+90
+80
+80
+90
+60
+40
+20
+e0
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+40
+20
+00
+60
+90
+f0
+80
+c8
+70
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+20
+40
+00
+60
+90
+f0
+80
+c8
+70
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+20
+50
+00
+60
+90
+f0
+80
+c8
+70
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 8 1 0
+BITMAP
+50
+00
+60
+90
+f0
+80
+c8
+70
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+80
+40
+00
+c0
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+40
+80
+00
+c0
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+40
+a0
+00
+c0
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 8 0 0
+BITMAP
+a0
+00
+c0
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 9 1 0
+BITMAP
+40
+70
+a0
+70
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+28
+50
+00
+b0
+48
+48
+48
+48
+ec
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 9 1 0
+BITMAP
+40
+20
+00
+60
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 9 1 0
+BITMAP
+20
+40
+00
+60
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 9 1 0
+BITMAP
+20
+50
+00
+60
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 9 1 0
+BITMAP
+50
+a0
+00
+60
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 8 1 0
+BITMAP
+a0
+00
+60
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+00
+f8
+00
+20
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 7 0 -1
+BITMAP
+34
+48
+48
+48
+48
+70
+80
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+20
+10
+00
+d8
+48
+48
+48
+48
+34
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+10
+20
+00
+d8
+48
+48
+48
+48
+34
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+20
+50
+00
+d8
+48
+48
+48
+48
+34
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 8 0 0
+BITMAP
+50
+00
+d8
+48
+48
+48
+48
+34
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+08
+10
+00
+cc
+48
+58
+50
+30
+20
+20
+40
+c0
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 12 0 -3
+BITMAP
+c0
+40
+40
+70
+48
+48
+48
+48
+70
+40
+40
+e0
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 11 0 -3
+BITMAP
+48
+00
+cc
+48
+58
+50
+30
+20
+20
+40
+c0
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/times12.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/times12.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/times12.h	(revision 12606)
@@ -0,0 +1,792 @@
+static unsigned char times12_0_bits[] = {
+0x00};
+static unsigned char times12_1_bits[] = {
+0x00};
+static unsigned char times12_2_bits[] = {
+0x00};
+static unsigned char times12_3_bits[] = {
+0x00};
+static unsigned char times12_4_bits[] = {
+0x00};
+static unsigned char times12_5_bits[] = {
+0x00};
+static unsigned char times12_6_bits[] = {
+0x00};
+static unsigned char times12_7_bits[] = {
+0x00};
+static unsigned char times12_8_bits[] = {
+0x00};
+static unsigned char times12_9_bits[] = {
+0x00};
+static unsigned char times12_10_bits[] = {
+0x00};
+static unsigned char times12_11_bits[] = {
+0x00};
+static unsigned char times12_12_bits[] = {
+0x00};
+static unsigned char times12_13_bits[] = {
+0x00};
+static unsigned char times12_14_bits[] = {
+0x00};
+static unsigned char times12_15_bits[] = {
+0x00};
+static unsigned char times12_16_bits[] = {
+0x00};
+static unsigned char times12_17_bits[] = {
+0x00};
+static unsigned char times12_18_bits[] = {
+0x00};
+static unsigned char times12_19_bits[] = {
+0x00};
+static unsigned char times12_20_bits[] = {
+0x00};
+static unsigned char times12_21_bits[] = {
+0x00};
+static unsigned char times12_22_bits[] = {
+0x00};
+static unsigned char times12_23_bits[] = {
+0x00};
+static unsigned char times12_24_bits[] = {
+0x00};
+static unsigned char times12_25_bits[] = {
+0x00};
+static unsigned char times12_26_bits[] = {
+0x00};
+static unsigned char times12_27_bits[] = {
+0x00};
+static unsigned char times12_28_bits[] = {
+0x00};
+static unsigned char times12_29_bits[] = {
+0x00};
+static unsigned char times12_30_bits[] = {
+0x00};
+static unsigned char times12_31_bits[] = {
+0x00};
+static unsigned char times12_32_bits[] = {
+0x00};
+static unsigned char times12_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01};
+static unsigned char times12_34_bits[] = {
+0x05, 0x05, 0x05};
+static unsigned char times12_35_bits[] = {
+0x0a, 0x0a, 0x1f, 0x0a, 0x0a, 0x1f, 0x0a, 0x0a};
+static unsigned char times12_36_bits[] = {
+0x04, 0x0e, 0x15, 0x05, 0x06, 0x0c, 0x14, 0x14, 0x15, 0x0e, 0x04};
+static unsigned char times12_37_bits[] = {
+0xc6, 0x79, 0x29, 0x16, 0x08, 0x6c, 0x94, 0x92, 0x62};
+static unsigned char times12_38_bits[] = {
+0x18, 0x00, 0x24, 0x00, 0x24, 0x00, 0xd8, 0x01, 0x9e, 0x00, 0x73, 0x00, 
+0x21, 0x00, 0x73, 0x01, 0xde, 0x00};
+static unsigned char times12_39_bits[] = {
+0x03, 0x02, 0x01};
+static unsigned char times12_40_bits[] = {
+0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x04};
+static unsigned char times12_41_bits[] = {
+0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01};
+static unsigned char times12_42_bits[] = {
+0x04, 0x15, 0x0e, 0x15, 0x04};
+static unsigned char times12_43_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x04};
+static unsigned char times12_44_bits[] = {
+0x02, 0x02, 0x01};
+static unsigned char times12_45_bits[] = {
+0x1f};
+static unsigned char times12_46_bits[] = {
+0x01};
+static unsigned char times12_47_bits[] = {
+0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01};
+static unsigned char times12_48_bits[] = {
+0x0e, 0x1b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char times12_49_bits[] = {
+0x04, 0x06, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0e};
+static unsigned char times12_50_bits[] = {
+0x0e, 0x11, 0x10, 0x10, 0x08, 0x04, 0x02, 0x11, 0x1f};
+static unsigned char times12_51_bits[] = {
+0x0e, 0x11, 0x10, 0x08, 0x0e, 0x10, 0x10, 0x11, 0x0e};
+static unsigned char times12_52_bits[] = {
+0x08, 0x0c, 0x0c, 0x0a, 0x0a, 0x09, 0x1f, 0x08, 0x08};
+static unsigned char times12_53_bits[] = {
+0x1c, 0x02, 0x02, 0x0e, 0x18, 0x10, 0x10, 0x19, 0x0e};
+static unsigned char times12_54_bits[] = {
+0x18, 0x06, 0x02, 0x0f, 0x19, 0x11, 0x11, 0x13, 0x0e};
+static unsigned char times12_55_bits[] = {
+0x1f, 0x11, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x02};
+static unsigned char times12_56_bits[] = {
+0x0e, 0x11, 0x11, 0x13, 0x0e, 0x19, 0x11, 0x11, 0x0e};
+static unsigned char times12_57_bits[] = {
+0x0e, 0x19, 0x11, 0x11, 0x13, 0x1e, 0x08, 0x0c, 0x03};
+static unsigned char times12_58_bits[] = {
+0x01, 0x00, 0x00, 0x00, 0x00, 0x01};
+static unsigned char times12_59_bits[] = {
+0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01};
+static unsigned char times12_60_bits[] = {
+0x30, 0x0c, 0x03, 0x0c, 0x30};
+static unsigned char times12_61_bits[] = {
+0x1f, 0x00, 0x1f};
+static unsigned char times12_62_bits[] = {
+0x03, 0x0c, 0x30, 0x0c, 0x03};
+static unsigned char times12_63_bits[] = {
+0x06, 0x09, 0x08, 0x04, 0x02, 0x02, 0x02, 0x00, 0x02};
+static unsigned char times12_64_bits[] = {
+0xf0, 0x00, 0x0c, 0x01, 0x06, 0x02, 0xb2, 0x02, 0x49, 0x02, 0x45, 0x02, 
+0x25, 0x01, 0x25, 0x01, 0xd9, 0x00, 0x02, 0x00, 0x7c, 0x00};
+static unsigned char times12_65_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 
+0x44, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char times12_66_bits[] = {
+0x3f, 0x62, 0x42, 0x62, 0x3e, 0x42, 0x42, 0x62, 0x3f};
+static unsigned char times12_67_bits[] = {
+0x5c, 0x66, 0x42, 0x01, 0x01, 0x01, 0x42, 0x66, 0x3c};
+static unsigned char times12_68_bits[] = {
+0x3f, 0x62, 0x42, 0x82, 0x82, 0x82, 0x42, 0x62, 0x3f};
+static unsigned char times12_69_bits[] = {
+0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 0x7f};
+static unsigned char times12_70_bits[] = {
+0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x02, 0x0f};
+static unsigned char times12_71_bits[] = {
+0x5c, 0x66, 0x42, 0x01, 0xe1, 0x41, 0x42, 0x66, 0x3c};
+static unsigned char times12_72_bits[] = {
+0xe7, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0xe7};
+static unsigned char times12_73_bits[] = {
+0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_74_bits[] = {
+0x0e, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x03};
+static unsigned char times12_75_bits[] = {
+0x77, 0x22, 0x12, 0x0a, 0x0e, 0x1a, 0x32, 0x62, 0xe7};
+static unsigned char times12_76_bits[] = {
+0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x22, 0x3f};
+static unsigned char times12_77_bits[] = {
+0x03, 0x06, 0x06, 0x03, 0x06, 0x03, 0x8a, 0x02, 0x8a, 0x02, 0x52, 0x02, 
+0x52, 0x02, 0x22, 0x02, 0x27, 0x07};
+static unsigned char times12_78_bits[] = {
+0xc3, 0x01, 0x86, 0x00, 0x86, 0x00, 0x8a, 0x00, 0x92, 0x00, 0x92, 0x00, 
+0xa2, 0x00, 0xc2, 0x00, 0x87, 0x00};
+static unsigned char times12_79_bits[] = {
+0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char times12_80_bits[] = {
+0x3f, 0x62, 0x42, 0x62, 0x3e, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_81_bits[] = {
+0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c, 0x30, 0xc0};
+static unsigned char times12_82_bits[] = {
+0x3f, 0x62, 0x42, 0x62, 0x3e, 0x12, 0x22, 0x42, 0xc7};
+static unsigned char times12_83_bits[] = {
+0x2e, 0x31, 0x21, 0x06, 0x1c, 0x30, 0x21, 0x33, 0x1d};
+static unsigned char times12_84_bits[] = {
+0x7f, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c};
+static unsigned char times12_85_bits[] = {
+0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3c};
+static unsigned char times12_86_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 
+0x38, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char times12_87_bits[] = {
+0x77, 0x0e, 0x22, 0x04, 0x66, 0x04, 0x44, 0x02, 0xec, 0x02, 0xa8, 0x02, 
+0x98, 0x01, 0x10, 0x01, 0x10, 0x01};
+static unsigned char times12_88_bits[] = {
+0xe7, 0x42, 0x24, 0x1c, 0x18, 0x34, 0x24, 0x42, 0xe7};
+static unsigned char times12_89_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x48, 0x00, 0x38, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x38, 0x00};
+static unsigned char times12_90_bits[] = {
+0x7f, 0x61, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x41, 0x7f};
+static unsigned char times12_91_bits[] = {
+0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07};
+static unsigned char times12_92_bits[] = {
+0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04};
+static unsigned char times12_93_bits[] = {
+0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07};
+static unsigned char times12_94_bits[] = {
+0x04, 0x0a, 0x0a, 0x11, 0x11};
+static unsigned char times12_95_bits[] = {
+0x3f};
+static unsigned char times12_96_bits[] = {
+0x02, 0x01, 0x03};
+static unsigned char times12_97_bits[] = {
+0x06, 0x09, 0x0e, 0x09, 0x09, 0x16};
+static unsigned char times12_98_bits[] = {
+0x03, 0x02, 0x02, 0x0e, 0x12, 0x12, 0x12, 0x12, 0x0e};
+static unsigned char times12_99_bits[] = {
+0x06, 0x09, 0x01, 0x01, 0x09, 0x06};
+static unsigned char times12_100_bits[] = {
+0x0c, 0x08, 0x08, 0x0e, 0x09, 0x09, 0x09, 0x09, 0x16};
+static unsigned char times12_101_bits[] = {
+0x06, 0x09, 0x0f, 0x01, 0x13, 0x0e};
+static unsigned char times12_102_bits[] = {
+0x04, 0x02, 0x02, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char times12_103_bits[] = {
+0x1e, 0x09, 0x09, 0x07, 0x02, 0x0e, 0x11, 0x11, 0x0e};
+static unsigned char times12_104_bits[] = {
+0x03, 0x02, 0x02, 0x0e, 0x12, 0x12, 0x12, 0x12, 0x37};
+static unsigned char times12_105_bits[] = {
+0x02, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_106_bits[] = {
+0x02, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char times12_107_bits[] = {
+0x03, 0x02, 0x02, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x32};
+static unsigned char times12_108_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_109_bits[] = {
+0x6d, 0x00, 0x92, 0x00, 0x92, 0x00, 0x92, 0x00, 0x92, 0x00, 0xb7, 0x01};
+static unsigned char times12_110_bits[] = {
+0x0d, 0x12, 0x12, 0x12, 0x12, 0x37};
+static unsigned char times12_111_bits[] = {
+0x06, 0x09, 0x09, 0x09, 0x09, 0x06};
+static unsigned char times12_112_bits[] = {
+0x0f, 0x12, 0x12, 0x12, 0x12, 0x0e, 0x02, 0x02, 0x07};
+static unsigned char times12_113_bits[] = {
+0x0e, 0x09, 0x09, 0x09, 0x09, 0x0e, 0x08, 0x08, 0x1c};
+static unsigned char times12_114_bits[] = {
+0x0d, 0x06, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_115_bits[] = {
+0x0e, 0x09, 0x03, 0x0c, 0x09, 0x07};
+static unsigned char times12_116_bits[] = {
+0x02, 0x0f, 0x02, 0x02, 0x02, 0x02, 0x0c};
+static unsigned char times12_117_bits[] = {
+0x1b, 0x12, 0x12, 0x12, 0x12, 0x2c};
+static unsigned char times12_118_bits[] = {
+0x33, 0x12, 0x1a, 0x0a, 0x0c, 0x04};
+static unsigned char times12_119_bits[] = {
+0xb7, 0x01, 0x92, 0x00, 0xd6, 0x00, 0x54, 0x00, 0x2c, 0x00, 0x24, 0x00};
+static unsigned char times12_120_bits[] = {
+0x1b, 0x0a, 0x04, 0x04, 0x0a, 0x1b};
+static unsigned char times12_121_bits[] = {
+0x33, 0x12, 0x1a, 0x0a, 0x0c, 0x04, 0x04, 0x02, 0x03};
+static unsigned char times12_122_bits[] = {
+0x0f, 0x09, 0x04, 0x02, 0x09, 0x0f};
+static unsigned char times12_123_bits[] = {
+0x0c, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0c};
+static unsigned char times12_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times12_125_bits[] = {
+0x03, 0x04, 0x04, 0x04, 0x04, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03};
+static unsigned char times12_126_bits[] = {
+0x26, 0x19};
+static unsigned char times12_127_bits[] = {
+0x00};
+static unsigned char times12_128_bits[] = {
+0x00};
+static unsigned char times12_129_bits[] = {
+0x00};
+static unsigned char times12_130_bits[] = {
+0x00};
+static unsigned char times12_131_bits[] = {
+0x00};
+static unsigned char times12_132_bits[] = {
+0x00};
+static unsigned char times12_133_bits[] = {
+0x00};
+static unsigned char times12_134_bits[] = {
+0x00};
+static unsigned char times12_135_bits[] = {
+0x00};
+static unsigned char times12_136_bits[] = {
+0x00};
+static unsigned char times12_137_bits[] = {
+0x00};
+static unsigned char times12_138_bits[] = {
+0x00};
+static unsigned char times12_139_bits[] = {
+0x00};
+static unsigned char times12_140_bits[] = {
+0x00};
+static unsigned char times12_141_bits[] = {
+0x00};
+static unsigned char times12_142_bits[] = {
+0x00};
+static unsigned char times12_143_bits[] = {
+0x00};
+static unsigned char times12_144_bits[] = {
+0x00};
+static unsigned char times12_145_bits[] = {
+0x00};
+static unsigned char times12_146_bits[] = {
+0x00};
+static unsigned char times12_147_bits[] = {
+0x00};
+static unsigned char times12_148_bits[] = {
+0x00};
+static unsigned char times12_149_bits[] = {
+0x00};
+static unsigned char times12_150_bits[] = {
+0x00};
+static unsigned char times12_151_bits[] = {
+0x00};
+static unsigned char times12_152_bits[] = {
+0x00};
+static unsigned char times12_153_bits[] = {
+0x00};
+static unsigned char times12_154_bits[] = {
+0x00};
+static unsigned char times12_155_bits[] = {
+0x00};
+static unsigned char times12_156_bits[] = {
+0x00};
+static unsigned char times12_157_bits[] = {
+0x00};
+static unsigned char times12_158_bits[] = {
+0x00};
+static unsigned char times12_159_bits[] = {
+0x00};
+static unsigned char times12_160_bits[] = {
+0x00};
+static unsigned char times12_161_bits[] = {
+0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times12_162_bits[] = {
+0x10, 0x0e, 0x19, 0x05, 0x05, 0x13, 0x0e, 0x01};
+static unsigned char times12_163_bits[] = {
+0x0c, 0x12, 0x02, 0x02, 0x0f, 0x02, 0x02, 0x17, 0x1b};
+static unsigned char times12_164_bits[] = {
+0x21, 0x1e, 0x12, 0x12, 0x12, 0x1e, 0x21};
+static unsigned char times12_165_bits[] = {
+0x11, 0x11, 0x0a, 0x0a, 0x1f, 0x04, 0x1f, 0x04, 0x0e};
+static unsigned char times12_166_bits[] = {
+0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times12_167_bits[] = {
+0x0e, 0x09, 0x03, 0x06, 0x0d, 0x09, 0x09, 0x0b, 0x06, 0x0c, 0x09, 0x07};
+static unsigned char times12_168_bits[] = {
+0x05};
+static unsigned char times12_169_bits[] = {
+0x38, 0x00, 0xc6, 0x00, 0xba, 0x00, 0x25, 0x01, 0x05, 0x01, 0x25, 0x01, 
+0xba, 0x00, 0xc6, 0x00, 0x38, 0x00};
+static unsigned char times12_170_bits[] = {
+0x03, 0x04, 0x07, 0x05, 0x00, 0x07};
+static unsigned char times12_171_bits[] = {
+0x14, 0x0a, 0x05, 0x0a, 0x14};
+static unsigned char times12_172_bits[] = {
+0x3f, 0x20, 0x20, 0x20};
+static unsigned char times12_173_bits[] = {
+0x0f};
+static unsigned char times12_174_bits[] = {
+0x38, 0x00, 0xc6, 0x00, 0xba, 0x00, 0x49, 0x01, 0x39, 0x01, 0x29, 0x01, 
+0xab, 0x00, 0xc6, 0x00, 0x3c, 0x00};
+static unsigned char times12_175_bits[] = {
+0x0f};
+static unsigned char times12_176_bits[] = {
+0x06, 0x09, 0x09, 0x06};
+static unsigned char times12_177_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x04, 0x00, 0x1f};
+static unsigned char times12_178_bits[] = {
+0x06, 0x09, 0x04, 0x02, 0x0f};
+static unsigned char times12_179_bits[] = {
+0x07, 0x04, 0x02, 0x04, 0x03};
+static unsigned char times12_180_bits[] = {
+0x02, 0x01};
+static unsigned char times12_181_bits[] = {
+0x1b, 0x12, 0x12, 0x12, 0x12, 0x2e, 0x02, 0x02, 0x06};
+static unsigned char times12_182_bits[] = {
+0x3e, 0x17, 0x17, 0x17, 0x17, 0x16, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14};
+static unsigned char times12_183_bits[] = {
+0x01};
+static unsigned char times12_184_bits[] = {
+0x02, 0x04, 0x07};
+static unsigned char times12_185_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x07};
+static unsigned char times12_186_bits[] = {
+0x02, 0x05, 0x05, 0x02, 0x00, 0x07};
+static unsigned char times12_187_bits[] = {
+0x05, 0x0a, 0x14, 0x0a, 0x05};
+static unsigned char times12_188_bits[] = {
+0x42, 0x00, 0x23, 0x00, 0x22, 0x00, 0x12, 0x00, 0x97, 0x00, 0xc8, 0x00, 
+0xa8, 0x00, 0xe4, 0x01, 0x84, 0x00};
+static unsigned char times12_189_bits[] = {
+0x42, 0x00, 0x23, 0x00, 0x22, 0x00, 0x12, 0x00, 0xd7, 0x00, 0x28, 0x01, 
+0x88, 0x00, 0x44, 0x00, 0xe4, 0x01};
+static unsigned char times12_190_bits[] = {
+0x47, 0x00, 0x24, 0x00, 0x22, 0x00, 0x14, 0x00, 0x93, 0x00, 0xc8, 0x00, 
+0xa8, 0x00, 0xe4, 0x01, 0x84, 0x00};
+static unsigned char times12_191_bits[] = {
+0x04, 0x00, 0x04, 0x04, 0x04, 0x02, 0x01, 0x09, 0x06};
+static unsigned char times12_192_bits[] = {
+0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x44, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char times12_193_bits[] = {
+0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x44, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char times12_194_bits[] = {
+0x10, 0x00, 0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x44, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char times12_195_bits[] = {
+0x50, 0x00, 0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x44, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char times12_196_bits[] = {
+0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 0x28, 0x00, 
+0x44, 0x00, 0x7c, 0x00, 0x44, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char times12_197_bits[] = {
+0x10, 0x00, 0x28, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x44, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char times12_198_bits[] = {
+0xfc, 0x03, 0x18, 0x02, 0x14, 0x00, 0x14, 0x01, 0xf2, 0x01, 0x1e, 0x01, 
+0x12, 0x00, 0x11, 0x02, 0xf3, 0x03};
+static unsigned char times12_199_bits[] = {
+0x5c, 0x66, 0x42, 0x01, 0x01, 0x01, 0x42, 0x66, 0x3c, 0x08, 0x10, 0x1c};
+static unsigned char times12_200_bits[] = {
+0x04, 0x08, 0x00, 0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 0x7f};
+static unsigned char times12_201_bits[] = {
+0x10, 0x08, 0x00, 0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 0x7f};
+static unsigned char times12_202_bits[] = {
+0x08, 0x14, 0x00, 0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 0x7f};
+static unsigned char times12_203_bits[] = {
+0x14, 0x00, 0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 0x7f};
+static unsigned char times12_204_bits[] = {
+0x01, 0x02, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_205_bits[] = {
+0x04, 0x02, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_206_bits[] = {
+0x02, 0x05, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_207_bits[] = {
+0x05, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_208_bits[] = {
+0x3f, 0x62, 0x42, 0x82, 0x87, 0x82, 0x42, 0x62, 0x3f};
+static unsigned char times12_209_bits[] = {
+0x50, 0x00, 0x28, 0x00, 0x00, 0x00, 0xc3, 0x01, 0x86, 0x00, 0x86, 0x00, 
+0x8a, 0x00, 0x92, 0x00, 0x92, 0x00, 0xa2, 0x00, 0xc2, 0x00, 0x87, 0x00};
+static unsigned char times12_210_bits[] = {
+0x04, 0x08, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char times12_211_bits[] = {
+0x20, 0x10, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char times12_212_bits[] = {
+0x08, 0x14, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char times12_213_bits[] = {
+0x28, 0x14, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char times12_214_bits[] = {
+0x24, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char times12_215_bits[] = {
+0x11, 0x0a, 0x04, 0x0a, 0x11};
+static unsigned char times12_216_bits[] = {
+0x00, 0x01, 0xbc, 0x00, 0x66, 0x00, 0x62, 0x00, 0x91, 0x00, 0x91, 0x00, 
+0x89, 0x00, 0x46, 0x00, 0x66, 0x00, 0x3d, 0x00};
+static unsigned char times12_217_bits[] = {
+0x08, 0x10, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3c};
+static unsigned char times12_218_bits[] = {
+0x20, 0x10, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3c};
+static unsigned char times12_219_bits[] = {
+0x08, 0x14, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3c};
+static unsigned char times12_220_bits[] = {
+0x24, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3c};
+static unsigned char times12_221_bits[] = {
+0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 
+0x48, 0x00, 0x38, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x38, 0x00};
+static unsigned char times12_222_bits[] = {
+0x07, 0x02, 0x3e, 0x62, 0x42, 0x62, 0x3e, 0x02, 0x07};
+static unsigned char times12_223_bits[] = {
+0x0c, 0x12, 0x12, 0x0a, 0x0e, 0x12, 0x22, 0x22, 0x1b};
+static unsigned char times12_224_bits[] = {
+0x02, 0x04, 0x00, 0x06, 0x09, 0x0e, 0x09, 0x09, 0x16};
+static unsigned char times12_225_bits[] = {
+0x08, 0x04, 0x00, 0x06, 0x09, 0x0e, 0x09, 0x09, 0x16};
+static unsigned char times12_226_bits[] = {
+0x04, 0x0a, 0x00, 0x06, 0x09, 0x0e, 0x09, 0x09, 0x16};
+static unsigned char times12_227_bits[] = {
+0x0a, 0x05, 0x00, 0x06, 0x09, 0x0e, 0x09, 0x09, 0x16};
+static unsigned char times12_228_bits[] = {
+0x0a, 0x00, 0x06, 0x09, 0x0e, 0x09, 0x09, 0x16};
+static unsigned char times12_229_bits[] = {
+0x04, 0x0a, 0x04, 0x06, 0x09, 0x0e, 0x09, 0x09, 0x16};
+static unsigned char times12_230_bits[] = {
+0x36, 0x49, 0x7e, 0x09, 0x99, 0x76};
+static unsigned char times12_231_bits[] = {
+0x06, 0x09, 0x01, 0x01, 0x09, 0x06, 0x02, 0x04, 0x07};
+static unsigned char times12_232_bits[] = {
+0x02, 0x04, 0x00, 0x06, 0x09, 0x0f, 0x01, 0x13, 0x0e};
+static unsigned char times12_233_bits[] = {
+0x04, 0x02, 0x00, 0x06, 0x09, 0x0f, 0x01, 0x13, 0x0e};
+static unsigned char times12_234_bits[] = {
+0x04, 0x0a, 0x00, 0x06, 0x09, 0x0f, 0x01, 0x13, 0x0e};
+static unsigned char times12_235_bits[] = {
+0x0a, 0x00, 0x06, 0x09, 0x0f, 0x01, 0x13, 0x0e};
+static unsigned char times12_236_bits[] = {
+0x01, 0x02, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_237_bits[] = {
+0x02, 0x01, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_238_bits[] = {
+0x02, 0x05, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_239_bits[] = {
+0x05, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_240_bits[] = {
+0x02, 0x0e, 0x05, 0x0e, 0x09, 0x09, 0x09, 0x09, 0x06};
+static unsigned char times12_241_bits[] = {
+0x14, 0x0a, 0x00, 0x0d, 0x12, 0x12, 0x12, 0x12, 0x37};
+static unsigned char times12_242_bits[] = {
+0x02, 0x04, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06};
+static unsigned char times12_243_bits[] = {
+0x04, 0x02, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06};
+static unsigned char times12_244_bits[] = {
+0x04, 0x0a, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06};
+static unsigned char times12_245_bits[] = {
+0x0a, 0x05, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06};
+static unsigned char times12_246_bits[] = {
+0x05, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06};
+static unsigned char times12_247_bits[] = {
+0x04, 0x00, 0x1f, 0x00, 0x04};
+static unsigned char times12_248_bits[] = {
+0x2c, 0x12, 0x12, 0x12, 0x12, 0x0e, 0x01};
+static unsigned char times12_249_bits[] = {
+0x04, 0x08, 0x00, 0x1b, 0x12, 0x12, 0x12, 0x12, 0x2c};
+static unsigned char times12_250_bits[] = {
+0x08, 0x04, 0x00, 0x1b, 0x12, 0x12, 0x12, 0x12, 0x2c};
+static unsigned char times12_251_bits[] = {
+0x04, 0x0a, 0x00, 0x1b, 0x12, 0x12, 0x12, 0x12, 0x2c};
+static unsigned char times12_252_bits[] = {
+0x0a, 0x00, 0x1b, 0x12, 0x12, 0x12, 0x12, 0x2c};
+static unsigned char times12_253_bits[] = {
+0x10, 0x08, 0x00, 0x33, 0x12, 0x1a, 0x0a, 0x0c, 0x04, 0x04, 0x02, 0x03};
+static unsigned char times12_254_bits[] = {
+0x03, 0x02, 0x02, 0x0e, 0x12, 0x12, 0x12, 0x12, 0x0e, 0x02, 0x02, 0x07};
+static unsigned char times12_255_bits[] = {
+0x12, 0x00, 0x33, 0x12, 0x1a, 0x0a, 0x0c, 0x04, 0x04, 0x02, 0x03};
+static RotFont times12font[] = {
+{5, 1, 1, times12_0_bits},
+{5, 1, 1, times12_1_bits},
+{5, 1, 1, times12_2_bits},
+{5, 1, 1, times12_3_bits},
+{5, 1, 1, times12_4_bits},
+{5, 1, 1, times12_5_bits},
+{5, 1, 1, times12_6_bits},
+{5, 1, 1, times12_7_bits},
+{5, 1, 1, times12_8_bits},
+{5, 1, 1, times12_9_bits},
+{5, 1, 1, times12_10_bits},
+{5, 1, 1, times12_11_bits},
+{5, 1, 1, times12_12_bits},
+{5, 1, 1, times12_13_bits},
+{5, 1, 1, times12_14_bits},
+{5, 1, 1, times12_15_bits},
+{5, 1, 1, times12_16_bits},
+{5, 1, 1, times12_17_bits},
+{5, 1, 1, times12_18_bits},
+{5, 1, 1, times12_19_bits},
+{5, 1, 1, times12_20_bits},
+{5, 1, 1, times12_21_bits},
+{5, 1, 1, times12_22_bits},
+{5, 1, 1, times12_23_bits},
+{5, 1, 1, times12_24_bits},
+{5, 1, 1, times12_25_bits},
+{5, 1, 1, times12_26_bits},
+{5, 1, 1, times12_27_bits},
+{5, 1, 1, times12_28_bits},
+{5, 1, 1, times12_29_bits},
+{5, 1, 1, times12_30_bits},
+{5, 1, 1, times12_31_bits},
+{5, 1, 1, times12_32_bits},
+{1, 9, 9, times12_33_bits},
+{3, 3, 9, times12_34_bits},
+{5, 8, 8, times12_35_bits},
+{5, 11, 10, times12_36_bits},
+{8, 9, 9, times12_37_bits},
+{9, 9, 9, times12_38_bits},
+{2, 3, 9, times12_39_bits},
+{3, 12, 9, times12_40_bits},
+{3, 12, 9, times12_41_bits},
+{5, 5, 9, times12_42_bits},
+{5, 5, 6, times12_43_bits},
+{2, 3, 1, times12_44_bits},
+{5, 1, 4, times12_45_bits},
+{1, 1, 1, times12_46_bits},
+{3, 9, 9, times12_47_bits},
+{5, 9, 9, times12_48_bits},
+{4, 9, 9, times12_49_bits},
+{5, 9, 9, times12_50_bits},
+{5, 9, 9, times12_51_bits},
+{5, 9, 9, times12_52_bits},
+{5, 9, 9, times12_53_bits},
+{5, 9, 9, times12_54_bits},
+{5, 9, 9, times12_55_bits},
+{5, 9, 9, times12_56_bits},
+{5, 9, 9, times12_57_bits},
+{1, 6, 6, times12_58_bits},
+{2, 8, 6, times12_59_bits},
+{6, 5, 6, times12_60_bits},
+{5, 3, 5, times12_61_bits},
+{6, 5, 6, times12_62_bits},
+{4, 9, 9, times12_63_bits},
+{10, 11, 9, times12_64_bits},
+{9, 9, 9, times12_65_bits},
+{7, 9, 9, times12_66_bits},
+{7, 9, 9, times12_67_bits},
+{8, 9, 9, times12_68_bits},
+{7, 9, 9, times12_69_bits},
+{7, 9, 9, times12_70_bits},
+{8, 9, 9, times12_71_bits},
+{8, 9, 9, times12_72_bits},
+{3, 9, 9, times12_73_bits},
+{4, 9, 9, times12_74_bits},
+{8, 9, 9, times12_75_bits},
+{6, 9, 9, times12_76_bits},
+{11, 9, 9, times12_77_bits},
+{9, 9, 9, times12_78_bits},
+{8, 9, 9, times12_79_bits},
+{7, 9, 9, times12_80_bits},
+{8, 11, 9, times12_81_bits},
+{8, 9, 9, times12_82_bits},
+{6, 9, 9, times12_83_bits},
+{7, 9, 9, times12_84_bits},
+{8, 9, 9, times12_85_bits},
+{9, 9, 9, times12_86_bits},
+{12, 9, 9, times12_87_bits},
+{8, 9, 9, times12_88_bits},
+{9, 9, 9, times12_89_bits},
+{7, 9, 9, times12_90_bits},
+{3, 12, 9, times12_91_bits},
+{3, 9, 9, times12_92_bits},
+{3, 12, 9, times12_93_bits},
+{5, 5, 9, times12_94_bits},
+{6, 1, -2, times12_95_bits},
+{2, 3, 9, times12_96_bits},
+{5, 6, 6, times12_97_bits},
+{5, 9, 9, times12_98_bits},
+{4, 6, 6, times12_99_bits},
+{5, 9, 9, times12_100_bits},
+{5, 6, 6, times12_101_bits},
+{3, 9, 9, times12_102_bits},
+{5, 9, 6, times12_103_bits},
+{6, 9, 9, times12_104_bits},
+{3, 9, 9, times12_105_bits},
+{2, 12, 9, times12_106_bits},
+{6, 9, 9, times12_107_bits},
+{3, 9, 9, times12_108_bits},
+{9, 6, 6, times12_109_bits},
+{6, 6, 6, times12_110_bits},
+{4, 6, 6, times12_111_bits},
+{5, 9, 6, times12_112_bits},
+{5, 9, 6, times12_113_bits},
+{4, 6, 6, times12_114_bits},
+{4, 6, 6, times12_115_bits},
+{4, 7, 7, times12_116_bits},
+{6, 6, 6, times12_117_bits},
+{6, 6, 6, times12_118_bits},
+{9, 6, 6, times12_119_bits},
+{5, 6, 6, times12_120_bits},
+{6, 9, 6, times12_121_bits},
+{4, 6, 6, times12_122_bits},
+{4, 12, 9, times12_123_bits},
+{1, 9, 9, times12_124_bits},
+{4, 12, 9, times12_125_bits},
+{6, 2, 5, times12_126_bits},
+{5, 1, 1, times12_127_bits},
+{5, 1, 1, times12_128_bits},
+{5, 1, 1, times12_129_bits},
+{5, 1, 1, times12_130_bits},
+{5, 1, 1, times12_131_bits},
+{5, 1, 1, times12_132_bits},
+{5, 1, 1, times12_133_bits},
+{5, 1, 1, times12_134_bits},
+{5, 1, 1, times12_135_bits},
+{5, 1, 1, times12_136_bits},
+{5, 1, 1, times12_137_bits},
+{5, 1, 1, times12_138_bits},
+{5, 1, 1, times12_139_bits},
+{5, 1, 1, times12_140_bits},
+{5, 1, 1, times12_141_bits},
+{5, 1, 1, times12_142_bits},
+{5, 1, 1, times12_143_bits},
+{5, 1, 1, times12_144_bits},
+{5, 1, 1, times12_145_bits},
+{5, 1, 1, times12_146_bits},
+{5, 1, 1, times12_147_bits},
+{5, 1, 1, times12_148_bits},
+{5, 1, 1, times12_149_bits},
+{5, 1, 1, times12_150_bits},
+{5, 1, 1, times12_151_bits},
+{5, 1, 1, times12_152_bits},
+{5, 1, 1, times12_153_bits},
+{5, 1, 1, times12_154_bits},
+{5, 1, 1, times12_155_bits},
+{5, 1, 1, times12_156_bits},
+{5, 1, 1, times12_157_bits},
+{5, 1, 1, times12_158_bits},
+{5, 1, 1, times12_159_bits},
+{1, 1, 1, times12_160_bits},
+{1, 9, 6, times12_161_bits},
+{5, 8, 7, times12_162_bits},
+{5, 9, 9, times12_163_bits},
+{6, 7, 8, times12_164_bits},
+{5, 9, 9, times12_165_bits},
+{1, 9, 9, times12_166_bits},
+{4, 12, 9, times12_167_bits},
+{3, 1, 8, times12_168_bits},
+{9, 9, 9, times12_169_bits},
+{3, 6, 9, times12_170_bits},
+{5, 5, 5, times12_171_bits},
+{6, 4, 5, times12_172_bits},
+{4, 1, 4, times12_173_bits},
+{9, 9, 9, times12_174_bits},
+{4, 1, 8, times12_175_bits},
+{4, 4, 9, times12_176_bits},
+{5, 7, 7, times12_177_bits},
+{4, 5, 9, times12_178_bits},
+{3, 5, 9, times12_179_bits},
+{2, 2, 9, times12_180_bits},
+{6, 9, 6, times12_181_bits},
+{6, 12, 9, times12_182_bits},
+{1, 1, 4, times12_183_bits},
+{3, 3, 0, times12_184_bits},
+{3, 5, 9, times12_185_bits},
+{3, 6, 9, times12_186_bits},
+{5, 5, 5, times12_187_bits},
+{9, 9, 9, times12_188_bits},
+{9, 9, 9, times12_189_bits},
+{9, 9, 9, times12_190_bits},
+{4, 9, 6, times12_191_bits},
+{9, 12, 12, times12_192_bits},
+{9, 12, 12, times12_193_bits},
+{9, 12, 12, times12_194_bits},
+{9, 12, 12, times12_195_bits},
+{9, 11, 11, times12_196_bits},
+{9, 12, 12, times12_197_bits},
+{10, 9, 9, times12_198_bits},
+{7, 12, 9, times12_199_bits},
+{7, 12, 12, times12_200_bits},
+{7, 12, 12, times12_201_bits},
+{7, 12, 12, times12_202_bits},
+{7, 11, 11, times12_203_bits},
+{3, 12, 12, times12_204_bits},
+{3, 12, 12, times12_205_bits},
+{3, 12, 12, times12_206_bits},
+{3, 11, 11, times12_207_bits},
+{8, 9, 9, times12_208_bits},
+{9, 12, 12, times12_209_bits},
+{8, 12, 12, times12_210_bits},
+{8, 12, 12, times12_211_bits},
+{8, 12, 12, times12_212_bits},
+{8, 12, 12, times12_213_bits},
+{8, 11, 11, times12_214_bits},
+{5, 5, 6, times12_215_bits},
+{9, 10, 10, times12_216_bits},
+{8, 12, 12, times12_217_bits},
+{8, 12, 12, times12_218_bits},
+{8, 12, 12, times12_219_bits},
+{8, 11, 11, times12_220_bits},
+{9, 12, 12, times12_221_bits},
+{7, 9, 9, times12_222_bits},
+{6, 9, 9, times12_223_bits},
+{5, 9, 9, times12_224_bits},
+{5, 9, 9, times12_225_bits},
+{5, 9, 9, times12_226_bits},
+{5, 9, 9, times12_227_bits},
+{5, 8, 8, times12_228_bits},
+{5, 9, 9, times12_229_bits},
+{8, 6, 6, times12_230_bits},
+{4, 9, 6, times12_231_bits},
+{5, 9, 9, times12_232_bits},
+{5, 9, 9, times12_233_bits},
+{5, 9, 9, times12_234_bits},
+{5, 8, 8, times12_235_bits},
+{3, 9, 9, times12_236_bits},
+{3, 9, 9, times12_237_bits},
+{3, 9, 9, times12_238_bits},
+{3, 8, 8, times12_239_bits},
+{4, 9, 9, times12_240_bits},
+{6, 9, 9, times12_241_bits},
+{4, 9, 9, times12_242_bits},
+{4, 9, 9, times12_243_bits},
+{4, 9, 9, times12_244_bits},
+{4, 9, 9, times12_245_bits},
+{4, 8, 8, times12_246_bits},
+{5, 5, 6, times12_247_bits},
+{6, 7, 6, times12_248_bits},
+{6, 9, 9, times12_249_bits},
+{6, 9, 9, times12_250_bits},
+{6, 9, 9, times12_251_bits},
+{6, 8, 8, times12_252_bits},
+{6, 12, 9, times12_253_bits},
+{5, 12, 9, times12_254_bits},
+{6, 11, 8, times12_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/times14.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/times14.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/times14.bdf	(revision 12606)
@@ -0,0 +1,3205 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Times-Medium-R-Normal--14-100-100-100-P-74-ISO8859-1
+SIZE 10 100 100
+FONTBOUNDINGBOX 14 17 -1 -3
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Times"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 14
+POINT_SIZE 100
+RESOLUTION_X 100
+RESOLUTION_Y 100
+SPACING "P"
+AVERAGE_WIDTH 74
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 10
+X_HEIGHT 7
+FACE_NAME "Times Roman"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Times is a trademark of Linotype-Hell AG and/or its subsidiaries."
+_DEC_DEVICE_FONTNAMES "PS=Times-Roman"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Times Roman"
+FONT "-Adobe-Times-Medium-R-Normal--14-100-100-100-P-74-ISO8859-1"
+WEIGHT 10
+RESOLUTION 138
+QUAD_WIDTH 8
+DEFAULT_CHAR 32
+FONT_ASCENT 12
+FONT_DESCENT 3
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 1 10 2 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+00
+80
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 3 3 1 7
+BITMAP
+a0
+a0
+a0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+14
+14
+7e
+28
+28
+28
+fc
+50
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 12 1 -1
+BITMAP
+20
+78
+a8
+a0
+a0
+70
+28
+28
+28
+a8
+f0
+20
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 9 10 1 0
+BITMAP
+7180
+df00
+9200
+9400
+6800
+0b00
+1680
+2480
+4480
+4300
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 10 10 1 0
+BITMAP
+1800
+2400
+2400
+3800
+1380
+7900
+ca00
+8400
+ce40
+7380
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 3 1 7
+BITMAP
+c0
+40
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 13 1 -3
+BITMAP
+20
+20
+40
+40
+80
+80
+80
+80
+80
+40
+40
+20
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 13 1 -3
+BITMAP
+80
+80
+40
+40
+20
+20
+20
+20
+20
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 6 1 4
+BITMAP
+20
+a8
+70
+70
+a8
+20
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+10
+10
+10
+fe
+10
+10
+10
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 3 1 -2
+BITMAP
+c0
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 1 1 3
+BITMAP
+fc
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 1 1 0
+BITMAP
+c0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 12 0 -2
+BITMAP
+10
+10
+10
+20
+20
+20
+40
+40
+40
+80
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+78
+cc
+84
+84
+84
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+20
+e0
+20
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+70
+d8
+88
+08
+18
+10
+20
+40
+88
+f8
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+8c
+04
+08
+30
+38
+04
+04
+cc
+78
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+08
+18
+18
+28
+68
+48
+88
+fc
+08
+08
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+78
+40
+80
+e0
+30
+18
+08
+08
+90
+e0
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+0c
+10
+20
+40
+78
+cc
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+fc
+84
+08
+08
+10
+10
+20
+20
+40
+40
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+70
+98
+88
+c8
+70
+98
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+78
+cc
+84
+84
+cc
+78
+08
+10
+20
+c0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 7 1 0
+BITMAP
+c0
+00
+00
+00
+00
+00
+c0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 9 1 -2
+BITMAP
+c0
+00
+00
+00
+00
+00
+c0
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+06
+18
+60
+c0
+60
+18
+06
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 3 0 2
+BITMAP
+fe
+00
+fe
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+c0
+30
+0c
+06
+0c
+30
+c0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 5 10 0 0
+BITMAP
+70
+88
+88
+08
+10
+20
+20
+00
+20
+20
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 936 0
+DWIDTH 13 0
+BBX 12 12 0 -2
+BITMAP
+0f80
+3060
+6020
+4690
+8910
+9110
+9110
+9320
+cdc0
+4000
+30c0
+0f00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+0800
+0800
+1400
+1400
+2200
+2200
+3e00
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+fc
+46
+42
+46
+7c
+46
+42
+42
+46
+fc
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+3d
+63
+41
+81
+80
+80
+80
+c1
+62
+3c
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 9 10 0 0
+BITMAP
+fe00
+2300
+2100
+2080
+2080
+2080
+2080
+2100
+2300
+fe00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+fe
+42
+40
+44
+7c
+44
+40
+42
+42
+fe
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 10 1 0
+BITMAP
+fe
+42
+40
+44
+7c
+44
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+3d00
+6300
+4100
+8100
+8000
+8780
+8100
+c100
+6300
+3e00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+e7
+42
+42
+42
+7e
+42
+42
+42
+42
+e7
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 10 1 0
+BITMAP
+e0
+40
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 4 10 1 0
+BITMAP
+70
+20
+20
+20
+20
+20
+20
+20
+a0
+c0
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+ee
+44
+48
+50
+70
+50
+48
+44
+46
+e7
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+e0
+40
+40
+40
+40
+40
+40
+40
+42
+fe
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 936 0
+DWIDTH 13 0
+BBX 11 10 1 0
+BITMAP
+e0e0
+60c0
+5140
+5140
+5b40
+4a40
+4a40
+4e40
+4440
+e4e0
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+e380
+6100
+5100
+5900
+4900
+4d00
+4500
+4500
+4300
+e300
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+3c
+66
+42
+81
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 10 1 0
+BITMAP
+f8
+4c
+44
+44
+4c
+78
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 13 1 -3
+BITMAP
+3c
+66
+42
+81
+81
+81
+81
+42
+66
+3c
+08
+06
+03
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+fc00
+2600
+2200
+2200
+2600
+3c00
+2400
+2200
+2300
+f180
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 10 1 0
+BITMAP
+74
+cc
+84
+c0
+70
+18
+04
+84
+cc
+b8
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+fe
+92
+92
+10
+10
+10
+10
+10
+10
+38
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+e7
+42
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+e380
+4100
+6300
+2200
+2200
+3600
+1400
+1c00
+0800
+0800
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 936 0
+DWIDTH 13 0
+BBX 13 10 0 0
+BITMAP
+e738
+4210
+6230
+2220
+2520
+3560
+1540
+18c0
+0880
+0880
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 10 10 0 0
+BITMAP
+7380
+2100
+1200
+1200
+0c00
+0c00
+1200
+2100
+6180
+f3c0
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+e380
+4100
+2200
+2200
+1400
+0800
+0800
+0800
+0800
+1c00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 8 10 0 0
+BITMAP
+7f
+43
+02
+04
+08
+10
+20
+40
+c1
+ff
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 13 1 -3
+BITMAP
+e0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+e0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 10 0 0
+BITMAP
+80
+80
+40
+40
+40
+20
+20
+20
+10
+10
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 13 1 -3
+BITMAP
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+e0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 5 1 5
+BITMAP
+20
+50
+50
+88
+88
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 1 0 -3
+BITMAP
+fe
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 3 1 7
+BITMAP
+40
+80
+c0
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 7 1 0
+BITMAP
+70
+c8
+18
+68
+88
+c8
+74
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+c0
+40
+40
+58
+6c
+44
+44
+44
+4c
+78
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 7 1 0
+BITMAP
+78
+cc
+80
+80
+80
+c4
+78
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+18
+08
+08
+78
+c8
+88
+88
+88
+d8
+74
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 7 1 0
+BITMAP
+70
+88
+f8
+80
+80
+c4
+78
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 5 10 0 0
+BITMAP
+38
+60
+40
+f8
+40
+40
+40
+40
+40
+f0
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 1 -3
+BITMAP
+78
+d0
+88
+c8
+70
+40
+78
+84
+cc
+70
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+c0
+40
+40
+58
+6c
+44
+44
+44
+44
+ee
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 3 10 0 0
+BITMAP
+40
+40
+00
+c0
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 3 13 0 -3
+BITMAP
+20
+20
+00
+60
+20
+20
+20
+20
+20
+20
+20
+a0
+c0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+c0
+40
+40
+4c
+48
+70
+50
+48
+4c
+e6
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 3 10 0 0
+BITMAP
+c0
+40
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 11 7 0 0
+BITMAP
+db80
+6ec0
+4440
+4440
+4440
+4440
+eee0
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+d8
+6c
+44
+44
+44
+44
+ee
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+d8
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+d8
+6c
+44
+44
+44
+6c
+58
+40
+40
+e0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 1 -3
+BITMAP
+78
+c8
+88
+88
+88
+d8
+68
+08
+08
+1c
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+b8
+60
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 4 7 1 0
+BITMAP
+70
+90
+c0
+60
+30
+90
+e0
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 8 0 0
+BITMAP
+40
+f0
+40
+40
+40
+40
+40
+30
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+cc
+44
+44
+44
+44
+6c
+36
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+ee
+44
+44
+28
+28
+10
+10
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 11 7 0 0
+BITMAP
+eee0
+4440
+4440
+2480
+3b80
+1100
+1100
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+ee
+44
+38
+10
+38
+44
+ee
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 10 0 -3
+BITMAP
+ee
+44
+44
+28
+28
+10
+30
+20
+a0
+c0
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+fc
+88
+18
+30
+60
+c4
+fc
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+18
+20
+20
+20
+20
+40
+80
+40
+20
+20
+20
+20
+18
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 10 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+c0
+20
+20
+20
+20
+10
+08
+10
+20
+20
+20
+20
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 2 0 3
+BITMAP
+62
+9c
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 1 10 2 -3
+BITMAP
+80
+80
+00
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 9 0 -1
+BITMAP
+04
+7c
+cc
+90
+90
+a0
+e4
+78
+80
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 10 0 0
+BITMAP
+1c
+34
+20
+20
+f8
+20
+20
+20
+e2
+bc
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 7 1 1
+BITMAP
+88
+70
+88
+88
+88
+70
+88
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+ee
+44
+6c
+28
+7c
+10
+7c
+10
+10
+38
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 10 1 0
+BITMAP
+80
+80
+80
+80
+00
+00
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+38
+58
+40
+60
+70
+98
+88
+c8
+70
+30
+10
+d0
+e0
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 2 1 8
+BITMAP
+a0
+a0
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 10 10 1 0
+BITMAP
+1e00
+6180
+4e80
+9240
+9040
+9040
+9240
+4c80
+6180
+1e00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 3 6 0 4
+BITMAP
+e0
+20
+a0
+e0
+00
+e0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 6 0 0
+BITMAP
+24
+48
+90
+90
+48
+24
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 4 1 2
+BITMAP
+fe
+02
+02
+02
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 3 1 0 3
+BITMAP
+e0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 10 10 1 0
+BITMAP
+1e00
+6180
+5c80
+9240
+9c40
+9440
+9240
+5280
+6180
+1e00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 1 0 8
+BITMAP
+f0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 4 4 1 6
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+10
+10
+fe
+10
+10
+00
+fe
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 6 0 4
+BITMAP
+60
+90
+10
+20
+40
+f0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 6 0 4
+BITMAP
+60
+90
+20
+10
+90
+60
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 3 1 8
+BITMAP
+20
+60
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 10 0 -3
+BITMAP
+cc
+44
+44
+44
+44
+6c
+76
+40
+40
+60
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 13 0 -3
+BITMAP
+3e
+74
+f4
+f4
+f4
+74
+34
+14
+14
+14
+14
+14
+14
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 1 2 2 3
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 3 1 -3
+BITMAP
+40
+20
+c0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 3 6 0 4
+BITMAP
+40
+c0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 4 6 0 4
+BITMAP
+60
+90
+90
+60
+00
+f0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 6 1 0
+BITMAP
+90
+48
+24
+24
+48
+90
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 10 10 0 0
+BITMAP
+4100
+c200
+4200
+4400
+4480
+e980
+0a80
+1480
+17c0
+2080
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 10 10 0 0
+BITMAP
+4100
+c200
+4200
+4400
+4580
+ea40
+0840
+1080
+1100
+23c0
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 10 10 0 0
+BITMAP
+6100
+9200
+2200
+1400
+9480
+6980
+0a80
+1480
+17c0
+2080
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 5 10 0 -3
+BITMAP
+20
+20
+00
+20
+20
+40
+80
+88
+88
+70
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+1000
+1800
+0400
+0000
+0800
+0800
+1400
+1400
+2200
+2200
+3e00
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+0400
+0c00
+1000
+0000
+0800
+0800
+1400
+1400
+2200
+2200
+3e00
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+0800
+1c00
+2200
+0000
+0800
+0800
+1400
+1400
+2200
+2200
+3e00
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+1200
+2a00
+2400
+0000
+0800
+0800
+1400
+1400
+2200
+2200
+3e00
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+2400
+2400
+0000
+0800
+0800
+1400
+1400
+2200
+2200
+3e00
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+1800
+2400
+1800
+0000
+0800
+0800
+1400
+1400
+2200
+2200
+3e00
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 936 0
+DWIDTH 13 0
+BBX 11 10 1 0
+BITMAP
+1fe0
+0c20
+1400
+1440
+27c0
+2440
+3c00
+4420
+4420
+efe0
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 13 1 -3
+BITMAP
+3d
+63
+41
+81
+80
+80
+80
+c1
+62
+3c
+08
+04
+18
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+20
+30
+08
+00
+fe
+42
+40
+44
+7c
+44
+40
+42
+42
+fe
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+04
+0c
+10
+00
+fe
+42
+40
+44
+7c
+44
+40
+42
+42
+fe
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+10
+38
+44
+00
+fe
+42
+40
+44
+7c
+44
+40
+42
+42
+fe
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+24
+24
+00
+fe
+42
+40
+44
+7c
+44
+40
+42
+42
+fe
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 14 1 0
+BITMAP
+80
+c0
+20
+00
+e0
+40
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 14 1 0
+BITMAP
+20
+60
+80
+00
+e0
+40
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 5 14 0 0
+BITMAP
+20
+70
+88
+00
+70
+20
+20
+20
+20
+20
+20
+20
+20
+70
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 13 1 0
+BITMAP
+a0
+a0
+00
+e0
+40
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 9 10 0 0
+BITMAP
+fe00
+2300
+2100
+2080
+f880
+2080
+2080
+2100
+2300
+fe00
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+1200
+2a00
+2400
+0000
+e380
+6100
+5100
+5900
+4900
+4d00
+4500
+4500
+4300
+e300
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+20
+30
+08
+00
+3c
+66
+42
+81
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+04
+0c
+10
+00
+3c
+66
+42
+81
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+10
+38
+44
+00
+3c
+66
+42
+81
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+24
+54
+48
+00
+3c
+66
+42
+81
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+24
+24
+00
+3c
+66
+42
+81
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 7 1 0
+BITMAP
+82
+44
+28
+10
+28
+44
+82
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 9 12 0 -1
+BITMAP
+0080
+1f00
+3100
+2300
+4480
+4c80
+4880
+5080
+3100
+6300
+5e00
+8000
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+20
+30
+08
+00
+e7
+42
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+04
+0c
+10
+00
+e7
+42
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+10
+38
+44
+00
+e7
+42
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+24
+24
+00
+e7
+42
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 14 0 0
+BITMAP
+0200
+0600
+0800
+0000
+e380
+4100
+2200
+2200
+1400
+0800
+0800
+0800
+0800
+1c00
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 10 1 0
+BITMAP
+e0
+40
+78
+4c
+44
+44
+4c
+78
+40
+e0
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+38
+6c
+44
+48
+70
+58
+4c
+44
+54
+d8
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+40
+60
+10
+00
+70
+c8
+18
+68
+88
+c8
+74
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+08
+18
+20
+00
+70
+c8
+18
+68
+88
+c8
+74
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+20
+70
+88
+00
+70
+c8
+18
+68
+88
+c8
+74
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+48
+a8
+90
+00
+70
+c8
+18
+68
+88
+c8
+74
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+50
+50
+00
+70
+c8
+18
+68
+88
+c8
+74
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+30
+48
+30
+00
+70
+c8
+18
+68
+88
+c8
+74
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 7 1 0
+BITMAP
+7f00
+c980
+1f00
+6800
+8800
+cc80
+7700
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 1 -3
+BITMAP
+70
+c8
+80
+80
+80
+c4
+78
+20
+10
+60
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+40
+60
+10
+00
+70
+88
+f8
+80
+80
+c4
+78
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+08
+18
+20
+00
+70
+88
+f8
+80
+80
+c4
+78
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+20
+70
+88
+00
+70
+88
+f8
+80
+80
+c4
+78
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+50
+50
+00
+70
+88
+f8
+80
+80
+c4
+78
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 3 11 0 0
+BITMAP
+80
+c0
+20
+00
+c0
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 3 11 0 0
+BITMAP
+20
+60
+80
+00
+c0
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 5 11 -1 0
+BITMAP
+20
+70
+88
+00
+60
+20
+20
+20
+20
+20
+70
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 3 10 0 0
+BITMAP
+a0
+a0
+00
+c0
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+d8
+60
+90
+78
+d8
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+24
+54
+48
+00
+d8
+6c
+44
+44
+44
+44
+ee
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+40
+60
+10
+00
+70
+d8
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+10
+30
+40
+00
+70
+d8
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+20
+70
+88
+00
+70
+d8
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+48
+a8
+90
+00
+70
+d8
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+50
+50
+00
+70
+d8
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 7 1 0
+BITMAP
+10
+10
+00
+fe
+00
+10
+10
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 9 0 -1
+BITMAP
+02
+3c
+6c
+44
+44
+44
+6c
+78
+80
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+20
+30
+08
+00
+cc
+44
+44
+44
+44
+6c
+36
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+08
+18
+20
+00
+cc
+44
+44
+44
+44
+6c
+36
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+10
+38
+44
+00
+cc
+44
+44
+44
+44
+6c
+36
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+28
+28
+00
+cc
+44
+44
+44
+44
+6c
+36
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 14 0 -3
+BITMAP
+04
+0c
+10
+00
+ee
+44
+44
+28
+28
+10
+30
+20
+a0
+c0
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 13 0 -3
+BITMAP
+c0
+40
+40
+58
+6c
+44
+44
+44
+6c
+58
+40
+40
+e0
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 13 0 -3
+BITMAP
+28
+28
+00
+ee
+44
+44
+28
+28
+10
+30
+20
+a0
+c0
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/times14.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/times14.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/times14.h	(revision 12606)
@@ -0,0 +1,840 @@
+static unsigned char times14_0_bits[] = {
+0x00};
+static unsigned char times14_1_bits[] = {
+0x00};
+static unsigned char times14_2_bits[] = {
+0x00};
+static unsigned char times14_3_bits[] = {
+0x00};
+static unsigned char times14_4_bits[] = {
+0x00};
+static unsigned char times14_5_bits[] = {
+0x00};
+static unsigned char times14_6_bits[] = {
+0x00};
+static unsigned char times14_7_bits[] = {
+0x00};
+static unsigned char times14_8_bits[] = {
+0x00};
+static unsigned char times14_9_bits[] = {
+0x00};
+static unsigned char times14_10_bits[] = {
+0x00};
+static unsigned char times14_11_bits[] = {
+0x00};
+static unsigned char times14_12_bits[] = {
+0x00};
+static unsigned char times14_13_bits[] = {
+0x00};
+static unsigned char times14_14_bits[] = {
+0x00};
+static unsigned char times14_15_bits[] = {
+0x00};
+static unsigned char times14_16_bits[] = {
+0x00};
+static unsigned char times14_17_bits[] = {
+0x00};
+static unsigned char times14_18_bits[] = {
+0x00};
+static unsigned char times14_19_bits[] = {
+0x00};
+static unsigned char times14_20_bits[] = {
+0x00};
+static unsigned char times14_21_bits[] = {
+0x00};
+static unsigned char times14_22_bits[] = {
+0x00};
+static unsigned char times14_23_bits[] = {
+0x00};
+static unsigned char times14_24_bits[] = {
+0x00};
+static unsigned char times14_25_bits[] = {
+0x00};
+static unsigned char times14_26_bits[] = {
+0x00};
+static unsigned char times14_27_bits[] = {
+0x00};
+static unsigned char times14_28_bits[] = {
+0x00};
+static unsigned char times14_29_bits[] = {
+0x00};
+static unsigned char times14_30_bits[] = {
+0x00};
+static unsigned char times14_31_bits[] = {
+0x00};
+static unsigned char times14_32_bits[] = {
+0x00};
+static unsigned char times14_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01};
+static unsigned char times14_34_bits[] = {
+0x05, 0x05, 0x05};
+static unsigned char times14_35_bits[] = {
+0x28, 0x28, 0x7e, 0x14, 0x14, 0x14, 0x3f, 0x0a, 0x0a, 0x0a};
+static unsigned char times14_36_bits[] = {
+0x04, 0x1e, 0x15, 0x05, 0x05, 0x0e, 0x14, 0x14, 0x14, 0x15, 0x0f, 0x04};
+static unsigned char times14_37_bits[] = {
+0x8e, 0x01, 0xfb, 0x00, 0x49, 0x00, 0x29, 0x00, 0x16, 0x00, 0xd0, 0x00, 
+0x68, 0x01, 0x24, 0x01, 0x22, 0x01, 0xc2, 0x00};
+static unsigned char times14_38_bits[] = {
+0x18, 0x00, 0x24, 0x00, 0x24, 0x00, 0x1c, 0x00, 0xc8, 0x01, 0x9e, 0x00, 
+0x53, 0x00, 0x21, 0x00, 0x73, 0x02, 0xce, 0x01};
+static unsigned char times14_39_bits[] = {
+0x03, 0x02, 0x01};
+static unsigned char times14_40_bits[] = {
+0x04, 0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x04, 
+0x04};
+static unsigned char times14_41_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01, 
+0x01};
+static unsigned char times14_42_bits[] = {
+0x04, 0x15, 0x0e, 0x0e, 0x15, 0x04};
+static unsigned char times14_43_bits[] = {
+0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08};
+static unsigned char times14_44_bits[] = {
+0x03, 0x02, 0x01};
+static unsigned char times14_45_bits[] = {
+0x3f};
+static unsigned char times14_46_bits[] = {
+0x03};
+static unsigned char times14_47_bits[] = {
+0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01};
+static unsigned char times14_48_bits[] = {
+0x1e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char times14_49_bits[] = {
+0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char times14_50_bits[] = {
+0x0e, 0x1b, 0x11, 0x10, 0x18, 0x08, 0x04, 0x02, 0x11, 0x1f};
+static unsigned char times14_51_bits[] = {
+0x1e, 0x31, 0x20, 0x10, 0x0c, 0x1c, 0x20, 0x20, 0x33, 0x1e};
+static unsigned char times14_52_bits[] = {
+0x10, 0x18, 0x18, 0x14, 0x16, 0x12, 0x11, 0x3f, 0x10, 0x10};
+static unsigned char times14_53_bits[] = {
+0x1e, 0x02, 0x01, 0x07, 0x0c, 0x18, 0x10, 0x10, 0x09, 0x07};
+static unsigned char times14_54_bits[] = {
+0x30, 0x08, 0x04, 0x02, 0x1e, 0x33, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char times14_55_bits[] = {
+0x3f, 0x21, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02};
+static unsigned char times14_56_bits[] = {
+0x0e, 0x19, 0x11, 0x13, 0x0e, 0x19, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char times14_57_bits[] = {
+0x1e, 0x33, 0x21, 0x21, 0x33, 0x1e, 0x10, 0x08, 0x04, 0x03};
+static unsigned char times14_58_bits[] = {
+0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
+static unsigned char times14_59_bits[] = {
+0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01};
+static unsigned char times14_60_bits[] = {
+0x60, 0x18, 0x06, 0x03, 0x06, 0x18, 0x60};
+static unsigned char times14_61_bits[] = {
+0x7f, 0x00, 0x7f};
+static unsigned char times14_62_bits[] = {
+0x03, 0x0c, 0x30, 0x60, 0x30, 0x0c, 0x03};
+static unsigned char times14_63_bits[] = {
+0x0e, 0x11, 0x11, 0x10, 0x08, 0x04, 0x04, 0x00, 0x04, 0x04};
+static unsigned char times14_64_bits[] = {
+0xf0, 0x01, 0x0c, 0x06, 0x06, 0x04, 0x62, 0x09, 0x91, 0x08, 0x89, 0x08, 
+0x89, 0x08, 0xc9, 0x04, 0xb3, 0x03, 0x02, 0x00, 0x0c, 0x03, 0xf0, 0x00};
+static unsigned char times14_65_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 
+0x7c, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char times14_66_bits[] = {
+0x3f, 0x62, 0x42, 0x62, 0x3e, 0x62, 0x42, 0x42, 0x62, 0x3f};
+static unsigned char times14_67_bits[] = {
+0xbc, 0xc6, 0x82, 0x81, 0x01, 0x01, 0x01, 0x83, 0x46, 0x3c};
+static unsigned char times14_68_bits[] = {
+0x7f, 0x00, 0xc4, 0x00, 0x84, 0x00, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 
+0x04, 0x01, 0x84, 0x00, 0xc4, 0x00, 0x7f, 0x00};
+static unsigned char times14_69_bits[] = {
+0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 0x42, 0x7f};
+static unsigned char times14_70_bits[] = {
+0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_71_bits[] = {
+0xbc, 0x00, 0xc6, 0x00, 0x82, 0x00, 0x81, 0x00, 0x01, 0x00, 0xe1, 0x01, 
+0x81, 0x00, 0x83, 0x00, 0xc6, 0x00, 0x7c, 0x00};
+static unsigned char times14_72_bits[] = {
+0xe7, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0xe7};
+static unsigned char times14_73_bits[] = {
+0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_74_bits[] = {
+0x0e, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x03};
+static unsigned char times14_75_bits[] = {
+0x77, 0x22, 0x12, 0x0a, 0x0e, 0x0a, 0x12, 0x22, 0x62, 0xe7};
+static unsigned char times14_76_bits[] = {
+0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x7f};
+static unsigned char times14_77_bits[] = {
+0x07, 0x07, 0x06, 0x03, 0x8a, 0x02, 0x8a, 0x02, 0xda, 0x02, 0x52, 0x02, 
+0x52, 0x02, 0x72, 0x02, 0x22, 0x02, 0x27, 0x07};
+static unsigned char times14_78_bits[] = {
+0xc7, 0x01, 0x86, 0x00, 0x8a, 0x00, 0x9a, 0x00, 0x92, 0x00, 0xb2, 0x00, 
+0xa2, 0x00, 0xa2, 0x00, 0xc2, 0x00, 0xc7, 0x00};
+static unsigned char times14_79_bits[] = {
+0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char times14_80_bits[] = {
+0x1f, 0x32, 0x22, 0x22, 0x32, 0x1e, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_81_bits[] = {
+0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c, 0x10, 0x60, 
+0xc0};
+static unsigned char times14_82_bits[] = {
+0x3f, 0x00, 0x64, 0x00, 0x44, 0x00, 0x44, 0x00, 0x64, 0x00, 0x3c, 0x00, 
+0x24, 0x00, 0x44, 0x00, 0xc4, 0x00, 0x8f, 0x01};
+static unsigned char times14_83_bits[] = {
+0x2e, 0x33, 0x21, 0x03, 0x0e, 0x18, 0x20, 0x21, 0x33, 0x1d};
+static unsigned char times14_84_bits[] = {
+0x7f, 0x49, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c};
+static unsigned char times14_85_bits[] = {
+0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3c};
+static unsigned char times14_86_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0xc6, 0x00, 0x44, 0x00, 0x44, 0x00, 0x6c, 0x00, 
+0x28, 0x00, 0x38, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char times14_87_bits[] = {
+0xe7, 0x1c, 0x42, 0x08, 0x46, 0x0c, 0x44, 0x04, 0xa4, 0x04, 0xac, 0x06, 
+0xa8, 0x02, 0x18, 0x03, 0x10, 0x01, 0x10, 0x01};
+static unsigned char times14_88_bits[] = {
+0xce, 0x01, 0x84, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x48, 0x00, 0x84, 0x00, 0x86, 0x01, 0xcf, 0x03};
+static unsigned char times14_89_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x38, 0x00};
+static unsigned char times14_90_bits[] = {
+0xfe, 0xc2, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x83, 0xff};
+static unsigned char times14_91_bits[] = {
+0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x07};
+static unsigned char times14_92_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08};
+static unsigned char times14_93_bits[] = {
+0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x07};
+static unsigned char times14_94_bits[] = {
+0x04, 0x0a, 0x0a, 0x11, 0x11};
+static unsigned char times14_95_bits[] = {
+0x7f};
+static unsigned char times14_96_bits[] = {
+0x02, 0x01, 0x03};
+static unsigned char times14_97_bits[] = {
+0x0e, 0x13, 0x18, 0x16, 0x11, 0x13, 0x2e};
+static unsigned char times14_98_bits[] = {
+0x03, 0x02, 0x02, 0x1a, 0x36, 0x22, 0x22, 0x22, 0x32, 0x1e};
+static unsigned char times14_99_bits[] = {
+0x1e, 0x33, 0x01, 0x01, 0x01, 0x23, 0x1e};
+static unsigned char times14_100_bits[] = {
+0x18, 0x10, 0x10, 0x1e, 0x13, 0x11, 0x11, 0x11, 0x1b, 0x2e};
+static unsigned char times14_101_bits[] = {
+0x0e, 0x11, 0x1f, 0x01, 0x01, 0x23, 0x1e};
+static unsigned char times14_102_bits[] = {
+0x1c, 0x06, 0x02, 0x1f, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0f};
+static unsigned char times14_103_bits[] = {
+0x1e, 0x0b, 0x11, 0x13, 0x0e, 0x02, 0x1e, 0x21, 0x33, 0x0e};
+static unsigned char times14_104_bits[] = {
+0x03, 0x02, 0x02, 0x1a, 0x36, 0x22, 0x22, 0x22, 0x22, 0x77};
+static unsigned char times14_105_bits[] = {
+0x02, 0x02, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_106_bits[] = {
+0x04, 0x04, 0x00, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 
+0x03};
+static unsigned char times14_107_bits[] = {
+0x03, 0x02, 0x02, 0x32, 0x12, 0x0e, 0x0a, 0x12, 0x32, 0x67};
+static unsigned char times14_108_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_109_bits[] = {
+0xdb, 0x01, 0x76, 0x03, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 
+0x77, 0x07};
+static unsigned char times14_110_bits[] = {
+0x1b, 0x36, 0x22, 0x22, 0x22, 0x22, 0x77};
+static unsigned char times14_111_bits[] = {
+0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char times14_112_bits[] = {
+0x1b, 0x36, 0x22, 0x22, 0x22, 0x36, 0x1a, 0x02, 0x02, 0x07};
+static unsigned char times14_113_bits[] = {
+0x1e, 0x13, 0x11, 0x11, 0x11, 0x1b, 0x16, 0x10, 0x10, 0x38};
+static unsigned char times14_114_bits[] = {
+0x1d, 0x06, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_115_bits[] = {
+0x0e, 0x09, 0x03, 0x06, 0x0c, 0x09, 0x07};
+static unsigned char times14_116_bits[] = {
+0x02, 0x0f, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0c};
+static unsigned char times14_117_bits[] = {
+0x33, 0x22, 0x22, 0x22, 0x22, 0x36, 0x6c};
+static unsigned char times14_118_bits[] = {
+0x77, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08};
+static unsigned char times14_119_bits[] = {
+0x77, 0x07, 0x22, 0x02, 0x22, 0x02, 0x24, 0x01, 0xdc, 0x01, 0x88, 0x00, 
+0x88, 0x00};
+static unsigned char times14_120_bits[] = {
+0x77, 0x22, 0x1c, 0x08, 0x1c, 0x22, 0x77};
+static unsigned char times14_121_bits[] = {
+0x77, 0x22, 0x22, 0x14, 0x14, 0x08, 0x0c, 0x04, 0x05, 0x03};
+static unsigned char times14_122_bits[] = {
+0x3f, 0x11, 0x18, 0x0c, 0x06, 0x23, 0x3f};
+static unsigned char times14_123_bits[] = {
+0x18, 0x04, 0x04, 0x04, 0x04, 0x02, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 
+0x18};
+static unsigned char times14_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times14_125_bits[] = {
+0x03, 0x04, 0x04, 0x04, 0x04, 0x08, 0x10, 0x08, 0x04, 0x04, 0x04, 0x04, 
+0x03};
+static unsigned char times14_126_bits[] = {
+0x46, 0x39};
+static unsigned char times14_127_bits[] = {
+0x00};
+static unsigned char times14_128_bits[] = {
+0x00};
+static unsigned char times14_129_bits[] = {
+0x00};
+static unsigned char times14_130_bits[] = {
+0x00};
+static unsigned char times14_131_bits[] = {
+0x00};
+static unsigned char times14_132_bits[] = {
+0x00};
+static unsigned char times14_133_bits[] = {
+0x00};
+static unsigned char times14_134_bits[] = {
+0x00};
+static unsigned char times14_135_bits[] = {
+0x00};
+static unsigned char times14_136_bits[] = {
+0x00};
+static unsigned char times14_137_bits[] = {
+0x00};
+static unsigned char times14_138_bits[] = {
+0x00};
+static unsigned char times14_139_bits[] = {
+0x00};
+static unsigned char times14_140_bits[] = {
+0x00};
+static unsigned char times14_141_bits[] = {
+0x00};
+static unsigned char times14_142_bits[] = {
+0x00};
+static unsigned char times14_143_bits[] = {
+0x00};
+static unsigned char times14_144_bits[] = {
+0x00};
+static unsigned char times14_145_bits[] = {
+0x00};
+static unsigned char times14_146_bits[] = {
+0x00};
+static unsigned char times14_147_bits[] = {
+0x00};
+static unsigned char times14_148_bits[] = {
+0x00};
+static unsigned char times14_149_bits[] = {
+0x00};
+static unsigned char times14_150_bits[] = {
+0x00};
+static unsigned char times14_151_bits[] = {
+0x00};
+static unsigned char times14_152_bits[] = {
+0x00};
+static unsigned char times14_153_bits[] = {
+0x00};
+static unsigned char times14_154_bits[] = {
+0x00};
+static unsigned char times14_155_bits[] = {
+0x00};
+static unsigned char times14_156_bits[] = {
+0x00};
+static unsigned char times14_157_bits[] = {
+0x00};
+static unsigned char times14_158_bits[] = {
+0x00};
+static unsigned char times14_159_bits[] = {
+0x00};
+static unsigned char times14_160_bits[] = {
+0x00};
+static unsigned char times14_161_bits[] = {
+0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times14_162_bits[] = {
+0x20, 0x3e, 0x33, 0x09, 0x09, 0x05, 0x27, 0x1e, 0x01};
+static unsigned char times14_163_bits[] = {
+0x38, 0x2c, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x04, 0x47, 0x3d};
+static unsigned char times14_164_bits[] = {
+0x11, 0x0e, 0x11, 0x11, 0x11, 0x0e, 0x11};
+static unsigned char times14_165_bits[] = {
+0x77, 0x22, 0x36, 0x14, 0x3e, 0x08, 0x3e, 0x08, 0x08, 0x1c};
+static unsigned char times14_166_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times14_167_bits[] = {
+0x1c, 0x1a, 0x02, 0x06, 0x0e, 0x19, 0x11, 0x13, 0x0e, 0x0c, 0x08, 0x0b, 
+0x07};
+static unsigned char times14_168_bits[] = {
+0x05, 0x05};
+static unsigned char times14_169_bits[] = {
+0x78, 0x00, 0x86, 0x01, 0x72, 0x01, 0x49, 0x02, 0x09, 0x02, 0x09, 0x02, 
+0x49, 0x02, 0x32, 0x01, 0x86, 0x01, 0x78, 0x00};
+static unsigned char times14_170_bits[] = {
+0x07, 0x04, 0x05, 0x07, 0x00, 0x07};
+static unsigned char times14_171_bits[] = {
+0x24, 0x12, 0x09, 0x09, 0x12, 0x24};
+static unsigned char times14_172_bits[] = {
+0x7f, 0x40, 0x40, 0x40};
+static unsigned char times14_173_bits[] = {
+0x07};
+static unsigned char times14_174_bits[] = {
+0x78, 0x00, 0x86, 0x01, 0x3a, 0x01, 0x49, 0x02, 0x39, 0x02, 0x29, 0x02, 
+0x49, 0x02, 0x4a, 0x01, 0x86, 0x01, 0x78, 0x00};
+static unsigned char times14_175_bits[] = {
+0x0f};
+static unsigned char times14_176_bits[] = {
+0x06, 0x09, 0x09, 0x06};
+static unsigned char times14_177_bits[] = {
+0x08, 0x08, 0x7f, 0x08, 0x08, 0x00, 0x7f};
+static unsigned char times14_178_bits[] = {
+0x06, 0x09, 0x08, 0x04, 0x02, 0x0f};
+static unsigned char times14_179_bits[] = {
+0x06, 0x09, 0x04, 0x08, 0x09, 0x06};
+static unsigned char times14_180_bits[] = {
+0x04, 0x06, 0x01};
+static unsigned char times14_181_bits[] = {
+0x33, 0x22, 0x22, 0x22, 0x22, 0x36, 0x6e, 0x02, 0x02, 0x06};
+static unsigned char times14_182_bits[] = {
+0x7c, 0x2e, 0x2f, 0x2f, 0x2f, 0x2e, 0x2c, 0x28, 0x28, 0x28, 0x28, 0x28, 
+0x28};
+static unsigned char times14_183_bits[] = {
+0x01, 0x01};
+static unsigned char times14_184_bits[] = {
+0x02, 0x04, 0x03};
+static unsigned char times14_185_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_186_bits[] = {
+0x06, 0x09, 0x09, 0x06, 0x00, 0x0f};
+static unsigned char times14_187_bits[] = {
+0x09, 0x12, 0x24, 0x24, 0x12, 0x09};
+static unsigned char times14_188_bits[] = {
+0x82, 0x00, 0x43, 0x00, 0x42, 0x00, 0x22, 0x00, 0x22, 0x01, 0x97, 0x01, 
+0x50, 0x01, 0x28, 0x01, 0xe8, 0x03, 0x04, 0x01};
+static unsigned char times14_189_bits[] = {
+0x82, 0x00, 0x43, 0x00, 0x42, 0x00, 0x22, 0x00, 0xa2, 0x01, 0x57, 0x02, 
+0x10, 0x02, 0x08, 0x01, 0x88, 0x00, 0xc4, 0x03};
+static unsigned char times14_190_bits[] = {
+0x86, 0x00, 0x49, 0x00, 0x44, 0x00, 0x28, 0x00, 0x29, 0x01, 0x96, 0x01, 
+0x50, 0x01, 0x28, 0x01, 0xe8, 0x03, 0x04, 0x01};
+static unsigned char times14_191_bits[] = {
+0x04, 0x04, 0x00, 0x04, 0x04, 0x02, 0x01, 0x11, 0x11, 0x0e};
+static unsigned char times14_192_bits[] = {
+0x08, 0x00, 0x18, 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0xc7, 0x01};
+static unsigned char times14_193_bits[] = {
+0x20, 0x00, 0x30, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0xc7, 0x01};
+static unsigned char times14_194_bits[] = {
+0x10, 0x00, 0x38, 0x00, 0x44, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0xc7, 0x01};
+static unsigned char times14_195_bits[] = {
+0x48, 0x00, 0x54, 0x00, 0x24, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0xc7, 0x01};
+static unsigned char times14_196_bits[] = {
+0x24, 0x00, 0x24, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x82, 0x00, 
+0xc7, 0x01};
+static unsigned char times14_197_bits[] = {
+0x18, 0x00, 0x24, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0xc7, 0x01};
+static unsigned char times14_198_bits[] = {
+0xf8, 0x07, 0x30, 0x04, 0x28, 0x00, 0x28, 0x02, 0xe4, 0x03, 0x24, 0x02, 
+0x3c, 0x00, 0x22, 0x04, 0x22, 0x04, 0xf7, 0x07};
+static unsigned char times14_199_bits[] = {
+0xbc, 0xc6, 0x82, 0x81, 0x01, 0x01, 0x01, 0x83, 0x46, 0x3c, 0x10, 0x20, 
+0x18};
+static unsigned char times14_200_bits[] = {
+0x04, 0x0c, 0x10, 0x00, 0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 
+0x42, 0x7f};
+static unsigned char times14_201_bits[] = {
+0x20, 0x30, 0x08, 0x00, 0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 
+0x42, 0x7f};
+static unsigned char times14_202_bits[] = {
+0x08, 0x1c, 0x22, 0x00, 0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 
+0x42, 0x7f};
+static unsigned char times14_203_bits[] = {
+0x24, 0x24, 0x00, 0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 0x42, 
+0x7f};
+static unsigned char times14_204_bits[] = {
+0x01, 0x03, 0x04, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
+0x02, 0x07};
+static unsigned char times14_205_bits[] = {
+0x04, 0x06, 0x01, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
+0x02, 0x07};
+static unsigned char times14_206_bits[] = {
+0x04, 0x0e, 0x11, 0x00, 0x0e, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x0e};
+static unsigned char times14_207_bits[] = {
+0x05, 0x05, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
+0x07};
+static unsigned char times14_208_bits[] = {
+0x7f, 0x00, 0xc4, 0x00, 0x84, 0x00, 0x04, 0x01, 0x1f, 0x01, 0x04, 0x01, 
+0x04, 0x01, 0x84, 0x00, 0xc4, 0x00, 0x7f, 0x00};
+static unsigned char times14_209_bits[] = {
+0x48, 0x00, 0x54, 0x00, 0x24, 0x00, 0x00, 0x00, 0xc7, 0x01, 0x86, 0x00, 
+0x8a, 0x00, 0x9a, 0x00, 0x92, 0x00, 0xb2, 0x00, 0xa2, 0x00, 0xa2, 0x00, 
+0xc2, 0x00, 0xc7, 0x00};
+static unsigned char times14_210_bits[] = {
+0x04, 0x0c, 0x10, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 
+0x66, 0x3c};
+static unsigned char times14_211_bits[] = {
+0x20, 0x30, 0x08, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 
+0x66, 0x3c};
+static unsigned char times14_212_bits[] = {
+0x08, 0x1c, 0x22, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 
+0x66, 0x3c};
+static unsigned char times14_213_bits[] = {
+0x24, 0x2a, 0x12, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 
+0x66, 0x3c};
+static unsigned char times14_214_bits[] = {
+0x24, 0x24, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x66, 
+0x3c};
+static unsigned char times14_215_bits[] = {
+0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41};
+static unsigned char times14_216_bits[] = {
+0x00, 0x01, 0xf8, 0x00, 0x8c, 0x00, 0xc4, 0x00, 0x22, 0x01, 0x32, 0x01, 
+0x12, 0x01, 0x0a, 0x01, 0x8c, 0x00, 0xc6, 0x00, 0x7a, 0x00, 0x01, 0x00};
+static unsigned char times14_217_bits[] = {
+0x04, 0x0c, 0x10, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 
+0x66, 0x3c};
+static unsigned char times14_218_bits[] = {
+0x20, 0x30, 0x08, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 
+0x66, 0x3c};
+static unsigned char times14_219_bits[] = {
+0x08, 0x1c, 0x22, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 
+0x66, 0x3c};
+static unsigned char times14_220_bits[] = {
+0x24, 0x24, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 
+0x3c};
+static unsigned char times14_221_bits[] = {
+0x40, 0x00, 0x60, 0x00, 0x10, 0x00, 0x00, 0x00, 0xc7, 0x01, 0x82, 0x00, 
+0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x38, 0x00};
+static unsigned char times14_222_bits[] = {
+0x07, 0x02, 0x1e, 0x32, 0x22, 0x22, 0x32, 0x1e, 0x02, 0x07};
+static unsigned char times14_223_bits[] = {
+0x1c, 0x36, 0x22, 0x12, 0x0e, 0x1a, 0x32, 0x22, 0x2a, 0x1b};
+static unsigned char times14_224_bits[] = {
+0x02, 0x06, 0x08, 0x00, 0x0e, 0x13, 0x18, 0x16, 0x11, 0x13, 0x2e};
+static unsigned char times14_225_bits[] = {
+0x10, 0x18, 0x04, 0x00, 0x0e, 0x13, 0x18, 0x16, 0x11, 0x13, 0x2e};
+static unsigned char times14_226_bits[] = {
+0x04, 0x0e, 0x11, 0x00, 0x0e, 0x13, 0x18, 0x16, 0x11, 0x13, 0x2e};
+static unsigned char times14_227_bits[] = {
+0x12, 0x15, 0x09, 0x00, 0x0e, 0x13, 0x18, 0x16, 0x11, 0x13, 0x2e};
+static unsigned char times14_228_bits[] = {
+0x0a, 0x0a, 0x00, 0x0e, 0x13, 0x18, 0x16, 0x11, 0x13, 0x2e};
+static unsigned char times14_229_bits[] = {
+0x0c, 0x12, 0x0c, 0x00, 0x0e, 0x13, 0x18, 0x16, 0x11, 0x13, 0x2e};
+static unsigned char times14_230_bits[] = {
+0xfe, 0x00, 0x93, 0x01, 0xf8, 0x00, 0x16, 0x00, 0x11, 0x00, 0x33, 0x01, 
+0xee, 0x00};
+static unsigned char times14_231_bits[] = {
+0x0e, 0x13, 0x01, 0x01, 0x01, 0x23, 0x1e, 0x04, 0x08, 0x06};
+static unsigned char times14_232_bits[] = {
+0x02, 0x06, 0x08, 0x00, 0x0e, 0x11, 0x1f, 0x01, 0x01, 0x23, 0x1e};
+static unsigned char times14_233_bits[] = {
+0x10, 0x18, 0x04, 0x00, 0x0e, 0x11, 0x1f, 0x01, 0x01, 0x23, 0x1e};
+static unsigned char times14_234_bits[] = {
+0x04, 0x0e, 0x11, 0x00, 0x0e, 0x11, 0x1f, 0x01, 0x01, 0x23, 0x1e};
+static unsigned char times14_235_bits[] = {
+0x0a, 0x0a, 0x00, 0x0e, 0x11, 0x1f, 0x01, 0x01, 0x23, 0x1e};
+static unsigned char times14_236_bits[] = {
+0x01, 0x03, 0x04, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_237_bits[] = {
+0x04, 0x06, 0x01, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_238_bits[] = {
+0x04, 0x0e, 0x11, 0x00, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0e};
+static unsigned char times14_239_bits[] = {
+0x05, 0x05, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_240_bits[] = {
+0x1b, 0x06, 0x09, 0x1e, 0x1b, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char times14_241_bits[] = {
+0x24, 0x2a, 0x12, 0x00, 0x1b, 0x36, 0x22, 0x22, 0x22, 0x22, 0x77};
+static unsigned char times14_242_bits[] = {
+0x02, 0x06, 0x08, 0x00, 0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char times14_243_bits[] = {
+0x08, 0x0c, 0x02, 0x00, 0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char times14_244_bits[] = {
+0x04, 0x0e, 0x11, 0x00, 0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char times14_245_bits[] = {
+0x12, 0x15, 0x09, 0x00, 0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char times14_246_bits[] = {
+0x0a, 0x0a, 0x00, 0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char times14_247_bits[] = {
+0x08, 0x08, 0x00, 0x7f, 0x00, 0x08, 0x08};
+static unsigned char times14_248_bits[] = {
+0x40, 0x3c, 0x36, 0x22, 0x22, 0x22, 0x36, 0x1e, 0x01};
+static unsigned char times14_249_bits[] = {
+0x04, 0x0c, 0x10, 0x00, 0x33, 0x22, 0x22, 0x22, 0x22, 0x36, 0x6c};
+static unsigned char times14_250_bits[] = {
+0x10, 0x18, 0x04, 0x00, 0x33, 0x22, 0x22, 0x22, 0x22, 0x36, 0x6c};
+static unsigned char times14_251_bits[] = {
+0x08, 0x1c, 0x22, 0x00, 0x33, 0x22, 0x22, 0x22, 0x22, 0x36, 0x6c};
+static unsigned char times14_252_bits[] = {
+0x14, 0x14, 0x00, 0x33, 0x22, 0x22, 0x22, 0x22, 0x36, 0x6c};
+static unsigned char times14_253_bits[] = {
+0x20, 0x30, 0x08, 0x00, 0x77, 0x22, 0x22, 0x14, 0x14, 0x08, 0x0c, 0x04, 
+0x05, 0x03};
+static unsigned char times14_254_bits[] = {
+0x03, 0x02, 0x02, 0x1a, 0x36, 0x22, 0x22, 0x22, 0x36, 0x1a, 0x02, 0x02, 
+0x07};
+static unsigned char times14_255_bits[] = {
+0x14, 0x14, 0x00, 0x77, 0x22, 0x22, 0x14, 0x14, 0x08, 0x0c, 0x04, 0x05, 
+0x03};
+static RotFont times14font[] = {
+{5, 1, 1, times14_0_bits},
+{5, 1, 1, times14_1_bits},
+{5, 1, 1, times14_2_bits},
+{5, 1, 1, times14_3_bits},
+{5, 1, 1, times14_4_bits},
+{5, 1, 1, times14_5_bits},
+{5, 1, 1, times14_6_bits},
+{5, 1, 1, times14_7_bits},
+{5, 1, 1, times14_8_bits},
+{5, 1, 1, times14_9_bits},
+{5, 1, 1, times14_10_bits},
+{5, 1, 1, times14_11_bits},
+{5, 1, 1, times14_12_bits},
+{5, 1, 1, times14_13_bits},
+{5, 1, 1, times14_14_bits},
+{5, 1, 1, times14_15_bits},
+{5, 1, 1, times14_16_bits},
+{5, 1, 1, times14_17_bits},
+{5, 1, 1, times14_18_bits},
+{5, 1, 1, times14_19_bits},
+{5, 1, 1, times14_20_bits},
+{5, 1, 1, times14_21_bits},
+{5, 1, 1, times14_22_bits},
+{5, 1, 1, times14_23_bits},
+{5, 1, 1, times14_24_bits},
+{5, 1, 1, times14_25_bits},
+{5, 1, 1, times14_26_bits},
+{5, 1, 1, times14_27_bits},
+{5, 1, 1, times14_28_bits},
+{5, 1, 1, times14_29_bits},
+{5, 1, 1, times14_30_bits},
+{5, 1, 1, times14_31_bits},
+{6, 1, 1, times14_32_bits},
+{1, 10, 10, times14_33_bits},
+{3, 3, 10, times14_34_bits},
+{7, 10, 10, times14_35_bits},
+{5, 12, 11, times14_36_bits},
+{9, 10, 10, times14_37_bits},
+{10, 10, 10, times14_38_bits},
+{2, 3, 10, times14_39_bits},
+{3, 13, 10, times14_40_bits},
+{3, 13, 10, times14_41_bits},
+{5, 6, 10, times14_42_bits},
+{7, 7, 7, times14_43_bits},
+{2, 3, 1, times14_44_bits},
+{6, 1, 4, times14_45_bits},
+{2, 1, 1, times14_46_bits},
+{4, 12, 10, times14_47_bits},
+{6, 10, 10, times14_48_bits},
+{5, 10, 10, times14_49_bits},
+{5, 10, 10, times14_50_bits},
+{6, 10, 10, times14_51_bits},
+{6, 10, 10, times14_52_bits},
+{5, 10, 10, times14_53_bits},
+{6, 10, 10, times14_54_bits},
+{6, 10, 10, times14_55_bits},
+{5, 10, 10, times14_56_bits},
+{6, 10, 10, times14_57_bits},
+{2, 7, 7, times14_58_bits},
+{2, 9, 7, times14_59_bits},
+{7, 7, 7, times14_60_bits},
+{7, 3, 5, times14_61_bits},
+{7, 7, 7, times14_62_bits},
+{5, 10, 10, times14_63_bits},
+{12, 12, 10, times14_64_bits},
+{9, 10, 10, times14_65_bits},
+{7, 10, 10, times14_66_bits},
+{8, 10, 10, times14_67_bits},
+{9, 10, 10, times14_68_bits},
+{7, 10, 10, times14_69_bits},
+{7, 10, 10, times14_70_bits},
+{9, 10, 10, times14_71_bits},
+{8, 10, 10, times14_72_bits},
+{3, 10, 10, times14_73_bits},
+{4, 10, 10, times14_74_bits},
+{8, 10, 10, times14_75_bits},
+{7, 10, 10, times14_76_bits},
+{11, 10, 10, times14_77_bits},
+{9, 10, 10, times14_78_bits},
+{8, 10, 10, times14_79_bits},
+{6, 10, 10, times14_80_bits},
+{8, 13, 10, times14_81_bits},
+{9, 10, 10, times14_82_bits},
+{6, 10, 10, times14_83_bits},
+{7, 10, 10, times14_84_bits},
+{8, 10, 10, times14_85_bits},
+{9, 10, 10, times14_86_bits},
+{13, 10, 10, times14_87_bits},
+{10, 10, 10, times14_88_bits},
+{9, 10, 10, times14_89_bits},
+{8, 10, 10, times14_90_bits},
+{3, 13, 10, times14_91_bits},
+{4, 10, 10, times14_92_bits},
+{3, 13, 10, times14_93_bits},
+{5, 5, 10, times14_94_bits},
+{7, 1, -2, times14_95_bits},
+{2, 3, 10, times14_96_bits},
+{6, 7, 7, times14_97_bits},
+{6, 10, 10, times14_98_bits},
+{6, 7, 7, times14_99_bits},
+{6, 10, 10, times14_100_bits},
+{6, 7, 7, times14_101_bits},
+{5, 10, 10, times14_102_bits},
+{6, 10, 7, times14_103_bits},
+{7, 10, 10, times14_104_bits},
+{3, 10, 10, times14_105_bits},
+{3, 13, 10, times14_106_bits},
+{7, 10, 10, times14_107_bits},
+{3, 10, 10, times14_108_bits},
+{11, 7, 7, times14_109_bits},
+{7, 7, 7, times14_110_bits},
+{5, 7, 7, times14_111_bits},
+{6, 10, 7, times14_112_bits},
+{6, 10, 7, times14_113_bits},
+{5, 7, 7, times14_114_bits},
+{4, 7, 7, times14_115_bits},
+{4, 8, 8, times14_116_bits},
+{7, 7, 7, times14_117_bits},
+{7, 7, 7, times14_118_bits},
+{11, 7, 7, times14_119_bits},
+{7, 7, 7, times14_120_bits},
+{7, 10, 7, times14_121_bits},
+{6, 7, 7, times14_122_bits},
+{5, 13, 10, times14_123_bits},
+{1, 10, 10, times14_124_bits},
+{5, 13, 10, times14_125_bits},
+{7, 2, 5, times14_126_bits},
+{5, 1, 1, times14_127_bits},
+{5, 1, 1, times14_128_bits},
+{5, 1, 1, times14_129_bits},
+{5, 1, 1, times14_130_bits},
+{5, 1, 1, times14_131_bits},
+{5, 1, 1, times14_132_bits},
+{5, 1, 1, times14_133_bits},
+{5, 1, 1, times14_134_bits},
+{5, 1, 1, times14_135_bits},
+{5, 1, 1, times14_136_bits},
+{5, 1, 1, times14_137_bits},
+{5, 1, 1, times14_138_bits},
+{5, 1, 1, times14_139_bits},
+{5, 1, 1, times14_140_bits},
+{5, 1, 1, times14_141_bits},
+{5, 1, 1, times14_142_bits},
+{5, 1, 1, times14_143_bits},
+{5, 1, 1, times14_144_bits},
+{5, 1, 1, times14_145_bits},
+{5, 1, 1, times14_146_bits},
+{5, 1, 1, times14_147_bits},
+{5, 1, 1, times14_148_bits},
+{5, 1, 1, times14_149_bits},
+{5, 1, 1, times14_150_bits},
+{5, 1, 1, times14_151_bits},
+{5, 1, 1, times14_152_bits},
+{5, 1, 1, times14_153_bits},
+{5, 1, 1, times14_154_bits},
+{5, 1, 1, times14_155_bits},
+{5, 1, 1, times14_156_bits},
+{5, 1, 1, times14_157_bits},
+{5, 1, 1, times14_158_bits},
+{5, 1, 1, times14_159_bits},
+{1, 1, 1, times14_160_bits},
+{1, 10, 7, times14_161_bits},
+{6, 9, 8, times14_162_bits},
+{7, 10, 10, times14_163_bits},
+{5, 7, 8, times14_164_bits},
+{7, 10, 10, times14_165_bits},
+{1, 10, 10, times14_166_bits},
+{5, 13, 10, times14_167_bits},
+{3, 2, 10, times14_168_bits},
+{10, 10, 10, times14_169_bits},
+{3, 6, 10, times14_170_bits},
+{6, 6, 6, times14_171_bits},
+{7, 4, 6, times14_172_bits},
+{3, 1, 4, times14_173_bits},
+{10, 10, 10, times14_174_bits},
+{4, 1, 9, times14_175_bits},
+{4, 4, 10, times14_176_bits},
+{7, 7, 7, times14_177_bits},
+{4, 6, 10, times14_178_bits},
+{4, 6, 10, times14_179_bits},
+{3, 3, 11, times14_180_bits},
+{7, 10, 7, times14_181_bits},
+{7, 13, 10, times14_182_bits},
+{1, 2, 5, times14_183_bits},
+{3, 3, 0, times14_184_bits},
+{3, 6, 10, times14_185_bits},
+{4, 6, 10, times14_186_bits},
+{6, 6, 6, times14_187_bits},
+{10, 10, 10, times14_188_bits},
+{10, 10, 10, times14_189_bits},
+{10, 10, 10, times14_190_bits},
+{5, 10, 7, times14_191_bits},
+{9, 14, 14, times14_192_bits},
+{9, 14, 14, times14_193_bits},
+{9, 14, 14, times14_194_bits},
+{9, 14, 14, times14_195_bits},
+{9, 13, 13, times14_196_bits},
+{9, 14, 14, times14_197_bits},
+{11, 10, 10, times14_198_bits},
+{8, 13, 10, times14_199_bits},
+{7, 14, 14, times14_200_bits},
+{7, 14, 14, times14_201_bits},
+{7, 14, 14, times14_202_bits},
+{7, 13, 13, times14_203_bits},
+{3, 14, 14, times14_204_bits},
+{3, 14, 14, times14_205_bits},
+{5, 14, 14, times14_206_bits},
+{3, 13, 13, times14_207_bits},
+{9, 10, 10, times14_208_bits},
+{9, 14, 14, times14_209_bits},
+{8, 14, 14, times14_210_bits},
+{8, 14, 14, times14_211_bits},
+{8, 14, 14, times14_212_bits},
+{8, 14, 14, times14_213_bits},
+{8, 13, 13, times14_214_bits},
+{7, 7, 7, times14_215_bits},
+{9, 12, 11, times14_216_bits},
+{8, 14, 14, times14_217_bits},
+{8, 14, 14, times14_218_bits},
+{8, 14, 14, times14_219_bits},
+{8, 13, 13, times14_220_bits},
+{9, 14, 14, times14_221_bits},
+{6, 10, 10, times14_222_bits},
+{6, 10, 10, times14_223_bits},
+{6, 11, 11, times14_224_bits},
+{6, 11, 11, times14_225_bits},
+{6, 11, 11, times14_226_bits},
+{6, 11, 11, times14_227_bits},
+{6, 10, 10, times14_228_bits},
+{6, 11, 11, times14_229_bits},
+{9, 7, 7, times14_230_bits},
+{6, 10, 7, times14_231_bits},
+{6, 11, 11, times14_232_bits},
+{6, 11, 11, times14_233_bits},
+{6, 11, 11, times14_234_bits},
+{6, 10, 10, times14_235_bits},
+{3, 11, 11, times14_236_bits},
+{3, 11, 11, times14_237_bits},
+{5, 11, 11, times14_238_bits},
+{3, 10, 10, times14_239_bits},
+{5, 10, 10, times14_240_bits},
+{7, 11, 11, times14_241_bits},
+{5, 11, 11, times14_242_bits},
+{5, 11, 11, times14_243_bits},
+{5, 11, 11, times14_244_bits},
+{5, 11, 11, times14_245_bits},
+{5, 10, 10, times14_246_bits},
+{7, 7, 7, times14_247_bits},
+{7, 9, 8, times14_248_bits},
+{7, 11, 11, times14_249_bits},
+{7, 11, 11, times14_250_bits},
+{7, 11, 11, times14_251_bits},
+{7, 10, 10, times14_252_bits},
+{7, 14, 11, times14_253_bits},
+{6, 13, 10, times14_254_bits},
+{7, 13, 10, times14_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/times18.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/times18.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/times18.bdf	(revision 12606)
@@ -0,0 +1,3675 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Times-Medium-R-Normal--18-180-75-75-P-94-ISO8859-1
+SIZE 18 75 75
+FONTBOUNDINGBOX 19 21 -1 -4
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Times"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 18
+POINT_SIZE 180
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 94
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 13
+X_HEIGHT 9
+FACE_NAME "Times Roman"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Times is a trademark of Linotype-Hell AG and/or its subsidiaries."
+_DEC_DEVICE_FONTNAMES "PS=Times-Roman"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2-1, 22-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Times Roman"
+FONT "-Adobe-Times-Medium-R-Normal--18-180-75-75-P-94-ISO8859-1"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 10
+DEFAULT_CHAR 32
+FONT_ASCENT 15
+FONT_DESCENT 4
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 1 1 1 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 13 1 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+40
+40
+40
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 6 4 1 9
+BITMAP
+cc
+cc
+cc
+88
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 11 13 -1 0
+BITMAP
+0d80
+0d80
+0d80
+0d80
+7fe0
+1b00
+1b00
+1b00
+ffc0
+3600
+3600
+3600
+3600
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 16 1 -2
+BITMAP
+10
+7c
+d6
+d2
+d0
+f0
+78
+3c
+1c
+16
+16
+96
+d6
+7c
+10
+10
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+3830
+6fe0
+c440
+c480
+cd80
+fb00
+7270
+06d8
+0d88
+0988
+1998
+31f0
+20e0
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+1c00
+3200
+3200
+3200
+3400
+19e0
+38c0
+6d80
+cf00
+c700
+c780
+edf0
+78e0
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 3 4 1 9
+BITMAP
+c0
+e0
+20
+40
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 17 1 -4
+BITMAP
+18
+30
+60
+60
+40
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+40
+60
+60
+30
+18
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 17 1 -4
+BITMAP
+c0
+60
+30
+30
+10
+18
+18
+18
+18
+18
+18
+18
+10
+30
+30
+60
+c0
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 8 1 6
+BITMAP
+10
+10
+d6
+54
+38
+d6
+92
+10
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 9 1 0
+BITMAP
+0800
+0800
+0800
+0800
+ff80
+0800
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 3 5 0 -3
+BITMAP
+60
+60
+20
+60
+c0
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 1 1 4
+BITMAP
+ff
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 2 1 0
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 15 0 -2
+BITMAP
+08
+08
+18
+10
+10
+30
+20
+20
+60
+40
+40
+c0
+80
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+3c
+66
+42
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+42
+66
+3c
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 6 13 2 0
+BITMAP
+30
+70
+f0
+30
+30
+30
+30
+30
+30
+30
+30
+78
+fc
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+3c
+7e
+ce
+86
+06
+06
+0c
+0c
+18
+30
+62
+fe
+fe
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+7c
+ce
+86
+06
+0c
+38
+3c
+0e
+06
+06
+06
+cc
+f8
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+06
+0e
+0e
+16
+26
+66
+46
+86
+ff
+ff
+06
+06
+06
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+7e
+7c
+c0
+c0
+f0
+3c
+0c
+0e
+06
+06
+0c
+dc
+f0
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+07
+1c
+30
+60
+60
+fc
+c6
+c3
+c3
+c3
+e3
+76
+3c
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+fe
+fe
+84
+0c
+08
+18
+18
+10
+30
+30
+20
+60
+60
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+3c
+66
+62
+62
+74
+3c
+3c
+6e
+c7
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+3c
+6e
+c6
+c3
+c3
+c3
+e3
+7f
+06
+06
+0c
+38
+e0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 9 1 0
+BITMAP
+c0
+c0
+00
+00
+00
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 3 12 0 -3
+BITMAP
+60
+60
+00
+00
+00
+00
+00
+60
+60
+20
+60
+c0
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+0180
+0700
+1c00
+7000
+c000
+7000
+1c00
+0700
+0180
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 3 1 3
+BITMAP
+ff
+00
+ff
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+c000
+7000
+1c00
+0700
+0180
+0700
+1c00
+7000
+c000
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 6 13 1 0
+BITMAP
+78
+8c
+c4
+cc
+0c
+18
+18
+30
+20
+20
+00
+30
+30
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 906 0
+DWIDTH 17 0
+BBX 14 16 1 -3
+BITMAP
+07e0
+0e30
+3818
+3008
+63ec
+67e4
+c664
+cc64
+cccc
+ccc8
+cdd8
+6770
+6000
+3000
+1c30
+07e0
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+0200
+0700
+0700
+0500
+0d80
+0980
+19c0
+10c0
+1fc0
+30e0
+2060
+6070
+f0f8
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 13 1 0
+BITMAP
+ff00
+6380
+6180
+6180
+6180
+6300
+7f80
+61c0
+60c0
+60c0
+60c0
+6180
+ff00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 11 13 1 0
+BITMAP
+0f20
+30e0
+6060
+6020
+c000
+c000
+c000
+c000
+c000
+6000
+6060
+38c0
+0f00
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+ff00
+6380
+60c0
+60c0
+6060
+6060
+6060
+6060
+6060
+60c0
+60c0
+6380
+ff00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+ff80
+6180
+6080
+6000
+6000
+6100
+7f00
+6100
+6000
+6000
+6080
+6180
+ff80
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+ff80
+6180
+6080
+6000
+6000
+6100
+7f00
+6100
+6000
+6000
+6000
+6000
+f000
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+0f20
+30e0
+6060
+6020
+c000
+c000
+c0f0
+c060
+c060
+6060
+6060
+39c0
+0f00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+f1e0
+60c0
+60c0
+60c0
+60c0
+60c0
+7fc0
+60c0
+60c0
+60c0
+60c0
+60c0
+f1e0
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 13 1 0
+BITMAP
+f0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 6 13 0 0
+BITMAP
+3c
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+d8
+f0
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+f3c0
+6180
+6300
+6600
+6c00
+7800
+7800
+6c00
+6600
+6300
+6380
+61c0
+f0e0
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 13 1 0
+BITMAP
+f000
+6000
+6000
+6000
+6000
+6000
+6000
+6000
+6000
+6000
+6040
+60c0
+ffc0
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 853 0
+DWIDTH 16 0
+BBX 14 13 1 0
+BITMAP
+e01c
+7038
+7038
+7878
+5858
+58d8
+5cd8
+4c98
+4d98
+4718
+4718
+4218
+e23c
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+e0e0
+6040
+7040
+7840
+5840
+4c40
+4e40
+4740
+4340
+41c0
+41c0
+40c0
+e040
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+0f00
+30c0
+6060
+6060
+c030
+c030
+c030
+c030
+c030
+6060
+6060
+30c0
+0f00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 13 1 0
+BITMAP
+ff00
+6380
+6180
+6180
+6180
+6300
+7e00
+6000
+6000
+6000
+6000
+6000
+f000
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 17 1 -4
+BITMAP
+0f00
+30c0
+6060
+6060
+c030
+c030
+c030
+c030
+c030
+6060
+6060
+30c0
+0f00
+0600
+0300
+01c0
+00f0
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 11 13 1 0
+BITMAP
+ff00
+6380
+6180
+6180
+6180
+6300
+7e00
+6600
+6300
+6180
+6180
+60c0
+f0e0
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3a
+66
+c2
+c0
+e0
+78
+3c
+0e
+07
+03
+83
+c6
+bc
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 13 1 0
+BITMAP
+ffc0
+ccc0
+8c40
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+1e00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+f0e0
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+70c0
+3980
+1f00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 13 13 0 0
+BITMAP
+f878
+7030
+3020
+3820
+1860
+1840
+1c40
+0cc0
+0e80
+0680
+0780
+0300
+0300
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 18 13 0 0
+BITMAP
+f9e3c0
+30c180
+30c100
+18c100
+186300
+186200
+1ce200
+0ca600
+0cb400
+0d3400
+073c00
+061800
+061800
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 13 0 0
+BITMAP
+f070
+7060
+38c0
+1980
+0d00
+0e00
+0600
+0f00
+1b00
+1180
+31c0
+60e0
+f0f0
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 13 0 0
+BITMAP
+f0f0
+7060
+30c0
+1880
+1900
+0f00
+0600
+0600
+0600
+0600
+0600
+0600
+0f00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 13 1 0
+BITMAP
+7fc0
+61c0
+4180
+0380
+0700
+0600
+0e00
+1c00
+3800
+3000
+7040
+e0c0
+ffc0
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 16 2 -3
+BITMAP
+f0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+f0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 13 0 0
+BITMAP
+80
+80
+c0
+40
+60
+60
+20
+30
+30
+10
+18
+08
+08
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 16 0 -3
+BITMAP
+f0
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+f0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 7 1 6
+BITMAP
+10
+38
+28
+6c
+44
+c6
+82
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 1 0 -4
+BITMAP
+ff80
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 3 4 1 9
+BITMAP
+40
+80
+e0
+60
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+78
+cc
+cc
+1c
+6c
+cc
+cc
+fc
+66
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+e0
+60
+60
+60
+6e
+77
+63
+63
+63
+63
+63
+76
+3c
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+3c
+66
+c6
+c0
+c0
+c0
+c0
+62
+3c
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+0e
+06
+06
+06
+3e
+66
+c6
+c6
+c6
+c6
+c6
+66
+3f
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+3c
+66
+c3
+ff
+c0
+c0
+e1
+76
+3c
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 13 0 0
+BITMAP
+1c
+34
+20
+60
+f8
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 8 13 0 -4
+BITMAP
+3e
+cc
+c4
+c4
+cc
+78
+40
+7c
+7f
+83
+c1
+e2
+7c
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 13 0 0
+BITMAP
+e000
+6000
+6000
+6000
+6600
+6f00
+7300
+6300
+6300
+6300
+6300
+6300
+f380
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 4 13 0 0
+BITMAP
+60
+60
+00
+00
+e0
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 4 17 -1 -4
+BITMAP
+30
+30
+00
+00
+70
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+e0
+c0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 13 0 0
+BITMAP
+e000
+6000
+6000
+6000
+6700
+6200
+6400
+6800
+7800
+6c00
+6600
+6300
+e380
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 4 13 0 0
+BITMAP
+e0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 14 9 0 0
+BITMAP
+e630
+6f78
+7398
+6318
+6318
+6318
+6318
+6318
+f7bc
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+e600
+6f00
+7300
+6300
+6300
+6300
+6300
+6300
+f380
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3c
+66
+c3
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 -4
+BITMAP
+ee
+77
+63
+63
+63
+63
+63
+76
+6c
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 -4
+BITMAP
+3e
+66
+c6
+c6
+c6
+c6
+c6
+66
+3e
+06
+06
+06
+0f
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+ec
+6c
+70
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 9 0 0
+BITMAP
+68
+d8
+c8
+e0
+70
+38
+98
+d8
+b0
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 11 0 0
+BITMAP
+20
+60
+f8
+60
+60
+60
+60
+60
+60
+74
+38
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 9 -1 0
+BITMAP
+e700
+6300
+6300
+6300
+6300
+6300
+6300
+7700
+3b80
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 9 -1 0
+BITMAP
+f380
+6300
+6200
+3200
+3600
+1400
+1c00
+0800
+0800
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 13 9 -1 0
+BITMAP
+e738
+6630
+6260
+3660
+3760
+1d40
+1dc0
+0880
+0880
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+e380
+6300
+3600
+1c00
+0c00
+1c00
+3600
+6300
+e380
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 9 13 -1 -4
+BITMAP
+f380
+6100
+7300
+3200
+3600
+1c00
+1c00
+0c00
+1800
+1800
+1000
+f000
+e000
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+fe
+ce
+8c
+18
+30
+30
+62
+e6
+fe
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 17 1 -4
+BITMAP
+0e
+18
+30
+30
+30
+30
+30
+60
+c0
+60
+30
+30
+30
+30
+30
+18
+0e
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 160 0
+DWIDTH 3 0
+BBX 1 13 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 17 1 -4
+BITMAP
+e0
+30
+18
+18
+18
+18
+18
+0c
+06
+0c
+18
+18
+18
+18
+18
+30
+e0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 2 1 4
+BITMAP
+7980
+cf00
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 1 1 1 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 13 1 -4
+BITMAP
+c0
+c0
+00
+00
+80
+80
+80
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 1 -2
+BITMAP
+06
+04
+3e
+6b
+cb
+c8
+d8
+d0
+d0
+72
+7c
+40
+c0
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 13 0 0
+BITMAP
+0f00
+1980
+1980
+1800
+1800
+1800
+7e00
+1800
+1800
+1000
+7840
+bfc0
+e780
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 7 1 3
+BITMAP
+dd80
+f780
+6300
+4100
+6300
+f780
+dd80
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+f7
+62
+62
+76
+34
+34
+7e
+18
+7e
+18
+18
+18
+7e
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 160 0
+DWIDTH 3 0
+BBX 1 13 1 0
+BITMAP
+80
+80
+80
+80
+80
+00
+00
+00
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 16 1 -3
+BITMAP
+3c
+66
+66
+70
+38
+7c
+8e
+c7
+e3
+71
+3e
+1c
+0e
+66
+66
+3c
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 2 0 10
+BITMAP
+d8
+d8
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+0f80
+3060
+4010
+4790
+8888
+9008
+9008
+9008
+8888
+4710
+4010
+3060
+0f80
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 8 0 5
+BITMAP
+60
+90
+10
+70
+90
+e8
+00
+f8
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 7 1 1
+BITMAP
+11
+33
+66
+cc
+66
+33
+11
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 5 1 1
+BITMAP
+ff80
+0080
+0080
+0080
+0080
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 2 0 4
+BITMAP
+f8
+f8
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+0f80
+3060
+4010
+5f10
+8888
+8888
+8f08
+8908
+8888
+5cd0
+4010
+3060
+0f80
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 1 0 11
+BITMAP
+f8
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 5 1 8
+BITMAP
+70
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 10 1 0
+BITMAP
+0800
+0800
+0800
+0800
+ff80
+0800
+0800
+0800
+0000
+ff80
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 8 0 5
+BITMAP
+70
+98
+18
+10
+20
+20
+40
+f8
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 8 0 5
+BITMAP
+70
+88
+18
+70
+18
+08
+88
+70
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 4 3 0 10
+BITMAP
+30
+60
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 13 0 -4
+BITMAP
+e700
+6300
+6300
+6300
+6300
+6300
+6300
+7700
+7b80
+4000
+4000
+6000
+6000
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 17 1 -4
+BITMAP
+3e
+74
+f4
+f4
+f4
+f4
+f4
+74
+14
+14
+14
+14
+14
+14
+14
+14
+14
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 2 1 4
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 5 1 -4
+BITMAP
+20
+20
+10
+b0
+60
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 3 8 1 5
+BITMAP
+40
+c0
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 8 0 5
+BITMAP
+70
+d8
+88
+88
+d8
+70
+00
+f8
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 7 1 1
+BITMAP
+88
+cc
+66
+33
+66
+cc
+88
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+4080
+c180
+4100
+4300
+4600
+4440
+4cc0
+e940
+1b40
+3240
+27e0
+6040
+4040
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+4080
+c180
+4100
+4300
+4600
+45c0
+4e60
+e860
+1840
+3080
+2080
+6100
+43e0
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 13 13 -1 0
+BITMAP
+7020
+8860
+1840
+70c0
+1980
+0910
+8b30
+7250
+06d0
+0c90
+09f8
+1810
+1010
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 6 13 1 -4
+BITMAP
+30
+30
+00
+10
+10
+30
+60
+60
+c0
+cc
+8c
+c4
+78
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+0c00
+0600
+0100
+0000
+0200
+0700
+0700
+0500
+0d80
+0980
+19c0
+10c0
+1fc0
+30e0
+2060
+6070
+f0f8
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+00c0
+0180
+0200
+0000
+0200
+0700
+0700
+0500
+0d80
+0980
+19c0
+10c0
+1fc0
+30e0
+2060
+6070
+f0f8
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+0200
+0700
+0880
+0000
+0200
+0700
+0700
+0500
+0d80
+0980
+19c0
+10c0
+1fc0
+30e0
+2060
+6070
+f0f8
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 16 1 0
+BITMAP
+0740
+0b80
+0000
+0200
+0700
+0700
+0500
+0d80
+0980
+19c0
+10c0
+1fc0
+30e0
+2060
+6070
+f0f8
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 16 1 0
+BITMAP
+0d80
+0d80
+0000
+0200
+0700
+0700
+0500
+0d80
+0980
+19c0
+10c0
+1fc0
+30e0
+2060
+6070
+f0f8
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+0300
+0480
+0480
+0300
+0200
+0700
+0700
+0500
+0d80
+0980
+19c0
+10c0
+1fc0
+30e0
+2060
+6070
+f0f8
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 906 0
+DWIDTH 17 0
+BBX 15 13 1 0
+BITMAP
+0ffc
+078c
+0584
+0580
+0d80
+0988
+19f8
+1f88
+1180
+3180
+2182
+6186
+f7fe
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 11 17 1 -4
+BITMAP
+0f20
+30e0
+6060
+6020
+c000
+c000
+c000
+c000
+c000
+6000
+6060
+38c0
+0f00
+0400
+0200
+1600
+0c00
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+3000
+1800
+0400
+0000
+ff80
+6180
+6080
+6000
+6000
+6100
+7f00
+6100
+6000
+6000
+6080
+6180
+ff80
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+0600
+0c00
+1000
+0000
+ff80
+6180
+6080
+6000
+6000
+6100
+7f00
+6100
+6000
+6000
+6080
+6180
+ff80
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+0800
+1c00
+2200
+0000
+ff80
+6180
+6080
+6000
+6000
+6100
+7f00
+6100
+6000
+6000
+6080
+6180
+ff80
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 16 1 0
+BITMAP
+3300
+3300
+0000
+ff80
+6180
+6080
+6000
+6000
+6100
+7f00
+6100
+6000
+6000
+6080
+6180
+ff80
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 17 1 0
+BITMAP
+c0
+60
+10
+00
+f0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 17 1 0
+BITMAP
+30
+60
+80
+00
+f0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 17 1 0
+BITMAP
+20
+70
+88
+00
+f0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 16 0 0
+BITMAP
+cc
+cc
+00
+78
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+78
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 13 0 0
+BITMAP
+7f80
+31c0
+3060
+3060
+3030
+3030
+fc30
+3030
+3030
+3060
+3060
+31c0
+7f80
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 16 1 0
+BITMAP
+0e80
+1700
+0000
+e0e0
+6040
+7040
+7840
+5840
+4c40
+4e40
+4740
+4340
+41c0
+41c0
+40c0
+e040
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 17 1 0
+BITMAP
+1800
+0c00
+0200
+0000
+0f00
+30c0
+6060
+6060
+c030
+c030
+c030
+c030
+c030
+6060
+6060
+30c0
+0f00
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 17 1 0
+BITMAP
+00c0
+0180
+0200
+0000
+0f00
+30c0
+6060
+6060
+c030
+c030
+c030
+c030
+c030
+6060
+6060
+30c0
+0f00
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 17 1 0
+BITMAP
+0200
+0700
+0880
+0000
+0f00
+30c0
+6060
+6060
+c030
+c030
+c030
+c030
+c030
+6060
+6060
+30c0
+0f00
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 16 1 0
+BITMAP
+0e80
+1700
+0000
+0f00
+30c0
+6060
+6060
+c030
+c030
+c030
+c030
+c030
+6060
+6060
+30c0
+0f00
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 16 1 0
+BITMAP
+1980
+1980
+0000
+0f00
+30c0
+6060
+6060
+c030
+c030
+c030
+c030
+c030
+6060
+6060
+30c0
+0f00
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 7 1 1
+BITMAP
+c3
+66
+3c
+18
+3c
+66
+c3
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 15 1 -1
+BITMAP
+0030
+0f60
+30c0
+60e0
+61a0
+c330
+c330
+c630
+cc30
+cc30
+5860
+7060
+30c0
+6f00
+c000
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+1800
+0c00
+0200
+0000
+f0e0
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+70c0
+3980
+1f00
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+0180
+0300
+0400
+0000
+f0e0
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+70c0
+3980
+1f00
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+0400
+0e00
+1100
+0000
+f0e0
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+70c0
+3980
+1f00
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 16 1 0
+BITMAP
+1980
+1980
+0000
+f0e0
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+70c0
+3980
+1f00
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 17 0 0
+BITMAP
+0180
+0300
+0400
+0000
+f0f0
+7060
+30c0
+1880
+1900
+0f00
+0600
+0600
+0600
+0600
+0600
+0600
+0f00
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 13 1 0
+BITMAP
+f000
+6000
+6000
+7f00
+6380
+6180
+6180
+6180
+6300
+7e00
+6000
+6000
+f000
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+1c
+36
+23
+63
+63
+66
+7c
+66
+63
+63
+6b
+6b
+ee
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+c0
+60
+10
+00
+78
+c8
+cc
+1c
+6c
+cc
+cc
+fc
+66
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+0c
+18
+20
+00
+78
+c8
+cc
+1c
+6c
+cc
+cc
+fc
+66
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+10
+38
+44
+00
+78
+c8
+cc
+1c
+6c
+cc
+cc
+fc
+66
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+34
+58
+00
+78
+c8
+cc
+1c
+6c
+cc
+cc
+fc
+66
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+6c
+6c
+00
+78
+c8
+cc
+1c
+6c
+cc
+cc
+fc
+66
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+30
+48
+48
+30
+78
+c8
+cc
+1c
+6c
+cc
+cc
+fc
+66
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 11 9 0 0
+BITMAP
+7bc0
+ce60
+cc20
+1fe0
+6c00
+cc00
+cc00
+fe60
+63c0
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 13 0 -4
+BITMAP
+3c
+66
+c0
+c0
+c0
+c0
+c0
+66
+3c
+10
+08
+58
+30
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 13 0 0
+BITMAP
+60
+30
+08
+00
+3c
+66
+c2
+fe
+c0
+c0
+c0
+66
+3c
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 13 0 0
+BITMAP
+06
+0c
+10
+00
+3c
+66
+c2
+fe
+c0
+c0
+c0
+66
+3c
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 13 0 0
+BITMAP
+10
+38
+44
+00
+3c
+66
+c2
+fe
+c0
+c0
+c0
+66
+3c
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 12 0 0
+BITMAP
+6c
+6c
+00
+3c
+66
+c2
+fe
+c0
+c0
+c0
+66
+3c
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 4 13 0 0
+BITMAP
+c0
+60
+10
+00
+e0
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 4 13 0 0
+BITMAP
+30
+60
+80
+00
+e0
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 13 0 0
+BITMAP
+20
+70
+88
+00
+e0
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 12 0 0
+BITMAP
+d8
+d8
+00
+e0
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+60
+36
+38
+4c
+3e
+66
+c3
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 12 0 0
+BITMAP
+3a00
+5c00
+0000
+e600
+6f00
+7300
+6300
+6300
+6300
+6300
+6300
+f380
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+60
+30
+08
+00
+3c
+66
+c3
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+06
+0c
+10
+00
+3c
+66
+c3
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+10
+38
+44
+00
+3c
+66
+c3
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+1a
+2c
+00
+3c
+66
+c3
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+6c
+6c
+00
+3c
+66
+c3
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 7 1 1
+BITMAP
+18
+18
+00
+ff
+00
+18
+18
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 11 0 -1
+BITMAP
+01
+3f
+66
+cf
+cb
+db
+d3
+f3
+66
+7c
+c0
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 13 0 0
+BITMAP
+3000
+1800
+0400
+0000
+e700
+6300
+6300
+6300
+6300
+6300
+6300
+7700
+3b80
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 13 0 0
+BITMAP
+0600
+0c00
+1000
+0000
+e700
+6300
+6300
+6300
+6300
+6300
+6300
+7700
+3b80
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 13 0 0
+BITMAP
+0800
+1c00
+2200
+0000
+e700
+6300
+6300
+6300
+6300
+6300
+6300
+7700
+3b80
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+3600
+3600
+0000
+e700
+6300
+6300
+6300
+6300
+6300
+6300
+7700
+3b80
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 8 17 -1 -4
+BITMAP
+03
+06
+08
+00
+f3
+63
+72
+32
+36
+1c
+1c
+0c
+08
+18
+10
+f0
+e0
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 17 0 -4
+BITMAP
+e0
+60
+60
+60
+6e
+77
+63
+63
+63
+63
+63
+76
+7c
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 8 16 -1 -4
+BITMAP
+36
+36
+00
+f3
+63
+72
+32
+36
+1c
+1c
+0c
+08
+18
+10
+f0
+e0
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/times18.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/times18.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/times18.h	(revision 12606)
@@ -0,0 +1,980 @@
+static unsigned char times18_0_bits[] = {
+0x00};
+static unsigned char times18_1_bits[] = {
+0x00};
+static unsigned char times18_2_bits[] = {
+0x00};
+static unsigned char times18_3_bits[] = {
+0x00};
+static unsigned char times18_4_bits[] = {
+0x00};
+static unsigned char times18_5_bits[] = {
+0x00};
+static unsigned char times18_6_bits[] = {
+0x00};
+static unsigned char times18_7_bits[] = {
+0x00};
+static unsigned char times18_8_bits[] = {
+0x00};
+static unsigned char times18_9_bits[] = {
+0x00};
+static unsigned char times18_10_bits[] = {
+0x00};
+static unsigned char times18_11_bits[] = {
+0x00};
+static unsigned char times18_12_bits[] = {
+0x00};
+static unsigned char times18_13_bits[] = {
+0x00};
+static unsigned char times18_14_bits[] = {
+0x00};
+static unsigned char times18_15_bits[] = {
+0x00};
+static unsigned char times18_16_bits[] = {
+0x00};
+static unsigned char times18_17_bits[] = {
+0x00};
+static unsigned char times18_18_bits[] = {
+0x00};
+static unsigned char times18_19_bits[] = {
+0x00};
+static unsigned char times18_20_bits[] = {
+0x00};
+static unsigned char times18_21_bits[] = {
+0x00};
+static unsigned char times18_22_bits[] = {
+0x00};
+static unsigned char times18_23_bits[] = {
+0x00};
+static unsigned char times18_24_bits[] = {
+0x00};
+static unsigned char times18_25_bits[] = {
+0x00};
+static unsigned char times18_26_bits[] = {
+0x00};
+static unsigned char times18_27_bits[] = {
+0x00};
+static unsigned char times18_28_bits[] = {
+0x00};
+static unsigned char times18_29_bits[] = {
+0x00};
+static unsigned char times18_30_bits[] = {
+0x00};
+static unsigned char times18_31_bits[] = {
+0x00};
+static unsigned char times18_32_bits[] = {
+0x00};
+static unsigned char times18_33_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x00, 0x00, 0x03, 
+0x03};
+static unsigned char times18_34_bits[] = {
+0x33, 0x33, 0x33, 0x11};
+static unsigned char times18_35_bits[] = {
+0xb0, 0x01, 0xb0, 0x01, 0xb0, 0x01, 0xb0, 0x01, 0xfe, 0x07, 0xd8, 0x00, 
+0xd8, 0x00, 0xd8, 0x00, 0xff, 0x03, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 
+0x6c, 0x00};
+static unsigned char times18_36_bits[] = {
+0x08, 0x3e, 0x6b, 0x4b, 0x0b, 0x0f, 0x1e, 0x3c, 0x38, 0x68, 0x68, 0x69, 
+0x6b, 0x3e, 0x08, 0x08};
+static unsigned char times18_37_bits[] = {
+0x1c, 0x0c, 0xf6, 0x07, 0x23, 0x02, 0x23, 0x01, 0xb3, 0x01, 0xdf, 0x00, 
+0x4e, 0x0e, 0x60, 0x1b, 0xb0, 0x11, 0x90, 0x11, 0x98, 0x19, 0x8c, 0x0f, 
+0x04, 0x07};
+static unsigned char times18_38_bits[] = {
+0x38, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x2c, 0x00, 0x98, 0x07, 
+0x1c, 0x03, 0xb6, 0x01, 0xf3, 0x00, 0xe3, 0x00, 0xe3, 0x01, 0xb7, 0x0f, 
+0x1e, 0x07};
+static unsigned char times18_39_bits[] = {
+0x03, 0x07, 0x04, 0x02};
+static unsigned char times18_40_bits[] = {
+0x18, 0x0c, 0x06, 0x06, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x02, 0x06, 0x06, 0x0c, 0x18};
+static unsigned char times18_41_bits[] = {
+0x03, 0x06, 0x0c, 0x0c, 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x08, 0x0c, 0x0c, 0x06, 0x03};
+static unsigned char times18_42_bits[] = {
+0x08, 0x08, 0x6b, 0x2a, 0x1c, 0x6b, 0x49, 0x08};
+static unsigned char times18_43_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0xff, 0x01, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char times18_44_bits[] = {
+0x06, 0x06, 0x04, 0x06, 0x03};
+static unsigned char times18_45_bits[] = {
+0xff};
+static unsigned char times18_46_bits[] = {
+0x03, 0x03};
+static unsigned char times18_47_bits[] = {
+0x10, 0x10, 0x18, 0x08, 0x08, 0x0c, 0x04, 0x04, 0x06, 0x02, 0x02, 0x03, 
+0x01, 0x01, 0x01};
+static unsigned char times18_48_bits[] = {
+0x3c, 0x66, 0x42, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x42, 0x66, 
+0x3c};
+static unsigned char times18_49_bits[] = {
+0x0c, 0x0e, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 
+0x3f};
+static unsigned char times18_50_bits[] = {
+0x3c, 0x7e, 0x73, 0x61, 0x60, 0x60, 0x30, 0x30, 0x18, 0x0c, 0x46, 0x7f, 
+0x7f};
+static unsigned char times18_51_bits[] = {
+0x3e, 0x73, 0x61, 0x60, 0x30, 0x1c, 0x3c, 0x70, 0x60, 0x60, 0x60, 0x33, 
+0x1f};
+static unsigned char times18_52_bits[] = {
+0x60, 0x70, 0x70, 0x68, 0x64, 0x66, 0x62, 0x61, 0xff, 0xff, 0x60, 0x60, 
+0x60};
+static unsigned char times18_53_bits[] = {
+0x7e, 0x3e, 0x03, 0x03, 0x0f, 0x3c, 0x30, 0x70, 0x60, 0x60, 0x30, 0x3b, 
+0x0f};
+static unsigned char times18_54_bits[] = {
+0xe0, 0x38, 0x0c, 0x06, 0x06, 0x3f, 0x63, 0xc3, 0xc3, 0xc3, 0xc7, 0x6e, 
+0x3c};
+static unsigned char times18_55_bits[] = {
+0x7f, 0x7f, 0x21, 0x30, 0x10, 0x18, 0x18, 0x08, 0x0c, 0x0c, 0x04, 0x06, 
+0x06};
+static unsigned char times18_56_bits[] = {
+0x3c, 0x66, 0x46, 0x46, 0x2e, 0x3c, 0x3c, 0x76, 0xe3, 0xc3, 0xc3, 0x66, 
+0x3c};
+static unsigned char times18_57_bits[] = {
+0x3c, 0x76, 0x63, 0xc3, 0xc3, 0xc3, 0xc7, 0xfe, 0x60, 0x60, 0x30, 0x1c, 
+0x07};
+static unsigned char times18_58_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03};
+static unsigned char times18_59_bits[] = {
+0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x04, 0x06, 0x03};
+static unsigned char times18_60_bits[] = {
+0x80, 0x01, 0xe0, 0x00, 0x38, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x0e, 0x00, 
+0x38, 0x00, 0xe0, 0x00, 0x80, 0x01};
+static unsigned char times18_61_bits[] = {
+0xff, 0x00, 0xff};
+static unsigned char times18_62_bits[] = {
+0x03, 0x00, 0x0e, 0x00, 0x38, 0x00, 0xe0, 0x00, 0x80, 0x01, 0xe0, 0x00, 
+0x38, 0x00, 0x0e, 0x00, 0x03, 0x00};
+static unsigned char times18_63_bits[] = {
+0x1e, 0x31, 0x23, 0x33, 0x30, 0x18, 0x18, 0x0c, 0x04, 0x04, 0x00, 0x0c, 
+0x0c};
+static unsigned char times18_64_bits[] = {
+0xe0, 0x07, 0x70, 0x0c, 0x1c, 0x18, 0x0c, 0x10, 0xc6, 0x37, 0xe6, 0x27, 
+0x63, 0x26, 0x33, 0x26, 0x33, 0x33, 0x33, 0x13, 0xb3, 0x1b, 0xe6, 0x0e, 
+0x06, 0x00, 0x0c, 0x00, 0x38, 0x0c, 0xe0, 0x07};
+static unsigned char times18_65_bits[] = {
+0x40, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xa0, 0x00, 0xb0, 0x01, 0x90, 0x01, 
+0x98, 0x03, 0x08, 0x03, 0xf8, 0x03, 0x0c, 0x07, 0x04, 0x06, 0x06, 0x0e, 
+0x0f, 0x1f};
+static unsigned char times18_66_bits[] = {
+0xff, 0x00, 0xc6, 0x01, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 0xc6, 0x00, 
+0xfe, 0x01, 0x86, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x86, 0x01, 
+0xff, 0x00};
+static unsigned char times18_67_bits[] = {
+0xf0, 0x04, 0x0c, 0x07, 0x06, 0x06, 0x06, 0x04, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0x06, 0x06, 0x1c, 0x03, 
+0xf0, 0x00};
+static unsigned char times18_68_bits[] = {
+0xff, 0x00, 0xc6, 0x01, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x03, 0x06, 0x03, 0xc6, 0x01, 
+0xff, 0x00};
+static unsigned char times18_69_bits[] = {
+0xff, 0x01, 0x86, 0x01, 0x06, 0x01, 0x06, 0x00, 0x06, 0x00, 0x86, 0x00, 
+0xfe, 0x00, 0x86, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x01, 0x86, 0x01, 
+0xff, 0x01};
+static unsigned char times18_70_bits[] = {
+0xff, 0x01, 0x86, 0x01, 0x06, 0x01, 0x06, 0x00, 0x06, 0x00, 0x86, 0x00, 
+0xfe, 0x00, 0x86, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 
+0x0f, 0x00};
+static unsigned char times18_71_bits[] = {
+0xf0, 0x04, 0x0c, 0x07, 0x06, 0x06, 0x06, 0x04, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x0f, 0x03, 0x06, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x9c, 0x03, 
+0xf0, 0x00};
+static unsigned char times18_72_bits[] = {
+0x8f, 0x07, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0xfe, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x8f, 0x07};
+static unsigned char times18_73_bits[] = {
+0x0f, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char times18_74_bits[] = {
+0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1b, 
+0x0f};
+static unsigned char times18_75_bits[] = {
+0xcf, 0x03, 0x86, 0x01, 0xc6, 0x00, 0x66, 0x00, 0x36, 0x00, 0x1e, 0x00, 
+0x1e, 0x00, 0x36, 0x00, 0x66, 0x00, 0xc6, 0x00, 0xc6, 0x01, 0x86, 0x03, 
+0x0f, 0x07};
+static unsigned char times18_76_bits[] = {
+0x0f, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 
+0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x02, 0x06, 0x03, 
+0xff, 0x03};
+static unsigned char times18_77_bits[] = {
+0x07, 0x38, 0x0e, 0x1c, 0x0e, 0x1c, 0x1e, 0x1e, 0x1a, 0x1a, 0x1a, 0x1b, 
+0x3a, 0x1b, 0x32, 0x19, 0xb2, 0x19, 0xe2, 0x18, 0xe2, 0x18, 0x42, 0x18, 
+0x47, 0x3c};
+static unsigned char times18_78_bits[] = {
+0x07, 0x07, 0x06, 0x02, 0x0e, 0x02, 0x1e, 0x02, 0x1a, 0x02, 0x32, 0x02, 
+0x72, 0x02, 0xe2, 0x02, 0xc2, 0x02, 0x82, 0x03, 0x82, 0x03, 0x02, 0x03, 
+0x07, 0x02};
+static unsigned char times18_79_bits[] = {
+0xf0, 0x00, 0x0c, 0x03, 0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c, 
+0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 
+0xf0, 0x00};
+static unsigned char times18_80_bits[] = {
+0xff, 0x00, 0xc6, 0x01, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 0xc6, 0x00, 
+0x7e, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 
+0x0f, 0x00};
+static unsigned char times18_81_bits[] = {
+0xf0, 0x00, 0x0c, 0x03, 0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c, 
+0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 
+0xf0, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x80, 0x03, 0x00, 0x0f};
+static unsigned char times18_82_bits[] = {
+0xff, 0x00, 0xc6, 0x01, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 0xc6, 0x00, 
+0x7e, 0x00, 0x66, 0x00, 0xc6, 0x00, 0x86, 0x01, 0x86, 0x01, 0x06, 0x03, 
+0x0f, 0x07};
+static unsigned char times18_83_bits[] = {
+0x5c, 0x66, 0x43, 0x03, 0x07, 0x1e, 0x3c, 0x70, 0xe0, 0xc0, 0xc1, 0x63, 
+0x3d};
+static unsigned char times18_84_bits[] = {
+0xff, 0x03, 0x33, 0x03, 0x31, 0x02, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x78, 0x00};
+static unsigned char times18_85_bits[] = {
+0x0f, 0x07, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 
+0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x0e, 0x03, 0x9c, 0x01, 
+0xf8, 0x00};
+static unsigned char times18_86_bits[] = {
+0x1f, 0x1e, 0x0e, 0x0c, 0x0c, 0x04, 0x1c, 0x04, 0x18, 0x06, 0x18, 0x02, 
+0x38, 0x02, 0x30, 0x03, 0x70, 0x01, 0x60, 0x01, 0xe0, 0x01, 0xc0, 0x00, 
+0xc0, 0x00};
+static unsigned char times18_87_bits[] = {
+0x9f, 0xc7, 0x03, 0x0c, 0x83, 0x01, 0x0c, 0x83, 0x00, 0x18, 0x83, 0x00, 
+0x18, 0xc6, 0x00, 0x18, 0x46, 0x00, 0x38, 0x47, 0x00, 0x30, 0x65, 0x00, 
+0x30, 0x2d, 0x00, 0xb0, 0x2c, 0x00, 0xe0, 0x3c, 0x00, 0x60, 0x18, 0x00, 
+0x60, 0x18, 0x00};
+static unsigned char times18_88_bits[] = {
+0x0f, 0x0e, 0x0e, 0x06, 0x1c, 0x03, 0x98, 0x01, 0xb0, 0x00, 0x70, 0x00, 
+0x60, 0x00, 0xf0, 0x00, 0xd8, 0x00, 0x88, 0x01, 0x8c, 0x03, 0x06, 0x07, 
+0x0f, 0x0f};
+static unsigned char times18_89_bits[] = {
+0x0f, 0x0f, 0x0e, 0x06, 0x0c, 0x03, 0x18, 0x01, 0x98, 0x00, 0xf0, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0xf0, 0x00};
+static unsigned char times18_90_bits[] = {
+0xfe, 0x03, 0x86, 0x03, 0x82, 0x01, 0xc0, 0x01, 0xe0, 0x00, 0x60, 0x00, 
+0x70, 0x00, 0x38, 0x00, 0x1c, 0x00, 0x0c, 0x00, 0x0e, 0x02, 0x07, 0x03, 
+0xff, 0x03};
+static unsigned char times18_91_bits[] = {
+0x0f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x0f};
+static unsigned char times18_92_bits[] = {
+0x01, 0x01, 0x03, 0x02, 0x06, 0x06, 0x04, 0x0c, 0x0c, 0x08, 0x18, 0x10, 
+0x10};
+static unsigned char times18_93_bits[] = {
+0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0f};
+static unsigned char times18_94_bits[] = {
+0x08, 0x1c, 0x14, 0x36, 0x22, 0x63, 0x41};
+static unsigned char times18_95_bits[] = {
+0xff, 0x01};
+static unsigned char times18_96_bits[] = {
+0x02, 0x01, 0x07, 0x06};
+static unsigned char times18_97_bits[] = {
+0x1e, 0x33, 0x33, 0x38, 0x36, 0x33, 0x33, 0x3f, 0x66};
+static unsigned char times18_98_bits[] = {
+0x07, 0x06, 0x06, 0x06, 0x76, 0xee, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6e, 
+0x3c};
+static unsigned char times18_99_bits[] = {
+0x3c, 0x66, 0x63, 0x03, 0x03, 0x03, 0x03, 0x46, 0x3c};
+static unsigned char times18_100_bits[] = {
+0x70, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x63, 0x63, 0x63, 0x63, 0x63, 0x66, 
+0xfc};
+static unsigned char times18_101_bits[] = {
+0x3c, 0x66, 0xc3, 0xff, 0x03, 0x03, 0x87, 0x6e, 0x3c};
+static unsigned char times18_102_bits[] = {
+0x38, 0x2c, 0x04, 0x06, 0x1f, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char times18_103_bits[] = {
+0x7c, 0x33, 0x23, 0x23, 0x33, 0x1e, 0x02, 0x3e, 0xfe, 0xc1, 0x83, 0x47, 
+0x3e};
+static unsigned char times18_104_bits[] = {
+0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x66, 0x00, 0xf6, 0x00, 
+0xce, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 
+0xcf, 0x01};
+static unsigned char times18_105_bits[] = {
+0x06, 0x06, 0x00, 0x00, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char times18_106_bits[] = {
+0x0c, 0x0c, 0x00, 0x00, 0x0e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x07, 0x03};
+static unsigned char times18_107_bits[] = {
+0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xe6, 0x00, 0x46, 0x00, 
+0x26, 0x00, 0x16, 0x00, 0x1e, 0x00, 0x36, 0x00, 0x66, 0x00, 0xc6, 0x00, 
+0xc7, 0x01};
+static unsigned char times18_108_bits[] = {
+0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char times18_109_bits[] = {
+0x67, 0x0c, 0xf6, 0x1e, 0xce, 0x19, 0xc6, 0x18, 0xc6, 0x18, 0xc6, 0x18, 
+0xc6, 0x18, 0xc6, 0x18, 0xef, 0x3d};
+static unsigned char times18_110_bits[] = {
+0x67, 0x00, 0xf6, 0x00, 0xce, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 
+0xc6, 0x00, 0xc6, 0x00, 0xcf, 0x01};
+static unsigned char times18_111_bits[] = {
+0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c};
+static unsigned char times18_112_bits[] = {
+0x77, 0xee, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6e, 0x36, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char times18_113_bits[] = {
+0x7c, 0x66, 0x63, 0x63, 0x63, 0x63, 0x63, 0x66, 0x7c, 0x60, 0x60, 0x60, 
+0xf0};
+static unsigned char times18_114_bits[] = {
+0x37, 0x36, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times18_115_bits[] = {
+0x16, 0x1b, 0x13, 0x07, 0x0e, 0x1c, 0x19, 0x1b, 0x0d};
+static unsigned char times18_116_bits[] = {
+0x04, 0x06, 0x1f, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x2e, 0x1c};
+static unsigned char times18_117_bits[] = {
+0xe7, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 
+0xc6, 0x00, 0xee, 0x00, 0xdc, 0x01};
+static unsigned char times18_118_bits[] = {
+0xcf, 0x01, 0xc6, 0x00, 0x46, 0x00, 0x4c, 0x00, 0x6c, 0x00, 0x28, 0x00, 
+0x38, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char times18_119_bits[] = {
+0xe7, 0x1c, 0x66, 0x0c, 0x46, 0x06, 0x6c, 0x06, 0xec, 0x06, 0xb8, 0x02, 
+0xb8, 0x03, 0x10, 0x01, 0x10, 0x01};
+static unsigned char times18_120_bits[] = {
+0xc7, 0x01, 0xc6, 0x00, 0x6c, 0x00, 0x38, 0x00, 0x30, 0x00, 0x38, 0x00, 
+0x6c, 0x00, 0xc6, 0x00, 0xc7, 0x01};
+static unsigned char times18_121_bits[] = {
+0xcf, 0x01, 0x86, 0x00, 0xce, 0x00, 0x4c, 0x00, 0x6c, 0x00, 0x38, 0x00, 
+0x38, 0x00, 0x30, 0x00, 0x18, 0x00, 0x18, 0x00, 0x08, 0x00, 0x0f, 0x00, 
+0x07, 0x00};
+static unsigned char times18_122_bits[] = {
+0x7f, 0x73, 0x31, 0x18, 0x0c, 0x0c, 0x46, 0x67, 0x7f};
+static unsigned char times18_123_bits[] = {
+0x70, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x18, 0x70};
+static unsigned char times18_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01};
+static unsigned char times18_125_bits[] = {
+0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x60, 0x30, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x0c, 0x07};
+static unsigned char times18_126_bits[] = {
+0x9e, 0x01, 0xf3, 0x00};
+static unsigned char times18_127_bits[] = {
+0x00};
+static unsigned char times18_128_bits[] = {
+0x00};
+static unsigned char times18_129_bits[] = {
+0x00};
+static unsigned char times18_130_bits[] = {
+0x00};
+static unsigned char times18_131_bits[] = {
+0x00};
+static unsigned char times18_132_bits[] = {
+0x00};
+static unsigned char times18_133_bits[] = {
+0x00};
+static unsigned char times18_134_bits[] = {
+0x00};
+static unsigned char times18_135_bits[] = {
+0x00};
+static unsigned char times18_136_bits[] = {
+0x00};
+static unsigned char times18_137_bits[] = {
+0x00};
+static unsigned char times18_138_bits[] = {
+0x00};
+static unsigned char times18_139_bits[] = {
+0x00};
+static unsigned char times18_140_bits[] = {
+0x00};
+static unsigned char times18_141_bits[] = {
+0x00};
+static unsigned char times18_142_bits[] = {
+0x00};
+static unsigned char times18_143_bits[] = {
+0x00};
+static unsigned char times18_144_bits[] = {
+0x00};
+static unsigned char times18_145_bits[] = {
+0x00};
+static unsigned char times18_146_bits[] = {
+0x00};
+static unsigned char times18_147_bits[] = {
+0x00};
+static unsigned char times18_148_bits[] = {
+0x00};
+static unsigned char times18_149_bits[] = {
+0x00};
+static unsigned char times18_150_bits[] = {
+0x00};
+static unsigned char times18_151_bits[] = {
+0x00};
+static unsigned char times18_152_bits[] = {
+0x00};
+static unsigned char times18_153_bits[] = {
+0x00};
+static unsigned char times18_154_bits[] = {
+0x00};
+static unsigned char times18_155_bits[] = {
+0x00};
+static unsigned char times18_156_bits[] = {
+0x00};
+static unsigned char times18_157_bits[] = {
+0x00};
+static unsigned char times18_158_bits[] = {
+0x00};
+static unsigned char times18_159_bits[] = {
+0x00};
+static unsigned char times18_160_bits[] = {
+0x00};
+static unsigned char times18_161_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char times18_162_bits[] = {
+0x60, 0x20, 0x7c, 0xd6, 0xd3, 0x13, 0x1b, 0x0b, 0x0b, 0x4e, 0x3e, 0x02, 
+0x03};
+static unsigned char times18_163_bits[] = {
+0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 
+0x7e, 0x00, 0x18, 0x00, 0x18, 0x00, 0x08, 0x00, 0x1e, 0x02, 0xfd, 0x03, 
+0xe7, 0x01};
+static unsigned char times18_164_bits[] = {
+0xbb, 0x01, 0xef, 0x01, 0xc6, 0x00, 0x82, 0x00, 0xc6, 0x00, 0xef, 0x01, 
+0xbb, 0x01};
+static unsigned char times18_165_bits[] = {
+0xef, 0x46, 0x46, 0x6e, 0x2c, 0x2c, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 
+0x7e};
+static unsigned char times18_166_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 
+0x01};
+static unsigned char times18_167_bits[] = {
+0x3c, 0x66, 0x66, 0x0e, 0x1c, 0x3e, 0x71, 0xe3, 0xc7, 0x8e, 0x7c, 0x38, 
+0x70, 0x66, 0x66, 0x3c};
+static unsigned char times18_168_bits[] = {
+0x1b, 0x1b};
+static unsigned char times18_169_bits[] = {
+0xf0, 0x01, 0x0c, 0x06, 0x02, 0x08, 0xe2, 0x09, 0x11, 0x11, 0x09, 0x10, 
+0x09, 0x10, 0x09, 0x10, 0x11, 0x11, 0xe2, 0x08, 0x02, 0x08, 0x0c, 0x06, 
+0xf0, 0x01};
+static unsigned char times18_170_bits[] = {
+0x06, 0x09, 0x08, 0x0e, 0x09, 0x17, 0x00, 0x1f};
+static unsigned char times18_171_bits[] = {
+0x88, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x88};
+static unsigned char times18_172_bits[] = {
+0xff, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01};
+static unsigned char times18_173_bits[] = {
+0x1f, 0x1f};
+static unsigned char times18_174_bits[] = {
+0xf0, 0x01, 0x0c, 0x06, 0x02, 0x08, 0xfa, 0x08, 0x11, 0x11, 0x11, 0x11, 
+0xf1, 0x10, 0x91, 0x10, 0x11, 0x11, 0x3a, 0x0b, 0x02, 0x08, 0x0c, 0x06, 
+0xf0, 0x01};
+static unsigned char times18_175_bits[] = {
+0x1f};
+static unsigned char times18_176_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char times18_177_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0xff, 0x01, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0xff, 0x01};
+static unsigned char times18_178_bits[] = {
+0x0e, 0x19, 0x18, 0x08, 0x04, 0x04, 0x02, 0x1f};
+static unsigned char times18_179_bits[] = {
+0x0e, 0x11, 0x18, 0x0e, 0x18, 0x10, 0x11, 0x0e};
+static unsigned char times18_180_bits[] = {
+0x0c, 0x06, 0x01};
+static unsigned char times18_181_bits[] = {
+0xe7, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 
+0xc6, 0x00, 0xee, 0x00, 0xde, 0x01, 0x02, 0x00, 0x02, 0x00, 0x06, 0x00, 
+0x06, 0x00};
+static unsigned char times18_182_bits[] = {
+0x7c, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2e, 0x28, 0x28, 0x28, 0x28, 
+0x28, 0x28, 0x28, 0x28, 0x28};
+static unsigned char times18_183_bits[] = {
+0x03, 0x03};
+static unsigned char times18_184_bits[] = {
+0x04, 0x04, 0x08, 0x0d, 0x06};
+static unsigned char times18_185_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times18_186_bits[] = {
+0x0e, 0x1b, 0x11, 0x11, 0x1b, 0x0e, 0x00, 0x1f};
+static unsigned char times18_187_bits[] = {
+0x11, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x11};
+static unsigned char times18_188_bits[] = {
+0x02, 0x01, 0x83, 0x01, 0x82, 0x00, 0xc2, 0x00, 0x62, 0x00, 0x22, 0x02, 
+0x32, 0x03, 0x97, 0x02, 0xd8, 0x02, 0x4c, 0x02, 0xe4, 0x07, 0x06, 0x02, 
+0x02, 0x02};
+static unsigned char times18_189_bits[] = {
+0x02, 0x01, 0x83, 0x01, 0x82, 0x00, 0xc2, 0x00, 0x62, 0x00, 0xa2, 0x03, 
+0x72, 0x06, 0x17, 0x06, 0x18, 0x02, 0x0c, 0x01, 0x04, 0x01, 0x86, 0x00, 
+0xc2, 0x07};
+static unsigned char times18_190_bits[] = {
+0x0e, 0x04, 0x11, 0x06, 0x18, 0x02, 0x0e, 0x03, 0x98, 0x01, 0x90, 0x08, 
+0xd1, 0x0c, 0x4e, 0x0a, 0x60, 0x0b, 0x30, 0x09, 0x90, 0x1f, 0x18, 0x08, 
+0x08, 0x08};
+static unsigned char times18_191_bits[] = {
+0x0c, 0x0c, 0x00, 0x08, 0x08, 0x0c, 0x06, 0x06, 0x03, 0x33, 0x31, 0x23, 
+0x1e};
+static unsigned char times18_192_bits[] = {
+0x30, 0x00, 0x60, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0xe0, 0x00, 
+0xe0, 0x00, 0xa0, 0x00, 0xb0, 0x01, 0x90, 0x01, 0x98, 0x03, 0x08, 0x03, 
+0xf8, 0x03, 0x0c, 0x07, 0x04, 0x06, 0x06, 0x0e, 0x0f, 0x1f};
+static unsigned char times18_193_bits[] = {
+0x00, 0x03, 0x80, 0x01, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0xe0, 0x00, 
+0xe0, 0x00, 0xa0, 0x00, 0xb0, 0x01, 0x90, 0x01, 0x98, 0x03, 0x08, 0x03, 
+0xf8, 0x03, 0x0c, 0x07, 0x04, 0x06, 0x06, 0x0e, 0x0f, 0x1f};
+static unsigned char times18_194_bits[] = {
+0x40, 0x00, 0xe0, 0x00, 0x10, 0x01, 0x00, 0x00, 0x40, 0x00, 0xe0, 0x00, 
+0xe0, 0x00, 0xa0, 0x00, 0xb0, 0x01, 0x90, 0x01, 0x98, 0x03, 0x08, 0x03, 
+0xf8, 0x03, 0x0c, 0x07, 0x04, 0x06, 0x06, 0x0e, 0x0f, 0x1f};
+static unsigned char times18_195_bits[] = {
+0xe0, 0x02, 0xd0, 0x01, 0x00, 0x00, 0x40, 0x00, 0xe0, 0x00, 0xe0, 0x00, 
+0xa0, 0x00, 0xb0, 0x01, 0x90, 0x01, 0x98, 0x03, 0x08, 0x03, 0xf8, 0x03, 
+0x0c, 0x07, 0x04, 0x06, 0x06, 0x0e, 0x0f, 0x1f};
+static unsigned char times18_196_bits[] = {
+0xb0, 0x01, 0xb0, 0x01, 0x00, 0x00, 0x40, 0x00, 0xe0, 0x00, 0xe0, 0x00, 
+0xa0, 0x00, 0xb0, 0x01, 0x90, 0x01, 0x98, 0x03, 0x08, 0x03, 0xf8, 0x03, 
+0x0c, 0x07, 0x04, 0x06, 0x06, 0x0e, 0x0f, 0x1f};
+static unsigned char times18_197_bits[] = {
+0xc0, 0x00, 0x20, 0x01, 0x20, 0x01, 0xc0, 0x00, 0x40, 0x00, 0xe0, 0x00, 
+0xe0, 0x00, 0xa0, 0x00, 0xb0, 0x01, 0x90, 0x01, 0x98, 0x03, 0x08, 0x03, 
+0xf8, 0x03, 0x0c, 0x07, 0x04, 0x06, 0x06, 0x0e, 0x0f, 0x1f};
+static unsigned char times18_198_bits[] = {
+0xf0, 0x3f, 0xe0, 0x31, 0xa0, 0x21, 0xa0, 0x01, 0xb0, 0x01, 0x90, 0x11, 
+0x98, 0x1f, 0xf8, 0x11, 0x88, 0x01, 0x8c, 0x01, 0x84, 0x41, 0x86, 0x61, 
+0xef, 0x7f};
+static unsigned char times18_199_bits[] = {
+0xf0, 0x04, 0x0c, 0x07, 0x06, 0x06, 0x06, 0x04, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0x06, 0x06, 0x1c, 0x03, 
+0xf0, 0x00, 0x20, 0x00, 0x40, 0x00, 0x68, 0x00, 0x30, 0x00};
+static unsigned char times18_200_bits[] = {
+0x0c, 0x00, 0x18, 0x00, 0x20, 0x00, 0x00, 0x00, 0xff, 0x01, 0x86, 0x01, 
+0x06, 0x01, 0x06, 0x00, 0x06, 0x00, 0x86, 0x00, 0xfe, 0x00, 0x86, 0x00, 
+0x06, 0x00, 0x06, 0x00, 0x06, 0x01, 0x86, 0x01, 0xff, 0x01};
+static unsigned char times18_201_bits[] = {
+0x60, 0x00, 0x30, 0x00, 0x08, 0x00, 0x00, 0x00, 0xff, 0x01, 0x86, 0x01, 
+0x06, 0x01, 0x06, 0x00, 0x06, 0x00, 0x86, 0x00, 0xfe, 0x00, 0x86, 0x00, 
+0x06, 0x00, 0x06, 0x00, 0x06, 0x01, 0x86, 0x01, 0xff, 0x01};
+static unsigned char times18_202_bits[] = {
+0x10, 0x00, 0x38, 0x00, 0x44, 0x00, 0x00, 0x00, 0xff, 0x01, 0x86, 0x01, 
+0x06, 0x01, 0x06, 0x00, 0x06, 0x00, 0x86, 0x00, 0xfe, 0x00, 0x86, 0x00, 
+0x06, 0x00, 0x06, 0x00, 0x06, 0x01, 0x86, 0x01, 0xff, 0x01};
+static unsigned char times18_203_bits[] = {
+0xcc, 0x00, 0xcc, 0x00, 0x00, 0x00, 0xff, 0x01, 0x86, 0x01, 0x06, 0x01, 
+0x06, 0x00, 0x06, 0x00, 0x86, 0x00, 0xfe, 0x00, 0x86, 0x00, 0x06, 0x00, 
+0x06, 0x00, 0x06, 0x01, 0x86, 0x01, 0xff, 0x01};
+static unsigned char times18_204_bits[] = {
+0x03, 0x06, 0x08, 0x00, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times18_205_bits[] = {
+0x0c, 0x06, 0x01, 0x00, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times18_206_bits[] = {
+0x04, 0x0e, 0x11, 0x00, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times18_207_bits[] = {
+0x33, 0x33, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x1e};
+static unsigned char times18_208_bits[] = {
+0xfe, 0x01, 0x8c, 0x03, 0x0c, 0x06, 0x0c, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x06, 0x0c, 0x06, 0x8c, 0x03, 
+0xfe, 0x01};
+static unsigned char times18_209_bits[] = {
+0x70, 0x01, 0xe8, 0x00, 0x00, 0x00, 0x07, 0x07, 0x06, 0x02, 0x0e, 0x02, 
+0x1e, 0x02, 0x1a, 0x02, 0x32, 0x02, 0x72, 0x02, 0xe2, 0x02, 0xc2, 0x02, 
+0x82, 0x03, 0x82, 0x03, 0x02, 0x03, 0x07, 0x02};
+static unsigned char times18_210_bits[] = {
+0x18, 0x00, 0x30, 0x00, 0x40, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x03, 
+0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 
+0x03, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 0xf0, 0x00};
+static unsigned char times18_211_bits[] = {
+0x00, 0x03, 0x80, 0x01, 0x40, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x03, 
+0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 
+0x03, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 0xf0, 0x00};
+static unsigned char times18_212_bits[] = {
+0x40, 0x00, 0xe0, 0x00, 0x10, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x03, 
+0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 
+0x03, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 0xf0, 0x00};
+static unsigned char times18_213_bits[] = {
+0x70, 0x01, 0xe8, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x03, 0x06, 0x06, 
+0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 
+0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 0xf0, 0x00};
+static unsigned char times18_214_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x03, 0x06, 0x06, 
+0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 
+0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 0xf0, 0x00};
+static unsigned char times18_215_bits[] = {
+0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3};
+static unsigned char times18_216_bits[] = {
+0x00, 0x0c, 0xf0, 0x06, 0x0c, 0x03, 0x06, 0x07, 0x86, 0x05, 0xc3, 0x0c, 
+0xc3, 0x0c, 0x63, 0x0c, 0x33, 0x0c, 0x33, 0x0c, 0x1a, 0x06, 0x0e, 0x06, 
+0x0c, 0x03, 0xf6, 0x00, 0x03, 0x00};
+static unsigned char times18_217_bits[] = {
+0x18, 0x00, 0x30, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0f, 0x07, 0x06, 0x02, 
+0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 
+0x06, 0x02, 0x06, 0x02, 0x0e, 0x03, 0x9c, 0x01, 0xf8, 0x00};
+static unsigned char times18_218_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0f, 0x07, 0x06, 0x02, 
+0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 
+0x06, 0x02, 0x06, 0x02, 0x0e, 0x03, 0x9c, 0x01, 0xf8, 0x00};
+static unsigned char times18_219_bits[] = {
+0x20, 0x00, 0x70, 0x00, 0x88, 0x00, 0x00, 0x00, 0x0f, 0x07, 0x06, 0x02, 
+0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 
+0x06, 0x02, 0x06, 0x02, 0x0e, 0x03, 0x9c, 0x01, 0xf8, 0x00};
+static unsigned char times18_220_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x0f, 0x07, 0x06, 0x02, 0x06, 0x02, 
+0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 
+0x06, 0x02, 0x0e, 0x03, 0x9c, 0x01, 0xf8, 0x00};
+static unsigned char times18_221_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0e, 0x06, 
+0x0c, 0x03, 0x18, 0x01, 0x98, 0x00, 0xf0, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xf0, 0x00};
+static unsigned char times18_222_bits[] = {
+0x0f, 0x00, 0x06, 0x00, 0x06, 0x00, 0xfe, 0x00, 0xc6, 0x01, 0x86, 0x01, 
+0x86, 0x01, 0x86, 0x01, 0xc6, 0x00, 0x7e, 0x00, 0x06, 0x00, 0x06, 0x00, 
+0x0f, 0x00};
+static unsigned char times18_223_bits[] = {
+0x38, 0x6c, 0xc4, 0xc6, 0xc6, 0x66, 0x3e, 0x66, 0xc6, 0xc6, 0xd6, 0xd6, 
+0x77};
+static unsigned char times18_224_bits[] = {
+0x03, 0x06, 0x08, 0x00, 0x1e, 0x13, 0x33, 0x38, 0x36, 0x33, 0x33, 0x3f, 
+0x66};
+static unsigned char times18_225_bits[] = {
+0x30, 0x18, 0x04, 0x00, 0x1e, 0x13, 0x33, 0x38, 0x36, 0x33, 0x33, 0x3f, 
+0x66};
+static unsigned char times18_226_bits[] = {
+0x08, 0x1c, 0x22, 0x00, 0x1e, 0x13, 0x33, 0x38, 0x36, 0x33, 0x33, 0x3f, 
+0x66};
+static unsigned char times18_227_bits[] = {
+0x2c, 0x1a, 0x00, 0x1e, 0x13, 0x33, 0x38, 0x36, 0x33, 0x33, 0x3f, 0x66};
+static unsigned char times18_228_bits[] = {
+0x36, 0x36, 0x00, 0x1e, 0x13, 0x33, 0x38, 0x36, 0x33, 0x33, 0x3f, 0x66};
+static unsigned char times18_229_bits[] = {
+0x0c, 0x12, 0x12, 0x0c, 0x1e, 0x13, 0x33, 0x38, 0x36, 0x33, 0x33, 0x3f, 
+0x66};
+static unsigned char times18_230_bits[] = {
+0xde, 0x03, 0x73, 0x06, 0x33, 0x04, 0xf8, 0x07, 0x36, 0x00, 0x33, 0x00, 
+0x33, 0x00, 0x7f, 0x06, 0xc6, 0x03};
+static unsigned char times18_231_bits[] = {
+0x3c, 0x66, 0x03, 0x03, 0x03, 0x03, 0x03, 0x66, 0x3c, 0x08, 0x10, 0x1a, 
+0x0c};
+static unsigned char times18_232_bits[] = {
+0x06, 0x0c, 0x10, 0x00, 0x3c, 0x66, 0x43, 0x7f, 0x03, 0x03, 0x03, 0x66, 
+0x3c};
+static unsigned char times18_233_bits[] = {
+0x60, 0x30, 0x08, 0x00, 0x3c, 0x66, 0x43, 0x7f, 0x03, 0x03, 0x03, 0x66, 
+0x3c};
+static unsigned char times18_234_bits[] = {
+0x08, 0x1c, 0x22, 0x00, 0x3c, 0x66, 0x43, 0x7f, 0x03, 0x03, 0x03, 0x66, 
+0x3c};
+static unsigned char times18_235_bits[] = {
+0x36, 0x36, 0x00, 0x3c, 0x66, 0x43, 0x7f, 0x03, 0x03, 0x03, 0x66, 0x3c};
+static unsigned char times18_236_bits[] = {
+0x03, 0x06, 0x08, 0x00, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char times18_237_bits[] = {
+0x0c, 0x06, 0x01, 0x00, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char times18_238_bits[] = {
+0x04, 0x0e, 0x11, 0x00, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char times18_239_bits[] = {
+0x1b, 0x1b, 0x00, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times18_240_bits[] = {
+0x06, 0x6c, 0x1c, 0x32, 0x7c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 
+0x3c};
+static unsigned char times18_241_bits[] = {
+0x5c, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x67, 0x00, 0xf6, 0x00, 0xce, 0x00, 
+0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xcf, 0x01};
+static unsigned char times18_242_bits[] = {
+0x06, 0x0c, 0x10, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 
+0x3c};
+static unsigned char times18_243_bits[] = {
+0x60, 0x30, 0x08, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 
+0x3c};
+static unsigned char times18_244_bits[] = {
+0x08, 0x1c, 0x22, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 
+0x3c};
+static unsigned char times18_245_bits[] = {
+0x58, 0x34, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c};
+static unsigned char times18_246_bits[] = {
+0x36, 0x36, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c};
+static unsigned char times18_247_bits[] = {
+0x18, 0x18, 0x00, 0xff, 0x00, 0x18, 0x18};
+static unsigned char times18_248_bits[] = {
+0x80, 0xfc, 0x66, 0xf3, 0xd3, 0xdb, 0xcb, 0xcf, 0x66, 0x3e, 0x03};
+static unsigned char times18_249_bits[] = {
+0x0c, 0x00, 0x18, 0x00, 0x20, 0x00, 0x00, 0x00, 0xe7, 0x00, 0xc6, 0x00, 
+0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xee, 0x00, 
+0xdc, 0x01};
+static unsigned char times18_250_bits[] = {
+0x60, 0x00, 0x30, 0x00, 0x08, 0x00, 0x00, 0x00, 0xe7, 0x00, 0xc6, 0x00, 
+0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xee, 0x00, 
+0xdc, 0x01};
+static unsigned char times18_251_bits[] = {
+0x10, 0x00, 0x38, 0x00, 0x44, 0x00, 0x00, 0x00, 0xe7, 0x00, 0xc6, 0x00, 
+0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xee, 0x00, 
+0xdc, 0x01};
+static unsigned char times18_252_bits[] = {
+0x6c, 0x00, 0x6c, 0x00, 0x00, 0x00, 0xe7, 0x00, 0xc6, 0x00, 0xc6, 0x00, 
+0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xee, 0x00, 0xdc, 0x01};
+static unsigned char times18_253_bits[] = {
+0xc0, 0x60, 0x10, 0x00, 0xcf, 0xc6, 0x4e, 0x4c, 0x6c, 0x38, 0x38, 0x30, 
+0x10, 0x18, 0x08, 0x0f, 0x07};
+static unsigned char times18_254_bits[] = {
+0x07, 0x06, 0x06, 0x06, 0x76, 0xee, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6e, 
+0x3e, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times18_255_bits[] = {
+0x6c, 0x6c, 0x00, 0xcf, 0xc6, 0x4e, 0x4c, 0x6c, 0x38, 0x38, 0x30, 0x10, 
+0x18, 0x08, 0x0f, 0x07};
+static RotFont times18font[] = {
+{5, 1, 1, times18_0_bits},
+{5, 1, 1, times18_1_bits},
+{5, 1, 1, times18_2_bits},
+{5, 1, 1, times18_3_bits},
+{5, 1, 1, times18_4_bits},
+{5, 1, 1, times18_5_bits},
+{5, 1, 1, times18_6_bits},
+{5, 1, 1, times18_7_bits},
+{5, 1, 1, times18_8_bits},
+{5, 1, 1, times18_9_bits},
+{5, 1, 1, times18_10_bits},
+{5, 1, 1, times18_11_bits},
+{5, 1, 1, times18_12_bits},
+{5, 1, 1, times18_13_bits},
+{5, 1, 1, times18_14_bits},
+{5, 1, 1, times18_15_bits},
+{5, 1, 1, times18_16_bits},
+{5, 1, 1, times18_17_bits},
+{5, 1, 1, times18_18_bits},
+{5, 1, 1, times18_19_bits},
+{5, 1, 1, times18_20_bits},
+{5, 1, 1, times18_21_bits},
+{5, 1, 1, times18_22_bits},
+{5, 1, 1, times18_23_bits},
+{5, 1, 1, times18_24_bits},
+{5, 1, 1, times18_25_bits},
+{5, 1, 1, times18_26_bits},
+{5, 1, 1, times18_27_bits},
+{5, 1, 1, times18_28_bits},
+{5, 1, 1, times18_29_bits},
+{5, 1, 1, times18_30_bits},
+{5, 1, 1, times18_31_bits},
+{8, 1, 1, times18_32_bits},
+{2, 13, 13, times18_33_bits},
+{6, 4, 13, times18_34_bits},
+{11, 13, 13, times18_35_bits},
+{7, 16, 14, times18_36_bits},
+{13, 13, 13, times18_37_bits},
+{12, 13, 13, times18_38_bits},
+{3, 4, 13, times18_39_bits},
+{5, 17, 13, times18_40_bits},
+{5, 17, 13, times18_41_bits},
+{7, 8, 14, times18_42_bits},
+{9, 9, 9, times18_43_bits},
+{3, 5, 2, times18_44_bits},
+{8, 1, 5, times18_45_bits},
+{2, 2, 2, times18_46_bits},
+{5, 15, 13, times18_47_bits},
+{8, 13, 13, times18_48_bits},
+{6, 13, 13, times18_49_bits},
+{7, 13, 13, times18_50_bits},
+{7, 13, 13, times18_51_bits},
+{8, 13, 13, times18_52_bits},
+{7, 13, 13, times18_53_bits},
+{8, 13, 13, times18_54_bits},
+{7, 13, 13, times18_55_bits},
+{8, 13, 13, times18_56_bits},
+{8, 13, 13, times18_57_bits},
+{2, 9, 9, times18_58_bits},
+{3, 12, 9, times18_59_bits},
+{9, 9, 9, times18_60_bits},
+{8, 3, 6, times18_61_bits},
+{9, 9, 9, times18_62_bits},
+{6, 13, 13, times18_63_bits},
+{14, 16, 13, times18_64_bits},
+{13, 13, 13, times18_65_bits},
+{10, 13, 13, times18_66_bits},
+{11, 13, 13, times18_67_bits},
+{11, 13, 13, times18_68_bits},
+{9, 13, 13, times18_69_bits},
+{9, 13, 13, times18_70_bits},
+{12, 13, 13, times18_71_bits},
+{11, 13, 13, times18_72_bits},
+{4, 13, 13, times18_73_bits},
+{6, 13, 13, times18_74_bits},
+{11, 13, 13, times18_75_bits},
+{10, 13, 13, times18_76_bits},
+{14, 13, 13, times18_77_bits},
+{11, 13, 13, times18_78_bits},
+{12, 13, 13, times18_79_bits},
+{9, 13, 13, times18_80_bits},
+{12, 17, 13, times18_81_bits},
+{11, 13, 13, times18_82_bits},
+{8, 13, 13, times18_83_bits},
+{10, 13, 13, times18_84_bits},
+{11, 13, 13, times18_85_bits},
+{13, 13, 13, times18_86_bits},
+{18, 13, 13, times18_87_bits},
+{12, 13, 13, times18_88_bits},
+{12, 13, 13, times18_89_bits},
+{10, 13, 13, times18_90_bits},
+{4, 16, 13, times18_91_bits},
+{5, 13, 13, times18_92_bits},
+{4, 16, 13, times18_93_bits},
+{7, 7, 13, times18_94_bits},
+{9, 1, -3, times18_95_bits},
+{3, 4, 13, times18_96_bits},
+{7, 9, 9, times18_97_bits},
+{8, 13, 13, times18_98_bits},
+{7, 9, 9, times18_99_bits},
+{8, 13, 13, times18_100_bits},
+{8, 9, 9, times18_101_bits},
+{6, 13, 13, times18_102_bits},
+{8, 13, 9, times18_103_bits},
+{9, 13, 13, times18_104_bits},
+{4, 13, 13, times18_105_bits},
+{4, 17, 13, times18_106_bits},
+{9, 13, 13, times18_107_bits},
+{4, 13, 13, times18_108_bits},
+{14, 9, 9, times18_109_bits},
+{9, 9, 9, times18_110_bits},
+{8, 9, 9, times18_111_bits},
+{8, 13, 9, times18_112_bits},
+{8, 13, 9, times18_113_bits},
+{6, 9, 9, times18_114_bits},
+{5, 9, 9, times18_115_bits},
+{6, 11, 11, times18_116_bits},
+{9, 9, 9, times18_117_bits},
+{9, 9, 9, times18_118_bits},
+{13, 9, 9, times18_119_bits},
+{9, 9, 9, times18_120_bits},
+{9, 13, 9, times18_121_bits},
+{7, 9, 9, times18_122_bits},
+{7, 17, 13, times18_123_bits},
+{1, 13, 13, times18_124_bits},
+{7, 17, 13, times18_125_bits},
+{9, 2, 6, times18_126_bits},
+{5, 1, 1, times18_127_bits},
+{5, 1, 1, times18_128_bits},
+{5, 1, 1, times18_129_bits},
+{5, 1, 1, times18_130_bits},
+{5, 1, 1, times18_131_bits},
+{5, 1, 1, times18_132_bits},
+{5, 1, 1, times18_133_bits},
+{5, 1, 1, times18_134_bits},
+{5, 1, 1, times18_135_bits},
+{5, 1, 1, times18_136_bits},
+{5, 1, 1, times18_137_bits},
+{5, 1, 1, times18_138_bits},
+{5, 1, 1, times18_139_bits},
+{5, 1, 1, times18_140_bits},
+{5, 1, 1, times18_141_bits},
+{5, 1, 1, times18_142_bits},
+{5, 1, 1, times18_143_bits},
+{5, 1, 1, times18_144_bits},
+{5, 1, 1, times18_145_bits},
+{5, 1, 1, times18_146_bits},
+{5, 1, 1, times18_147_bits},
+{5, 1, 1, times18_148_bits},
+{5, 1, 1, times18_149_bits},
+{5, 1, 1, times18_150_bits},
+{5, 1, 1, times18_151_bits},
+{5, 1, 1, times18_152_bits},
+{5, 1, 1, times18_153_bits},
+{5, 1, 1, times18_154_bits},
+{5, 1, 1, times18_155_bits},
+{5, 1, 1, times18_156_bits},
+{5, 1, 1, times18_157_bits},
+{5, 1, 1, times18_158_bits},
+{5, 1, 1, times18_159_bits},
+{1, 1, 1, times18_160_bits},
+{2, 13, 9, times18_161_bits},
+{8, 13, 11, times18_162_bits},
+{10, 13, 13, times18_163_bits},
+{9, 7, 10, times18_164_bits},
+{8, 13, 13, times18_165_bits},
+{1, 13, 13, times18_166_bits},
+{8, 16, 13, times18_167_bits},
+{5, 2, 12, times18_168_bits},
+{13, 13, 13, times18_169_bits},
+{5, 8, 13, times18_170_bits},
+{8, 7, 8, times18_171_bits},
+{9, 5, 6, times18_172_bits},
+{5, 2, 6, times18_173_bits},
+{13, 13, 13, times18_174_bits},
+{5, 1, 12, times18_175_bits},
+{5, 5, 13, times18_176_bits},
+{9, 10, 10, times18_177_bits},
+{5, 8, 13, times18_178_bits},
+{5, 8, 13, times18_179_bits},
+{4, 3, 13, times18_180_bits},
+{9, 13, 9, times18_181_bits},
+{7, 17, 13, times18_182_bits},
+{2, 2, 6, times18_183_bits},
+{4, 5, 1, times18_184_bits},
+{3, 8, 13, times18_185_bits},
+{5, 8, 13, times18_186_bits},
+{8, 7, 8, times18_187_bits},
+{11, 13, 13, times18_188_bits},
+{11, 13, 13, times18_189_bits},
+{13, 13, 13, times18_190_bits},
+{6, 13, 9, times18_191_bits},
+{13, 17, 17, times18_192_bits},
+{13, 17, 17, times18_193_bits},
+{13, 17, 17, times18_194_bits},
+{13, 16, 16, times18_195_bits},
+{13, 16, 16, times18_196_bits},
+{13, 17, 17, times18_197_bits},
+{15, 13, 13, times18_198_bits},
+{11, 17, 13, times18_199_bits},
+{9, 17, 17, times18_200_bits},
+{9, 17, 17, times18_201_bits},
+{9, 17, 17, times18_202_bits},
+{9, 16, 16, times18_203_bits},
+{4, 17, 17, times18_204_bits},
+{4, 17, 17, times18_205_bits},
+{5, 17, 17, times18_206_bits},
+{6, 16, 16, times18_207_bits},
+{12, 13, 13, times18_208_bits},
+{11, 16, 16, times18_209_bits},
+{12, 17, 17, times18_210_bits},
+{12, 17, 17, times18_211_bits},
+{12, 17, 17, times18_212_bits},
+{12, 16, 16, times18_213_bits},
+{12, 16, 16, times18_214_bits},
+{8, 7, 8, times18_215_bits},
+{12, 15, 14, times18_216_bits},
+{11, 17, 17, times18_217_bits},
+{11, 17, 17, times18_218_bits},
+{11, 17, 17, times18_219_bits},
+{11, 16, 16, times18_220_bits},
+{12, 17, 17, times18_221_bits},
+{9, 13, 13, times18_222_bits},
+{8, 13, 13, times18_223_bits},
+{7, 13, 13, times18_224_bits},
+{7, 13, 13, times18_225_bits},
+{7, 13, 13, times18_226_bits},
+{7, 12, 12, times18_227_bits},
+{7, 12, 12, times18_228_bits},
+{7, 13, 13, times18_229_bits},
+{11, 9, 9, times18_230_bits},
+{7, 13, 9, times18_231_bits},
+{7, 13, 13, times18_232_bits},
+{7, 13, 13, times18_233_bits},
+{7, 13, 13, times18_234_bits},
+{7, 12, 12, times18_235_bits},
+{4, 13, 13, times18_236_bits},
+{4, 13, 13, times18_237_bits},
+{5, 13, 13, times18_238_bits},
+{5, 12, 12, times18_239_bits},
+{8, 13, 13, times18_240_bits},
+{9, 12, 12, times18_241_bits},
+{8, 13, 13, times18_242_bits},
+{8, 13, 13, times18_243_bits},
+{8, 13, 13, times18_244_bits},
+{8, 12, 12, times18_245_bits},
+{8, 12, 12, times18_246_bits},
+{8, 7, 8, times18_247_bits},
+{8, 11, 10, times18_248_bits},
+{9, 13, 13, times18_249_bits},
+{9, 13, 13, times18_250_bits},
+{9, 13, 13, times18_251_bits},
+{9, 12, 12, times18_252_bits},
+{8, 17, 13, times18_253_bits},
+{8, 17, 13, times18_254_bits},
+{8, 16, 12, times18_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/times24.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/times24.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/times24.bdf	(revision 12606)
@@ -0,0 +1,4377 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Times-Medium-R-Normal--24-240-75-75-P-124-ISO8859-1
+SIZE 24 75 75
+FONTBOUNDINGBOX 24 28 -1 -6
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Times"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 24
+POINT_SIZE 240
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 124
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 17
+X_HEIGHT 12
+FACE_NAME "Times Roman"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Times is a trademark of Linotype-Hell AG and/or its subsidiaries."
+_DEC_DEVICE_FONTNAMES "PS=Times-Roman"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2-1, 22-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Times Roman"
+FONT "-Adobe-Times-Medium-R-Normal--24-240-75-75-P-124-ISO8859-1"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 14
+DEFAULT_CHAR 32
+FONT_ASCENT 20
+FONT_DESCENT 6
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 2 17 3 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+00
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 6 5 1 12
+BITMAP
+cc
+cc
+cc
+cc
+88
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+0880
+0880
+0880
+0880
+0880
+7fe0
+7fe0
+1100
+1100
+1100
+ffc0
+ffc0
+2200
+2200
+2200
+2200
+2200
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 11 21 0 -2
+BITMAP
+0400
+0400
+1f80
+34e0
+6460
+6420
+6400
+7400
+3c00
+1e00
+0780
+07c0
+04e0
+0460
+8460
+8460
+c4c0
+e5c0
+3f00
+0400
+0400
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 17 16 1 0
+BITMAP
+1e0c00
+33fc00
+611800
+c11000
+c13000
+c26000
+e44000
+78c000
+018f00
+011980
+033080
+066080
+046080
+0c6100
+187200
+303c00
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+0780
+0cc0
+1840
+1840
+18c0
+1d80
+0f00
+0e3e
+1e18
+3710
+6320
+c1a0
+c1c0
+c0c0
+e1e1
+7f7e
+3c3c
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 3 5 3 12
+BITMAP
+c0
+e0
+20
+60
+c0
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 22 1 -5
+BITMAP
+04
+08
+10
+30
+20
+60
+60
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+60
+60
+20
+30
+10
+08
+04
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 22 1 -5
+BITMAP
+80
+40
+20
+30
+10
+18
+18
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+18
+18
+10
+30
+20
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 9 9 2 8
+BITMAP
+0800
+1c00
+c980
+eb80
+1c00
+eb80
+c980
+1c00
+0800
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 12 1 1
+BITMAP
+0600
+0600
+0600
+0600
+0600
+fff0
+fff0
+0600
+0600
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 3 5 2 -3
+BITMAP
+c0
+e0
+20
+60
+c0
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 2 1 6
+BITMAP
+fff0
+fff0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 2 2 0
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 8 20 -1 -3
+BITMAP
+03
+03
+03
+06
+06
+04
+0c
+0c
+08
+18
+18
+10
+30
+30
+20
+60
+60
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1e00
+3300
+6180
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+e1c0
+6180
+6180
+3300
+1e00
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 8 17 2 0
+BITMAP
+08
+18
+78
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ff
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1c00
+7f00
+4380
+8180
+8180
+0180
+0180
+0300
+0300
+0600
+0400
+0c00
+1800
+3000
+6040
+ffc0
+ff80
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 9 17 1 0
+BITMAP
+1c00
+7e00
+4700
+8300
+8300
+0600
+0c00
+1e00
+0700
+0380
+0180
+0180
+0180
+0100
+c300
+e600
+7800
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+0300
+0700
+0700
+0b00
+1b00
+1300
+3300
+2300
+6300
+4300
+c300
+ffc0
+ffc0
+0300
+0300
+0300
+0300
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1fc0
+1f80
+2000
+2000
+6000
+7800
+7e00
+0f80
+0380
+01c0
+00c0
+00c0
+00c0
+00c0
+c180
+e380
+7e00
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+03c0
+0e00
+1800
+3000
+7000
+6000
+ee00
+f380
+c180
+c0c0
+c0c0
+c0c0
+c0c0
+e0c0
+6180
+7b80
+1e00
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+7fc0
+ffc0
+c0c0
+8180
+0180
+0100
+0300
+0300
+0200
+0600
+0600
+0400
+0c00
+0c00
+0c00
+1800
+1800
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1e00
+3300
+6180
+6180
+6180
+3300
+1e00
+1e00
+3700
+6180
+41c0
+c0c0
+c0c0
+c0c0
+e180
+7380
+1e00
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1e00
+7780
+6180
+c1c0
+c0c0
+c0c0
+c0c0
+c0c0
+61c0
+73c0
+1d80
+0180
+0380
+0300
+0600
+1c00
+f000
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 11 2 0
+BITMAP
+c0
+c0
+00
+00
+00
+00
+00
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 3 14 2 -3
+BITMAP
+c0
+c0
+00
+00
+00
+00
+00
+00
+00
+c0
+e0
+20
+60
+c0
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 11 1 1
+BITMAP
+0060
+01c0
+0700
+1c00
+7000
+c000
+7000
+1c00
+0700
+01c0
+0060
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 6 1 4
+BITMAP
+fff0
+fff0
+0000
+0000
+fff0
+fff0
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 11 1 1
+BITMAP
+c000
+7000
+1c00
+0700
+01c0
+0060
+01c0
+0700
+1c00
+7000
+c000
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 8 17 2 0
+BITMAP
+7c
+c6
+83
+c3
+c3
+07
+0e
+0c
+18
+18
+10
+10
+10
+00
+00
+30
+30
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 880 0
+DWIDTH 22 0
+BBX 18 20 2 -3
+BITMAP
+03f800
+0f0e00
+1c0300
+380180
+700080
+60ecc0
+e1fc40
+c38c40
+c30c40
+c60c40
+c61840
+c618c0
+c61880
+c63980
+637b00
+61de00
+300000
+180000
+0e0c00
+03f000
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 17 17 0 0
+BITMAP
+008000
+01c000
+01c000
+016000
+026000
+023000
+063000
+043000
+041800
+0c1800
+0ff800
+080c00
+180c00
+100c00
+100600
+300600
+fc1f80
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 17 1 0
+BITMAP
+ffc0
+3070
+3030
+3018
+3018
+3018
+3030
+3040
+3fe0
+3038
+3018
+300c
+300c
+300c
+3018
+3078
+ffe0
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 17 1 0
+BITMAP
+07e4
+1c3c
+380c
+6004
+6004
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+6000
+6004
+3808
+1e38
+07e0
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 17 1 0
+BITMAP
+ffc0
+3070
+3038
+300c
+300c
+3006
+3006
+3006
+3006
+3006
+3006
+3006
+300c
+300c
+3038
+3070
+ffc0
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+fff0
+3030
+3010
+3010
+3000
+3000
+3040
+3040
+3fc0
+3040
+3040
+3000
+3000
+3008
+3008
+3018
+fff8
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 17 1 0
+BITMAP
+fff0
+3030
+3010
+3010
+3000
+3000
+3020
+3020
+3fe0
+3020
+3020
+3000
+3000
+3000
+3000
+3000
+fc00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+07e4
+1c3c
+380c
+6004
+6004
+c000
+c000
+c000
+c000
+c03f
+c00c
+c00c
+600c
+600c
+381c
+1e38
+07e0
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 17 17 1 0
+BITMAP
+fc1f80
+300600
+300600
+300600
+300600
+300600
+300600
+300600
+3ffe00
+300600
+300600
+300600
+300600
+300600
+300600
+300600
+fc1f80
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 17 1 0
+BITMAP
+fc
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+fc
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+1f80
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+c600
+cc00
+7800
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 16 17 1 0
+BITMAP
+fc7e
+3018
+3030
+3060
+30c0
+3180
+3300
+3e00
+3f00
+3380
+31c0
+30e0
+3070
+3038
+301c
+300e
+fc1f
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 13 17 1 0
+BITMAP
+fc00
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3008
+3008
+3018
+fff8
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 880 0
+DWIDTH 22 0
+BBX 21 17 1 0
+BITMAP
+f000f8
+3000e0
+380160
+380160
+2c0260
+2c0260
+260260
+260460
+230460
+230860
+218860
+218860
+20d060
+20d060
+206060
+206060
+f821f8
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+f01f
+3004
+3804
+3804
+2c04
+2604
+2604
+2304
+2184
+2184
+20c4
+2064
+2064
+2034
+201c
+201c
+f80c
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+07e0
+1c38
+381c
+6006
+6006
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+6006
+6006
+381c
+1c38
+07e0
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+ffc0
+3070
+3030
+3018
+3018
+3018
+3030
+3070
+3fc0
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+fc00
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 22 1 -5
+BITMAP
+07e0
+1c38
+381c
+6006
+6006
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+6006
+6006
+381c
+1c38
+07e0
+01c0
+00e0
+0070
+0038
+000f
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 15 17 1 0
+BITMAP
+ffc0
+3070
+3030
+3038
+3018
+3038
+3030
+3070
+3fc0
+3380
+31c0
+30c0
+3060
+3070
+3038
+301c
+fc1e
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+1e40
+63c0
+c0c0
+c040
+c040
+e000
+7800
+1e00
+0f80
+03c0
+00e0
+0060
+8060
+8060
+c0c0
+f180
+9e00
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 17 1 0
+BITMAP
+fffc
+c30c
+8304
+8304
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0fc0
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+fc1f
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3008
+1808
+1c30
+07e0
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 17 17 0 0
+BITMAP
+fc1f80
+300600
+300400
+180c00
+180800
+180800
+0c1800
+0c1000
+063000
+062000
+062000
+036000
+034000
+03c000
+018000
+018000
+018000
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 920 0
+DWIDTH 23 0
+BBX 23 17 0 0
+BITMAP
+fc7e7e
+301818
+301810
+181810
+181830
+182c20
+0c2c20
+0c2c60
+064c60
+064c40
+064640
+0346c0
+034680
+038780
+018380
+018300
+018300
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 18 17 0 0
+BITMAP
+7e0f80
+1c0600
+0e0c00
+060800
+031000
+03a000
+01c000
+00c000
+00e000
+017000
+023800
+061800
+040c00
+080e00
+180700
+300380
+fc0fc0
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 16 17 0 0
+BITMAP
+fc3f
+300c
+3808
+1818
+1c10
+0c30
+0620
+0660
+0340
+03c0
+0180
+0180
+0180
+0180
+0180
+0180
+07e0
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+fff0
+c070
+80e0
+80c0
+01c0
+0380
+0300
+0700
+0600
+0e00
+1c00
+1800
+3800
+3008
+7008
+e018
+fff8
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 5 21 2 -4
+BITMAP
+f8
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+f8
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 7 17 0 0
+BITMAP
+c0
+c0
+40
+60
+60
+20
+30
+30
+10
+18
+18
+08
+0c
+0c
+04
+06
+06
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 5 21 1 -4
+BITMAP
+f8
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+f8
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 9 1 8
+BITMAP
+0800
+1c00
+1400
+3600
+2200
+6300
+4100
+c180
+8080
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 13 2 0 -5
+BITMAP
+fff8
+fff8
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 3 5 2 12
+BITMAP
+60
+c0
+80
+e0
+60
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+3e00
+6700
+6300
+0300
+0f00
+3b00
+6300
+c300
+c300
+c700
+fb00
+7180
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+e000
+6000
+6000
+6000
+6000
+6e00
+7380
+6180
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+6180
+7380
+5e00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+1f00
+6380
+4180
+c000
+c000
+c000
+c000
+c000
+e000
+7080
+7f00
+1e00
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+0380
+0180
+0180
+0180
+0180
+1d80
+7380
+6180
+c180
+c180
+c180
+c180
+c180
+c180
+6180
+7380
+1ec0
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+1e00
+6300
+4180
+c180
+ff80
+c000
+c000
+c000
+e000
+7080
+7f00
+1e00
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 7 17 0 0
+BITMAP
+0e
+16
+30
+30
+30
+fe
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+78
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 11 17 1 -5
+BITMAP
+1fc0
+3300
+6180
+6180
+6180
+6180
+3300
+3e00
+3000
+6000
+7f00
+3fc0
+6060
+c020
+c060
+f1c0
+3f00
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+e000
+6000
+6000
+6000
+6000
+6700
+6f80
+71c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+f1e0
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 4 17 1 0
+BITMAP
+60
+60
+00
+00
+00
+e0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 4 22 0 -5
+BITMAP
+30
+30
+00
+00
+00
+70
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+e0
+c0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 11 17 1 0
+BITMAP
+e000
+6000
+6000
+6000
+6000
+67c0
+6300
+6600
+6400
+6800
+7800
+6c00
+6e00
+6700
+6380
+61c0
+f3e0
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 4 17 1 0
+BITMAP
+e0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 800 0
+DWIDTH 20 0
+BBX 18 12 1 0
+BITMAP
+e70e00
+6f9f00
+71e380
+60c180
+60c180
+60c180
+60c180
+60c180
+60c180
+60c180
+60c180
+f1e3c0
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 12 1 0
+BITMAP
+e700
+6f80
+71c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+f1e0
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 12 1 0
+BITMAP
+1e00
+7380
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+7380
+1e00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 -5
+BITMAP
+ee00
+7380
+6180
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+6180
+7380
+6e00
+6000
+6000
+6000
+6000
+f000
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 -5
+BITMAP
+1d80
+7380
+6180
+c180
+c180
+c180
+c180
+c180
+c180
+6180
+7380
+1d80
+0180
+0180
+0180
+0180
+03c0
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 7 12 1 0
+BITMAP
+e6
+6e
+76
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+3e
+66
+c2
+e0
+70
+7c
+1e
+07
+03
+83
+c6
+f8
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 7 15 0 0
+BITMAP
+10
+30
+70
+fe
+30
+30
+30
+30
+30
+30
+30
+30
+30
+32
+1c
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 12 1 0
+BITMAP
+e1c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+71c0
+3ec0
+1ce0
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 11 12 0 0
+BITMAP
+f1e0
+60c0
+6080
+3080
+3080
+3100
+1900
+1900
+1a00
+0e00
+0e00
+0400
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 17 12 0 0
+BITMAP
+f1e780
+60c300
+60c200
+30c200
+30c200
+316400
+196400
+1a6400
+1a2800
+0e3800
+0e3800
+041000
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 12 1 0
+BITMAP
+f1e0
+60c0
+3180
+3900
+1a00
+0c00
+0e00
+1b00
+3380
+2180
+60c0
+f1e0
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 11 17 0 -5
+BITMAP
+f1e0
+60c0
+6080
+3080
+3080
+3100
+1900
+1900
+1a00
+0e00
+0e00
+0400
+0c00
+0800
+1800
+f000
+e000
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+ff
+c3
+86
+0e
+1c
+18
+38
+30
+70
+61
+c3
+ff
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 8 22 1 -5
+BITMAP
+07
+0c
+18
+18
+18
+18
+18
+10
+30
+20
+c0
+20
+30
+10
+18
+18
+18
+18
+18
+18
+0c
+07
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 17 2 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 8 22 1 -5
+BITMAP
+e0
+30
+18
+18
+18
+18
+18
+08
+0c
+04
+03
+04
+0c
+08
+18
+18
+18
+18
+18
+18
+30
+e0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 4 1 5
+BITMAP
+3820
+7c60
+c7c0
+8380
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 2 17 4 -5
+BITMAP
+c0
+c0
+00
+00
+00
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 9 16 1 -2
+BITMAP
+0100
+0100
+1f00
+6380
+4380
+c400
+c400
+c800
+c800
+c800
+d000
+7080
+7f00
+3e00
+4000
+4000
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+0f00
+1980
+3180
+3000
+3000
+3000
+3000
+fc00
+3000
+3000
+3000
+3000
+3000
+3000
+7840
+bec0
+e780
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 12 1 3
+BITMAP
+c060
+eee0
+7fc0
+3180
+60c0
+60c0
+60c0
+60c0
+3180
+7fc0
+eee0
+c060
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 14 17 0 0
+BITMAP
+f87c
+7030
+3020
+1860
+1840
+0cc0
+0c80
+0780
+0300
+1fe0
+0300
+1fe0
+0300
+0300
+0300
+0300
+0fc0
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 17 2 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+00
+00
+00
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 8 20 2 -2
+BITMAP
+1c
+26
+46
+60
+70
+38
+3c
+4e
+87
+83
+c3
+e2
+74
+38
+1c
+0e
+06
+62
+64
+38
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 2 1 14
+BITMAP
+cc
+cc
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 17 17 1 0
+BITMAP
+07f000
+1c1c00
+300600
+61e300
+473100
+c41980
+8c0080
+880080
+880080
+880080
+8c0080
+c41980
+477100
+61c300
+300600
+1c1c00
+07f000
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 7 9 0 8
+BITMAP
+78
+cc
+0c
+7c
+cc
+cc
+76
+00
+7e
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 9 10 2 1
+BITMAP
+0880
+1980
+3300
+6600
+cc00
+cc00
+6600
+3300
+1980
+0880
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 7 1 3
+BITMAP
+fff0
+fff0
+0030
+0030
+0030
+0030
+0030
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 360 0
+DWIDTH 9 0
+BBX 7 2 1 5
+BITMAP
+fe
+fe
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 17 17 1 0
+BITMAP
+07f000
+1c1c00
+300600
+67e300
+423100
+c21180
+821080
+823080
+83e080
+824080
+822080
+c23180
+471900
+600300
+300600
+1c1c00
+07f000
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 2 1 14
+BITMAP
+fc
+fc
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 360 0
+DWIDTH 9 0
+BBX 7 7 1 10
+BITMAP
+38
+44
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 15 1 0
+BITMAP
+0600
+0600
+0600
+0600
+0600
+fff0
+fff0
+0600
+0600
+0600
+0600
+0600
+0000
+fff0
+fff0
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 6 10 0 7
+BITMAP
+38
+4c
+8c
+0c
+08
+10
+30
+20
+44
+fc
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 6 10 0 7
+BITMAP
+38
+4c
+8c
+08
+30
+08
+0c
+8c
+88
+70
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 5 4 2 13
+BITMAP
+18
+38
+60
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 17 1 -5
+BITMAP
+e1c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+71c0
+7ec0
+5ce0
+4000
+4000
+c000
+e000
+4000
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 22 1 -5
+BITMAP
+1f80
+3900
+7900
+7900
+f900
+f900
+f900
+7900
+7900
+3900
+1900
+0900
+0900
+0900
+0900
+0900
+0900
+0900
+0900
+0900
+0900
+0900
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 2 2 6
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 6 1 -6
+BITMAP
+10
+30
+3c
+0c
+cc
+78
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 5 10 1 7
+BITMAP
+20
+60
+a0
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 9 1 8
+BITMAP
+78
+cc
+cc
+cc
+cc
+cc
+78
+00
+fc
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 9 10 2 1
+BITMAP
+8800
+cc00
+6600
+3300
+1980
+1980
+3300
+6600
+cc00
+8800
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+2008
+6018
+a030
+2020
+2060
+2040
+20c0
+2184
+210c
+fb1c
+0214
+0624
+0c64
+0844
+18ff
+1004
+3004
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 15 17 1 0
+BITMAP
+2008
+6018
+a030
+2020
+2060
+2040
+20c0
+219c
+2126
+fb46
+0206
+0604
+0c08
+0818
+1810
+1022
+307e
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 17 17 0 0
+BITMAP
+380400
+4c0c00
+8c1800
+081000
+303000
+082000
+0c6000
+8cc200
+888600
+718e00
+010a00
+031200
+063200
+042200
+0c7f80
+080200
+180200
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 8 17 1 -5
+BITMAP
+0c
+0c
+00
+00
+08
+08
+18
+18
+38
+30
+70
+e0
+c3
+c3
+c1
+63
+3e
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 17 22 0 0
+BITMAP
+030000
+038000
+00c000
+002000
+000000
+008000
+01c000
+01c000
+016000
+026000
+023000
+063000
+043000
+041800
+0c1800
+0ff800
+080c00
+180c00
+100c00
+100600
+300600
+fc1f80
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 17 22 0 0
+BITMAP
+003000
+007000
+00c000
+010000
+000000
+008000
+01c000
+01c000
+016000
+026000
+023000
+063000
+043000
+041800
+0c1800
+0ff800
+080c00
+180c00
+100c00
+100600
+300600
+fc1f80
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 17 22 0 0
+BITMAP
+018000
+03c000
+066000
+081000
+000000
+008000
+01c000
+01c000
+016000
+026000
+023000
+063000
+043000
+041800
+0c1800
+0ff800
+080c00
+180c00
+100c00
+100600
+300600
+fc1f80
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 17 21 0 0
+BITMAP
+039000
+04e000
+000000
+000000
+008000
+01c000
+01c000
+016000
+026000
+023000
+063000
+043000
+041800
+0c1800
+0ff800
+080c00
+180c00
+100c00
+100600
+300700
+fc1f80
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 17 21 0 0
+BITMAP
+063000
+063000
+000000
+000000
+008000
+01c000
+01c000
+016000
+026000
+023000
+063000
+043000
+041800
+0c1800
+0ff800
+080c00
+180c00
+100c00
+100600
+300600
+fc1f80
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 17 21 0 0
+BITMAP
+01c000
+022000
+022000
+01c000
+008000
+01c000
+01c000
+016000
+026000
+023000
+063000
+043000
+041800
+0c1800
+0ff800
+080c00
+180c00
+100c00
+100600
+300600
+fc1f80
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 840 0
+DWIDTH 21 0
+BBX 20 17 0 0
+BITMAP
+03ffe0
+01e060
+016020
+016020
+026000
+026000
+066080
+046080
+047f80
+0c6080
+0fe080
+086000
+186000
+106010
+106010
+306030
+f9fff0
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 23 1 -6
+BITMAP
+07e4
+1c3c
+380c
+6004
+6004
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+6000
+6004
+3808
+1e38
+07e0
+0100
+0300
+03c0
+00c0
+0cc0
+0780
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 22 1 0
+BITMAP
+1800
+1c00
+0600
+0100
+0000
+fff0
+3030
+3010
+3010
+3000
+3000
+3040
+3040
+3fc0
+3040
+3040
+3000
+3000
+3008
+3008
+3018
+fff8
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 22 1 0
+BITMAP
+00c0
+01c0
+0300
+0400
+0000
+fff0
+3030
+3010
+3010
+3000
+3000
+3040
+3040
+3fc0
+3040
+3040
+3000
+3000
+3008
+3008
+3018
+fff8
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 22 1 0
+BITMAP
+0300
+0780
+0cc0
+1020
+0000
+fff0
+3030
+3010
+3010
+3000
+3000
+3040
+3040
+3fc0
+3040
+3040
+3000
+3000
+3008
+3008
+3018
+fff8
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 21 1 0
+BITMAP
+1980
+1980
+0000
+0000
+fff0
+3030
+3010
+3010
+3000
+3000
+3040
+3040
+3fc0
+3040
+3040
+3000
+3000
+3008
+3008
+3018
+fff8
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 22 1 0
+BITMAP
+c0
+e0
+30
+08
+00
+fc
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+fc
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 22 1 0
+BITMAP
+0c
+1c
+30
+40
+00
+fc
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+fc
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 8 22 1 0
+BITMAP
+18
+3c
+66
+81
+00
+7e
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+7e
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 21 1 0
+BITMAP
+cc
+cc
+00
+00
+fc
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+fc
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 16 17 0 0
+BITMAP
+7fe0
+1838
+181c
+1806
+1806
+1803
+1803
+1803
+ff03
+1803
+1803
+1803
+1806
+1806
+181c
+1838
+7fe0
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 21 1 0
+BITMAP
+0390
+04e0
+0000
+0000
+f01f
+3004
+3804
+3804
+2c04
+2604
+2604
+2304
+2184
+2184
+20c4
+2064
+2064
+2034
+201c
+201c
+f80c
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 22 1 0
+BITMAP
+0600
+0700
+0180
+0040
+0000
+07e0
+1c38
+381c
+6006
+6006
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+6006
+6006
+381c
+1c38
+07e0
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 22 1 0
+BITMAP
+0030
+0070
+00c0
+0100
+0000
+07e0
+1c38
+381c
+6006
+6006
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+6006
+6006
+381c
+1c38
+07e0
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 22 1 0
+BITMAP
+0180
+03c0
+0660
+0810
+0000
+07e0
+1c38
+381c
+6006
+6006
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+6006
+6006
+381c
+1c38
+07e0
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 21 1 0
+BITMAP
+0390
+04e0
+0000
+0000
+07e0
+1c38
+381c
+6006
+6006
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+6006
+6006
+381c
+1c38
+07e0
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 21 1 0
+BITMAP
+0660
+0660
+0000
+0000
+07e0
+1c38
+381c
+6006
+6006
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+6006
+6006
+381c
+1c38
+07e0
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 11 2 1
+BITMAP
+8040
+c0c0
+6180
+3300
+1e00
+0c00
+1e00
+3300
+6180
+c0c0
+8040
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 19 1 -1
+BITMAP
+0004
+07e4
+1c38
+381c
+6026
+6046
+c043
+c083
+c083
+c103
+c103
+c203
+c203
+6406
+6806
+381c
+1c38
+27e0
+2000
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 22 1 0
+BITMAP
+0600
+0700
+0180
+0040
+0000
+fc1f
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3008
+1808
+1c30
+07e0
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 22 1 0
+BITMAP
+0030
+0070
+00c0
+0100
+0000
+fc1f
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3008
+1808
+1c30
+07e0
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 22 1 0
+BITMAP
+0180
+03c0
+0660
+0810
+0000
+fc1f
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3008
+1808
+1c30
+07e0
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 21 1 0
+BITMAP
+0630
+0630
+0000
+0000
+fc1f
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3008
+1808
+1c30
+07e0
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 16 22 0 0
+BITMAP
+0030
+0070
+00c0
+0100
+0000
+fc3f
+300c
+3808
+1818
+1c10
+0c30
+0620
+0660
+0340
+03c0
+0180
+0180
+0180
+0180
+0180
+0180
+07e0
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+fc00
+3000
+3000
+3000
+3fc0
+3070
+3030
+3018
+3018
+3018
+3030
+3070
+3fc0
+3000
+3000
+3000
+fc00
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1e00
+3300
+6180
+6180
+6180
+6180
+6300
+6c00
+6700
+6380
+6180
+61c0
+60c0
+60c0
+6cc0
+6c80
+e700
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+6000
+7000
+1800
+0400
+0000
+3e00
+6700
+6300
+0300
+0f00
+3b00
+6300
+c300
+c300
+c700
+fb00
+7180
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+0300
+0700
+0c00
+1000
+0000
+3e00
+6700
+6300
+0300
+0f00
+3b00
+6300
+c300
+c300
+c700
+fb00
+7180
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+1800
+3c00
+2400
+4200
+0000
+3e00
+6700
+6300
+0300
+0f00
+3b00
+6300
+c300
+c300
+c700
+fb00
+7180
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 16 1 0
+BITMAP
+3a00
+5c00
+0000
+0000
+3e00
+6700
+6300
+0300
+0f00
+3b00
+6300
+c300
+c300
+c700
+fb00
+7180
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 16 1 0
+BITMAP
+6600
+6600
+0000
+0000
+3e00
+6700
+6300
+0300
+0f00
+3b00
+6300
+c300
+c300
+c700
+fb00
+7180
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+1c00
+2200
+2200
+1c00
+0000
+3e00
+6700
+6300
+0300
+0f00
+3b00
+6300
+c300
+c300
+c700
+fb00
+7180
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 12 1 0
+BITMAP
+3cf0
+6798
+630c
+030c
+0ffc
+3b00
+6300
+c300
+c300
+c784
+fbf8
+70f0
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 18 1 -6
+BITMAP
+1f00
+6380
+4180
+c000
+c000
+c000
+c000
+c000
+e000
+7080
+7f00
+1e00
+0800
+1800
+1e00
+0600
+6600
+3c00
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+6000
+7000
+1800
+0400
+0000
+1e00
+6300
+4180
+c180
+ff80
+c000
+c000
+c000
+e000
+7080
+7f00
+1e00
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+0300
+0700
+0c00
+1000
+0000
+1e00
+6300
+4180
+c180
+ff80
+c000
+c000
+c000
+e000
+7080
+7f00
+1e00
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+0c00
+1e00
+1200
+2100
+0000
+1e00
+6300
+4180
+c180
+ff80
+c000
+c000
+c000
+e000
+7080
+7f00
+1e00
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 16 1 0
+BITMAP
+3300
+3300
+0000
+0000
+1e00
+6300
+4180
+c180
+ff80
+c000
+c000
+c000
+e000
+7080
+7f00
+1e00
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 5 17 0 0
+BITMAP
+c0
+e0
+30
+08
+00
+70
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+78
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 5 17 1 0
+BITMAP
+18
+38
+60
+80
+00
+e0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 6 17 0 0
+BITMAP
+30
+78
+48
+84
+00
+70
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+78
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 6 16 0 0
+BITMAP
+cc
+cc
+00
+00
+70
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+78
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+c000
+7180
+1e00
+3c00
+c600
+1f00
+7380
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+7380
+1e00
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 16 1 0
+BITMAP
+1c80
+2700
+0000
+0000
+e700
+6f80
+71c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+f1e0
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+3000
+3800
+0c00
+0200
+0000
+1e00
+7380
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+7380
+1e00
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+0180
+0380
+0600
+0800
+0000
+1e00
+7380
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+7380
+1e00
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+0c00
+1e00
+1200
+2100
+0000
+1e00
+7380
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+7380
+1e00
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 16 1 0
+BITMAP
+1c80
+2700
+0000
+0000
+1e00
+7380
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+7380
+1e00
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 16 1 0
+BITMAP
+3300
+3300
+0000
+0000
+1e00
+7380
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+7380
+1e00
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 10 1 2
+BITMAP
+0600
+0600
+0000
+0000
+fff0
+fff0
+0000
+0000
+0600
+0600
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 14 1 -1
+BITMAP
+00c0
+1ec0
+7380
+6380
+c6c0
+c4c0
+ccc0
+c8c0
+d8c0
+d0c0
+7180
+7380
+de00
+c000
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+3000
+3800
+0c00
+0200
+0000
+e1c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+71c0
+3ec0
+1ce0
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+0180
+0380
+0600
+0800
+0000
+e1c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+71c0
+3ec0
+1ce0
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+0c00
+1e00
+1200
+2100
+0000
+e1c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+71c0
+3ec0
+1ce0
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 16 1 0
+BITMAP
+3300
+3300
+0000
+0000
+e1c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+71c0
+3ec0
+1ce0
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 11 22 0 -5
+BITMAP
+0180
+0380
+0600
+0800
+0000
+f1e0
+60c0
+6080
+3080
+3080
+3100
+1900
+1900
+1a00
+0e00
+0e00
+0400
+0c00
+0800
+1800
+f000
+e000
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 22 1 -5
+BITMAP
+e000
+6000
+6000
+6000
+6000
+6e00
+7380
+6180
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+6180
+7380
+6e00
+6000
+6000
+6000
+6000
+f000
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 11 21 0 -5
+BITMAP
+3300
+3300
+0000
+0000
+f1e0
+60c0
+6080
+3080
+3080
+3100
+1900
+1900
+1a00
+0e00
+0e00
+0400
+0c00
+0800
+1800
+f000
+e000
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/times24.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/times24.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/times24.h	(revision 12606)
@@ -0,0 +1,1110 @@
+static unsigned char times24_0_bits[] = {
+0x00};
+static unsigned char times24_1_bits[] = {
+0x00};
+static unsigned char times24_2_bits[] = {
+0x00};
+static unsigned char times24_3_bits[] = {
+0x00};
+static unsigned char times24_4_bits[] = {
+0x00};
+static unsigned char times24_5_bits[] = {
+0x00};
+static unsigned char times24_6_bits[] = {
+0x00};
+static unsigned char times24_7_bits[] = {
+0x00};
+static unsigned char times24_8_bits[] = {
+0x00};
+static unsigned char times24_9_bits[] = {
+0x00};
+static unsigned char times24_10_bits[] = {
+0x00};
+static unsigned char times24_11_bits[] = {
+0x00};
+static unsigned char times24_12_bits[] = {
+0x00};
+static unsigned char times24_13_bits[] = {
+0x00};
+static unsigned char times24_14_bits[] = {
+0x00};
+static unsigned char times24_15_bits[] = {
+0x00};
+static unsigned char times24_16_bits[] = {
+0x00};
+static unsigned char times24_17_bits[] = {
+0x00};
+static unsigned char times24_18_bits[] = {
+0x00};
+static unsigned char times24_19_bits[] = {
+0x00};
+static unsigned char times24_20_bits[] = {
+0x00};
+static unsigned char times24_21_bits[] = {
+0x00};
+static unsigned char times24_22_bits[] = {
+0x00};
+static unsigned char times24_23_bits[] = {
+0x00};
+static unsigned char times24_24_bits[] = {
+0x00};
+static unsigned char times24_25_bits[] = {
+0x00};
+static unsigned char times24_26_bits[] = {
+0x00};
+static unsigned char times24_27_bits[] = {
+0x00};
+static unsigned char times24_28_bits[] = {
+0x00};
+static unsigned char times24_29_bits[] = {
+0x00};
+static unsigned char times24_30_bits[] = {
+0x00};
+static unsigned char times24_31_bits[] = {
+0x00};
+static unsigned char times24_32_bits[] = {
+0x00};
+static unsigned char times24_33_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x00, 0x00, 0x00, 0x03, 0x03};
+static unsigned char times24_34_bits[] = {
+0x33, 0x33, 0x33, 0x33, 0x11};
+static unsigned char times24_35_bits[] = {
+0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xfe, 0x07, 
+0xfe, 0x07, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0xff, 0x03, 0xff, 0x03, 
+0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0x44, 0x00};
+static unsigned char times24_36_bits[] = {
+0x20, 0x00, 0x20, 0x00, 0xf8, 0x01, 0x2c, 0x07, 0x26, 0x06, 0x26, 0x04, 
+0x26, 0x00, 0x2e, 0x00, 0x3c, 0x00, 0x78, 0x00, 0xe0, 0x01, 0xe0, 0x03, 
+0x20, 0x07, 0x20, 0x06, 0x21, 0x06, 0x21, 0x06, 0x23, 0x03, 0xa7, 0x03, 
+0xfc, 0x00, 0x20, 0x00, 0x20, 0x00};
+static unsigned char times24_37_bits[] = {
+0x78, 0x30, 0x00, 0xcc, 0x3f, 0x00, 0x86, 0x18, 0x00, 0x83, 0x08, 0x00, 
+0x83, 0x0c, 0x00, 0x43, 0x06, 0x00, 0x27, 0x02, 0x00, 0x1e, 0x03, 0x00, 
+0x80, 0xf1, 0x00, 0x80, 0x98, 0x01, 0xc0, 0x0c, 0x01, 0x60, 0x06, 0x01, 
+0x20, 0x06, 0x01, 0x30, 0x86, 0x00, 0x18, 0x4e, 0x00, 0x0c, 0x3c, 0x00};
+static unsigned char times24_38_bits[] = {
+0xe0, 0x01, 0x30, 0x03, 0x18, 0x02, 0x18, 0x02, 0x18, 0x03, 0xb8, 0x01, 
+0xf0, 0x00, 0x70, 0x7c, 0x78, 0x18, 0xec, 0x08, 0xc6, 0x04, 0x83, 0x05, 
+0x83, 0x03, 0x03, 0x03, 0x87, 0x87, 0xfe, 0x7e, 0x3c, 0x3c};
+static unsigned char times24_39_bits[] = {
+0x03, 0x07, 0x04, 0x06, 0x03};
+static unsigned char times24_40_bits[] = {
+0x20, 0x10, 0x08, 0x0c, 0x04, 0x06, 0x06, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x06, 0x06, 0x04, 0x0c, 0x08, 0x10, 0x20};
+static unsigned char times24_41_bits[] = {
+0x01, 0x02, 0x04, 0x0c, 0x08, 0x18, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 
+0x30, 0x30, 0x30, 0x18, 0x18, 0x08, 0x0c, 0x04, 0x02, 0x01};
+static unsigned char times24_42_bits[] = {
+0x10, 0x00, 0x38, 0x00, 0x93, 0x01, 0xd7, 0x01, 0x38, 0x00, 0xd7, 0x01, 
+0x93, 0x01, 0x38, 0x00, 0x10, 0x00};
+static unsigned char times24_43_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xff, 0x0f, 
+0xff, 0x0f, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char times24_44_bits[] = {
+0x03, 0x07, 0x04, 0x06, 0x03};
+static unsigned char times24_45_bits[] = {
+0xff, 0x0f, 0xff, 0x0f};
+static unsigned char times24_46_bits[] = {
+0x03, 0x03};
+static unsigned char times24_47_bits[] = {
+0xc0, 0xc0, 0xc0, 0x60, 0x60, 0x20, 0x30, 0x30, 0x10, 0x18, 0x18, 0x08, 
+0x0c, 0x0c, 0x04, 0x06, 0x06, 0x03, 0x03, 0x03};
+static unsigned char times24_48_bits[] = {
+0x78, 0x00, 0xcc, 0x00, 0x86, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x87, 0x03, 0x86, 0x01, 0x86, 0x01, 0xcc, 0x00, 0x78, 0x00};
+static unsigned char times24_49_bits[] = {
+0x10, 0x18, 0x1e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0xff};
+static unsigned char times24_50_bits[] = {
+0x38, 0x00, 0xfe, 0x00, 0xc2, 0x01, 0x81, 0x01, 0x81, 0x01, 0x80, 0x01, 
+0x80, 0x01, 0xc0, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x20, 0x00, 0x30, 0x00, 
+0x18, 0x00, 0x0c, 0x00, 0x06, 0x02, 0xff, 0x03, 0xff, 0x01};
+static unsigned char times24_51_bits[] = {
+0x38, 0x00, 0x7e, 0x00, 0xe2, 0x00, 0xc1, 0x00, 0xc1, 0x00, 0x60, 0x00, 
+0x30, 0x00, 0x78, 0x00, 0xe0, 0x00, 0xc0, 0x01, 0x80, 0x01, 0x80, 0x01, 
+0x80, 0x01, 0x80, 0x00, 0xc3, 0x00, 0x67, 0x00, 0x1e, 0x00};
+static unsigned char times24_52_bits[] = {
+0xc0, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xd0, 0x00, 0xd8, 0x00, 0xc8, 0x00, 
+0xcc, 0x00, 0xc4, 0x00, 0xc6, 0x00, 0xc2, 0x00, 0xc3, 0x00, 0xff, 0x03, 
+0xff, 0x03, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00};
+static unsigned char times24_53_bits[] = {
+0xf8, 0x03, 0xf8, 0x01, 0x04, 0x00, 0x04, 0x00, 0x06, 0x00, 0x1e, 0x00, 
+0x7e, 0x00, 0xf0, 0x01, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x03, 0x00, 0x03, 
+0x00, 0x03, 0x00, 0x03, 0x83, 0x01, 0xc7, 0x01, 0x7e, 0x00};
+static unsigned char times24_54_bits[] = {
+0xc0, 0x03, 0x70, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x06, 0x00, 
+0x77, 0x00, 0xcf, 0x01, 0x83, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x07, 0x03, 0x86, 0x01, 0xde, 0x01, 0x78, 0x00};
+static unsigned char times24_55_bits[] = {
+0xfe, 0x03, 0xff, 0x03, 0x03, 0x03, 0x81, 0x01, 0x80, 0x01, 0x80, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x20, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x18, 0x00, 0x18, 0x00};
+static unsigned char times24_56_bits[] = {
+0x78, 0x00, 0xcc, 0x00, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 0xcc, 0x00, 
+0x78, 0x00, 0x78, 0x00, 0xec, 0x00, 0x86, 0x01, 0x82, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x87, 0x01, 0xce, 0x01, 0x78, 0x00};
+static unsigned char times24_57_bits[] = {
+0x78, 0x00, 0xee, 0x01, 0x86, 0x01, 0x83, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x86, 0x03, 0xce, 0x03, 0xb8, 0x01, 0x80, 0x01, 
+0xc0, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x38, 0x00, 0x0f, 0x00};
+static unsigned char times24_58_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03};
+static unsigned char times24_59_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x04, 
+0x06, 0x03};
+static unsigned char times24_60_bits[] = {
+0x00, 0x06, 0x80, 0x03, 0xe0, 0x00, 0x38, 0x00, 0x0e, 0x00, 0x03, 0x00, 
+0x0e, 0x00, 0x38, 0x00, 0xe0, 0x00, 0x80, 0x03, 0x00, 0x06};
+static unsigned char times24_61_bits[] = {
+0xff, 0x0f, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0xff, 0x0f};
+static unsigned char times24_62_bits[] = {
+0x03, 0x00, 0x0e, 0x00, 0x38, 0x00, 0xe0, 0x00, 0x80, 0x03, 0x00, 0x06, 
+0x80, 0x03, 0xe0, 0x00, 0x38, 0x00, 0x0e, 0x00, 0x03, 0x00};
+static unsigned char times24_63_bits[] = {
+0x3e, 0x63, 0xc1, 0xc3, 0xc3, 0xe0, 0x70, 0x30, 0x18, 0x18, 0x08, 0x08, 
+0x08, 0x00, 0x00, 0x0c, 0x0c};
+static unsigned char times24_64_bits[] = {
+0xc0, 0x1f, 0x00, 0xf0, 0x70, 0x00, 0x38, 0xc0, 0x00, 0x1c, 0x80, 0x01, 
+0x0e, 0x00, 0x01, 0x06, 0x37, 0x03, 0x87, 0x3f, 0x02, 0xc3, 0x31, 0x02, 
+0xc3, 0x30, 0x02, 0x63, 0x30, 0x02, 0x63, 0x18, 0x02, 0x63, 0x18, 0x03, 
+0x63, 0x18, 0x01, 0x63, 0x9c, 0x01, 0xc6, 0xde, 0x00, 0x86, 0x7b, 0x00, 
+0x0c, 0x00, 0x00, 0x18, 0x00, 0x00, 0x70, 0x30, 0x00, 0xc0, 0x0f, 0x00};
+static unsigned char times24_65_bits[] = {
+0x00, 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x80, 0x06, 0x00, 
+0x40, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x60, 0x0c, 0x00, 0x20, 0x0c, 0x00, 
+0x20, 0x18, 0x00, 0x30, 0x18, 0x00, 0xf0, 0x1f, 0x00, 0x10, 0x30, 0x00, 
+0x18, 0x30, 0x00, 0x08, 0x30, 0x00, 0x08, 0x60, 0x00, 0x0c, 0x60, 0x00, 
+0x3f, 0xf8, 0x01};
+static unsigned char times24_66_bits[] = {
+0xff, 0x03, 0x0c, 0x0e, 0x0c, 0x0c, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x18, 
+0x0c, 0x0c, 0x0c, 0x02, 0xfc, 0x07, 0x0c, 0x1c, 0x0c, 0x18, 0x0c, 0x30, 
+0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x18, 0x0c, 0x1e, 0xff, 0x07};
+static unsigned char times24_67_bits[] = {
+0xe0, 0x27, 0x38, 0x3c, 0x1c, 0x30, 0x06, 0x20, 0x06, 0x20, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x06, 0x00, 0x06, 0x20, 0x1c, 0x10, 0x78, 0x1c, 0xe0, 0x07};
+static unsigned char times24_68_bits[] = {
+0xff, 0x03, 0x0c, 0x0e, 0x0c, 0x1c, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x60, 
+0x0c, 0x60, 0x0c, 0x60, 0x0c, 0x60, 0x0c, 0x60, 0x0c, 0x60, 0x0c, 0x60, 
+0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x1c, 0x0c, 0x0e, 0xff, 0x03};
+static unsigned char times24_69_bits[] = {
+0xff, 0x0f, 0x0c, 0x0c, 0x0c, 0x08, 0x0c, 0x08, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x02, 0x0c, 0x02, 0xfc, 0x03, 0x0c, 0x02, 0x0c, 0x02, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x10, 0x0c, 0x10, 0x0c, 0x18, 0xff, 0x1f};
+static unsigned char times24_70_bits[] = {
+0xff, 0x0f, 0x0c, 0x0c, 0x0c, 0x08, 0x0c, 0x08, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x04, 0x0c, 0x04, 0xfc, 0x07, 0x0c, 0x04, 0x0c, 0x04, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x3f, 0x00};
+static unsigned char times24_71_bits[] = {
+0xe0, 0x27, 0x38, 0x3c, 0x1c, 0x30, 0x06, 0x20, 0x06, 0x20, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0xfc, 0x03, 0x30, 0x03, 0x30, 
+0x06, 0x30, 0x06, 0x30, 0x1c, 0x38, 0x78, 0x1c, 0xe0, 0x07};
+static unsigned char times24_72_bits[] = {
+0x3f, 0xf8, 0x01, 0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 
+0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 
+0xfc, 0x7f, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 
+0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 
+0x3f, 0xf8, 0x01};
+static unsigned char times24_73_bits[] = {
+0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x3f};
+static unsigned char times24_74_bits[] = {
+0xf8, 0x01, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x63, 0x00, 0x33, 0x00, 0x1e, 0x00};
+static unsigned char times24_75_bits[] = {
+0x3f, 0x7e, 0x0c, 0x18, 0x0c, 0x0c, 0x0c, 0x06, 0x0c, 0x03, 0x8c, 0x01, 
+0xcc, 0x00, 0x7c, 0x00, 0xfc, 0x00, 0xcc, 0x01, 0x8c, 0x03, 0x0c, 0x07, 
+0x0c, 0x0e, 0x0c, 0x1c, 0x0c, 0x38, 0x0c, 0x70, 0x3f, 0xf8};
+static unsigned char times24_76_bits[] = {
+0x3f, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x10, 0x0c, 0x10, 0x0c, 0x18, 0xff, 0x1f};
+static unsigned char times24_77_bits[] = {
+0x0f, 0x00, 0x1f, 0x0c, 0x00, 0x07, 0x1c, 0x80, 0x06, 0x1c, 0x80, 0x06, 
+0x34, 0x40, 0x06, 0x34, 0x40, 0x06, 0x64, 0x40, 0x06, 0x64, 0x20, 0x06, 
+0xc4, 0x20, 0x06, 0xc4, 0x10, 0x06, 0x84, 0x11, 0x06, 0x84, 0x11, 0x06, 
+0x04, 0x0b, 0x06, 0x04, 0x0b, 0x06, 0x04, 0x06, 0x06, 0x04, 0x06, 0x06, 
+0x1f, 0x84, 0x1f};
+static unsigned char times24_78_bits[] = {
+0x0f, 0xf8, 0x0c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x34, 0x20, 0x64, 0x20, 
+0x64, 0x20, 0xc4, 0x20, 0x84, 0x21, 0x84, 0x21, 0x04, 0x23, 0x04, 0x26, 
+0x04, 0x26, 0x04, 0x2c, 0x04, 0x38, 0x04, 0x38, 0x1f, 0x30};
+static unsigned char times24_79_bits[] = {
+0xe0, 0x07, 0x38, 0x1c, 0x1c, 0x38, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x06, 0x60, 0x06, 0x60, 0x1c, 0x38, 0x38, 0x1c, 0xe0, 0x07};
+static unsigned char times24_80_bits[] = {
+0xff, 0x03, 0x0c, 0x0e, 0x0c, 0x0c, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x18, 
+0x0c, 0x0c, 0x0c, 0x0e, 0xfc, 0x03, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x3f, 0x00};
+static unsigned char times24_81_bits[] = {
+0xe0, 0x07, 0x38, 0x1c, 0x1c, 0x38, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x06, 0x60, 0x06, 0x60, 0x1c, 0x38, 0x38, 0x1c, 0xe0, 0x07, 0x80, 0x03, 
+0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c, 0x00, 0xf0};
+static unsigned char times24_82_bits[] = {
+0xff, 0x03, 0x0c, 0x0e, 0x0c, 0x0c, 0x0c, 0x1c, 0x0c, 0x18, 0x0c, 0x1c, 
+0x0c, 0x0c, 0x0c, 0x0e, 0xfc, 0x03, 0xcc, 0x01, 0x8c, 0x03, 0x0c, 0x03, 
+0x0c, 0x06, 0x0c, 0x0e, 0x0c, 0x1c, 0x0c, 0x38, 0x3f, 0x78};
+static unsigned char times24_83_bits[] = {
+0x78, 0x02, 0xc6, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x02, 0x07, 0x00, 
+0x1e, 0x00, 0x78, 0x00, 0xf0, 0x01, 0xc0, 0x03, 0x00, 0x07, 0x00, 0x06, 
+0x01, 0x06, 0x01, 0x06, 0x03, 0x03, 0x8f, 0x01, 0x79, 0x00};
+static unsigned char times24_84_bits[] = {
+0xff, 0x3f, 0xc3, 0x30, 0xc1, 0x20, 0xc1, 0x20, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xf0, 0x03};
+static unsigned char times24_85_bits[] = {
+0x3f, 0xf8, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 
+0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 
+0x0c, 0x20, 0x0c, 0x10, 0x18, 0x10, 0x38, 0x0c, 0xe0, 0x07};
+static unsigned char times24_86_bits[] = {
+0x3f, 0xf8, 0x01, 0x0c, 0x60, 0x00, 0x0c, 0x20, 0x00, 0x18, 0x30, 0x00, 
+0x18, 0x10, 0x00, 0x18, 0x10, 0x00, 0x30, 0x18, 0x00, 0x30, 0x08, 0x00, 
+0x60, 0x0c, 0x00, 0x60, 0x04, 0x00, 0x60, 0x04, 0x00, 0xc0, 0x06, 0x00, 
+0xc0, 0x02, 0x00, 0xc0, 0x03, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 
+0x80, 0x01, 0x00};
+static unsigned char times24_87_bits[] = {
+0x3f, 0x7e, 0x7e, 0x0c, 0x18, 0x18, 0x0c, 0x18, 0x08, 0x18, 0x18, 0x08, 
+0x18, 0x18, 0x0c, 0x18, 0x34, 0x04, 0x30, 0x34, 0x04, 0x30, 0x34, 0x06, 
+0x60, 0x32, 0x06, 0x60, 0x32, 0x02, 0x60, 0x62, 0x02, 0xc0, 0x62, 0x03, 
+0xc0, 0x62, 0x01, 0xc0, 0xe1, 0x01, 0x80, 0xc1, 0x01, 0x80, 0xc1, 0x00, 
+0x80, 0xc1, 0x00};
+static unsigned char times24_88_bits[] = {
+0x7e, 0xf0, 0x01, 0x38, 0x60, 0x00, 0x70, 0x30, 0x00, 0x60, 0x10, 0x00, 
+0xc0, 0x08, 0x00, 0xc0, 0x05, 0x00, 0x80, 0x03, 0x00, 0x00, 0x03, 0x00, 
+0x00, 0x07, 0x00, 0x80, 0x0e, 0x00, 0x40, 0x1c, 0x00, 0x60, 0x18, 0x00, 
+0x20, 0x30, 0x00, 0x10, 0x70, 0x00, 0x18, 0xe0, 0x00, 0x0c, 0xc0, 0x01, 
+0x3f, 0xf0, 0x03};
+static unsigned char times24_89_bits[] = {
+0x3f, 0xfc, 0x0c, 0x30, 0x1c, 0x10, 0x18, 0x18, 0x38, 0x08, 0x30, 0x0c, 
+0x60, 0x04, 0x60, 0x06, 0xc0, 0x02, 0xc0, 0x03, 0x80, 0x01, 0x80, 0x01, 
+0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xe0, 0x07};
+static unsigned char times24_90_bits[] = {
+0xff, 0x0f, 0x03, 0x0e, 0x01, 0x07, 0x01, 0x03, 0x80, 0x03, 0xc0, 0x01, 
+0xc0, 0x00, 0xe0, 0x00, 0x60, 0x00, 0x70, 0x00, 0x38, 0x00, 0x18, 0x00, 
+0x1c, 0x00, 0x0c, 0x10, 0x0e, 0x10, 0x07, 0x18, 0xff, 0x1f};
+static unsigned char times24_91_bits[] = {
+0x1f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x1f};
+static unsigned char times24_92_bits[] = {
+0x03, 0x03, 0x02, 0x06, 0x06, 0x04, 0x0c, 0x0c, 0x08, 0x18, 0x18, 0x10, 
+0x30, 0x30, 0x20, 0x60, 0x60};
+static unsigned char times24_93_bits[] = {
+0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f};
+static unsigned char times24_94_bits[] = {
+0x10, 0x00, 0x38, 0x00, 0x28, 0x00, 0x6c, 0x00, 0x44, 0x00, 0xc6, 0x00, 
+0x82, 0x00, 0x83, 0x01, 0x01, 0x01};
+static unsigned char times24_95_bits[] = {
+0xff, 0x1f, 0xff, 0x1f};
+static unsigned char times24_96_bits[] = {
+0x06, 0x03, 0x01, 0x07, 0x06};
+static unsigned char times24_97_bits[] = {
+0x7c, 0x00, 0xe6, 0x00, 0xc6, 0x00, 0xc0, 0x00, 0xf0, 0x00, 0xdc, 0x00, 
+0xc6, 0x00, 0xc3, 0x00, 0xc3, 0x00, 0xe3, 0x00, 0xdf, 0x00, 0x8e, 0x01};
+static unsigned char times24_98_bits[] = {
+0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x76, 0x00, 
+0xce, 0x01, 0x86, 0x01, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x86, 0x01, 0xce, 0x01, 0x7a, 0x00};
+static unsigned char times24_99_bits[] = {
+0xf8, 0x00, 0xc6, 0x01, 0x82, 0x01, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x01, 0xfe, 0x00, 0x78, 0x00};
+static unsigned char times24_100_bits[] = {
+0xc0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xb8, 0x01, 
+0xce, 0x01, 0x86, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 
+0x83, 0x01, 0x83, 0x01, 0x86, 0x01, 0xce, 0x01, 0x78, 0x03};
+static unsigned char times24_101_bits[] = {
+0x78, 0x00, 0xc6, 0x00, 0x82, 0x01, 0x83, 0x01, 0xff, 0x01, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x01, 0xfe, 0x00, 0x78, 0x00};
+static unsigned char times24_102_bits[] = {
+0x70, 0x68, 0x0c, 0x0c, 0x0c, 0x7f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x1e};
+static unsigned char times24_103_bits[] = {
+0xf8, 0x03, 0xcc, 0x00, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 
+0xcc, 0x00, 0x7c, 0x00, 0x0c, 0x00, 0x06, 0x00, 0xfe, 0x00, 0xfc, 0x03, 
+0x06, 0x06, 0x03, 0x04, 0x03, 0x06, 0x8f, 0x03, 0xfc, 0x00};
+static unsigned char times24_104_bits[] = {
+0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xe6, 0x00, 
+0xf6, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x8f, 0x07};
+static unsigned char times24_105_bits[] = {
+0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times24_106_bits[] = {
+0x0c, 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x07, 0x03};
+static unsigned char times24_107_bits[] = {
+0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xe6, 0x03, 
+0xc6, 0x00, 0x66, 0x00, 0x26, 0x00, 0x16, 0x00, 0x1e, 0x00, 0x36, 0x00, 
+0x76, 0x00, 0xe6, 0x00, 0xc6, 0x01, 0x86, 0x03, 0xcf, 0x07};
+static unsigned char times24_108_bits[] = {
+0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times24_109_bits[] = {
+0xe7, 0x70, 0x00, 0xf6, 0xf9, 0x00, 0x8e, 0xc7, 0x01, 0x06, 0x83, 0x01, 
+0x06, 0x83, 0x01, 0x06, 0x83, 0x01, 0x06, 0x83, 0x01, 0x06, 0x83, 0x01, 
+0x06, 0x83, 0x01, 0x06, 0x83, 0x01, 0x06, 0x83, 0x01, 0x8f, 0xc7, 0x03};
+static unsigned char times24_110_bits[] = {
+0xe7, 0x00, 0xf6, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x8f, 0x07};
+static unsigned char times24_111_bits[] = {
+0x78, 0x00, 0xce, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x86, 0x01, 0xce, 0x01, 0x78, 0x00};
+static unsigned char times24_112_bits[] = {
+0x77, 0x00, 0xce, 0x01, 0x86, 0x01, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x86, 0x01, 0xce, 0x01, 0x76, 0x00, 
+0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0f, 0x00};
+static unsigned char times24_113_bits[] = {
+0xb8, 0x01, 0xce, 0x01, 0x86, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 
+0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x86, 0x01, 0xce, 0x01, 0xb8, 0x01, 
+0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xc0, 0x03};
+static unsigned char times24_114_bits[] = {
+0x67, 0x76, 0x6e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times24_115_bits[] = {
+0x7c, 0x66, 0x43, 0x07, 0x0e, 0x3e, 0x78, 0xe0, 0xc0, 0xc1, 0x63, 0x1f};
+static unsigned char times24_116_bits[] = {
+0x08, 0x0c, 0x0e, 0x7f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x4c, 0x38};
+static unsigned char times24_117_bits[] = {
+0x87, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x8e, 0x03, 0x7c, 0x03, 0x38, 0x07};
+static unsigned char times24_118_bits[] = {
+0x8f, 0x07, 0x06, 0x03, 0x06, 0x01, 0x0c, 0x01, 0x0c, 0x01, 0x8c, 0x00, 
+0x98, 0x00, 0x98, 0x00, 0x58, 0x00, 0x70, 0x00, 0x70, 0x00, 0x20, 0x00};
+static unsigned char times24_119_bits[] = {
+0x8f, 0xe7, 0x01, 0x06, 0xc3, 0x00, 0x06, 0x43, 0x00, 0x0c, 0x43, 0x00, 
+0x0c, 0x43, 0x00, 0x8c, 0x26, 0x00, 0x98, 0x26, 0x00, 0x58, 0x26, 0x00, 
+0x58, 0x14, 0x00, 0x70, 0x1c, 0x00, 0x70, 0x1c, 0x00, 0x20, 0x08, 0x00};
+static unsigned char times24_120_bits[] = {
+0x8f, 0x07, 0x06, 0x03, 0x8c, 0x01, 0x9c, 0x00, 0x58, 0x00, 0x30, 0x00, 
+0x70, 0x00, 0xd8, 0x00, 0xcc, 0x01, 0x84, 0x01, 0x06, 0x03, 0x8f, 0x07};
+static unsigned char times24_121_bits[] = {
+0x8f, 0x07, 0x06, 0x03, 0x06, 0x01, 0x0c, 0x01, 0x0c, 0x01, 0x8c, 0x00, 
+0x98, 0x00, 0x98, 0x00, 0x58, 0x00, 0x70, 0x00, 0x70, 0x00, 0x20, 0x00, 
+0x30, 0x00, 0x10, 0x00, 0x18, 0x00, 0x0f, 0x00, 0x07, 0x00};
+static unsigned char times24_122_bits[] = {
+0xff, 0xc3, 0x61, 0x70, 0x38, 0x18, 0x1c, 0x0c, 0x0e, 0x86, 0xc3, 0xff};
+static unsigned char times24_123_bits[] = {
+0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x08, 0x0c, 0x04, 0x03, 0x04, 
+0x0c, 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0};
+static unsigned char times24_124_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char times24_125_bits[] = {
+0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x10, 0x30, 0x20, 0xc0, 0x20, 
+0x30, 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x07};
+static unsigned char times24_126_bits[] = {
+0x1c, 0x04, 0x3e, 0x06, 0xe3, 0x03, 0xc1, 0x01};
+static unsigned char times24_127_bits[] = {
+0x00};
+static unsigned char times24_128_bits[] = {
+0x00};
+static unsigned char times24_129_bits[] = {
+0x00};
+static unsigned char times24_130_bits[] = {
+0x00};
+static unsigned char times24_131_bits[] = {
+0x00};
+static unsigned char times24_132_bits[] = {
+0x00};
+static unsigned char times24_133_bits[] = {
+0x00};
+static unsigned char times24_134_bits[] = {
+0x00};
+static unsigned char times24_135_bits[] = {
+0x00};
+static unsigned char times24_136_bits[] = {
+0x00};
+static unsigned char times24_137_bits[] = {
+0x00};
+static unsigned char times24_138_bits[] = {
+0x00};
+static unsigned char times24_139_bits[] = {
+0x00};
+static unsigned char times24_140_bits[] = {
+0x00};
+static unsigned char times24_141_bits[] = {
+0x00};
+static unsigned char times24_142_bits[] = {
+0x00};
+static unsigned char times24_143_bits[] = {
+0x00};
+static unsigned char times24_144_bits[] = {
+0x00};
+static unsigned char times24_145_bits[] = {
+0x00};
+static unsigned char times24_146_bits[] = {
+0x00};
+static unsigned char times24_147_bits[] = {
+0x00};
+static unsigned char times24_148_bits[] = {
+0x00};
+static unsigned char times24_149_bits[] = {
+0x00};
+static unsigned char times24_150_bits[] = {
+0x00};
+static unsigned char times24_151_bits[] = {
+0x00};
+static unsigned char times24_152_bits[] = {
+0x00};
+static unsigned char times24_153_bits[] = {
+0x00};
+static unsigned char times24_154_bits[] = {
+0x00};
+static unsigned char times24_155_bits[] = {
+0x00};
+static unsigned char times24_156_bits[] = {
+0x00};
+static unsigned char times24_157_bits[] = {
+0x00};
+static unsigned char times24_158_bits[] = {
+0x00};
+static unsigned char times24_159_bits[] = {
+0x00};
+static unsigned char times24_160_bits[] = {
+0x00};
+static unsigned char times24_161_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char times24_162_bits[] = {
+0x80, 0x00, 0x80, 0x00, 0xf8, 0x00, 0xc6, 0x01, 0xc2, 0x01, 0x23, 0x00, 
+0x23, 0x00, 0x13, 0x00, 0x13, 0x00, 0x13, 0x00, 0x0b, 0x00, 0x0e, 0x01, 
+0xfe, 0x00, 0x7c, 0x00, 0x02, 0x00, 0x02, 0x00};
+static unsigned char times24_163_bits[] = {
+0xf0, 0x00, 0x98, 0x01, 0x8c, 0x01, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x3f, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x1e, 0x02, 0x7d, 0x03, 0xe7, 0x01};
+static unsigned char times24_164_bits[] = {
+0x03, 0x06, 0x77, 0x07, 0xfe, 0x03, 0x8c, 0x01, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x8c, 0x01, 0xfe, 0x03, 0x77, 0x07, 0x03, 0x06};
+static unsigned char times24_165_bits[] = {
+0x1f, 0x3e, 0x0e, 0x0c, 0x0c, 0x04, 0x18, 0x06, 0x18, 0x02, 0x30, 0x03, 
+0x30, 0x01, 0xe0, 0x01, 0xc0, 0x00, 0xf8, 0x07, 0xc0, 0x00, 0xf8, 0x07, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xf0, 0x03};
+static unsigned char times24_166_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char times24_167_bits[] = {
+0x38, 0x64, 0x62, 0x06, 0x0e, 0x1c, 0x3c, 0x72, 0xe1, 0xc1, 0xc3, 0x47, 
+0x2e, 0x1c, 0x38, 0x70, 0x60, 0x46, 0x26, 0x1c};
+static unsigned char times24_168_bits[] = {
+0x33, 0x33};
+static unsigned char times24_169_bits[] = {
+0xe0, 0x0f, 0x00, 0x38, 0x38, 0x00, 0x0c, 0x60, 0x00, 0x86, 0xc7, 0x00, 
+0xe2, 0x8c, 0x00, 0x23, 0x98, 0x01, 0x31, 0x00, 0x01, 0x11, 0x00, 0x01, 
+0x11, 0x00, 0x01, 0x11, 0x00, 0x01, 0x31, 0x00, 0x01, 0x23, 0x98, 0x01, 
+0xe2, 0x8e, 0x00, 0x86, 0xc3, 0x00, 0x0c, 0x60, 0x00, 0x38, 0x38, 0x00, 
+0xe0, 0x0f, 0x00};
+static unsigned char times24_170_bits[] = {
+0x1e, 0x33, 0x30, 0x3e, 0x33, 0x33, 0x6e, 0x00, 0x7e};
+static unsigned char times24_171_bits[] = {
+0x10, 0x01, 0x98, 0x01, 0xcc, 0x00, 0x66, 0x00, 0x33, 0x00, 0x33, 0x00, 
+0x66, 0x00, 0xcc, 0x00, 0x98, 0x01, 0x10, 0x01};
+static unsigned char times24_172_bits[] = {
+0xff, 0x0f, 0xff, 0x0f, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 
+0x00, 0x0c};
+static unsigned char times24_173_bits[] = {
+0x7f, 0x7f};
+static unsigned char times24_174_bits[] = {
+0xe0, 0x0f, 0x00, 0x38, 0x38, 0x00, 0x0c, 0x60, 0x00, 0xe6, 0xc7, 0x00, 
+0x42, 0x8c, 0x00, 0x43, 0x88, 0x01, 0x41, 0x08, 0x01, 0x41, 0x0c, 0x01, 
+0xc1, 0x07, 0x01, 0x41, 0x02, 0x01, 0x41, 0x04, 0x01, 0x43, 0x8c, 0x01, 
+0xe2, 0x98, 0x00, 0x06, 0xc0, 0x00, 0x0c, 0x60, 0x00, 0x38, 0x38, 0x00, 
+0xe0, 0x0f, 0x00};
+static unsigned char times24_175_bits[] = {
+0x3f, 0x3f};
+static unsigned char times24_176_bits[] = {
+0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char times24_177_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xff, 0x0f, 
+0xff, 0x0f, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x00, 0x00, 0xff, 0x0f, 0xff, 0x0f};
+static unsigned char times24_178_bits[] = {
+0x1c, 0x32, 0x31, 0x30, 0x10, 0x08, 0x0c, 0x04, 0x22, 0x3f};
+static unsigned char times24_179_bits[] = {
+0x1c, 0x32, 0x31, 0x10, 0x0c, 0x10, 0x30, 0x31, 0x11, 0x0e};
+static unsigned char times24_180_bits[] = {
+0x18, 0x1c, 0x06, 0x01};
+static unsigned char times24_181_bits[] = {
+0x87, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x8e, 0x03, 0x7e, 0x03, 0x3a, 0x07, 
+0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x07, 0x00, 0x02, 0x00};
+static unsigned char times24_182_bits[] = {
+0xf8, 0x01, 0x9c, 0x00, 0x9e, 0x00, 0x9e, 0x00, 0x9f, 0x00, 0x9f, 0x00, 
+0x9f, 0x00, 0x9e, 0x00, 0x9e, 0x00, 0x9c, 0x00, 0x98, 0x00, 0x90, 0x00, 
+0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 
+0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00};
+static unsigned char times24_183_bits[] = {
+0x03, 0x03};
+static unsigned char times24_184_bits[] = {
+0x08, 0x0c, 0x3c, 0x30, 0x33, 0x1e};
+static unsigned char times24_185_bits[] = {
+0x04, 0x06, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char times24_186_bits[] = {
+0x1e, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1e, 0x00, 0x3f};
+static unsigned char times24_187_bits[] = {
+0x11, 0x00, 0x33, 0x00, 0x66, 0x00, 0xcc, 0x00, 0x98, 0x01, 0x98, 0x01, 
+0xcc, 0x00, 0x66, 0x00, 0x33, 0x00, 0x11, 0x00};
+static unsigned char times24_188_bits[] = {
+0x04, 0x10, 0x06, 0x18, 0x05, 0x0c, 0x04, 0x04, 0x04, 0x06, 0x04, 0x02, 
+0x04, 0x03, 0x84, 0x21, 0x84, 0x30, 0xdf, 0x38, 0x40, 0x28, 0x60, 0x24, 
+0x30, 0x26, 0x10, 0x22, 0x18, 0xff, 0x08, 0x20, 0x0c, 0x20};
+static unsigned char times24_189_bits[] = {
+0x04, 0x10, 0x06, 0x18, 0x05, 0x0c, 0x04, 0x04, 0x04, 0x06, 0x04, 0x02, 
+0x04, 0x03, 0x84, 0x39, 0x84, 0x64, 0xdf, 0x62, 0x40, 0x60, 0x60, 0x20, 
+0x30, 0x10, 0x10, 0x18, 0x18, 0x08, 0x08, 0x44, 0x0c, 0x7e};
+static unsigned char times24_190_bits[] = {
+0x1c, 0x20, 0x00, 0x32, 0x30, 0x00, 0x31, 0x18, 0x00, 0x10, 0x08, 0x00, 
+0x0c, 0x0c, 0x00, 0x10, 0x04, 0x00, 0x30, 0x06, 0x00, 0x31, 0x43, 0x00, 
+0x11, 0x61, 0x00, 0x8e, 0x71, 0x00, 0x80, 0x50, 0x00, 0xc0, 0x48, 0x00, 
+0x60, 0x4c, 0x00, 0x20, 0x44, 0x00, 0x30, 0xfe, 0x01, 0x10, 0x40, 0x00, 
+0x18, 0x40, 0x00};
+static unsigned char times24_191_bits[] = {
+0x30, 0x30, 0x00, 0x00, 0x10, 0x10, 0x18, 0x18, 0x1c, 0x0c, 0x0e, 0x07, 
+0xc3, 0xc3, 0x83, 0xc6, 0x7c};
+static unsigned char times24_192_bits[] = {
+0xc0, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 
+0x80, 0x06, 0x00, 0x40, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x60, 0x0c, 0x00, 
+0x20, 0x0c, 0x00, 0x20, 0x18, 0x00, 0x30, 0x18, 0x00, 0xf0, 0x1f, 0x00, 
+0x10, 0x30, 0x00, 0x18, 0x30, 0x00, 0x08, 0x30, 0x00, 0x08, 0x60, 0x00, 
+0x0c, 0x60, 0x00, 0x3f, 0xf8, 0x01};
+static unsigned char times24_193_bits[] = {
+0x00, 0x0c, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 
+0x80, 0x06, 0x00, 0x40, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x60, 0x0c, 0x00, 
+0x20, 0x0c, 0x00, 0x20, 0x18, 0x00, 0x30, 0x18, 0x00, 0xf0, 0x1f, 0x00, 
+0x10, 0x30, 0x00, 0x18, 0x30, 0x00, 0x08, 0x30, 0x00, 0x08, 0x60, 0x00, 
+0x0c, 0x60, 0x00, 0x3f, 0xf8, 0x01};
+static unsigned char times24_194_bits[] = {
+0x80, 0x01, 0x00, 0xc0, 0x03, 0x00, 0x60, 0x06, 0x00, 0x10, 0x08, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 
+0x80, 0x06, 0x00, 0x40, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x60, 0x0c, 0x00, 
+0x20, 0x0c, 0x00, 0x20, 0x18, 0x00, 0x30, 0x18, 0x00, 0xf0, 0x1f, 0x00, 
+0x10, 0x30, 0x00, 0x18, 0x30, 0x00, 0x08, 0x30, 0x00, 0x08, 0x60, 0x00, 
+0x0c, 0x60, 0x00, 0x3f, 0xf8, 0x01};
+static unsigned char times24_195_bits[] = {
+0xc0, 0x09, 0x00, 0x20, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x80, 0x06, 0x00, 
+0x40, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x60, 0x0c, 0x00, 0x20, 0x0c, 0x00, 
+0x20, 0x18, 0x00, 0x30, 0x18, 0x00, 0xf0, 0x1f, 0x00, 0x10, 0x30, 0x00, 
+0x18, 0x30, 0x00, 0x08, 0x30, 0x00, 0x08, 0x60, 0x00, 0x0c, 0xe0, 0x00, 
+0x3f, 0xf8, 0x01};
+static unsigned char times24_196_bits[] = {
+0x60, 0x0c, 0x00, 0x60, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x80, 0x06, 0x00, 
+0x40, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x60, 0x0c, 0x00, 0x20, 0x0c, 0x00, 
+0x20, 0x18, 0x00, 0x30, 0x18, 0x00, 0xf0, 0x1f, 0x00, 0x10, 0x30, 0x00, 
+0x18, 0x30, 0x00, 0x08, 0x30, 0x00, 0x08, 0x60, 0x00, 0x0c, 0x60, 0x00, 
+0x3f, 0xf8, 0x01};
+static unsigned char times24_197_bits[] = {
+0x80, 0x03, 0x00, 0x40, 0x04, 0x00, 0x40, 0x04, 0x00, 0x80, 0x03, 0x00, 
+0x00, 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x80, 0x06, 0x00, 
+0x40, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x60, 0x0c, 0x00, 0x20, 0x0c, 0x00, 
+0x20, 0x18, 0x00, 0x30, 0x18, 0x00, 0xf0, 0x1f, 0x00, 0x10, 0x30, 0x00, 
+0x18, 0x30, 0x00, 0x08, 0x30, 0x00, 0x08, 0x60, 0x00, 0x0c, 0x60, 0x00, 
+0x3f, 0xf8, 0x01};
+static unsigned char times24_198_bits[] = {
+0xc0, 0xff, 0x07, 0x80, 0x07, 0x06, 0x80, 0x06, 0x04, 0x80, 0x06, 0x04, 
+0x40, 0x06, 0x00, 0x40, 0x06, 0x00, 0x60, 0x06, 0x01, 0x20, 0x06, 0x01, 
+0x20, 0xfe, 0x01, 0x30, 0x06, 0x01, 0xf0, 0x07, 0x01, 0x10, 0x06, 0x00, 
+0x18, 0x06, 0x00, 0x08, 0x06, 0x08, 0x08, 0x06, 0x08, 0x0c, 0x06, 0x0c, 
+0x9f, 0xff, 0x0f};
+static unsigned char times24_199_bits[] = {
+0xe0, 0x27, 0x38, 0x3c, 0x1c, 0x30, 0x06, 0x20, 0x06, 0x20, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x06, 0x00, 0x06, 0x20, 0x1c, 0x10, 0x78, 0x1c, 0xe0, 0x07, 0x80, 0x00, 
+0xc0, 0x00, 0xc0, 0x03, 0x00, 0x03, 0x30, 0x03, 0xe0, 0x01};
+static unsigned char times24_200_bits[] = {
+0x18, 0x00, 0x38, 0x00, 0x60, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x0f, 
+0x0c, 0x0c, 0x0c, 0x08, 0x0c, 0x08, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x02, 
+0x0c, 0x02, 0xfc, 0x03, 0x0c, 0x02, 0x0c, 0x02, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x10, 0x0c, 0x10, 0x0c, 0x18, 0xff, 0x1f};
+static unsigned char times24_201_bits[] = {
+0x00, 0x03, 0x80, 0x03, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0xff, 0x0f, 
+0x0c, 0x0c, 0x0c, 0x08, 0x0c, 0x08, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x02, 
+0x0c, 0x02, 0xfc, 0x03, 0x0c, 0x02, 0x0c, 0x02, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x10, 0x0c, 0x10, 0x0c, 0x18, 0xff, 0x1f};
+static unsigned char times24_202_bits[] = {
+0xc0, 0x00, 0xe0, 0x01, 0x30, 0x03, 0x08, 0x04, 0x00, 0x00, 0xff, 0x0f, 
+0x0c, 0x0c, 0x0c, 0x08, 0x0c, 0x08, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x02, 
+0x0c, 0x02, 0xfc, 0x03, 0x0c, 0x02, 0x0c, 0x02, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x10, 0x0c, 0x10, 0x0c, 0x18, 0xff, 0x1f};
+static unsigned char times24_203_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x0c, 0x0c, 
+0x0c, 0x08, 0x0c, 0x08, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x02, 0x0c, 0x02, 
+0xfc, 0x03, 0x0c, 0x02, 0x0c, 0x02, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x10, 
+0x0c, 0x10, 0x0c, 0x18, 0xff, 0x1f};
+static unsigned char times24_204_bits[] = {
+0x03, 0x07, 0x0c, 0x10, 0x00, 0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3f};
+static unsigned char times24_205_bits[] = {
+0x30, 0x38, 0x0c, 0x02, 0x00, 0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3f};
+static unsigned char times24_206_bits[] = {
+0x18, 0x3c, 0x66, 0x81, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e};
+static unsigned char times24_207_bits[] = {
+0x33, 0x33, 0x00, 0x00, 0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3f};
+static unsigned char times24_208_bits[] = {
+0xfe, 0x07, 0x18, 0x1c, 0x18, 0x38, 0x18, 0x60, 0x18, 0x60, 0x18, 0xc0, 
+0x18, 0xc0, 0x18, 0xc0, 0xff, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 
+0x18, 0x60, 0x18, 0x60, 0x18, 0x38, 0x18, 0x1c, 0xfe, 0x07};
+static unsigned char times24_209_bits[] = {
+0xc0, 0x09, 0x20, 0x07, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf8, 0x0c, 0x20, 
+0x1c, 0x20, 0x1c, 0x20, 0x34, 0x20, 0x64, 0x20, 0x64, 0x20, 0xc4, 0x20, 
+0x84, 0x21, 0x84, 0x21, 0x04, 0x23, 0x04, 0x26, 0x04, 0x26, 0x04, 0x2c, 
+0x04, 0x38, 0x04, 0x38, 0x1f, 0x30};
+static unsigned char times24_210_bits[] = {
+0x60, 0x00, 0xe0, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x00, 0xe0, 0x07, 
+0x38, 0x1c, 0x1c, 0x38, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x06, 0x60, 
+0x06, 0x60, 0x1c, 0x38, 0x38, 0x1c, 0xe0, 0x07};
+static unsigned char times24_211_bits[] = {
+0x00, 0x0c, 0x00, 0x0e, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x07, 
+0x38, 0x1c, 0x1c, 0x38, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x06, 0x60, 
+0x06, 0x60, 0x1c, 0x38, 0x38, 0x1c, 0xe0, 0x07};
+static unsigned char times24_212_bits[] = {
+0x80, 0x01, 0xc0, 0x03, 0x60, 0x06, 0x10, 0x08, 0x00, 0x00, 0xe0, 0x07, 
+0x38, 0x1c, 0x1c, 0x38, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x06, 0x60, 
+0x06, 0x60, 0x1c, 0x38, 0x38, 0x1c, 0xe0, 0x07};
+static unsigned char times24_213_bits[] = {
+0xc0, 0x09, 0x20, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x38, 0x1c, 
+0x1c, 0x38, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x06, 0x60, 0x06, 0x60, 
+0x1c, 0x38, 0x38, 0x1c, 0xe0, 0x07};
+static unsigned char times24_214_bits[] = {
+0x60, 0x06, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x38, 0x1c, 
+0x1c, 0x38, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x06, 0x60, 0x06, 0x60, 
+0x1c, 0x38, 0x38, 0x1c, 0xe0, 0x07};
+static unsigned char times24_215_bits[] = {
+0x01, 0x02, 0x03, 0x03, 0x86, 0x01, 0xcc, 0x00, 0x78, 0x00, 0x30, 0x00, 
+0x78, 0x00, 0xcc, 0x00, 0x86, 0x01, 0x03, 0x03, 0x01, 0x02};
+static unsigned char times24_216_bits[] = {
+0x00, 0x20, 0xe0, 0x27, 0x38, 0x1c, 0x1c, 0x38, 0x06, 0x64, 0x06, 0x62, 
+0x03, 0xc2, 0x03, 0xc1, 0x03, 0xc1, 0x83, 0xc0, 0x83, 0xc0, 0x43, 0xc0, 
+0x43, 0xc0, 0x26, 0x60, 0x16, 0x60, 0x1c, 0x38, 0x38, 0x1c, 0xe4, 0x07, 
+0x04, 0x00};
+static unsigned char times24_217_bits[] = {
+0x60, 0x00, 0xe0, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x00, 0x3f, 0xf8, 
+0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 
+0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 
+0x0c, 0x10, 0x18, 0x10, 0x38, 0x0c, 0xe0, 0x07};
+static unsigned char times24_218_bits[] = {
+0x00, 0x0c, 0x00, 0x0e, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x3f, 0xf8, 
+0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 
+0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 
+0x0c, 0x10, 0x18, 0x10, 0x38, 0x0c, 0xe0, 0x07};
+static unsigned char times24_219_bits[] = {
+0x80, 0x01, 0xc0, 0x03, 0x60, 0x06, 0x10, 0x08, 0x00, 0x00, 0x3f, 0xf8, 
+0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 
+0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 
+0x0c, 0x10, 0x18, 0x10, 0x38, 0x0c, 0xe0, 0x07};
+static unsigned char times24_220_bits[] = {
+0x60, 0x0c, 0x60, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x0c, 0x20, 
+0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 
+0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x10, 
+0x18, 0x10, 0x38, 0x0c, 0xe0, 0x07};
+static unsigned char times24_221_bits[] = {
+0x00, 0x0c, 0x00, 0x0e, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x3f, 0xfc, 
+0x0c, 0x30, 0x1c, 0x10, 0x18, 0x18, 0x38, 0x08, 0x30, 0x0c, 0x60, 0x04, 
+0x60, 0x06, 0xc0, 0x02, 0xc0, 0x03, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 
+0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xe0, 0x07};
+static unsigned char times24_222_bits[] = {
+0x3f, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0xfc, 0x03, 0x0c, 0x0e, 
+0x0c, 0x0c, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x0c, 0x0c, 0x0e, 
+0xfc, 0x03, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x3f, 0x00};
+static unsigned char times24_223_bits[] = {
+0x78, 0x00, 0xcc, 0x00, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 
+0xc6, 0x00, 0x36, 0x00, 0xe6, 0x00, 0xc6, 0x01, 0x86, 0x01, 0x86, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x36, 0x03, 0x36, 0x01, 0xe7, 0x00};
+static unsigned char times24_224_bits[] = {
+0x06, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x20, 0x00, 0x00, 0x00, 0x7c, 0x00, 
+0xe6, 0x00, 0xc6, 0x00, 0xc0, 0x00, 0xf0, 0x00, 0xdc, 0x00, 0xc6, 0x00, 
+0xc3, 0x00, 0xc3, 0x00, 0xe3, 0x00, 0xdf, 0x00, 0x8e, 0x01};
+static unsigned char times24_225_bits[] = {
+0xc0, 0x00, 0xe0, 0x00, 0x30, 0x00, 0x08, 0x00, 0x00, 0x00, 0x7c, 0x00, 
+0xe6, 0x00, 0xc6, 0x00, 0xc0, 0x00, 0xf0, 0x00, 0xdc, 0x00, 0xc6, 0x00, 
+0xc3, 0x00, 0xc3, 0x00, 0xe3, 0x00, 0xdf, 0x00, 0x8e, 0x01};
+static unsigned char times24_226_bits[] = {
+0x18, 0x00, 0x3c, 0x00, 0x24, 0x00, 0x42, 0x00, 0x00, 0x00, 0x7c, 0x00, 
+0xe6, 0x00, 0xc6, 0x00, 0xc0, 0x00, 0xf0, 0x00, 0xdc, 0x00, 0xc6, 0x00, 
+0xc3, 0x00, 0xc3, 0x00, 0xe3, 0x00, 0xdf, 0x00, 0x8e, 0x01};
+static unsigned char times24_227_bits[] = {
+0x5c, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xe6, 0x00, 
+0xc6, 0x00, 0xc0, 0x00, 0xf0, 0x00, 0xdc, 0x00, 0xc6, 0x00, 0xc3, 0x00, 
+0xc3, 0x00, 0xe3, 0x00, 0xdf, 0x00, 0x8e, 0x01};
+static unsigned char times24_228_bits[] = {
+0x66, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xe6, 0x00, 
+0xc6, 0x00, 0xc0, 0x00, 0xf0, 0x00, 0xdc, 0x00, 0xc6, 0x00, 0xc3, 0x00, 
+0xc3, 0x00, 0xe3, 0x00, 0xdf, 0x00, 0x8e, 0x01};
+static unsigned char times24_229_bits[] = {
+0x38, 0x00, 0x44, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x7c, 0x00, 
+0xe6, 0x00, 0xc6, 0x00, 0xc0, 0x00, 0xf0, 0x00, 0xdc, 0x00, 0xc6, 0x00, 
+0xc3, 0x00, 0xc3, 0x00, 0xe3, 0x00, 0xdf, 0x00, 0x8e, 0x01};
+static unsigned char times24_230_bits[] = {
+0x3c, 0x0f, 0xe6, 0x19, 0xc6, 0x30, 0xc0, 0x30, 0xf0, 0x3f, 0xdc, 0x00, 
+0xc6, 0x00, 0xc3, 0x00, 0xc3, 0x00, 0xe3, 0x21, 0xdf, 0x1f, 0x0e, 0x0f};
+static unsigned char times24_231_bits[] = {
+0xf8, 0x00, 0xc6, 0x01, 0x82, 0x01, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x01, 0xfe, 0x00, 0x78, 0x00, 
+0x10, 0x00, 0x18, 0x00, 0x78, 0x00, 0x60, 0x00, 0x66, 0x00, 0x3c, 0x00};
+static unsigned char times24_232_bits[] = {
+0x06, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x20, 0x00, 0x00, 0x00, 0x78, 0x00, 
+0xc6, 0x00, 0x82, 0x01, 0x83, 0x01, 0xff, 0x01, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x07, 0x00, 0x0e, 0x01, 0xfe, 0x00, 0x78, 0x00};
+static unsigned char times24_233_bits[] = {
+0xc0, 0x00, 0xe0, 0x00, 0x30, 0x00, 0x08, 0x00, 0x00, 0x00, 0x78, 0x00, 
+0xc6, 0x00, 0x82, 0x01, 0x83, 0x01, 0xff, 0x01, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x07, 0x00, 0x0e, 0x01, 0xfe, 0x00, 0x78, 0x00};
+static unsigned char times24_234_bits[] = {
+0x30, 0x00, 0x78, 0x00, 0x48, 0x00, 0x84, 0x00, 0x00, 0x00, 0x78, 0x00, 
+0xc6, 0x00, 0x82, 0x01, 0x83, 0x01, 0xff, 0x01, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x07, 0x00, 0x0e, 0x01, 0xfe, 0x00, 0x78, 0x00};
+static unsigned char times24_235_bits[] = {
+0xcc, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xc6, 0x00, 
+0x82, 0x01, 0x83, 0x01, 0xff, 0x01, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x07, 0x00, 0x0e, 0x01, 0xfe, 0x00, 0x78, 0x00};
+static unsigned char times24_236_bits[] = {
+0x03, 0x07, 0x0c, 0x10, 0x00, 0x0e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x1e};
+static unsigned char times24_237_bits[] = {
+0x18, 0x1c, 0x06, 0x01, 0x00, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times24_238_bits[] = {
+0x0c, 0x1e, 0x12, 0x21, 0x00, 0x0e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x1e};
+static unsigned char times24_239_bits[] = {
+0x33, 0x33, 0x00, 0x00, 0x0e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x1e};
+static unsigned char times24_240_bits[] = {
+0x03, 0x00, 0x8e, 0x01, 0x78, 0x00, 0x3c, 0x00, 0x63, 0x00, 0xf8, 0x00, 
+0xce, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x86, 0x01, 0xce, 0x01, 0x78, 0x00};
+static unsigned char times24_241_bits[] = {
+0x38, 0x01, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x00, 0xf6, 0x01, 
+0x8e, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x8f, 0x07};
+static unsigned char times24_242_bits[] = {
+0x0c, 0x00, 0x1c, 0x00, 0x30, 0x00, 0x40, 0x00, 0x00, 0x00, 0x78, 0x00, 
+0xce, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x86, 0x01, 0xce, 0x01, 0x78, 0x00};
+static unsigned char times24_243_bits[] = {
+0x80, 0x01, 0xc0, 0x01, 0x60, 0x00, 0x10, 0x00, 0x00, 0x00, 0x78, 0x00, 
+0xce, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x86, 0x01, 0xce, 0x01, 0x78, 0x00};
+static unsigned char times24_244_bits[] = {
+0x30, 0x00, 0x78, 0x00, 0x48, 0x00, 0x84, 0x00, 0x00, 0x00, 0x78, 0x00, 
+0xce, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x86, 0x01, 0xce, 0x01, 0x78, 0x00};
+static unsigned char times24_245_bits[] = {
+0x38, 0x01, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xce, 0x01, 
+0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x86, 0x01, 0xce, 0x01, 0x78, 0x00};
+static unsigned char times24_246_bits[] = {
+0xcc, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xce, 0x01, 
+0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x86, 0x01, 0xce, 0x01, 0x78, 0x00};
+static unsigned char times24_247_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0xff, 0x0f, 
+0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char times24_248_bits[] = {
+0x00, 0x03, 0x78, 0x03, 0xce, 0x01, 0xc6, 0x01, 0x63, 0x03, 0x23, 0x03, 
+0x33, 0x03, 0x13, 0x03, 0x1b, 0x03, 0x0b, 0x03, 0x8e, 0x01, 0xce, 0x01, 
+0x7b, 0x00, 0x03, 0x00};
+static unsigned char times24_249_bits[] = {
+0x0c, 0x00, 0x1c, 0x00, 0x30, 0x00, 0x40, 0x00, 0x00, 0x00, 0x87, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x8e, 0x03, 0x7c, 0x03, 0x38, 0x07};
+static unsigned char times24_250_bits[] = {
+0x80, 0x01, 0xc0, 0x01, 0x60, 0x00, 0x10, 0x00, 0x00, 0x00, 0x87, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x8e, 0x03, 0x7c, 0x03, 0x38, 0x07};
+static unsigned char times24_251_bits[] = {
+0x30, 0x00, 0x78, 0x00, 0x48, 0x00, 0x84, 0x00, 0x00, 0x00, 0x87, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x8e, 0x03, 0x7c, 0x03, 0x38, 0x07};
+static unsigned char times24_252_bits[] = {
+0xcc, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x8e, 0x03, 0x7c, 0x03, 0x38, 0x07};
+static unsigned char times24_253_bits[] = {
+0x80, 0x01, 0xc0, 0x01, 0x60, 0x00, 0x10, 0x00, 0x00, 0x00, 0x8f, 0x07, 
+0x06, 0x03, 0x06, 0x01, 0x0c, 0x01, 0x0c, 0x01, 0x8c, 0x00, 0x98, 0x00, 
+0x98, 0x00, 0x58, 0x00, 0x70, 0x00, 0x70, 0x00, 0x20, 0x00, 0x30, 0x00, 
+0x10, 0x00, 0x18, 0x00, 0x0f, 0x00, 0x07, 0x00};
+static unsigned char times24_254_bits[] = {
+0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x76, 0x00, 
+0xce, 0x01, 0x86, 0x01, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x86, 0x01, 0xce, 0x01, 0x76, 0x00, 0x06, 0x00, 
+0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0f, 0x00};
+static unsigned char times24_255_bits[] = {
+0xcc, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x07, 0x06, 0x03, 
+0x06, 0x01, 0x0c, 0x01, 0x0c, 0x01, 0x8c, 0x00, 0x98, 0x00, 0x98, 0x00, 
+0x58, 0x00, 0x70, 0x00, 0x70, 0x00, 0x20, 0x00, 0x30, 0x00, 0x10, 0x00, 
+0x18, 0x00, 0x0f, 0x00, 0x07, 0x00};
+static RotFont times24font[] = {
+{5, 1, 1, times24_0_bits},
+{5, 1, 1, times24_1_bits},
+{5, 1, 1, times24_2_bits},
+{5, 1, 1, times24_3_bits},
+{5, 1, 1, times24_4_bits},
+{5, 1, 1, times24_5_bits},
+{5, 1, 1, times24_6_bits},
+{5, 1, 1, times24_7_bits},
+{5, 1, 1, times24_8_bits},
+{5, 1, 1, times24_9_bits},
+{5, 1, 1, times24_10_bits},
+{5, 1, 1, times24_11_bits},
+{5, 1, 1, times24_12_bits},
+{5, 1, 1, times24_13_bits},
+{5, 1, 1, times24_14_bits},
+{5, 1, 1, times24_15_bits},
+{5, 1, 1, times24_16_bits},
+{5, 1, 1, times24_17_bits},
+{5, 1, 1, times24_18_bits},
+{5, 1, 1, times24_19_bits},
+{5, 1, 1, times24_20_bits},
+{5, 1, 1, times24_21_bits},
+{5, 1, 1, times24_22_bits},
+{5, 1, 1, times24_23_bits},
+{5, 1, 1, times24_24_bits},
+{5, 1, 1, times24_25_bits},
+{5, 1, 1, times24_26_bits},
+{5, 1, 1, times24_27_bits},
+{5, 1, 1, times24_28_bits},
+{5, 1, 1, times24_29_bits},
+{5, 1, 1, times24_30_bits},
+{5, 1, 1, times24_31_bits},
+{10, 1, 1, times24_32_bits},
+{2, 17, 17, times24_33_bits},
+{6, 5, 17, times24_34_bits},
+{11, 17, 17, times24_35_bits},
+{11, 21, 19, times24_36_bits},
+{17, 16, 16, times24_37_bits},
+{16, 17, 17, times24_38_bits},
+{3, 5, 17, times24_39_bits},
+{6, 22, 17, times24_40_bits},
+{6, 22, 17, times24_41_bits},
+{9, 9, 17, times24_42_bits},
+{12, 12, 13, times24_43_bits},
+{3, 5, 2, times24_44_bits},
+{12, 2, 8, times24_45_bits},
+{2, 2, 2, times24_46_bits},
+{8, 20, 17, times24_47_bits},
+{10, 17, 17, times24_48_bits},
+{8, 17, 17, times24_49_bits},
+{10, 17, 17, times24_50_bits},
+{9, 17, 17, times24_51_bits},
+{10, 17, 17, times24_52_bits},
+{10, 17, 17, times24_53_bits},
+{10, 17, 17, times24_54_bits},
+{10, 17, 17, times24_55_bits},
+{10, 17, 17, times24_56_bits},
+{10, 17, 17, times24_57_bits},
+{2, 11, 11, times24_58_bits},
+{3, 14, 11, times24_59_bits},
+{11, 11, 12, times24_60_bits},
+{12, 6, 10, times24_61_bits},
+{11, 11, 12, times24_62_bits},
+{8, 17, 17, times24_63_bits},
+{18, 20, 17, times24_64_bits},
+{17, 17, 17, times24_65_bits},
+{14, 17, 17, times24_66_bits},
+{14, 17, 17, times24_67_bits},
+{15, 17, 17, times24_68_bits},
+{13, 17, 17, times24_69_bits},
+{12, 17, 17, times24_70_bits},
+{16, 17, 17, times24_71_bits},
+{17, 17, 17, times24_72_bits},
+{6, 17, 17, times24_73_bits},
+{9, 17, 17, times24_74_bits},
+{16, 17, 17, times24_75_bits},
+{13, 17, 17, times24_76_bits},
+{21, 17, 17, times24_77_bits},
+{16, 17, 17, times24_78_bits},
+{16, 17, 17, times24_79_bits},
+{13, 17, 17, times24_80_bits},
+{16, 22, 17, times24_81_bits},
+{15, 17, 17, times24_82_bits},
+{11, 17, 17, times24_83_bits},
+{14, 17, 17, times24_84_bits},
+{16, 17, 17, times24_85_bits},
+{17, 17, 17, times24_86_bits},
+{23, 17, 17, times24_87_bits},
+{18, 17, 17, times24_88_bits},
+{16, 17, 17, times24_89_bits},
+{13, 17, 17, times24_90_bits},
+{5, 21, 17, times24_91_bits},
+{7, 17, 17, times24_92_bits},
+{5, 21, 17, times24_93_bits},
+{9, 9, 17, times24_94_bits},
+{13, 2, -3, times24_95_bits},
+{3, 5, 17, times24_96_bits},
+{9, 12, 12, times24_97_bits},
+{10, 17, 17, times24_98_bits},
+{9, 12, 12, times24_99_bits},
+{10, 17, 17, times24_100_bits},
+{9, 12, 12, times24_101_bits},
+{7, 17, 17, times24_102_bits},
+{11, 17, 12, times24_103_bits},
+{11, 17, 17, times24_104_bits},
+{4, 17, 17, times24_105_bits},
+{4, 22, 17, times24_106_bits},
+{11, 17, 17, times24_107_bits},
+{4, 17, 17, times24_108_bits},
+{18, 12, 12, times24_109_bits},
+{11, 12, 12, times24_110_bits},
+{10, 12, 12, times24_111_bits},
+{10, 17, 12, times24_112_bits},
+{10, 17, 12, times24_113_bits},
+{7, 12, 12, times24_114_bits},
+{8, 12, 12, times24_115_bits},
+{7, 15, 15, times24_116_bits},
+{11, 12, 12, times24_117_bits},
+{11, 12, 12, times24_118_bits},
+{17, 12, 12, times24_119_bits},
+{11, 12, 12, times24_120_bits},
+{11, 17, 12, times24_121_bits},
+{8, 12, 12, times24_122_bits},
+{8, 22, 17, times24_123_bits},
+{2, 17, 17, times24_124_bits},
+{8, 22, 17, times24_125_bits},
+{11, 4, 9, times24_126_bits},
+{5, 1, 1, times24_127_bits},
+{5, 1, 1, times24_128_bits},
+{5, 1, 1, times24_129_bits},
+{5, 1, 1, times24_130_bits},
+{5, 1, 1, times24_131_bits},
+{5, 1, 1, times24_132_bits},
+{5, 1, 1, times24_133_bits},
+{5, 1, 1, times24_134_bits},
+{5, 1, 1, times24_135_bits},
+{5, 1, 1, times24_136_bits},
+{5, 1, 1, times24_137_bits},
+{5, 1, 1, times24_138_bits},
+{5, 1, 1, times24_139_bits},
+{5, 1, 1, times24_140_bits},
+{5, 1, 1, times24_141_bits},
+{5, 1, 1, times24_142_bits},
+{5, 1, 1, times24_143_bits},
+{5, 1, 1, times24_144_bits},
+{5, 1, 1, times24_145_bits},
+{5, 1, 1, times24_146_bits},
+{5, 1, 1, times24_147_bits},
+{5, 1, 1, times24_148_bits},
+{5, 1, 1, times24_149_bits},
+{5, 1, 1, times24_150_bits},
+{5, 1, 1, times24_151_bits},
+{5, 1, 1, times24_152_bits},
+{5, 1, 1, times24_153_bits},
+{5, 1, 1, times24_154_bits},
+{5, 1, 1, times24_155_bits},
+{5, 1, 1, times24_156_bits},
+{5, 1, 1, times24_157_bits},
+{5, 1, 1, times24_158_bits},
+{5, 1, 1, times24_159_bits},
+{1, 1, 1, times24_160_bits},
+{2, 17, 12, times24_161_bits},
+{9, 16, 14, times24_162_bits},
+{10, 17, 17, times24_163_bits},
+{11, 12, 15, times24_164_bits},
+{14, 17, 17, times24_165_bits},
+{2, 17, 17, times24_166_bits},
+{8, 20, 18, times24_167_bits},
+{6, 2, 16, times24_168_bits},
+{17, 17, 17, times24_169_bits},
+{7, 9, 17, times24_170_bits},
+{9, 10, 11, times24_171_bits},
+{12, 7, 10, times24_172_bits},
+{7, 2, 7, times24_173_bits},
+{17, 17, 17, times24_174_bits},
+{6, 2, 16, times24_175_bits},
+{7, 7, 17, times24_176_bits},
+{12, 15, 15, times24_177_bits},
+{6, 10, 17, times24_178_bits},
+{6, 10, 17, times24_179_bits},
+{5, 4, 17, times24_180_bits},
+{11, 17, 12, times24_181_bits},
+{9, 22, 17, times24_182_bits},
+{2, 2, 8, times24_183_bits},
+{6, 6, 0, times24_184_bits},
+{5, 10, 17, times24_185_bits},
+{6, 9, 17, times24_186_bits},
+{9, 10, 11, times24_187_bits},
+{16, 17, 17, times24_188_bits},
+{15, 17, 17, times24_189_bits},
+{17, 17, 17, times24_190_bits},
+{8, 17, 12, times24_191_bits},
+{17, 22, 22, times24_192_bits},
+{17, 22, 22, times24_193_bits},
+{17, 22, 22, times24_194_bits},
+{17, 21, 21, times24_195_bits},
+{17, 21, 21, times24_196_bits},
+{17, 21, 21, times24_197_bits},
+{20, 17, 17, times24_198_bits},
+{14, 23, 17, times24_199_bits},
+{13, 22, 22, times24_200_bits},
+{13, 22, 22, times24_201_bits},
+{13, 22, 22, times24_202_bits},
+{13, 21, 21, times24_203_bits},
+{6, 22, 22, times24_204_bits},
+{6, 22, 22, times24_205_bits},
+{8, 22, 22, times24_206_bits},
+{6, 21, 21, times24_207_bits},
+{16, 17, 17, times24_208_bits},
+{16, 21, 21, times24_209_bits},
+{16, 22, 22, times24_210_bits},
+{16, 22, 22, times24_211_bits},
+{16, 22, 22, times24_212_bits},
+{16, 21, 21, times24_213_bits},
+{16, 21, 21, times24_214_bits},
+{10, 11, 12, times24_215_bits},
+{16, 19, 18, times24_216_bits},
+{16, 22, 22, times24_217_bits},
+{16, 22, 22, times24_218_bits},
+{16, 22, 22, times24_219_bits},
+{16, 21, 21, times24_220_bits},
+{16, 22, 22, times24_221_bits},
+{13, 17, 17, times24_222_bits},
+{10, 17, 17, times24_223_bits},
+{9, 17, 17, times24_224_bits},
+{9, 17, 17, times24_225_bits},
+{9, 17, 17, times24_226_bits},
+{9, 16, 16, times24_227_bits},
+{9, 16, 16, times24_228_bits},
+{9, 17, 17, times24_229_bits},
+{14, 12, 12, times24_230_bits},
+{9, 18, 12, times24_231_bits},
+{9, 17, 17, times24_232_bits},
+{9, 17, 17, times24_233_bits},
+{9, 17, 17, times24_234_bits},
+{9, 16, 16, times24_235_bits},
+{5, 17, 17, times24_236_bits},
+{5, 17, 17, times24_237_bits},
+{6, 17, 17, times24_238_bits},
+{6, 16, 16, times24_239_bits},
+{10, 17, 17, times24_240_bits},
+{11, 16, 16, times24_241_bits},
+{10, 17, 17, times24_242_bits},
+{10, 17, 17, times24_243_bits},
+{10, 17, 17, times24_244_bits},
+{10, 16, 16, times24_245_bits},
+{10, 16, 16, times24_246_bits},
+{12, 10, 12, times24_247_bits},
+{10, 14, 13, times24_248_bits},
+{11, 17, 17, times24_249_bits},
+{11, 17, 17, times24_250_bits},
+{11, 17, 17, times24_251_bits},
+{11, 16, 16, times24_252_bits},
+{11, 22, 17, times24_253_bits},
+{10, 22, 17, times24_254_bits},
+{11, 21, 16, times24_255_bits}};
Index: /tags/start/Ohana/src/kapa/rotfont/times8.bdf
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/times8.bdf	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/times8.bdf	(revision 12606)
@@ -0,0 +1,2435 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Times-Medium-R-Normal--8-80-75-75-P-44-ISO8859-1
+SIZE 8 75 75
+FONTBOUNDINGBOX 9 10 -1 -2
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Times"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 8
+POINT_SIZE 80
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 44
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 5
+X_HEIGHT 4
+FACE_NAME "Times Roman"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Times is a trademark of Linotype-Hell AG and/or its subsidiaries."
+_DEC_DEVICE_FONTNAMES "PS=Times-Roman"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Times Roman"
+FONT "-Adobe-Times-Medium-R-Normal--8-80-75-75-P-44-ISO8859-1"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 5
+DEFAULT_CHAR 32
+FONT_ASCENT 7
+FONT_DESCENT 2
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 6 1 0
+BITMAP
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 2 0 3
+BITMAP
+a0
+a0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 5 0 0
+BITMAP
+50
+f0
+50
+f0
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 -1
+BITMAP
+40
+60
+80
+60
+a0
+c0
+40
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+c8
+d0
+20
+58
+98
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+20
+50
+60
+a8
+90
+78
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 2 1 4
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 7 1 -1
+BITMAP
+40
+80
+80
+80
+80
+80
+40
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 7 0 -1
+BITMAP
+80
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 3 1 2
+BITMAP
+a0
+40
+a0
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+20
+20
+f0
+20
+20
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 2 1 -1
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 1 1 2
+BITMAP
+f0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 1 0
+BITMAP
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 7 0 -1
+BITMAP
+20
+20
+40
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+40
+a0
+a0
+a0
+40
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+40
+c0
+40
+40
+e0
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+c0
+20
+40
+80
+e0
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+c0
+20
+40
+20
+c0
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 5 0 0
+BITMAP
+20
+60
+a0
+f0
+20
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+e0
+80
+60
+20
+c0
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+60
+80
+c0
+a0
+40
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+e0
+20
+40
+80
+80
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+40
+a0
+40
+a0
+40
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+40
+a0
+60
+20
+c0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 3 1 0
+BITMAP
+80
+00
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 4 1 -1
+BITMAP
+40
+00
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+20
+40
+80
+40
+20
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 3 0 1
+BITMAP
+f0
+00
+f0
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 1 0
+BITMAP
+80
+40
+20
+40
+80
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 5 0 0
+BITMAP
+c0
+20
+40
+00
+40
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 6 7 0 -1
+BITMAP
+78
+84
+9c
+a4
+bc
+80
+78
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+20
+50
+70
+50
+d8
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+e0
+50
+60
+50
+e0
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+70
+88
+80
+88
+70
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+f0
+48
+48
+48
+f0
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+f0
+40
+60
+40
+f0
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+f0
+40
+70
+40
+c0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+70
+80
+b8
+88
+70
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 5 0 0
+BITMAP
+cc
+48
+78
+48
+cc
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 5 0 0
+BITMAP
+e0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 5 0 0
+BITMAP
+c0
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+c8
+50
+60
+50
+d8
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+e0
+40
+40
+50
+f0
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 7 5 0 0
+BITMAP
+ee
+6c
+54
+54
+c6
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 5 0 0
+BITMAP
+cc
+68
+68
+58
+c8
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+70
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+BITMAP
+f0
+48
+70
+40
+c0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 -2
+BITMAP
+70
+88
+88
+88
+70
+20
+10
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+e0
+50
+60
+50
+d8
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+70
+80
+60
+10
+e0
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+BITMAP
+f8
+a8
+20
+20
+70
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 5 0 0
+BITMAP
+cc
+48
+48
+48
+30
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+d8
+50
+50
+20
+20
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 8 5 0 0
+BITMAP
+d3
+52
+4a
+5a
+2c
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 5 0 0
+BITMAP
+cc
+30
+30
+48
+cc
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+d8
+50
+20
+20
+70
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 1 0
+BITMAP
+f0
+a0
+40
+90
+f0
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 7 0 -1
+BITMAP
+c0
+80
+80
+80
+80
+80
+c0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 7 0 -1
+BITMAP
+80
+80
+40
+40
+40
+20
+20
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 7 0 -1
+BITMAP
+c0
+40
+40
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 2 1 4
+BITMAP
+40
+a0
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 1 0 -1
+BITMAP
+f0
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 2 1 4
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 4 0 0
+BITMAP
+80
+40
+c0
+c0
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+80
+c0
+a0
+a0
+c0
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 2 4 0 0
+BITMAP
+40
+80
+80
+40
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+20
+60
+a0
+a0
+60
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+40
+e0
+80
+40
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 5 0 0
+BITMAP
+20
+40
+e0
+40
+40
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 5 0 -1
+BITMAP
+70
+a0
+40
+a0
+40
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+80
+c0
+a0
+a0
+a0
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 6 0 0
+BITMAP
+80
+00
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 8 -1 -2
+BITMAP
+40
+00
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+80
+a0
+c0
+c0
+a0
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 1 5 0 0
+BITMAP
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 4 0 0
+BITMAP
+d0
+a8
+a8
+a8
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+c0
+a0
+a0
+a0
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+40
+a0
+a0
+40
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 -2
+BITMAP
+c0
+a0
+a0
+c0
+80
+80
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 -2
+BITMAP
+60
+a0
+a0
+60
+20
+20
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 4 0 0
+BITMAP
+a0
+c0
+80
+80
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 4 0 0
+BITMAP
+c0
+80
+40
+c0
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 5 0 0
+BITMAP
+80
+c0
+80
+80
+40
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+a0
+a0
+a0
+40
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 4 0 0
+BITMAP
+a8
+a8
+a8
+50
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+90
+60
+60
+90
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 -2
+BITMAP
+a0
+a0
+a0
+40
+40
+80
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+e0
+40
+80
+e0
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 7 0 -1
+BITMAP
+20
+40
+40
+c0
+40
+40
+20
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 7 0 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 7 0 -1
+BITMAP
+80
+40
+40
+60
+40
+40
+80
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 2 0 2
+BITMAP
+68
+b0
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 7 0 -2
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 -1
+BITMAP
+40
+60
+80
+80
+60
+40
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 5 0 0
+BITMAP
+20
+40
+e0
+40
+f0
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 4 0 0
+BITMAP
+90
+60
+60
+90
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+88
+50
+f8
+20
+20
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 7 0 -1
+BITMAP
+80
+80
+80
+00
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 -1
+BITMAP
+60
+80
+c0
+a0
+60
+20
+c0
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 1 1 6
+BITMAP
+90
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 6 7 1 -1
+BITMAP
+78
+84
+94
+a4
+94
+84
+78
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 5 0 1
+BITMAP
+80
+40
+c0
+00
+c0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 4 0 0
+BITMAP
+50
+a0
+a0
+50
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 3 1 1
+BITMAP
+f0
+10
+10
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 1 0 2
+BITMAP
+c0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 6 7 1 -1
+BITMAP
+78
+b4
+ac
+b4
+ac
+84
+78
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 1 0 6
+BITMAP
+e0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 3 0 2
+BITMAP
+40
+a0
+40
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+BITMAP
+40
+e0
+40
+00
+e0
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 4 0 2
+BITMAP
+80
+40
+80
+c0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 5 0 1
+BITMAP
+80
+40
+80
+40
+80
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 2 0 5
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 5 0 -1
+BITMAP
+a0
+a0
+a0
+d0
+80
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f8
+d0
+d0
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 0 2
+BITMAP
+80
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 2 0 -2
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 4 0 2
+BITMAP
+c0
+40
+40
+e0
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 5 0 1
+BITMAP
+40
+a0
+40
+00
+e0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 4 0 0
+BITMAP
+a0
+50
+50
+a0
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 7 0 -1
+BITMAP
+44
+48
+50
+24
+4c
+9c
+04
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 7 0 -1
+BITMAP
+44
+48
+50
+28
+44
+88
+0c
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 7 0 -1
+BITMAP
+80
+44
+88
+54
+ac
+5c
+04
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 6 0 -1
+BITMAP
+40
+00
+40
+80
+80
+40
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+40
+20
+00
+20
+20
+50
+70
+d8
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+10
+20
+00
+20
+20
+50
+70
+d8
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+20
+50
+00
+20
+20
+50
+70
+d8
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+28
+50
+00
+20
+20
+50
+70
+d8
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+50
+00
+20
+20
+50
+70
+d8
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+20
+50
+20
+20
+20
+50
+70
+d8
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 5 0 0
+BITMAP
+3c
+50
+7c
+50
+dc
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 -2
+BITMAP
+70
+88
+80
+88
+70
+20
+40
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 0 0
+BITMAP
+40
+20
+00
+f0
+40
+60
+40
+f0
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 0 0
+BITMAP
+10
+20
+00
+f0
+40
+60
+40
+f0
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 0 0
+BITMAP
+20
+50
+00
+f0
+40
+60
+40
+f0
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 0 0
+BITMAP
+50
+00
+f0
+40
+60
+40
+f0
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 8 0 0
+BITMAP
+80
+40
+00
+e0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 8 0 0
+BITMAP
+20
+40
+00
+e0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 8 0 0
+BITMAP
+40
+a0
+00
+e0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 7 0 0
+BITMAP
+a0
+00
+e0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+f0
+48
+e8
+48
+f0
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 8 0 0
+BITMAP
+28
+50
+00
+cc
+68
+58
+48
+c8
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+40
+20
+00
+70
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+10
+20
+00
+70
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+20
+50
+00
+70
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+28
+50
+00
+70
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+50
+00
+70
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+90
+60
+60
+90
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 -1
+BITMAP
+08
+70
+98
+a8
+c8
+70
+80
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 8 0 0
+BITMAP
+20
+10
+00
+cc
+48
+48
+48
+30
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 8 0 0
+BITMAP
+08
+10
+00
+cc
+48
+48
+48
+30
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 8 0 0
+BITMAP
+10
+28
+00
+cc
+48
+48
+48
+30
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+28
+00
+cc
+48
+48
+48
+30
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+10
+20
+00
+d8
+50
+50
+20
+20
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+c0
+60
+50
+60
+c0
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+a0
+90
+a0
+80
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 7 0 0
+BITMAP
+80
+40
+00
+80
+40
+c0
+c0
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 7 0 0
+BITMAP
+40
+80
+00
+80
+40
+c0
+c0
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 7 0 0
+BITMAP
+40
+a0
+00
+80
+40
+c0
+c0
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 4 7 0 0
+BITMAP
+50
+a0
+00
+80
+40
+c0
+c0
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 7 0 0
+BITMAP
+a0
+00
+00
+80
+40
+c0
+c0
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 7 0 0
+BITMAP
+40
+a0
+40
+80
+40
+c0
+c0
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 4 0 0
+BITMAP
+90
+78
+e0
+d0
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 2 5 1 -1
+BITMAP
+40
+80
+80
+40
+80
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+80
+40
+00
+40
+e0
+80
+40
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+20
+40
+00
+40
+e0
+80
+40
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+40
+a0
+00
+40
+e0
+80
+40
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+a0
+00
+00
+40
+e0
+80
+40
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 7 0 0
+BITMAP
+80
+40
+00
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 7 0 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 7 -1 0
+BITMAP
+40
+a0
+00
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 6 -1 0
+BITMAP
+a0
+00
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 6 0 0
+BITMAP
+a0
+40
+a0
+50
+50
+20
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 7 0 0
+BITMAP
+50
+a0
+00
+c0
+a0
+a0
+a0
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+80
+40
+00
+40
+a0
+a0
+40
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+20
+40
+00
+40
+a0
+a0
+40
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+40
+a0
+00
+40
+a0
+a0
+40
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 7 0 0
+BITMAP
+50
+a0
+00
+40
+a0
+a0
+40
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+a0
+00
+00
+40
+a0
+a0
+40
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+40
+00
+e0
+00
+40
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 -1
+BITMAP
+20
+60
+a0
+a0
+c0
+80
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+80
+40
+00
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+20
+40
+00
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+40
+a0
+00
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+a0
+00
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 9 0 -2
+BITMAP
+20
+40
+00
+a0
+a0
+a0
+40
+40
+80
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 7 -1 -2
+BITMAP
+c0
+60
+50
+50
+60
+40
+c0
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 8 0 -2
+BITMAP
+a0
+00
+a0
+a0
+a0
+40
+40
+80
+ENDCHAR
+ENDFONT
Index: /tags/start/Ohana/src/kapa/rotfont/times8.h
===================================================================
--- /tags/start/Ohana/src/kapa/rotfont/times8.h	(revision 12606)
+++ /tags/start/Ohana/src/kapa/rotfont/times8.h	(revision 12606)
@@ -0,0 +1,769 @@
+static unsigned char times8_0_bits[] = {
+0x00};
+static unsigned char times8_1_bits[] = {
+0x00};
+static unsigned char times8_2_bits[] = {
+0x00};
+static unsigned char times8_3_bits[] = {
+0x00};
+static unsigned char times8_4_bits[] = {
+0x00};
+static unsigned char times8_5_bits[] = {
+0x00};
+static unsigned char times8_6_bits[] = {
+0x00};
+static unsigned char times8_7_bits[] = {
+0x00};
+static unsigned char times8_8_bits[] = {
+0x00};
+static unsigned char times8_9_bits[] = {
+0x00};
+static unsigned char times8_10_bits[] = {
+0x00};
+static unsigned char times8_11_bits[] = {
+0x00};
+static unsigned char times8_12_bits[] = {
+0x00};
+static unsigned char times8_13_bits[] = {
+0x00};
+static unsigned char times8_14_bits[] = {
+0x00};
+static unsigned char times8_15_bits[] = {
+0x00};
+static unsigned char times8_16_bits[] = {
+0x00};
+static unsigned char times8_17_bits[] = {
+0x00};
+static unsigned char times8_18_bits[] = {
+0x00};
+static unsigned char times8_19_bits[] = {
+0x00};
+static unsigned char times8_20_bits[] = {
+0x00};
+static unsigned char times8_21_bits[] = {
+0x00};
+static unsigned char times8_22_bits[] = {
+0x00};
+static unsigned char times8_23_bits[] = {
+0x00};
+static unsigned char times8_24_bits[] = {
+0x00};
+static unsigned char times8_25_bits[] = {
+0x00};
+static unsigned char times8_26_bits[] = {
+0x00};
+static unsigned char times8_27_bits[] = {
+0x00};
+static unsigned char times8_28_bits[] = {
+0x00};
+static unsigned char times8_29_bits[] = {
+0x00};
+static unsigned char times8_30_bits[] = {
+0x00};
+static unsigned char times8_31_bits[] = {
+0x00};
+static unsigned char times8_32_bits[] = {
+0x00};
+static unsigned char times8_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x00, 0x01};
+static unsigned char times8_34_bits[] = {
+0x05, 0x05};
+static unsigned char times8_35_bits[] = {
+0x0a, 0x0f, 0x0a, 0x0f, 0x0a};
+static unsigned char times8_36_bits[] = {
+0x02, 0x06, 0x01, 0x06, 0x05, 0x03, 0x02};
+static unsigned char times8_37_bits[] = {
+0x13, 0x0b, 0x04, 0x1a, 0x19};
+static unsigned char times8_38_bits[] = {
+0x04, 0x0a, 0x06, 0x15, 0x09, 0x1e};
+static unsigned char times8_39_bits[] = {
+0x01, 0x01};
+static unsigned char times8_40_bits[] = {
+0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02};
+static unsigned char times8_41_bits[] = {
+0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char times8_42_bits[] = {
+0x05, 0x02, 0x05};
+static unsigned char times8_43_bits[] = {
+0x04, 0x04, 0x0f, 0x04, 0x04};
+static unsigned char times8_44_bits[] = {
+0x02, 0x01};
+static unsigned char times8_45_bits[] = {
+0x0f};
+static unsigned char times8_46_bits[] = {
+0x01};
+static unsigned char times8_47_bits[] = {
+0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01};
+static unsigned char times8_48_bits[] = {
+0x02, 0x05, 0x05, 0x05, 0x02};
+static unsigned char times8_49_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x07};
+static unsigned char times8_50_bits[] = {
+0x03, 0x04, 0x02, 0x01, 0x07};
+static unsigned char times8_51_bits[] = {
+0x03, 0x04, 0x02, 0x04, 0x03};
+static unsigned char times8_52_bits[] = {
+0x04, 0x06, 0x05, 0x0f, 0x04};
+static unsigned char times8_53_bits[] = {
+0x07, 0x01, 0x06, 0x04, 0x03};
+static unsigned char times8_54_bits[] = {
+0x06, 0x01, 0x03, 0x05, 0x02};
+static unsigned char times8_55_bits[] = {
+0x07, 0x04, 0x02, 0x01, 0x01};
+static unsigned char times8_56_bits[] = {
+0x02, 0x05, 0x02, 0x05, 0x02};
+static unsigned char times8_57_bits[] = {
+0x02, 0x05, 0x06, 0x04, 0x03};
+static unsigned char times8_58_bits[] = {
+0x01, 0x00, 0x01};
+static unsigned char times8_59_bits[] = {
+0x02, 0x00, 0x02, 0x01};
+static unsigned char times8_60_bits[] = {
+0x04, 0x02, 0x01, 0x02, 0x04};
+static unsigned char times8_61_bits[] = {
+0x0f, 0x00, 0x0f};
+static unsigned char times8_62_bits[] = {
+0x01, 0x02, 0x04, 0x02, 0x01};
+static unsigned char times8_63_bits[] = {
+0x03, 0x04, 0x02, 0x00, 0x02};
+static unsigned char times8_64_bits[] = {
+0x1e, 0x21, 0x39, 0x25, 0x3d, 0x01, 0x1e};
+static unsigned char times8_65_bits[] = {
+0x04, 0x0a, 0x0e, 0x0a, 0x1b};
+static unsigned char times8_66_bits[] = {
+0x07, 0x0a, 0x06, 0x0a, 0x07};
+static unsigned char times8_67_bits[] = {
+0x0e, 0x11, 0x01, 0x11, 0x0e};
+static unsigned char times8_68_bits[] = {
+0x0f, 0x12, 0x12, 0x12, 0x0f};
+static unsigned char times8_69_bits[] = {
+0x0f, 0x02, 0x06, 0x02, 0x0f};
+static unsigned char times8_70_bits[] = {
+0x0f, 0x02, 0x0e, 0x02, 0x03};
+static unsigned char times8_71_bits[] = {
+0x0e, 0x01, 0x1d, 0x11, 0x0e};
+static unsigned char times8_72_bits[] = {
+0x33, 0x12, 0x1e, 0x12, 0x33};
+static unsigned char times8_73_bits[] = {
+0x07, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times8_74_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x01};
+static unsigned char times8_75_bits[] = {
+0x13, 0x0a, 0x06, 0x0a, 0x1b};
+static unsigned char times8_76_bits[] = {
+0x07, 0x02, 0x02, 0x0a, 0x0f};
+static unsigned char times8_77_bits[] = {
+0x77, 0x36, 0x2a, 0x2a, 0x63};
+static unsigned char times8_78_bits[] = {
+0x33, 0x16, 0x16, 0x1a, 0x13};
+static unsigned char times8_79_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char times8_80_bits[] = {
+0x0f, 0x12, 0x0e, 0x02, 0x03};
+static unsigned char times8_81_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x0e, 0x04, 0x08};
+static unsigned char times8_82_bits[] = {
+0x07, 0x0a, 0x06, 0x0a, 0x1b};
+static unsigned char times8_83_bits[] = {
+0x0e, 0x01, 0x06, 0x08, 0x07};
+static unsigned char times8_84_bits[] = {
+0x1f, 0x15, 0x04, 0x04, 0x0e};
+static unsigned char times8_85_bits[] = {
+0x33, 0x12, 0x12, 0x12, 0x0c};
+static unsigned char times8_86_bits[] = {
+0x1b, 0x0a, 0x0a, 0x04, 0x04};
+static unsigned char times8_87_bits[] = {
+0xcb, 0x4a, 0x52, 0x5a, 0x34};
+static unsigned char times8_88_bits[] = {
+0x33, 0x0c, 0x0c, 0x12, 0x33};
+static unsigned char times8_89_bits[] = {
+0x1b, 0x0a, 0x04, 0x04, 0x0e};
+static unsigned char times8_90_bits[] = {
+0x0f, 0x05, 0x02, 0x09, 0x0f};
+static unsigned char times8_91_bits[] = {
+0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03};
+static unsigned char times8_92_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x02, 0x04, 0x04};
+static unsigned char times8_93_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03};
+static unsigned char times8_94_bits[] = {
+0x02, 0x05};
+static unsigned char times8_95_bits[] = {
+0x0f};
+static unsigned char times8_96_bits[] = {
+0x01, 0x01};
+static unsigned char times8_97_bits[] = {
+0x01, 0x02, 0x03, 0x03};
+static unsigned char times8_98_bits[] = {
+0x01, 0x03, 0x05, 0x05, 0x03};
+static unsigned char times8_99_bits[] = {
+0x02, 0x01, 0x01, 0x02};
+static unsigned char times8_100_bits[] = {
+0x04, 0x06, 0x05, 0x05, 0x06};
+static unsigned char times8_101_bits[] = {
+0x02, 0x07, 0x01, 0x02};
+static unsigned char times8_102_bits[] = {
+0x04, 0x02, 0x07, 0x02, 0x02};
+static unsigned char times8_103_bits[] = {
+0x0e, 0x05, 0x02, 0x05, 0x02};
+static unsigned char times8_104_bits[] = {
+0x01, 0x03, 0x05, 0x05, 0x05};
+static unsigned char times8_105_bits[] = {
+0x01, 0x00, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times8_106_bits[] = {
+0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char times8_107_bits[] = {
+0x01, 0x05, 0x03, 0x03, 0x05};
+static unsigned char times8_108_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times8_109_bits[] = {
+0x0b, 0x15, 0x15, 0x15};
+static unsigned char times8_110_bits[] = {
+0x03, 0x05, 0x05, 0x05};
+static unsigned char times8_111_bits[] = {
+0x02, 0x05, 0x05, 0x02};
+static unsigned char times8_112_bits[] = {
+0x03, 0x05, 0x05, 0x03, 0x01, 0x01};
+static unsigned char times8_113_bits[] = {
+0x06, 0x05, 0x05, 0x06, 0x04, 0x04};
+static unsigned char times8_114_bits[] = {
+0x05, 0x03, 0x01, 0x01};
+static unsigned char times8_115_bits[] = {
+0x03, 0x01, 0x02, 0x03};
+static unsigned char times8_116_bits[] = {
+0x01, 0x03, 0x01, 0x01, 0x02};
+static unsigned char times8_117_bits[] = {
+0x05, 0x05, 0x05, 0x06};
+static unsigned char times8_118_bits[] = {
+0x05, 0x05, 0x05, 0x02};
+static unsigned char times8_119_bits[] = {
+0x15, 0x15, 0x15, 0x0a};
+static unsigned char times8_120_bits[] = {
+0x09, 0x06, 0x06, 0x09};
+static unsigned char times8_121_bits[] = {
+0x05, 0x05, 0x05, 0x02, 0x02, 0x01};
+static unsigned char times8_122_bits[] = {
+0x07, 0x02, 0x01, 0x07};
+static unsigned char times8_123_bits[] = {
+0x04, 0x02, 0x02, 0x03, 0x02, 0x02, 0x04};
+static unsigned char times8_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times8_125_bits[] = {
+0x01, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01};
+static unsigned char times8_126_bits[] = {
+0x16, 0x0d};
+static unsigned char times8_127_bits[] = {
+0x00};
+static unsigned char times8_128_bits[] = {
+0x00};
+static unsigned char times8_129_bits[] = {
+0x00};
+static unsigned char times8_130_bits[] = {
+0x00};
+static unsigned char times8_131_bits[] = {
+0x00};
+static unsigned char times8_132_bits[] = {
+0x00};
+static unsigned char times8_133_bits[] = {
+0x00};
+static unsigned char times8_134_bits[] = {
+0x00};
+static unsigned char times8_135_bits[] = {
+0x00};
+static unsigned char times8_136_bits[] = {
+0x00};
+static unsigned char times8_137_bits[] = {
+0x00};
+static unsigned char times8_138_bits[] = {
+0x00};
+static unsigned char times8_139_bits[] = {
+0x00};
+static unsigned char times8_140_bits[] = {
+0x00};
+static unsigned char times8_141_bits[] = {
+0x00};
+static unsigned char times8_142_bits[] = {
+0x00};
+static unsigned char times8_143_bits[] = {
+0x00};
+static unsigned char times8_144_bits[] = {
+0x00};
+static unsigned char times8_145_bits[] = {
+0x00};
+static unsigned char times8_146_bits[] = {
+0x00};
+static unsigned char times8_147_bits[] = {
+0x00};
+static unsigned char times8_148_bits[] = {
+0x00};
+static unsigned char times8_149_bits[] = {
+0x00};
+static unsigned char times8_150_bits[] = {
+0x00};
+static unsigned char times8_151_bits[] = {
+0x00};
+static unsigned char times8_152_bits[] = {
+0x00};
+static unsigned char times8_153_bits[] = {
+0x00};
+static unsigned char times8_154_bits[] = {
+0x00};
+static unsigned char times8_155_bits[] = {
+0x00};
+static unsigned char times8_156_bits[] = {
+0x00};
+static unsigned char times8_157_bits[] = {
+0x00};
+static unsigned char times8_158_bits[] = {
+0x00};
+static unsigned char times8_159_bits[] = {
+0x00};
+static unsigned char times8_160_bits[] = {
+0x00};
+static unsigned char times8_161_bits[] = {
+0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times8_162_bits[] = {
+0x02, 0x06, 0x01, 0x01, 0x06, 0x02};
+static unsigned char times8_163_bits[] = {
+0x04, 0x02, 0x07, 0x02, 0x0f};
+static unsigned char times8_164_bits[] = {
+0x09, 0x06, 0x06, 0x09};
+static unsigned char times8_165_bits[] = {
+0x11, 0x0a, 0x1f, 0x04, 0x04};
+static unsigned char times8_166_bits[] = {
+0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01};
+static unsigned char times8_167_bits[] = {
+0x06, 0x01, 0x03, 0x05, 0x06, 0x04, 0x03};
+static unsigned char times8_168_bits[] = {
+0x09};
+static unsigned char times8_169_bits[] = {
+0x1e, 0x21, 0x29, 0x25, 0x29, 0x21, 0x1e};
+static unsigned char times8_170_bits[] = {
+0x01, 0x02, 0x03, 0x00, 0x03};
+static unsigned char times8_171_bits[] = {
+0x0a, 0x05, 0x05, 0x0a};
+static unsigned char times8_172_bits[] = {
+0x0f, 0x08, 0x08};
+static unsigned char times8_173_bits[] = {
+0x03};
+static unsigned char times8_174_bits[] = {
+0x1e, 0x2d, 0x35, 0x2d, 0x35, 0x21, 0x1e};
+static unsigned char times8_175_bits[] = {
+0x07};
+static unsigned char times8_176_bits[] = {
+0x02, 0x05, 0x02};
+static unsigned char times8_177_bits[] = {
+0x02, 0x07, 0x02, 0x00, 0x07};
+static unsigned char times8_178_bits[] = {
+0x01, 0x02, 0x01, 0x03};
+static unsigned char times8_179_bits[] = {
+0x01, 0x02, 0x01, 0x02, 0x01};
+static unsigned char times8_180_bits[] = {
+0x02, 0x01};
+static unsigned char times8_181_bits[] = {
+0x05, 0x05, 0x05, 0x0b, 0x01};
+static unsigned char times8_182_bits[] = {
+0x1f, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a};
+static unsigned char times8_183_bits[] = {
+0x01};
+static unsigned char times8_184_bits[] = {
+0x02, 0x01};
+static unsigned char times8_185_bits[] = {
+0x03, 0x02, 0x02, 0x07};
+static unsigned char times8_186_bits[] = {
+0x02, 0x05, 0x02, 0x00, 0x07};
+static unsigned char times8_187_bits[] = {
+0x05, 0x0a, 0x0a, 0x05};
+static unsigned char times8_188_bits[] = {
+0x22, 0x12, 0x0a, 0x24, 0x32, 0x39, 0x20};
+static unsigned char times8_189_bits[] = {
+0x22, 0x12, 0x0a, 0x14, 0x22, 0x11, 0x30};
+static unsigned char times8_190_bits[] = {
+0x01, 0x22, 0x11, 0x2a, 0x35, 0x3a, 0x20};
+static unsigned char times8_191_bits[] = {
+0x02, 0x00, 0x02, 0x01, 0x01, 0x02};
+static unsigned char times8_192_bits[] = {
+0x02, 0x04, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x1b};
+static unsigned char times8_193_bits[] = {
+0x08, 0x04, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x1b};
+static unsigned char times8_194_bits[] = {
+0x04, 0x0a, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x1b};
+static unsigned char times8_195_bits[] = {
+0x14, 0x0a, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x1b};
+static unsigned char times8_196_bits[] = {
+0x0a, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x1b};
+static unsigned char times8_197_bits[] = {
+0x04, 0x0a, 0x04, 0x04, 0x04, 0x0a, 0x0e, 0x1b};
+static unsigned char times8_198_bits[] = {
+0x3c, 0x0a, 0x3e, 0x0a, 0x3b};
+static unsigned char times8_199_bits[] = {
+0x0e, 0x11, 0x01, 0x11, 0x0e, 0x04, 0x02};
+static unsigned char times8_200_bits[] = {
+0x02, 0x04, 0x00, 0x0f, 0x02, 0x06, 0x02, 0x0f};
+static unsigned char times8_201_bits[] = {
+0x08, 0x04, 0x00, 0x0f, 0x02, 0x06, 0x02, 0x0f};
+static unsigned char times8_202_bits[] = {
+0x04, 0x0a, 0x00, 0x0f, 0x02, 0x06, 0x02, 0x0f};
+static unsigned char times8_203_bits[] = {
+0x0a, 0x00, 0x0f, 0x02, 0x06, 0x02, 0x0f};
+static unsigned char times8_204_bits[] = {
+0x01, 0x02, 0x00, 0x07, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times8_205_bits[] = {
+0x04, 0x02, 0x00, 0x07, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times8_206_bits[] = {
+0x02, 0x05, 0x00, 0x07, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times8_207_bits[] = {
+0x05, 0x00, 0x07, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times8_208_bits[] = {
+0x0f, 0x12, 0x17, 0x12, 0x0f};
+static unsigned char times8_209_bits[] = {
+0x14, 0x0a, 0x00, 0x33, 0x16, 0x1a, 0x12, 0x13};
+static unsigned char times8_210_bits[] = {
+0x02, 0x04, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char times8_211_bits[] = {
+0x08, 0x04, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char times8_212_bits[] = {
+0x04, 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char times8_213_bits[] = {
+0x14, 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char times8_214_bits[] = {
+0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char times8_215_bits[] = {
+0x09, 0x06, 0x06, 0x09};
+static unsigned char times8_216_bits[] = {
+0x10, 0x0e, 0x19, 0x15, 0x13, 0x0e, 0x01};
+static unsigned char times8_217_bits[] = {
+0x04, 0x08, 0x00, 0x33, 0x12, 0x12, 0x12, 0x0c};
+static unsigned char times8_218_bits[] = {
+0x10, 0x08, 0x00, 0x33, 0x12, 0x12, 0x12, 0x0c};
+static unsigned char times8_219_bits[] = {
+0x08, 0x14, 0x00, 0x33, 0x12, 0x12, 0x12, 0x0c};
+static unsigned char times8_220_bits[] = {
+0x14, 0x00, 0x33, 0x12, 0x12, 0x12, 0x0c};
+static unsigned char times8_221_bits[] = {
+0x08, 0x04, 0x00, 0x1b, 0x0a, 0x0a, 0x04, 0x04};
+static unsigned char times8_222_bits[] = {
+0x03, 0x06, 0x0a, 0x06, 0x03};
+static unsigned char times8_223_bits[] = {
+0x06, 0x09, 0x05, 0x09, 0x05, 0x01};
+static unsigned char times8_224_bits[] = {
+0x01, 0x02, 0x00, 0x01, 0x02, 0x03, 0x03};
+static unsigned char times8_225_bits[] = {
+0x02, 0x01, 0x00, 0x01, 0x02, 0x03, 0x03};
+static unsigned char times8_226_bits[] = {
+0x02, 0x05, 0x00, 0x01, 0x02, 0x03, 0x03};
+static unsigned char times8_227_bits[] = {
+0x0a, 0x05, 0x00, 0x01, 0x02, 0x03, 0x03};
+static unsigned char times8_228_bits[] = {
+0x05, 0x00, 0x00, 0x01, 0x02, 0x03, 0x03};
+static unsigned char times8_229_bits[] = {
+0x02, 0x05, 0x02, 0x01, 0x02, 0x03, 0x03};
+static unsigned char times8_230_bits[] = {
+0x09, 0x1e, 0x07, 0x0b};
+static unsigned char times8_231_bits[] = {
+0x02, 0x01, 0x01, 0x02, 0x01};
+static unsigned char times8_232_bits[] = {
+0x01, 0x02, 0x00, 0x02, 0x07, 0x01, 0x02};
+static unsigned char times8_233_bits[] = {
+0x04, 0x02, 0x00, 0x02, 0x07, 0x01, 0x02};
+static unsigned char times8_234_bits[] = {
+0x02, 0x05, 0x00, 0x02, 0x07, 0x01, 0x02};
+static unsigned char times8_235_bits[] = {
+0x05, 0x00, 0x00, 0x02, 0x07, 0x01, 0x02};
+static unsigned char times8_236_bits[] = {
+0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times8_237_bits[] = {
+0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times8_238_bits[] = {
+0x02, 0x05, 0x00, 0x02, 0x02, 0x02, 0x02};
+static unsigned char times8_239_bits[] = {
+0x05, 0x00, 0x02, 0x02, 0x02, 0x02};
+static unsigned char times8_240_bits[] = {
+0x05, 0x02, 0x05, 0x0a, 0x0a, 0x04};
+static unsigned char times8_241_bits[] = {
+0x0a, 0x05, 0x00, 0x03, 0x05, 0x05, 0x05};
+static unsigned char times8_242_bits[] = {
+0x01, 0x02, 0x00, 0x02, 0x05, 0x05, 0x02};
+static unsigned char times8_243_bits[] = {
+0x04, 0x02, 0x00, 0x02, 0x05, 0x05, 0x02};
+static unsigned char times8_244_bits[] = {
+0x02, 0x05, 0x00, 0x02, 0x05, 0x05, 0x02};
+static unsigned char times8_245_bits[] = {
+0x0a, 0x05, 0x00, 0x02, 0x05, 0x05, 0x02};
+static unsigned char times8_246_bits[] = {
+0x05, 0x00, 0x00, 0x02, 0x05, 0x05, 0x02};
+static unsigned char times8_247_bits[] = {
+0x02, 0x00, 0x07, 0x00, 0x02};
+static unsigned char times8_248_bits[] = {
+0x04, 0x06, 0x05, 0x05, 0x03, 0x01};
+static unsigned char times8_249_bits[] = {
+0x01, 0x02, 0x00, 0x05, 0x05, 0x05, 0x06};
+static unsigned char times8_250_bits[] = {
+0x04, 0x02, 0x00, 0x05, 0x05, 0x05, 0x06};
+static unsigned char times8_251_bits[] = {
+0x02, 0x05, 0x00, 0x05, 0x05, 0x05, 0x06};
+static unsigned char times8_252_bits[] = {
+0x05, 0x00, 0x05, 0x05, 0x05, 0x06};
+static unsigned char times8_253_bits[] = {
+0x04, 0x02, 0x00, 0x05, 0x05, 0x05, 0x02, 0x02, 0x01};
+static unsigned char times8_254_bits[] = {
+0x03, 0x06, 0x0a, 0x0a, 0x06, 0x02, 0x03};
+static unsigned char times8_255_bits[] = {
+0x05, 0x00, 0x05, 0x05, 0x05, 0x02, 0x02, 0x01};
+static RotFont times8font[] = {
+{5, 1, 1, times8_0_bits},
+{5, 1, 1, times8_1_bits},
+{5, 1, 1, times8_2_bits},
+{5, 1, 1, times8_3_bits},
+{5, 1, 1, times8_4_bits},
+{5, 1, 1, times8_5_bits},
+{5, 1, 1, times8_6_bits},
+{5, 1, 1, times8_7_bits},
+{5, 1, 1, times8_8_bits},
+{5, 1, 1, times8_9_bits},
+{5, 1, 1, times8_10_bits},
+{5, 1, 1, times8_11_bits},
+{5, 1, 1, times8_12_bits},
+{5, 1, 1, times8_13_bits},
+{5, 1, 1, times8_14_bits},
+{5, 1, 1, times8_15_bits},
+{5, 1, 1, times8_16_bits},
+{5, 1, 1, times8_17_bits},
+{5, 1, 1, times8_18_bits},
+{5, 1, 1, times8_19_bits},
+{5, 1, 1, times8_20_bits},
+{5, 1, 1, times8_21_bits},
+{5, 1, 1, times8_22_bits},
+{5, 1, 1, times8_23_bits},
+{5, 1, 1, times8_24_bits},
+{5, 1, 1, times8_25_bits},
+{5, 1, 1, times8_26_bits},
+{5, 1, 1, times8_27_bits},
+{5, 1, 1, times8_28_bits},
+{5, 1, 1, times8_29_bits},
+{5, 1, 1, times8_30_bits},
+{5, 1, 1, times8_31_bits},
+{4, 1, 1, times8_32_bits},
+{1, 6, 6, times8_33_bits},
+{3, 2, 5, times8_34_bits},
+{4, 5, 5, times8_35_bits},
+{3, 7, 6, times8_36_bits},
+{5, 5, 5, times8_37_bits},
+{5, 6, 6, times8_38_bits},
+{1, 2, 6, times8_39_bits},
+{2, 7, 6, times8_40_bits},
+{2, 7, 6, times8_41_bits},
+{3, 3, 5, times8_42_bits},
+{4, 5, 5, times8_43_bits},
+{2, 2, 1, times8_44_bits},
+{4, 1, 3, times8_45_bits},
+{1, 1, 1, times8_46_bits},
+{3, 7, 6, times8_47_bits},
+{3, 5, 5, times8_48_bits},
+{3, 5, 5, times8_49_bits},
+{3, 5, 5, times8_50_bits},
+{3, 5, 5, times8_51_bits},
+{4, 5, 5, times8_52_bits},
+{3, 5, 5, times8_53_bits},
+{3, 5, 5, times8_54_bits},
+{3, 5, 5, times8_55_bits},
+{3, 5, 5, times8_56_bits},
+{3, 5, 5, times8_57_bits},
+{1, 3, 3, times8_58_bits},
+{2, 4, 3, times8_59_bits},
+{3, 5, 5, times8_60_bits},
+{4, 3, 4, times8_61_bits},
+{3, 5, 5, times8_62_bits},
+{3, 5, 5, times8_63_bits},
+{6, 7, 6, times8_64_bits},
+{5, 5, 5, times8_65_bits},
+{4, 5, 5, times8_66_bits},
+{5, 5, 5, times8_67_bits},
+{5, 5, 5, times8_68_bits},
+{4, 5, 5, times8_69_bits},
+{4, 5, 5, times8_70_bits},
+{5, 5, 5, times8_71_bits},
+{6, 5, 5, times8_72_bits},
+{3, 5, 5, times8_73_bits},
+{2, 5, 5, times8_74_bits},
+{5, 5, 5, times8_75_bits},
+{4, 5, 5, times8_76_bits},
+{7, 5, 5, times8_77_bits},
+{6, 5, 5, times8_78_bits},
+{5, 5, 5, times8_79_bits},
+{5, 5, 5, times8_80_bits},
+{5, 7, 5, times8_81_bits},
+{5, 5, 5, times8_82_bits},
+{4, 5, 5, times8_83_bits},
+{5, 5, 5, times8_84_bits},
+{6, 5, 5, times8_85_bits},
+{5, 5, 5, times8_86_bits},
+{8, 5, 5, times8_87_bits},
+{6, 5, 5, times8_88_bits},
+{5, 5, 5, times8_89_bits},
+{4, 5, 5, times8_90_bits},
+{2, 7, 6, times8_91_bits},
+{3, 7, 6, times8_92_bits},
+{2, 7, 6, times8_93_bits},
+{3, 2, 6, times8_94_bits},
+{4, 1, 0, times8_95_bits},
+{1, 2, 6, times8_96_bits},
+{2, 4, 4, times8_97_bits},
+{3, 5, 5, times8_98_bits},
+{2, 4, 4, times8_99_bits},
+{3, 5, 5, times8_100_bits},
+{3, 4, 4, times8_101_bits},
+{3, 5, 5, times8_102_bits},
+{4, 5, 4, times8_103_bits},
+{3, 5, 5, times8_104_bits},
+{1, 6, 6, times8_105_bits},
+{2, 8, 6, times8_106_bits},
+{3, 5, 5, times8_107_bits},
+{1, 5, 5, times8_108_bits},
+{5, 4, 4, times8_109_bits},
+{3, 4, 4, times8_110_bits},
+{3, 4, 4, times8_111_bits},
+{3, 6, 4, times8_112_bits},
+{3, 6, 4, times8_113_bits},
+{3, 4, 4, times8_114_bits},
+{2, 4, 4, times8_115_bits},
+{2, 5, 5, times8_116_bits},
+{3, 4, 4, times8_117_bits},
+{3, 4, 4, times8_118_bits},
+{5, 4, 4, times8_119_bits},
+{4, 4, 4, times8_120_bits},
+{3, 6, 4, times8_121_bits},
+{3, 4, 4, times8_122_bits},
+{3, 7, 6, times8_123_bits},
+{1, 7, 6, times8_124_bits},
+{3, 7, 6, times8_125_bits},
+{5, 2, 4, times8_126_bits},
+{5, 1, 1, times8_127_bits},
+{5, 1, 1, times8_128_bits},
+{5, 1, 1, times8_129_bits},
+{5, 1, 1, times8_130_bits},
+{5, 1, 1, times8_131_bits},
+{5, 1, 1, times8_132_bits},
+{5, 1, 1, times8_133_bits},
+{5, 1, 1, times8_134_bits},
+{5, 1, 1, times8_135_bits},
+{5, 1, 1, times8_136_bits},
+{5, 1, 1, times8_137_bits},
+{5, 1, 1, times8_138_bits},
+{5, 1, 1, times8_139_bits},
+{5, 1, 1, times8_140_bits},
+{5, 1, 1, times8_141_bits},
+{5, 1, 1, times8_142_bits},
+{5, 1, 1, times8_143_bits},
+{5, 1, 1, times8_144_bits},
+{5, 1, 1, times8_145_bits},
+{5, 1, 1, times8_146_bits},
+{5, 1, 1, times8_147_bits},
+{5, 1, 1, times8_148_bits},
+{5, 1, 1, times8_149_bits},
+{5, 1, 1, times8_150_bits},
+{5, 1, 1, times8_151_bits},
+{5, 1, 1, times8_152_bits},
+{5, 1, 1, times8_153_bits},
+{5, 1, 1, times8_154_bits},
+{5, 1, 1, times8_155_bits},
+{5, 1, 1, times8_156_bits},
+{5, 1, 1, times8_157_bits},
+{5, 1, 1, times8_158_bits},
+{5, 1, 1, times8_159_bits},
+{1, 1, 1, times8_160_bits},
+{1, 7, 5, times8_161_bits},
+{3, 6, 5, times8_162_bits},
+{4, 5, 5, times8_163_bits},
+{4, 4, 4, times8_164_bits},
+{5, 5, 5, times8_165_bits},
+{1, 7, 6, times8_166_bits},
+{3, 7, 6, times8_167_bits},
+{4, 1, 7, times8_168_bits},
+{6, 7, 6, times8_169_bits},
+{2, 5, 6, times8_170_bits},
+{4, 4, 4, times8_171_bits},
+{4, 3, 4, times8_172_bits},
+{2, 1, 3, times8_173_bits},
+{6, 7, 6, times8_174_bits},
+{3, 1, 7, times8_175_bits},
+{3, 3, 5, times8_176_bits},
+{3, 5, 5, times8_177_bits},
+{2, 4, 6, times8_178_bits},
+{2, 5, 6, times8_179_bits},
+{2, 2, 7, times8_180_bits},
+{4, 5, 4, times8_181_bits},
+{5, 7, 6, times8_182_bits},
+{1, 1, 3, times8_183_bits},
+{2, 2, 0, times8_184_bits},
+{3, 4, 6, times8_185_bits},
+{3, 5, 6, times8_186_bits},
+{4, 4, 4, times8_187_bits},
+{6, 7, 6, times8_188_bits},
+{6, 7, 6, times8_189_bits},
+{6, 7, 6, times8_190_bits},
+{2, 6, 5, times8_191_bits},
+{5, 8, 8, times8_192_bits},
+{5, 8, 8, times8_193_bits},
+{5, 8, 8, times8_194_bits},
+{5, 8, 8, times8_195_bits},
+{5, 7, 7, times8_196_bits},
+{5, 8, 8, times8_197_bits},
+{6, 5, 5, times8_198_bits},
+{5, 7, 5, times8_199_bits},
+{4, 8, 8, times8_200_bits},
+{4, 8, 8, times8_201_bits},
+{4, 8, 8, times8_202_bits},
+{4, 7, 7, times8_203_bits},
+{3, 8, 8, times8_204_bits},
+{3, 8, 8, times8_205_bits},
+{3, 8, 8, times8_206_bits},
+{3, 7, 7, times8_207_bits},
+{5, 5, 5, times8_208_bits},
+{6, 8, 8, times8_209_bits},
+{5, 8, 8, times8_210_bits},
+{5, 8, 8, times8_211_bits},
+{5, 8, 8, times8_212_bits},
+{5, 8, 8, times8_213_bits},
+{5, 7, 7, times8_214_bits},
+{4, 4, 4, times8_215_bits},
+{5, 7, 6, times8_216_bits},
+{6, 8, 8, times8_217_bits},
+{6, 8, 8, times8_218_bits},
+{6, 8, 8, times8_219_bits},
+{6, 7, 7, times8_220_bits},
+{5, 8, 8, times8_221_bits},
+{4, 5, 5, times8_222_bits},
+{4, 6, 5, times8_223_bits},
+{2, 7, 7, times8_224_bits},
+{2, 7, 7, times8_225_bits},
+{3, 7, 7, times8_226_bits},
+{4, 7, 7, times8_227_bits},
+{3, 7, 7, times8_228_bits},
+{3, 7, 7, times8_229_bits},
+{5, 4, 4, times8_230_bits},
+{2, 5, 4, times8_231_bits},
+{3, 7, 7, times8_232_bits},
+{3, 7, 7, times8_233_bits},
+{3, 7, 7, times8_234_bits},
+{3, 7, 7, times8_235_bits},
+{2, 7, 7, times8_236_bits},
+{2, 7, 7, times8_237_bits},
+{3, 7, 7, times8_238_bits},
+{3, 6, 6, times8_239_bits},
+{4, 6, 6, times8_240_bits},
+{4, 7, 7, times8_241_bits},
+{3, 7, 7, times8_242_bits},
+{3, 7, 7, times8_243_bits},
+{3, 7, 7, times8_244_bits},
+{4, 7, 7, times8_245_bits},
+{3, 7, 7, times8_246_bits},
+{3, 5, 5, times8_247_bits},
+{3, 6, 5, times8_248_bits},
+{3, 7, 7, times8_249_bits},
+{3, 7, 7, times8_250_bits},
+{3, 7, 7, times8_251_bits},
+{3, 6, 6, times8_252_bits},
+{3, 9, 7, times8_253_bits},
+{4, 7, 5, times8_254_bits},
+{3, 8, 6, times8_255_bits}};
Index: /tags/start/Ohana/src/kapa/setup/CheckColors.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/CheckColors.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/CheckColors.c	(revision 12606)
@@ -0,0 +1,41 @@
+# include "Ximage.h"
+
+/************** CheckColors *************/
+void CheckColors (int *argc, char **argv) {
+
+  char *temp_name;
+  int N;
+  unsigned long temp_color;
+
+  graphic.fore = BlackPixel (graphic.display, graphic.screen);
+  temp_name = XGetDefault (graphic.display, argv[0], "Foreground");
+  if (N = get_argument (*argc, argv, "-fg")) {
+    if (N + 1 < *argc) {
+      temp_name = argv[N+1];
+    } else {
+      fprintf (stderr, "error: usage is -fg color\n");
+      exit (0);
+    }
+  }
+  if (temp_name != (char *) NULL) 
+    graphic.fore = GetColor (graphic.display, temp_name, graphic.colormap, graphic.fore);
+
+  graphic.back = WhitePixel (graphic.display, graphic.screen);
+  temp_name = XGetDefault (graphic.display, argv[0], "Background");
+  if (N = get_argument (*argc, argv, "-bg")) {
+    if (N + 1 < *argc) {
+      temp_name = argv[N+1];
+    } else {
+      fprintf (stderr, "error: usage is -bg color\n");
+      exit (0);
+    }
+  }  
+  if (temp_name != (char *)NULL) 
+    graphic.back = GetColor (graphic.display, temp_name, graphic.colormap, graphic.back);
+ 
+}
+
+  /* here we define the values for foreground and background
+     if -fg, or -bg exist, or if Foreground or Background are set in .Xdefaults, 
+     use those.  foreground defaults to black, background defaults to white. */
+
Index: /tags/start/Ohana/src/kapa/setup/CheckDisplayName.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/CheckDisplayName.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/CheckDisplayName.c	(revision 12606)
@@ -0,0 +1,30 @@
+# include "Ximage.h"
+
+/************** CheckDisplayName *************/
+void CheckDisplayName (int *argc, char **argv, char *display_name) {
+
+  int N;
+
+  display_name[0] = 0;
+  if (N = get_argument (*argc, argv, "-d")) {
+    if (N + 1 < *argc) {
+      strcpy (display_name, argv[N + 1]);
+      remove_argument(N, argc, argv);
+      remove_argument(N, argc, argv);
+    } else {
+      fprintf (stderr, "error: usage is [-display/-d] DisplayName\n");
+      exit (0);
+    }
+  }
+
+  if (N = get_argument (*argc, argv, "-display")) {
+    if (N + 1 < *argc) {
+      strcpy (display_name, argv[N + 1]);
+      remove_argument(N, argc, argv);
+      remove_argument(N, argc, argv);
+    } else {
+      fprintf (stderr, "error: usage is [-display/-d] DisplayName\n");
+      exit (0);
+    }
+  }
+}
Index: /tags/start/Ohana/src/kapa/setup/CheckFontName.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/CheckFontName.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/CheckFontName.c	(revision 12606)
@@ -0,0 +1,28 @@
+# include "Ximage.h"
+
+/************** CheckFontName *************/
+void CheckFontName (int *argc, char **argv, char *fontname) {
+
+  int N;
+
+  if (N = get_argument (*argc, argv, "-font")) {
+    if (N + 1 < *argc) {
+      strcpy (fontname, argv[N + 1]);
+      remove_argument(N, argc, argv);
+      remove_argument(N, argc, argv);
+    } else {
+      fprintf (stderr, "error: usage is -font fontname\n");
+      exit (0);
+    }
+  }   
+  if (N = get_argument (*argc, argv, "-fn")) {
+    if (N + 1 < *argc) {
+      strcpy (fontname, argv[N + 1]);
+      remove_argument(N, argc, argv);
+      remove_argument(N, argc, argv);
+    } else {
+      fprintf (stderr, "error: usage is -fn fontname\n");
+      exit (0);
+    }
+  }   
+}
Index: /tags/start/Ohana/src/kapa/setup/CheckGeometry.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/CheckGeometry.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/CheckGeometry.c	(revision 12606)
@@ -0,0 +1,46 @@
+# include "Ximage.h"
+
+/************** CheckGeometry *************/
+void CheckGeometry (int *argc, char **argv) {
+
+  int status, x, y, N;
+  unsigned int dx, dy;
+  int X, Y, dX, dY;
+  char *temp_name;
+  
+  temp_name = XGetDefault (graphic.display, argv[0], "geometry");
+  if (N = get_argument (*argc, argv, "-geom")) {
+    if (N + 1 < *argc) {
+      temp_name = argv[N+1];
+    } else {
+      fprintf (stderr, "error: usage is -geom DisplayName\n");
+      exit (0);
+    }
+  }
+
+  X = 10;
+  Y = 10;
+  dX = 512;
+  dY = 512;
+  if (temp_name != (char *)NULL) {  
+    status = XParseGeometry (temp_name, &x, &y, &dx, &dy);
+    if (status & XValue) X = x;
+    if (status & YValue) Y = y;
+    if (status & WidthValue) {
+      dX = dx;
+      MAX (dX, MIN_WIDTH);
+    }
+    if (status & HeightValue) {
+      dY = dy;
+      MAX (dY, MIN_HEIGHT);
+    }
+    if (status & XNegative) X  = DisplayWidth  (graphic.display, graphic.screen) - dX + X;
+    if (status & YNegative) Y  = DisplayHeight (graphic.display, graphic.screen) - dY + Y;
+  }
+
+  graphic.x = X;
+  graphic.y = Y;
+  graphic.dx = dX;
+  graphic.dy = dY; 
+  
+}
Index: /tags/start/Ohana/src/kapa/setup/CloseDisplay.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/CloseDisplay.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/CloseDisplay.c	(revision 12606)
@@ -0,0 +1,11 @@
+# include "Ximage.h"
+
+/************** CloseDisplay *************/
+void CloseDisplay () {
+  XFreeGC (graphic.display, graphic.gc);
+  XDestroySubwindows (graphic.display, graphic.window);
+  XDestroyWindow (graphic.display, graphic.window);
+  XFlush (graphic.display);
+  XCloseDisplay (graphic.display);
+}
+
Index: /tags/start/Ohana/src/kapa/setup/CreateWindow.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/CreateWindow.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/CreateWindow.c	(revision 12606)
@@ -0,0 +1,34 @@
+# include "Ximage.h"
+
+/************** CreateWindow *************/
+void CreateWindow (Window parent, int border, long events) {
+
+  XSetWindowAttributes attributes;
+  unsigned long attribute_mask;
+  Visual *visual = CopyFromParent;
+
+  HAVE_BACKING = (DoesBackingStore (ScreenOfDisplay(graphic.display, graphic.screen)) == Always);
+
+  if (HAVE_BACKING) {
+    attributes.backing_store = Always;
+    attribute_mask = CWBackingStore | CWBackPixel | CWBorderPixel | CWEventMask;
+  } else {
+    attribute_mask = CWBackPixel | CWBorderPixel | CWEventMask;
+  }
+
+  attributes.background_pixel = graphic.back;
+  attributes.border_pixel     = graphic.fore;
+  attributes.event_mask       = events;
+
+  graphic.window = XCreateWindow (graphic.display, parent, 
+				     graphic.x, graphic.y, 
+				     graphic.dx, graphic.dy, 
+				     border, CopyFromParent,
+				     InputOutput, visual, 
+				     attribute_mask, &attributes);
+
+  if (graphic.window == (Window) None)
+    QuitX (graphic.display, "", "error: could not open window");
+
+  XSelectInput (graphic.display, graphic.window, events);
+}
Index: /tags/start/Ohana/src/kapa/setup/DefineLayout.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/DefineLayout.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/DefineLayout.c	(revision 12606)
@@ -0,0 +1,85 @@
+# include "Ximage.h"
+# define PAD 40
+
+/* general initialization for things not specific to X */
+void DefineLayout (int argc, char **argv) {
+
+  int i, j, status, N, offset, FOREGROUND;
+  Visual *visual = CopyFromParent;
+  struct sockaddr_un Address;
+  char temp[100];
+  double PADx, PADy;
+  
+  if ((N = get_argument (argc, argv, "-debug"))) {
+    remove_argument(N, &argc, argv);
+    DEBUG = TRUE;
+  } else {
+    DEBUG = FALSE;
+  }
+
+  FOREGROUND = FALSE;
+  if ((N = get_argument (argc, argv, "-fg"))) {
+    remove_argument(N, &argc, argv);
+    FOREGROUND = TRUE;
+  }
+
+  /** initiate connection with server **/
+  if (!FOREGROUND) {	
+    if (argc < 2) {
+      fprintf (stderr, "socket path not specified\n");
+      exit (0);
+    }
+    strcpy (Address.sun_path, argv[1]);
+    Address.sun_family = AF_UNIX;
+    sock = socket (AF_UNIX, SOCK_STREAM, 0);
+    status = connect (sock, &Address, sizeof (Address));
+    if (status < 0) {
+      fprintf (stderr, "kapa - unsuccessful connection: %d\n", status);
+      exit (0);
+    }
+    fcntl (sock, F_SETFL, O_NONBLOCK);  
+    sprintf (temp, "rm -f %s\0", argv[1]);
+    system (temp);
+  }
+
+  InitRotFonts ();
+  MakeColormap (argc, argv);
+
+  /** set up defaults for display region **/
+  /* default startup uses one graphic region, filling the window */
+  
+  Nsection = 1;
+  ALLOCATE (section, Layout, Nsection);
+  TheSection = 0;
+
+  /* set up axis positions */
+  for (i = 0; i < 4; i++) {
+    section[0].axis[i].min = 0.0;
+    section[0].axis[i].max = 1.0;
+    section[0].axis[i].isaxis = FALSE;
+    section[0].axis[i].areticks = FALSE;
+    section[0].axis[i].islabel = FALSE;
+    strcpy (section[0].axis[i].label, " ");
+  }    
+  for (i = 0; i < 8; i++) {
+    strcpy (section[0].label[i].text, "");
+  }
+  section[0].x  = 0;
+  section[0].dx = 1; 
+  section[0].y  = 0; 
+  section[0].dy = 1; 
+  strcpy (section[0].name, "default");
+
+  PositionPicture (&section[0]);
+
+  section[0].Nobjects = 0;
+  section[0].Nptext = 0;
+
+  ALLOCATE (section[0].objects, Gobjects, 1);  /* allocate so later free will not crash! */
+  section[0].objects[0].x   = section[0].objects[0].y   = section[0].objects[0].z = (float *) NULL;
+  section[0].objects[0].dxm = section[0].objects[0].dxp = (float *) NULL;
+  section[0].objects[0].dym = section[0].objects[0].dyp = (float *) NULL;
+  
+  ALLOCATE (section[0].ptext, Label, 1);       /* allocate so later free will not crash! */
+
+}
Index: /tags/start/Ohana/src/kapa/setup/GetColor.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/GetColor.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/GetColor.c	(revision 12606)
@@ -0,0 +1,25 @@
+# include "Ximage.h"
+
+/************** GetColor *************/
+unsigned long 
+GetColor (display, name, colormap, default_color)
+Display  *display;
+char      name[];
+Colormap  colormap;
+unsigned long default_color;
+{
+
+  unsigned long color;
+  XColor rgbcolor, hardwarecolor;
+  int status;
+
+  color = default_color;
+  status = XLookupColor (display, colormap, name, &rgbcolor, &hardwarecolor);
+  if (status) {
+    status = XAllocColor (display, colormap, &hardwarecolor);
+    if (status) {
+      color = hardwarecolor.pixel;
+    }
+  }
+  return (color);
+}
Index: /tags/start/Ohana/src/kapa/setup/LoadFont.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/LoadFont.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/LoadFont.c	(revision 12606)
@@ -0,0 +1,31 @@
+# include "Ximage.h"
+
+/************** LoadFont *************/
+void LoadFont (int *argc, char **argv, char *default_name) {
+
+  char name[400];
+  char *temp_name;
+
+  temp_name = XGetDefault (graphic.display, argv[0], "Font");
+  if (temp_name == (char *) NULL) 
+    strcpy (name, default_name);
+  else 
+    strcpy (name, temp_name);
+
+  CheckFontName (argc, argv, name);
+
+  graphic.font = XLoadQueryFont (graphic.display, name);
+  if (graphic.font == (XFontStruct *) NULL) {
+    fprintf (stderr, "Could not load fond %s, using %s\n", name, default_name);
+    graphic.font = XLoadQueryFont (graphic.display, default_name);
+    if (graphic.font == (XFontStruct *) NULL) {
+      graphic.font = XLoadQueryFont (graphic.display, "fixed");
+      fprintf (stderr, "Could not load fond %s, using %s\n", default_name, "fixed");
+    }
+  }
+
+  if (graphic.font != (XFontStruct *) NULL) 
+    XSetFont (graphic.display, graphic.gc, graphic.font[0].fid);
+  else
+    QuitX (graphic.display, "Error: could not load font", name);
+}
Index: /tags/start/Ohana/src/kapa/setup/MakeColormap.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/MakeColormap.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/MakeColormap.c	(revision 12606)
@@ -0,0 +1,13 @@
+# include "Ximage.h"
+
+void MakeColormap (int argc, char **argv) {
+
+  int i;
+  char *temp_name;
+
+
+  for (i = 0; i < NGRAPHCOLORS; i++) {
+    temp_name = XGetDefault (graphic.display, argv[0], GRAPHCOLORS[i][0]);
+    graphic.color[i] = GetColor (graphic.display, (temp_name == (char *) NULL ? GRAPHCOLORS[i][0] : temp_name), graphic.colormap, graphic.fore);
+  }
+}
Index: /tags/start/Ohana/src/kapa/setup/MakeCursor.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/MakeCursor.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/MakeCursor.c	(revision 12606)
@@ -0,0 +1,9 @@
+# include "Ximage.h"
+
+/************** MakeCursor *************/
+void MakeCursor (unsigned int which_cursor) {
+
+  graphic.cursor = XCreateFontCursor (graphic.display, (unsigned) which_cursor);
+
+  if (graphic.cursor != (Cursor) None) XDefineCursor (graphic.display, graphic.window, graphic.cursor);
+}
Index: /tags/start/Ohana/src/kapa/setup/MakeGC.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/MakeGC.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/MakeGC.c	(revision 12606)
@@ -0,0 +1,15 @@
+# include "Ximage.h"
+
+/************** MakeGC *************/
+void MakeGC () {
+
+  GC gc;
+  XGCValues gcvalues;
+
+  gcvalues.foreground = graphic.fore;
+  gcvalues.background = graphic.back;
+  graphic.gc = XCreateGC (graphic.display, graphic.window, 
+			     GCForeground | GCBackground, &gcvalues);
+  if (graphic.gc == 0)
+    QuitX (graphic.display, "Error in creating a Graphics Context", "");
+}
Index: /tags/start/Ohana/src/kapa/setup/MapWindow.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/MapWindow.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/MapWindow.c	(revision 12606)
@@ -0,0 +1,10 @@
+# include "Ximage.h"
+
+/************** MapWindow *************/
+void MapWindow () {
+
+  XMapRaised (graphic.display, graphic.window);
+  XMapSubwindows (graphic.display, graphic.window);
+  FlushDisplay ();
+}
+
Index: /tags/start/Ohana/src/kapa/setup/NameWindow.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/NameWindow.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/NameWindow.c	(revision 12606)
@@ -0,0 +1,31 @@
+# include "Ximage.h"
+
+/************** NameWindow *************/
+void NameWindow (char *Name) {
+
+  char       *name;
+  char       *class_name;
+  char       *class_type;
+  XClassHint *classhints;
+
+  name = strrchr (Name, '/');
+  if (name != NULL) 
+    name ++;
+  else 
+    name = Name;
+
+  class_type = class_name = name;
+  classhints = XAllocClassHint ();
+
+  if (classhints != (XClassHint *) NULL)  {
+    classhints[0].res_name = class_name;
+    classhints[0].res_class = class_type;
+    XSetClassHint (graphic.display, graphic.window, classhints);
+    XFree (classhints);
+  }
+  
+  XStoreName (graphic.display, graphic.window, name);
+  XSetIconName (graphic.display, graphic.window, name);
+
+}
+
Index: /tags/start/Ohana/src/kapa/setup/OpenDisplay.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/OpenDisplay.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/OpenDisplay.c	(revision 12606)
@@ -0,0 +1,18 @@
+# include "Ximage.h"
+
+/************** OpenDisplay *************/
+Display *OpenDisplay (char *display_name, int *screen) {
+
+  Display *display;
+  char *tmp;
+  
+  display = XOpenDisplay (display_name);
+  if (display != (Display *) NULL) *screen = DefaultScreen (display);
+  if (display == (Display *) NULL) {
+    fprintf (stderr, "Error could not open X display to %s\n", XDisplayName (display_name));
+    exit (0);
+  }
+  
+  return (display);
+}
+
Index: /tags/start/Ohana/src/kapa/setup/QuitX.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/QuitX.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/QuitX.c	(revision 12606)
@@ -0,0 +1,12 @@
+# include "Ximage.h"
+
+/************** QuitX *************/
+void QuitX (Display *display, char *error_message, char *error_file) {
+
+  fprintf (stderr, "Error: %s%s\n", error_message, error_file);
+  XCloseDisplay (display);
+  exit (0);
+
+}
+
+
Index: /tags/start/Ohana/src/kapa/setup/SetNormalHints.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/SetNormalHints.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/SetNormalHints.c	(revision 12606)
@@ -0,0 +1,27 @@
+# include "Ximage.h"
+
+/************** SetNormalHints  *************/
+void SetNormalHints () {
+
+  XSizeHints *sizehints;
+
+  sizehints = XAllocSizeHints ();
+
+  if (sizehints != (XSizeHints *) NULL)  {
+    sizehints[0].x = graphic.x;
+    sizehints[0].y = graphic.x;
+    sizehints[0].width = graphic.dx;
+    sizehints[0].height = graphic.dy;
+    sizehints[0].min_width = MIN_WIDTH;
+    sizehints[0].min_height = MIN_HEIGHT;    
+    sizehints[0].flags = USPosition | USSize | PMinSize;
+
+    sizehints[0].base_width = graphic.dx;
+    sizehints[0].base_height = graphic.dy;
+    sizehints[0].flags |= PBaseSize;
+    
+    XSetWMNormalHints (graphic.display, graphic.window, sizehints);
+    XFree (sizehints);
+  }
+}
+
Index: /tags/start/Ohana/src/kapa/setup/SetUpDisplay.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/SetUpDisplay.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/SetUpDisplay.c	(revision 12606)
@@ -0,0 +1,16 @@
+# include "Ximage.h"
+
+/************** SetUpDisplay *************/
+Display *SetUpDisplay (int *argc, char **argv) {
+
+  char display_name[120];
+
+  CheckDisplayName (argc, argv, display_name);
+
+  graphic.display  = OpenDisplay     (display_name,   &graphic.screen);
+  graphic.colormap = DefaultColormap (graphic.display, graphic.screen);
+  graphic.depth    = DefaultDepth    (graphic.display, graphic.screen);
+  CheckColors (argc, argv);
+
+}
+
Index: /tags/start/Ohana/src/kapa/setup/SetUpWindow.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/SetUpWindow.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/SetUpWindow.c	(revision 12606)
@@ -0,0 +1,31 @@
+# include "Ximage.h"
+# include "icons/icon.h"
+
+/************** SetUpWindow *************/
+void SetUpWindow (int *argc, char **argv) {
+
+  int N;
+  Icon icon;
+
+  icon.width = icon_width;
+  icon.height = icon_height;
+  icon.bits = icon_bits;
+
+  CheckGeometry (argc, argv);
+  TopWindow (&icon);
+  LoadFont (argc, argv, "fixed"); 
+
+  FlushDisplay ();
+  XSetWindowBackground (graphic.display, graphic.window, graphic.back);
+
+  SetNormalHints ();
+  SetWMHints (&icon);
+  NameWindow ("Kapa");
+
+  if ((N = get_argument (*argc, argv, "-nomap"))) {
+    remove_argument(N, argc, argv);
+  } else {
+    MapWindow (graphic);
+  }  
+  
+}
Index: /tags/start/Ohana/src/kapa/setup/SetWMHints.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/SetWMHints.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/SetWMHints.c	(revision 12606)
@@ -0,0 +1,25 @@
+# include "Ximage.h"
+
+/************** SetWMHints  *************/
+void SetWMHints (Icon *icon) {
+
+  XWMHints *wmhints;
+
+  wmhints = XAllocWMHints ();
+  if (wmhints != (XWMHints *) NULL) {
+    wmhints[0].initial_state = NormalState;
+    wmhints[0].input = True;
+    if (icon[0].pixmap != (Pixmap) None) {
+      wmhints[0].icon_pixmap = icon[0].pixmap;
+      wmhints[0].icon_mask = icon[0].pixmap;
+      wmhints[0].flags = StateHint | InputHint | IconPixmapHint | IconMaskHint;
+    } else {
+      wmhints[0].flags = StateHint | InputHint;
+    }
+    
+    XSetWMHints (graphic.display, graphic.window, wmhints);
+    XFree (wmhints);
+
+  }
+}
+
Index: /tags/start/Ohana/src/kapa/setup/TopWindow.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/TopWindow.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/TopWindow.c	(revision 12606)
@@ -0,0 +1,21 @@
+# include "Ximage.h"
+
+/************** TopWindow *************/
+void TopWindow (Icon *icon) {
+
+  int screen;
+  Window rootwindow;
+
+  rootwindow = RootWindow (graphic.display, graphic.screen);
+
+  CreateWindow (rootwindow, BORDER_WIDTH, EVENT_MASK);
+  MakeGC ();
+
+  icon[0].pixmap = XCreateBitmapFromData (graphic.display, graphic.window, icon[0].bits, icon[0].width, icon[0].height);
+
+  MakeCursor (DEFAULT_CURSOR);
+  XFreeCursor (graphic.display, graphic.cursor);
+  FlushDisplay ();
+
+}
+
Index: /tags/start/Ohana/src/kapa/setup/Ximage.c
===================================================================
--- /tags/start/Ohana/src/kapa/setup/Ximage.c	(revision 12606)
+++ /tags/start/Ohana/src/kapa/setup/Ximage.c	(revision 12606)
@@ -0,0 +1,19 @@
+# include "Ximage.h"
+
+main (argc, argv)
+int argc;
+char *argv[];
+
+{
+  
+  SetUpDisplay (&argc, argv);
+  SetUpWindow (&argc, argv);
+
+  DefineLayout (argc, argv);
+  EventLoop ();
+
+  XFreeFont (graphic.display, graphic.font); 
+  CloseDisplay ();
+
+}
+
Index: /tags/start/Ohana/src/kii/Makefile
===================================================================
--- /tags/start/Ohana/src/kii/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/kii/Makefile	(revision 12606)
@@ -0,0 +1,124 @@
+include ../../Configure
+HOME 	=	$(ROOT)/src/kii
+PROGRAM =       kii
+
+default: $(PROGRAM)
+
+INC	=	$(HOME)/include
+BIN	=	$(HOME)/bin
+BDIR	=	$(HOME)/button
+CDIR	=	$(HOME)/colorbar
+EDIR	=	$(HOME)/event
+MDIR	=	$(HOME)/misc
+ODIR	=	$(HOME)/overlay
+PDIR	=	$(HOME)/picture
+SDIR	=	$(HOME)/setup
+ZDIR	=	$(HOME)/zoom
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+#
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) $(XLIB) -lohana -lFITS -ljpeg -lX11 -lsocket -lnsl -lm
+# LIBS	= 	-L$(LLIB) $(XLIB) -lohana -lFITS -ljpeg -lX11 -lsocket -lnsl -lm -static
+CFLAGS  =	-o $*.$(ARCH).o $(INCS) 
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+# local source / object files ########################
+BOBJ = \
+$(BDIR)/ButtonFunctions.$(ARCH).o         $(BDIR)/InButton.$(ARCH).o           \
+$(BDIR)/CheckButtons.$(ARCH).o     	  $(BDIR)/InPicture.$(ARCH).o          \
+$(BDIR)/DrawButton.$(ARCH).o       	  $(BDIR)/InvertButton.$(ARCH).o       \
+$(BDIR)/FlashButton.$(ARCH).o      	  $(BDIR)/PSit.$(ARCH).o		\
+$(BDIR)/JPEGit.$(ARCH).o
+
+COBJ = \
+$(CDIR)/CreateColorbar.$(ARCH).o          $(CDIR)/SetColormap.$(ARCH).o        \
+$(CDIR)/DragColorbar.$(ARCH).o
+
+EOBJ = \
+$(EDIR)/CheckPipe.$(ARCH).o               $(EDIR)/Stop.$(ARCH).o               \
+$(EDIR)/EventLoop.$(ARCH).o         	  $(EDIR)/Reconfig.$(ARCH).o           \
+$(EDIR)/InterpretKeys.$(ARCH).o     	  $(EDIR)/Refresh.$(ARCH).o            \
+$(EDIR)/InterpretPresses.$(ARCH).o  	  $(EDIR)/FlushDisplay.$(ARCH).o
+
+MOBJ = \
+$(MDIR)/hh_hms.$(ARCH).o		  
+
+OOBJ = \
+$(ODIR)/EraseOverlay.$(ARCH).o            $(ODIR)/PaintOverlay.$(ARCH).o       \
+$(ODIR)/LoadOverlay.$(ARCH).o   	  $(ODIR)/SaveOverlay.$(ARCH).o        \
+$(ODIR)/DrawOverlay.$(ARCH).o		  $(ODIR)/CSaveOverlay.$(ARCH).o 	\
+$(ODIR)/PaintTickmarks.$(ARCH).o          $(ODIR)/LoadTickmarks.$(ARCH).o
+
+POBJ = \
+$(PDIR)/CreatePicture.$(ARCH).o           $(PDIR)/Reorient.$(ARCH).o           \
+$(PDIR)/NewPicture.$(ARCH).o        	  $(PDIR)/Center.$(ARCH).o             \
+$(PDIR)/PositionPictures.$(ARCH).o  	  $(PDIR)/StatusBox.$(ARCH).o          \
+$(PDIR)/cursor.$(ARCH).o 							\
+$(PDIR)/CursorOps.$(ARCH).o 		  $(PDIR)/Resize.$(ARCH).o 		\
+$(PDIR)/Remap8.$(ARCH).o 		  $(PDIR)/Remap24.$(ARCH).o 		\
+$(PDIR)/Remap.$(ARCH).o             	  $(PDIR)/Remap32.$(ARCH).o		\
+$(PDIR)/Remap16.$(ARCH).o
+
+SOBJ = \
+$(SDIR)/CheckColors.$(ARCH).o             $(SDIR)/MakeGC.$(ARCH).o             \
+$(SDIR)/CheckDisplayName.$(ARCH).o  	  $(SDIR)/MapWindow.$(ARCH).o          \
+$(SDIR)/CheckFontName.$(ARCH).o     	  $(SDIR)/NameWindow.$(ARCH).o         \
+$(SDIR)/CheckGeometry.$(ARCH).o     	  $(SDIR)/OpenDisplay.$(ARCH).o        \
+$(SDIR)/CloseDisplay.$(ARCH).o      	  $(SDIR)/QuitX.$(ARCH).o              \
+$(SDIR)/CreateWindow.$(ARCH).o      	  $(SDIR)/SetNormalHints.$(ARCH).o     \
+$(SDIR)/DefineLayout.$(ARCH).o      	  $(SDIR)/SetUpDisplay.$(ARCH).o       \
+$(SDIR)/DrawBitmap.$(ARCH).o        	  $(SDIR)/SetUpWindow.$(ARCH).o        \
+$(SDIR)/GetColor.$(ARCH).o          	  $(SDIR)/SetWMHints.$(ARCH).o         \
+$(SDIR)/LoadFont.$(ARCH).o          	  $(SDIR)/TopWindow.$(ARCH).o          \
+$(SDIR)/MakeColormap.$(ARCH).o      	  $(SDIR)/Ximage.$(ARCH).o             \
+$(SDIR)/MakeCursor.$(ARCH).o              $(SDIR)/CheckVisual.$(ARCH).o
+
+ZOBJ = \
+$(ZDIR)/UpdatePointer.$(ARCH).o      \
+$(ZDIR)/CrossHairs.$(ARCH).o		  $(ZDIR)/UpdateStatusBox.$(ARCH).o	\
+$(ZDIR)/CreateZoom.$(ARCH).o              $(ZDIR)/CreateZoom32.$(ARCH).o        \
+$(ZDIR)/CreateZoom8.$(ARCH).o             $(ZDIR)/CreateZoom24.$(ARCH).o	\
+$(ZDIR)/CreateZoom16.$(ARCH).o
+
+
+OBJ  =  $(BOBJ) $(COBJ) $(EOBJ) $(MOBJ) $(OOBJ) $(POBJ) $(SOBJ) $(ZOBJ)
+
+# dependancy rules for include files ########################
+$(OBJ): $(INC)/Ximage.h \
+	$(INC)/constants.h \
+	$(INC)/structures.h \
+	$(INC)/prototypes.h
+
+#### nothing program-dependant below ####
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+dist: clean
+	rm -f */*.*.o
+	rm -f $(BIN)/$(PROGRAM).*
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
+
+
Index: /tags/start/Ohana/src/kii/button/ButtonFunctions.c
===================================================================
--- /tags/start/Ohana/src/kii/button/ButtonFunctions.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/button/ButtonFunctions.c	(revision 12606)
@@ -0,0 +1,120 @@
+# include "Ximage.h"
+
+static char *GREY = "greyscale";
+static char *PUNS = "Puns";
+static char *RAINBOW = "Rainbow";
+
+int greycolors (Graphic *graphic, Layout *layout) {
+  char *name;
+  name = GREY;
+  SetColormap (graphic, layout, name);
+  CreateColorbar (layout, graphic);
+  Remap (graphic, layout, &layout[0].matrix);
+  CreateZoom (layout, graphic, 0, 0); 
+  return (TRUE);
+}
+
+int puns (Graphic *graphic, Layout *layout) {
+  char *name;
+  name = PUNS;
+  SetColormap (graphic, layout, name);
+  CreateColorbar (layout, graphic);
+  Remap (graphic, layout, &layout[0].matrix);
+  CreateZoom (layout, graphic, 0, 0); 
+  return (TRUE);
+}
+
+int rainbow (Graphic *graphic, Layout *layout) {
+  char *name;
+  name = RAINBOW;
+  SetColormap (graphic, layout, name);
+  CreateColorbar (layout, graphic);
+  Remap (graphic, layout, &layout[0].matrix);
+  CreateZoom (layout, graphic, 0, 0); 
+  return (TRUE);
+}
+
+int Recenter (Graphic *graphic, Layout *layout) {
+
+  layout[0].X = 0;
+  layout[0].Y = 0;
+ 
+  Remap (graphic, layout, &layout[0].matrix);
+  Refresh (graphic, layout, 0);
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int Rescale (Graphic *graphic, Layout *layout) {
+
+  layout[0].expand = 1;
+  Remap (graphic, layout, &layout[0].matrix);
+  Refresh (graphic, layout, 0);
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int RecenterRescale (Graphic *graphic, Layout *layout) {
+
+  layout[0].X = 0;
+  layout[0].Y = 0;
+  layout[0].expand = 1;
+ 
+  Remap (graphic, layout, &layout[0].matrix);
+  Refresh (graphic, layout, 0);
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int ToggleDEG (Graphic *graphic, Layout *layout) {
+
+  DECIMAL_DEG = DECIMAL_DEG ^ TRUE;
+  StatusBox (graphic, layout);
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+/*********** overlay_button functions ************/
+int Overlay0 (Graphic *graphic, Layout *layout) {
+
+  OVERLAY[0] = OVERLAY[0] ^ TRUE;
+  Refresh (graphic, layout, 0);
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int Overlay1 (Graphic *graphic, Layout *layout) {
+
+  OVERLAY[1] = OVERLAY[1] ^ TRUE;
+  Refresh (graphic, layout, 0);
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int Overlay2 (Graphic *graphic, Layout *layout) {
+
+  OVERLAY[2] = OVERLAY[2] ^ TRUE;
+  Refresh (graphic, layout, 0);
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int Overlay3 (Graphic *graphic, Layout *layout) {
+
+  OVERLAY[3] = OVERLAY[3] ^ TRUE;
+  Refresh (graphic, layout, 0);
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+/* this routine is NOT independent of the number of overlays */
+
+
Index: /tags/start/Ohana/src/kii/button/CheckButtons.c
===================================================================
--- /tags/start/Ohana/src/kii/button/CheckButtons.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/button/CheckButtons.c	(revision 12606)
@@ -0,0 +1,57 @@
+# include "Ximage.h"
+# define PAD_X 10
+# define PAD_Y 10
+# define NPLANES 1
+# define NPIXELS 255
+
+/******** Here we test the Buttons specific to this program  *******/
+Button *
+CheckButtons (event, layout)
+XButtonEvent  event[];
+Layout        layout[];
+{
+
+  int i;
+  Button *button;
+  button = (Button *) NULL;
+
+  if (InButton (event, &layout[0].recenter_button)) 
+    button = &layout[0].recenter_button;
+
+  if (InButton (event, &layout[0].grey_button)) 
+    button = &layout[0].grey_button;
+
+  if (InButton (event, &layout[0].rainbow_button)) 
+    button = &layout[0].rainbow_button;
+
+  if (InButton (event, &layout[0].puns_button)) 
+    button = &layout[0].puns_button;
+
+  if (InButton (event, &layout[0].PS_button)) 
+    button = &layout[0].PS_button;
+
+  if (InButton (event, &layout[0].hms_button)) 
+    button = &layout[0].hms_button;
+
+  for (i = 0; i < NOVERLAYS; i++) {
+    if (InButton (event, &layout[0].overlay_button[i])) 
+      button = &layout[0].overlay_button[i];
+  }
+
+  return (button);
+
+}
+
+
+/* To define a button, you must:
+
+   0) add the button to the Layout structure in structures.h
+   1) place the info about the button in PositionPicture.c
+   2) (make any bitmaps needed and put them in buttons.h
+   3) place an entry in CheckButtons.c
+   4) Add the button to Refresh.c
+   5) create the button's function
+   6) add it to the Makefile
+   7) add it to the prototypes
+
+*/
Index: /tags/start/Ohana/src/kii/button/DrawButton.c
===================================================================
--- /tags/start/Ohana/src/kii/button/DrawButton.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/button/DrawButton.c	(revision 12606)
@@ -0,0 +1,44 @@
+# include "Ximage.h"
+
+void
+DrawButton (graphic, button)
+Graphic graphic[];
+Button button[];
+{
+  
+  int y, dX;
+  
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+  XFillRectangle (graphic[0].display, 
+		  graphic[0].window,
+		  graphic[0].gc,
+		  button[0].x,  button[0].y,
+		  button[0].dx, button[0].dy);
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+  XDrawRectangle (graphic[0].display, 
+		  graphic[0].window,
+		  graphic[0].gc,
+		  button[0].x,  button[0].y,
+		  button[0].dx, button[0].dy);
+
+  if (button[0].text) {
+    dX = XTextWidth (graphic[0].font, button[0].bitmap, strlen(button[0].bitmap));
+    y = button[0].y + (button[0].dy + graphic[0].font[0].ascent)/2;
+    XDrawString (graphic[0].display, 
+		 graphic[0].window, 
+		 graphic[0].gc, 
+		 button[0].x + (button[0].dx - dX) / 2, y,
+		 button[0].bitmap, strlen(button[0].bitmap));
+  }
+  else {
+    DrawBitmap (graphic, 
+		button[0].x + (button[0].dx - button[0].width) / 2 + 1, 
+		button[0].y + (button[0].dy - button[0].height) / 2 + 1, 
+		button[0].width, button[0].height, 
+		button[0].bitmap, 1);
+  }
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+
+}
+
Index: /tags/start/Ohana/src/kii/button/FlashButton.c
===================================================================
--- /tags/start/Ohana/src/kii/button/FlashButton.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/button/FlashButton.c	(revision 12606)
@@ -0,0 +1,22 @@
+# include "Ximage.h"
+
+void FlashButton (Graphic *graphic, Button *button) {
+
+  unsigned long black, white;
+
+  black =  graphic[0].black;
+  white =  graphic[0].white;
+  graphic[0].black = white;
+  graphic[0].white = black;
+
+  DrawButton (graphic, button);
+  XFlush (graphic[0].display);
+/*  usleep (20000);  removed - not a standard C sleep command, apparently! */
+  
+  graphic[0].black = black;
+  graphic[0].white = white;
+  DrawButton (graphic, button);
+  XFlush (graphic[0].display);
+
+}
+
Index: /tags/start/Ohana/src/kii/button/InButton.c
===================================================================
--- /tags/start/Ohana/src/kii/button/InButton.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/button/InButton.c	(revision 12606)
@@ -0,0 +1,22 @@
+# include "Ximage.h"
+
+int
+InButton (button_event, button)
+XButtonEvent *button_event;
+Button button[];
+{
+
+  int answer;
+  int x, y;
+
+  x = button_event[0].x;
+  y = button_event[0].y;
+  
+  answer = ((x >= button[0].x) && (x <= button[0].x + button[0].dx) &&
+	    (y >= button[0].y) && (y <= button[0].y + button[0].dy));
+
+  return (answer);
+
+}
+
+/*** make this a macro? ***/
Index: /tags/start/Ohana/src/kii/button/InPicture.c
===================================================================
--- /tags/start/Ohana/src/kii/button/InPicture.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/button/InPicture.c	(revision 12606)
@@ -0,0 +1,21 @@
+# include "Ximage.h"
+
+int
+InPicture (button_event, picture)
+XButtonEvent *button_event;
+Picture picture[];
+{
+
+  int answer;
+  int x, y;
+
+  x = button_event[0].x;
+  y = button_event[0].y;
+  
+  answer = ((x >= picture[0].x) && (x <= picture[0].x + picture[0].dx) &&
+	    (y >= picture[0].y) && (y <= picture[0].y + picture[0].dy));
+
+  return (answer);
+
+}
+
Index: /tags/start/Ohana/src/kii/button/InvertButton.c
===================================================================
--- /tags/start/Ohana/src/kii/button/InvertButton.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/button/InvertButton.c	(revision 12606)
@@ -0,0 +1,20 @@
+# include "Ximage.h"
+
+void InvertButton (Graphic *graphic, Button *button) {
+
+  unsigned long black, white;
+
+  black =  graphic[0].black;
+  white =  graphic[0].white;
+
+  graphic[0].black = white;
+  graphic[0].white = black;
+
+  DrawButton (graphic, button);
+  FlushDisplay (graphic[0].display);
+  
+  graphic[0].black = black;
+  graphic[0].white = white;
+
+}
+
Index: /tags/start/Ohana/src/kii/button/JPEGit.c
===================================================================
--- /tags/start/Ohana/src/kii/button/JPEGit.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/button/JPEGit.c	(revision 12606)
@@ -0,0 +1,153 @@
+# include "Ximage.h"
+# include "jpeglib.h"
+
+int JPEGit (Graphic *graphic, Layout *layout) {
+  
+  struct jpeg_compress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */
+  JSAMPLE *image_buffer;	/* Points to data for current line */
+
+  int j, k, m;
+  unsigned char *buff;
+  double Nchar, Npix, start, slope, frac;
+  int quality;
+  unsigned long pcolor;
+
+  char filename[1024];
+  int Nbytes, status;
+
+  XImage *tmpimage;
+
+  FILE *f;
+  
+  /* expect a line telling the number of bytes and a filename */
+  status = read (layout[0].Ximage, filename, 16);
+  filename[16] = 0;
+  sscanf (filename, "%*s %d", &Nbytes);
+  status = read (layout[0].Ximage, filename, Nbytes);
+  filename[status] = 0; /* make the string easy to parse */
+
+  /* 
+  switch (graphic[0].Nbits) {
+  case 8:
+    break;
+  case 16:
+    fprintf (stderr, "converter to 16 bit not yet implemented\n");
+    return (TRUE);
+    break;
+  case 24:
+    fprintf (stderr, "converter to 24 bit not yet implemented\n");
+    return (TRUE);
+    break;
+  case 32:
+    fprintf (stderr, "converter to 32 bit not yet implemented\n");
+    return (TRUE);
+    break;
+  }
+  */
+
+  /* set up the error handler , initialize the JPEG compression object. */
+  cinfo.err = jpeg_std_error (&jerr);
+  jpeg_create_compress (&cinfo);
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "failed to open %s for output\n", filename);
+    return (TRUE);
+  }
+  jpeg_stdio_dest(&cinfo, f);
+  
+  quality = 75;
+  cinfo.image_width = layout[0].picture.dx; 	/* image width and height, in pixels */
+  cinfo.image_height = layout[0].picture.dy;
+# ifdef GREYSCALE
+  cinfo.input_components = 1;		        /* # of color components per pixel */
+  cinfo.in_color_space = JCS_GRAYSCALE; 	/* colorspace of input image */
+# else 
+  cinfo.input_components = 3;		        
+  cinfo.in_color_space = JCS_RGB; 	
+# endif
+  jpeg_set_defaults (&cinfo);
+  jpeg_set_quality (&cinfo, quality, TRUE       /* limit to baseline-JPEG values */);
+  jpeg_start_compress (&cinfo, TRUE);
+
+  ALLOCATE (image_buffer, JSAMPLE, 3*layout[0].picture.dx);
+  buff = (unsigned char *)layout[0].picture.data;
+  slope = layout[0].slope;
+  start = layout[0].start;
+  Nchar = 255.0;                                /* range of output values */
+  Npix = layout[0].Npixels;
+  frac = Nchar / Npix;
+  
+  {
+    XWindowAttributes WindowAttributes;
+    Pixmap tmp_pixmap;
+    Window tmp_window;
+    
+    XGetWindowAttributes (graphic[0].display, graphic[0].window, &WindowAttributes);
+    
+    tmp_pixmap = XCreatePixmap (graphic[0].display, graphic[0].window, graphic[0].dx, graphic[0].dy, WindowAttributes.depth);
+
+    tmp_window = graphic[0].window;
+    graphic[0].window = tmp_pixmap;
+
+    Refresh (graphic, layout, 0);
+
+    tmpimage = XGetImage (graphic[0].display, graphic[0].window, layout[0].picture.x+1, layout[0].picture.y+1, layout[0].picture.dx, layout[0].picture.dy, 0xffffffff, ZPixmap);
+
+    for (j = 0; (j < layout[0].picture.dy) && (cinfo.next_scanline < cinfo.image_height); j++) {
+      for (k = 0; k < layout[0].picture.dx; k++) {
+	pcolor = XGetPixel (tmpimage, k, j);
+	if (pcolor == layout[0].white) { 
+	  image_buffer[3*k+0] = Nchar;
+	  image_buffer[3*k+1] = Nchar;
+	  image_buffer[3*k+2] = Nchar;
+	  continue;
+	}
+	if (pcolor == layout[0].overlay[0].color) { 
+	  image_buffer[3*k+0] = Nchar;
+	  image_buffer[3*k+1] = 0;
+	  image_buffer[3*k+2] = 0;
+	  continue;
+	}
+	if (pcolor == layout[0].overlay[1].color) { 
+	  image_buffer[3*k+0] = 0;
+	  image_buffer[3*k+1] = Nchar;
+	  image_buffer[3*k+2] = 0;
+	  continue;
+	}
+	if (pcolor == layout[0].overlay[2].color) { 
+	  image_buffer[3*k+0] = 0;
+	  image_buffer[3*k+1] = 0;
+	  image_buffer[3*k+2] = Nchar;
+	  continue;
+	}
+	if (pcolor == layout[0].overlay[3].color) { 
+	  image_buffer[3*k+0] = Nchar;
+	  image_buffer[3*k+1] = Nchar;
+	  image_buffer[3*k+2] = 0;
+	  continue;
+	}
+	for (m = 0; (layout[0].cmap[m].pixel != pcolor) && (m < Npix); m++);
+	/* val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix); */
+	image_buffer[3*k+0] = layout[0].cmap[m].red / 256;
+	image_buffer[3*k+1] = layout[0].cmap[m].green / 256;
+	image_buffer[3*k+2] = layout[0].cmap[m].blue / 256;
+      }
+      row_pointer[0] = image_buffer;
+      (void) jpeg_write_scanlines (&cinfo, row_pointer, 1);
+    }
+    graphic[0].window = tmp_window;
+    XFreePixmap (graphic[0].display, tmp_pixmap);
+  }
+
+  XDestroyImage (tmpimage);
+
+  jpeg_finish_compress (&cinfo);
+  fclose (f);
+  jpeg_destroy_compress (&cinfo);
+
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/kii/button/PSit.c
===================================================================
--- /tags/start/Ohana/src/kii/button/PSit.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/button/PSit.c	(revision 12606)
@@ -0,0 +1,238 @@
+# include "Ximage.h"
+/* Notice: we are using a fixed border size of 10 pt */
+void ConvertPixmap8  (Layout *layout, FILE *f);
+void ConvertPixmap16 (Layout *layout, FILE *f);
+void ConvertPixmap24 (Layout *layout, FILE *f);
+void ConvertPixmap32 (Layout *layout, FILE *f);
+
+int PSit (Graphic *graphic, Layout *layout, int Raw) {
+  
+  FILE *f;
+  int i;
+  double scale;
+  char filename[1024];
+  int Nbytes, status;
+
+  /* expect a line telling the number of bytes and a filename */
+  status = read (layout[0].Ximage, filename, 16);
+  filename[16] = 0;
+  sscanf (filename, "%*s %d", &Nbytes);
+  status = read (layout[0].Ximage, filename, Nbytes);
+  filename[status] = 0; /* make the string easy to parse */
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "failed to open %s for output\n", filename);
+    return (TRUE);
+  }
+  
+  scale = MIN ((500.0/(double)layout[0].picture.dx), (700.0/(double)layout[0].picture.dy));
+  if (!Raw) {
+    fprintf (f, "%%!PS-Adobe-2.0 EPSF-2.0\n");
+    fprintf (f, "%%%%Title: %s\n", layout[0].file);
+    fprintf (f, "%%%%Creator: Ki'i (0.95)\n");
+    fprintf (f, "%%%%BoundingBox: 10 40 %d %d \n", (int)(scale*layout[0].picture.dx + 30), (int)(scale*layout[0].picture.dy + 60));
+    fprintf (f, "%%%%Pages: 1\n");
+    fprintf (f, "%%%%DocumentFonts:\n");
+    fprintf (f, "%%%%EndComments\n");
+    fprintf (f, "%%%%EndProlog\n");
+    fprintf (f, "%%%%Page: 1 1\n\n");
+
+  }
+
+  fprintf (f, "gsave %% encloses picture\n");
+  fprintf (f, "%% local abbreviations\n");
+  fprintf (f, "/Times-Roman findfont 18 scalefont setfont\n");
+  fprintf (f, "/T {moveto show stroke} def\n");
+  fprintf (f, "/B { newpath moveto dup 0 exch rlineto exch dup 0 rlineto exch -1 mul\n");
+  fprintf (f, " 0 exch rlineto -1 mul 0 rlineto closepath stroke } def\n");
+  fprintf (f, "/C {0 360 arc stroke} def\n");
+  fprintf (f, "/L {newpath moveto lineto stroke} def\n\n");
+
+  if (!Raw) {
+    fprintf (f, " 20 50 translate\n");
+    fprintf (f, "  %f  %f scale\n", scale, scale);
+  }
+
+  fprintf (f, " newpath 0 0 moveto %d 0 lineto %d %d lineto 0 %d lineto closepath clip\n\n", 
+	   layout[0].picture.dx, layout[0].picture.dx, layout[0].picture.dy, layout[0].picture.dy);
+  fprintf (f, "gsave %% encloses image\n");
+  fprintf (f, "%d %d 8\n", layout[0].picture.dx, layout[0].picture.dy);
+  fprintf (f, "[1 0 0 1 0 0]\n");
+  fprintf (f, "{currentfile %d string readhexstring pop} image\n\n", layout[0].picture.dx);
+
+  /******** First we draw the picture itself ********/
+  switch (graphic[0].Nbits) {
+  case 8:
+    ConvertPixmap8 (layout, f);
+    break;
+  case 16:
+    ConvertPixmap16 (layout, f);
+    break;
+  case 24:
+    ConvertPixmap24 (layout, f);
+    break;
+  case 32:
+    ConvertPixmap32 (layout, f);
+    break;
+  }
+
+  fprintf (f, "grestore %% end of image\n");
+  fprintf (f, "stroke\n");
+  fprintf (f, "%% plot overlay objects\n");
+  fprintf (f, "1 setgray\n");
+
+  for (i = 0; i < NOVERLAYS; i++) {
+    if (OVERLAY[i]) {
+      fprintf (f, "%% overlay %d\n", i);
+      DrawOverlay (graphic, layout, i, f, 0);
+    }
+  }
+  fprintf (f, "0 setgray\n");
+  for (i = 0; i < NOVERLAYS; i++) {
+    if (OVERLAY[i]) {
+      fprintf (f, "%% overlay %d\n", i);
+      DrawOverlay (graphic, layout, i, f, 1);
+    }
+  }
+  
+  fprintf (f, "grestore %% end of picture\n");
+
+  if (!Raw) fprintf (f, "showpage\n");
+
+  fclose (f);
+
+  return (TRUE);
+
+}
+
+void ConvertPixmap8 (Layout *layout, FILE *f) {
+
+  int i, k, m, val;
+  double Nchar, Npix, start, slope, frac;
+  char *buff;
+
+  Nchar = 255.0;
+  Npix = layout[0].Npixels;
+  frac = Nchar / Npix;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned char *)layout[0].picture.data + layout[0].picture.dx*(layout[0].picture.dy - 1);
+  slope = layout[0].slope;
+  start = layout[0].start;
+
+  for (i = 0; i < layout[0].picture.dy; i++) {
+    for (k = 0; k < layout[0].picture.dx; k++, buff++) {
+      if (*buff == layout[0].white) 
+	val = Nchar;
+      else {
+	for (m = 0; (layout[0].cmap[m].pixel != *buff) && (m < Npix); m++);
+	val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix);
+      }
+      fprintf (f, "%02x", val);
+      if (!((k+1) % 40)) fprintf (f, "\n"); 
+    }
+    fprintf (f, "\n");
+    buff -= 2*layout[0].picture.dx;
+  }
+  return;
+}
+
+void ConvertPixmap16 (Layout *layout, FILE *f) {
+
+  int i, k, m, val;
+  double Nchar, Npix, start, slope, frac;
+  unsigned short *buff;
+
+  Nchar = 255.0;
+  Npix = layout[0].Npixels;
+  frac = Nchar / Npix;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned short *)layout[0].picture.data + layout[0].picture.dx*(layout[0].picture.dy - 1);
+  slope = layout[0].slope;
+  start = layout[0].start;
+
+  for (i = 0; i < layout[0].picture.dy; i++) {
+    for (k = 0; k < layout[0].picture.dx; k++, buff++) {
+      if (*buff == layout[0].white) 
+	val = Nchar;
+      else {
+	for (m = 0; (layout[0].cmap[m].pixel != *buff) && (m < Npix); m++);
+	val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix);
+      }
+      fprintf (f, "%02x", val);
+      if (!((k+1) % 40)) fprintf (f, "\n"); 
+    }
+    fprintf (f, "\n");
+    buff -= 2*layout[0].picture.dx;
+  }
+  return;
+}
+
+void ConvertPixmap24 (Layout *layout, FILE *f) {
+
+  int i, k, m, dx, dy, val, extra;
+  unsigned char *buff;
+  unsigned long color, byte;
+  double Nchar, Npix, start, slope, frac;
+
+  Nchar = 255.0;
+  Npix = layout[0].Npixels;
+  frac = Nchar / Npix;
+  dx = layout[0].picture.dx;
+  dy = layout[0].picture.dy;
+  extra = 4 - (dx * 3) % 4;
+  /* start at the last line, print lines in decending order */
+  buff = &layout[0].picture.data[(dy - 1)*(3*dx + extra)];
+  slope = layout[0].slope;
+  start = layout[0].start;
+
+  for (i = 0; i < dy; i++) {
+    for (k = 0; k < dx; k++, buff+=3) {
+      color = 0;
+      byte = buff[2];
+      color = (byte << 16);
+      byte = buff[1];
+      color |= (byte << 8);
+      byte = buff[0];
+      color |= byte;
+      for (m = 0; (layout[0].cmap[m].pixel != color) && (m < Npix); m++);
+      val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix);
+      fprintf (f, "%02x", val);
+      if (!((k+1) % 40)) fprintf (f, "\n"); 
+    }
+    fprintf (f, "\n");
+    buff -= 2*3*dx + extra;
+  }
+  return;
+}
+
+void ConvertPixmap32 (Layout *layout, FILE *f) {
+
+  int i, k, m, val;
+  double Nchar, Npix, start, slope, frac;
+  unsigned int *buff;
+
+  Nchar = 255.0;
+  Npix = layout[0].Npixels;
+  frac = Nchar / Npix;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned int *)layout[0].picture.data + layout[0].picture.dx*(layout[0].picture.dy - 1);
+  slope = layout[0].slope;
+  start = layout[0].start;
+
+  for (i = 0; i < layout[0].picture.dy; i++) {
+    for (k = 0; k < layout[0].picture.dx; k++, buff++) {
+      if (*buff == layout[0].white) 
+	val = Nchar;
+      else {
+	for (m = 0; (layout[0].cmap[m].pixel != *buff) && (m < Npix); m++);
+	val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix);
+      }
+      fprintf (f, "%02x", val);
+      if (!((k+1) % 40)) fprintf (f, "\n"); 
+    }
+    fprintf (f, "\n");
+    buff -= 2*layout[0].picture.dx;
+  }
+  return;
+}
Index: /tags/start/Ohana/src/kii/colorbar/CreateColorbar.c
===================================================================
--- /tags/start/Ohana/src/kii/colorbar/CreateColorbar.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/colorbar/CreateColorbar.c	(revision 12606)
@@ -0,0 +1,73 @@
+# include "Ximage.h"
+
+void CreateColorbar (Layout *layout, Graphic *graphic) {
+
+  int i, j, dx, dy, extra, start;
+  unsigned long  pixvalue;
+  unsigned int  *out24;
+  unsigned char *out8;
+
+  dx = layout[0].cmapbar.dx;
+  dy = layout[0].cmapbar.dy;
+
+  /* create the cmap scale */
+  switch (graphic[0].Nbits) {
+  case 8:
+    REALLOCATE (layout[0].cmapbar.data, char, dx*dy);
+    out8 = (unsigned char *) layout[0].cmapbar.data;
+    for (i = 0; i < dx; i++) {
+      pixvalue = layout[0].cmap[(int)(i*layout[0].Npixels/dx)].pixel;
+      for (j = 0; j < dy; j++) {
+	out8[j*dx + i] = pixvalue;
+      }
+    }
+    layout[0].cmapbar.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  layout[0].cmapbar.data, dx, dy, 8, 0);
+    break;
+
+  case 16:
+    REALLOCATE (layout[0].cmapbar.data, char, 2*dy*dx);
+    out8 = layout[0].cmapbar.data;
+    for (i = 0; i < dx; i++) {
+      pixvalue = layout[0].cmap[(int)(i*layout[0].Npixels/dx)].pixel;
+      for (j = 0; j < dy; j++) {
+	start = 2*j*dx + 2*i;
+	out8[start + 0] = 0x0000ff & pixvalue;
+	out8[start + 1] = 0x0000ff & (pixvalue >> 8);
+      }
+    }
+    layout[0].cmapbar.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  layout[0].cmapbar.data, dx, dy, 16, 0);
+    break;
+
+  case 24:
+    extra = 4 - (dx * 3) % 4;
+    REALLOCATE (layout[0].cmapbar.data, char, dy*(3*dx + extra));
+    out8 = layout[0].cmapbar.data;
+    for (i = 0; i < dx; i++) {
+      pixvalue = layout[0].cmap[(int)(i*layout[0].Npixels/dx)].pixel;
+      for (j = 0; j < dy; j++) {
+	start = j*(3*dx+extra) + 3*i;
+	out8[start + 0] = 0x0000ff & pixvalue;
+	out8[start + 1] = 0x0000ff & (pixvalue >> 8);
+	out8[start + 2] = 0x0000ff & (pixvalue >> 16);
+      }
+    }
+    layout[0].cmapbar.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  layout[0].cmapbar.data, dx, dy, 32, 0);
+    break;
+
+  case 32:
+    REALLOCATE (layout[0].cmapbar.data, char, 4*dx*dy);
+    out24 = (unsigned int *) layout[0].cmapbar.data;
+    for (i = 0; i < dx; i++) {
+      pixvalue = layout[0].cmap[(int)(i*layout[0].Npixels/dx)].pixel;
+      for (j = 0; j < dy; j++) {
+	out24[j*dx + i] = pixvalue;
+      }
+    }
+    layout[0].cmapbar.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  layout[0].cmapbar.data, dx, dy, 32, 0);
+    break;
+  }
+}
Index: /tags/start/Ohana/src/kii/colorbar/DragColorbar.c
===================================================================
--- /tags/start/Ohana/src/kii/colorbar/DragColorbar.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/colorbar/DragColorbar.c	(revision 12606)
@@ -0,0 +1,107 @@
+# include "Ximage.h"
+/* future expansion: warp mouse to the right spot for the current settings */
+
+void DragColorbar (Graphic *graphic, Layout *layout, XButtonEvent *mouse_event) {
+
+  double          frac_x, oldfrac_x, frac_y, oldfrac_y, start, slope;
+  int             X, Y;
+  XEvent          event;
+  XMotionEvent   *move;
+  int             xstatus, Npix, center;
+
+  if (!graphic[0].visualclass) return;
+
+  X = mouse_event[0].x;
+  Y = mouse_event[0].y;
+  Npix = layout[0].Npixels;
+  slope = layout[0].slope;
+  start = layout[0].start;
+  oldfrac_x = 10;
+  
+  while (1) {
+    frac_x = X / (1.0*graphic[0].dx);
+    frac_x = MAX (0, frac_x);
+    frac_x = MIN (1, frac_x);
+    frac_y = Y / (1.0*graphic[0].dy);
+    frac_y = MAX (0, frac_y);
+    frac_y = MIN (1, frac_y);
+    switch (mouse_event[0].button) {
+    case 1:
+      center = frac_x*Npix;
+      slope = Npix / (1 + 4*frac_y*frac_y*Npix);
+      start = Npix/2.0 - center*slope;
+      break;
+    case 2:
+      start = 0;
+      slope = 1;
+      break;
+    case 3:
+      center = (Npix/2.0 - start) / slope;
+      slope = Npix / (1 + 4*frac_x*frac_x*Npix);
+      start = Npix/2.0 - center*slope;
+      break;
+    }
+
+    if ((frac_x != oldfrac_x) || (frac_y != oldfrac_y)) {
+      ResetColorbar (graphic, layout, start, slope);
+    }
+    oldfrac_x = frac_x;
+    oldfrac_y = frac_y;
+      
+    if ((xstatus = XCheckMaskEvent (graphic[0].display, EVENT_MASK, &event))) {
+      
+      switch (event.type)  {
+	
+      case MotionNotify:
+	if ((xstatus = XPending (graphic[0].display)) < 2) {
+	  move = (XMotionEvent *) &event;
+	  X = move[0].x;
+	  Y = move[0].y;
+	}
+	break;
+	
+      case ButtonPress:
+      case ButtonRelease:
+	layout[0].start = start;	
+	layout[0].slope = slope;
+	return;
+	break;
+	
+      }
+    }
+  }
+  
+}
+
+void ResetColorbar (Graphic *graphic, Layout *layout, double start, double slope) {
+
+  int i, j;
+  XColor cmap[256];
+
+  if (!graphic[0].visualclass) return;
+
+  for (i = 0; i < layout[0].Npixels; i++) {
+    cmap[i] = layout[0].cmap[i];
+    j = start + i * slope;
+    if (j < 0) {
+      cmap[i].red = layout[0].cmap[0].red;
+      cmap[i].blue = layout[0].cmap[0].blue;
+      cmap[i].green = layout[0].cmap[0].green;
+    }
+    else {
+      if (j >= layout[0].Npixels) {
+	cmap[i].red = layout[0].cmap[layout[0].Npixels-1].red;
+	cmap[i].blue = layout[0].cmap[layout[0].Npixels-1].blue;
+	cmap[i].green = layout[0].cmap[layout[0].Npixels-1].green;
+      }
+      else {
+	cmap[i].red = layout[0].cmap[j].red;
+	cmap[i].blue = layout[0].cmap[j].blue;
+	cmap[i].green = layout[0].cmap[j].green;
+      }
+    }
+  }
+
+  XStoreColors(graphic[0].display, graphic[0].colormap, cmap, layout[0].Npixels);
+
+}
Index: /tags/start/Ohana/src/kii/colorbar/SetColormap.c
===================================================================
--- /tags/start/Ohana/src/kii/colorbar/SetColormap.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/colorbar/SetColormap.c	(revision 12606)
@@ -0,0 +1,97 @@
+# include "Ximage.h"
+
+int SetColormap (Graphic *graphic, Layout *layout, char *name) {
+
+  int i;
+
+  /* greyscale */
+  if ((!strcmp (name, "grayscale")) || (!strcmp (name, "greyscale"))) {
+    for (i = 0; i < layout[0].Npixels; i++) {  
+      layout[0].cmap[i].red = 256*(255 - 255*i/layout[0].Npixels);
+      layout[0].cmap[i].green = 256*(255 - 255*i/layout[0].Npixels);
+      layout[0].cmap[i].blue = 256*(255 - 255*i/layout[0].Npixels);
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  /* heat */
+  if (!strcmp (name, "Puns")) {
+    for (i = 0; i < (int)(0.25*layout[0].Npixels); i++) {  
+      layout[0].cmap[i].green = 0;
+      layout[0].cmap[i].blue = 0;
+      layout[0].cmap[i].red = MIN (256*255, 256*255*2*i/(1.0*layout[0].Npixels));  
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.25*layout[0].Npixels); i < (int)(0.50*layout[0].Npixels); i++) {  
+      layout[0].cmap[i].red = MIN (256*255, 256*255*2*i/(1.0*layout[0].Npixels));
+      layout[0].cmap[i].green = MIN (256*255, 256*255*2*(i/(1.0*layout[0].Npixels) - 0.25));
+      layout[0].cmap[i].blue = 0;
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.50*layout[0].Npixels); i < (int)(0.75*layout[0].Npixels); i++) {  
+      layout[0].cmap[i].red = 256*255;
+      layout[0].cmap[i].green = MIN (256*255, 256*255*2*(i/(1.0*layout[0].Npixels) - 0.25));
+      layout[0].cmap[i].blue = MIN (256*255, 256*255*2*(i/(1.0*layout[0].Npixels) - 0.50));
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.75*layout[0].Npixels); i < layout[0].Npixels; i++) {  
+      layout[0].cmap[i].red = 256*255;
+      layout[0].cmap[i].green = 256*255;
+      layout[0].cmap[i].blue = MIN (256*255, 256*255*2*(i/(1.0*layout[0].Npixels) - 0.50));
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  /* -grayscale */
+  if ((!strcmp (name, "-grayscale")) || (!strcmp (name, "-greyscale"))) {
+    for (i = 0; i < layout[0].Npixels; i++) {  
+      layout[0].cmap[i].red = 256*(255*i/layout[0].Npixels);
+      layout[0].cmap[i].green = 256*(255*i/layout[0].Npixels);
+      layout[0].cmap[i].blue = 256*(255*i/layout[0].Npixels);
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  /* rainbow */
+  if (!strcmp (name, "Rainbow")) {
+    for (i = 0; i < (int)(0.25*layout[0].Npixels); i++) {  
+      layout[0].cmap[i].red = 0;
+      layout[0].cmap[i].green = 0;
+      layout[0].cmap[i].blue = 256*(255*4*(i/(1.0*layout[0].Npixels)));  
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.25*layout[0].Npixels); i < (int)(0.50*layout[0].Npixels); i++) {  
+      layout[0].cmap[i].red = 256*(255*4*((i/(1.0*layout[0].Npixels)) - 0.25));
+      layout[0].cmap[i].green = 0;
+      layout[0].cmap[i].blue = 256*(255*4*(0.50 - (i/(1.0*layout[0].Npixels))));
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.50*layout[0].Npixels); i < (int)(0.75*layout[0].Npixels); i++) {  
+      layout[0].cmap[i].red = 256*255;
+      layout[0].cmap[i].green = 256*(255*4*((i/(1.0*layout[0].Npixels)) - 0.50));
+      layout[0].cmap[i].blue = 0;
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.75*layout[0].Npixels); i < layout[0].Npixels; i++) {  
+      layout[0].cmap[i].red = 256*255;
+      layout[0].cmap[i].green = 256*255;
+      layout[0].cmap[i].blue = 256*(255*4*((i/(1.0*layout[0].Npixels)) - 0.75));
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  return (FALSE);
+
+ store_colors:
+  if (graphic[0].visualclass) {
+    XStoreColors(graphic[0].display, graphic[0].colormap, layout[0].cmap, layout[0].Npixels);
+  } else {
+    for (i = 0; i < layout[0].Npixels; i++) {
+      if (XAllocColor (graphic[0].display, graphic[0].colormap, &layout[0].cmap[i]) == 0) {
+	fprintf (stderr, "error on %d\n", i);
+      }
+    }
+  }
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/kii/event/CheckPipe.c
===================================================================
--- /tags/start/Ohana/src/kii/event/CheckPipe.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/event/CheckPipe.c	(revision 12606)
@@ -0,0 +1,117 @@
+# include "Ximage.h"
+# define STRCONST(A) ((int)(0x1000000*A[0] + 0x10000*A[1] + 0x100*A[2] + 0x1*A[3]))
+
+int CheckPipe (Graphic *graphic, Layout *layout) {
+
+  int status;
+  char buffer[1024];
+
+  /* attempt to read 4 bytes from stdin */
+
+  status = read (layout[0].Ximage, buffer, 4);
+  buffer[4] = 0;
+
+  switch (status) {
+  case -1:
+    /* no input from pipe: continue */
+    return (TRUE);
+    break;
+
+  case 0:
+    fprintf (stderr, "pipe has died!\n");
+    return (FALSE);
+    break;
+
+  case 4:
+/*    fprintf (stderr, "got signal %s from pipe\n", buffer);    */
+    break;
+
+  default:
+    fprintf (stderr, "weird signal: too many or few bytes!  %d\n", status);
+    return (TRUE);
+    break;
+  }
+
+  
+  if (!strcmp (buffer, "QUIT")) {
+    /* fprintf (stderr, "Goodbye!\n"); */
+    return (FALSE);
+  }
+  
+  if (!strcmp (buffer, "READ")) {
+    status = NewPicture (graphic, layout);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "CURS")) {
+    status = cursor (graphic, layout);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "ERAS")) {
+    status = EraseOverlay (graphic, layout);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "LOAD")) {
+    status = LoadOverlay (graphic, layout);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "TICK")) {
+    status = LoadTickmarks (graphic, layout);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "SAVE")) {
+    status = SaveOverlay (graphic, layout);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "PSIT")) {
+    status = PSit (graphic, layout, 0);
+    write (layout[0].Ximage, "DONE", 4);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "PSRW")) {
+    status = PSit (graphic, layout, 1);
+    write (layout[0].Ximage, "DONE", 4);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "JPEG")) {
+    status = JPEGit (graphic, layout);
+    write (layout[0].Ximage, "DONE", 4);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "RSIZ")) {
+    status = Resize (graphic, layout);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "CSVE")) {
+    status = CSaveOverlay (graphic, layout);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "CENT")) {
+    status = Center (graphic, layout);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "NPIX")) {
+    sprintf (buffer, "NPIX:   %8d", layout[0].Npixels);
+    write (layout[0].Ximage, buffer, 16);
+    return (TRUE);
+  }
+
+  fprintf (stderr, "unknown signal %s\n", buffer);
+
+  return (TRUE);
+
+}
+
+
+    
Index: /tags/start/Ohana/src/kii/event/EventLoop.c
===================================================================
--- /tags/start/Ohana/src/kii/event/EventLoop.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/event/EventLoop.c	(revision 12606)
@@ -0,0 +1,94 @@
+# include "Ximage.h"
+# define MAX_STRING 100
+/* WARNING: this is defined because the HP UX installation i have does not
+seem to know this structure, though it should */
+# ifdef DUMMY
+struct Ktimeval {
+  unsigned long tv_sec;         /* seconds */
+  long          tv_usec;        /* and microseconds */
+};
+# endif
+
+int EventLoop (Graphic *graphic, Layout *layout) {
+  
+  XEvent          event;
+  int             status;
+  
+  /* gettimeofday (&then, (struct timeval *) NULL); */
+
+  Refresh (graphic, layout, 1);
+
+  status = TRUE;
+  while (status) {
+    
+    if (!CheckPipe (graphic, layout))
+      return (FALSE);
+    
+    if (XEventsQueued (graphic[0].display, QueuedAfterFlush) < 1) {
+      usleep (10000);
+      continue;
+    }
+
+    if (XCheckMaskEvent (graphic[0].display, EVENT_MASK, &event)) {
+
+      switch (event.type)  {
+	
+      case MotionNotify:
+	if (XEventsQueued (graphic[0].display, QueuedAlready) < 2) {
+	  UpdatePointer (graphic, layout, (XMotionEvent *) &event);
+	}
+	break;
+      case ButtonPress:
+	status = InterpretPresses (graphic, layout, (XButtonEvent *) &event);
+	break;
+	
+      case Expose:
+	if (XEventsQueued (graphic[0].display, QueuedAlready) < 2) {
+	  Refresh (graphic, layout, 1);
+	}
+	break;
+	/* if (event.xexpose.count == 0) */
+	
+      case ConfigureNotify:
+	status = Reconfig (graphic, layout, &event);
+	/*
+	if (XEventsQueued (graphic[0].display, QueuedAlready) < 2) {
+	  status = Reconfig (graphic, layout, &event);
+	}
+	*/
+	break;
+	
+      case KeyPress:
+	status = InterpretKeys (graphic, layout, &event);
+	break;
+	
+      case MappingNotify:
+	if (XEventsQueued (graphic[0].display, QueuedAlready) < 2) {
+	  XRefreshKeyboardMapping ((XMappingEvent *) &event);
+	}
+	break;
+	
+      }
+    }
+  }
+  return (status);
+}
+
+/*     
+while (XPending (graphic[0].display) {
+if (readfds && display_mask) { 
+*/
+/*
+  while (1) {
+    fprintf (stderr, "window in EventLoop: %x  %d\n", graphic[0].display, graphic[0].window);
+    XNextEvent (graphic[0].display, &event);
+    if (event.type == ClientMessage) {
+      fprintf (stderr, "choice 1\n");
+    }
+    
+    if (event.xclient.send_event) {
+      fprintf (stderr, "choice 2\n");
+    }
+  }
+*/
+  
Index: /tags/start/Ohana/src/kii/event/FlushDisplay.c
===================================================================
--- /tags/start/Ohana/src/kii/event/FlushDisplay.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/event/FlushDisplay.c	(revision 12606)
@@ -0,0 +1,32 @@
+# include "Ximage.h"
+
+static struct timeval reftime; 
+static char reftimeset = FALSE;
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+
+void FlushDisplay (Display *display) {
+
+  struct timeval now;
+  int flush;
+  double dtime;
+
+  flush = FALSE;
+  if (!reftimeset) {
+    flush = TRUE;
+    gettimeofday (&reftime, NULL);
+  } 
+
+  gettimeofday (&now, NULL);
+  dtime = DTIME (now, reftime);
+
+  if (dtime > 0.1) {
+    flush = TRUE;
+  }
+
+  if (flush) {
+    XFlush (display);
+    reftime = now;
+  }
+
+}
+
Index: /tags/start/Ohana/src/kii/event/InterpretKeys.c
===================================================================
--- /tags/start/Ohana/src/kii/event/InterpretKeys.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/event/InterpretKeys.c	(revision 12606)
@@ -0,0 +1,44 @@
+# include "Ximage.h"
+
+int 
+InterpretKeys (graphic, layout, event)
+Graphic        graphic[];
+Layout         layout[];
+XEvent        *event;
+{
+
+  int    status;
+  KeySym keysym;
+  char            string[10];
+  XComposeStatus  composestatus;
+
+  XLookupString ((XKeyEvent *)event, string, 9, &keysym, &composestatus);
+
+  switch (keysym) {
+
+  case XK_Tab:
+    MOVE_POINTER = MOVE_POINTER ^ TRUE;
+    if (MOVE_POINTER) UpdatePointer (graphic, layout, (XMotionEvent *)event);
+    status = TRUE;
+    break;
+
+  default:
+    status = TRUE;
+  }
+
+  return (status);
+
+}
+
+
+
+
+/************* the stuff below this line is old - remove eventually */
+/*
+  case XK_Right:
+  case XK_Left:
+  this is all old, but a good example for putting in the cursor motion.
+
+    break;
+*/
+
Index: /tags/start/Ohana/src/kii/event/InterpretPresses.c
===================================================================
--- /tags/start/Ohana/src/kii/event/InterpretPresses.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/event/InterpretPresses.c	(revision 12606)
@@ -0,0 +1,51 @@
+# include "Ximage.h"
+
+int InterpretPresses (Graphic *graphic, Layout *layout, XButtonEvent *event) {
+
+  int             status, done, this_button;
+  Button         *button;
+
+  status = TRUE;
+  this_button = event[0].button;
+  
+  if ((event[0].type == ButtonPress) && InPicture (event, &layout[0].picture)) {
+    Reorient (graphic, layout, event);
+  }
+
+  if ((event[0].type == ButtonPress) && InPicture (event, &layout[0].cmapbar)) {
+    DragColorbar (graphic, layout, event);
+  }
+
+  /* if on an exisiting button, Invert, wait for release, then go (or not) */
+  if ((button = CheckButtons (event, layout)) != (Button *) NULL) {
+    InvertButton (graphic, button); 
+    done = FALSE;
+    while (!done) { /* wait for release of this button */
+      XNextEvent (graphic[0].display, (XEvent *) event);
+      if ((event[0].type == ButtonRelease) && (event[0].button == this_button)) {
+	done = TRUE;
+      }
+    }
+    DrawButton (graphic, button);
+    if (InButton (event, button)) {
+      switch (event[0].button) {
+      case 1:
+	status = button[0].function_1(graphic, layout);
+	break;
+      case 2:
+	status = button[0].function_2(graphic, layout);
+	break;
+      case 3:
+	status = button[0].function_3(graphic, layout);
+	break;
+      }
+    }
+    else {
+      return (status);
+    }
+  }
+
+  return (status);
+
+}
+
Index: /tags/start/Ohana/src/kii/event/NextEvent.c
===================================================================
--- /tags/start/Ohana/src/kii/event/NextEvent.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/event/NextEvent.c	(revision 12606)
@@ -0,0 +1,20 @@
+# include "Ximage.h"
+
+/************** NextEvent *************/
+void
+NextEvent (graphic, event, keysym)
+Graphic graphic[];
+XEvent *event;
+KeySym *keysym;
+{
+  int status;
+
+  status = FALSE;
+
+  while (!status) {
+    XNextEvent (graphic[0].display, event);
+    status = ParseEvent (graphic, event, keysym);
+  }
+}
+
+
Index: /tags/start/Ohana/src/kii/event/ParseEvent.c
===================================================================
--- /tags/start/Ohana/src/kii/event/ParseEvent.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/event/ParseEvent.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include "Ximage.h"
+
+/************** ParseEvent *************/
+int
+ParseEvent (graphic, event, keysym)
+Graphic graphic[];
+XEvent *event;
+KeySym *keysym;
+{
+
+  XComposeStatus composestatus;
+  char string[10];
+  int status;
+ 
+  status = FALSE;
+  switch (event[0].type) {
+  case ButtonPress:
+    status = TRUE;
+    break;
+  case ButtonRelease:
+    status = TRUE;
+    break;
+  case ClientMessage:
+    status = TRUE;
+    break;
+  case MotionNotify:
+    status = TRUE;
+    break;
+  case PropertyNotify:
+    status = TRUE;
+    break;
+  case SelectionClear:
+    status = TRUE;
+    break;
+  case SelectionNotify:
+    status = TRUE;
+    break;
+  case SelectionRequest:
+    status = TRUE;
+    break;
+  case ConfigureNotify:
+    if ((graphic[0].dx != event[0].xconfigure.width) || 
+	(graphic[0].dy != event[0].xconfigure.height))
+      status = TRUE;
+    break;
+  case Expose:
+    status = TRUE;
+    if (event[0].xexpose.count != 0)
+      status = FALSE;
+    break;
+  case KeyPress:
+    status = TRUE;
+    XLookupString ((XKeyEvent *)event, string, 9, keysym, &composestatus);
+    break;
+  case MappingNotify:
+    XRefreshKeyboardMapping ((XMappingEvent *)event);
+    break;
+  }
+
+  return (status);
+}
Index: /tags/start/Ohana/src/kii/event/Reconfig.c
===================================================================
--- /tags/start/Ohana/src/kii/event/Reconfig.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/event/Reconfig.c	(revision 12606)
@@ -0,0 +1,19 @@
+# include "Ximage.h"
+# define MAX_STRING 100
+
+int Reconfig (Graphic *graphic, Layout *layout, XEvent *event) {
+  
+  if ((graphic[0].dx == event[0].xconfigure.width) &&
+      (graphic[0].dy == event[0].xconfigure.height)) 
+    return (TRUE);
+
+  graphic[0].dx = MAX(event[0].xconfigure.width,  MIN_WIDTH); 
+  graphic[0].dy = MAX(event[0].xconfigure.height, MIN_HEIGHT);
+
+  PositionPictures (layout, graphic);
+  CreateColorbar (layout, graphic);
+  CreatePicture (layout, graphic);
+  Remap (graphic, layout, &layout[0].matrix); 
+  Refresh (graphic, layout, 1);
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/kii/event/Refresh.c
===================================================================
--- /tags/start/Ohana/src/kii/event/Refresh.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/event/Refresh.c	(revision 12606)
@@ -0,0 +1,55 @@
+# include "Ximage.h"
+# define NPOINTS 10
+
+void Refresh (Graphic *graphic, Layout *layout, int mode) {
+
+  int i;
+
+  XSetForeground (graphic[0].display, graphic[0].gc, layout[0].black);
+  XDrawRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		  layout[0].picture.x, layout[0].picture.y, 
+		  layout[0].picture.dx + 1, layout[0].picture.dy + 1);
+  
+  XPutImage (graphic[0].display, graphic[0].window, graphic[0].gc,
+	     layout[0].picture.pix, 0, 0, 
+	     layout[0].picture.x + 1, layout[0].picture.y + 1, 
+	     layout[0].picture.dx, layout[0].picture.dy);
+
+  XPutImage (graphic[0].display, graphic[0].window, graphic[0].gc,
+	     layout[0].cmapbar.pix, 0, 0, 
+	     layout[0].cmapbar.x, layout[0].cmapbar.y, 
+	     layout[0].cmapbar.dx, layout[0].cmapbar.dy);
+
+  CrossHairs (graphic, layout);
+
+  for (i = 0; i < NOVERLAYS; i++) {
+    if (OVERLAY[i])
+      PaintOverlay (graphic, layout, i);
+  }
+  PaintTickmarks (graphic, layout);
+
+  if (mode == 1) {
+    /* erase everything below zoom box, then draw */
+    XSetForeground (graphic[0].display, graphic[0].gc, layout[0].white);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		    layout[0].text_x, layout[0].text_x, layout[0].zoom.dx, graphic[0].dy); 
+    
+    DrawButton (graphic, &layout[0].PS_button);
+    DrawButton (graphic, &layout[0].recenter_button);
+    DrawButton (graphic, &layout[0].grey_button);
+    DrawButton (graphic, &layout[0].rainbow_button);
+    DrawButton (graphic, &layout[0].puns_button);
+    DrawButton (graphic, &layout[0].hms_button);
+
+    for (i = 0; i < NOVERLAYS; i++) {
+      DrawButton (graphic, &layout[0].overlay_button[i]);
+    }
+  }
+
+  StatusBox (graphic, layout);
+
+  FlushDisplay (graphic[0].display);
+}
+
+/* this routine is independent of the number of overlays */
+
Index: /tags/start/Ohana/src/kii/event/Stop.c
===================================================================
--- /tags/start/Ohana/src/kii/event/Stop.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/event/Stop.c	(revision 12606)
@@ -0,0 +1,19 @@
+# include "Ximage.h"
+# define XBorder 10
+# define YBorder 2
+
+int
+Stop (graphic, layout)
+Graphic   graphic[];
+Layout    layout[];
+{
+  return (FALSE);
+}
+
+
+
+
+
+
+/******  this function looks stupid, but it has to be like this:
+  it is called as a pointer to function **/
Index: /tags/start/Ohana/src/kii/include/Ximage.h
===================================================================
--- /tags/start/Ohana/src/kii/include/Ximage.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/Ximage.h	(revision 12606)
@@ -0,0 +1,5 @@
+# include <Xohana.h>
+# include <loneos.h>
+# include "constants.h"
+# include "structures.h"
+# include "prototypes.h"
Index: /tags/start/Ohana/src/kii/include/buttons.h
===================================================================
--- /tags/start/Ohana/src/kii/include/buttons.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/buttons.h	(revision 12606)
@@ -0,0 +1,120 @@
+#define PS_width 25
+#define PS_height 25
+static char PS_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x81, 0x3f, 0x00,
+   0x82, 0x67, 0x60, 0x00, 0x02, 0x26, 0x40, 0x00, 0x02, 0x24, 0x40, 0x00,
+   0x02, 0x24, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00,
+   0x02, 0x24, 0x00, 0x00, 0x02, 0x64, 0x00, 0x00, 0x02, 0xc6, 0x00, 0x00,
+   0x82, 0x07, 0x07, 0x00, 0xfe, 0x01, 0x0c, 0x00, 0x02, 0x00, 0x18, 0x00,
+   0x02, 0x00, 0x20, 0x00, 0x02, 0x00, 0x60, 0x00, 0x02, 0x00, 0x40, 0x00,
+   0x02, 0x00, 0xc0, 0x00, 0x02, 0x10, 0x80, 0x00, 0x02, 0x10, 0xc0, 0x00,
+   0x02, 0x60, 0x60, 0x00, 0x02, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00}; 
+#define grey_width 25
+#define grey_height 25
+static char grey_bits[] = {
+   0x90, 0x40, 0xf7, 0x01, 0x04, 0xaa, 0xad, 0x01, 0x68, 0xd5, 0xfe, 0x01,
+   0x82, 0x28, 0xdb, 0x01, 0x10, 0xd2, 0x75, 0x01, 0x40, 0xad, 0xee, 0x01,
+   0xac, 0x50, 0xbf, 0x01, 0x00, 0xaa, 0xf9, 0x01, 0x52, 0xd5, 0xd6, 0x01,
+   0x80, 0x28, 0x6f, 0x01, 0x28, 0xd2, 0xfd, 0x01, 0x44, 0xad, 0xba, 0x01,
+   0x90, 0x50, 0xf7, 0x01, 0x02, 0xaa, 0xcd, 0x01, 0x68, 0xd5, 0x7e, 0x01,
+   0x80, 0x28, 0xfb, 0x01, 0x14, 0xd2, 0xb5, 0x01, 0x40, 0xad, 0xee, 0x01,
+   0xaa, 0x50, 0xdf, 0x01, 0x00, 0xaa, 0x79, 0x01, 0x50, 0xd5, 0xf6, 0x01,
+   0x84, 0x28, 0xaf, 0x01, 0x28, 0xd2, 0xfd, 0x01, 0x40, 0xad, 0xda, 0x01,
+   0x90, 0x50, 0x77, 0x01};
+#define rainbow_width 25
+#define rainbow_height 25
+static char rainbow_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x80, 0xff, 0x00, 0x00, 0x70, 0x00, 0x01, 0x00, 0x0c, 0x7f, 0x00,
+   0x00, 0xe3, 0x80, 0x01, 0xc0, 0x9c, 0xff, 0x00, 0x20, 0x62, 0x00, 0x01,
+   0x90, 0x99, 0xff, 0x00, 0x48, 0x76, 0x00, 0x01, 0x24, 0x09, 0x00, 0x00,
+   0x94, 0x06, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00,
+   0xa5, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+   0x2a, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+   0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
+   0x15, 0x00, 0x00, 0x00};
+#define recenter_width 25
+#define recenter_height 25
+static char recenter_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00,
+   0x80, 0xef, 0x03, 0x00, 0xe0, 0x00, 0x0e, 0x00, 0x30, 0x00, 0x18, 0x00,
+   0x10, 0x00, 0x10, 0x00, 0x18, 0x00, 0x30, 0x00, 0x08, 0x00, 0x20, 0x00,
+   0x0c, 0x00, 0x60, 0x00, 0x0c, 0x38, 0x60, 0x00, 0x0c, 0x7c, 0x60, 0x00,
+   0x04, 0x7c, 0x40, 0x00, 0x0c, 0x7c, 0x60, 0x00, 0x0c, 0x38, 0x60, 0x00,
+   0x0c, 0x00, 0x60, 0x00, 0x08, 0x00, 0x20, 0x00, 0x18, 0x00, 0x30, 0x00,
+   0x10, 0x00, 0x10, 0x00, 0x30, 0x00, 0x18, 0x00, 0xe0, 0x00, 0x0e, 0x00,
+   0x80, 0xef, 0x03, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define puns_width 25
+#define puns_height 25
+static char puns_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0xd8, 0x01,
+   0x00, 0x0c, 0x37, 0x00, 0xf8, 0xc9, 0x6f, 0x00, 0x0c, 0xde, 0xf0, 0x00,
+   0x06, 0x5b, 0x1f, 0x00, 0x7b, 0xd9, 0x0c, 0x00, 0xc9, 0x70, 0x06, 0x00,
+   0x81, 0x71, 0x03, 0x00, 0x78, 0xb9, 0x39, 0x00, 0xc8, 0xdb, 0x0f, 0x00,
+   0x84, 0xf7, 0x7f, 0x00, 0x04, 0xff, 0xc3, 0x00, 0xe6, 0xfe, 0x8e, 0x00,
+   0x9a, 0x7d, 0x0b, 0x00, 0x08, 0xbc, 0x01, 0x00, 0x08, 0xfc, 0x3f, 0x00,
+   0x0c, 0xff, 0x78, 0x00, 0x84, 0x39, 0x60, 0x00, 0x40, 0x38, 0x40, 0x00,
+   0x60, 0x38, 0x40, 0x00, 0x20, 0x38, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00,
+   0x00, 0xd6, 0x00, 0x00};
+#define red_width 25
+#define red_height 25
+static char red_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xfc, 0x03, 0x00,
+   0x20, 0x07, 0x06, 0x00, 0xe0, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x08, 0x00,
+   0x20, 0x00, 0x08, 0x00, 0x20, 0x00, 0x08, 0x00, 0x20, 0x00, 0x08, 0x00,
+   0x20, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x06, 0x00, 0x20, 0x80, 0x01, 0x00,
+   0x20, 0xe0, 0x00, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xe0, 0xc3, 0x00, 0x00,
+   0x20, 0xc0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x20, 0x80, 0x01, 0x00,
+   0x20, 0x00, 0x01, 0x00, 0x20, 0x00, 0x01, 0x00, 0x20, 0x00, 0x03, 0x00,
+   0x20, 0x00, 0x06, 0x00, 0x20, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x18, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define green_width 25
+#define green_height 25
+static char green_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00,
+   0x00, 0x06, 0x04, 0x00, 0x80, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0x40, 0x80, 0x0f, 0x00, 0x40, 0xc0, 0x30, 0x00,
+   0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x08, 0x00,
+   0x00, 0x03, 0x08, 0x00, 0x00, 0x7e, 0x0e, 0x00, 0x00, 0xc0, 0x03, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define blue_width 25
+#define blue_height 25
+static char blue_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xfe, 0x00, 0x00,
+   0xc0, 0x83, 0x07, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x08, 0x00,
+   0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00,
+   0x40, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x04, 0x00, 0x40, 0x00, 0x02, 0x00,
+   0x40, 0x80, 0x07, 0x00, 0x40, 0xe0, 0x0c, 0x00, 0xc0, 0x3f, 0x08, 0x00,
+   0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00,
+   0x40, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x06, 0x00, 0x40, 0x00, 0x02, 0x00,
+   0xc0, 0x80, 0x03, 0x00, 0x40, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define yellow_width 25
+#define yellow_height 25
+static char yellow_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00,
+   0x80, 0x01, 0x0c, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x02, 0x02, 0x00,
+   0x00, 0x84, 0x01, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00,
+   0x00, 0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+   0x00, 0x30, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define hms_width 25
+#define hms_height 25
+static char hms_bits[] = {
+   0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+   0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0xf0, 0x00, 0x1e, 0xef, 0x89, 0x00,
+   0x22, 0x11, 0x09, 0x00, 0x22, 0x11, 0x71, 0x00, 0x22, 0x11, 0x81, 0x00,
+   0x22, 0x11, 0x89, 0x00, 0x22, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x1e, 0xc7, 0xf1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x80, 0x00,
+   0x40, 0x80, 0x80, 0x00, 0x40, 0x80, 0x80, 0x00, 0x40, 0x80, 0x80, 0x00,
+   0x40, 0x80, 0x80, 0x00, 0x5c, 0xb8, 0xb8, 0x00, 0x62, 0xc4, 0xc4, 0x00,
+   0x42, 0x84, 0x84, 0x00, 0x42, 0x84, 0x84, 0x00, 0x62, 0xc4, 0xc4, 0x00,
+   0x5c, 0xb9, 0xb8, 0x00};
Index: /tags/start/Ohana/src/kii/include/constants.h
===================================================================
--- /tags/start/Ohana/src/kii/include/constants.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/constants.h	(revision 12606)
@@ -0,0 +1,27 @@
+# define PAD1  5
+# define PAD2  3
+# define TEXTPAD 25
+# define COLORPAD 10
+# define TEXT_Y 15
+# define ZOOM_X 170
+# define ZOOM_Y 170
+# define NOVERLAYS 4
+/* number of overlays is defined here.
+   the number is also crucial in the following files:
+   PositionPictures.c
+   MakeColormap.c
+   prototypes.h
+*/
+
+# define EVENT_MASK (long) (ButtonPressMask | ClientMessage | ButtonReleaseMask | KeyPressMask | ExposureMask | StructureNotifyMask | PointerMotionMask)
+# define DEFAULT_CURSOR XC_crosshair
+# define BORDER_WIDTH 2
+# define MIN_WIDTH 10
+# define MIN_HEIGHT 20
+# define AssignText(X,T) allocate (X, char, strlen (T)); strcpy (X, T);
+# define AssignData(X,T,N) allocate (X, char, N); bcopy (T, X, N);
+
+int OVERLAY[NOVERLAYS];
+int MOVE_POINTER;
+int DECIMAL_DEG;
+int DEBUG;
Index: /tags/start/Ohana/src/kii/include/icons/R0.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/R0.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/R0.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define R0_width 9
+#define R0_height 6
+static char R0_bits[] = {
+   0x00, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x01, 0x01, 0x82, 0x00, 0x7c, 0x00};
Index: /tags/start/Ohana/src/kii/include/icons/R1.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/R1.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/R1.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define R1_width 9
+#define R1_height 6
+static char R1_bits[] = {
+   0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xff, 0x01, 0x02, 0x01, 0x04, 0x01};
Index: /tags/start/Ohana/src/kii/include/icons/R2.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/R2.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/R2.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define R2_width 9
+#define R2_height 6
+static char R2_bits[] = {
+   0x00, 0x00, 0x0e, 0x01, 0x11, 0x01, 0x21, 0x01, 0x41, 0x01, 0x86, 0x01};
Index: /tags/start/Ohana/src/kii/include/icons/R3.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/R3.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/R3.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define R3_width 9
+#define R3_height 6
+static char R3_bits[] = {
+   0x00, 0x00, 0xe3, 0x00, 0x15, 0x01, 0x19, 0x01, 0x11, 0x01, 0x81, 0x00};
Index: /tags/start/Ohana/src/kii/include/icons/R4.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/R4.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/R4.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define R4_width 9
+#define R4_height 6
+static char R4_bits[] = {
+   0x00, 0x00, 0x40, 0x00, 0xff, 0x01, 0x44, 0x00, 0x58, 0x00, 0x60, 0x00};
Index: /tags/start/Ohana/src/kii/include/icons/R5.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/R5.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/R5.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define R5_width 9
+#define R5_height 6
+static char R5_bits[] = {
+   0x00, 0x00, 0xf1, 0x00, 0x09, 0x01, 0x09, 0x01, 0x11, 0x01, 0x9f, 0x00};
Index: /tags/start/Ohana/src/kii/include/icons/R6.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/R6.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/R6.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define R6_width 9
+#define R6_height 6
+static char R6_bits[] = {
+   0x00, 0x00, 0xe2, 0x00, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0xfe, 0x00};
Index: /tags/start/Ohana/src/kii/include/icons/R7.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/R7.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/R7.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define R7_width 9
+#define R7_height 6
+static char R7_bits[] = {
+   0x00, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x31, 0x00, 0xc1, 0x01, 0x01, 0x00};
Index: /tags/start/Ohana/src/kii/include/icons/R8.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/R8.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/R8.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define R8_width 9
+#define R8_height 6
+static char R8_bits[] = {
+   0x00, 0x00, 0xee, 0x00, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0xee, 0x00};
Index: /tags/start/Ohana/src/kii/include/icons/R9.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/R9.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/R9.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define R9_width 9
+#define R9_height 6
+static char R9_bits[] = {
+   0x00, 0x00, 0xfe, 0x00, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x8e, 0x00};
Index: /tags/start/Ohana/src/kii/include/icons/Rd.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/Rd.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/Rd.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define Rd_width 9
+#define Rd_height 6
+static char Rd_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x01, 0x80, 0x00, 0x00, 0x00};
Index: /tags/start/Ohana/src/kii/include/icons/Re.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/Re.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/Re.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define Re_width 9
+#define Re_height 6
+static char Re_bits[] = {
+   0x00, 0x00, 0xb0, 0x00, 0x28, 0x01, 0x28, 0x01, 0x28, 0x01, 0xf0, 0x00};
Index: /tags/start/Ohana/src/kii/include/icons/Rm.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/Rm.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/Rm.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define Rm_width 9
+#define Rm_height 6
+static char Rm_bits[] = {
+   0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00};
Index: /tags/start/Ohana/src/kii/include/icons/Rp.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/Rp.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/Rp.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define Rp_width 9
+#define Rp_height 6
+static char Rp_bits[] = {
+   0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x7c, 0x00, 0x10, 0x00, 0x10, 0x00};
Index: /tags/start/Ohana/src/kii/include/icons/arrow.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/arrow.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/arrow.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define arrow_width 6
+#define arrow_height 9
+static char arrow_bits[] = {
+   0x00, 0x02, 0x06, 0x0e, 0x1e, 0x0e, 0x06, 0x02, 0x00};
Index: /tags/start/Ohana/src/kii/include/icons/back.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/back.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/back.h	(revision 12606)
@@ -0,0 +1,6 @@
+#define back_width 16
+#define back_height 16
+static char back_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x3c, 0x00, 0x3f, 0xc0, 0x3f,
+   0xf0, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xf0, 0x3f, 0xc0, 0x3f, 0x00, 0x3f,
+   0x00, 0x3c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00};
Index: /tags/start/Ohana/src/kii/include/icons/down.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/down.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/down.h	(revision 12606)
@@ -0,0 +1,4 @@
+#define down_width 9
+#define down_height 6
+static char down_bits[] = {
+   0x00, 0x00, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00};
Index: /tags/start/Ohana/src/kii/include/icons/fore.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/fore.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/fore.h	(revision 12606)
@@ -0,0 +1,6 @@
+#define fore_width 16
+#define fore_height 16
+static char fore_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x3c, 0x00, 0xfc, 0x00, 0xfc, 0x03,
+   0xfc, 0x0f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x0f, 0xfc, 0x03, 0xfc, 0x00,
+   0x3c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00};
Index: /tags/start/Ohana/src/kii/include/icons/icon.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/icon.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/icon.h	(revision 12606)
@@ -0,0 +1,13 @@
+#define icon_width 30
+#define icon_height 30
+static char icon_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00,
+   0x00, 0xfe, 0x0f, 0x00, 0x00, 0xff, 0x1f, 0x00, 0xc0, 0x0f, 0x7e, 0x00,
+   0xe0, 0x01, 0xf0, 0x00, 0xe0, 0xff, 0xff, 0x00, 0xf0, 0xff, 0xff, 0x01,
+   0xb8, 0xff, 0xbf, 0x03, 0xb8, 0x03, 0xb8, 0x03, 0xb8, 0xe3, 0xb8, 0x03,
+   0x9c, 0xf3, 0x39, 0x07, 0x9c, 0xfb, 0x3b, 0x07, 0x9c, 0xfb, 0x3b, 0x07,
+   0x9c, 0xfb, 0x3b, 0x07, 0x9c, 0xf3, 0x39, 0x07, 0xb8, 0xe3, 0xb8, 0x03,
+   0xb8, 0x03, 0xb8, 0x03, 0xb8, 0xff, 0xbf, 0x03, 0xf0, 0xff, 0xff, 0x01,
+   0xe0, 0xff, 0xff, 0x00, 0xe0, 0x01, 0xf0, 0x00, 0xc0, 0x0f, 0x7e, 0x00,
+   0x00, 0xff, 0x1f, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0xf0, 0x01, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Index: /tags/start/Ohana/src/kii/include/icons/stop.h
===================================================================
--- /tags/start/Ohana/src/kii/include/icons/stop.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/icons/stop.h	(revision 12606)
@@ -0,0 +1,6 @@
+#define stop_width 16
+#define stop_height 16
+static char stop_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f,
+   0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f,
+   0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Index: /tags/start/Ohana/src/kii/include/prototypes.h
===================================================================
--- /tags/start/Ohana/src/kii/include/prototypes.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/prototypes.h	(revision 12606)
@@ -0,0 +1,103 @@
+int SetColormap (Graphic *graphic, Layout *layout, char *name);
+void FlushDisplay (Display *display);
+int Recenter (Graphic *graphic, Layout *layout);
+void DrawOverlay (Graphic *graphic, Layout *layout, int N, FILE *f, int extra);
+int cursor (Graphic *graphic, Layout *layout);
+int PSit (Graphic *graphic, Layout *layout, int Raw);
+int JPEGit (Graphic *graphic, Layout *layout);
+int Resize (Graphic *graphic, Layout *layout);
+int Center (Graphic *graphic, Layout *layout);
+int LoadTickmarks (Graphic *graphic, Layout *layout);
+void PaintTickmarks (Graphic *graphic, Layout *layout);
+void Screen_to_Image (double *x1, double *y1, double x2, double y2, Layout *layout);
+void Image_to_Screen (double *x1, double *y1, double x2, double y2, Layout *layout);
+void UpdateStatusBox (Graphic *graphic, Layout *layout, double x, double y, double z, int mode);
+void Remap8 (Graphic *graphic, Layout *layout, Matrix *matrix);
+void Remap16 (Graphic *graphic, Layout *layout, Matrix *matrix);
+void Remap24 (Graphic *graphic, Layout *layout, Matrix *matrix);
+void Remap32 (Graphic *graphic, Layout *layout, Matrix *matrix);
+void CheckVisual (Graphic *graphic, int *argc, char **argv);
+void CreateZoom8 (Layout *layout, Graphic *graphic, double x, double y);
+void CreateZoom16 (Layout *layout, Graphic *graphic, double x, double y);
+void CreateZoom24 (Layout *layout, Graphic *graphic, double x, double y);
+void CreateZoom32 (Layout *layout, Graphic *graphic, double x, double y);
+
+/***** Prototypes for image ***************/
+
+void          PositionPictures    PROTO((Layout *, Graphic *));
+void          CreateColorbar      PROTO((Layout *, Graphic *));
+void          CreatePicture       PROTO((Layout *, Graphic *));
+void          CreateZoom          PROTO((Layout *, Graphic *, double, double));
+void          Remap               PROTO((Graphic *, Layout *, Matrix  *));
+int           NewPicture          PROTO((Graphic *, Layout *));
+void          Reorient            PROTO((Graphic *, Layout *, XButtonEvent *));
+int           UpdatePointer       PROTO((Graphic *, Layout *, XMotionEvent *));
+void          CrossHairs          PROTO((Graphic *, Layout *));
+int           LoadOverlay         PROTO((Graphic *, Layout *));
+int           SaveOverlay         PROTO((Graphic *, Layout *));
+int           CSaveOverlay         PROTO((Graphic *, Layout *));
+int           EraseOverlay        PROTO((Graphic *, Layout *));
+void          StatusBox           PROTO((Graphic *, Layout *));
+void          PaintOverlay        PROTO((Graphic *, Layout *, int));
+
+/***** Prototypes for action ***************/
+
+int           CheckPipe           PROTO((Graphic *, Layout *));
+void          DefineLayout        PROTO((Layout *, Graphic *, int, char **));
+int           EventLoop           PROTO((Graphic *, Layout *));
+int           InPicture           PROTO((XButtonEvent *, Picture *));
+int           InterpretKeys       PROTO((Graphic *, Layout *, XEvent *));
+int           InterpretPresses    PROTO((Graphic *, Layout *, XButtonEvent *));
+int           Reconfig            PROTO((Graphic *, Layout *, XEvent *));
+void          Refresh             PROTO((Graphic *, Layout *, int));
+int           Stop                PROTO((Graphic *, Layout *));
+int           PSit                PROTO((Graphic *, Layout *, int));
+int           get_argument        PROTO((int, char **, char *));
+int           remove_argument     PROTO((int, int *, char **));
+void          DragColorbar        PROTO((Graphic *, Layout *, XButtonEvent *));
+void          ResetColorbar       PROTO((Graphic *, Layout *, double, double));
+void          MakeColormap        PROTO((Graphic *, Layout *, int, char **));
+
+/***** Prototypes for button ***************/
+
+Button       *CheckButtons        PROTO((XButtonEvent *, Layout *));
+void          DrawButton          PROTO((Graphic *, Button *));
+void          FlashButton         PROTO((Graphic *, Button *));
+int           InButton            PROTO((XButtonEvent *, Button *));
+void          InvertButton        PROTO((Graphic *, Button *));
+int           greycolors          PROTO((Graphic *, Layout *));
+int           rainbow             PROTO((Graphic *, Layout *));
+int           puns                PROTO((Graphic *, Layout *));
+int           Recenter            PROTO((Graphic *, Layout *));
+int           RecenterRescale     PROTO((Graphic *, Layout *));
+int           Rescale             PROTO((Graphic *, Layout *));
+int           ToggleDEG           PROTO((Graphic *, Layout *));
+int           Overlay0            PROTO((Graphic *, Layout *));
+int           Overlay1            PROTO((Graphic *, Layout *));
+int           Overlay2            PROTO((Graphic *, Layout *));
+int           Overlay3            PROTO((Graphic *, Layout *));
+
+/***** Prototypes for xtools ***************/
+
+void          CheckColors         PROTO((Graphic *, int *, char **));
+void          CheckDisplayName    PROTO((int *, char **, char *));
+void          CheckFontName       PROTO((int *, char **, char *));
+void          CheckGeometry       PROTO((int *, char **, Graphic *));
+void          CloseDisplay        PROTO((Graphic *));
+void          CreateWindow        PROTO((Graphic *, Window, int, long));
+void          DrawBitmap          PROTO((Graphic *, int, int, int, int, char *, int));
+unsigned long GetColor            PROTO((Display *, char *, Colormap, unsigned long));
+void          LoadFont            PROTO((Graphic *, int *, char **, char *));
+void          MakeCursor          PROTO((Graphic *, unsigned int));
+void          MakeGC              PROTO((Graphic *));
+void          MapWindow           PROTO((Graphic *));
+void          NameWindow          PROTO((Graphic *, char *));
+Display      *OpenDisplay         PROTO((char *, int *));
+void          QuitX               PROTO((Display *, char *, char *));
+void          SetNormalHints      PROTO((Graphic *));
+void          SetUpDisplay        PROTO((Graphic *, int *, char **));
+void          SetUpWindow         PROTO((Graphic *, int *, char **));
+void          SetWMHints          PROTO((Graphic *, Icon *));
+void          TopWindow           PROTO((Graphic *, Icon *));
+
+void          hh_hms              PROTO((char *, double, double, char));
Index: /tags/start/Ohana/src/kii/include/rotletters.h
===================================================================
--- /tags/start/Ohana/src/kii/include/rotletters.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/rotletters.h	(revision 12606)
@@ -0,0 +1,56 @@
+#define R0_width 9
+#define R0_height 6
+static char R0_bits[] = {
+   0x00, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x01, 0x01, 0x82, 0x00, 0x7c, 0x00};
+#define R1_width 9
+#define R1_height 6
+static char R1_bits[] = {
+   0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xff, 0x01, 0x02, 0x01, 0x04, 0x01};
+#define R2_width 9
+#define R2_height 6
+static char R2_bits[] = {
+   0x00, 0x00, 0x0e, 0x01, 0x11, 0x01, 0x21, 0x01, 0x41, 0x01, 0x86, 0x01};
+#define R3_width 9
+#define R3_height 6
+static char R3_bits[] = {
+   0x00, 0x00, 0xe3, 0x00, 0x15, 0x01, 0x19, 0x01, 0x11, 0x01, 0x81, 0x00};
+#define R4_width 9
+#define R4_height 6
+static char R4_bits[] = {
+   0x00, 0x00, 0x40, 0x00, 0xff, 0x01, 0x44, 0x00, 0x58, 0x00, 0x60, 0x00};
+#define R5_width 9
+#define R5_height 6
+static char R5_bits[] = {
+   0x00, 0x00, 0xf1, 0x00, 0x09, 0x01, 0x09, 0x01, 0x11, 0x01, 0x9f, 0x00};
+#define R6_width 9
+#define R6_height 6
+static char R6_bits[] = {
+   0x00, 0x00, 0xe2, 0x00, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0xfe, 0x00};
+#define R7_width 9
+#define R7_height 6
+static char R7_bits[] = {
+   0x00, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x31, 0x00, 0xc1, 0x01, 0x01, 0x00};
+#define R8_width 9
+#define R8_height 6
+static char R8_bits[] = {
+   0x00, 0x00, 0xee, 0x00, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0xee, 0x00};
+#define R9_width 9
+#define R9_height 6
+static char R9_bits[] = {
+   0x00, 0x00, 0xfe, 0x00, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x8e, 0x00};
+#define Rd_width 9
+#define Rd_height 6
+static char Rd_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x01, 0x80, 0x00, 0x00, 0x00};
+#define Re_width 9
+#define Re_height 6
+static char Re_bits[] = {
+   0x00, 0x00, 0xb0, 0x00, 0x28, 0x01, 0x28, 0x01, 0x28, 0x01, 0xf0, 0x00};
+#define Rm_width 9
+#define Rm_height 6
+static char Rm_bits[] = {
+   0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00};
+#define Rp_width 9
+#define Rp_height 6
+static char Rp_bits[] = {
+   0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x7c, 0x00, 0x10, 0x00, 0x10, 0x00};
Index: /tags/start/Ohana/src/kii/include/structures.h
===================================================================
--- /tags/start/Ohana/src/kii/include/structures.h	(revision 12606)
+++ /tags/start/Ohana/src/kii/include/structures.h	(revision 12606)
@@ -0,0 +1,129 @@
+/**************** Graphic carries X info around ****************/
+typedef struct {
+  Display       *display;
+  int            screen;
+  int            depth;
+  Window         window;
+  Visual        *visual;
+  int            visualclass;
+  GC             gc;
+  XFontStruct   *font;
+  Cursor         cursor;
+  int            x,  y;
+  int            dx, dy;
+  Colormap       colormap;
+  unsigned long  Npixels, pixels[256];
+  int            Nbits;
+  /*
+  unsigned long  fore;
+  unsigned long  back;
+  */
+  unsigned long  black, white;
+} Graphic;
+
+/**************** X related "widget" structures ****************/
+typedef struct {
+  int      x, y, dx, dy;      /* position and size */
+  int      text;              /* does this have a picture or text? */
+  int      width, height;
+  char    *bitmap;          /* picture on button */
+  int    (*function_1) ();  /* mouse_button 1 function */
+  int    (*function_2) ();  /* mouse_button 2 function */
+  int    (*function_3) ();  /* mouse_button 3 function */
+} Button;
+
+typedef struct {
+  int      x, y, dx, dy;   /* position and size */
+  char    *label;          /* label on TextLine */
+  char     text[1024];     /* words of TextLine */
+  char     old_text[1024]; /* words of TextLine */
+  int      outline;        /* draw an outline?  */ 
+  int      cursor;         /* location of cursor (if selected) */
+  int    (*function) ();   /* textline function */
+} TextLine;
+
+typedef char STRING[1024];
+
+typedef struct {
+  int      x, y, dx, dy;   /* position and size */
+  STRING  *text;           /* words of TextLine */
+  int      Nlines;
+  int      outline;        /* draw an outline?  */ 
+  int      cursor_line;    /* cursor line */
+  int      cursor_x;       /* location of cursor (if selected) */
+  int      cursor_y;       /* location of cursor (if selected) */
+  int    (*function) ();   /* textline function */
+} TextBox;
+
+/**************** general structures ****************/
+typedef struct {
+  Pixmap pixmap;
+  int    width;
+  int    height;
+  char  *bits;
+} Icon;
+
+typedef struct {
+  int      dx, dy, x, y;
+  XImage  *pix;
+  char    *data;
+} Picture;
+
+typedef struct {
+  char type[10];
+  double x, y;
+  double dx, dy;
+  double angle;
+  char  *text;
+} Object;
+
+typedef struct {
+  int Nobjects;
+  unsigned long color;
+  Object *objects;
+} Overlay;
+  
+/******** Here we define the Layout struct specific to this program  *******/
+typedef struct {
+  /* objects on the mana window */
+  Picture  picture;
+  Picture  cmapbar;
+  Picture  zoom;
+  Button   PS_button;
+  Button   recenter_button;
+  Button   hms_button; /* toggle HMS/DECIMAL mode (DECIMAL_DEG macro) */
+  Button   grey_button;
+  Button   rainbow_button;
+  Button   puns_button;
+  Button   overlay_button[NOVERLAYS];
+  Overlay  overlay[NOVERLAYS];
+  Overlay  tickmarks;
+  int      text_x, text_y;
+
+  /* file descriptor for socket connection to mana */
+  int Ximage; 
+
+  /* data mana needs */
+  Matrix   matrix;         /* data for picture */
+  double   X, Y;           /* image pixel at screen center */
+  int      expand;         /* zoomscale */
+  double   zero, range;    /* zero, range for picture to cmap */
+  double   max, min;       /* zero, range for data to z-value */
+  double   start, slope;   /* zero, range for cmap to pixels */
+  double   x, y, z;        /* last pointer coords */
+  Coords   coords;
+  char     file[1024];     /* name of file */
+  char     buffer_name[1024];  /* name of buffer */
+
+  /* fundamental pieces */
+  unsigned long  black;
+  unsigned long  white;
+  XColor   cmap[256];
+  int      Npixels;
+
+} Layout;
+
+
+/* this routine is independent of the number of overlays */
+
+
Index: /tags/start/Ohana/src/kii/misc/hh_hms.c
===================================================================
--- /tags/start/Ohana/src/kii/misc/hh_hms.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/misc/hh_hms.c	(revision 12606)
@@ -0,0 +1,28 @@
+# include "Ximage.h"
+
+void hh_hms (char *line, double ra, double dec, char sep) {
+
+  int h, m, flag;
+  double s;
+  
+  ra /= 15.0;  /* convert from degrees to hours */
+  flag = SIGN(ra);
+  ra *= flag;
+  h = ra;
+  m = 60.000001*(ra - h);
+  s = 3600*(ra - h - m / 60.0);
+  if (flag > 0)
+    sprintf (line, " %02d%c%02d%c%04.1f  ", h, sep, m, sep, s);
+  else
+    sprintf (line, "-%02d%c%02d%c%04.1f  ", h, sep, m, sep, s);
+  
+  flag = SIGN(dec);
+  dec *= flag;
+  h = dec;
+  m = 60.000001*(dec - h);
+  s = 3600*(dec - h - m / 60.0);
+  if (flag > 0)
+    sprintf (&line[13], " %02d%c%02d%c%04.1f", h, sep, m, sep, s);
+  else
+    sprintf (&line[13], "-%02d%c%02d%c%04.1f", h, sep, m, sep, s);
+}
Index: /tags/start/Ohana/src/kii/notes
===================================================================
--- /tags/start/Ohana/src/kii/notes	(revision 12606)
+++ /tags/start/Ohana/src/kii/notes	(revision 12606)
@@ -0,0 +1,4 @@
+1/31/94: totally revamped the overlay function -- made two overlays,
+red and green.  Added two buttons to toggle them on and off.  Made
+functions for mana to "load" and "save" files with overlay objects
+defined.  Made contour function for mana.  
Index: /tags/start/Ohana/src/kii/overlay/CSaveOverlay.c
===================================================================
--- /tags/start/Ohana/src/kii/overlay/CSaveOverlay.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/overlay/CSaveOverlay.c	(revision 12606)
@@ -0,0 +1,51 @@
+# include "Ximage.h"
+
+/*************/
+int CSaveOverlay (Graphic *graphic, Layout *layout) {
+
+  char buffer[256], filename[256];
+  int i, status, Nbytes, N;
+  double ra, dec, ra1, dec1, x1, y1, dra, ddec;
+  FILE *f;
+
+  status = read (layout[0].Ximage, buffer, 16); 
+  buffer[16] = 0; 
+  sscanf (buffer, "%*s %d", &Nbytes); 
+  status = read (layout[0].Ximage, buffer, Nbytes); 
+  buffer[Nbytes] = 0; 
+  sscanf (buffer, "%*s %d %s", &N, filename);
+  
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "could not open %s\n", filename);
+    return (TRUE);
+  }
+
+  for (i = 0; i < layout[0].overlay[N].Nobjects; i++) {
+    if (!strcmp (layout[0].overlay[N].objects[i].type, "LINE")) {
+      XY_to_RD (&ra, &dec, layout[0].overlay[N].objects[i].x, layout[0].overlay[N].objects[i].y, &layout[0].coords);
+      x1 = layout[0].overlay[N].objects[i].x + layout[0].overlay[N].objects[i].dx;
+      y1 = layout[0].overlay[N].objects[i].y + layout[0].overlay[N].objects[i].dy;
+      XY_to_RD (&ra1, &dec1, x1, y1, &layout[0].coords);
+      dra = (ra1 - ra);
+      ddec = (dec1 - dec);
+    } else {
+      XY_to_RD (&ra, &dec, layout[0].overlay[N].objects[i].x, layout[0].overlay[N].objects[i].y, &layout[0].coords);
+      x1 = layout[0].overlay[N].objects[i].x;
+      y1 = layout[0].overlay[N].objects[i].y + layout[0].overlay[N].objects[i].dy;
+      XY_to_RD (&ra1, &dec1, x1, y1, &layout[0].coords);
+      ddec = fabs (dec1 - dec);
+      x1 = layout[0].overlay[N].objects[i].x + layout[0].overlay[N].objects[i].dx;
+      y1 = layout[0].overlay[N].objects[i].y;
+      XY_to_RD (&ra1, &dec1, x1, y1, &layout[0].coords);
+      dra = cos (dec*RAD_DEG) * fabs (ra1 - ra);
+    }
+    fprintf (f, "%s %lf %lf %lf %lf\n", layout[0].overlay[N].objects[i].type, ra, dec, dra, ddec);
+   }
+  fclose (f);
+  return (TRUE);
+}
+
+
+/* this routine is independent of the number of overlays */
+
Index: /tags/start/Ohana/src/kii/overlay/DrawOverlay.c
===================================================================
--- /tags/start/Ohana/src/kii/overlay/DrawOverlay.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/overlay/DrawOverlay.c	(revision 12606)
@@ -0,0 +1,81 @@
+# include "Ximage.h"
+# define INFRONT 3
+
+void DrawOverlay (Graphic *graphic, Layout *layout, int N, FILE *f, int extra) {
+
+  int i;
+  double X, Y, dX, dY;
+  int Xmin, Ymin, Xmax, Ymax;
+  double expand, X0, Y0;
+ 
+  if (layout[0].expand > 0) {
+    expand = 1 / (1.0*layout[0].expand);
+  }
+  if (layout[0].expand < 0) {
+    expand = fabs((double)layout[0].expand);
+  }
+  /*  
+  X0 =  (layout[0].X + 1 - 0.5*layout[0].matrix.Naxis[0])/expand + 0.5*layout[0].picture.dx;
+  Y0 =  (layout[0].Y + 1 - 0.5*layout[0].matrix.Naxis[1])/expand + 0.5*layout[0].picture.dy;
+  */
+  Image_to_Screen (&X0, &Y0, 0.0, 0.0, layout);
+  X0 -= layout[0].picture.x;
+  Y0 -= layout[0].picture.y;
+
+  Xmin = 0;
+  Ymin = 0;
+  Xmax = layout[0].picture.dx;
+  Ymax = layout[0].picture.dy;
+
+  for (i = 0; i < layout[0].overlay[N].Nobjects; i++) {
+    if (N == INFRONT) {
+      X  = layout[0].overlay[N].objects[i].x * Xmax;
+      Y  = layout[0].overlay[N].objects[i].y * Ymax;
+      dX = layout[0].overlay[N].objects[i].dx * Xmax;
+      dY = layout[0].overlay[N].objects[i].dy * Ymax;
+    } else {
+      X  = (layout[0].overlay[N].objects[i].x)/expand + X0;
+      Y =  Ymax - (layout[0].overlay[N].objects[i].y)/expand - Y0;
+      dX = (layout[0].overlay[N].objects[i].dx)/expand;
+      dY = (layout[0].overlay[N].objects[i].dy)/expand;
+    }
+    
+    if (!strcmp (layout[0].overlay[N].objects[i].type, "LINE")) {
+      if (((X < Xmin) && (X + dX < Xmin)) || ((X > Xmax) && (X + dX > Xmax)) ||
+	  ((Y < Ymin) && (Y + dY < Ymin)) || ((Y > Ymax) && (Y + dY > Ymax))) {
+	continue;
+      }
+      fprintf (f, " %6.1f %6.1f %6.1f %6.1f L\n", X + extra, Y + extra, (X+dX + extra), (Y-dY + extra));
+      continue;
+    }
+    if (!strcmp (layout[0].overlay[N].objects[i].type, "TEXT")) {
+      if (((X < Xmin) && (X + dX < Xmin)) || ((X > Xmax) && (X + dX > Xmax)) ||
+	  ((Y < Ymin) && (Y + dY < Ymin)) || ((Y > Ymax) && (Y + dY > Ymax))) {
+	continue;
+      }
+      fprintf (f, "(%s) %6.1f %6.1f T\n", layout[0].overlay[N].objects[i].text, X + extra, Y + extra); 
+      continue;
+    }
+    if (!strcmp (layout[0].overlay[N].objects[i].type, "BOX")) {
+      if (((X - 0.5*dX < Xmin) && (X + 0.5*dX < Xmin)) || ((X - 0.5*dX > Xmax) && (X + 0.5*dX > Xmax)) ||
+	  ((Y - 0.5*dY < Ymin) && (Y + 0.5*dY < Ymin)) || ((Y - 0.5*dY > Ymax) && (Y + 0.5*dY > Ymax))) {
+	continue;
+      }
+      fprintf (f, " %6.1f %6.1f %6.1f %6.1f B\n", (dX + 2*extra), (dY + 2*extra), (X - 0.5*dX - extra), (Y - 0.5*dY - extra));
+      continue;
+    }
+    if (!strcmp (layout[0].overlay[N].objects[i].type, "CIRCLE")) {
+      if (((X - dX < Xmin) && (X + dX < Xmin)) || ((X - dX > Xmax) && (X + dX > Xmax)) ||
+	  ((Y - dY < Ymin) && (Y + dY < Ymin)) || ((Y - dY > Ymax) && (Y + dY > Ymax))) {
+	continue;
+      }
+      fprintf (f, " %6.1f %6.1f %6.1f C\n", X, Y, fabs(dX + extra));
+      continue;
+    }
+    fprintf (stderr, "don't know %s, skipping\n", layout[0].overlay[N].objects[i].type);
+  }
+  
+}
+
+/* this routine is independent of the number of overlays */
+
Index: /tags/start/Ohana/src/kii/overlay/EraseOverlay.c
===================================================================
--- /tags/start/Ohana/src/kii/overlay/EraseOverlay.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/overlay/EraseOverlay.c	(revision 12606)
@@ -0,0 +1,27 @@
+# include "Ximage.h"
+
+int EraseOverlay (Graphic *graphic, Layout *layout) {
+
+  char buffer[256];
+  int i, status, N;
+
+  status = read (layout[0].Ximage, buffer, 16); 
+  buffer[16] = 0; 
+  sscanf (buffer, "%*s %d", &N); 
+  if (N > NOVERLAYS) {
+    REALLOCATE (layout[0].tickmarks.objects, Object, 1);
+    layout[0].tickmarks.Nobjects = 0;
+  } else {
+    for (i = 0; i < layout[0].overlay[N].Nobjects; i++) {
+      if (!strcmp (layout[0].overlay[N].objects[i].type, "TEXT")) {
+	free (layout[0].overlay[N].objects[i].text);
+      }
+    }
+    REALLOCATE (layout[0].overlay[N].objects, Object, 1);
+    layout[0].overlay[N].Nobjects = 0;
+    OVERLAY[N] = FALSE;
+  }
+
+  Refresh (graphic, layout, 0);
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/kii/overlay/LoadOverlay.c
===================================================================
--- /tags/start/Ohana/src/kii/overlay/LoadOverlay.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/overlay/LoadOverlay.c	(revision 12606)
@@ -0,0 +1,102 @@
+# include "Ximage.h"
+
+int LoadOverlay (graphic, layout)
+     Graphic graphic[];
+     Layout  layout[];
+{
+  
+  char line[17], *buffer, *buff, type[16], string[128];
+  double x, y, dx, dy;
+  int Nin, bytes, status;
+  int i, N, NOBJECTS, Nobjects, Nstart, done;
+
+  ALLOCATE (buffer, char, 65536);  /* space for 512 lines of 128 bytes */
+  bzero (buffer, 65536);
+  done = FALSE;
+
+  fcntl (layout[0].Ximage, F_SETFL, !O_NONBLOCK);  
+
+  status = read (layout[0].Ximage, line, 16); 
+  line[16] = 0; 
+  sscanf (line, "%*s %d", &N); 
+  Nstart = layout[0].overlay[N].Nobjects;
+
+  while (!done) {
+    status = read (layout[0].Ximage, line, 16); 
+    line[16] = 0; 
+    
+    if (!strncmp (line, "DONE", 4)) {
+      done = TRUE;
+      break;
+    }
+
+    if (!strncmp (line, "NLINES", 6)) {
+      sscanf (line, "%*s %d", &Nin);
+      buff = buffer;
+      bytes = 128*Nin;
+      fcntl (layout[0].Ximage, F_SETFL, O_NONBLOCK);  
+      while (bytes > 0) { 
+	status = read (layout[0].Ximage, buff, bytes);
+	if (status == 0) {  /* No more pipe */
+	  fprintf (stderr, "error: pipe closed\n");
+	  free (buffer);
+	  fcntl (layout[0].Ximage, F_SETFL, O_NONBLOCK);  
+	  return (FALSE);
+	}
+	if (status != -1) { /* pipe has data */
+	  bytes -= status;
+	  buff = (char *)(buff + status);
+	}
+      }
+      fcntl (layout[0].Ximage, F_SETFL, !O_NONBLOCK);  
+      /* parse buffer data */
+      NOBJECTS = layout[0].overlay[N].Nobjects + Nin;
+      Nobjects = layout[0].overlay[N].Nobjects;
+      REALLOCATE (layout[0].overlay[N].objects, Object, NOBJECTS);
+      for (i = 0; i < Nin; i++) {
+	sscanf (&buffer[i*128], "%s %lf %lf %lf %lf\n", type, &x, &y, &dx, &dy);
+
+	if (strcasecmp (type, "TEXT") && strcasecmp (type, "LINE") && strcasecmp (type, "BOX") && strcasecmp (type, "CIRCLE")) {  /* skip */
+	  fprintf (stderr, "don't know %s, skipping\n", type);
+	  continue;
+	}
+
+	if (!strcasecmp (type, "TEXT")) { /* end of objects */
+	  sscanf (&buffer[i*128], "%s %lf %lf %s\n", type, &x, &y, string);
+	}
+	
+	strcpy (layout[0].overlay[N].objects[Nobjects].type, type);
+	layout[0].overlay[N].objects[Nobjects].x = x;
+	layout[0].overlay[N].objects[Nobjects].y = y;
+	if (!strcmp (type, "TEXT")) {
+	  layout[0].overlay[N].objects[Nobjects].dx = 0;
+	  layout[0].overlay[N].objects[Nobjects].dy = 0;
+	  layout[0].overlay[N].objects[Nobjects].text = strcreate (string);
+	} else {
+	  layout[0].overlay[N].objects[Nobjects].dx = dx;
+	  layout[0].overlay[N].objects[Nobjects].dy = dy;
+	}
+	Nobjects++;
+      }
+      REALLOCATE (layout[0].overlay[N].objects, Object, MAX(Nobjects, 1));
+      layout[0].overlay[N].Nobjects = Nobjects;
+    }
+  }
+
+  free (buffer);
+  REALLOCATE (layout[0].overlay[N].objects, Object, MAX (1, layout[0].overlay[N].Nobjects));
+  OVERLAY[N] = TRUE;
+  /*  Refresh (graphic, layout, 0); */
+  for (i = 0; i < NOVERLAYS; i++) {
+    if (OVERLAY[i])
+      PaintOverlay (graphic, layout, i);
+  }
+  PaintTickmarks (graphic, layout);
+  XFlush (graphic[0].display);
+  fcntl (layout[0].Ximage, F_SETFL, O_NONBLOCK);  
+  return (TRUE);
+
+}
+
+
+/* this routine is independent of the number of overlays */
Index: /tags/start/Ohana/src/kii/overlay/LoadTickmarks.c
===================================================================
--- /tags/start/Ohana/src/kii/overlay/LoadTickmarks.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/overlay/LoadTickmarks.c	(revision 12606)
@@ -0,0 +1,64 @@
+# include "Ximage.h"
+
+int LoadTickmarks (Graphic *graphic, Layout *layout) {
+  
+  char line[129], type[16];
+  double x, y, dx, dy;
+  int status, NOBJECTS, Nobjects, done;
+
+  fcntl (layout[0].Ximage, F_SETFL, !O_NONBLOCK);  
+
+  Nobjects = layout[0].tickmarks.Nobjects;
+  NOBJECTS = Nobjects + 100;
+  REALLOCATE (layout[0].tickmarks.objects, Object, NOBJECTS);
+  
+  done = FALSE;
+  while (!done) {
+    status = read (layout[0].Ximage, line, 128); 
+    line[128] = 0; 
+
+    if (!strncmp (line, "DONE", 4)) {
+      done = TRUE;
+      break;
+    }
+    
+    sscanf (line, "%s %lf %lf %lf %lf\n", type, &x, &y, &dx, &dy);
+    
+    if (strcmp (type, "TEXT") && strcmp (type, "LINE") && strcmp (type, "BOX") && strcmp (type, "CIRCLE")) {  /* skip */
+      fprintf (stderr, "don't know %s, skipping\n", type);
+      continue;
+    }
+    
+    strcpy (layout[0].tickmarks.objects[Nobjects].type, type);
+    layout[0].tickmarks.objects[Nobjects].x = x;
+    layout[0].tickmarks.objects[Nobjects].y = y;
+    layout[0].tickmarks.objects[Nobjects].dx = dx;
+    layout[0].tickmarks.objects[Nobjects].dy = dy;
+    
+    if (!strcmp (type, "TEXT")) { /* dx = Nchar, dy = angle (not yet used) */
+      status = read (layout[0].Ximage, line, 128); 
+      line[128] = 0; 
+      ALLOCATE (layout[0].tickmarks.objects[Nobjects].text, char, (int) dx + 1);
+      strncpy (layout[0].tickmarks.objects[Nobjects].text, line, (int) dx);
+      layout[0].tickmarks.objects[Nobjects].text[(int)dx] = 0;
+    }      
+    
+    Nobjects++;
+    if (Nobjects >= NOBJECTS) {
+      NOBJECTS = Nobjects + 100;
+      REALLOCATE (layout[0].tickmarks.objects, Object, NOBJECTS);
+    }
+
+  }
+
+  REALLOCATE (layout[0].tickmarks.objects, Object, MAX(Nobjects, 1));
+  layout[0].tickmarks.Nobjects = Nobjects;
+
+  Refresh (graphic, layout, 0);
+  fcntl (layout[0].Ximage, F_SETFL, O_NONBLOCK);  
+  return (TRUE);
+  
+}
+
+
+/* this routine is independent of the number of overlays */
Index: /tags/start/Ohana/src/kii/overlay/PaintOverlay.c
===================================================================
--- /tags/start/Ohana/src/kii/overlay/PaintOverlay.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/overlay/PaintOverlay.c	(revision 12606)
@@ -0,0 +1,84 @@
+# include "Ximage.h"
+# define INFRONT 4
+
+void PaintOverlay (Graphic *graphic, Layout *layout, int N) {
+
+  int i;
+  int dX, dY, dx, dy;
+  int X, Y, Xmin, Ymin, Xmax, Ymax, Xrange, Yrange;
+  double expand, X0, Y0;
+ 
+  XSetForeground (graphic[0].display, graphic[0].gc, layout[0].overlay[N].color);
+  
+  if (layout[0].expand > 0) {
+    expand = 1 / (1.0*layout[0].expand);
+  }
+  if (layout[0].expand < 0) {
+    expand = fabs((double)layout[0].expand);
+  }
+  /* 
+  X = 0.5*layout[0].matrix.Naxis[0] - expand*((int)(0.5*layout[0].picture.dx + 0.5) - 0.0) - layout[0].X;
+  Y = 0.5*layout[0].matrix.Naxis[1] - expand*((int)(0.5*layout[0].picture.dy + 0.5) - 0.0) - layout[0].Y;  
+  X0 =  (layout[0].X + 1 - (int)(0.5*layout[0].matrix.Naxis[0] + 0.5) - X + (int)X)/expand + layout[0].picture.x + 0.5*layout[0].picture.dx;
+  Y0 =  (layout[0].Y + 1 - (int)(0.5*layout[0].matrix.Naxis[1] + 0.5) - Y + (int)Y)/expand + layout[0].picture.y + 0.5*layout[0].picture.dy;
+  */
+
+  Image_to_Screen (&X0, &Y0, 0.0, 0.0, layout);
+
+  Xmin = layout[0].picture.x;
+  Ymin = layout[0].picture.y;
+  Xmax = layout[0].picture.x + layout[0].picture.dx;
+  Ymax = layout[0].picture.y + layout[0].picture.dy;
+  Xrange = layout[0].picture.dx;
+  Yrange = layout[0].picture.dy;
+
+  for (i = 0; i < layout[0].overlay[N].Nobjects; i++) {
+    if (N == INFRONT) {
+      X  = layout[0].overlay[N].objects[i].x * Xrange + Xmin;
+      Y  = layout[0].overlay[N].objects[i].y * Yrange + Ymin;
+      dX = layout[0].overlay[N].objects[i].dx * Xrange;
+      dY = layout[0].overlay[N].objects[i].dy * Yrange;
+    } else {
+      X  = layout[0].overlay[N].objects[i].x/expand + X0;
+      Y =  layout[0].overlay[N].objects[i].y/expand + Y0;
+      dX = layout[0].overlay[N].objects[i].dx/expand;
+      dY = layout[0].overlay[N].objects[i].dy/expand;
+    }
+    if ((X + dX < Xmin) || (X - dX > Xmax) ||
+	(Y + dY < Ymin) || (Y - dY > Ymax)) {
+      continue;
+    }
+
+    /* for a LINE, (x, y) is the start, (dx, dy) is the distance to end
+       for a CIRCLE (x, y) is the center, (dx, dy) is the radius 
+       for a BOX (x, y) is the center, (dx, dy) is the width */
+
+    if (!strcasecmp (layout[0].overlay[N].objects[i].type, "LINE")) {
+      XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, (X+dX), (Y+dY));
+      continue;
+    }
+    if (!strcasecmp (layout[0].overlay[N].objects[i].type, "TEXT")) {
+      XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, layout[0].overlay[N].objects[i].text, strlen(layout[0].overlay[N].objects[i].text));
+      continue;
+    }
+    if (!strcasecmp (layout[0].overlay[N].objects[i].type, "BOX")) {
+      dx = MAX (abs(dX),2) / 2;
+      dy = MAX (abs(dY),2) / 2;
+      XDrawRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, (X - dx), (Y - dy), 2*dx, 2*dy);
+       continue;
+    }
+    if (!strcasecmp (layout[0].overlay[N].objects[i].type, "CIRCLE")) {
+      dx = MAX (abs(dX),2);
+      dy = MAX (abs(dY),2);
+      XDrawArc (graphic[0].display, graphic[0].window, graphic[0].gc, (X - dx), (Y - dy), 2*dx, 2*dy, 0, 23040);
+      continue;
+    }
+    fprintf (stderr, "don't know %s, skipping (PO)\n", layout[0].overlay[N].objects[i].type);
+  }
+  
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+
+}
+
+/* this routine is independent of the number of overlays */
+
Index: /tags/start/Ohana/src/kii/overlay/PaintTickmarks.c
===================================================================
--- /tags/start/Ohana/src/kii/overlay/PaintTickmarks.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/overlay/PaintTickmarks.c	(revision 12606)
@@ -0,0 +1,66 @@
+# include "Ximage.h"
+# define INFRONT 3
+/* # include "rotletters.h" */
+
+void PaintTickmarks (Graphic *graphic, Layout *layout) {
+
+  int i;
+  int X, Y, dX, dY;
+  int Xmin, Ymin, Xmax, Ymax, Xrange, Yrange;
+ 
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+
+  Xmin = layout[0].picture.x;
+  Ymin = layout[0].picture.y;
+  Xmax = layout[0].picture.x + layout[0].picture.dx;
+  Ymax = layout[0].picture.y + layout[0].picture.dy;
+  Xrange = layout[0].picture.dx;
+  Yrange = layout[0].picture.dy;
+
+  for (i = 0; i < layout[0].tickmarks.Nobjects; i++) {
+    X  = layout[0].tickmarks.objects[i].x * Xrange + Xmin;
+    Y  = layout[0].tickmarks.objects[i].y * Yrange + Ymin;
+    dX = layout[0].tickmarks.objects[i].dx * Xrange;
+    dY = layout[0].tickmarks.objects[i].dy * Yrange;
+
+    if (!strcmp (layout[0].tickmarks.objects[i].type, "LINE")) {
+      XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, (X+dX), (Y+dY));
+      continue;
+    }
+    if (!strcmp (layout[0].tickmarks.objects[i].type, "TEXT")) {
+      if (layout[0].tickmarks.objects[i].dy == 0) {
+	XSetForeground (graphic[0].display, graphic[0].gc, layout[0].white);
+	XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y-11, 6*strlen(layout[0].tickmarks.objects[i].text), 11); 
+	XSetForeground (graphic[0].display, graphic[0].gc, layout[0].black);
+	XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, layout[0].tickmarks.objects[i].text, strlen(layout[0].tickmarks.objects[i].text));
+      }
+      if (layout[0].tickmarks.objects[i].dy == 90) {
+	XSetForeground (graphic[0].display, graphic[0].gc, layout[0].white);
+	XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y-6*strlen(layout[0].tickmarks.objects[i].text), 11, 6*strlen(layout[0].tickmarks.objects[i].text)); 
+	XSetForeground (graphic[0].display, graphic[0].gc, layout[0].black);
+	/* XDrawRotString (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, layout[0].tickmarks.objects[i].text, strlen(layout[0].tickmarks.objects[i].text)); */
+      }
+      continue;
+    }
+    if (!strcmp (layout[0].tickmarks.objects[i].type, "BOX")) {
+      XDrawRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, (int)(X - 0.5*dX), (int)(Y - 0.5*dY), abs(dX), abs(dY));
+       continue;
+    }
+    if (!strcmp (layout[0].tickmarks.objects[i].type, "CIRCLE")) {
+      XDrawArc (graphic[0].display, graphic[0].window, graphic[0].gc, X - dX, Y - dY, abs(2*dX), abs(2*dY), 0, 23040);
+      continue;
+    }
+    fprintf (stderr, "don't know %s, skipping (PO)\n", layout[0].tickmarks.objects[i].type);
+  }
+  
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+
+}
+
+/* this routine is independent of the number of overlays */
+
+
+/*
+XDrawRotString (dpy, win, gc, X, Y, text, len)
+     
+*/
Index: /tags/start/Ohana/src/kii/overlay/SaveOverlay.c
===================================================================
--- /tags/start/Ohana/src/kii/overlay/SaveOverlay.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/overlay/SaveOverlay.c	(revision 12606)
@@ -0,0 +1,41 @@
+# include "Ximage.h"
+
+/*************/
+int 
+SaveOverlay (graphic, layout)
+     Graphic graphic[];
+     Layout  layout[];
+{
+
+  char buffer[256], filename[256];
+  int i, status, Nbytes, N;
+  FILE *f;
+
+  status = read (layout[0].Ximage, buffer, 16); 
+  buffer[16] = 0; 
+  sscanf (buffer, "%*s %d", &Nbytes); 
+  status = read (layout[0].Ximage, buffer, Nbytes); 
+  buffer[Nbytes] = 0; 
+  sscanf (buffer, "%*s %d %s", &N, filename);
+  
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "could not open %s\n", filename);
+    return (TRUE);
+  }
+
+  for (i = 0; i < layout[0].overlay[N].Nobjects; i++) {
+    fprintf (f, "%s %lf %lf %lf %lf\n", 
+	     layout[0].overlay[N].objects[i].type,
+	     layout[0].overlay[N].objects[i].x,
+	     layout[0].overlay[N].objects[i].y,
+	     layout[0].overlay[N].objects[i].dx,
+	     layout[0].overlay[N].objects[i].dy);
+  }
+  fclose (f);
+  return (TRUE);
+}
+
+
+/* this routine is independent of the number of overlays */
+
Index: /tags/start/Ohana/src/kii/picture/Center.c
===================================================================
--- /tags/start/Ohana/src/kii/picture/Center.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/picture/Center.c	(revision 12606)
@@ -0,0 +1,28 @@
+# include "Ximage.h"
+
+int Center (Graphic *graphic, Layout *layout) {
+
+  char buffer[1024];
+  int status, zoom, Nbytes;
+  double X, Y;
+
+  status = read (layout[0].Ximage, buffer, 16); 
+  buffer[16] = 0; 
+  sscanf (buffer, "%*s %d", &Nbytes); 
+  status = read (layout[0].Ximage, buffer, Nbytes); 
+  buffer[status] = 0; /* make the string easy to parse */ 
+  sscanf (buffer, "%lf %lf %d", &X,  &Y, &zoom);
+
+  layout[0].X = 0.5*layout[0].matrix.Naxis[0] - X;
+  layout[0].Y = 0.5*layout[0].matrix.Naxis[1] - Y;
+  if ((zoom != 0) && (zoom != -1)) {
+    layout[0].expand = zoom;
+  }
+
+  Remap (graphic, layout, &layout[0].matrix);
+  Refresh (graphic, layout, 0);
+
+  XFlush (graphic[0].display);
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/kii/picture/CreatePicture.c
===================================================================
--- /tags/start/Ohana/src/kii/picture/CreatePicture.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/picture/CreatePicture.c	(revision 12606)
@@ -0,0 +1,67 @@
+# include "Ximage.h"
+
+void CreatePicture (Layout *layout, Graphic *graphic) {
+
+  int i, j, extra;
+  char *c;
+  unsigned int *l;
+  unsigned int start, start1, start2, start3;
+
+  start = layout[0].white;
+
+  switch (graphic[0].Nbits) {
+  case 8:
+    REALLOCATE (layout[0].picture.data, char, layout[0].picture.dx*layout[0].picture.dy);
+    c = layout[0].picture.data;
+    for (i = 0; i < (layout[0].picture.dx*layout[0].picture.dy); i++, c++)
+      *c = start;
+    layout[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  layout[0].picture.data, layout[0].picture.dx, layout[0].picture.dy, 8, 0);
+    break;
+
+  case 16:
+    REALLOCATE (layout[0].picture.data, char, 2*layout[0].picture.dy*layout[0].picture.dx);
+    c = layout[0].picture.data;
+    start1 = 0x0000ff & (start);
+    start2 = 0x0000ff & (start >> 8);
+    for (i = 0; i < layout[0].picture.dy; i++) {
+      for (j = 0; j < layout[0].picture.dx; j++, c+=2) {
+	c[0] = start1;
+	c[1] = start2;
+      }
+    }
+    layout[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  layout[0].picture.data, layout[0].picture.dx, layout[0].picture.dy, 16, 0);
+    break;
+
+  case 24:
+    extra = 4 - (layout[0].picture.dx * 3) % 4;
+    REALLOCATE (layout[0].picture.data, char, layout[0].picture.dy*(3*layout[0].picture.dx+extra));
+    c = (unsigned char *) layout[0].picture.data;
+    start1 = 0x0000ff & (start);
+    start2 = 0x0000ff & (start >> 8);
+    start3 = 0x0000ff & (start >> 16);
+    for (i = 0; i < layout[0].picture.dy; i++) {
+      for (j = 0; j < layout[0].picture.dx; j++, c+=3) {
+	c[0] = start1;
+	c[1] = start2;
+	c[2] = start3;
+      }
+      c+=extra;
+    }
+    layout[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  layout[0].picture.data, layout[0].picture.dx, layout[0].picture.dy, 24, 0);
+    break;
+
+  case 32:
+    ALLOCATE (layout[0].picture.data, char, (4*layout[0].picture.dx*layout[0].picture.dy + 32));
+    memset (layout[0].picture.data, 0xbd, 4*layout[0].picture.dx*layout[0].picture.dy + 30);
+    l = (unsigned int *) layout[0].picture.data;
+    for (i = 0; i < (layout[0].picture.dx*layout[0].picture.dy); i++, l++)
+      *l = start;
+    layout[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  layout[0].picture.data, layout[0].picture.dx, layout[0].picture.dy, 32, 0);
+    break;
+  }
+    
+}
Index: /tags/start/Ohana/src/kii/picture/CursorOps.c
===================================================================
--- /tags/start/Ohana/src/kii/picture/CursorOps.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/picture/CursorOps.c	(revision 12606)
@@ -0,0 +1,35 @@
+# include "Ximage.h"
+
+void Screen_to_Image (double *x1, double *y1, double x2, double y2, Layout *layout) {
+
+  double expand;
+
+  if (layout[0].expand > 0) {
+    expand = 1 / (1.0*layout[0].expand);
+  }
+  if (layout[0].expand < 0) {
+    expand = fabs((double)layout[0].expand);
+  }
+  
+  *x1 = expand*(x2 - layout[0].picture.x - 0.5*layout[0].picture.dx) + 0.5*layout[0].matrix.Naxis[0] - layout[0].X;
+  *y1 = expand*(y2 - layout[0].picture.y - 0.5*layout[0].picture.dy) + 0.5*layout[0].matrix.Naxis[1] - layout[0].Y;
+  
+}
+
+void Image_to_Screen (double *x1, double *y1, double x2, double y2, Layout *layout) {
+
+  double expand;
+
+  /* notice that here, expand is the reciprocal of the expand above */
+  if (layout[0].expand > 0) {
+    expand = abs(layout[0].expand);
+  }
+  if (layout[0].expand < 0) {
+    expand = 1 / ((double)abs(layout[0].expand));
+  }
+  
+  *x1 = (x2 - 0.5*layout[0].matrix.Naxis[0] + layout[0].X) * expand + layout[0].picture.x + 0.5*layout[0].picture.dx;
+  *y1 = (y2 - 0.5*layout[0].matrix.Naxis[1] + layout[0].Y) * expand + layout[0].picture.y + 0.5*layout[0].picture.dy;
+  
+}
+
Index: /tags/start/Ohana/src/kii/picture/NewPicture.c
===================================================================
--- /tags/start/Ohana/src/kii/picture/NewPicture.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/picture/NewPicture.c	(revision 12606)
@@ -0,0 +1,84 @@
+# include "Ximage.h"
+# define SCAN \
+  status = read (layout[0].Ximage, buffer, 16); \
+  buffer[16] = 0; \
+  sscanf (buffer, "%*s %d", &Nbytes); \
+  status = read (layout[0].Ximage, buffer, Nbytes); \
+  buffer[status] = 0; /* make the string easy to parse */ \
+  (DEBUG) && fprintf (stderr, "buffer: <%s>\n", buffer); \
+
+int NewPicture (Graphic *graphic, Layout *layout) {
+
+  Header header;
+  char buffer[1024], *buff;
+  int status, bytes_left, Nbytes;
+ 
+  fits_free_matrix (&layout[0].matrix);
+  sprintf (buffer, "NCOLOR: %6d ", layout[0].Npixels);
+  write (layout[0].Ximage, buffer, 16);
+
+  fcntl (layout[0].Ximage, F_SETFL, !O_NONBLOCK);  
+
+  header.Naxes = 2;
+  SCAN;
+  sscanf (buffer, "%d %d %d %d %lf %lf",
+	  &header.Naxis[0], &header.Naxis[1], &header.bitpix, 
+	  &header.unsign,   &header.bzero,    &header.bscale);
+
+  SCAN;
+  sscanf (buffer, "%lf %lf %lf %lf %d", &layout[0].zero, &layout[0].range, &layout[0].min,  &layout[0].max, &header.size);
+
+  SCAN;
+  sscanf (buffer, "%lf %f %f %f %f", &layout[0].coords.crval1, &layout[0].coords.crpix1, &layout[0].coords.cdelt1, &layout[0].coords.pc1_1, &layout[0].coords.pc1_2);
+	  
+  SCAN;
+  sscanf (buffer, "%lf %f %f %f %f", &layout[0].coords.crval2, &layout[0].coords.crpix2, &layout[0].coords.cdelt2, &layout[0].coords.pc2_1, &layout[0].coords.pc2_2);
+	  
+  SCAN;
+  sscanf (buffer, "%s %s %s", layout[0].coords.ctype, layout[0].file, layout[0].buffer_name);
+
+  fits_create_matrix (&header, &layout[0].matrix);
+
+  fcntl (layout[0].Ximage, F_SETFL, O_NONBLOCK);  
+
+  status = 1;
+  buff = layout[0].matrix.buffer;
+  bytes_left = header.size;
+  layout[0].matrix.size = 0;
+  while (bytes_left > 0) {
+    status = read (layout[0].Ximage, buff, bytes_left);
+    if (status == 0) {  /* No more pipe */
+      fprintf (stderr, "error: pipe closed\n");
+      return (FALSE);
+    }
+    if (status != -1) { /* pipe has data */
+      layout[0].matrix.size += status;
+      bytes_left -= status;
+      buff = (char *)(buff + status);
+    }
+  }
+
+  (DEBUG) && fprintf (stderr, "read %d bytes\n", layout[0].matrix.size);
+  /* it it not obvious this condition should kill kii, but ... */
+  if (layout[0].matrix.size != header.size) {  
+    fprintf (stderr, "error: expected %d bytes, but got only %d\n", header.size, layout[0].matrix.size);
+    return (FALSE);
+  }
+
+  Remap (graphic, layout, &layout[0].matrix);
+  (DEBUG) && fprintf (stderr, "remapped image\n");
+  Refresh (graphic, layout, 0);
+  
+  (DEBUG) && fprintf (stderr, "refreshed\n");
+  XFlush (graphic[0].display);
+
+  return (TRUE);
+
+}
+
+/*
+   layout[0].X = 0;
+   layout[0].Y = 0;
+   layout[0].expand = 1;
+*/
+  
Index: /tags/start/Ohana/src/kii/picture/PositionPictures.c
===================================================================
--- /tags/start/Ohana/src/kii/picture/PositionPictures.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/picture/PositionPictures.c	(revision 12606)
@@ -0,0 +1,152 @@
+# include "Ximage.h" 
+# include "buttons.h"
+# define BUTTON_WIDTH 28
+# define BUTTON_HEIGHT 28
+
+void PositionPictures (Layout *layout, Graphic *graphic) {
+
+  layout[0].cmapbar.dx = graphic[0].dx - 2*PAD1; 
+  layout[0].cmapbar.dy = COLORPAD;
+  layout[0].cmapbar.x = PAD1;
+  layout[0].cmapbar.y = PAD1;
+
+  layout[0].zoom.dx = ZOOM_X; 
+  layout[0].zoom.dy = ZOOM_Y;
+  layout[0].zoom.x = graphic[0].dx - PAD1 - ZOOM_X;
+  layout[0].zoom.y = layout[0].cmapbar.y + layout[0].cmapbar.dy + PAD2;
+
+  layout[0].picture.dx = layout[0].zoom.x - 2*PAD1 - 25; 
+  layout[0].picture.dy = graphic[0].dy - 2*PAD1 - PAD2 - COLORPAD - 25;
+  layout[0].picture.x = PAD1 + 25;
+  layout[0].picture.y = PAD1 + PAD2 + COLORPAD;
+
+  /** everything below is tied in x-dir to the zoom box **/
+  layout[0].text_x = layout[0].zoom.x;
+  layout[0].text_y = layout[0].zoom.y + layout[0].zoom.dy + PAD2;
+
+  /*  layout[0].PS_button.y = graphic[0].dy - BUTTON_HEIGHT - PAD1; */
+  layout[0].PS_button.x = layout[0].zoom.x + 5;
+  layout[0].PS_button.y = 2*ZOOM_Y;
+  layout[0].PS_button.dx = BUTTON_WIDTH;
+  layout[0].PS_button.dy = BUTTON_HEIGHT;
+  layout[0].PS_button.text = FALSE;
+  layout[0].PS_button.width = PS_width;
+  layout[0].PS_button.height = PS_height;
+  layout[0].PS_button.bitmap = PS_bits;
+  layout[0].PS_button.function_1 = PSit;
+  layout[0].PS_button.function_2 = PSit;
+  layout[0].PS_button.function_3 = PSit;
+
+  /** everything below is tied to the PS_button in y-dir **/
+  layout[0].grey_button.x = layout[0].PS_button.x + layout[0].PS_button.dx + PAD1;
+  layout[0].grey_button.y = layout[0].PS_button.y;
+  layout[0].grey_button.dx = BUTTON_WIDTH;
+  layout[0].grey_button.dy = BUTTON_HEIGHT;
+  layout[0].grey_button.text = FALSE;
+  layout[0].grey_button.width = grey_width;
+  layout[0].grey_button.height = grey_height;
+  layout[0].grey_button.bitmap = grey_bits;
+  layout[0].grey_button.function_1 = greycolors;
+  layout[0].grey_button.function_2 = greycolors;
+  layout[0].grey_button.function_3 = greycolors;
+
+  layout[0].rainbow_button.x = layout[0].grey_button.x + layout[0].grey_button.dx + PAD1;
+  layout[0].rainbow_button.y = layout[0].PS_button.y;
+  layout[0].rainbow_button.dx = BUTTON_WIDTH;
+  layout[0].rainbow_button.dy = BUTTON_HEIGHT;
+  layout[0].rainbow_button.text = FALSE;
+  layout[0].rainbow_button.width = rainbow_width;
+  layout[0].rainbow_button.height = rainbow_height;
+  layout[0].rainbow_button.bitmap = rainbow_bits;
+  layout[0].rainbow_button.function_1 = rainbow;
+  layout[0].rainbow_button.function_2 = rainbow;
+  layout[0].rainbow_button.function_3 = rainbow;
+
+  layout[0].puns_button.x = layout[0].rainbow_button.x + layout[0].rainbow_button.dx + PAD1;
+  layout[0].puns_button.y = layout[0].PS_button.y;
+  layout[0].puns_button.dx = BUTTON_WIDTH;
+  layout[0].puns_button.dy = BUTTON_HEIGHT;
+  layout[0].puns_button.text = FALSE;
+  layout[0].puns_button.width = puns_width;
+  layout[0].puns_button.height = puns_height;
+  layout[0].puns_button.bitmap = puns_bits;
+  layout[0].puns_button.function_1 = puns;
+  layout[0].puns_button.function_2 = puns;
+  layout[0].puns_button.function_3 = puns;
+
+  layout[0].recenter_button.x = layout[0].puns_button.x + layout[0].puns_button.dx + PAD1;
+  layout[0].recenter_button.y = layout[0].PS_button.y;
+  layout[0].recenter_button.dx = BUTTON_WIDTH;
+  layout[0].recenter_button.dy = BUTTON_HEIGHT;
+  layout[0].recenter_button.text = FALSE;
+  layout[0].recenter_button.width = recenter_width;
+  layout[0].recenter_button.height = recenter_height;
+  layout[0].recenter_button.bitmap = recenter_bits;
+  layout[0].recenter_button.function_1 = Recenter;
+  layout[0].recenter_button.function_2 = RecenterRescale;
+  layout[0].recenter_button.function_3 = Rescale;
+
+  layout[0].overlay_button[0].x = layout[0].zoom.x + 5;
+  layout[0].overlay_button[0].y = layout[0].PS_button.y - BUTTON_HEIGHT - PAD1;
+  layout[0].overlay_button[0].dx = BUTTON_WIDTH;
+  layout[0].overlay_button[0].dy = BUTTON_HEIGHT;
+  layout[0].overlay_button[0].text = FALSE;
+  layout[0].overlay_button[0].width = red_width;
+  layout[0].overlay_button[0].height = red_height;
+  layout[0].overlay_button[0].bitmap = red_bits;
+  layout[0].overlay_button[0].function_1 = Overlay0;
+  layout[0].overlay_button[0].function_2 = Overlay0;
+  layout[0].overlay_button[0].function_3 = Overlay0;
+		   	   
+  layout[0].overlay_button[1].x = layout[0].overlay_button[0].x + layout[0].overlay_button[0].dx + PAD1;
+  layout[0].overlay_button[1].y = layout[0].PS_button.y - BUTTON_HEIGHT - PAD1;
+  layout[0].overlay_button[1].dx = BUTTON_WIDTH;
+  layout[0].overlay_button[1].dy = BUTTON_HEIGHT;
+  layout[0].overlay_button[1].text = FALSE;
+  layout[0].overlay_button[1].width = green_width;
+  layout[0].overlay_button[1].height = green_height;
+  layout[0].overlay_button[1].bitmap = green_bits;
+  layout[0].overlay_button[1].function_1 = Overlay1;
+  layout[0].overlay_button[1].function_2 = Overlay1;
+  layout[0].overlay_button[1].function_3 = Overlay1;
+
+  layout[0].overlay_button[2].x = layout[0].overlay_button[1].x + layout[0].overlay_button[1].dx + PAD1;
+  layout[0].overlay_button[2].y = layout[0].PS_button.y - BUTTON_HEIGHT - PAD1;
+  layout[0].overlay_button[2].dx = BUTTON_WIDTH;
+  layout[0].overlay_button[2].dy = BUTTON_HEIGHT;
+  layout[0].overlay_button[2].text = FALSE;
+  layout[0].overlay_button[2].width = blue_width;
+  layout[0].overlay_button[2].height = blue_height;
+  layout[0].overlay_button[2].bitmap = blue_bits;
+  layout[0].overlay_button[2].function_1 = Overlay2;
+  layout[0].overlay_button[2].function_2 = Overlay2;
+  layout[0].overlay_button[2].function_3 = Overlay2;
+		   	   
+  layout[0].overlay_button[3].x = layout[0].overlay_button[2].x + layout[0].overlay_button[2].dx + PAD1;
+  layout[0].overlay_button[3].y = layout[0].PS_button.y - BUTTON_HEIGHT - PAD1;
+  layout[0].overlay_button[3].dx = BUTTON_WIDTH;
+  layout[0].overlay_button[3].dy = BUTTON_HEIGHT;
+  layout[0].overlay_button[3].text = FALSE;
+  layout[0].overlay_button[3].width = yellow_width;
+  layout[0].overlay_button[3].height = yellow_height;
+  layout[0].overlay_button[3].bitmap = yellow_bits;
+  layout[0].overlay_button[3].function_1 = Overlay3;
+  layout[0].overlay_button[3].function_2 = Overlay3;
+  layout[0].overlay_button[3].function_3 = Overlay3;
+
+  layout[0].hms_button.x = layout[0].overlay_button[3].x + layout[0].overlay_button[3].dx + PAD1;
+  layout[0].hms_button.y = layout[0].PS_button.y - BUTTON_HEIGHT - PAD1;
+  layout[0].hms_button.dx = BUTTON_WIDTH;
+  layout[0].hms_button.dy = BUTTON_HEIGHT;
+  layout[0].hms_button.text = FALSE;
+  layout[0].hms_button.width = hms_width;
+  layout[0].hms_button.height = hms_height;
+  layout[0].hms_button.bitmap = hms_bits;
+  layout[0].hms_button.function_1 = ToggleDEG;
+  layout[0].hms_button.function_2 = ToggleDEG;
+  layout[0].hms_button.function_3 = ToggleDEG;
+
+}
+
+
+/* this routine is dependent on the number of Overlays */
Index: /tags/start/Ohana/src/kii/picture/Remap.c
===================================================================
--- /tags/start/Ohana/src/kii/picture/Remap.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/picture/Remap.c	(revision 12606)
@@ -0,0 +1,21 @@
+# include "Ximage.h"
+
+void Remap (Graphic *graphic, Layout *layout, Matrix *matrix) {
+
+  switch (graphic[0].Nbits) {
+  case 8:
+    Remap8 (graphic, layout, matrix);
+    break;
+  case 16:
+    Remap16 (graphic, layout, matrix);
+    break;
+  case 24:
+    Remap24 (graphic, layout, matrix);
+    break;
+  case 32:
+    Remap32 (graphic, layout, matrix);
+    break;
+  }
+
+}
+
Index: /tags/start/Ohana/src/kii/picture/Remap16.c
===================================================================
--- /tags/start/Ohana/src/kii/picture/Remap16.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/picture/Remap16.c	(revision 12606)
@@ -0,0 +1,152 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+void Remap16 (Graphic *graphic, Layout *layout, Matrix *matrix) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, Rx, Ry, X, Y;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  unsigned char *in_pix,  *in_pix2;
+  unsigned char pixel1[256], pixel2[256], pixel3[256];
+  unsigned char pixvalue1, pixvalue2;
+  unsigned long white;
+  unsigned char white1, white2;
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel1[i] = 0x0000ff & layout[0].cmap[i].pixel;
+    pixel2[i] = 0x0000ff & (layout[0].cmap[i].pixel >> 8);
+    pixel3[i] = 0x0000ff & (layout[0].cmap[i].pixel >> 16);
+  }
+  white = layout[0].white;
+  white1 = 0x00ff & white;
+  white2 = 0x00ff & (white >> 8);
+
+  if (layout[0].expand == 0) /* set up expansions */
+    layout[0].expand = 1;
+  if (layout[0].expand > 0) {
+    expand = 1 / (1.0*layout[0].expand);
+    expand_out = layout[0].expand;
+    expand_in  = 1;
+  }
+  if (layout[0].expand < 0) {
+    expand = fabs((double)layout[0].expand);
+    expand_out = 1;
+    expand_in  = -layout[0].expand;
+  }
+
+  dx = layout[0].picture.dx;
+  dy = layout[0].picture.dy;
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+
+  /* X,Y are the image coordinates of the first image pixel */
+  X = MAX(0.5*(DX - dx*expand) - layout[0].X, 0);
+  if ((int)X != X) 
+    X = (int) X + 1;
+  else 
+    X = (int) X;
+  Y = MAX(0.5*(DY - dy*expand) - layout[0].Y, 0);
+  if ((int)Y != Y) 
+    Y = (int) Y + 1;
+  else 
+    Y = (int) Y;
+
+  /* Rx,Ry are the screen coordinates of the first image pixel */
+  Rx = (X + layout[0].X - 0.5*DX)/expand + 0.5*dx;
+  Ry = (Y + layout[0].Y - 0.5*DY)/expand + 0.5*dy;
+
+  i_start = MIN (MAX (Rx, 0), dx - expand_out + 1);
+  j_start = MIN (MAX (Ry, 0), dy - expand_out + 1);
+  
+  if (layout[0].expand > 0) {
+    i_end = MAX (MIN (i_start + ((int)(expand*(dx-i_start)))/expand, expand_out*(DX-X) + Rx), 0);
+    j_end = MAX (MIN (j_start + ((int)(expand*(dy-j_start)))/expand, expand_out*(DY-Y) + Ry), 0);
+  } else {
+    i_end = MAX (MIN (dx, (DX-X)/expand + Rx), 0);
+    j_end = MAX (MIN (dy, (DY-Y)/expand + Ry), 0);
+  }    
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  data = out_pix = (unsigned char *) layout[0].picture.data;
+  in_pix  = (unsigned char *) (matrix[0].buffer) + DX*(int)MAX(Y,0) + (int)MAX(X,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < j_start; j++) {
+    for (i = 0; i < dx; i++, out_pix+=2) {
+      out_pix[0] = white1;
+      out_pix[1] = white2;
+    }
+  }
+  
+  for (j = j_start; j < j_end; j+= expand_out, in_pix += expand_in*DX) {
+    out_pix = &data[2*j*dx];
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
+      out_pix2 = out_pix + 2*jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2+=2) {
+	out_pix2[0] = white1;
+	out_pix2[1] = white2;
+      }
+    }
+    out_pix += 2*i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix+=2) {
+	out_pix[0] = pixel1[*in_pix2];
+	out_pix[1] = pixel2[*in_pix2];
+      }
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 2*expand_out) { 
+	pixvalue1 = pixel1[*in_pix2];
+	pixvalue2 = pixel2[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=2*(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2+=2) {
+	    out_pix2[0] = pixvalue1; 
+	    out_pix2[1] = pixvalue2; 
+	  }
+	}
+      }
+    }
+    out_pix -= 2*dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + 2*jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2+=2) {
+	out_pix2[0] = white1;
+	out_pix2[1] = white2;
+      }
+    }
+  } 
+  
+  /*
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= expand_out - (j_end - j_start) % expand_out;
+  */
+  
+  out_pix = &data[2*j_end*dx];
+  /**** fill in top area ****/
+  for (j = 0; j < (dy - j_end); j++) {
+    for (i = 0; i < dx; i++, out_pix+=2) { 
+      out_pix[0] = white1;
+      out_pix[1] = white2;
+    }
+  }
+
+  layout[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					layout[0].picture.data, layout[0].picture.dx, layout[0].picture.dy, 16, 0);
+}
+
Index: /tags/start/Ohana/src/kii/picture/Remap24.c
===================================================================
--- /tags/start/Ohana/src/kii/picture/Remap24.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/picture/Remap24.c	(revision 12606)
@@ -0,0 +1,163 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+void Remap24 (Graphic *graphic, Layout *layout, Matrix *matrix) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback, extra;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, Rx, Ry, X, Y;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  unsigned char *in_pix,  *in_pix2;
+  unsigned char pixel1[256], pixel2[256], pixel3[256];
+  unsigned char pixvalue1, pixvalue2, pixvalue3;
+  unsigned long white;
+  unsigned char white1, white2, white3;
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel1[i] = 0x0000ff & layout[0].cmap[i].pixel;
+    pixel2[i] = 0x0000ff & (layout[0].cmap[i].pixel >> 8);
+    pixel3[i] = 0x0000ff & (layout[0].cmap[i].pixel >> 16);
+  }
+  white = layout[0].white;
+  white1 = 0x0000ff & white;
+  white2 = 0x0000ff & (white >> 8);
+  white3 = 0x0000ff & (white >> 16);
+
+  if (layout[0].expand == 0) /* set up expansions */
+    layout[0].expand = 1;
+  if (layout[0].expand > 0) {
+    expand = 1 / (1.0*layout[0].expand);
+    expand_out = layout[0].expand;
+    expand_in  = 1;
+  }
+  if (layout[0].expand < 0) {
+    expand = fabs((double)layout[0].expand);
+    expand_out = 1;
+    expand_in  = -layout[0].expand;
+  }
+
+  dx = layout[0].picture.dx;
+  dy = layout[0].picture.dy;
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+  extra = 4 - (dx * 3) % 4;
+
+  /* X,Y are the image coordinates of the first image pixel */
+  X = MAX(0.5*(DX - dx*expand) - layout[0].X, 0);
+  if ((int)X != X) 
+    X = (int) X + 1;
+  else 
+    X = (int) X;
+  Y = MAX(0.5*(DY - dy*expand) - layout[0].Y, 0);
+  if ((int)Y != Y) 
+    Y = (int) Y + 1;
+  else 
+    Y = (int) Y;
+
+  /* Rx,Ry are the screen coordinates of the first image pixel */
+  Rx = (X + layout[0].X - 0.5*DX)/expand + 0.5*dx;
+  Ry = (Y + layout[0].Y - 0.5*DY)/expand + 0.5*dy;
+
+  i_start = MIN (MAX (Rx, 0), dx - expand_out + 1);
+  j_start = MIN (MAX (Ry, 0), dy - expand_out + 1);
+  
+  if (layout[0].expand > 0) {
+    i_end = MAX (MIN (i_start + ((int)(expand*(dx-i_start)))/expand, expand_out*(DX-X) + Rx), 0);
+    j_end = MAX (MIN (j_start + ((int)(expand*(dy-j_start)))/expand, expand_out*(DY-Y) + Ry), 0);
+  } else {
+    i_end = MAX (MIN (dx, (DX-X)/expand + Rx), 0);
+    j_end = MAX (MIN (dy, (DY-Y)/expand + Ry), 0);
+  }    
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  data = out_pix = (unsigned char *) layout[0].picture.data;
+  in_pix  = (unsigned char *) (matrix[0].buffer) + DX*(int)MAX(Y,0) + (int)MAX(X,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < j_start; j++) {
+    for (i = 0; i < dx; i++, out_pix+=3) {
+      out_pix[0] = white1;
+      out_pix[1] = white2;
+      out_pix[2] = white3;
+    }
+    out_pix += extra;
+  }
+  
+  for (j = j_start; j < j_end; j+= expand_out, in_pix += expand_in*DX) {
+    out_pix = &data[j*(3*dx+extra)];
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
+      out_pix2 = out_pix + jj*(3*dx + extra);
+      for (i = 0; i < i_start; i++, out_pix2+=3) {
+	out_pix2[0] = white1;
+	out_pix2[1] = white2;
+	out_pix2[2] = white3;
+      }
+    }
+    out_pix += 3*i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix+=3) {
+	out_pix[0] = pixel1[*in_pix2];
+	out_pix[1] = pixel2[*in_pix2];
+	out_pix[2] = pixel3[*in_pix2];
+      }
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 3*expand_out) { 
+	pixvalue1 = pixel1[*in_pix2];
+	pixvalue2 = pixel2[*in_pix2];
+	pixvalue3 = pixel3[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=3*(dx-expand_out)+extra) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2+=3) {
+	    out_pix2[0] = pixvalue1; 
+	    out_pix2[1] = pixvalue2; 
+	    out_pix2[2] = pixvalue3; 
+	  }
+	}
+      }
+    }
+    out_pix -= 3*dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*(3*dx+extra);
+      for (i = i_end; i < dx; i++, out_pix2+=3) {
+	out_pix2[0] = white1;
+	out_pix2[1] = white2;
+	out_pix2[2] = white3;
+      }
+    }
+  } 
+  
+  /*
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= expand_out - (j_end - j_start) % expand_out;
+  */
+  
+  out_pix = &data[j_end*(3*dx+extra)];
+  /**** fill in top area ****/
+  for (j = 0; j < (dy - j_end); j++) {
+    for (i = 0; i < dx; i++, out_pix+=3) { 
+      out_pix[0] = white1;
+      out_pix[1] = white2;
+      out_pix[2] = white3;
+    }
+    out_pix+=extra;
+  }
+
+  layout[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					layout[0].picture.data, layout[0].picture.dx, layout[0].picture.dy, 32, 0);
+}
+
Index: /tags/start/Ohana/src/kii/picture/Remap32.c
===================================================================
--- /tags/start/Ohana/src/kii/picture/Remap32.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/picture/Remap32.c	(revision 12606)
@@ -0,0 +1,131 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+void Remap32 (Graphic *graphic, Layout *layout, Matrix *matrix) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, Rx, Ry, X, Y;
+  int expand_in, expand_out;
+  unsigned int *out_pix, *out_pix2;
+  unsigned char *in_pix,  *in_pix2;
+  unsigned long pixel[256], pixvalue;
+  unsigned long white;
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel[i] = layout[0].cmap[i].pixel;
+  }
+  white = layout[0].white;
+
+  if (layout[0].expand == 0) /* set up expansions */
+    layout[0].expand = 1;
+  if (layout[0].expand > 0) {
+    expand = 1 / (1.0*layout[0].expand);
+    expand_out = layout[0].expand;
+    expand_in  = 1;
+  }
+  if (layout[0].expand < 0) {
+    expand = fabs((double)layout[0].expand);
+    expand_out = 1;
+    expand_in  = -layout[0].expand;
+  }
+
+  dx = layout[0].picture.dx;
+  dy = layout[0].picture.dy;
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+  /* X,Y are the image coordinates of the first image pixel */
+  X = MAX(0.5*(DX - dx*expand) - layout[0].X, 0);
+  if ((int)X != X) 
+    X = (int) X + 1;
+  else 
+    X = (int) X;
+  Y = MAX(0.5*(DY - dy*expand) - layout[0].Y, 0);
+  if ((int)Y != Y) 
+    Y = (int) Y + 1;
+  else 
+    Y = (int) Y;
+
+  /* Rx,Ry are the screen coordinates of the first image pixel */
+  Rx = (X + layout[0].X - 0.5*DX)/expand + 0.5*dx;
+  Ry = (Y + layout[0].Y - 0.5*DY)/expand + 0.5*dy;
+
+  i_start = MIN (MAX (Rx, 0), dx - expand_out + 1);
+  j_start = MIN (MAX (Ry, 0), dy - expand_out + 1);
+  
+  if (layout[0].expand > 0) {
+    i_end = MAX (MIN (i_start + ((int)(expand*(dx-i_start)))/expand, expand_out*(DX-X) + Rx), 0);
+    j_end = MAX (MIN (j_start + ((int)(expand*(dy-j_start)))/expand, expand_out*(DY-Y) + Ry), 0);
+  } else {
+    i_end = MAX (MIN (dx, (DX-X)/expand + Rx), 0);
+    j_end = MAX (MIN (dy, (DY-Y)/expand + Ry), 0);
+  }    
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  out_pix = (unsigned int *) layout[0].picture.data;
+  in_pix  = (unsigned char *) (matrix[0].buffer) + DX*(int)MAX(Y,0) + (int)MAX(X,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < dx*j_start; j++, out_pix++) 
+    *out_pix = white;
+  
+  for (j = j_start; j < j_end; j+= expand_out, out_pix+=(expand_out-1)*dx, in_pix += expand_in*DX) {
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
+      out_pix2 = out_pix + jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2++) {
+	*out_pix2 = white;
+      }
+    }
+    out_pix += i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix++) {
+	*out_pix = pixel[*in_pix2];
+      }
+      /* *out_pix = *(pixel + *in_pix2);  */
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= expand_out) { 
+	pixvalue = pixel[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2++) {
+	    *out_pix2 = pixvalue;
+	  }
+	}
+      }
+    }
+    out_pix -= dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2++) {
+	*out_pix2 = white;
+      }
+    }
+    out_pix += (dx - i_end);
+    
+  } 
+  
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= expand_out - (j_end - j_start) % expand_out;
+  
+  /**** fill in top area ****/
+  for (j = 0; (j < dx*(dy - j_end)) && (out_pix - (unsigned int *)layout[0].picture.data < dx*dy); j++, out_pix++) { 
+    *out_pix = white;
+  }
+  layout[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					layout[0].picture.data, layout[0].picture.dx, layout[0].picture.dy, 32, 0);
+}
+
Index: /tags/start/Ohana/src/kii/picture/Remap8.c
===================================================================
--- /tags/start/Ohana/src/kii/picture/Remap8.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/picture/Remap8.c	(revision 12606)
@@ -0,0 +1,131 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+void Remap8 (Graphic *graphic, Layout *layout, Matrix *matrix) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, Rx, Ry, X, Y;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2;
+  unsigned char *in_pix,  *in_pix2;
+  unsigned long pixel[256], pixvalue;
+  unsigned long white;
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel[i] = layout[0].cmap[i].pixel;
+  }
+  white = layout[0].white;
+
+  if (layout[0].expand == 0) /* set up expansions */
+    layout[0].expand = 1;
+  if (layout[0].expand > 0) {
+    expand = 1 / (1.0*layout[0].expand);
+    expand_out = layout[0].expand;
+    expand_in  = 1;
+  }
+  if (layout[0].expand < 0) {
+    expand = fabs((double)layout[0].expand);
+    expand_out = 1;
+    expand_in  = -layout[0].expand;
+  }
+
+  dx = layout[0].picture.dx;
+  dy = layout[0].picture.dy;
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+  /* X,Y are the image coordinates of the first image pixel */
+  X = MAX(0.5*(DX - dx*expand) - layout[0].X, 0);
+  if ((int)X != X) 
+    X = (int) X + 1;
+  else 
+    X = (int) X;
+  Y = MAX(0.5*(DY - dy*expand) - layout[0].Y, 0);
+  if ((int)Y != Y) 
+    Y = (int) Y + 1;
+  else 
+    Y = (int) Y;
+
+  /* Rx,Ry are the screen coordinates of the first image pixel */
+  Rx = (X + layout[0].X - 0.5*DX)/expand + 0.5*dx;
+  Ry = (Y + layout[0].Y - 0.5*DY)/expand + 0.5*dy;
+
+  i_start = MIN (MAX (Rx, 0), dx - expand_out + 1);
+  j_start = MIN (MAX (Ry, 0), dy - expand_out + 1);
+  
+  if (layout[0].expand > 0) {
+    i_end = MAX (MIN (i_start + ((int)(expand*(dx-i_start)))/expand, expand_out*(DX-X) + Rx), 0);
+    j_end = MAX (MIN (j_start + ((int)(expand*(dy-j_start)))/expand, expand_out*(DY-Y) + Ry), 0);
+  } else {
+    i_end = MAX (MIN (dx, (DX-X)/expand + Rx), 0);
+    j_end = MAX (MIN (dy, (DY-Y)/expand + Ry), 0);
+  }    
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  out_pix = layout[0].picture.data;
+  in_pix  = (unsigned char *) (matrix[0].buffer) + DX*(int)MAX(Y,0) + (int)MAX(X,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < dx*j_start; j++, out_pix++) 
+    *out_pix = white;
+  
+  for (j = j_start; j < j_end; j+= expand_out, out_pix+=(expand_out-1)*dx, in_pix += expand_in*DX) {
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
+      out_pix2 = out_pix + jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2++) {
+	*out_pix2 = white;
+      }
+    }
+    out_pix += i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix++) {
+	*out_pix = pixel[*in_pix2];
+      }
+      /* *out_pix = *(pixel + *in_pix2);  */
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= expand_out) { 
+	pixvalue = pixel[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2++) {
+	    *out_pix2 = pixvalue;
+	  }
+	}
+      }
+    }
+    out_pix -= dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2++) {
+	*out_pix2 = white;
+      }
+    }
+    out_pix += (dx - i_end);
+    
+  } 
+  
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= expand_out - (j_end - j_start) % expand_out;
+  
+  /**** fill in top area ****/
+  for (j = 0; (j < dx*(dy - j_end)) && (out_pix - (unsigned char *)layout[0].picture.data < dx*dy); j++, out_pix++) { 
+    *out_pix = white;
+  }
+  layout[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					layout[0].picture.data, layout[0].picture.dx, layout[0].picture.dy, 8, 0);
+}
+
Index: /tags/start/Ohana/src/kii/picture/Reorient.c
===================================================================
--- /tags/start/Ohana/src/kii/picture/Reorient.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/picture/Reorient.c	(revision 12606)
@@ -0,0 +1,65 @@
+# include "Ximage.h"
+
+void Reorient (Graphic *graphic, Layout *layout, XButtonEvent *mouse_event) {
+
+  int x, y, dummy2;
+  double X0, Y0;
+  unsigned int dummy3;
+  Window dummy1;
+
+  if (layout[0].expand == 0)
+    layout[0].expand = 1;
+
+  Screen_to_Image (&X0, &Y0, (double)mouse_event[0].x, (double)mouse_event[0].y, layout);
+  X0 = 0.5*layout[0].matrix.Naxis[0] - X0;
+  Y0 = 0.5*layout[0].matrix.Naxis[1] - Y0;
+
+  switch (mouse_event[0].button) {
+  case 1:
+    if ((layout[0].X != X0) || (layout[0].Y != Y0)) {
+      layout[0].X = X0;
+      layout[0].Y = Y0;
+    }
+    break;
+  case 2: 
+    layout[0].expand--;
+    if ((layout[0].expand == 0) || (layout[0].expand == -1))
+      layout[0].expand = -2;
+    if (layout[0].expand < -30) {
+      fprintf (stderr, "can't get smaller!\n");
+      layout[0].expand = -30;
+      return;
+    }
+    layout[0].X = X0;
+    layout[0].Y = Y0;
+    break;
+  case 3:
+    layout[0].expand++;
+    if ((layout[0].expand == 0) || (layout[0].expand == -1))
+      layout[0].expand = 1;
+    if (layout[0].expand > 30) {
+      fprintf (stderr, "can't get bigger!\n");
+      layout[0].expand = 30;
+      return;
+    }
+    layout[0].X = X0;
+    layout[0].Y = Y0;
+    break;
+  }
+
+  Remap (graphic, layout, &layout[0].matrix);
+  Refresh (graphic, layout, 0);
+ 
+# ifndef NOWARP  /* the "warp" function seems to be a problem on SUNs for some reason */
+  XQueryPointer (graphic[0].display, graphic[0].window, &dummy1, &dummy1, &dummy2, &dummy2, &x, &y, &dummy3); 
+  if ((x > layout[0].picture.x) && (x < layout[0].picture.x + layout[0].picture.dx) &&
+      (y > layout[0].picture.y) && (y < layout[0].picture.y + layout[0].picture.dy) &&
+      ((mouse_event[0].button == 2) || (mouse_event[0].button == 3))) {
+    XWarpPointer (graphic[0].display, None, graphic[0].window, 0, 0, 0, 0, 
+		  layout[0].picture.x + 0.5*layout[0].picture.dx,
+		  layout[0].picture.y + 0.5*layout[0].picture.dy);
+  }
+# endif
+
+  XFlush (graphic[0].display);
+}
Index: /tags/start/Ohana/src/kii/picture/Rescale.c
===================================================================
--- /tags/start/Ohana/src/kii/picture/Rescale.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/picture/Rescale.c	(revision 12606)
@@ -0,0 +1,16 @@
+# include "Ximage.h"
+
+void
+Rescale (graphic, layout)
+Graphic graphic[];
+Layout  layout[];
+{
+
+  fprintf (stdout, "enter new zero, range: ");
+  fscanf (stdin, "%lf%lf", &layout[0].zero, &layout[0].range);
+
+  Remap (graphic, layout, &layout[0].matrix);
+  Refresh (graphic, layout, 0);
+  
+  XFlush (graphic[0].display);
+}
Index: /tags/start/Ohana/src/kii/picture/Resize.c
===================================================================
--- /tags/start/Ohana/src/kii/picture/Resize.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/picture/Resize.c	(revision 12606)
@@ -0,0 +1,42 @@
+# include "Ximage.h"
+# define SCAN \
+  status = read (layout[0].Ximage, buffer, 16); \
+  buffer[16] = 0; \
+  sscanf (buffer, "%*s %d", &Nbytes); \
+  status = read (layout[0].Ximage, buffer, Nbytes); \
+  buffer[status] = 0; /* make the string easy to parse */ \
+  (DEBUG) && fprintf (stderr, "buffer: <%s>\n", buffer); \
+
+
+int Resize (Graphic *graphic, Layout *layout) {
+ 
+  int status, Nbytes;
+  unsigned int NX, NY;
+  char buffer[128];
+
+  SCAN;
+  sscanf (buffer, "%d %d", &NX, &NY);
+
+  NX += ZOOM_X + 3*PAD1 + 25;
+  NY += 2*PAD1 + PAD2 + COLORPAD + 25;
+
+  if ((graphic[0].dx == NX) && (graphic[0].dy == NY)) 
+    return (TRUE);
+
+  /*  graphic[0].dx = MAX(NX,  MIN_WIDTH); 
+  graphic[0].dy = MAX(NY, MIN_HEIGHT); */
+  graphic[0].dx = MAX(NX, 50); 
+  graphic[0].dy = MAX(NY, 50); 
+
+  XResizeWindow (graphic[0].display, graphic[0].window, NX, NY);
+
+  PositionPictures (layout, graphic);
+  CreateColorbar (layout, graphic);
+  CreatePicture (layout, graphic);
+  Remap (graphic, layout, &layout[0].matrix); 
+
+  XClearWindow (graphic[0].display, graphic[0].window);
+  Refresh (graphic, layout, 1);
+
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/kii/picture/StatusBox.c
===================================================================
--- /tags/start/Ohana/src/kii/picture/StatusBox.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/picture/StatusBox.c	(revision 12606)
@@ -0,0 +1,27 @@
+# include "Ximage.h"
+
+void
+StatusBox (graphic, layout)
+Graphic        graphic[];
+Layout         layout[];
+{
+
+  double  x, y, z;
+
+  if (MOVE_POINTER) {
+    x = 0.5*layout[0].matrix.Naxis[0];
+    y = 0.5*layout[0].matrix.Naxis[1];
+    z = -1;
+    layout[0].x = x;
+    layout[0].y = y;
+    layout[0].z = z;
+  }
+  else {
+    x = layout[0].x;
+    y = layout[0].y;
+    z = layout[0].z;
+  }
+  
+  UpdateStatusBox (graphic, layout, x, y, z, 1);
+  
+}
Index: /tags/start/Ohana/src/kii/picture/TestPicture.c
===================================================================
--- /tags/start/Ohana/src/kii/picture/TestPicture.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/picture/TestPicture.c	(revision 12606)
@@ -0,0 +1,59 @@
+# include "Ximage.h"
+
+int 
+TestPicture (graphic, layout)
+     Graphic graphic[];
+     Layout  layout[];
+{
+
+  Header header;
+  char buffer[1024], *buff;
+  int status, bytes_left, Nbytes, i, j;
+  double frac;
+
+  fits_free_matrix (&layout[0].matrix);
+
+  header.Naxes = 2;
+  header.Naxis[0] = 512;
+  header.Naxis[1] = 512;
+  header.bitpix = 8;
+  header.unsign = 0;
+  header.bzero = 0;
+  header.bscale = 1;
+
+  layout[0].zero = 0;
+  layout[0].range = layout[0].Npixels;
+  layout[0].min = 0; 
+  layout[0].max = layout[0].Npixels;
+  
+  fits_create_matrix (&header, &layout[0].matrix);
+
+  frac = layout[0].Npixels / (512.0*512.0);
+  buff = layout[0].matrix.buffer;
+  for (i = 0; i < 512; i++) {
+    for (j = 0; j < 512; j++, buff++) {
+      *buff = (int)(i*j*frac);
+    }
+  }
+
+/*
+  Remap (layout, &layout[0].matrix);
+  layout[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					layout[0].picture.data, 
+					layout[0].picture.dx, layout[0].picture.dy, 8, 0);
+
+  (DEBUG) && fprintf (stderr, "remapped image\n", layout[0].matrix.size);
+  Refresh (graphic, layout);
+  
+  (DEBUG) && fprintf (stderr, "refreshed\n", layout[0].matrix.size);
+  XFlush (graphic[0].display);
+*/
+}
+
+
+/*
+   layout[0].X = 0;
+   layout[0].Y = 0;
+   layout[0].expand = 1;
+*/
+  
Index: /tags/start/Ohana/src/kii/picture/cursor.c
===================================================================
--- /tags/start/Ohana/src/kii/picture/cursor.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/picture/cursor.c	(revision 12606)
@@ -0,0 +1,86 @@
+# include "Ximage.h"
+
+int cursor (Graphic *graphic, Layout *layout) {
+
+  XEvent          event;
+  KeySym          keysym;
+  int             status, xstatus, value;
+  XComposeStatus  composestatus;
+  char            string[10], line[500];
+  double          x, y;
+  char            buffer[1024];
+  
+  while (1) {
+    
+    status = read (layout[0].Ximage, buffer, 4);
+    buffer[4] = 0;
+    
+    switch (status) {
+    case -1:
+      /* no input from pipe: continue */
+      break;
+      
+    case 0:
+      fprintf (stderr, "pipe has died!\n");
+      return (FALSE);
+      break;
+
+    case 4:
+      if (!strcmp (buffer, "NCUR")) {  /* stop reading cursor */
+	return (TRUE);
+      }
+      break;
+
+    default:
+      fprintf (stderr, "weird signal: too many or few bytes!  %d\n", status);
+      return (TRUE);
+      break;
+    }
+
+    if ((xstatus = XCheckMaskEvent (graphic[0].display, EVENT_MASK, &event))) {
+      
+      switch (event.type)  {
+	
+      case ButtonPress:
+	status = InterpretPresses (graphic, layout, (XButtonEvent *) &event);
+	break;
+	
+      case Expose:
+	if (event.xexpose.count == 0)
+	  Refresh (graphic, layout, 1);
+	break;
+	
+      case ConfigureNotify:
+	status =  Reconfig (graphic, layout, &event);
+	break;
+	
+      case MappingNotify:
+	XRefreshKeyboardMapping ((XMappingEvent *) &event);
+	break;
+	
+      case MotionNotify:
+	if (XPending (graphic[0].display) < 2) {
+	  UpdatePointer (graphic, layout, (XMotionEvent *) &event);
+	}
+	break;
+
+      case KeyPress:
+	value = XLookupString ((XKeyEvent *) &event, string, 9, &keysym, &composestatus);
+
+	if ((event.xkey.x >= layout[0].picture.x) && (event.xkey.x <= layout[0].picture.x + layout[0].picture.dx) &&
+	    (event.xkey.y >= layout[0].picture.y) && (event.xkey.y <= layout[0].picture.y + layout[0].picture.dy)) {
+
+	  Screen_to_Image (&x, &y, (double)event.xkey.x, (double)event.xkey.y, layout);
+
+	  if (isprint(string[0]))
+	    sprintf (line, "%c %6.1f %6.1f ", string[0], x, y);
+	  else {
+	    sprintf (line, "X %6.1f %6.1f ", x, y);
+	    break;
+	  }
+	  write (layout[0].Ximage, line, 16);
+	}
+      }
+    }
+  }
+}
Index: /tags/start/Ohana/src/kii/scrollbar/DownArrow.c
===================================================================
--- /tags/start/Ohana/src/kii/scrollbar/DownArrow.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/scrollbar/DownArrow.c	(revision 12606)
@@ -0,0 +1,20 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int 
+DownArrow (button_event, height, width, SB_x, SB_y)
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+{
+
+  int answer, m_x, m_y;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_y > (height - SB_y)) && 
+	    (m_x > (width - SB_y)));
+    return (answer);
+
+}
+
+
Index: /tags/start/Ohana/src/kii/scrollbar/LeftArrow.c
===================================================================
--- /tags/start/Ohana/src/kii/scrollbar/LeftArrow.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/scrollbar/LeftArrow.c	(revision 12606)
@@ -0,0 +1,18 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int
+LeftArrow (button_event, height, width, SB_x, SB_y) 
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+{
+
+  int answer, m_x, m_y;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_x < SB_x) && (m_y < SB_x));
+  return (answer);
+
+}
+
Index: /tags/start/Ohana/src/kii/scrollbar/RightArrow.c
===================================================================
--- /tags/start/Ohana/src/kii/scrollbar/RightArrow.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/scrollbar/RightArrow.c	(revision 12606)
@@ -0,0 +1,20 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int
+RightArrow (button_event, height, width, SB_x, SB_y) 
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+{
+
+  int answer, m_x, m_y;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_x < SB_x) && 
+	    (m_y > (height - SB_x - SB_y)) && 
+	    (m_y < (height - SB_y)));
+  return (answer);
+
+}
+
Index: /tags/start/Ohana/src/kii/scrollbar/ScrollBars.c
===================================================================
--- /tags/start/Ohana/src/kii/scrollbar/ScrollBars.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/scrollbar/ScrollBars.c	(revision 12606)
@@ -0,0 +1,38 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+void
+ScrollBars (display, window, gc, height, width, SB_x, SB_y, f_x, f_y)
+Display *display;
+Window window;
+GC gc;
+int width, height, SB_x, SB_y;
+double f_x, f_y;
+{
+  
+  int x, y;
+
+  y = height - SB_y;
+  XDrawLine (display, window, gc, 0, y, width, y);
+  XDrawLine (display, window, gc, SB_x, 0, SB_x, height);
+  XDrawLine (display, window, gc, 0, SB_x, SB_x, SB_x);
+  x = width - SB_y;
+  y = height - SB_y;
+  XDrawLine (display, window, gc, x, y, x, height);
+  y = height - SB_x - SB_y;
+  XDrawLine (display, window, gc, 0, y, SB_x, y);
+  x = SB_y + SB_x;
+  y = height - SB_y;
+  XDrawLine (display, window, gc, x, y, x, height);
+  x = (width - 2*SB_y - SB_x) * f_x + SB_x + SB_y;
+  y = (height - 2*SB_x - SB_y) * f_y + SB_x;
+  XDrawLine (display, window, gc, x, height - SB_y, x, height);
+  XDrawLine (display, window, gc, x + 1, height - SB_y, x + 1, height);
+  XDrawLine (display, window, gc, 0, y, SB_x, y);
+  XDrawLine (display, window, gc, 0, y+1, SB_x, y+1);
+  y = height - SB_y;
+  XFillRectangle (display, window, gc, 0, y, SB_x, SB_y);
+
+}
+
+
Index: /tags/start/Ohana/src/kii/scrollbar/UpArrow.c
===================================================================
--- /tags/start/Ohana/src/kii/scrollbar/UpArrow.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/scrollbar/UpArrow.c	(revision 12606)
@@ -0,0 +1,20 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int
+UpArrow (button_event, height, width, SB_x, SB_y) 
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+{
+
+  int answer, m_x, m_y;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_y > (height - SB_y)) && 
+	    (m_x > SB_x) && 
+	    (m_x < (SB_x + SB_y)));
+  return (answer);
+
+}
+
Index: /tags/start/Ohana/src/kii/scrollbar/xScrollBar.c
===================================================================
--- /tags/start/Ohana/src/kii/scrollbar/xScrollBar.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/scrollbar/xScrollBar.c	(revision 12606)
@@ -0,0 +1,26 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int 
+xScrollBar (button_event, height, width, SB_x, SB_y, f)
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+double *f;
+{
+
+  int answer, m_x, m_y;
+  double f1, f2;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_x < SB_x) && 
+	    (m_y > SB_x) && 
+	    (m_y < (height - SB_x - SB_y)));
+  f1 = (double)(m_y - SB_x);
+  f2 = (double)(height - 2*SB_x - SB_y);
+  *f = f1 / f2;
+  return (answer);
+
+}
+
+
Index: /tags/start/Ohana/src/kii/scrollbar/yScrollBar.c
===================================================================
--- /tags/start/Ohana/src/kii/scrollbar/yScrollBar.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/scrollbar/yScrollBar.c	(revision 12606)
@@ -0,0 +1,26 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int
+yScrollBar (button_event, height, width, SB_x, SB_y, f)
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+double *f;
+{
+
+  int answer, m_x, m_y;
+  double f1, f2;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_y > (height - SB_y)) && 
+	    (m_x > (SB_x + SB_y)) && 
+	    (m_x < (width - SB_y)));
+  f1 = (double)(m_x - SB_x - SB_y);
+  f2 = (double)(width - 2*SB_y - SB_x);
+  *f = f1 / f2;
+  return (answer);
+
+}
+
+	
Index: /tags/start/Ohana/src/kii/setup/CheckColors.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/CheckColors.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/CheckColors.c	(revision 12606)
@@ -0,0 +1,40 @@
+# include "Ximage.h"
+
+/************** CheckColors *************/
+void CheckColors (Graphic *graphic, int *argc, char **argv) {
+
+  char *temp_name;
+  int N;
+
+  /* here we define the values for "black" (blackground) and "white" (whiteground)
+     if -fg, or -bg exist, or if Foreground or Background are set in .Xdefaults, 
+     use those.  blackground defaults to Black, whiteground defaults to White. */
+
+  graphic[0].black = BlackPixel (graphic[0].display, graphic[0].screen);
+  temp_name = XGetDefault (graphic[0].display, argv[0], "Foreground");
+  if ((N = get_argument (*argc, argv, "-fg"))) {
+    if (N + 1 < *argc) {
+      temp_name = argv[N+1];
+    } else {
+      fprintf (stderr, "error: usage is -fg color\n");
+      exit (0);
+    }
+  }
+  if (temp_name != (char *)NULL) 
+    graphic[0].black = GetColor (graphic[0].display, temp_name, graphic[0].colormap, graphic[0].black);
+
+  graphic[0].white = WhitePixel (graphic[0].display, graphic[0].screen);
+  temp_name = XGetDefault (graphic[0].display, argv[0], "Background");
+  if ((N = get_argument (*argc, argv, "-bg"))) {
+    if (N + 1 < *argc) {
+      temp_name = argv[N+1];
+    } else {
+      fprintf (stderr, "error: usage is -bg color\n");
+      exit (0);
+    }
+  }  
+  if (temp_name != (char *)NULL) 
+    graphic[0].white = GetColor (graphic[0].display, temp_name, graphic[0].colormap, graphic[0].white);
+ 
+}
+
Index: /tags/start/Ohana/src/kii/setup/CheckDisplayName.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/CheckDisplayName.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/CheckDisplayName.c	(revision 12606)
@@ -0,0 +1,30 @@
+# include "Ximage.h"
+
+/************** CheckDisplayName *************/
+void CheckDisplayName (int *argc, char **argv, char *display_name) {
+
+  int N;
+
+  display_name[0] = 0;
+  if ((N = get_argument (*argc, argv, "-d"))) {
+    if (N + 1 < *argc) {
+      strcpy (display_name, argv[N + 1]);
+      remove_argument(N, argc, argv);
+      remove_argument(N, argc, argv);
+    } else {
+      fprintf (stderr, "error: usage is [-display/-d] DisplayName\n");
+      exit (0);
+    }
+  }
+  if ((N = get_argument (*argc, argv, "-display"))) {
+    if (N + 1 < *argc) {
+      strcpy (display_name, argv[N + 1]);
+      remove_argument(N, argc, argv);
+      remove_argument(N, argc, argv);
+    } else {
+      fprintf (stderr, "error: usage is [-display/-d] DisplayName\n");
+      exit (0);
+    }
+  }
+}
+
Index: /tags/start/Ohana/src/kii/setup/CheckFontName.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/CheckFontName.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/CheckFontName.c	(revision 12606)
@@ -0,0 +1,29 @@
+# include "Ximage.h"
+
+/************** CheckFontName *************/
+void CheckFontName (int *argc, char **argv, char *fontname) {
+
+  int N;
+
+  if ((N = get_argument (*argc, argv, "-font"))) {
+    if (N + 1 < *argc) {
+      strcpy (fontname, argv[N + 1]);
+      remove_argument(N, argc, argv);
+      remove_argument(N, argc, argv);
+    } else {
+      fprintf (stderr, "error: usage is -font fontname\n");
+      exit (0);
+    }
+  }   
+  if ((N = get_argument (*argc, argv, "-fn"))) {
+    if (N + 1 < *argc) {
+      strcpy (fontname, argv[N + 1]);
+      remove_argument(N, argc, argv);
+      remove_argument(N, argc, argv);
+    } else {
+      fprintf (stderr, "error: usage is -fn fontname\n");
+      exit (0);
+    }
+  }   
+}
+
Index: /tags/start/Ohana/src/kii/setup/CheckGeometry.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/CheckGeometry.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/CheckGeometry.c	(revision 12606)
@@ -0,0 +1,50 @@
+# include "Ximage.h"
+
+/************** CheckGeometry *************/
+void CheckGeometry (int *argc, char **argv, Graphic *graphic) {
+
+  int status, x, y, N;
+  unsigned int dx, dy;
+  int X, Y, dX, dY;
+  char *temp_name;
+  
+  temp_name = XGetDefault (graphic[0].display, argv[0], "geometry");
+  if ((N = get_argument (*argc, argv, "-geom"))) {
+    if (N + 1 < *argc) {
+      temp_name = argv[N+1];
+    }
+    else {
+      fprintf (stderr, "error: usage is -geom DisplayName\n");
+      exit (0);
+    }
+  }
+  X = 10;
+  Y = 10;
+  dX = 512 + 2*PAD1 + PAD1 + ZOOM_X;
+  dY = 512 + 2*PAD1 + PAD2 + COLORPAD;
+  if (temp_name != (char *)NULL) {  
+    status = XParseGeometry (temp_name, &x, &y, &dx, &dy);
+    if (status & XValue)
+      X = x;
+    if (status & YValue)
+      Y = y;
+    if (status & WidthValue) {
+      dX = dx + 2*PAD1 + PAD1 + ZOOM_X;
+      dX = MAX (dX, MIN_WIDTH);
+    }
+    if (status & HeightValue) {
+      dY = dy + 2*PAD1 + PAD2 + COLORPAD + 42;
+      dY = MAX (dY, MIN_HEIGHT);
+    }
+    if (status & XNegative)
+      X  = DisplayWidth  (graphic[0].display, graphic[0].screen) - dX + X;
+    if (status & YNegative)
+      Y  = DisplayHeight (graphic[0].display, graphic[0].screen) - dY + Y;
+  }
+
+  graphic[0].x = X;
+  graphic[0].y = Y;
+  graphic[0].dx = dX;
+  graphic[0].dy = dY; 
+  
+}
Index: /tags/start/Ohana/src/kii/setup/CheckVisual.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/CheckVisual.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/CheckVisual.c	(revision 12606)
@@ -0,0 +1,199 @@
+# include "Ximage.h"
+# define NPIXELS 64
+# define DEBUG 1
+
+/* DirectColor doesn't seem to work, even though it is available:
+   I cannot use XAllocColorCells to get pixels under DirectColor
+*/
+
+/* static int try_visual[] = {5, 3, 1, 4, 2, 0}; */
+
+void CheckVisual (Graphic *graphic, int *argc, char **argv) {
+
+  int i, Nfound, N;
+  int col, def, dyn;
+  XVisualInfo *visual_list, visual_temp;
+  unsigned long planes[3];
+  XPixmapFormatValues *pixmaps;
+  int Npixmaps;
+
+  if (DEBUG) {
+    fprintf (stderr, "DirectColor: %d\n", DirectColor);
+    fprintf (stderr, "PseudoColor: %d\n", PseudoColor);
+    fprintf (stderr, "TrueColor: %d\n", TrueColor);
+    fprintf (stderr, "GrayScale: %d\n", GrayScale);
+    fprintf (stderr, "StaticColor: %d\n", StaticColor);
+    fprintf (stderr, "StaticGray: %d\n", StaticGray);
+  }
+
+  visual_temp.screen = graphic[0].screen;
+  
+  /* find available visuals */
+  visual_list = XGetVisualInfo (graphic[0].display, VisualScreenMask, &visual_temp, &Nfound);
+  if (Nfound == 0) {
+    fprintf (stderr, "error finding useful visual\n");
+    exit (0);
+  }
+  
+  /* check default visual first */ 
+  for (i = 0; (i < Nfound) && (graphic[0].visual != visual_list[i].visual); i++);
+  if (i == Nfound) {
+    fprintf (stderr, "default visual not found??\n");
+    exit (0);
+  }
+
+  col = def = dyn = FALSE;
+  if (DEBUG) fprintf (stderr, "default visual class is %d\n", visual_list[i].class);
+  switch (visual_list[i].class) {
+  case PseudoColor:
+    col = def = dyn = TRUE;
+    graphic[0].visual = visual_list[i].visual;
+    graphic[0].visualclass = TRUE;
+    goto test_pixels;
+    break;
+  default:
+    break;
+  }
+
+  for (i = 0; i < Nfound; i++) {
+    switch (visual_list[i].class) {
+    case PseudoColor:
+      if (DEBUG) fprintf (stderr, "selected visual class is %d\n", visual_list[i].class);
+      col = dyn = TRUE;
+      if (graphic[0].visual == visual_list[i].visual) {
+	def = TRUE;
+      } else {
+	graphic[0].visual = visual_list[i].visual;
+      }
+      graphic[0].visualclass = TRUE;
+      goto test_pixels;
+      break;
+    default:
+      break;
+    }
+  }
+
+  for (i = 0; i < Nfound; i++) {
+    switch (visual_list[i].class) {
+    case GrayScale:
+      if (DEBUG) fprintf (stderr, "selected visual class is %d\n", visual_list[i].class);
+      dyn = TRUE;
+      if (graphic[0].visual == visual_list[i].visual) {
+	def = TRUE;
+      } else {
+	graphic[0].visual = visual_list[i].visual;
+      }
+      graphic[0].visualclass = TRUE;
+      goto test_pixels;
+      break;
+    default:
+      break;
+    }
+  }
+
+  for (i = 0; (i < Nfound) && (visual_list[i].class != TrueColor); i++);
+  if (i != Nfound) {
+    col = TRUE;
+    if (DEBUG) fprintf (stderr, "visual class is %d\n", visual_list[i].class);
+    if (graphic[0].visual == visual_list[i].visual) {
+      def = TRUE;
+    } else {
+      graphic[0].visual = visual_list[i].visual;
+    }
+    graphic[0].visualclass = FALSE;
+    goto test_pixels;
+  }
+
+  for (i = 0; (i < Nfound) && (visual_list[i].class != StaticColor); i++);
+  if (i != Nfound) {
+    if (DEBUG) fprintf (stderr, "visual class is %d\n", visual_list[i].class);
+    if (graphic[0].visual == visual_list[i].visual) {
+      def = TRUE;
+    } else {
+      graphic[0].visual = visual_list[i].visual;
+    }
+    graphic[0].visualclass = FALSE;
+    goto test_pixels;
+  }
+
+  for (i = 0; (i < Nfound) && (visual_list[i].class != StaticGray); i++);
+  if (i != Nfound) {
+    if (DEBUG) fprintf (stderr, "visual class is %d\n", visual_list[i].class);
+    if (graphic[0].visual == visual_list[i].visual) {
+      def = TRUE;
+    } else {
+      graphic[0].visual = visual_list[i].visual;
+    }
+    graphic[0].visualclass = FALSE;
+    goto test_pixels;
+  }
+
+  test_pixels:
+
+  /* need to make a colormap if 
+     1) the selected visual is not the default 
+     2) there are not enough colors available */
+
+  /* NEED TO ADD A COUPLE LINES DEFINING THE VARIOUS HARD COLORS (BLACK, WHITE, AND THE OVERLAYS) */
+
+  if ((N = get_argument (*argc, argv, "-private"))) {
+    remove_argument(N, argc, argv);
+    def = FALSE;
+  } 
+
+  if (!def) {
+    graphic[0].colormap = XCreateColormap (graphic[0].display, RootWindow (graphic[0].display, graphic[0].screen), graphic[0].visual, AllocNone);
+  }
+
+  if (dyn) {
+    /* allocate color cells  */
+    for (graphic[0].Npixels = NPIXELS;
+	 ((graphic[0].Npixels >= 16) && 
+	  !XAllocColorCells (graphic[0].display, graphic[0].colormap, FALSE, planes, 1, graphic[0].pixels, graphic[0].Npixels));
+	 graphic[0].Npixels -= 4) {
+      if (DEBUG) fprintf (stderr, "trying %d colors\n", (int) graphic[0].Npixels);
+    }
+
+
+    /* make private colormap  */
+    if (graphic[0].Npixels < 16) {
+      fprintf (stderr, "can't allocate enough cells, using private colormap\n");
+      graphic[0].colormap = XCreateColormap (graphic[0].display, RootWindow (graphic[0].display, graphic[0].screen), graphic[0].visual, AllocNone);
+      for (graphic[0].Npixels = NPIXELS;
+	   ((graphic[0].Npixels >= 16) && 
+	    !XAllocColorCells (graphic[0].display, graphic[0].colormap, FALSE, planes, 1, graphic[0].pixels, graphic[0].Npixels));
+	   graphic[0].Npixels -= 4);
+
+      if ((N = get_argument (*argc, argv, "-colorcount"))) {
+	fprintf (stderr, "kii can grab %d colors\n", (int) graphic[0].Npixels);
+	exit (0);
+      } 
+      if (graphic[0].Npixels < 16) {
+	fprintf (stderr, "can't even allocate enough cells in private colormap\n");
+	exit (0);
+      }
+    }
+  }
+
+  if (!dyn) {
+    graphic[0].Npixels = 256;
+    fprintf (stderr, "can't use dynamic colors, color scrollbar inactive\n");
+    fprintf (stderr, " this can be avoided by using a dynamic visual class\n");
+    fprintf (stderr, " (see Kii help page for details)\n");
+  }
+
+  if ((N = get_argument (*argc, argv, "-colorcount"))) {
+    fprintf (stderr, "kii can grab %d colors\n", (int) graphic[0].Npixels);
+    exit (0);
+  } 
+  
+  pixmaps = XListPixmapFormats (graphic[0].display, &Npixmaps);
+  for (i = 0; i < Npixmaps; i++) {
+    if (pixmaps[i].depth == graphic[0].depth) {
+      graphic[0].Nbits = pixmaps[i].bits_per_pixel;
+    }
+  }
+  
+
+}
+
Index: /tags/start/Ohana/src/kii/setup/CloseDisplay.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/CloseDisplay.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/CloseDisplay.c	(revision 12606)
@@ -0,0 +1,14 @@
+# include "Ximage.h"
+
+/************** CloseDisplay *************/
+void
+CloseDisplay (graphic)
+Graphic *graphic;
+{
+  XFreeGC (graphic[0].display, graphic[0].gc);
+  XDestroySubwindows (graphic[0].display, graphic[0].window);
+  XDestroyWindow (graphic[0].display, graphic[0].window);
+  XFlush (graphic[0].display);
+  XCloseDisplay (graphic[0].display);
+}
+
Index: /tags/start/Ohana/src/kii/setup/CreateWindow.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/CreateWindow.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/CreateWindow.c	(revision 12606)
@@ -0,0 +1,33 @@
+# include "Ximage.h"
+
+/************** CreateWindow *************/
+void
+CreateWindow (graphic, parent, border, events)
+Graphic       graphic[];
+Window        parent;
+int           border;
+long          events;
+{
+
+  XSetWindowAttributes attributes;
+  unsigned long attribute_mask;
+
+  attributes.background_pixel = graphic[0].white;
+  attributes.border_pixel     = graphic[0].black;
+  attributes.event_mask       = events;
+  attributes.colormap         = graphic[0].colormap;
+  attribute_mask              = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;
+
+  graphic[0].window = XCreateWindow (graphic[0].display, parent, 
+				     graphic[0].x, graphic[0].y, 
+				     graphic[0].dx, graphic[0].dy, 
+				     border, graphic[0].depth,
+				     InputOutput, graphic[0].visual, 
+				     attribute_mask, &attributes);
+
+  if (graphic[0].window == (Window) None)
+    QuitX (graphic[0].display, "", "error: could not open window");
+
+  XSelectInput (graphic[0].display, graphic[0].window, events);
+}
+
Index: /tags/start/Ohana/src/kii/setup/DefineLayout.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/DefineLayout.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/DefineLayout.c	(revision 12606)
@@ -0,0 +1,69 @@
+# include "Ximage.h"
+
+void DefineLayout (Layout *layout, Graphic *graphic, int argc, char **argv) {
+
+  int i, status, N;
+  struct sockaddr_un Address;
+  char temp[100];
+
+  DEBUG = FALSE;
+  if ((N = get_argument (argc, argv, "-debug"))) {
+    remove_argument(N, &argc, argv);
+    DEBUG = TRUE;
+  }
+
+  /** initiate connection with mana **/
+  if (!DEBUG) {	
+    if (argc < 2) {
+      fprintf (stderr, "socket path not specified\n");
+      exit (0);
+    }
+    strcpy (Address.sun_path, argv[1]);
+    Address.sun_family = AF_UNIX;
+    layout[0].Ximage = socket (AF_UNIX, SOCK_STREAM, 0);
+    status = connect (layout[0].Ximage, (struct sockaddr *) &Address, (socklen_t) sizeof (Address));
+    if (status < 0) {
+      fprintf (stderr, "kii - unsuccessful connection: %d\n", status);
+      exit (0);
+    }
+    fcntl (layout[0].Ximage, F_SETFL, O_NONBLOCK);  
+    sprintf (temp, "rm -f %s", argv[1]);
+    system (temp);
+  }
+
+  PositionPictures (layout, graphic);
+  
+  /* get the display colors */
+  MakeColormap (graphic, layout, argc, argv);
+
+  /** set up a bunch of default things **/
+  layout[0].X = layout[0].Y = 0;
+  layout[0].expand = 1;
+  layout[0].zero = 0;
+  layout[0].range = 1;
+  layout[0].coords.Npolyterms = 0;
+  for (i = 0; i < NOVERLAYS; i++) {
+    layout[0].overlay[i].Nobjects = 0;
+    ALLOCATE (layout[0].overlay[i].objects, Object, 1);  /* allocate so later free will not crash! */
+    OVERLAY[i] = FALSE;
+  }
+  layout[0].matrix.size = 0; /* a flag to show there is no data in the matrix */
+
+  MOVE_POINTER = TRUE;
+  DECIMAL_DEG  = TRUE;
+  ALLOCATE (layout[0].matrix.buffer, char, 1);  /* allocate so later free will not crash! */
+  ALLOCATE (layout[0].picture.data, char, 1);   /* allocate so later free will not crash! */
+  ALLOCATE (layout[0].cmapbar.data, char, 1);   /* allocate so later free will not crash! */
+  ALLOCATE (layout[0].zoom.data, char, 1);      /* allocate so later free will not crash! */
+
+  CreatePicture (layout, graphic);
+  CreateColorbar (layout, graphic);
+  CreateZoom (layout, graphic, 0, 0); 
+}
+
+
+/* this routine is independent of the number of overlays */
+
+  /* cmap = the mapping of value to color in kii
+     colormap = the set of pixel -> color representation in X */
+
Index: /tags/start/Ohana/src/kii/setup/DrawBitmap.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/DrawBitmap.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/DrawBitmap.c	(revision 12606)
@@ -0,0 +1,49 @@
+# include "Ximage.h"
+
+void
+DrawBitmap (graphic, x, y, dx, dy, bitmap, mode)
+Graphic     graphic[];
+int         x, y, dx, dy;
+char        bitmap[];
+int         mode;
+{
+
+  int i, j, byte_line, byte, bit, flag;
+  unsigned long int black, white;
+
+  if (mode == 0) {
+    black = graphic[0].black;
+    white = graphic[0].white;
+    graphic[0].black = white;
+    graphic[0].white = white;
+  }
+    
+  if (mode == 2) {
+    black = graphic[0].black;
+    white = graphic[0].white;
+    graphic[0].black = white;
+    graphic[0].white = black;
+  }
+    
+  
+  byte_line = (int) ((dx + 7) / 8);
+  for (i = 0; i < dy; i++) {
+    for (j = 0; j < dx; j++) {
+      byte = byte_line * i + (j / 8);
+      bit = j % 8;
+      flag = 0x01 & (bitmap[byte] >> bit);
+      if (flag)
+	XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+      else 
+	XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+      XDrawPoint (graphic[0].display, graphic[0].window, 
+		  graphic[0].gc, x + j, y + i);
+    }
+  }
+  if (mode == 0) {
+    graphic[0].black = black;
+    graphic[0].white = white;
+  }
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+}
+
Index: /tags/start/Ohana/src/kii/setup/GetColor.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/GetColor.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/GetColor.c	(revision 12606)
@@ -0,0 +1,25 @@
+# include "Ximage.h"
+
+/************** GetColor *************/
+unsigned long 
+GetColor (display, name, colormap, default_color)
+Display  *display;
+char      name[];
+Colormap  colormap;
+unsigned long default_color;
+{
+
+  unsigned long color;
+  XColor rgbcolor, hardwarecolor;
+  int status;
+
+  color = default_color;
+  status = XLookupColor (display, colormap, name, &rgbcolor, &hardwarecolor);
+  if (status) {
+    status = XAllocColor (display, colormap, &hardwarecolor);
+    if (status) {
+      color = hardwarecolor.pixel;
+    }
+  }
+  return (color);
+}
Index: /tags/start/Ohana/src/kii/setup/LoadFont.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/LoadFont.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/LoadFont.c	(revision 12606)
@@ -0,0 +1,31 @@
+# include "Ximage.h"
+
+/************** LoadFont *************/
+void
+LoadFont (graphic, argc, argv, default_name)
+Graphic   graphic[];
+int      *argc;
+char     *argv[];
+char      default_name[];
+{
+
+  char name[400];
+
+  strcpy (name, default_name);
+  CheckFontName (argc, argv, name);
+  graphic[0].font = XLoadQueryFont (graphic[0].display, name);
+  if (graphic[0].font == (XFontStruct *) NULL) {
+    fprintf (stderr, "Could not load fond %s, using %s\n", name, default_name);
+    graphic[0].font = XLoadQueryFont (graphic[0].display, default_name);
+    if (graphic[0].font == (XFontStruct *) NULL) {
+      graphic[0].font = XLoadQueryFont (graphic[0].display, "fixed");
+      fprintf (stderr, "Could not load fond %s, using %s\n", 
+	       default_name, "fixed");
+    }
+  }
+  if (graphic[0].font != (XFontStruct *) NULL) 
+    XSetFont (graphic[0].display, graphic[0].gc, graphic[0].font[0].fid);
+  else
+    QuitX (graphic[0].display, "Error: could not load font", name);
+}
+
Index: /tags/start/Ohana/src/kii/setup/MakeColormap.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/MakeColormap.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/MakeColormap.c	(revision 12606)
@@ -0,0 +1,54 @@
+# include "Ximage.h"
+# define NPIXELS 64
+
+static char default_cmap[] = "grayscale";
+
+void MakeColormap (Graphic *graphic, Layout *layout, int argc, char **argv) {
+
+  int i, N, status;
+  char *temp_name;
+
+  /* hardwired colors - white, black -- for drawing text and overlay graphics */
+  layout[0].white = graphic[0].white;
+  layout[0].black = graphic[0].black;
+  layout[0].start = 0;
+  layout[0].slope = 1;
+  temp_name = XGetDefault (graphic[0].display, argv[0], "ROverlay");
+  layout[0].overlay[0].color = GetColor (graphic[0].display, (temp_name == (char *) NULL ? "red"    : temp_name), graphic[0].colormap, graphic[0].black);
+  temp_name = XGetDefault (graphic[0].display, argv[0], "GOverlay");
+  layout[0].overlay[1].color = GetColor (graphic[0].display, (temp_name == (char *) NULL ? "green"  : temp_name), graphic[0].colormap, graphic[0].black);
+  temp_name = XGetDefault (graphic[0].display, argv[0], "BOverlay");
+  layout[0].overlay[2].color = GetColor (graphic[0].display, (temp_name == (char *) NULL ? "blue"   : temp_name), graphic[0].colormap, graphic[0].black);
+  temp_name = XGetDefault (graphic[0].display, argv[0], "YOverlay");
+  layout[0].overlay[3].color = GetColor (graphic[0].display, (temp_name == (char *) NULL ? "yellow" : temp_name), graphic[0].colormap, graphic[0].black);
+
+  layout[0].Npixels = graphic[0].Npixels;
+  for (i = 0; i < layout[0].Npixels; i++) 
+    layout[0].cmap[i].pixel = graphic[0].pixels[i];
+
+  /* decide on a color map */
+  temp_name = XGetDefault (graphic[0].display, argv[0], "Colormap");
+  if ((N = get_argument (argc, argv, "-cm"))) {
+    if (N + 1 < argc) {
+      temp_name = argv[N+1];
+    } else {
+      fprintf (stderr, "error: usage is -cm ColormapName\n");
+      exit (1);
+    }
+  }
+  if (temp_name == (char *) NULL) temp_name = default_cmap;
+
+  status = SetColormap (graphic, layout, temp_name);
+  if (!status) {
+    fprintf (stderr, "invalid colormap, using default %s\n", default_cmap);
+    temp_name = default_cmap;
+    status = SetColormap (graphic, layout, temp_name);
+    if (!status) {
+      fprintf (stderr, "problem with default colormap\n");
+      exit (1);
+    }
+  }
+}
+
+/* this routine is NOT independent of the number of overlays */
+
Index: /tags/start/Ohana/src/kii/setup/MakeCursor.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/MakeCursor.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/MakeCursor.c	(revision 12606)
@@ -0,0 +1,16 @@
+# include "Ximage.h"
+
+/************** MakeCursor *************/
+void
+MakeCursor  (graphic, which_cursor)
+Graphic      graphic[];
+unsigned int which_cursor;
+{
+
+  graphic[0].cursor = XCreateFontCursor (graphic[0].display, 
+					 (unsigned) which_cursor);
+  if (graphic[0].cursor != (Cursor) None)
+    XDefineCursor (graphic[0].display, graphic[0].window, graphic[0].cursor);
+}
+
+
Index: /tags/start/Ohana/src/kii/setup/MakeGC.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/MakeGC.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/MakeGC.c	(revision 12606)
@@ -0,0 +1,15 @@
+# include "Ximage.h"
+
+/************** MakeGC *************/
+void MakeGC (Graphic *graphic) {
+
+  XGCValues gcvalues;
+
+  gcvalues.foreground = graphic[0].black;
+  gcvalues.background = graphic[0].white;
+  graphic[0].gc = XCreateGC (graphic[0].display, graphic[0].window, 
+			     GCForeground | GCBackground, &gcvalues);
+  if (graphic[0].gc == 0)
+    QuitX (graphic[0].display, "Error in creating a Graphics Context", "");
+}
+
Index: /tags/start/Ohana/src/kii/setup/MapWindow.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/MapWindow.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/MapWindow.c	(revision 12606)
@@ -0,0 +1,13 @@
+# include "Ximage.h"
+
+/************** MapWindow *************/
+void
+MapWindow (graphic)
+Graphic    graphic[];
+{
+
+  XMapRaised (graphic[0].display, graphic[0].window);
+  XMapSubwindows (graphic[0].display, graphic[0].window);
+  XFlush (graphic[0].display);
+}
+
Index: /tags/start/Ohana/src/kii/setup/NameWindow.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/NameWindow.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/NameWindow.c	(revision 12606)
@@ -0,0 +1,35 @@
+# include "Ximage.h"
+
+/************** NameWindow *************/
+void
+NameWindow (graphic, Name)
+Graphic     graphic[];
+char       *Name;
+{
+
+  char       *name;
+  char       *class_name;
+  char       *class_type;
+  XClassHint *classhints;
+
+  name = strrchr (Name, '/');
+  if (name != NULL) 
+    name ++;
+  else 
+    name = Name;
+  class_type = class_name = name;
+
+
+  classhints = XAllocClassHint ();
+
+  if (classhints != (XClassHint *) NULL)  {
+    classhints[0].res_name = class_name;
+    classhints[0].res_class = class_type;
+    XSetClassHint (graphic[0].display, graphic[0].window, classhints);
+    XFree (classhints);
+  }
+  
+  XStoreName (graphic[0].display, graphic[0].window, name);
+  XSetIconName (graphic[0].display, graphic[0].window, name);
+}
+
Index: /tags/start/Ohana/src/kii/setup/OpenDisplay.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/OpenDisplay.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/OpenDisplay.c	(revision 12606)
@@ -0,0 +1,19 @@
+# include "Ximage.h"
+
+/************** OpenDisplay *************/
+Display *OpenDisplay (char *display_name, int *screen) {
+
+  Display *display;
+  
+  display = XOpenDisplay (display_name);
+  if (display != (Display *) NULL)
+    *screen = DefaultScreen (display);
+  if (display == (Display *) NULL) {
+    fprintf (stderr, "Error could not open X display to %s\n", 
+	     XDisplayName (display_name));
+    exit (0);
+  }
+
+  return (display);
+}
+
Index: /tags/start/Ohana/src/kii/setup/QuitX.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/QuitX.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/QuitX.c	(revision 12606)
@@ -0,0 +1,15 @@
+# include "Ximage.h"
+
+/************** QuitX *************/
+void
+QuitX (display, error_message, error_file)
+Display *display;
+char error_message[], error_file[];
+{
+
+  fprintf (stderr, "Error: %s%s\n", error_message, error_file);
+  XCloseDisplay (display);
+  exit (0);
+}
+
+
Index: /tags/start/Ohana/src/kii/setup/SetNormalHints.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/SetNormalHints.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/SetNormalHints.c	(revision 12606)
@@ -0,0 +1,30 @@
+# include "Ximage.h"
+
+/************** SetNormalHints  *************/
+void
+SetNormalHints (graphic)
+Graphic         graphic[];
+{
+
+  XSizeHints *sizehints;
+
+  sizehints = XAllocSizeHints ();
+
+  if (sizehints != (XSizeHints *) NULL)  {
+    sizehints[0].x = graphic[0].x;
+    sizehints[0].y = graphic[0].x;
+    sizehints[0].width = graphic[0].dx;
+    sizehints[0].height = graphic[0].dy;
+    sizehints[0].min_width = MIN_WIDTH;
+    sizehints[0].min_height = MIN_HEIGHT;    
+    sizehints[0].flags = USPosition | USSize | PMinSize;
+
+    sizehints[0].base_width = graphic[0].dx;
+    sizehints[0].base_height = graphic[0].dy;
+    sizehints[0].flags |= PBaseSize;
+    
+    XSetWMNormalHints (graphic[0].display, graphic[0].window, sizehints);
+    XFree (sizehints);
+  }
+}
+
Index: /tags/start/Ohana/src/kii/setup/SetUpDisplay.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/SetUpDisplay.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/SetUpDisplay.c	(revision 12606)
@@ -0,0 +1,20 @@
+# include "Ximage.h"
+
+/************** SetUpDisplay *************/
+void SetUpDisplay (Graphic *graphic, int *argc, char **argv) {
+
+  char display_name[120];
+
+  CheckDisplayName (argc, argv, display_name); 
+
+  /* set default values */
+  graphic[0].display  = OpenDisplay (display_name, &graphic[0].screen);
+  graphic[0].colormap = DefaultColormap (graphic[0].display, graphic[0].screen);
+  graphic[0].depth    = DefaultDepth    (graphic[0].display, graphic[0].screen);
+  graphic[0].visual   = DefaultVisual   (graphic[0].display, graphic[0].screen);
+
+  /* get the basic colors */
+  CheckVisual (graphic, argc, argv);
+  CheckColors (graphic, argc, argv);
+}
+
Index: /tags/start/Ohana/src/kii/setup/SetUpWindow.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/SetUpWindow.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/SetUpWindow.c	(revision 12606)
@@ -0,0 +1,33 @@
+# include "Ximage.h"
+# include "icons/icon.h"
+
+/************** SetUpWindow *************/
+void SetUpWindow (Graphic *graphic, int *argc, char **argv) {
+
+  int N;
+  Icon icon;
+
+  icon.width = icon_width;
+  icon.height = icon_height;
+  icon.bits = icon_bits;
+
+  CheckGeometry (argc, argv, graphic);
+  TopWindow (graphic, &icon);
+  LoadFont (graphic, argc, argv, "fixed"); 
+
+  XFlush (graphic[0].display);
+  XSetWindowBackground (graphic[0].display, graphic[0].window, graphic[0].white);
+
+  SetNormalHints (graphic);
+  SetWMHints (graphic, &icon);
+  NameWindow (graphic, "Ki'i");
+
+  if ((N = get_argument (*argc, argv, "-nomap"))) {
+    remove_argument(N, argc, argv);
+  } else {
+    MapWindow (graphic);
+  }  
+}
+
+
+
Index: /tags/start/Ohana/src/kii/setup/SetWMHints.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/SetWMHints.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/SetWMHints.c	(revision 12606)
@@ -0,0 +1,27 @@
+# include "Ximage.h"
+
+/************** SetWMHints  *************/
+void
+SetWMHints (graphic, icon) 
+Graphic     graphic[];
+Icon        icon[];
+{
+  XWMHints *wmhints;
+
+  wmhints = XAllocWMHints ();
+  if (wmhints != (XWMHints *)NULL) {
+    wmhints[0].initial_state = NormalState;
+    wmhints[0].input = True;
+    if (icon[0].pixmap != (Pixmap) None) {
+      wmhints[0].icon_pixmap = icon[0].pixmap;
+      wmhints[0].icon_mask = icon[0].pixmap;
+      wmhints[0].flags = StateHint | InputHint | IconPixmapHint | IconMaskHint;
+    }
+    else 
+      wmhints[0].flags = StateHint | InputHint;
+    
+    XSetWMHints (graphic[0].display, graphic[0].window, wmhints);
+    XFree (wmhints);
+  }
+}
+
Index: /tags/start/Ohana/src/kii/setup/TopWindow.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/TopWindow.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/TopWindow.c	(revision 12606)
@@ -0,0 +1,21 @@
+# include "Ximage.h"
+
+/************** TopWindow *************/
+void TopWindow (Graphic *graphic, Icon *icon) {
+
+  Window rootwindow;
+
+  rootwindow = RootWindow (graphic[0].display, graphic[0].screen);
+
+  CreateWindow (graphic, rootwindow, BORDER_WIDTH, EVENT_MASK);
+  MakeGC (graphic);
+  icon[0].pixmap = XCreateBitmapFromData (graphic[0].display,
+					graphic[0].window, 
+					icon[0].bits, 
+					icon[0].width, 
+					icon[0].height);
+  MakeCursor (graphic, DEFAULT_CURSOR);
+  XFreeCursor (graphic[0].display, graphic[0].cursor);
+  XFlush (graphic[0].display);
+}
+
Index: /tags/start/Ohana/src/kii/setup/Ximage.c
===================================================================
--- /tags/start/Ohana/src/kii/setup/Ximage.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/setup/Ximage.c	(revision 12606)
@@ -0,0 +1,22 @@
+# include "Ximage.h"
+
+int main (int argc, char **argv) {
+
+  Graphic graphic;
+  Layout  layout;
+  
+  bzero (&graphic, sizeof(Graphic));
+  bzero (&layout, sizeof(Layout));
+
+  SetUpDisplay (&graphic, &argc, argv);
+  SetUpWindow (&graphic, &argc, argv);
+
+  DefineLayout (&layout, &graphic, argc, argv);
+  EventLoop (&graphic, &layout);
+
+  XFlush (graphic.display);
+  XFreeFont (graphic.display, graphic.font); 
+  CloseDisplay (&graphic);
+  exit (0);
+}
+
Index: /tags/start/Ohana/src/kii/textline/CheckTextLines.c
===================================================================
--- /tags/start/Ohana/src/kii/textline/CheckTextLines.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/textline/CheckTextLines.c	(revision 12606)
@@ -0,0 +1,28 @@
+# include "Ximage.h"
+
+/******** Here we test the TextLines specific to this program  ****
+TextLine *
+CheckTextLines (graphic, event, layout)
+Graphic         graphic[];
+XEvent          event[];
+Layout          layout[];
+{
+
+  TextLine *textline;
+  textline = (TextLine *) NULL;
+
+  if (InTextLine (graphic, event, &layout[0].zero))
+    textline = &layout[0].zero;
+  if (InTextLine (graphic, event, &layout[0].range))
+    textline = &layout[0].range;
+  if (InTextLine (graphic, event, &layout[0].effects))
+    textline = &layout[0].effects;
+  if (InTextLine (graphic, event, &layout[0].command))
+    textline = &layout[0].command;
+
+  return (textline);
+
+}
+
+
+***/
Index: /tags/start/Ohana/src/kii/textline/DrawCursor.c
===================================================================
--- /tags/start/Ohana/src/kii/textline/DrawCursor.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/textline/DrawCursor.c	(revision 12606)
@@ -0,0 +1,45 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+
+
+DrawCursor (graphic, textline)    
+Graphic       graphic[];
+TextLine      textline[];
+{
+
+  int dx, label_width, DX, text_width, i;
+
+  label_width  = XTextWidth (graphic[0].font, 
+			     textline[0].label,
+			     strlen(textline[0].label));
+  
+  text_width  = XTextWidth (graphic[0].font, 
+			    textline[0].text,
+			    strlen(textline[0].text));
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+
+  if (label_width + text_width + 2*XBorder > textline[0].dx) {
+    DX = textline[0].dx - label_width - 2*XBorder - arrow_width;
+    for (i = 1; (i < strlen (textline[0].text)) && (text_width > DX); i++) {
+      text_width  = XTextWidth (graphic[0].font, 
+				&textline[0].text[i],
+				strlen(&textline[0].text[i]));
+    }
+    dx  = XTextWidth (graphic[0].font, &textline[0].text[i - 1], 
+		      textline[0].cursor - i + 1) + arrow_width;
+  }
+  else 
+    dx  = XTextWidth (graphic[0].font, textline[0].text, textline[0].cursor);
+
+  XDrawLine (graphic[0].display, 
+	     graphic[0].window, 
+	     graphic[0].gc, 
+	     textline[0].x + label_width + XBorder + dx, 
+	     textline[0].y + YBorder,
+	     textline[0].x + label_width + XBorder + dx, 
+	     textline[0].y + textline[0].dy - YBorder);
+
+}
Index: /tags/start/Ohana/src/kii/textline/DrawTextBox.c
===================================================================
--- /tags/start/Ohana/src/kii/textline/DrawTextBox.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/textline/DrawTextBox.c	(revision 12606)
@@ -0,0 +1,63 @@
+# include "Ximage.h"
+# define XBorder 10
+# define YBorder 2
+# define arrow_width 6
+# define arrow_height 9
+static char arrow_bits[] = {
+  0x00, 0x02, 0x06, 0x0e, 0x1e, 0x0e, 0x06, 0x02, 0x00};
+#define down_width 9
+#define down_height 6
+static char down_bits[] = {
+   0x00, 0x00, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00};
+
+/******************* DrawTextBox ****************/
+DrawTextBox (graphic, textbox)
+Graphic      graphic[];
+TextBox      textbox[];
+{
+
+  int X, Y, y, dy, Nlines, i;
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+  XFillRectangle (graphic[0].display, 
+		  graphic[0].window,
+		  graphic[0].gc,
+		  textbox[0].x  + 1,  textbox[0].y + 1,
+		  XBorder - 2, textbox[0].dy - 2);
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+  if (textbox[0].outline) {
+    XDrawRectangle (graphic[0].display, 
+		    graphic[0].window,
+		    graphic[0].gc,
+		    textbox[0].x,  textbox[0].y,
+		    textbox[0].dx, textbox[0].dy);
+  }
+
+  dy = graphic[0].font[0].ascent + graphic[0].font[0].descent;
+  Nlines = (textbox[0].dy - 2*YBorder) / dy;
+
+  for (i = 0; (i < Nlines) && (i < textbox[0].Nlines); i++) {
+    y = textbox[0].y + graphic[0].font[0].ascent + dy*i + YBorder;
+    XDrawString (graphic[0].display, 
+		 graphic[0].window, 
+		 graphic[0].gc, 
+		 textbox[0].x + XBorder, y,
+		 textbox[0].text[i], 
+		 strlen(textbox[0].text[i]));
+  }
+
+  if (Nlines < textbox[0].Nlines) {
+    DrawBitmap (graphic, 
+		textbox[0].x + textbox[0].dx - down_width - 2,
+		textbox[0].y + textbox[0].dy - down_height - 2,
+		down_width, down_height, down_bits, 1);
+  }
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+  if (textbox[0].cursor_line != -1) {
+    Y = textbox[0].y + dy*textbox[0].cursor_line + YBorder + (dy - arrow_height)/2;
+    X = textbox[0].x + (XBorder - arrow_width) / 2;
+    DrawBitmap (graphic, X, Y, arrow_width, arrow_height, arrow_bits, 1);
+  }
+}
+
Index: /tags/start/Ohana/src/kii/textline/DrawTextLine.c
===================================================================
--- /tags/start/Ohana/src/kii/textline/DrawTextLine.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/textline/DrawTextLine.c	(revision 12606)
@@ -0,0 +1,34 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+DrawTextLine (graphic, textline)
+Graphic  graphic[];
+TextLine textline[];
+{
+
+  int y;
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+  if (textline[0].outline) {
+    XDrawRectangle (graphic[0].display, 
+		    graphic[0].window,
+		    graphic[0].gc,
+		    textline[0].x,  textline[0].y,
+		    textline[0].dx, textline[0].dy);
+  }
+
+  y = textline[0].y + (textline[0].dy + graphic[0].font[0].ascent) / 2;
+  XDrawString (graphic[0].display, 
+	       graphic[0].window, 
+	       graphic[0].gc, 
+	       textline[0].x + XBorder, y,
+	       textline[0].label, 
+	       strlen(textline[0].label));
+  RedrawString (graphic, textline);
+
+  if (textline[0].cursor != -1)
+    DrawCursor (graphic, textline);
+
+}
+
Index: /tags/start/Ohana/src/kii/textline/InTextBox.c
===================================================================
--- /tags/start/Ohana/src/kii/textline/InTextBox.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/textline/InTextBox.c	(revision 12606)
@@ -0,0 +1,57 @@
+# include "Ximage.h"
+# define XBorder 10
+# define YBorder 2
+# define arrow_width 6
+# define arrow_height 9
+static char arrow_bits[] = {
+  0x00, 0x02, 0x06, 0x0e, 0x1e, 0x0e, 0x06, 0x02, 0x00};
+#define down_width 9
+#define down_height 6
+static char down_bits[] = {
+   0x00, 0x00, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00};
+
+/******************* InTextBox ****************/
+int
+InTextBox (graphic, event, textbox)
+Graphic          graphic[];
+XButtonEvent    *event;
+TextBox          textbox[];
+{
+
+  int answer;
+  int i, x, y, Y, X, dy;
+  int minX, maxX, minY, maxY;
+  
+  x = event[0].x;
+  y = event[0].y;
+  dy = graphic[0].font[0].ascent + graphic[0].font[0].descent;
+  
+  minX = textbox[0].x;
+  maxX = textbox[0].x + textbox[0].dx;
+  minY = textbox[0].y;
+  maxY = textbox[0].y + textbox[0].dy;
+  if (dy*textbox[0].Nlines + 2*YBorder < textbox[0].dy)
+    maxY = textbox[0].y + dy*textbox[0].Nlines + 2*YBorder;
+
+  answer = ((x >= minX) && (x <= maxX) && (y >= minY) && (y <= maxY));
+  
+  /* find the cursor position, erase the old arrow and draw a new arrow */
+  if (answer) {
+    if (textbox[0].cursor_line != -1) {
+      Y = textbox[0].y + dy*textbox[0].cursor_line + YBorder + (dy - arrow_height)/2;
+      X = textbox[0].x + (XBorder - arrow_width) / 2;
+      DrawBitmap (graphic, X, Y, arrow_width, arrow_height, arrow_bits, 0);
+    }
+    textbox[0].cursor_line = (y - textbox[0].y - YBorder)/dy;
+    X = textbox[0].x + (XBorder - arrow_width) / 2;
+    Y = textbox[0].y + dy*textbox[0].cursor_line + YBorder + (dy - arrow_height)/2;
+    DrawBitmap (graphic, X, Y, arrow_width, arrow_height, arrow_bits, 1);
+    textbox[0].cursor_x = x;
+    textbox[0].cursor_y = y;
+    XFlush (graphic[0].display);
+  }
+  
+  return (answer);
+  
+}
+
Index: /tags/start/Ohana/src/kii/textline/InTextLine.c
===================================================================
--- /tags/start/Ohana/src/kii/textline/InTextLine.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/textline/InTextLine.c	(revision 12606)
@@ -0,0 +1,58 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+int
+InTextLine (graphic, event, textline)
+Graphic          graphic[];
+XButtonEvent    *event;
+TextLine         textline[];
+{
+
+  int answer, done;
+  int i, x, dx, y, text_width, label_width;
+  int minX, maxX, minY, maxY;
+  char testline[1000];
+
+  x = event[0].x;
+  y = event[0].y;
+  
+  label_width  = XTextWidth (graphic[0].font, 
+			     textline[0].label,
+			     strlen(textline[0].label));
+  
+  minX = textline[0].x + XBorder + label_width;
+  maxX = textline[0].x + textline[0].dx;
+  minY = textline[0].y;
+  maxY = textline[0].y + textline[0].dy;
+
+  answer = ((x >= minX) && (x <= maxX) && (y >= minY) && (y <= maxY));
+
+  /* find the cursor position and draw a vertical bar */
+  if (answer) {
+    text_width  = XTextWidth (graphic[0].font, 
+			      textline[0].text,
+			      strlen(textline[0].text));
+    
+    if (x >= minX + text_width) {
+      textline[0].cursor = strlen (textline[0].text);
+    }
+    else {
+      for (i = 1, done = FALSE; (i <= strlen (textline[0].text)) && !done; i++) {
+	dx  = XTextWidth (graphic[0].font, 
+			  textline[0].text, i);
+	if (x < minX + dx) {
+	  textline[0].cursor = i - 1;
+	  done = TRUE;
+	}
+      }
+    }
+    DrawCursor (graphic, textline);
+  }    
+  XFlush (graphic[0].display);
+  
+  return (answer);
+  
+}
+
+
Index: /tags/start/Ohana/src/kii/textline/RedrawString.c
===================================================================
--- /tags/start/Ohana/src/kii/textline/RedrawString.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/textline/RedrawString.c	(revision 12606)
@@ -0,0 +1,73 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+
+#define arrow_width 6
+#define arrow_height 9
+RedrawString (graphic, textline)
+Graphic       graphic[];
+TextLine      textline[];
+{
+
+  int label_width, text_width, y, i, DX;
+  static char arrow_bits[] = {
+    0x00, 0x10, 0x18, 0x1c, 0x1e, 0x1c, 0x18, 0x10, 0x00};
+  
+  label_width  = XTextWidth (graphic[0].font, 
+			     textline[0].label,
+			     strlen(textline[0].label));
+  
+  text_width  = XTextWidth (graphic[0].font, 
+			    textline[0].text,
+			    strlen(textline[0].text));
+
+  if (label_width + text_width + 2*XBorder > textline[0].dx) {
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		    textline[0].x + XBorder + label_width, 
+		    textline[0].y + YBorder, 
+		    textline[0].dx - XBorder - label_width, 
+		    textline[0].dy - 2*YBorder + 1);
+    
+    DX = textline[0].dx - label_width - 2*XBorder - arrow_width;
+    for (i = 1; (i < strlen (textline[0].text)) && (text_width > DX); i++) {
+      text_width  = XTextWidth (graphic[0].font, 
+				&textline[0].text[i],
+				strlen(&textline[0].text[i]));
+    }
+
+    y = textline[0].y + (textline[0].dy + graphic[0].font[0].ascent) / 2;
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+    DrawBitmap (graphic, 
+		textline[0].x + XBorder + label_width,
+		textline[0].y + YBorder + (textline[0].dy - arrow_height)/2,
+		arrow_width, arrow_height, arrow_bits, 1);
+    XDrawString (graphic[0].display, 
+		 graphic[0].window, 
+		 graphic[0].gc, 
+		 textline[0].x + XBorder + label_width + arrow_width, y,
+		 &textline[0].text[i - 1], 
+		 strlen(&textline[0].text[i - 1]));
+    XFlush (graphic[0].display);
+  }
+  else {
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		    textline[0].x + XBorder + label_width, 
+		    textline[0].y + YBorder, 
+		    textline[0].dx - XBorder - label_width, 
+		    textline[0].dy - 2*YBorder + 1);
+    
+    y = textline[0].y + (textline[0].dy + graphic[0].font[0].ascent) / 2;
+    
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+    XDrawString (graphic[0].display, 
+		 graphic[0].window, 
+		 graphic[0].gc, 
+		 textline[0].x + XBorder + label_width, y,
+		 textline[0].text, 
+		 strlen(textline[0].text));
+  }
+
+}
Index: /tags/start/Ohana/src/kii/textline/TextLineEntry.c
===================================================================
--- /tags/start/Ohana/src/kii/textline/TextLineEntry.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/textline/TextLineEntry.c	(revision 12606)
@@ -0,0 +1,81 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+int 
+TextLineEntry (graphic, textline, keyevent)
+Graphic        graphic[];
+TextLine       textline[];
+XKeyEvent     *keyevent;
+{
+
+  int i, status, N;
+  char dummy[3];
+  XComposeStatus compose_status;
+  KeySym keysym;
+
+  status = TRUE;
+  strcpy (textline[0].old_text, textline[0].text);
+  bzero (&textline[0].text[strlen(textline[0].text)], 
+	 1024 - strlen(textline[0].text));
+  i = textline[0].cursor;
+
+
+  N = XLookupString (keyevent, dummy, 1, &keysym, &compose_status);
+  switch (keysym) {
+  case XK_BackSpace:
+  case XK_Delete:
+    if (textline[0].cursor > 0) {
+      bcopy (&textline[0].text[i], &textline[0].text[i - 1], 
+	     strlen(&textline[0].text[i]) + 1);
+      RedrawString (graphic, textline);
+      textline[0].cursor --;
+      DrawCursor (graphic, textline);
+    }
+    break;
+  case XK_Left:
+    RedrawString (graphic, textline);
+    textline[0].cursor --;
+    if (textline[0].cursor < 0)
+      textline[0].cursor = 0;
+    DrawCursor (graphic, textline);
+    break;
+  case XK_Right:
+    RedrawString (graphic, textline);
+    textline[0].cursor ++;
+    if (textline[0].cursor > strlen (textline[0].text))
+      textline[0].cursor = strlen (textline[0].text);
+    DrawCursor (graphic, textline);
+    break;
+  case XK_Return:
+    RedrawString (graphic, textline);
+    textline[0].cursor = -1;
+    status = FALSE;
+    break;
+  case XK_d:
+  case XK_D: 
+    if (dummy[0] == 4) { /* a control-d was typed! */
+      if (textline[0].cursor < strlen(textline[0].text)) {
+	bcopy (&textline[0].text[i + 1], &textline[0].text[i], 
+	       strlen(&textline[0].text[i]));
+	RedrawString (graphic, textline);
+	DrawCursor (graphic, textline);
+      }
+      break;  /* WARNING: this case MUST come before default.
+		 anything between this and default will be executed
+		 if no cntl-d is typed! */
+    }
+  default:
+    if (N != 0) {
+      bcopy (&textline[0].text[i], &textline[0].text[i + 1], 
+	     strlen(&textline[0].text[i]));
+      textline[0].text[i] = dummy[0];
+      RedrawString (graphic, textline);
+      textline[0].cursor ++;
+      DrawCursor (graphic, textline);
+    }
+  }
+  return (status);
+}
+
+
Index: /tags/start/Ohana/src/kii/zoom/CreateZoom.c
===================================================================
--- /tags/start/Ohana/src/kii/zoom/CreateZoom.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/zoom/CreateZoom.c	(revision 12606)
@@ -0,0 +1,26 @@
+# include "Ximage.h"
+# define XPIX(x,Rx,S) (x*S + Rx)
+# define ZPIX(value,Rz1,Rz2) (value*Rz1 - Rz2)
+# define FRAC(a) ((a) - (int)(a))
+
+void CreateZoom (Layout *layout, Graphic *graphic, double x, double y) {
+
+  switch (graphic[0].Nbits) {
+  case 8:
+    CreateZoom8 (layout, graphic, x, y);
+    break;
+
+  case 16:
+    CreateZoom16 (layout, graphic, x, y);
+    break;
+
+  case 24:
+    CreateZoom24 (layout, graphic, x, y);
+    break;
+
+  case 32:
+    CreateZoom32 (layout, graphic, x, y);
+    break;
+  }    
+
+}
Index: /tags/start/Ohana/src/kii/zoom/CreateZoom.new
===================================================================
--- /tags/start/Ohana/src/kii/zoom/CreateZoom.new	(revision 12606)
+++ /tags/start/Ohana/src/kii/zoom/CreateZoom.new	(revision 12606)
@@ -0,0 +1,112 @@
+# include "Ximage.h"
+# define XPIX(x,Rx,S) (x*S + Rx)
+
+void
+CreateZoom (layout, graphic, x, y)
+Layout layout[];
+Graphic graphic[];
+double x, y;
+{
+
+  int i, j, ii, jj, X, Y;
+  int zvalue;
+  double value, expand, zero, range, zoomscale;
+  double X0, Y0, Rx, Ry, Rz1, Rz2;
+  int expand_int, dx, dy, DX, DY, Npixels, yfac;
+  Visual *visual = CopyFromParent;
+  unsigned long pixel;
+
+
+  /* create a test pattern image to put in layout[0].picture */
+  if (layout[0].matrix.size == 0) {
+    REALLOCATE (layout[0].zoom.data, char, layout[0].zoom.dx*layout[0].zoom.dy);
+    bzero (layout[0].zoom.data, layout[0].zoom.dx*layout[0].zoom.dy);
+  }
+  else {
+    for (i = 0; i < 256; i++) 
+      pixel[i] = layout[0].cmap[i].pixel;
+    white = layout[0].white;
+    
+    zoomscale = MAX (5, layout[0].expand + 5);
+    expand = 1 / zoomscale;
+    expand_out = (int) zoomscale;
+    expand_in  = 1;
+    
+    dx = layout[0].zoom.dx;
+    dy = layout[0].zoom.dy;
+    DX = layout[0].matrix.Naxis[0];
+    DY = layout[0].matrix.Naxis[1];
+    Rx = DX/2 - dx*expand/2.0 - X0;
+    Ry = DY/2 - dy*expand/2.0 - Y0;  
+    
+    /* reassign as much for speed as clarity here */
+    X0 = 0.5*layout[0].matrix.Naxis[0] - x;
+    Y0 = 0.5*layout[0].matrix.Naxis[1] - y;
+    dx = layout[0].picture.dx;
+    dy = layout[0].picture.dy;
+    DX = matrix[0].Naxis[0];
+    DY = matrix[0].Naxis[1];
+    Rx = DX/2 - dx*expand/2.0 - X0;
+    Ry = DY/2 - dy*expand/2.0 - Y0;
+    
+    i_start = MAX (-Rx / expand, 0);
+    j_start = MAX (-Ry / expand, 0);
+    i_end   = MIN ((DX - Rx)/expand, dx - expand_out + 1);
+    j_end   = MIN ((DY - Ry)/expand, dy - expand_out + 1);
+    
+    in_pix = (short *) matrix[0].buffer;
+    out_pix = layout[0].zoom.data;
+    for (j = 0; j < j_start; j++) {
+      for (i = 0; i < dx; i++, out_pix++) {
+	*out_pix = white;
+      }
+    }
+    
+  for (j = j_start; j < j_end; j+= expand_out) {
+    Y = XPIX (j, Ry, expand);
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix = layout[0].zoom.data + (j+jj)*dx;  /* fencepost errors? */
+      for (i = 0; i < i_start; i++, out_pix++) {
+	*out_pix = white;
+      }
+    }
+    out_pix = layout[0].zoom.data + j*dx + i_start;  
+    X = XPIX (i_start, Rx, expand);
+    in_pix2 = in_pix + DX*Y + X;
+    for (i = i_start; i < i_end; i+= expand_out, in_pix2+= expand_in) { 
+      zvalue = 0x003f & *in_pix2;
+      for (ii = 0; ii < expand_out; ii++, out_pix++) {
+	for (jj = 0; jj < expand_out; jj++) {
+	  *(out_pix + jj*dx) = *(pixel + zvalue);
+	}
+      }
+    }
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix = layout[0].zoom.data + (j+jj)*dx + i_end;  /* fencepost errors? */
+      for (i = i_end; i < dx; i++, out_pix++) {
+	*out_pix = white;
+      }
+    }
+  }
+  for (j = j_end; j < dy; j++) {
+    out_pix = layout[0].picture.data + j*dx;
+    for (i = 0; i < dx; i++, out_pix++) {
+      *out_pix = white;
+    }
+  }
+}
+	
+  /*** here, if expand is < 1 (fractional expansion), we sparsely sample the 
+    original image, instead of box averaging - do we like this?  well, 
+    it speeds things up alot! ***/
+
+
+
+
+  layout[0].zoom.pix = XCreateImage (graphic[0].display, visual, graphic[0].depth, ZPixmap, 0, 
+					layout[0].zoom.data, 
+					layout[0].zoom.dx, layout[0].zoom.dy, 8, 0);
+  
+}
+
+ 
Index: /tags/start/Ohana/src/kii/zoom/CreateZoom16.c
===================================================================
--- /tags/start/Ohana/src/kii/zoom/CreateZoom16.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/zoom/CreateZoom16.c	(revision 12606)
@@ -0,0 +1,134 @@
+# include "Ximage.h"
+# define XPIX(x,Rx,S) (x*S + Rx)
+# define ZPIX(value,Rz1,Rz2) (value*Rz1 - Rz2)
+# define FRAC(a) ((a) - (int)(a))
+
+void CreateZoom16 (Layout *layout, Graphic *graphic, double x, double y) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, zoomscale, Rx, Ry;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  unsigned char *in_pix,  *in_pix2;
+  unsigned char pixel1[256], pixel2[256];
+  unsigned char pixvalue1, pixvalue2;
+  unsigned long white;
+  unsigned char white1, white2;
+
+  dx = layout[0].zoom.dx;
+  dy = layout[0].zoom.dy;
+
+  if (layout[0].matrix.size == 0) {  /* create a test pattern */
+    REALLOCATE (layout[0].zoom.data, char, 2*dy*dx);
+    bzero (layout[0].zoom.data, layout[0].zoom.dx*layout[0].zoom.dy);
+    layout[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+				       layout[0].zoom.data, layout[0].zoom.dx, layout[0].zoom.dy, 16, 0);
+    return;
+  }
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel1[i] = 0x0000ff & layout[0].cmap[i].pixel;
+    pixel2[i] = 0x0000ff & (layout[0].cmap[i].pixel >> 8);
+  }
+  white = layout[0].white;
+  white1 = 0x0000ff & white;
+  white2 = 0x0000ff & (white >> 8);
+
+  zoomscale = MAX (5, layout[0].expand + 5);
+  expand = 1 / zoomscale;
+  expand_out = (int) zoomscale;
+  expand_in  = 1;
+
+  DX = layout[0].matrix.Naxis[0];
+  DY = layout[0].matrix.Naxis[1];
+  Rx = x - expand*(int)(0.5*(dx + 1)) + 1;
+  Ry = y - expand*(int)(0.5*(dy + 1)) + 1;
+
+  i_start = MIN (MAX (-Rx / expand, (1 - FRAC(Rx)) / expand), dx - expand_out + 1);
+  j_start = MIN (MAX (-Ry / expand, (1 - FRAC(Ry)) / expand), dy - expand_out + 1);
+  i_end   = MAX (MIN ((DX-Rx) / expand, dx - expand_out + 1), 0);
+  j_end   = MAX (MIN ((DY-Ry) / expand, dy - expand_out + 1), 0);
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  data = out_pix = (unsigned char *) layout[0].zoom.data;
+  in_pix  = (unsigned char *) (layout[0].matrix.buffer) + DX*(int)MAX(Ry,0) + (int)MAX(Rx,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  if ((i_end < i_start) || (j_end < j_start)) {
+    for (j = 0; j < dx*dy; j++, out_pix++) 
+      *out_pix = white;
+    return;
+  } 
+  
+  /**** fill in bottom area ****/
+  for (j = 0; j < j_start; j++) {
+    for (i = 0; i < dx; i++, out_pix+=2) {
+      out_pix[0] = white1;
+      out_pix[1] = white2;
+    }
+  }
+
+  for (j = j_start; j < j_end; j+= expand_out, in_pix += expand_in*DX) {
+    out_pix = &data[2*j*dx];
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) { 
+      out_pix2 = out_pix + 2*jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2+=2) {
+	out_pix2[0] = white1;
+	out_pix2[1] = white2;
+      }
+    }
+    out_pix += 2*i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix+=2) {
+	out_pix[0] = pixel1[*in_pix2];
+	out_pix[1] = pixel2[*in_pix2];
+      }
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 2*expand_out) { 
+	pixvalue1 = pixel1[*in_pix2];
+	pixvalue2 = pixel2[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=2*(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2+=2) {
+	    out_pix2[0] = pixvalue1; 
+	    out_pix2[1] = pixvalue2; 
+	  }
+	}
+      }
+    }
+    out_pix -= 2*dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + 2*jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2+=2) {
+	out_pix2[0] = white1;
+	out_pix2[1] = white2;
+      }
+    }
+  } 
+  
+  out_pix = &data[2*j_end*dx];
+  /**** fill in top area ****/
+  for (j = 0; j < (dy - j_end); j++) {
+    for (i = 0; i < dx; i++, out_pix+=2) { 
+      out_pix[0] = white1;
+      out_pix[1] = white2;
+    }
+  }
+
+  layout[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, 16, ZPixmap, 0, 
+					layout[0].zoom.data, layout[0].zoom.dx, layout[0].zoom.dy, 32, 0);
+  
+}
Index: /tags/start/Ohana/src/kii/zoom/CreateZoom24.c
===================================================================
--- /tags/start/Ohana/src/kii/zoom/CreateZoom24.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/zoom/CreateZoom24.c	(revision 12606)
@@ -0,0 +1,167 @@
+# include "Ximage.h"
+# define XPIX(x,Rx,S) (x*S + Rx)
+# define ZPIX(value,Rz1,Rz2) (value*Rz1 - Rz2)
+# define FRAC(a) ((a) - (int)(a))
+
+void CreateZoom24 (Layout *layout, Graphic *graphic, double x, double y) {
+
+  int i, j, ii, jj, extra;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, zoomscale, Rx, Ry;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  unsigned char *in_pix,  *in_pix2;
+  unsigned char pixel1[256], pixel2[256], pixel3[256];
+  unsigned char pixvalue1, pixvalue2, pixvalue3;
+  unsigned long white;
+  unsigned char white1, white2, white3;
+
+  dx = layout[0].zoom.dx;
+  dy = layout[0].zoom.dy;
+  extra = 4 - (dx * 3) % 4;
+
+  if (layout[0].matrix.size == 0) {  /* create a test pattern */
+    REALLOCATE (layout[0].zoom.data, char, dy*(3*dx+extra));
+    bzero (layout[0].zoom.data, layout[0].zoom.dx*layout[0].zoom.dy);
+    layout[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+				       layout[0].zoom.data, layout[0].zoom.dx, layout[0].zoom.dy, 32, 0);
+    return;
+  }
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel1[i] = 0x0000ff & layout[0].cmap[i].pixel;
+    pixel2[i] = 0x0000ff & (layout[0].cmap[i].pixel >> 8);
+    pixel3[i] = 0x0000ff & (layout[0].cmap[i].pixel >> 16);
+  }
+  white = layout[0].white;
+  white1 = 0x0000ff & white;
+  white2 = 0x0000ff & (white >> 8);
+  white3 = 0x0000ff & (white >> 16);
+
+  zoomscale = MAX (5, layout[0].expand + 5);
+  expand = 1 / zoomscale;
+  expand_out = (int) zoomscale;
+  expand_in  = 1;
+
+  DX = layout[0].matrix.Naxis[0];
+  DY = layout[0].matrix.Naxis[1];
+  Rx = x - expand*(int)(0.5*(dx + 1)) + 1;
+  Ry = y - expand*(int)(0.5*(dy + 1)) + 1;
+
+  i_start = MIN (MAX (-Rx / expand, (1 - FRAC(Rx)) / expand), dx - expand_out + 1);
+  j_start = MIN (MAX (-Ry / expand, (1 - FRAC(Ry)) / expand), dy - expand_out + 1);
+  i_end   = MAX (MIN ((DX-Rx) / expand, dx - expand_out + 1), 0);
+  j_end   = MAX (MIN ((DY-Ry) / expand, dy - expand_out + 1), 0);
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  data = out_pix = (unsigned char *) layout[0].zoom.data;
+  in_pix  = (unsigned char *) (layout[0].matrix.buffer) + DX*(int)MAX(Ry,0) + (int)MAX(Rx,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  if ((i_end < i_start) || (j_end < j_start)) {
+    for (j = 0; j < dx*dy; j++, out_pix++) 
+      *out_pix = white;
+    return;
+  } 
+  
+  /**** fill in bottom area ****/
+  for (j = 0; j < j_start; j++) {
+    for (i = 0; i < dx; i++, out_pix+=3) {
+      out_pix[0] = white1;
+      out_pix[1] = white2;
+      out_pix[2] = white3;
+    }
+    out_pix += extra;
+  }
+
+  for (j = j_start; j < j_end; j+= expand_out, in_pix += expand_in*DX) {
+    out_pix = &data[j*(3*dx+extra)];
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) { 
+      out_pix2 = out_pix + jj*(3*dx + extra);
+      for (i = 0; i < i_start; i++, out_pix2+=3) {
+	out_pix2[0] = white1;
+	out_pix2[1] = white2;
+	out_pix2[2] = white3;
+      }
+    }
+    out_pix += 3*i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix+=3) {
+	out_pix[0] = pixel1[*in_pix2];
+	out_pix[1] = pixel2[*in_pix2];
+	out_pix[2] = pixel3[*in_pix2];
+      }
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 3*expand_out) { 
+	pixvalue1 = pixel1[*in_pix2];
+	pixvalue2 = pixel2[*in_pix2];
+	pixvalue3 = pixel3[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=3*(dx-expand_out)+extra) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2+=3) {
+	    out_pix2[0] = pixvalue1; 
+	    out_pix2[1] = pixvalue2; 
+	    out_pix2[2] = pixvalue3; 
+	  }
+	}
+      }
+    }
+    out_pix -= 3*dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*(3*dx+extra);
+      for (i = i_end; i < dx; i++, out_pix2+=3) {
+	out_pix2[0] = white1;
+	out_pix2[1] = white2;
+	out_pix2[2] = white3;
+      }
+    }
+  } 
+  
+  /*
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= (expand_out - (j_end - j_start) % expand_out);
+  */
+
+  out_pix = &data[j_end*(3*dx+extra)];
+  /**** fill in top area ****/
+  for (j = 0; j < (dy - j_end); j++) {
+    for (i = 0; i < dx; i++, out_pix+=3) { 
+      out_pix[0] = white1;
+      out_pix[1] = white2;
+      out_pix[2] = white3;
+    }
+    out_pix+=extra;
+  }
+
+  /*
+  out_pix = (unsigned char *) layout[0].zoom.data;
+  for (i = 0; i < dx*dy; i++) {
+    out_pix[3*i + 0] = white1;
+    out_pix[3*i + 1] = white2;
+    out_pix[3*i + 2] = white3;
+  }
+  for (j = 0; j < dy/2; j++) {
+    for (i = 0; i < dx; i++) {
+      out_pix[j*(extra + 3*dx) + 3*i + 0] = pixel1[10];
+      out_pix[j*(extra + 3*dx) + 3*i + 1] = pixel2[10];
+      out_pix[j*(extra + 3*dx) + 3*i + 2] = pixel3[10];
+    }
+
+  }
+  */
+  layout[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, 24, ZPixmap, 0, 
+					layout[0].zoom.data, layout[0].zoom.dx, layout[0].zoom.dy, 32, 0);
+  
+}
Index: /tags/start/Ohana/src/kii/zoom/CreateZoom32.c
===================================================================
--- /tags/start/Ohana/src/kii/zoom/CreateZoom32.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/zoom/CreateZoom32.c	(revision 12606)
@@ -0,0 +1,122 @@
+# include "Ximage.h"
+# define XPIX(x,Rx,S) (x*S + Rx)
+# define ZPIX(value,Rz1,Rz2) (value*Rz1 - Rz2)
+# define FRAC(a) ((a) - (int)(a))
+
+void CreateZoom32 (Layout *layout, Graphic *graphic, double x, double y) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, zoomscale, Rx, Ry;
+  int expand_in, expand_out;
+  unsigned int *out_pix, *out_pix2, *data;
+  unsigned char  *in_pix,  *in_pix2;
+  unsigned long pixel[256], pixvalue;
+  unsigned long white;
+
+  if (layout[0].matrix.size == 0) {  /* create a test pattern */
+    REALLOCATE (layout[0].zoom.data, char, 4*layout[0].zoom.dx*layout[0].zoom.dy);
+    layout[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+				       layout[0].zoom.data, layout[0].zoom.dx, layout[0].zoom.dy, 32, 0);
+    return;
+  }
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel[i] = layout[0].cmap[i].pixel;
+  }
+  white = layout[0].white;
+
+  zoomscale = MAX (5, layout[0].expand + 5);
+  expand = 1 / zoomscale;
+  expand_out = (int) zoomscale;
+  expand_in  = 1;
+
+  dx = layout[0].zoom.dx;
+  dy = layout[0].zoom.dy;
+  DX = layout[0].matrix.Naxis[0];
+  DY = layout[0].matrix.Naxis[1];
+  Rx = x - expand*(int)(0.5*(dx + 1)) + 1;
+  Ry = y - expand*(int)(0.5*(dy + 1)) + 1;
+
+  i_start = MIN (MAX (-Rx / expand, (1 - FRAC(Rx)) / expand), dx - expand_out + 1);
+  j_start = MIN (MAX (-Ry / expand, (1 - FRAC(Ry)) / expand), dy - expand_out + 1);
+  i_end   = MAX (MIN ((DX-Rx) / expand, dx - expand_out + 1), 0);
+  j_end   = MAX (MIN ((DY-Ry) / expand, dy - expand_out + 1), 0);
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  out_pix = (unsigned int *) layout[0].zoom.data;
+  data = (unsigned int *) layout[0].zoom.data;
+  in_pix  = (unsigned char *) (layout[0].matrix.buffer) + DX*(int)MAX(Ry,0) + (int)MAX(Rx,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  if ((i_end < i_start) || (j_end < j_start)) {
+    for (j = 0; j < dx*dy; j++, out_pix++) 
+      *out_pix = white;
+    return;
+  } 
+  
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < dx*j_start; j++, out_pix++) {
+    out_pix[0] = white;
+  }
+
+  for (j = j_start; j < j_end; j+= expand_out, out_pix+=(expand_out-1)*dx, in_pix += expand_in*DX) {
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) { 
+      out_pix2 = out_pix + jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2++) {
+	out_pix[0] = white;
+      }
+    }
+    out_pix += i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix++) {
+	out_pix[0] = pixel[*in_pix2];
+      }
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= expand_out) { 
+	pixvalue = *(pixel + *in_pix2);
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2++) {
+	    out_pix2[0] = pixvalue; 
+	  }
+	}
+      }
+    }
+    out_pix -= dropback;
+
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2++) {
+	out_pix2[0] = white;
+      }
+    }
+    out_pix += (dx - i_end);
+  } 
+  
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= (expand_out - (j_end - j_start) % expand_out);
+  
+  /**** fill in top area ****/
+  for (j = 0; (j < dx*(dy - j_end)) && (out_pix - (unsigned int *)layout[0].zoom.data < dx*dy); j++, out_pix++) { 
+    out_pix[0] = white;
+  }
+
+  out_pix = (unsigned int *)layout[0].zoom.data;
+  layout[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					layout[0].zoom.data, layout[0].zoom.dx, layout[0].zoom.dy, 32, 0);
+  
+}
Index: /tags/start/Ohana/src/kii/zoom/CreateZoom8.c
===================================================================
--- /tags/start/Ohana/src/kii/zoom/CreateZoom8.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/zoom/CreateZoom8.c	(revision 12606)
@@ -0,0 +1,140 @@
+# include "Ximage.h"
+# define XPIX(x,Rx,S) (x*S + Rx)
+# define ZPIX(value,Rz1,Rz2) (value*Rz1 - Rz2)
+# define FRAC(a) ((a) - (int)(a))
+
+void CreateZoom8 (Layout *layout, Graphic *graphic, double x, double y) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, zoomscale, Rx, Ry;
+  int expand_in, expand_out;
+  char  *out_pix, *out_pix2;
+  char  *in_pix,  *in_pix2;
+  unsigned long pixel[256], pixvalue;
+  unsigned long white;
+
+  if (layout[0].matrix.size == 0) {  /* create a test pattern */
+    REALLOCATE (layout[0].zoom.data, char, layout[0].zoom.dx*layout[0].zoom.dy);
+    bzero (layout[0].zoom.data, layout[0].zoom.dx*layout[0].zoom.dy);
+    layout[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+				       layout[0].zoom.data, layout[0].zoom.dx, layout[0].zoom.dy, 8, 0);
+    return;
+  }
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel[i] = layout[0].cmap[i].pixel;
+  }
+  white = layout[0].white;
+
+  zoomscale = MAX (5, layout[0].expand + 5);
+  expand = 1 / zoomscale;
+  expand_out = (int) zoomscale;
+  expand_in  = 1;
+
+  /*
+  dx = layout[0].zoom.dx;
+  dy = layout[0].zoom.dy;
+  DX = layout[0].matrix.Naxis[0];
+  DY = layout[0].matrix.Naxis[1];
+  Rx = 0.5*(DX - (dx - 1)*expand) - x;
+  Ry = 0.5*(DY - (dy - 1)*expand) - y;
+  data coords of 0,0 point in pic array 
+  X = 0.5*layout[0].matrix.Naxis[0] - expand*((int)(0.5*layout[0].zoom.dx + 0.5) - 0.0) - layout[0].X;
+  Y = 0.5*layout[0].matrix.Naxis[1] - expand*((int)(0.5*layout[0].zoom.dy + 0.5) - 0.0) - layout[0].Y;  
+  i_start = MIN (MAX (-Rx / expand, 0), dx - expand_out + 1);
+  j_start = MIN (MAX (-Ry / expand, 0), dy - expand_out + 1);
+  i_end   = MAX (MIN ((DX-Rx) / expand, dx - expand_out + 1), 0);
+  j_end   = MAX (MIN ((DY-Ry) / expand, dy - expand_out + 1), 0);
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  out_pix = layout[0].zoom.data;
+  in_pix  = (char *) (layout[0].matrix.buffer) + DX*(int)MAX(Y,0) + (int)MAX(X,0);
+
+  */
+
+  dx = layout[0].zoom.dx;
+  dy = layout[0].zoom.dy;
+  DX = layout[0].matrix.Naxis[0];
+  DY = layout[0].matrix.Naxis[1];
+  Rx = x - expand*(int)(0.5*(dx + 1)) + 1;
+  Ry = y - expand*(int)(0.5*(dy + 1)) + 1;
+
+  i_start = MIN (MAX (-Rx / expand, (1 - FRAC(Rx)) / expand), dx - expand_out + 1);
+  j_start = MIN (MAX (-Ry / expand, (1 - FRAC(Ry)) / expand), dy - expand_out + 1);
+  i_end   = MAX (MIN ((DX-Rx) / expand, dx - expand_out + 1), 0);
+  j_end   = MAX (MIN ((DY-Ry) / expand, dy - expand_out + 1), 0);
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  out_pix = (char *) layout[0].zoom.data;
+  in_pix  = (char *) (layout[0].matrix.buffer) + DX*(int)MAX(Ry,0) + (int)MAX(Rx,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  if ((i_end < i_start) || (j_end < j_start)) {
+    for (j = 0; j < dx*dy; j++, out_pix++) 
+      *out_pix = white;
+    return;
+  } 
+  
+  /**** fill in bottom area ****/
+  for (j = 0; j < dx*j_start; j++, out_pix++) 
+    *out_pix = white;
+  
+  for (j = j_start; j < j_end; j+= expand_out, out_pix+=(expand_out-1)*dx, in_pix += expand_in*DX) {
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) { 
+      out_pix2 = out_pix + jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2++) {
+	*out_pix2 = white;
+      }
+    }
+    out_pix += i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix++)
+	*out_pix = *(pixel + *in_pix2); 
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= expand_out) { 
+	pixvalue = *(pixel + *in_pix2);
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2++) {
+	    *out_pix2 = pixvalue;
+	  }
+	}
+      }
+    }
+    out_pix -= dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2++) {
+	*out_pix2 = white;
+      }
+    }
+    out_pix += (dx - i_end);
+    
+  } 
+  
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= expand_out - (j_end - j_start) % expand_out;
+  
+  /**** fill in top area ****/
+  for (j = 0; (j < dx*(dy - j_end)) && (out_pix - layout[0].zoom.data < dx*dy); j++, out_pix++) { 
+    *out_pix = white;
+  }
+
+  layout[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					layout[0].zoom.data, layout[0].zoom.dx, layout[0].zoom.dy, 8, 0);
+  
+}
Index: /tags/start/Ohana/src/kii/zoom/CrossHairs.c
===================================================================
--- /tags/start/Ohana/src/kii/zoom/CrossHairs.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/zoom/CrossHairs.c	(revision 12606)
@@ -0,0 +1,66 @@
+# include "Ximage.h"
+
+void CrossHairs (Graphic *graphic, Layout *layout) {
+
+  int x0, x1, x5, x7;
+  int y0, y2, y4, y5;
+  double zoomscale;
+
+  zoomscale = MAX (5, layout[0].expand + 5);
+  x0 = (zoomscale) * (0.5 * (ZOOM_X + 1) / zoomscale - 2.5) + layout[0].zoom.x;
+  x5 = (zoomscale) * (0.5 * (ZOOM_X + 1) / zoomscale - 0.5) + layout[0].zoom.x;
+  x7 = (zoomscale) * (0.5 * (ZOOM_X + 1) / zoomscale + 0.5) + layout[0].zoom.x;
+  x1 = (zoomscale) * (0.5 * (ZOOM_X + 1) / zoomscale + 2.5) + layout[0].zoom.x;
+						    	 
+  y4 = (zoomscale) * (0.5 * (ZOOM_Y + 1) / zoomscale - 2.5) + layout[0].zoom.y;
+  y2 = (zoomscale) * (0.5 * (ZOOM_Y + 1) / zoomscale - 0.5) + layout[0].zoom.y;
+  y0 = (zoomscale) * (0.5 * (ZOOM_Y + 1) / zoomscale + 0.5) + layout[0].zoom.y;
+  y5 = (zoomscale) * (0.5 * (ZOOM_Y + 1) / zoomscale + 2.5) + layout[0].zoom.y;
+
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+  
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x0, y0, x5, y0);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x5, y0, x5, y5);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7, y5, x7, y0);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7, y0, x1, y0);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x0, y2, x5, y2);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x5, y2, x5, y4);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7, y4, x7, y2);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7, y2, x1, y2);
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x0, y0+1, x5-1, y0+1);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x5-1, y0+1, x5-1, y5);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7+1, y5, x7+1, y0+1);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7+1, y0+1, x1, y0+1);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x0, y2-1, x5-1, y2-1);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x5-1, y2-1, x5-1, y4);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7+1, y4, x7+1, y2-1);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7+1, y2-1, x1, y2-1);
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+
+}
Index: /tags/start/Ohana/src/kii/zoom/UpdatePointer.c
===================================================================
--- /tags/start/Ohana/src/kii/zoom/UpdatePointer.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/zoom/UpdatePointer.c	(revision 12606)
@@ -0,0 +1,58 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+int UpdatePointer (Graphic *graphic, Layout *layout, XMotionEvent *event) {
+
+  int textpad;
+  double  x, y, z;
+  char line[100];
+
+  if (MOVE_POINTER && InPicture ((XButtonEvent *)event, &layout[0].picture)) {
+
+    Screen_to_Image (&x, &y, (double)event[0].x, (double)event[0].y, layout);
+
+    if ((x >= 0) && (x < layout[0].matrix.Naxis[0]) && (y >= 0) && (y < layout[0].matrix.Naxis[1])) {
+      /*
+      X = event[0].x - layout[0].picture.x;
+      Y = event[0].y - layout[0].picture.y;
+      pix = MIN (MAX (X + Y*layout[0].picture.dx, 0), layout[0].picture.dx*layout[0].picture.dy - 1);
+      z = layout[0].range * layout[0].picture.data[pix] / layout[0].Npixels + layout[0].zero;
+      */
+      z = -1;
+    }
+    else
+      z = -1;
+    layout[0].x = x;
+    layout[0].y = y;
+    layout[0].z = z;
+    
+    UpdateStatusBox (graphic, layout, x, y, z, 0);
+    XFlush (graphic[0].display);
+      
+    CreateZoom (layout, graphic, x, y);  
+    XPutImage (graphic[0].display, graphic[0].window, graphic[0].gc,
+	       layout[0].zoom.pix, 0, 0, 
+	       layout[0].zoom.x, layout[0].zoom.y, 
+	       layout[0].zoom.dx, layout[0].zoom.dy);
+    CrossHairs (graphic, layout);
+    XFlush (graphic[0].display);
+    
+  }
+  
+  if (InPicture ((XButtonEvent *)event, &layout[0].cmapbar)) {
+    z = layout[0].zero  + layout[0].range * (event[0].x - layout[0].cmapbar.x) / layout[0].cmapbar.dx;
+    textpad = graphic[0].font[0].ascent;
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc,
+                  layout[0].text_x + 1, layout[0].text_y + 1, ZOOM_X - 2, textpad + PAD1 + 1);
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+    bzero (line, 100);
+    sprintf (line, "%25.2f", z);
+    XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+                 layout[0].text_x + PAD1, layout[0].text_y + textpad + PAD1, 
+		 line, strlen(line));
+    
+  }
+
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/kii/zoom/UpdateStatusBox.c
===================================================================
--- /tags/start/Ohana/src/kii/zoom/UpdateStatusBox.c	(revision 12606)
+++ /tags/start/Ohana/src/kii/zoom/UpdateStatusBox.c	(revision 12606)
@@ -0,0 +1,63 @@
+# include "Ximage.h"
+
+void UpdateStatusBox (Graphic *graphic, Layout *layout, double x, double y, double z, int mode) {
+
+  int textpad;
+  double ra, dec; 
+  char line[100];
+
+  XY_to_RD (&ra, &dec, x, y, &layout[0].coords);
+
+  textpad = graphic[0].font[0].ascent;
+
+  if (mode) {
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc,
+		    layout[0].text_x, layout[0].text_y, ZOOM_X, 6*textpad+7*PAD1);  
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+    XDrawRectangle (graphic[0].display, graphic[0].window, graphic[0].gc,
+		    layout[0].text_x, layout[0].text_y, ZOOM_X, 6*textpad+7*PAD1);
+  
+    bzero (line, 100);
+    sprintf (line, "(%d x %d) @ %d                                         ", 
+	     layout[0].picture.dx, layout[0].picture.dy, layout[0].expand); 
+    XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		 layout[0].text_x + PAD1, layout[0].text_y + 4*textpad + 4*PAD1, line, 25);
+    
+    bzero (line, 100);
+    sprintf (line, "%-25s", layout[0].file); 
+    XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		 layout[0].text_x + PAD1, layout[0].text_y + 5*textpad + 5*PAD1, line, strlen(line));
+    
+    bzero (line, 100);
+    sprintf (line, "(%s)                                          ", layout[0].buffer_name); 
+    XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		 layout[0].text_x + PAD1, layout[0].text_y + 6*textpad + 6*PAD1, line, 25);
+    
+  } else {
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc,
+		    layout[0].text_x + 1, layout[0].text_y + 1, ZOOM_X - 2, 3*textpad+3*PAD1 +1);  
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+  }
+  bzero (line, 100);
+  sprintf (line, "%25.3f", z);
+  XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	       layout[0].text_x + PAD1, layout[0].text_y + textpad + PAD1, line, strlen(line));
+  
+  bzero (line, 100);
+  sprintf (line, "%12.1f %12.1f", x, y);
+  XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	       layout[0].text_x + PAD1, layout[0].text_y + 2*textpad + 2*PAD1, line, strlen(line));
+  
+  bzero (line, 100);
+  if (DECIMAL_DEG) {
+    sprintf (line, "%12.6f %12.6f", ra, dec); 
+  } else {
+    hh_hms (line, ra, dec, ':');
+  }
+  XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	       layout[0].text_x + PAD1, layout[0].text_y + 3*textpad + 3*PAD1, line, strlen(line));
+  
+ 
+}
Index: /tags/start/Ohana/src/libdummy/Makefile
===================================================================
--- /tags/start/Ohana/src/libdummy/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/libdummy/Makefile	(revision 12606)
@@ -0,0 +1,25 @@
+# this Makefile creates a dummy version of libsocket.a and libnsl.a
+# both are required for linking on SUN and HP, but don't exist and 
+# are not needed for linux.  creating and empty, dummy library allows 
+# the linking lines to be identical
+
+default: libdummy
+install: libdummy
+
+libsocket.a: dummy.c
+
+libdummy: libsocket.a
+	gcc -c -o dummy.o dummy.c
+	ar rcv libsocket.a dummy.o
+	ranlib libsocket.a
+	cp libsocket.a ../../lib/$(ARCH)/
+	ar rcv libnsl.a dummy.o
+	ranlib libnsl.a
+	cp libnsl.a ../../lib/$(ARCH)/
+
+# utilities #################################################
+clean:	
+	rm -f *.a
+	rm -f *.o
+	rm -f *~
+	rm -f #*
Index: /tags/start/Ohana/src/libdummy/dummy.c
===================================================================
--- /tags/start/Ohana/src/libdummy/dummy.c	(revision 12606)
+++ /tags/start/Ohana/src/libdummy/dummy.c	(revision 12606)
@@ -0,0 +1,9 @@
+# include <stdio.h>
+
+do_nothing_at_all () {
+  
+  int i;
+
+  i = 10;
+
+}
Index: /tags/start/Ohana/src/libfits/Makefile
===================================================================
--- /tags/start/Ohana/src/libfits/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/libfits/Makefile	(revision 12606)
@@ -0,0 +1,95 @@
+include ../../Configure
+HOME	=	.
+
+HEAD	=	$(HOME)/header
+MATR	=	$(HOME)/matrix
+TABL	=	$(HOME)/table
+LIB	=	$(HOME)/lib
+INC	=	$(HOME)/include
+MAN	= 	$(HOME)/doc
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+INCS	=	-I$(INC)  -I$(LINC)/$(ARCH)
+CFLAGS	=	-o $*.$(ARCH).o $(INCS) -D$(ARCH)
+LFLAGS	=	-c $(INCS)
+
+default: install
+
+sample: /h/eugene/src/ohana/lib/linux/libFITS.a sample.o
+	gcc -g -o sample sample.o /h/eugene/src/ohana/lib/linux/libFITS.a -lm
+
+sample2: /h/eugene/src/ohana/lib/linux/libFITS.a sample2.o
+	gcc -g -o sample2 sample2.o /h/eugene/src/ohana/lib/linux/libFITS.a -lm
+
+fits: $(DESTLIB)/libFITS.a
+
+install: $(DESTINC)/fitsio.h $(DESTLIB)/libFITS.a $(DESTMAN)/fits.1
+
+HEADER_OBJ = \
+$(HEAD)/F_modify.$(ARCH).o			$(HEAD)/F_create_H.$(ARCH).o  \
+$(HEAD)/F_free_H.$(ARCH).o			$(HEAD)/F_H_field.$(ARCH).o   \
+$(HEAD)/F_read_H.$(ARCH).o			$(HEAD)/F_write_H.$(ARCH).o   \
+$(HEAD)/F_scan.$(ARCH).o			$(HEAD)/F_print.$(ARCH).o     \
+$(HEAD)/F_copy_H.$(ARCH).o			$(HEAD)/F_delete.$(ARCH).o    \
+$(HEAD)/F_read_XH.$(ARCH).o			$(HEAD)/F_init_H.$(ARCH).o
+
+MATRIX_OBJ = \
+$(MATR)/F_add_M_value.$(ARCH).o 		$(MATR)/F_add_M.$(ARCH).o        \
+$(MATR)/F_create_M.$(ARCH).o 			$(MATR)/F_divide_M.$(ARCH).o     \
+$(MATR)/F_free_M.$(ARCH).o 			$(MATR)/F_copy_M.$(ARCH).o       \
+$(MATR)/F_write_M.$(ARCH).o 			$(MATR)/F_get_M_value.$(ARCH).o  \
+$(MATR)/F_multiply_M.$(ARCH).o 			$(MATR)/F_read_M.$(ARCH).o       \
+$(MATR)/F_insert_M.$(ARCH).o 			$(MATR)/F_set_M_value.$(ARCH).o  \
+$(MATR)/F_convert_format.$(ARCH).o              $(MATR)/F_read_segment.$(ARCH).o \
+$(MATR)/F_read_portion.$(ARCH).o		$(MATR)/F_load_M.$(ARCH).o	 \
+$(MATR)/F_matrix.$(ARCH).o
+
+TABLE_OBJ = \
+$(TABL)/F_create_T.$(ARCH).o 			$(TABL)/F_create_TH.$(ARCH).o    \
+$(TABL)/F_read_T.$(ARCH).o			$(TABL)/F_read_TH.$(ARCH).o      \
+$(TABL)/F_write_T.$(ARCH).o			$(TABL)/F_write_TH.$(ARCH).o     \
+$(TABL)/F_define_column.$(ARCH).o		$(TABL)/F_table_format.$(ARCH).o \
+$(TABL)/F_set_column.$(ARCH).o			$(TABL)/F_get_column.$(ARCH).o   \
+$(TABL)/F_table_row.$(ARCH).o			$(TABL)/F_free_T.$(ARCH).o
+
+# $(TABL)/F_table_column.$(ARCH).o		\
+# $(TABL)/F_get_T_column.$(ARCH).o		\
+# $(TABL)/F_get_T_value.$(ARCH).o
+
+LIBOBJ = $(HEADER_OBJ) $(MATRIX_OBJ) $(TABLE_OBJ)
+
+$(LIBOBJ): $(INC)/fits.h $(INC)/fitsio.h
+
+$(LIB)/libFITS.$(ARCH).a: $(LIBOBJ)
+	rm -f $(LIB)/libFITS.$(ARCH).a
+	ar rcv $(LIB)/libFITS.$(ARCH).a $(LIBOBJ)
+	ranlib $(LIB)/libFITS.$(ARCH).a
+
+$(DESTLIB)/libFITS.a: $(LIB)/libFITS.$(ARCH).a 
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	rm -f  $(DESTLIB)/libFITS.a
+	cp $(LIB)/libFITS.$(ARCH).a $(DESTLIB)/libFITS.a
+
+$(DESTINC)/fitsio.h: $(INC)/fitsio.h
+	@if [ ! -d $(DESTINC) ]; then mkdir -p $(DESTINC); fi
+	rm -f $(DESTINC)/fitsio.h
+	cp $(INC)/fitsio.h $(DESTINC)/
+
+$(DESTMAN)/fits.1: $(MAN)/fits.1
+	@if [ ! -d $(DESTMAN) ]; then mkdir -p $(DESTMAN); fi
+	rm -f $(DESTMAN)/fits.1
+	cp $(MAN)/fits.1    $(DESTMAN)/
+
+clean:
+	rm -f */*.a
+	rm -f */*.o
+	rm -f */*~
+	rm -f */#*
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
+
Index: /tags/start/Ohana/src/libfits/doc/README
===================================================================
--- /tags/start/Ohana/src/libfits/doc/README	(revision 12606)
+++ /tags/start/Ohana/src/libfits/doc/README	(revision 12606)
@@ -0,0 +1,33 @@
+
+Installing gene's FITS C libraries.
+
+These FITS libraries are part of a larger package, but the rest of the
+package is not needed to make the libraries.  To install it for a
+specific system, the Makefile expects the environment variable ARCH to
+be defined to something appropriate to your machine (ie, sol for
+solaris, or linux for linux machines.  The resulting .o files then
+have machine specific names (ie, F_read_M.sol.o), making it easy to
+recompile for multiple machines.  The compiled library also has
+a machine specific names (libFITS.sol.a), and the installed version is
+then placed with a generic name in a machine specific locations (ie
+lib/sol/libFITS.a).  
+
+
+Edit the Configure file match your current system.  As it stands, the Makefile
+expects the fits directory to be $(ROOT)/src/fits.  The XINC and XLIB
+variables are not actually used by the fits libraries, so you can
+igore them.  
+
+BYTE_SWAP: byte swapping can be forced by placing a -DBYTE_SWAP option
+on the CC line in Configure (see commented out line).  Byte swapping
+is also enabled automatically if ARCH = linux.  (If you have other
+byte swapped machines, you can edit include/fits.h to enable them
+automatically as well).
+
+define an environment variable ARCH and run "make" or "make install"
+to install the library.
+
+good luck
+
+gene
+
Index: /tags/start/Ohana/src/libfits/doc/fits.1
===================================================================
--- /tags/start/Ohana/src/libfits/doc/fits.1	(revision 12606)
+++ /tags/start/Ohana/src/libfits/doc/fits.1	(revision 12606)
@@ -0,0 +1,256 @@
+.ad l
+.nh
+.TH FITS 1.0 "Sept 18, 1992" "Version 1.0"
+.SH NAME
+\fIFITS HEADER routines:\fP  fits_read_header, fits_write_header, 
+fits_header_field,  fits_scan, fits_print, fits_copy_header,
+fits_create_header, fits_free_header.
+
+\fIFITS MATRIX routines:\fP  fits_read_matrix, fits_write_matrix, 
+fits_get_matrix_value, fits_set_matrix_value, fits_create_matrix, 
+fits_free_matrix, fits_insert_array
+
+.SH SYNOPSIS
+.nf
+.ft B
+(compile with -lFITS)
+# include <fitsio.h>
+.LP
+\fI FITS Header Routines \fP
+.RS
+int   fits_read_header (filename, header)
+char      *filename;
+Header    *header;
+
+int   fits_write_header (filename, header)
+char      *filename;
+Header    *header;
+
+char *fits_header_field (header, field, N)
+Header    *header;
+char      *field;
+int        N;
+
+int   fits_scan   (header, field, mode, N, value)
+int   fits_print  (header, field, mode, N, value)
+int   fits_modify (header, field, mode, N, value)
+Header    *header;
+char      *field, *mode, *value;
+int        N;
+
+int   fits_create_header (header)
+Header    *header;
+
+int   fits_copy_header (header1, header2)
+Header    *header1;
+Header    *header2;
+
+int   fits_free_header (header)
+Header    *header;
+
+.RE
+.LP
+\fI FITS Matrix Routines \fP
+.RS 
+int   fits_read_matrix (filename, matrix)
+char      *filename;
+Matrix    *matrix;
+
+int   fits_write_matrix (filename, matrix)
+char      *filename;
+Matrix    *matrix;
+
+int   fits_get_matrix_value (matrix, x, y)
+Matrix    *matrix;
+int        x, y;
+
+void  fits_set_matrix_value (matrix, x, y, value)
+Matrix    *matrix;
+int        x, y;
+double     value;
+
+int   fits_create_matrix (header, matrix)
+Header    *header;
+Matrix    *matrix;
+
+int   fits_insert_array (matrix, array, x, y)
+Matrix    *matrix;
+Matrix    *array;
+int        x, y;
+
+int   fits_free_matrix (matrix)
+Matrix    *matrix;
+
+
+.SH DESCRIPTION
+.LP
+These functions allow for FITS I/O in a general C-like way.  There are
+several relavant structures defined in \fIfitsio.h\fP (see
+STRUCTURES below).  
+
+\fI FITS Header Routines \fP
+
+.RS 
+\fIfits_read_header\fP opens a file and reads the FITS header into
+a Header structure.  No error checking, except file existence is
+currently provided.  
+
+\fIfits_write_header\fP opens a file and write the Header structure
+into the file in FITS format.  It also puts a RETURN character (0x0a)
+into the N*80 bytes (the end of every header line).  This is not FITS
+standard, but it makes the header more readable.
+
+\fIfits_header_field\fP returns a pointer to the start of the Nth
+header line with the given keyword "field".  No error check is
+provided, except to note the lack of such a field (returns a NULL
+value).
+
+\fIfits_scan\fP, \fIfits_print\fP and \fIfits_modify\fP are modeled on
+\fIfscanf\fP and \fIfprintf\fP but act on a FITS header instead of a
+stream.  \fIfits_print\fP write a new entry, while \fIfits_modify\fP
+alters the value of an existing entry (wiping out the comment line).
+\fBdNote:\fP \fIfits_modify\fP will create a new entry, but \fIfits_print\fP 
+will \fInot\fP modify and existing entry!
+The following modes are supported:
+
+.RS
+.PD 0
+.TP
+%d 
+A signed decimal integer is expected.
+.TP
+%u 
+An unsigned decimal integer is expected.
+.TP
+%ld 
+A long decimal integer is expected.
+.TP
+%hd 
+A short decimal integer is expected.
+.TP
+%f 
+A float is expected.
+.TP 
+%lf 
+A double is expected.
+.TP
+%t 
+A boolean is expected.  The pointer should be of type \fIbool\fP.
+.TP
+%s 
+A string is expected.  The pointer should be of type \fIchar\fP.
+.TP
+%S A comment line string is expected.  The pointer should be of type \fIchar\fP.
+.RE
+
+\fIfits_create_header\fP creates a Header structure based on a partially filled 
+Header structure.  The mandatory structure values (simple, bitpix, Naxes, 
+Naxis[N], extend, unsign) must be set.  The buffer will be filled in 
+according to these values.
+
+\fIfits_copy_header\fP copies the header1 to header2;
+
+\fIfits_free_header\fP frees the allocated pointers associated with the 
+header.
+.RE
+
+\fI FITS Matrix Routines \fP
+
+.RS
+\fIfits_read_matrix\fP opens the given file and reads the matrix structure.
+There is, of course, no decent error checking.
+
+\fIfits_write_matrix\fP opens the given file and writes the matrix structure.
+The matrix is written to the end of the file, in the assumption that
+there is already a Header written to the file.  
+There is, of course, no decent error checking.
+
+\fIfits_get_matrix_value\fP returns the value of the pixel at the given (2-D) 
+coordinates.
+
+\fIfits_set_matrix_value\fP sets the value of the pixel at the given (2-D) 
+coordinates.
+
+\fIfits_create_matrix\fP creates a matrix which corresponds to the format
+described in the Header structure.
+
+\fIfits_copy_matrix\fP makes a duplicate copy of header1 in header2. 
+
+\fIfits_free_matrix\fP frees the allocated pointers associated with the
+Matrix.
+
+\fIfits_insert_array\fP set the values of the Matrix to those of the
+array (a small Matrix), using the x,y values as a relative offset.
+.RE
+
+.SH STRUCTURES
+.PP
+There are several important structures defined in \fIfitsio.h\fP
+which are described here.
+
+# define bool char
+
+# typedef struct {
+  bool                    simple;
+  bool                    unsign;
+  bool                    extend;
+  int                     bitpix;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  double                  bzero, bscale;
+  char                   *buffer;
+ } Header;
+
+typedef struct {
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     bitpix;
+  bool                    unsign;
+  double                  bzero, bscale;
+  char                   *buffer;
+  int                     size;
+ } Matrix;
+
+REMINDER: data = (byte value) * bscale + bzero
+
+\fIbool\fP is defined to be a char.
+
+\fIHeader\fP is a structure for holding all header information.  It
+consists of values of the basic header fields required for a FITS file
+(SIMPLE, EXTEND, BITPIX, NAXIS, NAXIS1, NAXIS2...) as well as a
+pointer to the header data itself (\fIbuffer\fP) and the number of
+bytes in the header buffer (\fIsize\fP).  
+
+\fIMatrix\fP is a structure for holding the image matrix data.  It
+consists of the \fINaxes\fP, and \fINaxis[10]\fP entries as well
+as the \fIbuffer\fP and the \fIsize\fP entries.
+
+
+.SH COPYRIGHT
+Copyright 1991 Eugene Magnier
+.PP                                                
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of MIT not be used in
+advertising or publicity pertaining to distribution of the software
+without specific, written prior permission.  MIT and the authors make
+no representations about the suitability of this software for any
+purpose.  It is provided "as is" without express or implied warranty.
+.PP
+MIT and the authors disclaim all warranties with regard to this
+software, including all implied warranties of merchantability and
+fitness, in no event shall MIT or the authors be liable for any
+special, indirect or consequential damages or any damages whatsoever
+resulting from loss of use, data or profits, whether in an action of
+contract, negligence or other tortious action, arising out of or in
+connection with the use or performance of this software.
+.SH ACKNOWLEDGEMENTS
+Walter H.G. Lewin for inspiration
+.PP
+NASA for lots of money
+.PP
+.SH AUTHOR
+Eugene Magnier.  MIT - CSR
Index: /tags/start/Ohana/src/libfits/doc/fits.tex
===================================================================
--- /tags/start/Ohana/src/libfits/doc/fits.tex	(revision 12606)
+++ /tags/start/Ohana/src/libfits/doc/fits.tex	(revision 12606)
@@ -0,0 +1,62 @@
+\documentstyle{AA}
+
+\title{FITS I/O Routine}
+\author{gene magnier}
+
+\begin{document}
+\maketitle
+
+        This file documents the C routines I have created for easy
+manipulation of FITS files.  For now, I will assume familiarity with C
+and the FITS format definitions.  (Maybe I will expand this text
+later).  This set of routines consists of a number of subroutines,
+each of which is contained within its own file.  The subroutines fall into
+three classes: those which manipulte headers, those which manipulate
+data matrices, and those which manipulate tables.  Every subroutine
+has a name which starts with the word {\tt fits}, and includes the word
+{\tt header, matrix,} or {\tt table}.  The file names use the letters
+F, H, M, and T as abbreviations for these words.  Below, I list all of
+the subroutines, and following this I describe them and their use.   
+
+\begin{center}
+\begin{tabular}{ll}
+\hline
+routine name               &   file name \\
+\hline
+fits\_read\_header         &   F\_read\_H.c            \\
+fits\_write\_header        &   F\_write\_H.c           \\
+fits\_header\_field        &   F\_H\_field.c           \\
+fits\_scan                 &   F\_scan.c               \\
+fits\_print                &   F\_print.c              \\
+fits\_modify               &   F\_modify.c             \\
+fits\_delete               &   F\_delete.c             \\
+fits\_create\_header       &   F\_create\_H.c          \\
+fits\_copy\_header         &   F\_copy\_H.c            \\
+fits\_free\_header         &   F\_free\_H.c            \\
+\hline
+fits\_read\_matrix         &   F\_read\_M.c            \\
+fits\_write\_matrix        &   F\_write\_M.c           \\
+fits\_get\_matrix\_value   &   F\_get\_M\_value.c      \\
+fits\_set\_matrix\_value   &   F\_set\_M\_value.c      \\
+fits\_add\_matrix\_value   &   F\_add\_M\_value.c      \\
+fits\_create\_matrix       &   F\_create\_M.c          \\
+fits\_copy\_matrix         &   F\_copy\_M.c            \\
+fits\_free\_matrix         &   F\_free\_M.c            \\
+fits\_add\_matrix          &   F\_add\_M.c             \\
+fits\_multiply\_matrix     &   F\_multiply\_M.c        \\
+fits\_divide\_matrix       &   F\_divide\_M.c          \\
+fits\_insert\_matrix       &   F\_insert\_M.c          \\
+fits\_insert\_array        &   F\_insert\_array.c      \\
+\hline
+fits\_read\_Theader        &   F\_read\_TH.c           \\
+fits\_write\_Theader       &   F\_write\_TH.c          \\
+fits\_create\_Theader      &   F\_create\_TH.c         \\
+fits\_read\_table          &   F\_read\_T.c            \\
+fits\_get\_table\_column   &   F\_get\_T\_column.c     \\
+fits\_get\_table\_value    &   F\_get\_T\_value.c      \\
+\hline
+\end{tabular}
+\end{center}
+
+\end{document}
+
Index: /tags/start/Ohana/src/libfits/doc/fits.txt
===================================================================
--- /tags/start/Ohana/src/libfits/doc/fits.txt	(revision 12606)
+++ /tags/start/Ohana/src/libfits/doc/fits.txt	(revision 12606)
@@ -0,0 +1,253 @@
+
+FITS(1.0)         MISC. REFERENCE MANUAL PAGES          FITS(1.0)
+
+NAME
+     _F_I_T_S _H_E_A_D_E_R _r_o_u_t_i_n_e_s:  fits_read_header, fits_write_header,
+     fits_header_field,  fits_scan, fits_print, fits_copy_header,
+     fits_create_header, fits_free_header.
+
+     _F_I_T_S _M_A_T_R_I_X _r_o_u_t_i_n_e_s:  fits_read_matrix, fits_write_matrix,
+     fits_get_matrix_value, fits_set_matrix_value,
+     fits_create_matrix, fits_free_matrix, fits_insert_array
+
+SYNOPSIS
+     (compile with -lFITS)
+     # include <fitsio.h>
+
+      _F_I_T_S _H_e_a_d_e_r _R_o_u_t_i_n_e_s
+          int   fits_read_header (filename, header)
+          char      *filename;
+          Header    *header;
+
+          int   fits_write_header (filename, header)
+          char      *filename;
+          Header    *header;
+
+          char *fits_header_field (header, field, N)
+          Header    *header;
+          char      *field;
+          int        N;
+
+          int   fits_scan   (header, field, mode, value, N)
+          int   fits_print  (header, field, mode, value, N)
+          int   fits_modify (header, field, mode, value, N)
+          Header    *header;
+          char      *field, *mode, *value;
+          int        N;
+
+          int   fits_create_header (header)
+          Header    *header;
+
+          int   fits_copy_header (header1, header2)
+          Header    *header1;
+          Header    *header2;
+
+          int   fits_free_header (header)
+          Header    *header;
+
+      _F_I_T_S _M_a_t_r_i_x _R_o_u_t_i_n_e_s
+          int   fits_read_matrix (filename, matrix)
+          char      *filename;
+          Matrix    *matrix;
+
+          int   fits_write_matrix (filename, matrix)
+
+Version 1.0        Last change: Sept 18, 1992                   1
+
+FITS(1.0)         MISC. REFERENCE MANUAL PAGES          FITS(1.0)
+
+          char      *filename;
+          Matrix    *matrix;
+
+          int   fits_get_matrix_value (matrix, x, y)
+          Matrix    *matrix;
+          int        x, y;
+
+          void  fits_set_matrix_value (matrix, x, y, value)
+          Matrix    *matrix;
+          int        x, y;
+          double     value;
+
+          int   fits_create_matrix (header, matrix)
+          Header    *header;
+          Matrix    *matrix;
+
+          int   fits_insert_array (matrix, array, x, y)
+          Matrix    *matrix;
+          Matrix    *array;
+          int        x, y;
+
+          int   fits_free_matrix (matrix)
+          Matrix    *matrix;
+
+DESCRIPTION
+     These functions allow for FITS I/O in a general C-like way.
+     There are several relavant structures defined in _f_i_t_s_i_o._h
+     (see STRUCTURES below).
+
+      _F_I_T_S _H_e_a_d_e_r _R_o_u_t_i_n_e_s
+
+          _f_i_t_s__r_e_a_d__h_e_a_d_e_r opens a file and reads the FITS header
+          into a Header structure.  No error checking, except
+          file existence is currently provided.
+
+          _f_i_t_s__w_r_i_t_e__h_e_a_d_e_r opens a file and write the Header
+          structure into the file in FITS format.  It also puts a
+          RETURN character (0x0a) into the N*80 bytes (the end of
+          every header line).  This is not FITS standard, but it
+          makes the header more readable.
+
+          _f_i_t_s__h_e_a_d_e_r__f_i_e_l_d returns a pointer to the start of the
+          Nth header line with the given keyword "field".  No
+          error check is provided, except to note the lack of
+          such a field (returns a NULL value).
+
+          _f_i_t_s__s_c_a_n, _f_i_t_s__p_r_i_n_t and _f_i_t_s__m_o_d_i_f_y are modeled on
+          _f_s_c_a_n_f and _f_p_r_i_n_t_f but act on a FITS header instead of
+          a stream.  _f_i_t_s__p_r_i_n_t write a new entry, while
+          _f_i_t_s__m_o_d_i_f_y alters the value of an existing entry
+
+Version 1.0        Last change: Sept 18, 1992                   2
+
+FITS(1.0)         MISC. REFERENCE MANUAL PAGES          FITS(1.0)
+
+          (wiping out the comment line).  The following modes are
+          supported:
+
+               %d   A signed decimal integer is expected.
+               %u   An unsigned decimal integer is expected.
+               %ld  A long decimal integer is expected.
+               %hd  A short decimal integer is expected.
+               %f   A float is expected.
+               %lf  A double is expected.
+               %t   A boolean is expected.  The pointer should be
+                    of type _b_o_o_l.
+               %s   A string is expected.  The pointer should be
+                    of type _c_h_a_r.
+                    should be of type _c_h_a_r.
+               %S A comment line string is expected.  The pointer
+
+          _f_i_t_s__c_r_e_a_t_e__h_e_a_d_e_r creates a Header structure based on
+          a partially filled Header structure.  The mandatory
+          structure values (simple, bitpix, Naxes, Naxis[N],
+          extend, unsign) must be set.  The buffer will be filled
+          in according to these values.
+
+          _f_i_t_s__c_o_p_y__h_e_a_d_e_r copies the header1 to header2;
+
+          _f_i_t_s__f_r_e_e__h_e_a_d_e_r frees the allocated pointers
+          associated with the header.
+
+      _F_I_T_S _M_a_t_r_i_x _R_o_u_t_i_n_e_s
+
+          _f_i_t_s__r_e_a_d__m_a_t_r_i_x opens the given file and reads the
+          matrix structure.  There is, of course, no decent error
+          checking.
+
+          _f_i_t_s__w_r_i_t_e__m_a_t_r_i_x opens the given file and writes the
+          matrix structure.  The matrix is written to the end of
+          the file, in the assumption that there is already a
+          Header written to the file. There is, of course, no
+          decent error checking.
+
+          _f_i_t_s__g_e_t__m_a_t_r_i_x__v_a_l_u_e returns the value of the pixel at
+          the given (2-D) coordinates.
+
+          _f_i_t_s__s_e_t__m_a_t_r_i_x__v_a_l_u_e sets the value of the pixel at
+          the given (2-D) coordinates.
+
+          _f_i_t_s__c_r_e_a_t_e__m_a_t_r_i_x creates a matrix which corresponds
+          to the format described in the Header structure.
+
+          _f_i_t_s__c_o_p_y__m_a_t_r_i_x makes a duplicate copy of header1 in
+          header2.
+
+          _f_i_t_s__f_r_e_e__m_a_t_r_i_x frees the allocated pointers
+
+Version 1.0        Last change: Sept 18, 1992                   3
+
+FITS(1.0)         MISC. REFERENCE MANUAL PAGES          FITS(1.0)
+
+          associated with the Matrix.
+
+          _f_i_t_s__i_n_s_e_r_t__a_r_r_a_y set the values of the Matrix to those
+          of the array (a small Matrix), using the x,y values as
+          a relative offset.
+
+STRUCTURES
+     There are several important structures defined in _f_i_t_s_i_o._h
+     which are described here.
+
+     # define bool char
+
+     # typedef struct {
+       bool                    simple;
+       bool                    unsign;
+       bool                    extend;
+       int                     bitpix;
+       int                     Naxes;
+       int                     Naxis[FT_MAX_NAXES];
+       int                     size;
+       double                  bzero, bscale;
+       char                   *buffer;
+      } Header;
+
+     typedef struct {
+       int                     Naxes;
+       int                     Naxis[FT_MAX_NAXES];
+       int                     bitpix;
+       bool                    unsign;
+       double                  bzero, bscale;
+       char                   *buffer;
+       int                     size;
+      } Matrix;
+
+     REMINDER: data = (byte value) * bscale + bzero
+
+     _b_o_o_l is defined to be a char.
+
+     _H_e_a_d_e_r is a structure for holding all header information.
+     It consists of values of the basic header fields required
+     for a FITS file (SIMPLE, EXTEND, BITPIX, NAXIS, NAXIS1,
+     NAXIS2...) as well as a pointer to the header data itself
+     (_b_u_f_f_e_r) and the number of bytes in the header buffer
+     (_s_i_z_e).
+
+     _M_a_t_r_i_x is a structure for holding the image matrix data.  It
+     consists of the _N_a_x_e_s, and _N_a_x_i_s[_1_0] entries as well as the
+     _b_u_f_f_e_r and the _s_i_z_e entries.
+
+COPYRIGHT
+     Copyright 1991 Eugene Magnier
+
+Version 1.0        Last change: Sept 18, 1992                   4
+
+FITS(1.0)         MISC. REFERENCE MANUAL PAGES          FITS(1.0)
+
+     Permission to use, copy, modify, distribute, and sell this
+     software and its documentation for any purpose is hereby
+     granted without fee, provided that the above copyright
+     notice appear in all copies and that both that copyright
+     notice and this permission notice appear in supporting
+     documentation, and that the name of MIT not be used in
+     advertising or publicity pertaining to distribution of the
+     software without specific, written prior permission.  MIT
+     and the authors make no representations about the
+     suitability of this software for any purpose.  It is
+     provided "as is" without express or implied warranty.
+     MIT and the authors disclaim all warranties with regard to
+     this software, including all implied warranties of
+     merchantability and fitness, in no event shall MIT or the
+     authors be liable for any special, indirect or consequential
+     damages or any damages whatsoever resulting from loss of
+     use, data or profits, whether in an action of contract,
+     negligence or other tortious action, arising out of or in
+     connection with the use or performance of this software.
+ACKNOWLEDGEMENTS
+     Walter H.G. Lewin for inspiration
+     NASA for lots of money
+AUTHOR
+     Eugene Magnier.  MIT - CSR
+
+Version 1.0        Last change: Sept 18, 1992                   5
+
Index: /tags/start/Ohana/src/libfits/doc/notes.txt
===================================================================
--- /tags/start/Ohana/src/libfits/doc/notes.txt	(revision 12606)
+++ /tags/start/Ohana/src/libfits/doc/notes.txt	(revision 12606)
@@ -0,0 +1,133 @@
+
+2002/09/19
+
+I am making some substantial upgrades to libfits.  My primary goal for
+the moment is the improve the table handling, but I am also making
+some minor cleanups in other areas.  A major concern is that no
+changes should be made to existing functions that will alter their
+behavior and break other programs.  Below I list functions that change
+and note if they risk causing any problems.
+
+header:
+
+fits_init_header:   new function (SAFE)
+fits_create_header: changed fits_print to fits_modify (SAFE)
+fits_fread_header:  new function, to eventually replace fits_load_header (SAFE)
+fits_fwrite_header: new function, to eventually replace fits_save_header (SAFE)
+fits_write_header:  cleaned (f == NULL) (SAFE)
+
+matrix:
+
+fits_create_matrix: if NAXIS==0, create 0 size matrix, allocate min 1 byte
+ - this is different, but now follows correct fits standard.
+ - does not affect any existing programs: all assume NAXIS > 0
+fits_fread_matrix:  new function, to eventually replace fits_load_matrix (SAFE)
+fits_load_matrix:   cleanup declaration format (SAFE)
+fits_fwrite_matrix: new function (SAFE)
+fits_write_matrix:  file ops only, wrapper to fwrite (SAFE)
+fits_matrix_size:   new function (SAFE)
+
+table: no changes
+
+---
+
+fits_write_header:  open / truncate file, write header first
+fits_fwrite_header: 
+
+
+
+current table functions: (9/2002)
+
+fits_read_Theader   (char *filename, Header *theader);
+fits_load_Theader   (FILE *f, Header *theader)
+fits_read_table     (char *filename, Table *table);
+fits_table_column   (Table *table, char *field, char *mode, varg array);
+fits_create_Theader (Header *header, char *type);
+
+new functions:
+
+fits_init_header (Header *header);
+ - set all values to defaults: 
+   bitpix = 8, Naxes = 0, bscale = 1, bzero = 0, extend = FALSE, unsign = FALSE;
+   
+fits_create_table_header (Header *header, char *type);
+ - create an empty table header: TFIELDS = 0, NAXIS1 = NAXIS2 = 0
+
+fits_define_table_column (Header *header, char *format, char *type, char *comment, char *unit);
+ - add a column definition to header
+ - add appropriate keywords
+ - update TFIELDS
+ - update NAXIS1
+
+fits_define_bintable_column (Header *header, char *format, char *type, char *comment, char *unit, double scale, double zero);
+ - add a column definition to header
+ - add appropriate keywords
+ - update TFIELDS
+ - update NAXIS1
+
+fits_get_table_column ()
+
+fits_table_column (Table *table, char *field, char *mode, void *result);
+
+
+
+
+typedef struct {
+  int                     simple;
+  int                     unsign;
+  int                     extend;
+  int                     bitpix;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  double                  bzero;
+  double                  bscale;
+  char                   *buffer;
+} Header;
+
+typedef struct {
+  int                     unsign;
+  int                     bitpix;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  double                  bzero;
+  double                  bscale;
+  char                   *buffer;
+} Matrix;
+
+typedef struct {
+  int                     bitpix;
+  int                     Nfields;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  char                   *buffer;
+  Header                  header;
+} Table;
+          
+typedef struct {
+  Header                 *header;
+  char                   *buffer;
+  int                     size;
+} FTable;
+
+typedef struct {
+  Header                 *header;
+  char                  **buffer;
+  int			  Nrow;
+  int                    *row;
+  int                     size;  /* total buffer size */
+  int			  pad;   /* bytes of padding at the end */
+} VTable;
+
+virtual table:
+
+a virtual table contains only part of the data on disk size is the
+total size of the table (disk + mem) buffer is a contiguous block of
+data in the table msize is the size of the memory block stored at
+buffer offset is the start of the memory block
+
+Nx is width of table,
+Ny is number of occupied rows
+size = Nx*Ny + pad;
Index: /tags/start/Ohana/src/libfits/doc/notes2.txt
===================================================================
--- /tags/start/Ohana/src/libfits/doc/notes2.txt	(revision 12606)
+++ /tags/start/Ohana/src/libfits/doc/notes2.txt	(revision 12606)
@@ -0,0 +1,51 @@
+
+complete list of FITS table APIs:
+
+int fits_create_table (Header *header, FTable *table) 
+int fits_create_Theader (Header *header, char *type)  - create empty extension header 
+int fits_create_table_header (Header *header, char *type, char *extname) - create valid table header
+
+int fits_define_bintable_column (Header *header, char *format, char *label, char *comment, char *unit, double bscale, double bzero)
+int fits_define_table_column (Header *header, char *format, char *label, char *comment, char *unit) - 
+
+int fits_get_bintable_column (Header *header, FTable *table, char *label, void **data)
+int fits_get_table_column (Header *header, FTable *table, char *label, void **data)
+
+int fits_set_bintable_column (Header *header, FTable *table, char *label, void *data, int Nrow)
+int fits_set_table_column (Header *header, FTable *table, char *label, void *data, int Nrow)
+
+int fits_read_table (char *filename, Table *table)
+int fits_read_ftable (char *filename, FTable *table, char *extname)
+int fits_fread_ftable (FILE *f, FTable *table, char *extname)
+int fits_fread_vtable (FILE *f, VTable *table, char *extname, int Nrow, int *row)
+
+int fits_read_Theader (char *filename, Header *Theader)
+int fits_load_Theader (FILE *f, Header *Theader)
+int fits_fread_Theader (FILE *f, Header *Theader)
+
+int fits_bintable_format (char *format, char *type, int *Nval, int *Nbytes)
+int fits_table_format (char *format, char *type, int *Nval, int *Nbytes)
+
+  interpret table column format values.  
+  format - input column format value (TFORM), output C-style printing format
+  type   - char, int, float, double : use to case pointers
+  Nval   - number of entries 
+  Nbytes - bytes per entry
+
+int fits_table_to_vtable (FTable *ftable, VTable *vtable, int start, int Nkeep)
+
+int fits_add_rows (FTable *table, char *data, int Nrow, int Nbytes)
+int fits_vadd_rows (VTable *table, char *data, int Nrow, int Nbytes)
+int fits_delete_rows (FTable *table, int Nstart, int Nrow)
+
+int fits_write_table (char *filename, FTable *table)
+int fits_fwrite_table (FILE *f, FTable *table)
+int fits_fwrite_vtable (FILE *f, VTable *table)
+
+int fits_write_Theader (char *filename, Header *header)
+int fits_fwrite_Theader (FILE *f, Header *header)
+
+void fits_get_table_column (table, X, mode, values)  - REMOVED
+void fits_get_table_value (table, X, Y, mode, value) - REMOVED
+int fits_table_column (Table *table, char *field, char *mode,...) - REMOVED
+
Index: /tags/start/Ohana/src/libfits/doc/sample.c
===================================================================
--- /tags/start/Ohana/src/libfits/doc/sample.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/doc/sample.c	(revision 12606)
@@ -0,0 +1,72 @@
+# include "fitsio.h"
+# define TRUE 1
+
+main () {
+
+  char filename[80];
+  int i, Nrow;
+  Header header, theader1, theader2;
+  Matrix matrix;
+  FTable table1, table2;
+  float zpobs[1000];
+  float zpref[1000];
+  unsigned long int time[1000];
+  char tchar[1000];
+  
+  strcpy (filename, "test.fits");
+  Nrow = 20;
+  for (i = 0; i < Nrow; i++) {
+    zpobs[i] = i + 5;
+    zpref[i] = i + 15;
+    time[i] = i + 300000;
+    sprintf (&tchar[8*i], "%8d", i);
+  }
+
+  /* create primary header */
+  fits_init_header (&header);    header.extend = TRUE;
+  fits_create_header (&header);
+  fits_create_matrix (&header, &matrix);
+  fits_print (&header, "NEXTEND", "%d", 1, 2);
+
+  /* define bintable header & layout */
+  fits_create_table_header (&theader1, "BINTABLE", "ZERO_POINTS");
+
+  fits_define_bintable_column (&theader1, "E", "ZP_OBS", "measured zero point", "mag", 1.0, 0.0);
+  fits_define_bintable_column (&theader1, "E", "ZP_REF", "measured zero point", "mag", 1.0, 0.0);
+  fits_define_bintable_column (&theader1, "J", "TIME",   "time of data", "seconds since Jan 1, 1970 UT", 1.0, 0.0);
+  fits_define_bintable_column (&theader1, "8A", "TCHAR",   "time of data", "seconds since Jan 1, 1970 UT", 1.0, 0.0);
+
+  /* create table, add data values */
+  fits_create_table (&theader1, &table1);
+
+  /* set table column based on array, extend NAXIS2 as needed/appropriate */
+  fits_set_bintable_column (&theader1, &table1, "ZP_OBS", zpobs, Nrow);
+  fits_set_bintable_column (&theader1, &table1, "ZP_REF", zpref, Nrow);
+  fits_set_bintable_column (&theader1, &table1, "TIME",   time,  Nrow);
+  fits_set_bintable_column (&theader1, &table1, "TCHAR",  tchar,  Nrow);
+
+  /* define ASCII table header */
+  fits_create_table_header (&theader2, "TABLE", "ASCII_PTS");
+
+  fits_define_table_column (&theader2, "F5.2", "ZP_OBS", "measured zero point", "mag");
+  fits_define_table_column (&theader2, "F5.2", "ZP_REF", "measured zero point", "mag");
+  fits_define_table_column (&theader2, "I8", "TIME",    "time of data", "seconds");
+  fits_define_table_column (&theader2, "A8", "TCHAR",   "time of data", "YYYYMMDD");
+
+  /* create table, add data values */
+  fits_create_table (&theader2, &table2);
+
+  fits_set_table_column (&theader2, &table2, "ZP_OBS", zpobs, Nrow);
+  fits_set_table_column (&theader2, &table2, "ZP_REF", zpref, Nrow);
+  fits_set_table_column (&theader2, &table2, "TIME",   time,  Nrow);
+  fits_set_table_column (&theader2, &table2, "TCHAR",  tchar, Nrow);
+
+  /* write header, matrix, table1, table2 */
+  fits_write_header  (filename, &header);
+  fits_write_matrix  (filename, &matrix);
+  fits_write_Theader (filename, &theader1);
+  fits_write_table   (filename, &table1);
+  fits_write_Theader (filename, &theader2);
+  fits_write_table   (filename, &table2);
+
+}
Index: /tags/start/Ohana/src/libfits/doc/sample2.c
===================================================================
--- /tags/start/Ohana/src/libfits/doc/sample2.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/doc/sample2.c	(revision 12606)
@@ -0,0 +1,59 @@
+# include "fitsio.h"
+# include <stdio.h>
+# define TRUE 1
+
+main () {
+
+  char filename[80];
+  int i, j, Nrow;
+  Header header, theader1, theader2;
+  Matrix matrix;
+  FTable table1, table2;
+  float *zpobs, *zpref;
+  unsigned long int *time;
+  char *tchar;
+  
+  table1.header = &theader1;
+  table2.header = &theader2;
+
+  strcpy (filename, "test.fits");
+  fits_read_header  (filename, &header);
+  fits_read_matrix  (filename, &matrix);
+  fits_read_ftable  (filename, &table1, "ZERO_POINTS");
+  fits_read_ftable  (filename, &table2, "ASCII_PTS");
+  
+  /* set table column based on array, extend NAXIS2 as needed/appropriate */
+  fits_get_bintable_column (&theader1, &table1, "ZP_OBS", &zpobs);
+  fits_get_bintable_column (&theader1, &table1, "ZP_REF", &zpref);
+  fits_get_bintable_column (&theader1, &table1, "TIME",   &time);
+  fits_get_bintable_column (&theader1, &table1, "TCHAR",  &tchar);
+  fits_scan (&theader1, "NAXIS2", "%d", 1, &Nrow);
+
+  for (i = 0; i < Nrow; i++) {
+    fprintf (stderr, "%d %f %f %d   ", i, zpobs[i], zpref[i], time[i]);
+    for (j = 0; j < 8; j++) { fprintf (stderr, "%c", tchar[i*8 + j]); }
+    fprintf (stderr, "\n");
+  }
+
+  /* set table column based on array, extend NAXIS2 as needed/appropriate */
+  fits_get_table_column (&theader2, &table2, "ZP_OBS", &zpobs);
+  fits_get_table_column (&theader2, &table2, "ZP_REF", &zpref);
+  fits_get_table_column (&theader2, &table2, "TIME",   &time);
+  fits_get_table_column (&theader2, &table2, "TCHAR",  &tchar);
+  fits_scan (&theader2, "NAXIS2", "%d", 1, &Nrow);
+
+  for (i = 0; i < Nrow; i++) {
+    fprintf (stderr, "%d %f %f %d   ", i, zpobs[i], zpref[i], time[i]);
+    for (j = 0; j < 8; j++) { fprintf (stderr, "%c", tchar[i*8 + j]); }
+    fprintf (stderr, "\n");
+  }
+
+
+}      
+
+/*
+  fits_set_table_column (&theader2, &table2, "ZP_OBS", zpobs, Nrow);
+  fits_set_table_column (&theader2, &table2, "ZP_REF", zpref, Nrow);
+  fits_set_table_column (&theader2, &table2, "TIME",   time,  Nrow);
+  fits_set_table_column (&theader2, &table2, "TCHAR",  tchar, Nrow);
+*/
Index: /tags/start/Ohana/src/libfits/header/F_H_field.c
===================================================================
--- /tags/start/Ohana/src/libfits/header/F_H_field.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/header/F_H_field.c	(revision 12606)
@@ -0,0 +1,60 @@
+# include "fits.h"
+
+/*********************** fits header field ****************************/
+char *fits_header_field (Header *header, char *field, int N) {
+
+  char *buf;
+  int i, Nwant, Nfound;
+  char keyword[10];
+
+  /* create a blank-padded keyword with exactly 8 characters */
+  strcpy (keyword, field);
+  for (i = strlen(field); i < 8; i++) keyword[i] = ' ';
+  keyword[8] = 0;
+
+  buf = header[0].buffer;
+
+  if (N > 0) {
+    /* find the Nth entry */
+    Nfound = 0;
+    for (i = 0; i < header[0].size; i+= FT_LINE_LENGTH, buf += FT_LINE_LENGTH) {
+      if (!strncmp (keyword, buf, 8)) {
+	Nfound ++;
+	if (Nfound == N) return (buf);
+      }
+    }
+  }
+
+  if (N < 0) {
+    /* count the entries */
+    Nfound = 0;
+    for (i = 0; i < header[0].size; i+= FT_LINE_LENGTH, buf += FT_LINE_LENGTH) {
+      if (!strncmp (keyword, buf, 8)) {
+	Nfound ++;
+      }
+    }
+
+    Nwant = Nfound + N + 1;
+    buf = header[0].buffer;
+
+    /* find the Nwant entry */
+    Nfound = 0;
+    for (i = 0; i < header[0].size; i+= FT_LINE_LENGTH, buf += FT_LINE_LENGTH) {
+      if (!strncmp (keyword, buf, 8)) {
+	Nfound ++;
+	if (Nwant == Nfound) return (buf);
+      }
+    }
+
+  }
+
+  return ((char *) NULL);
+
+}
+
+/* 
+
+   find the Nth entry of this keyword.
+   if N < 0, find the last - N - 1 word (ie, -1 = last)
+
+*/
Index: /tags/start/Ohana/src/libfits/header/F_copy_H.c
===================================================================
--- /tags/start/Ohana/src/libfits/header/F_copy_H.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/header/F_copy_H.c	(revision 12606)
@@ -0,0 +1,28 @@
+# include "fits.h"
+
+/*********************** fits copy header ***********************************/
+int fits_copy_header (header1, header2) 
+Header *header1, *header2;
+{
+
+  int i;
+
+  header2[0].simple = header1[0].simple;
+  header2[0].bitpix = header1[0].bitpix;
+  header2[0].extend = header1[0].extend;
+  header2[0].unsign = header1[0].unsign;
+  header2[0].size   = header1[0].size;
+  header2[0].bscale = header1[0].bscale;
+  header2[0].bzero  = header1[0].bzero;
+  header2[0].Naxes  = header1[0].Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++) 
+    header2[0].Naxis[i] = header1[0].Naxis[i];
+
+  ALLOCATE (header2[0].buffer, char, header2[0].size);
+  
+  strncpy (header2[0].buffer, header1[0].buffer, header2[0].size);
+
+  return (TRUE);
+}	
+
+
Index: /tags/start/Ohana/src/libfits/header/F_create_H.c
===================================================================
--- /tags/start/Ohana/src/libfits/header/F_create_H.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/header/F_create_H.c	(revision 12606)
@@ -0,0 +1,35 @@
+# include "fits.h"
+
+/******************** fits create header ***********************************/
+int fits_create_header (Header *header) {
+
+  int i;
+  char axis[10];
+  
+  header[0].size = 2880;
+  ALLOCATE (header[0].buffer, char, 2880);
+
+  for (i = 0; i < 2880; i++) 
+    header[0].buffer[i] = ' ';
+  strncpy (header[0].buffer, "END", 3);
+
+  fits_modify (header, "SIMPLE", "%t", 1, header[0].simple);
+  fits_modify (header, "BITPIX", "%d", 1, header[0].bitpix);
+  fits_modify (header, "NAXIS",  "%d", 1, header[0].Naxes);
+				       
+  for (i = 0; i < header[0].Naxes; i++) {
+    sprintf (axis, "NAXIS%d", i + 1);
+    fits_modify (header,  axis, "%d", 1, header[0].Naxis[i]);
+  }
+
+  /* PCOUNT & GCOUNT are not implemented, but they are required to be here */
+  fits_modify (header, "PCOUNT", "%d", 1, 0);
+  fits_modify (header, "GCOUNT", "%d", 1, 1);
+  fits_modify (header, "BSCALE", "%lf", 1, header[0].bscale);
+  fits_modify (header, "BZERO",  "%lf", 1, header[0].bzero);
+  fits_modify (header, "EXTEND", "%t",  1, header[0].extend);
+  return (TRUE);
+
+}	
+
+
Index: /tags/start/Ohana/src/libfits/header/F_delete.c
===================================================================
--- /tags/start/Ohana/src/libfits/header/F_delete.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/header/F_delete.c	(revision 12606)
@@ -0,0 +1,31 @@
+# include "fits.h"
+
+/*********************** fits delete ****************************/
+int fits_delete (Header *header, char *field, int N) {
+  
+  int i, Nbytes;
+  char *p1, *p2;
+  
+  p1 = fits_header_field (header, field, N);
+  if (p1 == NULL) return (TRUE);
+
+  p2 = fits_header_field (header, "END", 1);
+  if (p2 == NULL) return (FALSE); 
+
+  /* pull everything from p1 + FT_LINE_LENGTH to p2 + 79 back 80 chars */
+  Nbytes = (p2 - p1);
+  memmove (p1, p1 + FT_LINE_LENGTH, Nbytes);
+
+  for (i = 0; i < FT_LINE_LENGTH; i++) 
+    *(p2 + i) = ' ';
+
+  p2 = fits_header_field (header, "END", 1);
+  if (header[0].size - (p2 - header[0].buffer + FT_LINE_LENGTH) > FT_RECORD_SIZE) {
+    header[0].size -= FT_RECORD_SIZE;
+    REALLOCATE (header[0].buffer, char, header[0].size);
+  }
+  return (TRUE);
+
+}
+
+
Index: /tags/start/Ohana/src/libfits/header/F_free_H.c
===================================================================
--- /tags/start/Ohana/src/libfits/header/F_free_H.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/header/F_free_H.c	(revision 12606)
@@ -0,0 +1,11 @@
+# include "fits.h"
+
+/*********************** fits free header ***********************************/
+void fits_free_header (Header *header) {
+
+  if (header[0].buffer == (char *) NULL) return;
+  free (header[0].buffer);
+  header[0].buffer = (char *) NULL;
+  
+}
+
Index: /tags/start/Ohana/src/libfits/header/F_init_H.c
===================================================================
--- /tags/start/Ohana/src/libfits/header/F_init_H.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/header/F_init_H.c	(revision 12606)
@@ -0,0 +1,20 @@
+# include "fits.h"
+int FT_UNSIGN_MODE;
+
+/*********************** fits read header ***********************************/
+int fits_init_header (Header *header) {
+
+  int i;
+
+  header[0].simple = TRUE;
+  header[0].extend = FALSE;
+  header[0].unsign = FALSE;
+  header[0].bscale = 1;
+  header[0].bzero  = 0;
+  header[0].bitpix = 8;
+  header[0].Naxes  = 0;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    header[0].Naxis[i] = 0;
+
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/libfits/header/F_insert_array.c
===================================================================
--- /tags/start/Ohana/src/libfits/header/F_insert_array.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/header/F_insert_array.c	(revision 12606)
@@ -0,0 +1,23 @@
+# include "fits.h"
+
+/*********************** fits insert array ***********************************/
+void fits_insert_matrix (matrix, array, x, y) 
+Matrix *matrix, *array; 
+int x, y;
+{
+
+  /* there is no check here to match BITPIX, BZERO, or BSCALE */
+
+  int i, start_m, Nbytes_m, Nbytes;
+
+  Nbytes = array[0].Naxis[0]*abs(array[0].bitpix) / 8;
+  Nbytes_m = matrix[0].Naxis[0]*abs(matrix[0].bitpix) / 8;
+  start_m = y*Nbytes_m + x*abs(matrix[0].bitpix) / 8;
+
+  for (i = 0; i < array[0].Naxis[1]; i++) {
+    bcopy (&array[0].buffer[i*Nbytes], 
+	   &matrix[0].buffer[start_m + i*Nbytes_m], Nbytes);
+  }
+  
+}
+
Index: /tags/start/Ohana/src/libfits/header/F_modify.c
===================================================================
--- /tags/start/Ohana/src/libfits/header/F_modify.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/header/F_modify.c	(revision 12606)
@@ -0,0 +1,157 @@
+# include "fits.h"
+
+char *fits_keyword_end (char *line);
+void pad_ending (char *line, char value, int Nbyte);
+
+int fits_modify (Header *header, char *field, char *mode, int N,...) {
+  
+  /* this function expects one more argument, the value to be written */
+  /* this function is extremely similar to fits_print, except it allows for changing an existing field. */
+
+  char comment[82], string[82], data[82];
+  char *p, *q;
+  va_list argp;
+  
+  va_start (argp, N);
+  bzero (data, 82);
+  bzero (string, 82);
+  bzero (comment, 82);
+
+  if (mode[0] != '%') {
+    fprintf (stderr, "fits_print: weird mode:  %s\n", mode);
+    return (FALSE);
+  }
+
+  /* find location of desired entry */
+  p = fits_header_field (header, field, N);
+  if (p == NULL)  {
+
+    /* new entry, find the END of the header */
+    p = fits_header_field (header, "END", 1);
+    if (p == NULL) return (FALSE); 
+    
+    /* is there enough space for 1 more line? */
+    if (header[0].size - (p - (header[0].buffer)) < 2*FT_LINE_LENGTH) {
+      header[0].size += FT_RECORD_SIZE;
+      REALLOCATE (header[0].buffer, char, header[0].size);
+      p = fits_header_field (header, "END", 1);
+      if (p == NULL) return (FALSE); 
+      memset (p + FT_LINE_LENGTH, ' ', FT_RECORD_SIZE);
+    }
+    
+    /* push END line back 1 */
+    memmove ((p + FT_LINE_LENGTH), p, FT_LINE_LENGTH);
+    memset (p, ' ', FT_LINE_LENGTH);
+  } else {
+    q = fits_keyword_end (p);
+    q += 3;
+    q = MIN (p + 80, q);
+    strncpy (comment, q, p + 80 - q);
+  }
+  pad_ending (comment, ' ', 82);  /* comment must contain spaces to the end */
+
+  /* write the numeric modes */
+  if (!strcmp (mode, "%d"))  snprintf (string, 81, "%-8s= %20d / %-s ",     field, va_arg (argp, int),      comment);
+  if (!strcmp (mode, "%u"))  snprintf (string, 81, "%-8s= %20d / %-s ",     field, va_arg (argp, unsigned), comment);
+  if (!strcmp (mode, "%ld")) snprintf (string, 81, "%-8s= %20ld / %-s ",    field, va_arg (argp, long),     comment);
+  if (!strcmp (mode, "%hd")) snprintf (string, 81, "%-8s= %20d / %-s ",     field, va_arg (argp, int),      comment);
+  if (!strcmp (mode, "%f"))  snprintf (string, 81, "%-8s= %20.10f / %-s ",  field, va_arg (argp, double),   comment); 
+  if (!strcmp (mode, "%lf")) snprintf (string, 81, "%-8s= %20.10f / %-s ",  field, va_arg (argp, double),   comment); 
+  if (!strcmp (mode, "%e"))  snprintf (string, 81, "%-8s= %20.10E / %-s ",  field, va_arg (argp, double),   comment); 
+  if (!strcmp (mode, "%le")) snprintf (string, 81, "%-8s= %20.10E / %-s ",  field, va_arg (argp, double),   comment); 
+  if (!strcmp (mode, "%g"))  snprintf (string, 81, "%-8s= %20.10G / %-s ",  field, va_arg (argp, double),   comment); 
+  if (!strcmp (mode, "%lg")) snprintf (string, 81, "%-8s= %20.10G / %-s ",  field, va_arg (argp, double),   comment); 
+
+  /* write the boolean mode */
+  if (!strcmp (mode, "%t")) {
+    if (va_arg (argp, int)) 
+      snprintf (string, 81, "%-8s= %18s T / %-s ", field, " ", comment);
+    else
+      snprintf (string, 81, "%-8s= %18s F / %-s ", field, " ", comment);
+  }
+
+  /* string value.  Quotes must be at least 18 chars apart */
+  if (!strcmp (mode, "%s")) {
+    strncpy (data, va_arg (argp, char *), 68);
+    snprintf (string, 81, "%-8s= '%-18s' / %-s ", field, data, comment);
+  }
+
+  /* comment type of value.  */
+  if (!strcmp (mode, "%S")) {
+    strncpy (data, va_arg (argp, char *), 71);
+    snprintf (string, 81, "%-8s %-71s", field, data);
+  }  
+
+  /* just a comment associated with a value.  this is assumes a fixed format position for the comment */
+  if (!strcmp (mode, "%C")) { 
+    q = fits_keyword_end (p);
+    strncpy (data, p + 9, MAX (MIN ((q - p - 9), 71), 0));
+    strncpy (comment, va_arg (argp, char *), 80);
+    pad_ending (comment, ' ', 82);  /* comment must contain spaces to the end */
+    snprintf (string, 81, "%-8s=%21s / %-s", field, data, comment);
+  }
+
+  strncpy (p, string, 80);
+  va_end (argp);
+  return (TRUE);
+
+}
+
+/* given a FITS card line, return pointer to the end of the data area */
+char *fits_keyword_end (char *line) {
+
+  int done;
+  char *c1, *c2;
+
+  /* find the end of the existing data region */
+  c2 = line + 8;
+  if (*c2 != '=') return (c2);  /* no data in COMMENT field */
+  
+  c1 = c2 + 2;
+  if (c1[0] == 0x27) { /* entry a string, skip over 'fred' */
+    for (done = FALSE, c2 = c1 + 1; !done && (c2 < line + 80); c2++) {
+      if ((c2[0] == 0x27) && (c2[1] == 0x27)) {
+	c2 += 2;
+	continue;
+      }
+      if (c2[0] == 0x27) {
+	c1 = c2 + 1;
+	done = TRUE;
+      }
+    }
+    if (!done) { /* error in line: mismatched ' chars, return fixed position */
+      c1 = line + 30;
+    }
+  } else {
+    while ((*c1 == ' ') && (c1 < line + 80)) c1++;
+    while ((*c1 != ' ') && (c1 < line + 80)) c1++;
+  }
+  return (c1);
+}
+
+/* according to the FITS guidelines, a string is supposed to start with a single quote
+   on the 11th character.  I'll be generous and allow the string to start at the 10th.
+   I read the string into tmp then strip off the leading single quote and spaces.
+   a string of "  '  fred is here  '  " should become "fred is here".
+   a string of "  fred is here  " should also become "fred is here".
+   the remaining problem:
+   "'O''HARA'" should be kept as O''HARA.  need to test for double single quotes
+   d -- /(0x2f: comment)  (*(p + i + 10) != 0x2f) &&  && (*(p + i + 10) != 0x27)
+ */
+
+/* fill 'line' with Nbyte space from first NULL to last byte with value */
+void pad_ending (char *line, char value, int Nbyte) {
+  
+  char *p;
+  int N;
+
+  line[Nbyte-1] = 0;
+  
+  p = line + strlen (line);
+  N = MAX (Nbyte - strlen (line) - 1, 0);
+  memset (p, value, N);
+}
+
+
+/* in this routine, the value field will expand as needed, forcing out the comment
+   the total line is limited by snprintf to only 80 chars + EOL */
Index: /tags/start/Ohana/src/libfits/header/F_print.c
===================================================================
--- /tags/start/Ohana/src/libfits/header/F_print.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/header/F_print.c	(revision 12606)
@@ -0,0 +1,99 @@
+# include "fits.h"
+
+int fits_print (Header *header, char *field, char *mode, int N,...) {
+  
+  /* this function expects one more argument, the value to be written */
+
+  static char blank[] = " ";
+  char string[82], line[80];
+  char *p, a;
+  va_list argp;  
+
+  va_start (argp, N);
+  
+  if (mode[0] != '%') {
+    fprintf (stderr, "fits_print: weird mode:  %s\n", mode);
+    return (FALSE);
+  }
+
+  /* this is supposed to create a new field, not modify an old one.  */
+  p = fits_header_field (header, field, N);
+  if (p != NULL) return (FALSE);
+
+  /* find the END of the header */
+  p = fits_header_field (header, "END", 1);
+  if (p == NULL) return (FALSE); 
+
+  /* is there enough space for 1 more line? */
+  if (header[0].size - (p - (header[0].buffer)) < 2*FT_LINE_LENGTH) {
+    header[0].size += FT_RECORD_SIZE;
+    REALLOCATE (header[0].buffer, char, header[0].size);
+    /* re-find the "END" marker, in case new memory block is used */
+    p = fits_header_field (header, "END", 1);
+    if (p == NULL) return (FALSE); 
+    memset (p + FT_LINE_LENGTH, ' ', FT_RECORD_SIZE);
+  }
+
+  /* push END line back 1 */
+  memmove ((p + FT_LINE_LENGTH), p, FT_LINE_LENGTH);
+  memset (p, ' ', FT_LINE_LENGTH);
+
+  /* write the new FITS card, setting the comment to be blank */
+  /* in these lines, the value field will expand as needed, forcing out the comment
+     the total line is limited by snprintf to only 80 chars + EOL */
+
+  /* write the numeric modes */
+  if (!strcmp (mode, "%d"))  { snprintf (string, 81, "%-8s= %20d / %46s ",    field, va_arg (argp, int),      blank); }
+  if (!strcmp (mode, "%u"))  { snprintf (string, 81, "%-8s= %20d / %46s ",    field, va_arg (argp, unsigned), blank); }
+  if (!strcmp (mode, "%ld")) { snprintf (string, 81, "%-8s= %20ld / %46s ",   field, va_arg (argp, long),     blank); }
+  if (!strcmp (mode, "%hd")) { snprintf (string, 81, "%-8s= %20d / %46s ",    field, va_arg (argp, int),      blank); }
+  if (!strcmp (mode, "%f"))  { snprintf (string, 81, "%-8s= %20.10f / %46s ", field, va_arg (argp, double),   blank); }
+  if (!strcmp (mode, "%lf")) { snprintf (string, 81, "%-8s= %20.10f / %46s ", field, va_arg (argp, double),   blank); }
+  if (!strcmp (mode, "%e"))  { snprintf (string, 81, "%-8s= %20.10E / %46s ", field, va_arg (argp, double),   blank); }
+  if (!strcmp (mode, "%le")) { snprintf (string, 81, "%-8s= %20.10E / %46s ", field, va_arg (argp, double),   blank); }
+  if (!strcmp (mode, "%g"))  { snprintf (string, 81, "%-8s= %20.10G / %46s ", field, va_arg (argp, double),   blank); }
+  if (!strcmp (mode, "%lg")) { snprintf (string, 81, "%-8s= %20.10G / %46s ", field, va_arg (argp, double),   blank); }
+
+  /* write the boolean mode */
+  if (!strcmp (mode, "%t")) {
+    a = va_arg (argp, int);
+    if (a == 1)
+      snprintf (string, 81, "%-8s= %18s T / %46s ", field, blank, blank);
+    else
+      snprintf (string, 81, "%-8s= %18s F / %46s ", field, blank, blank);
+  }
+
+  /* string value.  Quotes must be at least 18 chars apart.  Longer lines will this should be fixed to allow arbitrary string lengths, up to 69 chars */
+  if (!strcmp (mode, "%s")) {
+    strcpy (line, va_arg (argp, char *));
+    line[68] = 0;
+    snprintf (string, 81, "%-8s= '%-18s' / %46s ", field, line, blank);
+  }
+
+  /* comment type of value.  */
+  if (!strcmp (mode, "%S")) {
+    /* we are forcing the entry to be <= 69 char long */
+    strcpy (line, va_arg (argp, char *));
+    line[71] = 0;
+    snprintf (string, 81, "%-8s %-71s", field, line);
+  }  
+
+  /*
+maximal string line:
+12345678901234567890123456789012345678901234567890123456789012345678901234567890 .
+KEYWORD = '01234567890123456789012345678901234567890123456789012345678901234567'
+
+maximal comment line:
+12345678901234567890123456789012345678901234567890123456789012345678901234567890 .
+KEYWORD  01234567890123456789012345678901234567890123456789012345678901234567890
+  */
+
+  /* can't write the comment in fits_print - use fits_modify */
+  if (!strcmp (mode, "%C")) return (FALSE);
+
+  strncpy (p, string, 80);
+  
+  va_end (argp);
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/libfits/header/F_read_H.c
===================================================================
--- /tags/start/Ohana/src/libfits/header/F_read_H.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/header/F_read_H.c	(revision 12606)
@@ -0,0 +1,88 @@
+# include "fits.h"
+int FT_UNSIGN_MODE;
+
+/*********************** fits read header ***********************************/
+int fits_read_header (char *filename, Header *header) {
+  
+  FILE *f;
+  
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    header[0].buffer = NULL;
+    return (FALSE);
+  }
+  if (!fits_load_header (f, header)) {
+    fclose (f);
+    return (FALSE);
+  }
+
+  fclose (f);
+  return (TRUE);
+}	
+
+int fits_load_header (FILE *f, Header *header) {
+
+  int i, done, Nbytes, t1, t2;
+  char *p;
+
+  header[0].size = 0;
+  done = FALSE;
+  ALLOCATE (header[0].buffer, char, 1);
+
+  for (i = 0; !done; i++) {
+    REALLOCATE (header[0].buffer, char, (i + 1)*FT_RECORD_SIZE);
+    Nbytes = fread (&header[0].buffer[i*FT_RECORD_SIZE], 
+		    sizeof(char), FT_RECORD_SIZE, f);
+    header[0].size += Nbytes;
+    if (Nbytes != FT_RECORD_SIZE) {
+      return (FALSE);
+    }
+    if (i == 0) { 
+      /* on first block, verify it is a FITS table: SIMPLE .. or XTENSION ... */
+      t1 = strncmp (header[0].buffer, "SIMPLE", 6);
+      t2 = strncmp (header[0].buffer, "XTENSION", 8);
+      if (t1 && t2) return (FALSE);
+    }
+
+    p = fits_header_field (header, "END", 1);
+    if (p != NULL)
+      done = TRUE;
+  }
+
+  header[0].unsign = FT_UNSIGN_MODE;
+  header[0].bscale = 1;
+  header[0].bzero  = 0;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    header[0].Naxis[i] = 0;
+
+  fits_scan (header,  "SIMPLE", "%t",   1, &header[0].simple);
+  fits_scan (header,  "BITPIX", "%d",   1, &header[0].bitpix);
+  fits_scan (header,  "NAXIS",  "%d",   1, &header[0].Naxes);
+				                           
+  fits_scan (header,  "EXTEND", "%t",   1, &header[0].extend);
+  fits_scan (header,  "UNSIGN", "%t",   1, &header[0].unsign);
+  fits_scan (header,  "BSCALE", "%lf",  1, &header[0].bscale);
+  fits_scan (header,  "BZERO",  "%lf",  1, &header[0].bzero);
+				       
+  fits_scan (header,  "NAXIS1", "%d", 1, &header[0].Naxis[0]);
+  fits_scan (header,  "NAXIS2", "%d", 1, &header[0].Naxis[1]);
+  fits_scan (header,  "NAXIS3", "%d", 1, &header[0].Naxis[2]);
+  fits_scan (header,  "NAXIS4", "%d", 1, &header[0].Naxis[3]);
+  fits_scan (header,  "NAXIS5", "%d", 1, &header[0].Naxis[4]);
+  fits_scan (header,  "NAXIS6", "%d", 1, &header[0].Naxis[5]);
+  fits_scan (header,  "NAXIS7", "%d", 1, &header[0].Naxis[6]);
+  fits_scan (header,  "NAXIS8", "%d", 1, &header[0].Naxis[7]);
+  fits_scan (header,  "NAXIS9", "%d", 1, &header[0].Naxis[8]);
+  fits_scan (header, "NAXIS10", "%d", 1, &header[0].Naxis[9]);
+
+  return (TRUE);
+
+}
+
+int fits_fread_header (FILE *f, Header *header) {
+
+  int status;
+  
+  status = fits_load_header (f, header);
+  return (status);
+}
Index: /tags/start/Ohana/src/libfits/header/F_read_XH.c
===================================================================
--- /tags/start/Ohana/src/libfits/header/F_read_XH.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/header/F_read_XH.c	(revision 12606)
@@ -0,0 +1,43 @@
+# include "fits.h"
+int FT_UNSIGN_MODE;
+
+/*********************** fits read header ***********************************/
+int fits_read_Xheader (char *filename, Header *header, int N) {
+  
+  /* read header for extension number N */
+
+  FILE *f;
+  int j, Nmatrix, Nskip;
+  Header theader;
+  
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    header[0].buffer = NULL;
+    return (FALSE);
+  }
+
+  Nskip = 0;
+  for (j = -1; j < N; j++) {
+    /* load data for this header */
+    if (!fits_load_header (f, &theader)) {
+      fclose (f);
+      return (FALSE);
+    }
+
+    Nmatrix = fits_matrix_size (&theader);
+
+    /* skip to next header */
+    fseek (f, Nmatrix, SEEK_CUR);
+    Nskip += (Nmatrix + theader.size);
+    fits_free_header (&theader);
+  }
+  
+  if (!fits_load_header (f, header)) {
+    fclose (f);
+    return (FALSE);
+  }
+  fclose (f);
+  Nskip += header[0].size;
+  return (Nskip);
+}	
+
Index: /tags/start/Ohana/src/libfits/header/F_scan.c
===================================================================
--- /tags/start/Ohana/src/libfits/header/F_scan.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/header/F_scan.c	(revision 12606)
@@ -0,0 +1,133 @@
+# include "fits.h"
+
+int fits_scan (Header *header, char *field, char *mode, int N,...) {
+
+  int status;
+  va_list argp;
+  
+  va_start (argp, N);
+  status = fits_vscan (header, field, mode, N, argp);
+  va_end (argp);
+  return (status);
+}
+  
+int fits_vscan (Header *header, char *field, char *mode, int N, va_list argp) {
+
+  char *p, *q, tmp[81];
+  int Nchar;
+  double value;
+  
+  /* find the correct line with field */
+  p = fits_header_field (header, field, N);
+  if (p == NULL) return (FALSE);
+
+  /* non-data entry (COMMENT, HISTORY) */
+  if (!strcmp (mode, "%S")) {
+    strncpy (va_arg (argp, char *), p + 8, FT_HISTORY_LENGTH);
+    goto gotvalue;
+  }
+
+  /* all others require '=' in column 8 */
+  if (p[8] != '=') return (FALSE);
+
+  /* comment from data line */
+  if (!strcmp (mode, "%C")) {
+    q = fits_keyword_end (p) + 3;
+    q = MIN (p + 80, q);
+    bzero (tmp, 81);
+    Nchar = MIN (80, p + 80 - q);
+    memcpy (tmp, q, Nchar);
+    fits_stripwhite (tmp);
+    strcpy (va_arg (argp, char *), tmp);
+    goto gotvalue;
+  }
+
+  /* extract data into char array (exclude containing ' chars) */
+  if (!strcmp (mode, "%s")) {
+    q = fits_keyword_end (p);
+    q -= 1;
+    p += 10;
+
+    /* exclude containing ' chars, if they exist */
+    /* we are not requiring a string entry to have the quotes */
+    if (*p == 0x27) p++;
+    if (*q == 0x27) q--;
+
+    Nchar = MAX (0, (q - p + 1));
+    bzero (tmp, 81);
+    memcpy (tmp, p, Nchar);
+    fits_stripwhite (tmp);
+    strcpy (va_arg (argp, char *), tmp);
+    goto gotvalue;
+  }
+  
+  /* boolean data, requires int target */
+  if (!strcmp (mode, "%t")) {
+    if (p[29]  == 'T') 
+      *va_arg (argp, int *) = TRUE;
+    if (p[29]  == 'F') 
+      *va_arg (argp, int *) = FALSE;   
+    goto gotvalue;
+  }
+
+  /* remaining options are numerical data */
+  /* need to interpret 1.0d5 as 1.0e5 */
+  value = strtod (p + 10, &q);
+  if ((*q == 'd') || (*q == 'D')) 
+    value *= pow (10.0, atof (q + 1));
+
+  if (!strcmp (mode, "%d"))  { *va_arg (argp, int *)       = value; goto gotvalue; }
+  if (!strcmp (mode, "%u"))  { *va_arg (argp, unsigned *)  = value; goto gotvalue; }
+  if (!strcmp (mode, "%ld")) { *va_arg (argp, long *)      = value; goto gotvalue; }
+  if (!strcmp (mode, "%hd")) { *va_arg (argp, short *)     = value; goto gotvalue; }
+  if (!strcmp (mode, "%f"))  { *va_arg (argp, float *)     = value; goto gotvalue; }
+  if (!strcmp (mode, "%lf")) { *va_arg (argp, double *)    = value; goto gotvalue; }
+
+  /* no valid mode found */
+  return (FALSE);
+
+ gotvalue:
+  return (TRUE);
+}
+
+/* if the variable argument stuff breaks on another system, look 
+at F_modify.c as it has the old code */
+
+#ifndef whitespace
+#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
+#endif
+
+/* Strip whitespace from the start and end of STRING. */
+int fits_stripwhite (char *string) {
+
+  int i;
+
+  if (string == (char *) NULL)
+    return (FALSE);
+
+  for (i = 0; whitespace (string[i]); i++);
+  if (i) memmove (string, string + i, strlen(string+i)+1);
+  for (i = strlen (string) - 1; (i > 0) && whitespace (string[i]); i--);
+  string[++i] = 0;
+
+  return (i);
+
+}
+
+# if (0)
+    one_quote = FALSE;
+    tmp[0] = *(p + 10);
+    if (tmp[0] == 0x27)
+      one_quote = TRUE;
+    /* end the string if we hit: a -- end of line (80 chars) b -- NEWLINE c -- '(0x27: single quote) (end of string) */
+    for (i = 1; (i < 70) && (p[i + 10] != NEWLINE) && ((p[i + 10] != 0x27) || !one_quote); i++) {
+      tmp[i] = *(p + 10 + i);
+      if ((tmp[i] == 0x27) && !one_quote)
+	one_quote = TRUE;
+      if ((tmp[i] == 0x2f) && !one_quote)
+	break;
+    }
+    tmp[i] = 0;
+    if ((c = strchr (tmp, 0x27)) != NULL)
+      *c = ' ';
+# endif
Index: /tags/start/Ohana/src/libfits/header/F_write_H.c
===================================================================
--- /tags/start/Ohana/src/libfits/header/F_write_H.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/header/F_write_H.c	(revision 12606)
@@ -0,0 +1,48 @@
+# include "fits.h"
+
+/*********************** fits write header ***********************************/
+int fits_write_header (char *filename, Header *header) {
+
+  FILE *f;
+  int Nbytes, status;
+  
+  status = TRUE;
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) return (FALSE);
+
+  Nbytes = fwrite (header[0].buffer, sizeof(char), header[0].size, f);
+
+  if (Nbytes != header[0].size) {
+    status = FALSE;
+  }
+
+  fclose (f);
+
+  return (status);
+}	
+
+/*********************** fits write header ***********************************/
+int fits_save_header (FILE *f, Header *header) {
+
+  int Nbytes, status;
+  
+  status = TRUE;
+
+  Nbytes = fwrite (header[0].buffer, sizeof(char), header[0].size, f);
+
+  if (Nbytes != header[0].size) {
+    status = FALSE;
+  }
+
+  return (status);
+}	
+
+
+int fits_fwrite_header (FILE *f, Header *header) {
+
+  int status;
+  status = fits_save_header (f, header);
+  return (status);
+}
+
Index: /tags/start/Ohana/src/libfits/include/cfuncs.h
===================================================================
--- /tags/start/Ohana/src/libfits/include/cfuncs.h	(revision 12606)
+++ /tags/start/Ohana/src/libfits/include/cfuncs.h	(revision 12606)
@@ -0,0 +1,60 @@
+/*** random C-functions ***/
+
+void
+  bcopy
+  (char *b1,
+   char *b2,
+   int   length);
+
+void
+  bzero
+  (char *b,
+   int   length);
+
+# ifndef HAS_ANSI_PROTOTYPES
+int
+   fprintf 
+   (FILE *stream,
+    char *format,...);
+
+int
+   fscanf 
+   (FILE *stream,
+    char *format,...);
+
+int 
+  fread
+  (char *ptr,
+   int size, 
+   int nitems,
+   FILE *stream);
+
+/*
+char *
+  malloc
+  (unsigned size);
+
+char *
+  realloc
+  (char *ptr,
+   unsigned size);
+*/
+
+int 
+  fwrite
+  (char *ptr,
+   int size, 
+   int nitems,
+   FILE *stream);
+
+int
+  fseek 
+  (FILE *f,
+   int offset,
+   int from);
+
+int
+  fclose
+  (FILE *f);
+# endif /* HAS_ANSI_PROTOTYPES */
+
Index: /tags/start/Ohana/src/libfits/include/fits.h
===================================================================
--- /tags/start/Ohana/src/libfits/include/fits.h	(revision 12606)
+++ /tags/start/Ohana/src/libfits/include/fits.h	(revision 12606)
@@ -0,0 +1,52 @@
+# include <stdio.h>
+# include <math.h>
+# include <malloc.h>
+# include <string.h>
+# include <stdlib.h>
+
+# include <stdarg.h> 
+# include <fitsio.h>
+
+/*
+# ifndef ANSI
+# include <varargs.h>
+# else
+# include <stdarg.h> 
+# include <cfuncs.h> 
+# endif
+*/
+
+/********************** internal constants ************/
+# ifndef NEWLINE
+# define NEWLINE                 10  /* UNIX RETURN character */
+# endif /* NEWLINE */
+
+/* general macros which should exist anyway! */
+# ifndef ALLOCATE
+# define ALLOCATE(X,T,S)  \
+  X=(T *)malloc((unsigned) ((S)*sizeof(T)));\
+  if(X==NULL) \
+    { \
+      fprintf(stderr,"failed to malloc %d entries\n", S);\
+	exit(0);\
+    } 
+# define REALLOCATE(X,T,S) \
+  X=(T *)realloc(X,(unsigned) ((S)*sizeof(T))); \
+  if(X==NULL) \
+    { \
+       fprintf(stderr,"failed to realloc %d entries\n", S); \
+       exit(0); \
+    }
+# endif /* ALLOCATE */
+
+# ifndef TRUE
+# define TRUE                           (1)
+# define FALSE                          (0)
+# endif  /* TRUE */
+
+# ifdef linux
+# define BYTE_SWAP
+# endif
+
+# define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+# define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
Index: /tags/start/Ohana/src/libfits/include/fitsio.h
===================================================================
--- /tags/start/Ohana/src/libfits/include/fitsio.h	(revision 12606)
+++ /tags/start/Ohana/src/libfits/include/fitsio.h	(revision 12606)
@@ -0,0 +1,168 @@
+/* FITS specific macros and structures */
+
+# ifndef FITSIO
+# define FITSIO
+
+/********** FITS Constants *********/
+# define FT_TEXT_LENGTH          18  /* max length text header field */
+# define FT_MAX_NAXES            10  /* max number of axes */
+# define FT_FIELD_LENGTH          8  /* max length header field */   
+# define FT_COMMENT_LENGTH       47  /* max length comment field */
+# define FT_HISTORY_LENGTH       72  /* max length history / comment */
+# define FT_LINE_LENGTH          80  /* FITS header line length */
+# define FT_RECORD_SIZE        2880  /* FITS block size */
+
+extern int FT_UNSIGN_MODE; /* is unsigned the default? */
+
+/* this structure defines the buffer which contains a header
+   and contains the minimum required keywords */
+
+typedef struct {
+  int                     simple;
+  int                     unsign;
+  int                     extend;
+  int                     bitpix;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  double                  bzero;
+  double                  bscale;
+  char                   *buffer;
+} Header;
+
+/* this structure defines the buffer which contains a matrix
+   and contains some relavant info */
+
+typedef struct {
+  int                     unsign;
+  int                     bitpix;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  double                  bzero;
+  double                  bscale;
+  char                   *buffer;
+} Matrix;
+   
+/* the FTable represents a complete table on disk */          
+typedef struct {
+  Header                 *header;
+  char                   *buffer;
+  int                     size;
+} FTable;
+
+/* the VTable represents rows from a table on disk */          
+typedef struct {
+  Header                 *header;
+  char                  **buffer;
+  int                     Nrow;
+  int                    *row;
+  int                     size;  /* total buffer size */
+  int                     pad;   /* bytes of padding at the end */
+} VTable;
+
+# ifndef PROTO
+# define PROTO(A) A
+# endif
+
+/******************************* Header functions *************/
+int   fits_read_header            PROTO((char *, Header *));
+int   fits_copy_header            PROTO((Header *, Header *)); 
+void  fits_free_header            PROTO((Header *)); 
+int   fits_write_header           PROTO((char *, Header *)); 
+int   fits_create_header          PROTO((Header *)); 
+int   fits_delete                 PROTO((Header *, char *, int)); 
+char *fits_header_field           PROTO((Header *, char *, int)); 
+int   fits_read_Xheader           PROTO((char *filename, Header *header, int N));
+int   fits_load_header            PROTO((FILE *f, Header *header));
+
+int   fits_fread_header           PROTO((FILE *, Header *));
+int   fits_fread_Theader          PROTO((FILE *, Header *));
+int   fits_fread_ftable           PROTO((FILE *, FTable *, char *)); 
+int   fits_fread_vtable           PROTO((FILE *f, VTable *table, char *extname, int Nrow, int *row));
+int   fits_fwrite_header          PROTO((FILE *, Header *)); 
+int   fits_fwrite_Theader         PROTO((FILE *, Header *));
+int   fits_fwrite_matrix          PROTO((FILE *, Matrix *));      
+int   fits_fwrite_table           PROTO((FILE *, FTable *)); 
+int   fits_fwrite_vtable          PROTO((FILE *, VTable *)); 
+
+int   fits_matrix_size            PROTO ((Header *));
+int   fits_init_header            PROTO ((Header *));
+int   fits_create_table_header    PROTO ((Header *, char *, char *));
+int   fits_table_to_vtable        PROTO ((FTable *ftable, VTable *vtable, int start, int Nkeep));
+int   fits_create_table           PROTO ((Header *, FTable *));
+int   fits_vadd_rows              PROTO ((VTable *, char *, int, int));
+int   fits_add_rows               PROTO ((FTable *, char *, int, int));
+char *fits_table_print            PROTO ((FTable *,...));
+
+/******************************* Matrix functions *************/
+int   fits_read_matrix            PROTO((char *, Matrix *));      
+int   fits_read_portion           PROTO((char *filename, Matrix *matrix, int Nskip, int Npix));
+void  fits_free_matrix            PROTO((Matrix *)); 
+int   fits_copy_matrix            PROTO((Matrix *, Matrix *)); 
+int   fits_write_matrix           PROTO((char *,Matrix *)); 
+int   fits_create_matrix          PROTO((Header *, Matrix *)); 
+double  fits_get_matrix_value     PROTO((Matrix *, int, int)); 
+void  fits_set_matrix_value       PROTO((Matrix *, int, int, double)); 
+void  fits_add_matrix_value       PROTO((Matrix *, int, int, double)); 
+int   fits_multiply_matrix        PROTO((Matrix *, Matrix *, Matrix *)); 
+int   fits_divide_matrix          PROTO((Matrix *, Matrix *, Matrix *)); 
+void  fits_insert_array           PROTO((Matrix *, Matrix *, int, int)); 
+int   fits_load_matrix            PROTO((FILE *f, Matrix *matrix, Header *header));
+int   fits_fread_matrix           PROTO((FILE *f, Matrix *matrix, Header *header));
+int   fits_read_segment           PROTO((char *filename, Matrix *matrix, char *region));
+int   fits_convert_format         PROTO((Header *header, Matrix *matrix, int outBitpix, double outScale, double outZero, int outUnsign));
+
+/******************************* Table functions *************/
+int   fits_load_Theader           PROTO((FILE *f, Header *Theader));
+int   fits_read_Theader           PROTO((char *, Header *));     
+int   fits_read_table             PROTO((char *, FTable *)); 
+int   fits_write_Theader          PROTO((char *, Header *header));
+int   fits_write_table            PROTO((char *, FTable *)); 
+int   fits_bintable_format        PROTO((char *, char *, int *, int *));
+int   fits_table_format           PROTO((char *, char *, int *, int *));
+int   fits_save_header            PROTO((FILE *, Header *header));
+int   fits_set_bintable_column    PROTO((Header *header, FTable *table, char *, void *, int));
+int   fits_set_table_column       PROTO((Header *header, FTable *table, char *, void *, int));
+int   fits_define_bintable_column PROTO((Header *header, char *, char *, char *, char *, double, double));
+int   fits_define_table_column    PROTO((Header *header, char *, char *, char *, char *));
+
+int   fits_free_table             PROTO((FTable *table));
+int   fits_free_vtable            PROTO((VTable *table));
+
+/* prototyping demanded for these four -- could be a problem on non-ANSI comp comp */
+int   fits_scan                   PROTO((Header *, char *, char *, int,...)); 
+int   fits_print                  PROTO((Header *, char *, char *, int,...)); 
+int   fits_modify                 PROTO((Header *, char *, char *, int,...)); 
+int   fits_table_column           PROTO((FTable *, char *, char *,...)); 
+int   fits_table_column           PROTO((FTable *table, char *, char *,...));
+
+char *fits_keyword_end            PROTO((char *line));
+int   fits_vscan                  PROTO((Header *header, char *field, char *mode, int N, va_list argp));
+int   fits_scan                   PROTO((Header *header, char *field, char *mode, int N,...));
+int   fits_stripwhite             PROTO((char *string));
+int   fits_matrix_size            PROTO((Header *header));
+
+int   fits_get_bintable_column_type PROTO((Header *header, char *label, char *type, int *Nval));
+int   fits_get_bintable_column    PROTO((Header *header, FTable *table, char *label, void **data));
+int   fits_get_table_column_type  PROTO((Header *header, char *label, char *type));
+int   fits_get_table_column       PROTO((Header *header, FTable *table, char *label, void **data));
+
+#endif /* FITSIO */
+
+/* this structure defines the buffer which contains a table
+   and contains some relavant info */
+
+# if (0)
+/* an old construct, no longer used.  remove if not needed */
+typedef struct {
+  int                     bitpix;
+  int                     Nfields;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  char                   *buffer;
+  Header                  header;
+} Table;
+# endif
+          
Index: /tags/start/Ohana/src/libfits/matrix/F_add_M.c
===================================================================
--- /tags/start/Ohana/src/libfits/matrix/F_add_M.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/matrix/F_add_M.c	(revision 12606)
@@ -0,0 +1,30 @@
+# include "fits.h"
+
+/*********************** fits insert array ***********************************/
+void fits_add_matrix (matrix, array, x, y) 
+Matrix *matrix, *array; 
+int x, y;
+{
+
+  /* there is no check here to match BITPIX, BZERO, or BSCALE */
+
+  int i, j;
+  double V;
+
+  if ((x + array[0].Naxis[0] > matrix[0].Naxis[0]) ||
+      (y + array[0].Naxis[1] > matrix[0].Naxis[1])) {
+    fprintf (stderr, "can't add array here: (%d,%d) - (%d,%d) vs (%d,%d)\n",
+	     x, y, x + array[0].Naxis[0], y + array[0].Naxis[1],
+	     matrix[0].Naxis[0], matrix[0].Naxis[1]);
+    return;
+  }
+
+  for (i = 0; i < array[0].Naxis[0]; i++) {
+    for (j = 0; j < array[0].Naxis[1]; j++) {
+      V = fits_get_matrix_value (array, i, j);
+      V += fits_get_matrix_value (matrix, x + i, y + j);
+      fits_set_matrix_value (matrix, x + i, y + j, V);
+    }
+  }
+}
+
Index: /tags/start/Ohana/src/libfits/matrix/F_add_M_value.c
===================================================================
--- /tags/start/Ohana/src/libfits/matrix/F_add_M_value.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/matrix/F_add_M_value.c	(revision 12606)
@@ -0,0 +1,18 @@
+# include "fits.h"
+
+/***************** fits add matrix value ***********************************/
+void fits_add_matrix_value (matrix, x, y, Value) 
+Matrix *matrix; 
+int x, y; 
+double Value;
+{
+
+  double value;
+
+  value = fits_get_matrix_value (matrix, x, y);
+  value += Value;
+  fits_set_matrix_value (matrix, x, y, value);
+
+}
+
+
Index: /tags/start/Ohana/src/libfits/matrix/F_convert_format.c
===================================================================
--- /tags/start/Ohana/src/libfits/matrix/F_convert_format.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/matrix/F_convert_format.c	(revision 12606)
@@ -0,0 +1,391 @@
+# include "fits.h"
+
+# define CONVERTDOWN \
+  inMode  *in; \
+  outMode *out; \
+  out = (outMode *) matrix[0].buffer; \
+  in  = (inMode  *) matrix[0].buffer; \
+  for (i = 0; i < Npixels; i++, out++, in++) \
+    *out = *in*A + B; \
+  REALLOCATE (matrix[0].buffer, char, matrix[0].size); 
+
+# define CONVERTSAME \
+  inMode  *in; \
+  outMode *out; \
+  out = (outMode *) matrix[0].buffer; \
+  in  = (inMode  *) matrix[0].buffer; \
+  for (i = 0; i < Npixels; i++, out++, in++) \
+    *out = *in*A + B; 
+
+# define CONVERTUP \
+  inMode  *in; \
+  outMode *out; \
+  REALLOCATE (matrix[0].buffer, char, matrix[0].size); \
+  out = (outMode *)matrix[0].buffer + Npixels - 1; \
+  in  = (inMode  *)matrix[0].buffer + Npixels - 1; \
+  for (i = 0; i < Npixels; i++, out--, in--) \
+    *out = *in*A + B;
+
+/*********************** fits convert format ***********************************/
+int fits_convert_format (Header *header, Matrix *matrix, int outBitpix, double outScale, double outZero, int outUnsign) {
+
+  unsigned long i, nbytes, Npixels;
+  int    inBitpix, inUnsign;
+  double inScale, inZero;
+  double A, B;
+
+  inBitpix         = header[0].bitpix;
+  inScale          = header[0].bscale;
+  inZero           = header[0].bzero;
+  inUnsign         = header[0].unsign;
+
+  if ((inBitpix == outBitpix) && (inScale == outScale) && 
+      (inZero == outZero) && (inUnsign == outUnsign))
+    return (TRUE);
+
+  matrix[0].bitpix = header[0].bitpix = outBitpix;
+  matrix[0].bscale = header[0].bscale = outScale;
+  matrix[0].bzero  = header[0].bzero  = outZero;
+  matrix[0].unsign = header[0].unsign = outUnsign;
+  matrix[0].size   = fits_matrix_size (header);
+  fits_modify (header, "BITPIX", "%d", 1, outBitpix);
+  fits_modify (header, "BSCALE", "%lf", 1, outScale);
+  fits_modify (header, "BZERO",  "%lf", 1, outZero);
+  fits_modify (header, "UNSIGN", "%t", 1, outUnsign);
+
+  Npixels          = header[0].Naxis[0]*header[0].Naxis[1];
+  nbytes           = Npixels * (abs(outBitpix) / 8);
+
+  A = inScale / outScale;
+  B = (inZero - outZero) / outScale;
+
+  if ((!outUnsign) && (!inUnsign)) {  /** BLOCK 1 **/
+    switch (inBitpix) {
+    case 8: 
+      { typedef char inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTSAME; break; }
+	case 16:  { typedef short          outMode; CONVERTUP;   break; }
+	case -16: { typedef unsigned short outMode; CONVERTUP;   break; }
+	case 32:  { typedef int            outMode; CONVERTUP;   break; }
+	case -32: { typedef float          outMode; CONVERTUP;   break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 16: 
+      { typedef short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short outMode; CONVERTSAME; break; }
+	case 32:  { typedef int            outMode; CONVERTUP;   break; }
+	case -32: { typedef float          outMode; CONVERTUP;   break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case -16: 
+      { typedef unsigned short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short outMode; CONVERTSAME; break; }
+	case 32:  { typedef int            outMode; CONVERTUP;   break; }
+	case -32: { typedef float          outMode; CONVERTUP;   break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 32: 
+      { typedef int inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short outMode; CONVERTDOWN; break; }
+	case 32:  { typedef int            outMode; CONVERTSAME; break; }
+	case -32: { typedef float          outMode; CONVERTSAME; break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;
+    case -32: 
+      { typedef float inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short outMode; CONVERTDOWN; break; }
+	case 32:  { typedef int            outMode; CONVERTSAME; break; }
+	case -32: { typedef float          outMode; CONVERTSAME; break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;
+    case -64: 
+      { typedef double inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short outMode; CONVERTDOWN; break; }
+	case 32:  { typedef int            outMode; CONVERTDOWN; break; }
+	case -32: { typedef float          outMode; CONVERTDOWN; break; }
+	case -64: { typedef double         outMode; CONVERTSAME; break; }
+	}
+      }
+    }
+  }
+  if ((outUnsign) && (!inUnsign)) {  /** BLOCK 3 **/
+    switch (inBitpix) {
+    case 8: 
+      { typedef char inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTSAME; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTUP;   break; }
+	case -16: { typedef unsigned short  outMode; CONVERTUP;   break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTUP;   break; }
+	case -32: { typedef          float  outMode; CONVERTUP;   break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 16: 
+      { typedef short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTSAME; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTUP;   break; }
+	case -32: { typedef          float  outMode; CONVERTUP;   break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case -16: 
+      { typedef unsigned short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTSAME; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTUP;   break; }
+	case -32: { typedef          float  outMode; CONVERTUP;   break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 32: 
+      { typedef int inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTSAME; break; }
+	case -32: { typedef          float  outMode; CONVERTSAME; break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;
+    case -32: 
+      { typedef float inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTSAME; break; }
+	case -32: { typedef          float  outMode; CONVERTSAME; break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;
+    case -64: 
+      { typedef double inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTDOWN; break; }
+	case -32: { typedef          float  outMode; CONVERTDOWN; break; }
+	case -64: { typedef          double outMode; CONVERTSAME; break; }
+	}
+      }
+    }
+  }
+  if ((!outUnsign) && (inUnsign)) {  /** BLOCK 2 **/
+    switch (inBitpix) {
+    case 8: 
+      { typedef unsigned char inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTSAME; break; }
+	case 16:  { typedef short          outMode; CONVERTUP;   break; }
+	case -16: { typedef unsigned short outMode; CONVERTUP;   break; }
+	case 32:  { typedef int            outMode; CONVERTUP;   break; }
+	case -32: { typedef float          outMode; CONVERTUP;   break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 16: 
+      { typedef unsigned short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short outMode; CONVERTSAME; break; }
+	case 32:  { typedef int            outMode; CONVERTUP;   break; }
+	case -32: { typedef float          outMode; CONVERTUP;   break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case -16: 
+      { typedef unsigned short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short outMode; CONVERTSAME; break; }
+	case 32:  { typedef int            outMode; CONVERTUP;   break; }
+	case -32: { typedef float          outMode; CONVERTUP;   break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 32: 
+      { typedef unsigned int inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short outMode; CONVERTDOWN; break; }
+	case 32:  { typedef int            outMode; CONVERTSAME; break; }
+	case -32: { typedef float          outMode; CONVERTSAME; break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;
+    case -32: 
+      { typedef float inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short outMode; CONVERTDOWN; break; }
+	case 32:  { typedef int            outMode; CONVERTSAME; break; }
+	case -32: { typedef float          outMode; CONVERTSAME; break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;
+    case -64: 
+      { typedef double inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char           outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short outMode; CONVERTDOWN; break; }
+	case 32:  { typedef int            outMode; CONVERTDOWN; break; }
+	case -32: { typedef float          outMode; CONVERTDOWN; break; }
+	case -64: { typedef double         outMode; CONVERTSAME; break; }
+	}
+      }
+    }
+  }
+  if ((outUnsign) && (inUnsign)) {
+    switch (inBitpix) {
+    case 8: 
+      { typedef unsigned char inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTSAME; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTUP;   break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTUP;   break; }
+	case -32: { typedef          float  outMode; CONVERTUP;   break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 16: 
+      { typedef unsigned short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTUP;   break; }
+	case -32: { typedef          float  outMode; CONVERTUP;   break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case -16: 
+      { typedef unsigned short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTUP;   break; }
+	case -32: { typedef          float  outMode; CONVERTUP;   break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 32: 
+      { typedef unsigned int inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTSAME; break; }
+	case -32: { typedef          float  outMode; CONVERTSAME; break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}				    
+      }					    
+      break;				    
+    case -32: 				    
+      { typedef float inMode;		    
+	switch (outBitpix) {		    
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTSAME; break; }
+	case -32: { typedef          float  outMode; CONVERTSAME; break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}				    
+      }					    
+      break;				    
+    case -64: 				    
+      { typedef double inMode;		    
+	switch (outBitpix) {		    
+	case 8:   { typedef unsigned char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTDOWN; break; }
+	case -32: { typedef          float  outMode; CONVERTDOWN; break; }
+	case -64: { typedef          double outMode; CONVERTSAME; break; }
+	}
+      }
+    }
+  }
+
+  /* zero the padding region */
+  {
+    char *out;
+    int Nextra;
+    
+    out = (char *)matrix[0].buffer;
+    Nextra = matrix[0].size - nbytes;
+    bzero (&out[nbytes], Nextra);
+  }
+
+  return (TRUE);
+}
+ 
+/* WARNING --- this is STILL machine dependant.  It will now work on all 
+   machines, as long as char, int, short, float, double have sizes of 
+   8, 16, 32, 32, 64 bits resp.  However, the floating pt types are NOT
+   universal (or FITS standard), and so can't exchange from machine to 
+   machine. */
+
+/* NOTICE -- This file looks rather strange.  It is set this way to make 
+   all of the possible inter-conversions without too much excess code. 
+   The macros CONVERTUP and CONVERTDOWN need to be distinct.
+   Going to smaller or equal BITPIX, it is safe to run the array forward 
+   and allocate after the conversion.
+   Going to larger BITPIX, you need to reallocate first and run backwards 
+   to avoid wiping out the pixels.
+   OK, to deal with in and out UNSIGN, I have made four if blocks that are
+   almost identical. this looks silly.  any suggestions? 
+*/
Index: /tags/start/Ohana/src/libfits/matrix/F_copy_M.c
===================================================================
--- /tags/start/Ohana/src/libfits/matrix/F_copy_M.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/matrix/F_copy_M.c	(revision 12606)
@@ -0,0 +1,26 @@
+# include "fits.h"
+
+/*********************** fits copy header ***********************************/
+int fits_copy_matrix (matrix1, matrix2) 
+Matrix *matrix1, *matrix2;
+{
+
+  int i;
+
+  matrix2[0].unsign = matrix1[0].unsign;
+  matrix2[0].bitpix = matrix1[0].bitpix;
+  matrix2[0].size   = matrix1[0].size;
+  matrix2[0].bzero  = matrix1[0].bzero;
+  matrix2[0].bscale = matrix1[0].bscale;
+  matrix2[0].Naxes  = matrix1[0].Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++) 
+    matrix2[0].Naxis[i] = matrix1[0].Naxis[i];
+
+  ALLOCATE (matrix2[0].buffer, char, matrix2[0].size);
+  
+  memcpy (matrix2[0].buffer, matrix1[0].buffer, matrix2[0].size);
+
+  return (TRUE);
+}	
+
+
Index: /tags/start/Ohana/src/libfits/matrix/F_create_M.c
===================================================================
--- /tags/start/Ohana/src/libfits/matrix/F_create_M.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/matrix/F_create_M.c	(revision 12606)
@@ -0,0 +1,27 @@
+# include "fits.h"
+
+/*********************** fits create matrix *******************************/
+int fits_create_matrix (header, matrix) 
+Header *header;
+Matrix *matrix;
+{
+
+  int i, Nbytes;
+
+  matrix[0].bitpix = header[0].bitpix;
+  matrix[0].unsign = header[0].unsign;
+  matrix[0].bscale = header[0].bscale;
+  matrix[0].bzero  = header[0].bzero;
+  matrix[0].Naxes  = header[0].Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    matrix[0].Naxis[i] = header[0].Naxis[i];
+
+  Nbytes = fits_matrix_size (header);
+  ALLOCATE (matrix[0].buffer, char, MAX (Nbytes, 1));
+  bzero (matrix[0].buffer, Nbytes);
+  
+  matrix[0].size = Nbytes;
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/libfits/matrix/F_divide_M.c
===================================================================
--- /tags/start/Ohana/src/libfits/matrix/F_divide_M.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/matrix/F_divide_M.c	(revision 12606)
@@ -0,0 +1,31 @@
+# include "fits.h"
+
+/********************* fits divide matrix ***********************************/
+int fits_divide_matrix (M1, M2, M3) 
+Matrix *M1, *M2, *M3;
+{
+
+  int i,j;
+  double value, val2;
+
+  if ((M1[0].Naxis[0] != M2[0].Naxis[0]) ||
+      (M1[0].Naxis[1] != M2[0].Naxis[1])) 
+    return (FALSE);
+
+  for (i = 0; i < M1[0].Naxis[0]; i++) {
+    for (j = 0; j < M1[0].Naxis[1]; j++) {
+      value = fits_get_matrix_value (M1, i, j);
+      val2  = fits_get_matrix_value (M2, i, j);
+      if (val2 != 0) 
+	value = value / val2;
+      else
+	value = 0.0;
+      fits_set_matrix_value (M3, i, j, value);
+    }
+  }
+  
+  return (TRUE);
+
+}
+
+
Index: /tags/start/Ohana/src/libfits/matrix/F_free_M.c
===================================================================
--- /tags/start/Ohana/src/libfits/matrix/F_free_M.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/matrix/F_free_M.c	(revision 12606)
@@ -0,0 +1,12 @@
+# include "fits.h"
+
+/*********************** fits free matrix ***********************************/
+void fits_free_matrix (Matrix *matrix) {
+
+  if (matrix[0].buffer == (char *) NULL) return;
+  free (matrix[0].buffer);
+  matrix[0].buffer = (char *) NULL;
+  
+}
+
+
Index: /tags/start/Ohana/src/libfits/matrix/F_get_M_value.c
===================================================================
--- /tags/start/Ohana/src/libfits/matrix/F_get_M_value.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/matrix/F_get_M_value.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include "fits.h"
+
+/***************** fits get matrix value ***********************************/
+double fits_get_matrix_value (matrix, x, y) 
+Matrix *matrix; 
+int x, y;
+{
+
+  double value;
+  int pixel;
+
+  if ((x < 0) || (x >= matrix[0].Naxis[0]) || (y < 0) || (y >= matrix[0].Naxis[1]))
+    return (0.0);
+  pixel = matrix[0].Naxis[0]*y + x;
+  value = HUGE_VAL;
+
+  if (matrix[0].unsign) {
+    switch (matrix[0].bitpix) {
+    case 8:
+      value = *((unsigned char  *) matrix[0].buffer + pixel);
+      break;
+    case 16:
+      value = *((unsigned short *) matrix[0].buffer + pixel);
+      break;
+    case 32:
+      value = *((unsigned int   *) matrix[0].buffer + pixel);
+      break;
+    case -32:
+      value = *((float          *) matrix[0].buffer + pixel);
+      break;
+    case -64:
+      value = *((double         *) matrix[0].buffer + pixel);
+      break;
+    }
+  }
+  else {
+    switch (matrix[0].bitpix) {
+    case 8:
+      value = *((char  *) matrix[0].buffer + pixel);
+      break;
+    case 16:
+      value = *((short *) matrix[0].buffer + pixel);
+      break;
+    case 32:
+      value = *((int   *) matrix[0].buffer + pixel);
+      break;
+    case -32:
+      value = *((float          *) matrix[0].buffer + pixel);
+      break;
+    case -64:
+      value = *((double         *) matrix[0].buffer + pixel);
+      break;
+    }
+  }
+
+  value = matrix[0].bscale*value + matrix[0].bzero;
+  return (value);
+
+}
+
+
Index: /tags/start/Ohana/src/libfits/matrix/F_insert_M.c
===================================================================
--- /tags/start/Ohana/src/libfits/matrix/F_insert_M.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/matrix/F_insert_M.c	(revision 12606)
@@ -0,0 +1,31 @@
+# include "fits.h"
+
+/*********************** fits insert array ***********************************/
+void fits_insert_matrix (matrix, array, x, y) 
+Matrix *matrix, *array; 
+int x, y;
+{
+
+  /* there is no check here to match BITPIX, BZERO, or BSCALE */
+
+  int i, start_m, Nbytes_m, Nbytes;
+
+  if ((x + array[0].Naxis[0] > matrix[0].Naxis[0]) ||
+      (y + array[0].Naxis[1] > matrix[0].Naxis[1])) {
+    fprintf (stderr, "can't insert array here: (%d,%d) - (%d,%d) vs (%d,%d)\n",
+	     x, y, x + array[0].Naxis[0], y + array[0].Naxis[1],
+	     matrix[0].Naxis[0], matrix[0].Naxis[1]);
+    return;
+  }
+
+  Nbytes = array[0].Naxis[0]*abs(array[0].bitpix) / 8;
+  Nbytes_m = matrix[0].Naxis[0]*abs(matrix[0].bitpix) / 8;
+  start_m = y*Nbytes_m + x*abs(matrix[0].bitpix) / 8;
+
+  for (i = 0; i < array[0].Naxis[1]; i++) {
+    memmove (&matrix[0].buffer[start_m + i*Nbytes_m], 
+	     &array[0].buffer[i*Nbytes], Nbytes);
+  }
+  
+}
+
Index: /tags/start/Ohana/src/libfits/matrix/F_load_M.c
===================================================================
--- /tags/start/Ohana/src/libfits/matrix/F_load_M.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/matrix/F_load_M.c	(revision 12606)
@@ -0,0 +1,91 @@
+# include "fits.h"
+
+int fits_fread_matrix (FILE *f, Matrix *matrix, Header *header) {
+  
+  int status;
+  
+  status = fits_load_matrix (f, matrix, header);
+  return (status);
+}
+
+/*********************** fits read matrix ***********************************/
+int fits_load_matrix (FILE *f, Matrix *matrix, Header *header) {
+
+  int i, nbytes, Nbytes;
+  unsigned char *byte0, *byte1, *byte2, *byte3, *byte4, *byte5, *byte6, *byte7, tmp;
+  int perpix;
+
+  matrix[0].bitpix = header[0].bitpix;
+  matrix[0].unsign = header[0].unsign;
+  matrix[0].bscale = header[0].bscale;
+  matrix[0].bzero  = header[0].bzero;
+  matrix[0].Naxes  = header[0].Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    matrix[0].Naxis[i] = header[0].Naxis[i];
+
+  Nbytes = fits_matrix_size (header);
+  ALLOCATE (matrix[0].buffer, char, Nbytes);
+  matrix[0].size = Nbytes;
+
+  nbytes = fread (matrix[0].buffer, sizeof(char), Nbytes, f);
+
+# ifdef BYTE_SWAP  
+  perpix = abs(header[0].bitpix) / 8;
+  if (perpix > 1) {
+    byte0 = (char *) matrix[0].buffer;
+    byte1 = (char *) matrix[0].buffer + 1;
+    byte2 = (char *) matrix[0].buffer + 2;
+    byte3 = (char *) matrix[0].buffer + 3;
+    byte4 = (char *) matrix[0].buffer + 4;
+    byte5 = (char *) matrix[0].buffer + 5;
+    byte6 = (char *) matrix[0].buffer + 6;
+    byte7 = (char *) matrix[0].buffer + 7;
+    if (perpix == 2) {
+      for (i = 0; i < nbytes; i+=2, byte0 += 2, byte1 += 2) {
+	tmp = *byte0;
+	*byte0 = *byte1;
+	*byte1 = tmp;
+      }
+    }
+    if (perpix == 4) {
+      for (i = 0; i < nbytes; i+=4, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+	tmp = *byte0;
+	*byte0 = *byte3;
+	*byte3 = tmp;
+	tmp = *byte1;
+	*byte1 = *byte2;
+	*byte2 = tmp;
+      }
+    }
+    if (perpix == 8) {
+      for (i = 0; i < nbytes; i+=8, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
+	tmp = *byte0;
+	*byte0 = *byte7;
+	*byte7 = tmp;
+	tmp = *byte1;
+	*byte1 = *byte6;
+	*byte6 = tmp;
+	tmp = *byte1;
+	*byte2 = *byte5;
+	*byte5 = tmp;
+	tmp = *byte1;
+	*byte3 = *byte4;
+	*byte4 = tmp;
+      }
+    }
+  }
+# endif
+
+  if (nbytes < Nbytes - 2880) {  /* this is a bad FITS error: image is not OK */
+    fprintf (stderr, "error reading in matrix data from FITS file\n");
+    return (FALSE);
+  }
+  if (nbytes != Nbytes) {  /* this is a FITS error, but often the image is OK */
+    fprintf (stderr, "incomplete block in FITS file: (%d, %d)\n", nbytes, Nbytes);
+    return (TRUE); 
+  }
+
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/libfits/matrix/F_matrix.c
===================================================================
--- /tags/start/Ohana/src/libfits/matrix/F_matrix.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/matrix/F_matrix.c	(revision 12606)
@@ -0,0 +1,21 @@
+# include "fits.h"
+
+int fits_matrix_size (Header *header) {
+  
+  int i, Nrec, size;
+
+  if (header[0].Naxes == 0) return (0);
+
+  size = abs(header[0].bitpix / 8);
+
+  for (i = 0; i < header[0].Naxes; i++)
+    size *= header[0].Naxis[i];
+
+  /* round up to next complete block */
+  if (size % FT_RECORD_SIZE) {
+    Nrec = 1 + (int) (size / FT_RECORD_SIZE);
+    size = FT_RECORD_SIZE * Nrec;
+  }
+
+  return (size);
+}
Index: /tags/start/Ohana/src/libfits/matrix/F_multiply_M.c
===================================================================
--- /tags/start/Ohana/src/libfits/matrix/F_multiply_M.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/matrix/F_multiply_M.c	(revision 12606)
@@ -0,0 +1,27 @@
+# include "fits.h"
+
+/******************* fits multiply matrix ***********************************/
+int fits_multiply_matrix (M1, M2, M3) 
+Matrix *M1, *M2, *M3;
+{
+
+  int i,j;
+  double value;
+
+  if ((M1[0].Naxis[0] != M2[0].Naxis[0]) ||
+      (M1[0].Naxis[1] != M2[0].Naxis[1])) 
+    return (FALSE);
+
+  for (i = 0; i < M1[0].Naxis[0]; i++) {
+    for (j = 0; j < M1[0].Naxis[1]; j++) {
+      value = fits_get_matrix_value (M1, i, j);
+      value *= fits_get_matrix_value (M2, i, j);
+      fits_set_matrix_value (M3, i, j, value);
+    }
+  }
+  
+  return (TRUE);
+
+}
+
+
Index: /tags/start/Ohana/src/libfits/matrix/F_read_M.c
===================================================================
--- /tags/start/Ohana/src/libfits/matrix/F_read_M.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/matrix/F_read_M.c	(revision 12606)
@@ -0,0 +1,28 @@
+# include "fits.h"
+
+/*********************** fits read matrix ***********************************/
+int fits_read_matrix (char *filename, Matrix *matrix) {
+
+  FILE *f;
+  Header header;
+  int status;
+
+  status = fits_read_header (filename, &header);
+  if (!status) {
+    fprintf (stderr, "error reading header of FITS file %s\n", filename);
+    return (FALSE);
+  }
+
+  f = fopen (filename, "r");
+  if (f == NULL) return (FALSE);
+
+  fseek (f, header.size, 0);
+  
+  status = fits_load_matrix (f, matrix, &header);
+
+  fclose (f);
+
+  return (status);
+
+}
+
Index: /tags/start/Ohana/src/libfits/matrix/F_read_portion.c
===================================================================
--- /tags/start/Ohana/src/libfits/matrix/F_read_portion.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/matrix/F_read_portion.c	(revision 12606)
@@ -0,0 +1,111 @@
+# include "fits.h"
+# ifndef SEEK_CUR 
+# define SEEK_SET 0   
+# define SEEK_CUR 1   
+# define SEEK_END 2
+# endif
+
+/*********************** fits read matrix ***********************************/
+/** the result of this function is a matrix with dimension Npix * 1 **/
+int fits_read_portion (char *filename, Matrix *matrix, int Nskip, int Npix) {
+
+  FILE *f;
+  Header header;
+  int status, i, nbytes, Nbytes, Nrec;
+  unsigned char *byte0, *byte1, *byte2, *byte3, *byte4, *byte5, *byte6, *byte7, ctmp;
+  int perpix;
+
+  status = fits_read_header (filename, &header);
+  if (!status) {
+    fprintf (stderr, "error reading header of FITS file %s\n", filename);
+    return (FALSE);
+  }
+
+  matrix[0].bitpix = header.bitpix;
+  matrix[0].unsign = header.unsign;
+  matrix[0].bscale = header.bscale;
+  matrix[0].bzero  = header.bzero;
+  matrix[0].Naxes  = 2;
+  matrix[0].Naxis[0] = Npix;
+  matrix[0].Naxis[1] = 1;
+
+  Nbytes = Npix  * abs (matrix[0].bitpix)/8;
+  Nskip  = Nskip * abs (matrix[0].bitpix)/8;
+
+  /* round up to next complete block */
+  if (Nbytes % FT_RECORD_SIZE) {
+    Nrec = 1 + (int) (Nbytes / FT_RECORD_SIZE);
+    Nbytes = FT_RECORD_SIZE * Nrec;
+  }
+  matrix[0].size = Nbytes;
+  ALLOCATE (matrix[0].buffer, char, Nbytes);
+
+  /* open file, read data, close file */
+  f = fopen (filename, "r");
+  if (f == NULL) return (FALSE);
+  fseek (f, header.size + Nskip, SEEK_SET);
+  nbytes = fread (matrix[0].buffer, sizeof(char), Nbytes, f);
+  fclose (f);
+
+# ifdef BYTE_SWAP  
+  perpix = abs(header.bitpix) / 8;
+  if (perpix > 1) {
+    byte0 = (char *) matrix[0].buffer;
+    byte1 = (char *) matrix[0].buffer + 1;
+    byte2 = (char *) matrix[0].buffer + 2;
+    byte3 = (char *) matrix[0].buffer + 3;
+    byte4 = (char *) matrix[0].buffer + 4;
+    byte5 = (char *) matrix[0].buffer + 5;
+    byte6 = (char *) matrix[0].buffer + 6;
+    byte7 = (char *) matrix[0].buffer + 7;
+    if (perpix == 2) {
+      for (i = 0; i < nbytes; i+=2, byte0 += 2, byte1 += 2) {
+	ctmp = *byte0;
+	*byte0 = *byte1;
+	*byte1 = ctmp;
+      }
+    }
+    if (perpix == 4) {
+      for (i = 0; i < nbytes; i+=4, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+	ctmp = *byte0;
+	*byte0 = *byte3;
+	*byte3 = ctmp;
+	ctmp = *byte1;
+	*byte1 = *byte2;
+	*byte2 = ctmp;
+      }
+    }
+    if (perpix == 8) {
+      for (i = 0; i < nbytes; i+=8, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
+	ctmp = *byte0;
+	*byte0 = *byte7;
+	*byte7 = ctmp;
+	ctmp = *byte1;
+	*byte1 = *byte6;
+	*byte6 = ctmp;
+	ctmp = *byte1;
+	*byte2 = *byte5;
+	*byte5 = ctmp;
+	ctmp = *byte1;
+	*byte3 = *byte4;
+	*byte4 = ctmp;
+      }
+    }
+  }
+# endif
+
+  fits_free_header (&header);
+
+  if (nbytes < Nbytes - 2880) {  /* this is a bad FITS error: image is not OK */
+    fprintf (stderr, "error reading in matrix data from FITS file %s (%d < %d - 2880)\n", filename, nbytes, Nbytes);
+    return (FALSE);
+  }
+  if (nbytes != Nbytes) {  /* this is a FITS error, but often the image is OK */
+    fprintf (stderr, "incomplete block in %s: (%d, %d)\n", filename, nbytes, Nbytes);
+    return (TRUE); 
+  }
+
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/libfits/matrix/F_read_segment.c
===================================================================
--- /tags/start/Ohana/src/libfits/matrix/F_read_segment.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/matrix/F_read_segment.c	(revision 12606)
@@ -0,0 +1,143 @@
+# include "fits.h"
+
+/** warning: this function requires 'dparse' which is included in libohana.a **/
+int dparse (double *, int, char *region);
+
+/*********************** fits read matrix ***********************************/
+int fits_read_segment (char *filename, Matrix *matrix, char *region) {
+
+  FILE *f;
+  Header header;
+  int status, i, nbytes, Nbytes, Nskip, NbytesData;
+  int wantaxis[FT_MAX_NAXES][2];
+  unsigned char *byte0, *byte1, *byte2, *byte3, *byte4, *byte5, *byte6, *byte7, ctmp;
+  double tmp;
+  int perpix;
+
+  status = fits_read_header (filename, &header);
+  if (!status) {
+    fprintf (stderr, "error reading header of FITS file %s\n", filename);
+    return (FALSE);
+  }
+
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    return (FALSE);
+  }
+
+  for (i = 0; i < FT_MAX_NAXES; i++) {
+    wantaxis[i][0] = wantaxis[i][1] = 0;
+  }
+
+  for (i = 0; i < header.Naxes; i++) {
+    status = dparse (&tmp, 2*i + 1, region);
+    if (!status || (tmp < 0))
+      wantaxis[i][0] = 0;
+    else 
+      wantaxis[i][0] = (tmp > header.Naxis[i] - 1) ? header.Naxis[i] - 1 : tmp;
+    status = dparse (&tmp, 2*i + 2, region);
+    if (!status || (tmp < 0))
+      wantaxis[i][1] = header.Naxis[i];
+    else 
+      wantaxis[i][1] = (tmp > header.Naxis[i]) ? header.Naxis[i] : tmp;
+  }
+
+  fseek (f, header.size, 0);
+
+  matrix[0].bitpix = header.bitpix;
+  matrix[0].unsign = header.unsign;
+  matrix[0].bscale = header.bscale;
+  matrix[0].bzero  = header.bzero;
+  matrix[0].Naxes  = header.Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    matrix[0].Naxis[i] = wantaxis[i][1] - wantaxis[i][0];
+
+  matrix[0].size = abs (matrix[0].bitpix) / 8;
+  for (i = 0; i < matrix[0].Naxes; i++)
+    matrix[0].size *= matrix[0].Naxis[i];
+
+  Nskip = wantaxis[2][0]*matrix[0].Naxis[0]*matrix[0].Naxis[1]*abs(matrix[0].bitpix)/8;
+  NbytesData = Nskip + matrix[0].size;
+
+  if (NbytesData % FT_RECORD_SIZE) 
+    Nbytes = FT_RECORD_SIZE * ((int) (NbytesData / FT_RECORD_SIZE) + 1) - Nskip;
+  else 
+    Nbytes = FT_RECORD_SIZE * ((int) (NbytesData / FT_RECORD_SIZE)) - Nskip;
+
+  ALLOCATE (matrix[0].buffer, char, MAX (Nbytes, 1));
+
+# ifndef SEEK_CUR 
+# define SEEK_SET 0   
+# define SEEK_CUR 1   
+# define SEEK_END 2
+# endif
+
+  /* currently only good for reading in full planes in 3-D */
+  fseek (f, Nskip, SEEK_CUR);
+
+  nbytes = fread (matrix[0].buffer, sizeof(char), Nbytes, f);
+  fclose (f);
+  matrix[0].size = Nbytes;
+
+# ifdef BYTE_SWAP  
+  perpix = abs(header.bitpix) / 8;
+  if (perpix > 1) {
+    byte0 = (char *) matrix[0].buffer;
+    byte1 = (char *) matrix[0].buffer + 1;
+    byte2 = (char *) matrix[0].buffer + 2;
+    byte3 = (char *) matrix[0].buffer + 3;
+    byte4 = (char *) matrix[0].buffer + 4;
+    byte5 = (char *) matrix[0].buffer + 5;
+    byte6 = (char *) matrix[0].buffer + 6;
+    byte7 = (char *) matrix[0].buffer + 7;
+    if (perpix == 2) {
+      for (i = 0; i < nbytes; i+=2, byte0 += 2, byte1 += 2) {
+	ctmp = *byte0;
+	*byte0 = *byte1;
+	*byte1 = ctmp;
+      }
+    }
+    if (perpix == 4) {
+      for (i = 0; i < nbytes; i+=4, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+	ctmp = *byte0;
+	*byte0 = *byte3;
+	*byte3 = ctmp;
+	ctmp = *byte1;
+	*byte1 = *byte2;
+	*byte2 = ctmp;
+      }
+    }
+    if (perpix == 8) {
+      for (i = 0; i < nbytes; i+=8, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
+	ctmp = *byte0;
+	*byte0 = *byte7;
+	*byte7 = ctmp;
+	ctmp = *byte1;
+	*byte1 = *byte6;
+	*byte6 = ctmp;
+	ctmp = *byte1;
+	*byte2 = *byte5;
+	*byte5 = ctmp;
+	ctmp = *byte1;
+	*byte3 = *byte4;
+	*byte4 = ctmp;
+      }
+    }
+  }
+# endif
+
+  fits_free_header (&header);
+
+  if (nbytes < Nbytes - 2880) {  /* this is a bad FITS error: image is not OK */
+    fprintf (stderr, "error reading in matrix data from FITS file %s (%d < %d - 2880)\n", filename, nbytes, Nbytes);
+    return (FALSE);
+  }
+  if (nbytes != Nbytes) {  /* this is a FITS error, but often the image is OK */
+    fprintf (stderr, "incomplete block in %s: (%d, %d)\n", filename, nbytes, Nbytes);
+    return (TRUE); 
+  }
+
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/libfits/matrix/F_set_M_value.c
===================================================================
--- /tags/start/Ohana/src/libfits/matrix/F_set_M_value.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/matrix/F_set_M_value.c	(revision 12606)
@@ -0,0 +1,57 @@
+# include "fits.h"
+
+/****************** fits set matrix value ***********************************/
+void fits_set_matrix_value (matrix, x, y, Value) 
+Matrix *matrix; 
+int x, y; 
+double Value;
+{
+
+  int pixel;
+  double value;
+
+  pixel = matrix[0].Naxis[0]*y + x;
+  value = (Value - matrix[0].bzero) / matrix[0].bscale;
+
+  if (matrix[0].unsign) {
+    switch (matrix[0].bitpix) {
+    case 8:
+      *((char  *) matrix[0].buffer + pixel) = value;
+      break;
+    case 16:
+      *((short *) matrix[0].buffer + pixel) = value;
+      break;
+    case 32:
+      *((int   *) matrix[0].buffer + pixel) = value;
+      break;
+    case -32:
+      *((float          *) matrix[0].buffer + pixel) = value;
+      break;
+    case -64:
+      *((double         *) matrix[0].buffer + pixel) = value;
+      break;
+    }
+  }
+  else {
+    switch (matrix[0].bitpix) {
+    case 8:
+      *((unsigned char  *) matrix[0].buffer + pixel) = value;
+      break;
+    case 16:
+      *((unsigned short *) matrix[0].buffer + pixel) = value;
+      break;
+    case 32:
+      *((unsigned int   *) matrix[0].buffer + pixel) = value;
+      break;
+    case -32:
+      *((float          *) matrix[0].buffer + pixel) = value;
+      break;
+    case -64:
+      *((double         *) matrix[0].buffer + pixel) = value;
+      break;
+    }
+  }
+
+}
+
+
Index: /tags/start/Ohana/src/libfits/matrix/F_write_M.c
===================================================================
--- /tags/start/Ohana/src/libfits/matrix/F_write_M.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/matrix/F_write_M.c	(revision 12606)
@@ -0,0 +1,141 @@
+# include "fits.h"
+
+/*********************** fits write matrix ***********************************/
+int fits_write_matrix (char *filename, Matrix *matrix) {
+
+  FILE *f;
+  int status;
+
+  f = fopen (filename, "a");
+  if (f == NULL) return (FALSE);
+  
+  fseek (f, 0, SEEK_END);  /* write matrix to end of file! */
+
+  status = fits_fwrite_matrix (f, matrix);
+  fclose (f);
+  return (status);
+}
+
+/*********************** fits write matrix ***********************************/
+int fits_fwrite_matrix (FILE *f, Matrix *matrix) {
+
+  int i, status, nbytes, Nbytes;
+  unsigned char *byte0, *byte1, *byte2, *byte3, *byte4, *byte5, *byte6, *byte7, tmp;
+  int perpix;
+
+  status = TRUE;
+
+  /* this is a bit dangerous: we are not realloc'ing the matrix.
+     if the size is wrong, it probably should simply pad the fwrite statement.
+     better policy should be defined (ie, matrix.size always correct blocking?)
+ */
+
+  if (matrix[0].size % FT_RECORD_SIZE) 
+    nbytes = FT_RECORD_SIZE * ((int) (matrix[0].size / FT_RECORD_SIZE) + 1);
+  else 
+    nbytes = FT_RECORD_SIZE * ((int) (matrix[0].size / FT_RECORD_SIZE));
+
+  /* this is a bit cumbersome: swap all words, write out file, then swap back... */
+# ifdef BYTE_SWAP  
+  perpix = abs(matrix[0].bitpix) / 8;
+  if (perpix > 1) {
+    byte0 = (char *) matrix[0].buffer;
+    byte1 = (char *) matrix[0].buffer + 1;
+    byte2 = (char *) matrix[0].buffer + 2;
+    byte3 = (char *) matrix[0].buffer + 3;
+    byte4 = (char *) matrix[0].buffer + 4;
+    byte5 = (char *) matrix[0].buffer + 5;
+    byte6 = (char *) matrix[0].buffer + 6;
+    byte7 = (char *) matrix[0].buffer + 7;
+    if (perpix == 2) {
+      for (i = 0; i < nbytes; i+=2, byte0 += 2, byte1 += 2) {
+	tmp = *byte0;
+	*byte0 = *byte1;
+	*byte1 = tmp;
+      }
+    }
+    if (perpix == 4) {
+      for (i = 0; i < nbytes; i+=4, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+	tmp = *byte0;
+	*byte0 = *byte3;
+	*byte3 = tmp;
+	tmp = *byte1;
+	*byte1 = *byte2;
+	*byte2 = tmp;
+      }
+    }
+    if (perpix == 8) {
+      for (i = 0; i < nbytes; i+=8, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
+	tmp = *byte0;
+	*byte0 = *byte7;
+	*byte7 = tmp;
+	tmp = *byte1;
+	*byte1 = *byte6;
+	*byte6 = tmp;
+	tmp = *byte1;
+	*byte2 = *byte5;
+	*byte5 = tmp;
+	tmp = *byte1;
+	*byte3 = *byte4;
+	*byte4 = tmp;
+      }
+    }
+  }
+# endif
+
+  Nbytes = fwrite (matrix[0].buffer, sizeof(char), nbytes, f);
+  if (Nbytes != nbytes) {
+    status = FALSE;
+  }
+
+# ifdef BYTE_SWAP  
+  perpix = abs(matrix[0].bitpix) / 8;
+  if (perpix > 1) {
+    byte0 = (char *) matrix[0].buffer;
+    byte1 = (char *) matrix[0].buffer + 1;
+    byte2 = (char *) matrix[0].buffer + 2;
+    byte3 = (char *) matrix[0].buffer + 3;
+    byte4 = (char *) matrix[0].buffer + 4;
+    byte5 = (char *) matrix[0].buffer + 5;
+    byte6 = (char *) matrix[0].buffer + 6;
+    byte7 = (char *) matrix[0].buffer + 7;
+    if (perpix == 2) {
+      for (i = 0; i < nbytes; i+=2, byte0 += 2, byte1 += 2) {
+	tmp = *byte0;
+	*byte0 = *byte1;
+	*byte1 = tmp;
+      }
+    }
+    if (perpix == 4) {
+      for (i = 0; i < nbytes; i+=4, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+	tmp = *byte0;
+	*byte0 = *byte3;
+	*byte3 = tmp;
+	tmp = *byte1;
+	*byte1 = *byte2;
+	*byte2 = tmp;
+      }
+    }
+    if (perpix == 8) {
+      for (i = 0; i < nbytes; i+=8, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
+	tmp = *byte0;
+	*byte0 = *byte7;
+	*byte7 = tmp;
+	tmp = *byte1;
+	*byte1 = *byte6;
+	*byte6 = tmp;
+	tmp = *byte1;
+	*byte2 = *byte5;
+	*byte5 = tmp;
+	tmp = *byte1;
+	*byte3 = *byte4;
+	*byte4 = tmp;
+      }
+    }
+  }
+# endif
+
+  return (status);
+
+}
+
Index: /tags/start/Ohana/src/libfits/table/F_create_T.c
===================================================================
--- /tags/start/Ohana/src/libfits/table/F_create_T.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/table/F_create_T.c	(revision 12606)
@@ -0,0 +1,50 @@
+# include "fits.h"
+
+/*********************** fits create table *******************************/
+int fits_create_table (Header *header, FTable *table) {
+
+  int Nbytes;
+  char type[80];
+
+  fits_scan (header, "XTENSION", "%s", 1, type);
+
+  table[0].header = header;
+  
+  Nbytes = fits_matrix_size (header);
+  ALLOCATE (table[0].buffer, char, MAX (Nbytes, 1));
+  if (!strcmp (type, "TABLE")) {
+    memset (table[0].buffer, ' ', Nbytes);
+  } else {
+    memset (table[0].buffer, 0, Nbytes);
+  }
+  table[0].size = Nbytes;
+  return (TRUE);
+
+}
+
+/* init table structure, allocate space for data array (min 1 byte for 0 length) */
+
+/*********************** fits create table *******************************/
+int fits_create_vtable (Header *header, VTable *table, int Nrow) {
+
+  int Nbytes;
+  char type[80];
+
+  fits_scan (header, "XTENSION", "%s", 1, type);
+
+  table[0].header = header;
+  Nx = table[0].header[0].Naxis[0];
+  Ny = table[0].header[0].Naxis[0];
+  table[0].size = fits_matrix_size (header);
+  table[0].pad = table[0].size - Nx*Ny;
+ 
+  table[0].Nrow = Nrow;
+  ALLOCATE (table[0].buffer, char *, MAX (Nrow, 1));
+  ALLOCATE (table[0].row, int, MAX (Nrow, 1));
+  for (i = 0; i < Nrow; i++) {
+    ALLOCATE (table[0].buffer[i], char, Nx);
+  }
+  return (TRUE);
+}
+
+/* init table structure, allocate space for data array (min 1 byte for 0 length) */
Index: /tags/start/Ohana/src/libfits/table/F_create_TH.c
===================================================================
--- /tags/start/Ohana/src/libfits/table/F_create_TH.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/table/F_create_TH.c	(revision 12606)
@@ -0,0 +1,93 @@
+# include "fits.h"
+
+/* a basic table header (extension) is different from a primary header
+   in that it has the word XTENSION and a type for the first line,
+   instead of SIMPLE */
+
+/*********************** fits create Theader *********************************/
+int fits_create_Theader (Header *header, char *type) {
+  
+  int i;
+  char axis[10];
+  
+  header[0].size = 2880;
+  ALLOCATE (header[0].buffer, char, 2880);
+  
+  for (i = 0; i < 2880; i++) 
+  header[0].buffer[i] = ' ';
+  strncpy (header[0].buffer, "END", 3);
+  
+  fits_modify (header, "XTENSION", "%s", 1, type);
+  fits_modify (header, "BITPIX", "%d", 1, header[0].bitpix);
+  fits_modify (header, "NAXIS",  "%d", 1, header[0].Naxes);
+  
+  for (i = 0; i < header[0].Naxes; i++) {
+    sprintf (axis, "NAXIS%d", i + 1);
+    fits_modify (header,  axis, "%d", 1, header[0].Naxis[i], 1);
+  }
+  
+  /* PCOUNT & GCOUNT are not implemented, but they are required to be here */
+  fits_modify (header, "PCOUNT", "%d", 1, 0);
+  fits_modify (header, "GCOUNT", "%d", 1, 1);
+  if (!strcmp (type, "IMAGE")) {
+    fits_modify (header, "BSCALE", "%lf", 1, header[0].bscale);
+    fits_modify (header, "BZERO",  "%lf", 1, header[0].bzero);
+  }
+
+  return (TRUE);
+}	
+
+/*********************** fits create table header *********************************/
+int fits_create_table_header (Header *header, char *type, char *extname) {
+  
+  int i, valid;
+  char axis[10];
+
+  /* check valid table types */
+  valid = FALSE;
+  valid |= !strcmp (type, "TABLE");
+  valid |= !strcmp (type, "BINTABLE");
+  if (!valid) return (FALSE);
+
+  /* create empty header buffer */
+  header[0].size = 2880;
+  ALLOCATE (header[0].buffer, char, 2880);
+  
+  for (i = 0; i < 2880; i++) 
+  header[0].buffer[i] = ' ';
+  strncpy (header[0].buffer, "END", 3);
+
+  /* a table has BITPIX = 8, NAXIS = 2 */
+  header[0].simple = FALSE;
+  header[0].unsign = FALSE;
+  header[0].extend = FALSE;
+  header[0].bitpix = 8;
+  header[0].bscale = 1;
+  header[0].bzero  = 0;
+  header[0].Naxes  = 2;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    header[0].Naxis[i] = 0;
+  
+  /* required keywords */
+  fits_modify (header, "XTENSION", "%s", 1, type);
+  fits_modify (header, "BITPIX", "%d", 1, header[0].bitpix);
+  fits_modify (header, "NAXIS",  "%d", 1, header[0].Naxes);
+  
+  for (i = 0; i < header[0].Naxes; i++) {
+    sprintf (axis, "NAXIS%d", i + 1);
+    fits_modify (header,  axis, "%d", 1, header[0].Naxis[i], 1);
+  }
+  
+  /* PCOUNT & GCOUNT are not implemented, but they are required to be here */
+  fits_modify (header, "PCOUNT", "%d", 1, 0);
+  fits_modify (header, "GCOUNT", "%d", 1, 1);
+  if (!strcmp (type, "IMAGE")) {
+    fits_modify (header, "BSCALE", "%lf", 1, header[0].bscale);
+    fits_modify (header, "BZERO",  "%lf", 1, header[0].bzero);
+  }
+
+  fits_modify (header, "TFIELDS", "%d", 1, 0);
+  fits_modify (header, "EXTNAME", "%s", 1, extname);
+  
+  return (TRUE);
+}	
Index: /tags/start/Ohana/src/libfits/table/F_define_column.c
===================================================================
--- /tags/start/Ohana/src/libfits/table/F_define_column.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/table/F_define_column.c	(revision 12606)
@@ -0,0 +1,69 @@
+# include "fits.h"
+
+/***********************/
+int fits_define_bintable_column (Header *header, char *format, char *label, char *comment, char *unit, double bscale, double bzero) {
+
+  int Nfields, Nbytes, Nval, Naxis1;
+  char type[16], field[16];
+  
+  if (!fits_bintable_format (format, type, &Nval, &Nbytes)) return (FALSE);
+  
+  Nfields = 0;
+  fits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  fits_scan (header, "NAXIS1",  "%d", 1, &Naxis1);
+  Nfields ++;
+  Naxis1 += Nbytes*Nval;
+
+  sprintf (field, "TTYPE%d", Nfields);
+  fits_modify (header, field, "%s", 1, label);
+  fits_modify (header, field, "%C", 1, comment);
+  sprintf (field, "TUNIT%d", Nfields);
+  fits_modify (header, field, "%s", 1, unit);
+  sprintf (field, "TFORM%d", Nfields);
+  fits_modify (header, field, "%s", 1, format);
+  sprintf (field, "TSCAL%d", Nfields);
+  fits_modify (header, field, "%lf", 1, bscale);
+  sprintf (field, "TZERO%d", Nfields);
+  fits_modify (header, field, "%lf", 1, bzero);
+
+  /* update TFIELDS & NAXIS1 */
+  fits_modify (header, "TFIELDS", "%d", 1, Nfields);
+  fits_modify (header, "NAXIS1",  "%d", 1, Naxis1);
+  header[0].Naxis[0] = Naxis1;
+
+  return (TRUE);
+}
+
+/***********************/
+int fits_define_table_column (Header *header, char *format, char *label, char *comment, char *unit) {
+
+  int Nstart, Nfields, Nbytes, Nval, Naxis1;
+  char type[16], field[16], cformat[16];
+
+  strcpy (cformat, format);
+  if (!fits_table_format (cformat, type, &Nval, &Nbytes)) return (FALSE);
+
+  Nfields = 0;
+  fits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  fits_scan (header, "NAXIS1",  "%d", 1, &Naxis1);
+  Nstart = Naxis1 + 1;
+  Nfields ++;
+  Naxis1 += Nbytes*Nval;
+
+  sprintf (field, "TTYPE%d", Nfields);
+  fits_modify (header, field, "%s", 1, label);
+  fits_modify (header, field, "%C", 1, comment);
+  sprintf (field, "TUNIT%d", Nfields);
+  fits_modify (header, field, "%s", 1, unit);
+  sprintf (field, "TFORM%d", Nfields);
+  fits_modify (header, field, "%s", 1, format);
+
+  sprintf (field, "TBCOL%d", Nfields);
+  fits_modify (header, field, "%d", 1, Nstart);
+
+  fits_modify (header, "TFIELDS", "%d", 1, Nfields);
+  fits_modify (header, "NAXIS1",  "%d", 1, Naxis1);
+  header[0].Naxis[0] = Naxis1;
+
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/libfits/table/F_free_T.c
===================================================================
--- /tags/start/Ohana/src/libfits/table/F_free_T.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/table/F_free_T.c	(revision 12606)
@@ -0,0 +1,27 @@
+# include "fits.h"
+
+int fits_free_table (FTable *table) {
+  
+  if (table[0].buffer == (char *) NULL) return (TRUE);
+  free (table[0].buffer);
+  table[0].buffer = (char *) NULL;
+  return (TRUE);
+}
+
+int fits_free_vtable (VTable *table) {
+  
+  int i;
+
+  if (table[0].buffer == (char **) NULL) return (TRUE);
+
+  for (i = 0; i < table[0].Nrow; i++) {
+    free (table[0].buffer[i]);
+  }
+  free (table[0].buffer);
+  free (table[0].row);
+
+  table[0].buffer = NULL;
+  table[0].row    = NULL;
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/libfits/table/F_get_T_column.c
===================================================================
--- /tags/start/Ohana/src/libfits/table/F_get_T_column.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/table/F_get_T_column.c	(revision 12606)
@@ -0,0 +1,60 @@
+# include "fits.h"
+
+/*********************** fits get table column *****************************/
+void fits_get_table_column (table, X, mode, values) 
+Table *table; 
+int X; 
+char *mode, **values;
+{
+  
+  char Tform[100], field[100], tmp[100];
+  int  start, Nchar, i, N;
+  
+  int    *Ivalues;
+  long   *Lvalues;
+  short  *Svalues;
+  float  *Fvalues;
+  double *Dvalues;
+  char  **Cvalues;
+  
+  /* no error checking, all sorts of problems! */
+  /* should I count fields from 0 or from 1? */
+  
+  sprintf (field, "TBCOL%d\0", X);
+  fits_scan (&table[0].header, field, "%d", &start, 1);
+  start --;
+  sprintf (field, "TFORM%d\0", X);
+  fits_scan (&table[0].header, field, "%s", Tform, 1);
+  Nchar = atof (&Tform[1]);
+  
+  if (!strcmp (mode, "%d")) {
+    ALLOCATE (Ivalues, int, table[0].Naxis[1]);
+    for (i = 0; i < table[0].Naxis[1]; i++) {
+      strncpy (tmp, &table[0].buffer[i*table[0].Naxis[0] + start], Nchar);
+      tmp[Nchar] = 0;
+      Ivalues[i] = atof (tmp);
+    }
+    values[0] = (char *) Ivalues;
+  }
+  if (!strcmp (mode, "%lf")) {
+    ALLOCATE (Dvalues, double, table[0].Naxis[1]);
+    for (i = 0; i < table[0].Naxis[1]; i++) {
+      strncpy (tmp, &table[0].buffer[i*table[0].Naxis[0] + start], Nchar);
+      tmp[Nchar] = 0;
+      Dvalues[i] = atof (tmp);
+    }
+    values[0] = (char *) Dvalues;
+  }
+  if ((mode[0] == '%') && (mode[strlen(mode) - 1] == 'c')) {
+    mode[strlen(mode) - 1] = 0;
+    N = atof(&mode[1]);
+    ALLOCATE (Cvalues, char *, table[0].Naxis[1]);
+    for (i = 0; i < table[0].Naxis[1]; i++) {
+      ALLOCATE (Cvalues[i], char, N + 1);
+      strncpy (Cvalues[i], &table[0].buffer[i*table[0].Naxis[0] + start], N);
+      Cvalues[i][N] = 0;
+    }
+    values[0] = (char *) Cvalues;
+  }
+
+}
Index: /tags/start/Ohana/src/libfits/table/F_get_T_value.c
===================================================================
--- /tags/start/Ohana/src/libfits/table/F_get_T_value.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/table/F_get_T_value.c	(revision 12606)
@@ -0,0 +1,40 @@
+# include "fits.h"
+
+/*********************** fits get table value ********************************/
+  
+void fits_get_table_value (table, X, Y, mode, value)
+Table *table; 
+int X, Y; 
+char *mode, *value;
+{
+  
+  char Tform[100], field[100];
+  int  start, Nchar, byte;
+  char tmp[1000];
+  
+  /* no error checking, all sorts of problems! */
+  
+  sprintf (field, "TBCOL%d\0", X);
+  fits_scan (&table[0].header, field, "%d", &start, 1);
+  start --;
+  
+  sprintf (field, "TFORM%d\0", X);
+  fits_scan (&table[0].header, field, "%s", Tform, 1);
+  Nchar = atof (&Tform[1]);
+  
+  byte = Y*table[0].Naxis[0] + start;
+  strncpy (tmp, &table[0].buffer[byte], Nchar);
+  tmp[Nchar] = 0;
+
+  if (!strcmp (mode, "%d"))  *(int      *) value = (int)      atof (tmp);
+  if (!strcmp (mode, "%u"))  *(unsigned *) value = (unsigned) atof (tmp);
+  if (!strcmp (mode, "%ld")) *(long     *) value = (long)     atof (tmp);
+  if (!strcmp (mode, "%hd")) *(short    *) value = (short)    atof (tmp);
+  if (!strcmp (mode, "%f"))  *(float    *) value = (float)    atof (tmp);
+  if (!strcmp (mode, "%lf")) *(double   *) value = (double)   atof (tmp);
+
+  if (!strcmp (mode, "%s")) 
+    strcpy (value, tmp);
+
+}
+
Index: /tags/start/Ohana/src/libfits/table/F_get_column.c
===================================================================
--- /tags/start/Ohana/src/libfits/table/F_get_column.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/table/F_get_column.c	(revision 12606)
@@ -0,0 +1,272 @@
+# include "fits.h"
+# define SWAP_BYTE \
+  tmp = Pin[0]; Pin[0] = Pin[1]; Pin[1] = tmp;
+# define SWAP_WORD \
+  tmp = Pin[0]; Pin[0] = Pin[3]; Pin[3] = tmp; \
+  tmp = Pin[1]; Pin[1] = Pin[2]; Pin[2] = tmp;
+# define SWAP_DBLE \
+  tmp = Pin[0]; Pin[0] = Pin[7]; Pin[7] = tmp; \
+  tmp = Pin[1]; Pin[1] = Pin[6]; Pin[6] = tmp; \
+  tmp = Pin[2]; Pin[2] = Pin[5]; Pin[5] = tmp; \
+  tmp = Pin[3]; Pin[3] = Pin[4]; Pin[4] = tmp;
+
+/***********************/
+int fits_get_bintable_column_type (Header *header, char *label, char *type, int *Nval) {
+
+  int i, N, Nfields, Nbytes;
+  char tlabel[80], field[80], format[80];
+
+  if (label == (char *) NULL) return (FALSE);
+  if (label[0] == 0) return (FALSE);
+
+  /* find label in header */
+  tlabel[0] = 0;
+  fits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  for (i = 1; strcmp (label, tlabel) && (i < Nfields + 1); i++) {
+    sprintf (field, "TTYPE%d", i);
+    fits_scan (header, field, "%s", 1, tlabel);
+  }
+  if (strcmp (label, tlabel)) return (FALSE);
+  N = i - 1;
+
+  sprintf (field, "TFORM%d", N);
+  fits_scan (header, field, "%s", 1, format);
+
+  if (!fits_bintable_format (format, type, Nval, &Nbytes)) return (FALSE);
+  return (TRUE);
+}
+
+/***********************/
+int fits_get_bintable_column (Header *header, FTable *table, char *label, void **data) {
+
+  int i, N, Nfields, Nval, Nbytes, Nx, Ny, Nstart, Nv, Nb;
+  char tlabel[80], field[80], format[80], type[16], tmpline[16];
+  char *Pin, *Pout, *array, tmp;
+  double Bscale, Bzero;
+  int I;
+
+  if (label == (char *) NULL) return (FALSE);
+  if (label[0] == 0) return (FALSE);
+
+  /* find label in header */
+  tlabel[0] = 0;
+  fits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  for (i = 1; strcmp (label, tlabel) && (i < Nfields + 1); i++) {
+    sprintf (field, "TTYPE%d", i);
+    fits_scan (header, field, "%s", 1, tlabel);
+  }
+  if (strcmp (label, tlabel)) return (FALSE);
+  N = i - 1;
+
+  Bscale = 1; 
+  Bzero  = 0;
+
+  /* interpret format */
+  sprintf (field, "TSCAL%d", Nfields);
+  fits_scan (header, field, "%lf", 1, &Bscale);
+  sprintf (field, "TZERO%d", Nfields);
+  fits_scan (header, field, "%lf", 1, &Bzero);
+  sprintf (field, "TFORM%d", N);
+  fits_scan (header, field, "%s", 1, format);
+
+  if (!fits_bintable_format (format, type, &Nval, &Nbytes)) return (FALSE);
+  
+  /* check existing table dimensions */
+  fits_scan (header, "NAXIS1",  "%d", 1, &Nx);
+  fits_scan (header, "NAXIS2",  "%d", 1, &Ny);
+
+  /* scan columns to find insert point */
+  Nstart = 0;
+  for (i = 1; i < N; i++) {
+    sprintf (field, "TFORM%d", i);
+    fits_scan (header, field, "%s", 1, format);
+    fits_bintable_format (format, tmpline, &Nv, &Nb);
+    Nstart += Nv*Nb;
+  }
+
+  /* extract bytes from table into temporary array */
+  ALLOCATE (array, char, Nbytes*Nval*Ny);
+  Pin  = table[0].buffer + Nstart;
+  Pout = array;
+  for (i = 0; i < Ny; i++, Pin += Nx, Pout += Nval*Nbytes) {
+    memcpy (Pout, Pin, Nval*Nbytes);
+  }
+
+  /* convert data in-situ with correct type, byte swap and Bzero/Bscale */
+  Pin  = array;
+  Pout = array;
+  if (!strcmp (type, "char")) {
+    for (i = 0; i < Nval*Ny; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(char *)Pout = *(char *)Pin*Bscale + Bzero;
+    }
+  }
+  if (!strcmp (type, "short")) {
+    for (i = 0; i < Nval*Ny; i++, Pin+=Nbytes, Pout+=Nbytes) {
+# ifdef BYTE_SWAP
+      I = i*Nbytes;
+      SWAP_BYTE;
+# endif
+      *(short *)Pout = *(short *)Pin*Bscale + Bzero;
+    }  
+  }
+  if (!strcmp (type, "int")) {
+    for (i = 0; i < Nval*Ny; i++, Pin+=Nbytes, Pout+=Nbytes) {
+# ifdef BYTE_SWAP
+      I = i*Nbytes;
+      SWAP_WORD;
+# endif
+      *(int *)Pout = *(int *)Pin*Bscale + Bzero;
+    }
+  }
+  if (!strcmp (type, "float")) {
+    for (i = 0; i < Nval*Ny; i++, Pin+=Nbytes, Pout+=Nbytes) {
+# ifdef BYTE_SWAP
+      I = i*Nbytes;
+      SWAP_WORD;
+# endif
+      *(float *)Pout = *(float *)Pin*Bscale + Bzero;
+    }
+  }
+  if (!strcmp (type, "double")) {
+    for (i = 0; i < Nval*Ny; i++, Pin+=Nbytes, Pout+=Nbytes) {
+# ifdef BYTE_SWAP
+      I = i*Nbytes;
+      SWAP_DBLE;
+# endif
+      *(double *)Pout = *(double *)Pin*Bscale + Bzero;
+    }
+  }
+
+  *data = array;
+  return (TRUE);
+}
+
+/* 
+   valid BINTABLE column formats:
+   L - logical
+   X - bit
+   I - 16 bit int
+   J - 32 bit int
+   A - char
+   E - float 
+   D - double
+   B - unsigned bytes
+   C - complex float
+   M - complex double
+   P - var lenght array descrpt (64 bit)
+   
+   all can be preceeded by integer N which specified number
+   of entries in array
+   
+*/
+
+/***********************/
+int fits_get_table_column_type (Header *header, char *label, char *type) {
+
+  int i, N, Nfields, Nval, Nbytes;
+  char tlabel[80], field[80], format[80];
+
+  if (label == (char *) NULL) return (FALSE);
+  if (label[0] == 0) return (FALSE);
+
+  /* find label in header */
+  tlabel[0] = 0;
+  fits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  for (i = 1; strcmp (label, tlabel) && (i < Nfields + 1); i++) {
+    sprintf (field, "TTYPE%d", i);
+    fits_scan (header, field, "%s", 1, tlabel);
+  }
+  if (strcmp (label, tlabel)) return (FALSE);
+  N = i - 1;
+
+  /* interpret format */
+  sprintf (field, "TFORM%d", N);
+  fits_scan (header, field, "%s", 1, format);
+
+  if (!fits_table_format (format, type, &Nval, &Nbytes)) return (FALSE);
+  return (TRUE);
+}
+
+/***********************/
+int fits_get_table_column (Header *header, FTable *table, char *label, void **data) {
+
+  int i, N, Nfields, Nval, Nbytes, Nx, Ny, Nstart, Nv, Nb;
+  char tlabel[80], field[80], format[80], cformat[80], type[16], tmp[16];
+  char *array, *Pin, *Pout, *line;
+
+  if (label == (char *) NULL) return (FALSE);
+  if (label[0] == 0) return (FALSE);
+
+  /* find label in header */
+  tlabel[0] = 0;
+  fits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  for (i = 1; strcmp (label, tlabel) && (i < Nfields + 1); i++) {
+    sprintf (field, "TTYPE%d", i);
+    fits_scan (header, field, "%s", 1, tlabel);
+  }
+  if (strcmp (label, tlabel)) return (FALSE);
+  N = i - 1;
+
+  /* interpret format */
+  sprintf (field, "TFORM%d", N);
+  fits_scan (header, field, "%s", 1, format);
+
+  if (!fits_table_format (format, type, &Nval, &Nbytes)) return (FALSE);
+  strcpy (cformat, format);
+  
+  /* check existing table dimensions */
+  fits_scan (header, "NAXIS1",  "%d", 1, &Nx);
+  fits_scan (header, "NAXIS2",  "%d", 1, &Ny);
+
+  /* scan columns to find insert point */
+  Nstart = 0;
+  for (i = 1; i < N; i++) {
+    sprintf (field, "TFORM%d", i);
+    fits_scan (header, field, "%s", 1, format);
+    fits_table_format (format, tmp, &Nv, &Nb);
+    Nstart += Nv*Nb;
+  }
+
+  /* allocate temporary line, init pointers */
+  ALLOCATE (line, char, Nval+1);
+  bzero (line, Nval+1);
+  Pin  = table[0].buffer + Nstart;
+
+  /* allocate output array, copy/scan line as needed */
+  if (!strcmp (type, "char")) {
+    ALLOCATE (array, char, Ny*Nval);
+    Pout = array;
+    for (i = 0; i < Ny; i++, Pin+=Nx, Pout+=Nval*Nbytes) {
+      memcpy (Pout, Pin, Nval*Nbytes);
+    }
+  }
+  if (!strcmp (type, "int")) {
+    ALLOCATE (array, char, Ny*4);
+    Pout = array;
+    for (i = 0; i < Ny; i++, Pin+=Nx, Pout+=4) {
+      memcpy (line, Pin, Nval*Nbytes);
+      sscanf (line, "%d", (int *)Pout);
+    }
+  }
+  if (!strcmp (type, "float")) {
+    ALLOCATE (array, char, Ny*4);
+    Pout = array;
+    for (i = 0; i < Ny; i++, Pin+=Nx, Pout+=4) {
+      memcpy (line, Pin, Nval*Nbytes);
+      sscanf (line, "%f", (float *)Pout);
+    }
+  }
+  *data = array;
+  free (line);
+
+  return (TRUE);
+}
+
+/*
+  valid TABLE column formats:
+  FN.N  - floating point
+  INN   - integer
+  ANN   - NN char string
+  
+*/
+
Index: /tags/start/Ohana/src/libfits/table/F_read_T.c
===================================================================
--- /tags/start/Ohana/src/libfits/table/F_read_T.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/table/F_read_T.c	(revision 12606)
@@ -0,0 +1,234 @@
+# include "fits.h"
+
+/*********************** fits read table ***********************************/
+int fits_read_ftable (char *filename, FTable *table, char *extname) {
+
+  int status;
+  FILE *f;
+
+  f = fopen (filename, "r");
+  if (f == NULL) return (FALSE);
+
+  status = fits_fread_ftable (f, table, extname);
+  fclose (f);
+  return (status);
+}	
+
+/*********************** fits read table ***********************************/
+int fits_fread_ftable (FILE *f, FTable *table, char *extname) {
+
+  int j, found, Nbytes, Nread;
+  Header *header;
+  char tname[80];
+
+  header = table[0].header;
+  fseek (f, 0, SEEK_SET);
+
+  found = FALSE;
+  for (j = -1; !found; j++) {
+    /* load data for this header */
+    if (!fits_load_header (f, header)) return (FALSE);
+
+    /* check if this is the correct extension or not */
+    bzero (tname, 80);
+    fits_scan (header, "EXTNAME", "%s", 1, tname);
+    if (!strcmp (tname, extname)) {
+      if (fits_fread_ftable_data (f, table)) return (TRUE);
+      fits_free_header (header);
+      return (FALSE);
+    }
+
+    /* skip to next header */
+    Nbytes = fits_matrix_size (header);
+    fseek (f, Nbytes, SEEK_CUR);
+    fits_free_header (header);
+  }
+  return (TRUE);
+}	
+
+/*********************** fits read ftable data ***********************************/
+int fits_fread_ftable_data (FILE *f, FTable *table) {
+
+  int Nbytes, Nread;
+  char tname[80];
+
+  /* find buffer size */
+  Nbytes = fits_matrix_size (table[0].header);
+  ALLOCATE (table[0].buffer, char, Nbytes);
+
+  Nread = fread (table[0].buffer, sizeof (char), Nbytes, f);
+  if (Nread != Nbytes) {
+    fits_free_table  (table);
+    return (FALSE);
+  }
+  table[0].size = Nbytes;
+  return (TRUE);
+}	
+
+/*********************** fits read ftable data ***********************************/
+int fits_fread_vtable_range (FILE *f, VTable *table, int start, int Nrows) {
+
+  int Nbytes, Nread, Nskip, Nx, Ny;
+  char tname[80], *buffer;
+
+  /* find buffer size */
+  Nx = table[0].header[0].Naxis[0];
+  Ny = table[0].header[0].Naxis[1];
+  table[0].size = fits_matrix_size (table[0].header);
+  table[0].pad = table[0].size - Nx*Ny;
+
+  if (start < 0) return (FALSE);
+  if (start + Nrows >= Ny) return (FALSE);
+  
+  Nskip = start * Nx;
+  Nbytes = Nrows * Nx;
+  ALLOCATE (buffer, char, MAX (Nbytes, 1));
+
+  Fseek (f, Nskip, SEEK_CUR);
+  Nread = fread (buffer, sizeof (char), Nbytes, f);
+  if (Nread != Nbytes) {
+    free (buffer);
+    return (FALSE);
+  }
+
+  ALLOCATE (table[0].row, int, MAX (Nrows, 1));
+  ALLOCATE (table[0].buffer, char *, MAX (Nrows, 1));
+  for (i = 0; i < Nrows; i++) {
+    ALLOCATE (table[0].buffer[i], char, MAX (Nx, 1));
+    memcpy (table[0].buffer[i], &buffer[i*Nx], Nx);
+    table[0].row[i] = start + i;
+  }
+  free (buffer);
+
+  return (TRUE);
+}	
+
+/*********************** fits read virtual table ***********************************/
+int fits_fread_vtable (FILE *f, VTable *table, char *extname, int Nrow, int *row) {
+
+  int i, j, Nbytes, Nread;
+  int start, Nx, Ny, offset;
+  Header *header;
+  char tname[80];
+
+  header = table[0].header;
+  fseek (f, 0, SEEK_SET);
+
+  for (j = -1; TRUE; j++) {
+    /* load data for this header */
+    if (!fits_load_header (f, header)) return (FALSE);
+
+    /* find buffer size */
+    Nbytes = fits_matrix_size (header);
+
+    /* check if this is the correct extension or not */
+    bzero (tname, 80);
+    fits_scan (header, "EXTNAME", "%s", 1, tname);
+    if (strcmp (tname, extname)) {
+      /* skip to next header */
+      fseek (f, Nbytes, SEEK_CUR);
+      fits_free_header (header);
+      continue;
+    }
+
+    /* file pointer is at beginning of desired table data */
+    start = ftell (f);
+    fits_scan (header, "NAXIS1", "%d", 1, &Nx);
+    fits_scan (header, "NAXIS2", "%d", 1, &Ny);
+    for (i = 0; i < Nrow; i++) {
+      if (row[i] > Ny) { return (FALSE); }
+    }
+
+    ALLOCATE (table[0].buffer, char *, MAX (1, Nrow));
+    for (i = 0; i < Nrow; i++) {
+      ALLOCATE (table[0].buffer[i], char, MAX (1, Nx));
+      offset = start + Nx*row[i];
+      fseek (f, offset, SEEK_SET);
+      Nread = fread (table[0].buffer[i], sizeof (char), Nx, f);
+      if (Nread != Nx) { return (FALSE); }
+    }
+
+    table[0].Nrow  = Nrow;
+    ALLOCATE (table[0].row, int, MAX (1, Nrow));    
+    for (i = 0; i < Nrow; i++) table[0].row[i] = row[i];
+    table[0].size   = fits_matrix_size (table[0].header);
+    table[0].pad    = table[0].size - Nx*Ny;
+    return (TRUE);
+  }
+}	
+
+# if (0)
+/*********************** fits read table ***********************************/
+/* a poor function: read only the first table, regardless of name */
+/* keep until we are sure ohana code does not use it  */
+int fits_read_table (char *filename, FTable *table) {
+
+  FILE *f;
+  Header header;
+  int status, i, nbytes, Nbytes, matrix_size;
+
+  if (!fits_read_header (filename, &header)) {
+    fprintf (stderr, "error reading header of FITS file %s\n", filename);
+    return (FALSE);
+  }
+
+  if (!fits_read_Theader (filename, &table[0].header)) {
+    fprintf (stderr, "error reading Theader of FITS file %s\n", filename);
+    return (FALSE);
+  }
+
+  if ((f = fopen (filename, "r")) == NULL) {
+    fits_free_header (&header);
+    fits_free_header (&table[0].header);
+    return (FALSE);
+  }
+
+  matrix_size = fits_matrix_size (&header);
+
+  Nbytes = header.size + matrix_size + table[0].header.size;
+  fseek (f, Nbytes, 0);
+  fits_free_header (&header);
+ 
+  fits_scan (&table[0].header, "TFIELDS", "%d", 1, &table[0].Nfields);
+
+  /* place the field sizes in the structure? */
+  table[0].bitpix = table[0].header.bitpix;
+  table[0].Naxes  = table[0].header.Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    table[0].Naxis[i] = table[0].header.Naxis[i];
+
+  Nbytes = fits_matrix_size (&table[0].header);
+  ALLOCATE (table[0].buffer, char, Nbytes);
+  nbytes = fread (table[0].buffer, sizeof(char), Nbytes, f);
+  if (nbytes != Nbytes) {
+    fprintf (stderr, "error reading in table data from FITS file %s\n", filename);
+    fclose (f);
+    return (FALSE);
+  }
+  table[0].size = Nbytes;
+  fclose (f);
+  return (TRUE);
+}
+# endif
+
+
+int fits_fread_header_extname (FILE *f, Header *header, char *extname) {
+
+  char current[80];
+
+  fseek (f, 0, SEEK_SET);
+  fits_fread_header (f, header);
+
+  if (!strcasecmp (extname, "PHU")) return (TRUE);
+
+  Nbytes = fits_matrix_size (header);
+  fseek (f, Nbytes, SEEK_CUR);
+
+  while (fits_fread_header (f, &header)) {
+    fits_scan (&header, "EXTNAME", "%s", 1, current);
+    if (!strcmp (current, extname)) return (TRUE);
+    Nbytes = fits_matrix_size (&header);
+    fseek (f, Nbytes, SEEK_CUR);
+  }
+  return (FALSE);
+}
Index: /tags/start/Ohana/src/libfits/table/F_read_TH.c
===================================================================
--- /tags/start/Ohana/src/libfits/table/F_read_TH.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/table/F_read_TH.c	(revision 12606)
@@ -0,0 +1,86 @@
+# include "fits.h"
+
+/*********************** fits read Theader ***********************************/
+int fits_read_Theader (char *filename, Header *Theader) {
+  
+  FILE *f;
+  Header header;
+  int status, Nbytes;
+  
+  status = fits_read_header (filename, &header);
+  if (!status) {
+    fprintf (stderr, "error reading header of FITS file %s\n", filename);
+    return (FALSE);
+  }
+
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    Theader[0].buffer = NULL;
+    fits_free_header (&header);
+    return (FALSE);
+  }
+
+  Nbytes = fits_matrix_size (&header);
+  fseek (f, Nbytes, SEEK_SET);
+  fits_free_header (&header);
+
+  status = fits_load_Theader (f, Theader);
+  fclose (f);
+  return (status);
+}	
+
+/* load table from STREAM positioned at beginning of table header */
+/*********************** fits load Theader ***********************************/
+int fits_load_Theader (FILE *f, Header *Theader) {
+  
+  char *p;
+  int i, done, status, Nbytes;
+  
+  Theader[0].size = 0;
+  done = FALSE;
+  ALLOCATE (Theader[0].buffer, char, 1);
+
+  for (i = 0; !done; i++) {
+    REALLOCATE (Theader[0].buffer, char, (i + 1)*FT_RECORD_SIZE);
+    Nbytes = fread (&Theader[0].buffer[i*FT_RECORD_SIZE], 
+		    sizeof(char), FT_RECORD_SIZE, f);
+    Theader[0].size += Nbytes;
+    if (Nbytes != FT_RECORD_SIZE) 
+      done = TRUE;
+    p = fits_header_field (Theader, "END", 1);
+    if (p != NULL)
+      done = TRUE;
+  }
+
+  Theader[0].bscale = 0;
+  Theader[0].bzero  = 0;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    Theader[0].Naxis[i] = 0;
+
+  status = TRUE;
+  status &= fits_scan (Theader,  "BITPIX", "%d", 1, &Theader[0].bitpix);
+  status &= fits_scan (Theader,  "NAXIS",  "%d", 1, &Theader[0].Naxes);
+  if (!status) return (FALSE);
+				                           
+  fits_scan (Theader,  "NAXIS1", "%d", 1, &Theader[0].Naxis[0]);
+  fits_scan (Theader,  "NAXIS2", "%d", 1, &Theader[0].Naxis[1]);
+  fits_scan (Theader,  "NAXIS3", "%d", 1, &Theader[0].Naxis[2]);
+  fits_scan (Theader,  "NAXIS4", "%d", 1, &Theader[0].Naxis[3]);
+  fits_scan (Theader,  "NAXIS5", "%d", 1, &Theader[0].Naxis[4]);
+  fits_scan (Theader,  "NAXIS6", "%d", 1, &Theader[0].Naxis[5]);
+  fits_scan (Theader,  "NAXIS7", "%d", 1, &Theader[0].Naxis[6]);
+  fits_scan (Theader,  "NAXIS8", "%d", 1, &Theader[0].Naxis[7]);
+  fits_scan (Theader,  "NAXIS9", "%d", 1, &Theader[0].Naxis[8]);
+  fits_scan (Theader, "NAXIS10", "%d", 1, &Theader[0].Naxis[9]);
+
+  return (TRUE);
+}	
+
+/*********************** fits fread Theader ***********************************/
+int fits_fread_Theader (FILE *f, Header *Theader) {
+  
+  int status;
+  
+  status = fits_load_Theader (f, Theader);
+  return (status);
+}
Index: /tags/start/Ohana/src/libfits/table/F_set_column.c
===================================================================
--- /tags/start/Ohana/src/libfits/table/F_set_column.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/table/F_set_column.c	(revision 12606)
@@ -0,0 +1,252 @@
+# include "fits.h"
+# define SWAP_BYTE \
+  tmp = Pout[0]; Pout[0] = Pout[1]; Pout[1] = tmp;
+# define SWAP_WORD \
+  tmp = Pout[0]; Pout[0] = Pout[3]; Pout[3] = tmp; \
+  tmp = Pout[1]; Pout[1] = Pout[2]; Pout[2] = tmp;
+# define SWAP_DBLE \
+  tmp = Pout[0]; Pout[0] = Pout[7]; Pout[7] = tmp; \
+  tmp = Pout[1]; Pout[1] = Pout[6]; Pout[6] = tmp; \
+  tmp = Pout[2]; Pout[2] = Pout[5]; Pout[5] = tmp; \
+  tmp = Pout[3]; Pout[3] = Pout[4]; Pout[4] = tmp;
+
+/***********************/
+int fits_set_bintable_column (Header *header, FTable *table, char *label, void *data, int Nrow) {
+
+  int i, N, Nfields, Nval, Nbytes, Nx, Ny, nbytes, Nstart, Nv, Nb;
+  char tlabel[80], field[80], format[80], type[16], tmpline[16];
+  char *Pin, *Pout, *array, tmp;
+  double Bscale, Bzero;
+  int I;
+
+  if (label == (char *) NULL) return (FALSE);
+  if (label[0] == 0) return (FALSE);
+
+  /* find label in header */
+  tlabel[0] = 0;
+  fits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  for (i = 1; strcmp (label, tlabel) && (i < Nfields + 1); i++) {
+    sprintf (field, "TTYPE%d", i);
+    fits_scan (header, field, "%s", 1, tlabel);
+  }
+  if (strcmp (label, tlabel)) return (FALSE);
+  N = i - 1;
+
+  /* interpret format */
+  sprintf (field, "TSCAL%d", N);
+  fits_scan (header, field, "%lf", 1, &Bscale);
+  sprintf (field, "TZERO%d", N);
+  fits_scan (header, field, "%lf", 1, &Bzero);
+  sprintf (field, "TFORM%d", N);
+  fits_scan (header, field, "%s", 1, format);
+
+  if (!fits_bintable_format (format, type, &Nval, &Nbytes)) return (FALSE);
+  
+  /* check existing table dimensions */
+  fits_scan (header, "NAXIS1",  "%d", 1, &Nx);
+  fits_scan (header, "NAXIS2",  "%d", 1, &Ny);
+  if (Ny == 0) { 
+    Ny = Nrow;
+    header[0].Naxis[1] = Ny;
+    fits_modify (header, "NAXIS2",  "%d", 1, Ny);
+
+    nbytes = fits_matrix_size (header);
+    REALLOCATE (table[0].buffer, char, MAX (nbytes, 1));
+    bzero (table[0].buffer, nbytes);
+    table[0].size = nbytes;
+  }
+  if (Ny != Nrow) return (FALSE);
+
+  /* scan columns to find insert point */
+  Nstart = 0;
+  for (i = 1; i < N; i++) {
+    sprintf (field, "TFORM%d", i);
+    fits_scan (header, field, "%s", 1, format);
+    fits_bintable_format (format, tmpline, &Nv, &Nb);
+    Nstart += Nv*Nb;
+  }
+
+  /* make duplicate of data with correct type
+     byte swap and Bzero/Bscale */
+  ALLOCATE (array, char, Nbytes*Nval*Nrow);
+  Pin = data;
+  Pout = array;
+  if (!strcmp (type, "char")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(char *)Pout = (*(char *)Pin - Bzero) / Bscale;
+    }
+  }
+  if (!strcmp (type, "short")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(short *)Pout = (*(short *)Pin - Bzero) / Bscale;
+# ifdef BYTE_SWAP
+      I = i*Nbytes;
+      SWAP_BYTE;
+# endif
+    }  
+  }
+  if (!strcmp (type, "int")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(int *)Pout = (*(int *)Pin - Bzero) / Bscale;
+# ifdef BYTE_SWAP
+      I = i*Nbytes;
+      SWAP_WORD;
+# endif
+    }
+  }
+  if (!strcmp (type, "float")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(float *)Pout = (*(float *)Pin - Bzero) / Bscale;
+# ifdef BYTE_SWAP
+      I = i*Nbytes;
+      SWAP_WORD;
+# endif
+    }
+  }
+  if (!strcmp (type, "double")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(double *)Pout = (*(double *)Pin - Bzero) / Bscale;
+# ifdef BYTE_SWAP
+      I = i*Nbytes;
+      SWAP_DBLE;
+# endif
+    }
+  }
+
+  /* check array space */
+  if (Nx*Ny < Nx*(Nrow - 1) + Nstart + Nval*Nbytes) {
+    fprintf (stderr, "mismatch in array sizes\n");
+    return (FALSE);
+  }
+
+  /* insert bytes from array into appropriate section of buffer */
+  Pout = table[0].buffer + Nstart;
+  Pin  = array;
+  for (i = 0; i < Nrow; i++, Pout += Nx, Pin += Nval*Nbytes) {
+    memcpy (Pout, Pin, Nval*Nbytes);
+  }
+
+  free (array);
+  return (TRUE);
+}
+
+/* 
+   valid BINTABLE column formats:
+   L - logical
+   X - bit
+   I - 16 bit int
+   J - 32 bit int
+   A - char
+   E - float 
+   D - double
+   B - unsigned bytes
+   C - complex float
+   M - complex double
+   P - var lenght array descrpt (64 bit)
+   
+   all can be preceeded by integer N which specified number
+   of entries in array
+   
+*/
+
+
+/***********************/
+int fits_set_table_column (Header *header, FTable *table, char *label, void *data, int Nrow) {
+
+  int i, N, Nfields, Nval, Nbytes, Nx, Ny, nbytes, Nstart, Nv, Nb;
+  char tlabel[80], field[80], format[80], cformat[80], type[16], tmp[16];
+  char *array, *Pin, *Pout, *line;
+
+  if (label == (char *) NULL) return (FALSE);
+  if (label[0] == 0) return (FALSE);
+
+  /* find label in header */
+  tlabel[0] = 0;
+  fits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  for (i = 1; strcmp (label, tlabel) && (i < Nfields + 1); i++) {
+    sprintf (field, "TTYPE%d", i);
+    fits_scan (header, field, "%s", 1, tlabel);
+  }
+  if (strcmp (label, tlabel)) return (FALSE);
+  N = i - 1;
+
+  /* interpret format */
+  sprintf (field, "TFORM%d", N);
+  fits_scan (header, field, "%s", 1, format);
+
+  if (!fits_table_format (format, type, &Nval, &Nbytes)) return (FALSE);
+  strcpy (cformat, format);
+  
+  /* check existing table dimensions */
+  fits_scan (header, "NAXIS1",  "%d", 1, &Nx);
+  fits_scan (header, "NAXIS2",  "%d", 1, &Ny);
+  if (Ny == 0) { 
+    Ny = Nrow;
+    header[0].Naxis[1] = Ny;
+    fits_modify (header, "NAXIS2",  "%d", 1, Ny);
+
+    nbytes = fits_matrix_size (header);
+    REALLOCATE (table[0].buffer, char, MAX (nbytes, 1));
+    bzero (table[0].buffer, nbytes);
+    table[0].size = nbytes;
+  }
+  if (Ny != Nrow) return (FALSE);
+
+  /* scan columns to find insert point */
+  Nstart = 0;
+  for (i = 1; i < N; i++) {
+    sprintf (field, "TFORM%d", i);
+    fits_scan (header, field, "%s", 1, format);
+    fits_table_format (format, tmp, &Nv, &Nb);
+    Nstart += Nv*Nb;
+  }
+
+  /* print line with appropriate formatting */
+  ALLOCATE (array, char, Nbytes*Nval*Nrow);
+  ALLOCATE (line, char, Nval+1);
+  Pin = data;
+  Pout = array;
+  if (!strcmp (type, "char")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin++, Pout++) {
+      *Pout = *Pin;
+    }
+  }
+  if (!strcmp (type, "int")) {
+    for (i = 0; i < Nrow; i++, Pin+=4, Pout+=Nval) {
+      snprintf (line, Nval + 1, cformat, *(int *)Pin);
+      memcpy (Pout, line, Nval);
+    }
+  }
+  if (!strcmp (type, "float")) {
+    for (i = 0; i < Nrow; i++, Pin+=4, Pout+=Nval) {
+      snprintf (line, Nval + 1, cformat, *(float *)Pin);
+      memcpy (Pout, line, Nval);
+    }
+  }
+
+  /* check array space */
+  if (Nx*Ny < Nx*(Nrow - 1) + Nstart + Nval*Nbytes) {
+    fprintf (stderr, "mismatch in array sizes\n");
+    return (FALSE);
+  }
+
+  /* insert bytes from array into appropriate section of buffer */
+  Pout = table[0].buffer + Nstart;
+  Pin  = array;
+  for (i = 0; i < Nrow; i++, Pout += Nx, Pin += Nval*Nbytes) {
+    memcpy (Pout, Pin, Nval*Nbytes);
+  }
+
+  free (line);
+  free (array);
+  return (TRUE);
+}
+
+/*
+  valid TABLE column formats:
+  FN.N  - floating point
+  INN   - integer
+  ANN   - NN char string
+  
+*/
+
Index: /tags/start/Ohana/src/libfits/table/F_table_column.c
===================================================================
--- /tags/start/Ohana/src/libfits/table/F_table_column.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/table/F_table_column.c	(revision 12606)
@@ -0,0 +1,94 @@
+# include "fits.h"
+
+/*********************** fits table column ****************************/
+int fits_table_column (Table *table, char *field, char *mode,...) {
+/* we expect one more field: the pointer to the array we read in */
+
+  char string[80], this_field[80], form[80], temp[80];
+  int i, j, N, start, end, width, M;
+  va_list argp;
+  double **D;
+  float  **F;
+  char   ***C;
+  int    **I;
+  
+  va_start (argp, mode);
+
+  /* find the correct field */
+  for (i = 0; i < table[0].Nfields; i++) {
+    sprintf (string, "TTYPE%d\0", i+1);
+    fits_scan (&table[0].header, string, "%s", 1, this_field);
+    if (!strcmp (field, this_field)) {
+      break;
+    }
+  }
+  
+  if (i == table[0].Nfields) {
+    fprintf (stderr, "Table field %s does not exist\n", field);
+    return (FALSE);
+  }
+
+  N = i + 1;
+
+  sprintf (string, "TBCOL%d\0", N);
+  fits_scan (&table[0].header, string, "%d", 1, &start);
+  sprintf (string, "TFORM%d\0", N);
+  fits_scan (&table[0].header, string, "%s", 1, form);
+  /* we could use some error checking from the FITS table form, but
+     it is not immediately crucial */
+
+  if (N == table[0].Nfields) { 
+    end = table[0].Naxis[0];
+  } else {
+    sprintf (string, "TBCOL%d\0", N+1);
+    fits_scan (&table[0].header, string, "%d", 1, &end);
+  }
+  width = end - start;
+  
+  if (!strcmp (mode, "%d")) {
+    I = va_arg (argp, int **);
+    ALLOCATE ((*I), int, table[0].Naxis[1]);
+    M = 0;
+  }
+  if (!strcmp (mode, "%f"))  {
+    F = va_arg (argp, float **);
+    ALLOCATE ((*F), float, table[0].Naxis[1]);
+    M = 1;
+  }
+  if (!strcmp (mode, "%lf")) {
+    D = va_arg (argp, double **);
+    ALLOCATE ((*D), double, table[0].Naxis[1]);
+    M = 2;
+  }
+  if (!strcmp (mode, "%s")) {
+    C = va_arg (argp, char ***);
+    ALLOCATE ((*C), char *, table[0].Naxis[1]);
+    for (i = 0; i < table[0].Naxis[1]; i++) {
+      ALLOCATE ((*C)[i], char, width + 1);
+    }
+    M = 3;
+  }
+
+  for (i = 0; i < table[0].Naxis[1]; i++) {
+    strncpy (temp, &table[0].buffer[i*table[0].Naxis[0] + start - 1], width);
+    temp[width] = 0;
+    switch (M) {
+    case 0:
+      (*I)[i] = (int) atof (temp);
+      break;
+    case 1:
+      (*F)[i] = atof (temp);
+      break;
+    case 2:
+      (*D)[i] = atof (temp);
+      break;
+    case 3:
+      strcpy ((*C)[i], temp);
+      break;
+    default:
+      fprintf (stderr, "unknown fits_table_column mode: %s\n", mode);
+      return (FALSE);
+    }
+  }
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/libfits/table/F_table_format.c
===================================================================
--- /tags/start/Ohana/src/libfits/table/F_table_format.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/table/F_table_format.c	(revision 12606)
@@ -0,0 +1,162 @@
+# include "fits.h"
+
+/***********************/
+int fits_bintable_format (char *format, char *type, int *Nval, int *Nbytes) {
+
+  char *Lchar, *Fchar;
+  int Nv;
+
+  if (format == (char *) NULL) return (FALSE);
+  if (format[0] == 0) return (FALSE);
+  Lchar = &format[strlen(format) - 1];
+
+  Nv = strtol (format, &Fchar, 10);
+  if (Fchar != Lchar) return (FALSE);
+  if ((Nv == 0) && (Fchar == format)) Nv = 1;
+
+  *Nbytes = 0;
+  if (*Fchar == 'X') { *Nbytes = 1;  strcpy (type, "char");   *Nval = 1 + (int) Nv / 8; }
+  if (*Fchar == 'L') { *Nbytes = 1;  strcpy (type, "char");   *Nval = Nv;               }
+  if (*Fchar == 'A') { *Nbytes = 1;  strcpy (type, "char");   *Nval = Nv;               }
+  if (*Fchar == 'B') { *Nbytes = 1;  strcpy (type, "char");   *Nval = Nv;               }
+  if (*Fchar == 'I') { *Nbytes = 2;  strcpy (type, "short");  *Nval = Nv;               }
+  if (*Fchar == 'J') { *Nbytes = 4;  strcpy (type, "int");    *Nval = Nv;               }
+  if (*Fchar == 'E') { *Nbytes = 4;  strcpy (type, "float");  *Nval = Nv;               }
+  if (*Fchar == 'D') { *Nbytes = 8;  strcpy (type, "double"); *Nval = Nv;               }
+  if (*Fchar == 'P') { *Nbytes = 8;  strcpy (type, "float");  *Nval = 2*Nv;             }
+  if (*Fchar == 'C') { *Nbytes = 8;  strcpy (type, "float");  *Nval = 2*Nv;             }
+  if (*Fchar == 'M') { *Nbytes = 16; strcpy (type, "double"); *Nval = 2*Nv;             }
+  if (!*Nbytes) { return (FALSE); }
+
+  return (TRUE);
+}
+
+/* 
+   valid BINTABLE column formats:
+   L - logical
+   X - bit
+   I - 16 bit int
+   J - 32 bit int
+   A - char
+   E - float 
+   D - double
+   B - unsigned bytes
+   C - complex float
+   M - complex double
+   P - var length array descrpt (64 bit)
+   
+   all can be preceeded by integer N which specified number
+   of entries in array
+   
+*/
+
+/***********************/
+int fits_table_format (char *format, char *type, int *Nval, int *Nbytes) {
+
+  char Fchar, foo[80], bar;
+  int Nv;
+
+  if (format == (char *) NULL) return (FALSE);
+  if (format[0] == 0) return (FALSE);
+  Fchar = format[0];
+
+  Nv = strtol (&format[1], (char **) NULL, 10);
+  if (Nv == 0) { 
+    Nv = 1;
+    strcpy (foo, "1");
+  } else {
+    strcpy (foo, &format[1]);
+  }
+
+  if (Fchar == 'F') { *Nbytes = 1;  strcpy (type, "float");  bar = 'f'; *Nval = Nv; }
+  if (Fchar == 'I') { *Nbytes = 1;  strcpy (type, "int");    bar = 'd'; *Nval = Nv; }
+  if (Fchar == 'A') { *Nbytes = 1;  strcpy (type, "char");   bar = 's'; *Nval = Nv; }
+  if (!*Nbytes) { return (FALSE); }
+  
+  sprintf (format, "%%-%s%c", foo, bar);
+
+  return (TRUE);
+}
+
+/***********************/
+int fits_table_to_vtable (FTable *ftable, VTable *vtable, int start, int Nkeep) {
+
+  /* fits_table_to_vtable (f, v, 0, Ny - 1) - keep all of table
+     fits_table_to_vtable (f, v, 0, 0)      - keep none of table 
+  */  
+
+  int i, Nx, Ny;
+
+  fits_scan (ftable[0].header, "NAXIS1", "%d", 1, &Nx);
+  fits_scan (ftable[0].header, "NAXIS2", "%d", 1, &Ny);
+  
+  if (start + Nkeep > Ny) return (FALSE);
+  if (start < 0) return (FALSE);
+  if (Nkeep < 0) return (FALSE);
+
+  ALLOCATE (vtable[0].row, int, MAX (1, Nkeep));
+  ALLOCATE (vtable[0].buffer, char *, MAX (1, Nkeep));
+  for (i = 0; i < Nkeep; i++) {
+    ALLOCATE (vtable[0].buffer[i], char, MAX (1, Nx));
+    memcpy (vtable[0].buffer[i], &ftable[0].buffer[(i+start)*Nx], Nx);
+    vtable[0].row[i] = i + start;
+  }
+  
+  vtable[0].header = ftable[0].header;
+  vtable[0].size = ftable[0].size;
+  vtable[0].Nrow = Nkeep;
+  vtable[0].pad = vtable[0].size - Nx*Ny;
+
+  return (TRUE);
+}
+
+/* use table def to format a complete string */
+char *fits_table_print (FTable *table,...) { 
+  
+  int i, Nx, Nfields;
+  int off, Nchar, Nval, Nbytes;
+  char *line, format[64], field[16], type[16];
+  va_list argp;
+  
+  va_start (argp, table);
+
+  fits_scan (table[0].header, "NAXIS1",  "%d", 1, &Nx);
+  fits_scan (table[0].header, "TFIELDS", "%d", 1, &Nfields);
+
+  ALLOCATE (line, char, Nx + 1);
+  
+  off = 0;
+  for (i = 1; i <= Nfields; i++) {
+
+    sprintf (field, "TFORM%d", i);
+    fits_scan (table[0].header, field, "%s", 1, format);       /* get field format */
+    fits_table_format (format, type, &Nval, &Nbytes); /* convert to c-style */
+    Nchar = Nval * Nbytes;
+    if (!strcmp (type, "int"))   { 
+      /* d = va_arg (argp, int); */
+      snprintf (&line[off], Nchar + 1, format, va_arg (argp, int)); 
+    }
+    if (!strcmp (type, "float")) { 
+      /* f = va_arg (argp, double); */
+      snprintf (&line[off], Nchar + 1, format, va_arg (argp, double)); 
+    }
+    if (!strcmp (type, "char"))  { 
+      /* c = va_arg (argp, char *); */
+      snprintf (&line[off], Nchar + 1, format, va_arg (argp, char *));
+    }
+    off += Nchar;
+  }
+  va_end (argp);
+  return (line);
+}
+
+/*
+  valid TABLE column formats:
+  FN.N  - floating point
+  INN   - integer
+  ANN   - NN char string
+  
+*/
+
+
+    /* vsnprintf (&line[off], Nchar + 1, format, argp); */
Index: /tags/start/Ohana/src/libfits/table/F_table_row.c
===================================================================
--- /tags/start/Ohana/src/libfits/table/F_table_row.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/table/F_table_row.c	(revision 12606)
@@ -0,0 +1,105 @@
+# include "fits.h"
+
+/*********************** fits table column ****************************/
+int fits_add_rows (FTable *table, char *data, int Nrow, int Nbytes) {
+
+  int Nx, Ny;
+  int nbytes, Nstart;
+  Header *header;
+
+  header = table[0].header;
+
+  fits_scan (header, "NAXIS1", "%d", 1, &Nx);
+  fits_scan (header, "NAXIS2", "%d", 1, &Ny);
+  
+  if (header[0].Naxis[1] != Ny) return (FALSE);
+  if (header[0].Naxis[0] != Nx) return (FALSE);
+  if (header[0].Naxis[0] != Nbytes) return (FALSE);
+  
+  Nstart = Nx*Ny;
+
+  /* update header y dimension */
+  Ny += Nrow;
+  header[0].Naxis[1] = Ny;
+  fits_modify (header, "NAXIS2",  "%d", 1, Ny);
+
+  nbytes = fits_matrix_size (header);
+  REALLOCATE (table[0].buffer, char, MAX (nbytes, 1));
+  table[0].size = nbytes;
+  
+  memcpy (&table[0].buffer[Nstart], data, Nbytes*Nrow);
+  memset (&table[0].buffer[Nx*Ny], ' ', nbytes - Nx*Ny);
+  return (TRUE);
+}
+
+/*********************** fits add (real) rows to virtual table ****************************/
+int fits_vadd_rows (VTable *table, char *data, int Nrow, int Nbytes) {
+
+  int i, Nx, Ny;
+  int Nstart;
+  Header *header;
+
+  header = table[0].header;
+
+  fits_scan (header, "NAXIS1", "%d", 1, &Nx);
+  fits_scan (header, "NAXIS2", "%d", 1, &Ny);
+  
+  if (header[0].Naxis[1] != Ny) return (FALSE);
+  if (header[0].Naxis[0] != Nx) return (FALSE);
+  if (header[0].Naxis[0] != Nbytes) return (FALSE);
+  
+  /* Nstart is end of data in memory */
+  Nstart = table[0].Nrow;
+  table[0].Nrow += Nrow;
+  REALLOCATE (table[0].buffer, char *, table[0].Nrow);
+  REALLOCATE (table[0].row, int, table[0].Nrow);
+  for (i = 0; i < Nrow; i++) {
+    ALLOCATE (table[0].buffer[Nstart+i], char, MAX (1, Nx));
+    memcpy (table[0].buffer[Nstart+i], &data[i*Nx], Nx);
+    table[0].row[Nstart+i] = Ny + i;
+  }
+
+  /* update header y dimension */
+  Ny += Nrow;
+  header[0].Naxis[1] = Ny;
+  fits_modify (header, "NAXIS2",  "%d", 1, Ny);
+
+  table[0].size   = fits_matrix_size (table[0].header);
+  table[0].pad    = table[0].size - Nx*Ny;
+
+  return (TRUE);
+}
+
+/*********************** fits table column ****************************/
+int fits_delete_rows (FTable *table, int Nstart, int Nrow) {
+
+  int Nx, Ny, N0, N1, N2;
+  int nbytes;
+  Header *header;
+
+  header = table[0].header;
+
+  fits_scan (header, "NAXIS1", "%d", 1, &Nx);
+  fits_scan (header, "NAXIS2", "%d", 1, &Ny);
+  
+  if (header[0].Naxis[1] != Ny) return (FALSE);
+  if (header[0].Naxis[0] != Nx) return (FALSE);
+  if (Ny > Nstart + Nrow) return (FALSE);
+  
+  /* shrink buffer by Nrow entries */
+  N0 = Nx*Nstart;
+  N1 = Nx*(Nstart + Nrow);
+  N2 = Nx*(Ny - Nstart - Nrow);
+  memmove (&table[0].buffer[N0], &table[0].buffer[N1], N2);
+
+  /* update header y dimension */
+  Ny -= Nrow;
+  header[0].Naxis[1] = Ny;
+  fits_modify (header, "NAXIS2",  "%d", 1, Ny);
+
+  nbytes = fits_matrix_size (header);
+  REALLOCATE (table[0].buffer, char, MAX (nbytes, 1));
+  table[0].size = nbytes;
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/libfits/table/F_write_T.c
===================================================================
--- /tags/start/Ohana/src/libfits/table/F_write_T.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/table/F_write_T.c	(revision 12606)
@@ -0,0 +1,69 @@
+# include "fits.h"
+
+/*********************** fits write header *********************************/
+int fits_write_table (char *filename, FTable *table) {
+  
+  FILE *f;
+  int status;
+  
+  status = TRUE;
+  
+  f = fopen (filename, "a+");
+  if (f == (FILE *) NULL) return (FALSE);
+  
+  status = fseek (f, 0, SEEK_END);  /* write table to end of file! */
+  status = fits_fwrite_table (f, table);
+
+  fclose (f);
+  return (status);
+}	
+
+/*********************** fits write table *********************************/
+int fits_fwrite_table (FILE *f, FTable *table) {
+  
+  int Nbytes;
+  
+  Nbytes = fwrite (table[0].buffer, sizeof(char), table[0].size, f);
+  
+  if (Nbytes != table[0].size) return (FALSE);
+  return (TRUE);
+}	
+
+/*********************** fits write virtual table *********************************/
+int fits_fwrite_vtable (FILE *f, VTable *table) {
+  
+  int i, Nx, Ny, Npad, offset, start;
+  int Nbytes, *row, Nrow;
+  char *pad;
+
+  Nrow = table[0].Nrow;
+  row = table[0].row;
+  fits_scan (table[0].header, "NAXIS1", "%d", 1, &Nx);
+  fits_scan (table[0].header, "NAXIS2", "%d", 1, &Ny);
+
+  /* file pointer is at beginning of desired table data */
+  start = ftell (f);
+  
+  for (i = 0; i < Nrow; i++) {
+    offset = start + Nx*row[i];
+    fseek (f, offset, SEEK_SET);
+    Nbytes = fwrite (table[0].buffer[i], sizeof (char), Nx, f);
+    if (Nbytes != Nx) { return (FALSE); }
+  }
+  
+  Npad = table[0].size - Nx*Ny;
+  ALLOCATE (pad, char, Npad);
+  bzero (pad, Npad);
+
+  offset = start + Nx*Ny;
+  fseek (f, offset, SEEK_SET);
+  Nbytes = fwrite (pad, sizeof (char), Npad, f);
+  if (Nbytes != Npad) { return (FALSE); }
+  free (pad);
+
+  return (TRUE);
+}	
+
+
+/* this will add data beyond the end of the table in the file if needed,
+   filling intervening gap with 0 */
Index: /tags/start/Ohana/src/libfits/table/F_write_TH.c
===================================================================
--- /tags/start/Ohana/src/libfits/table/F_write_TH.c	(revision 12606)
+++ /tags/start/Ohana/src/libfits/table/F_write_TH.c	(revision 12606)
@@ -0,0 +1,32 @@
+# include "fits.h"
+
+/*********************** fits write header *********************************/
+int fits_write_Theader (char *filename, Header *header) {
+  
+  FILE *f;
+  int status;
+  
+  status = TRUE;
+  
+  f = fopen (filename, "a+");
+  if (f == (FILE *) NULL) return (FALSE);
+  
+  status = fseek (f, 0, SEEK_END);  /* write header to end of file! */
+  status = fits_fwrite_Theader (f, header);
+
+  fclose (f);
+  return (status);
+}	
+
+/*********************** fits write header *********************************/
+int fits_fwrite_Theader (FILE *f, Header *header) {
+  
+  int Nbytes;
+  
+  Nbytes = fwrite (header[0].buffer, sizeof(char), header[0].size, f);
+
+  if (Nbytes != header[0].size) return (FALSE);
+  return (TRUE);
+}	
+
+
Index: /tags/start/Ohana/src/libohana/Makefile
===================================================================
--- /tags/start/Ohana/src/libohana/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/libohana/Makefile	(revision 12606)
@@ -0,0 +1,60 @@
+include ../../Configure
+HOME 	=	.
+
+LIB	= 	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	=	$(HOME)/include
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+  
+INCS	= 	-I$(LINC) -I$(LINC)/$(ARCH)
+CFLAGS	=	-Wunused -o $*.$(ARCH).o $(INCS) 
+LFLAGS	=	-c $(INCS)
+
+default: install
+
+install: $(DESTLIB)/libohana.a
+
+ohana: $(LIB)/libohana.$(ARCH).a 
+
+HOBJ = $(DESTINC)/ohana.h $(DESTINC)/loneos.h 
+
+LOBJ = \
+$(SRC)/string.$(ARCH).o		$(SRC)/findexec.$(ARCH).o	 \
+$(SRC)/config.$(ARCH).o		$(SRC)/coordops.$(ARCH).o	 \
+$(SRC)/Fread.$(ARCH).o		$(SRC)/glockfile.$(ARCH).o	 \
+$(SRC)/LoadPhotcodes.$(ARCH).o  $(SRC)/photfits.$(ARCH).o	 \
+$(SRC)/phot_catalog.$(ARCH).o
+
+$(DESTLIB)/libohana.a: $(LIB)/libohana.$(ARCH).a
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	rm -f $(DESTLIB)/libohana.a
+	cp $(LIB)/libohana.$(ARCH).a 	$(DESTLIB)/libohana.a
+
+$(LIB)/libohana.$(ARCH).a: $(HOBJ) $(LOBJ)
+	rm -f $(LIB)/libohana.$(ARCH).a
+	ar rcv $(LIB)/libohana.$(ARCH).a $(LOBJ)
+	ranlib $(LIB)/libohana.$(ARCH).a
+
+$(LOBJ): $(DESTINC)/ohana.h $(DESTINC)/loneos.h
+
+$(DESTINC)/%: $(INC)/%
+	@if [ ! -d $(DESTINC) ]; then mkdir -p $(DESTINC); fi
+	rm -f $(DESTINC)/$*
+	cp $(INC)/$* $(DESTINC)/
+
+clean:
+	rm -f */*~
+	rm -f */#*
+	rm -f */*.o
+	rm -f */*.a
+
+dist: clean
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
Index: /tags/start/Ohana/src/libohana/doc/coords_minimal.c
===================================================================
--- /tags/start/Ohana/src/libohana/doc/coords_minimal.c	(revision 12606)
+++ /tags/start/Ohana/src/libohana/doc/coords_minimal.c	(revision 12606)
@@ -0,0 +1,115 @@
+/* 
+here is some C code to project from R,D to x,y (all in decimal
+degrees) in a SIN projection, with Ro, Do as projection center:
+*/
+
+# define FULLPROJECTION 0
+# define DEG_RAD 57.295779513082322
+# define RAD_DEG  0.017453292519943
+
+RD_to_XY (double *x, double *y, double R, double D, double Ro, double Do) {
+
+  double sdp, cdp, salp, calp, sdel, cdel, stht, sphi, cphi;
+                 
+  sdp  = sin(RAD_DEG*Do);
+  cdp  = cos(RAD_DEG*Do);
+  salp = sin(RAD_DEG*(ra - Ro));
+  calp = cos(RAD_DEG*(ra - Ro));
+  sdel = sin(RAD_DEG*dec);
+  cdel = cos(RAD_DEG*dec);
+  
+  stht = sdel*sdp + cdel*cdp*calp;    /* sin(theta) */
+  sphi = cdel*salp;                   /* = cos(theta)*sin(phi) */
+  cphi = cdel*sdp*calp - sdel*cdp;    /* = cos(theta)*cos(phi) */
+  if (stht < 0) { return 0; /* projection from the wrong side of the sphere */ }
+  
+  X =  DEG_RAD * sphi;
+  Y = -DEG_RAD * cphi;
+  
+# if (FULLPROJECTION) 
+  
+  /* 
+     these lines allow for a rotation / distortion 2x2 matrix (pci_j),
+     a (two direction) plate-scale shift (cdelt1, cdelt2), 
+     and a reference center offset of Xo, Yo, if desired. 
+  */
+
+  tmp_d = 1.0 / (pc_1_1*pc_2_2 - pc_1_2*pc_2_1); 
+  *x = tmp_d * (pc_2_2*X - pc_1_2*Y) / cdelt1 + Xo;
+  *y = tmp_d * (pc_1_1*Y - pc_2_1*X) / cdelt2 + Yo;
+
+# else
+
+  *x = X;
+  *y = Y;
+  
+# endif
+
+
+  return (1);
+
+}
+
+
+/* 
+here is some C code to project from x,y to R,D (all in decimal
+degrees) in a SIN projection, with Ro, Do as projection center:
+*/
+
+XY_to_RD (double *ra, double *dec, double x, double y, double Ro, double Do) {
+
+
+  double L, M, X, Y, T, Z;
+  double R, sphi, cphi, stht, ctht;
+  double alpha, delta, salp, calp, sdel, sdp, cdp;
+  
+  *ra  = 0;
+  *dec = 0;
+  stht = ctht = 1;
+
+  
+# if (FULLPROJECTION) 
+  /* 
+     these lines allow for a rotation / distortion 2x2 matrix (pci_j),
+     a (two direction) plate-scale shift (cdelt1, cdelt2), 
+     and a reference center offset of Xo, Yo, if desired. 
+  */
+  X = cdelt1 * (x - Xo);
+  Y = cdelt2 * (y - Yo);
+
+  L = (X*pc1_1 + Y*pc1_2);
+  M = (X*pc2_1 + Y*pc2_2);
+# else 
+  L = x;
+  M = y;
+# endif
+
+  R = hypot (L,M);
+  if ((L == 0) && (M == 0)) {
+    sphi = 0;
+    cphi = 1;
+  }
+  else {
+    sphi =  L / R;
+    cphi = -M / R;
+  }
+
+  ctht = RAD_DEG * R;
+  stht = sqrt (1 - ctht*ctht);
+
+  sdp  = sin(RAD_DEG*Do);
+  cdp  = cos(RAD_DEG*Do);
+  
+  sdel = stht*sdp - ctht*cphi*cdp;
+  salp = ctht*sphi;
+  calp = stht*cdp + ctht*cphi*sdp;
+  alpha = atan2 (salp, calp);
+  delta = asin (sdel);
+  
+  *ra  = DEG_RAD*alpha + Ro;
+  *dec = DEG_RAD*delta;
+  
+  return (1);
+
+}
+
Index: /tags/start/Ohana/src/libohana/doc/coordtrans.txt
===================================================================
--- /tags/start/Ohana/src/libohana/doc/coordtrans.txt	(revision 12606)
+++ /tags/start/Ohana/src/libohana/doc/coordtrans.txt	(revision 12606)
@@ -0,0 +1,57 @@
+
+{ 
+
+  X = coords[0].cdelt1*(x - coords[0].crpix1);
+  Y = coords[0].cdelt2*(y - coords[0].crpix2);
+  L = (X*coords[0].pc1_1 + Y*coords[0].pc1_2);
+  M = (X*coords[0].pc2_1 + Y*coords[0].pc2_2);
+  R = hypot (L,M);
+  if ((L == 0) && (M == 0)) {
+    sphi = 0;
+    cphi = 1;
+  } else {
+    sphi =  L / R;
+    cphi = -M / R;
+  }
+  if (R == 0) {
+    stht = 1.0;
+    ctht = 0.0;
+  } else {
+    T = DEG_RAD / R;
+    stht =   T / sqrt ( 1.0 + T*T);
+    ctht = 1.0 / sqrt ( 1.0 + T*T);
+  }
+  sdp  = sin(RAD_DEG*coords[0].crval2);
+  cdp  = cos(RAD_DEG*coords[0].crval2);
+    
+  sdel = stht*sdp - ctht*cphi*cdp;
+  salp = ctht*sphi;
+  calp = stht*cdp + ctht*cphi*sdp;
+  alpha = atan2 (salp, calp);
+  delta = asin (sdel);
+    
+  *ra  = DEG_RAD*alpha + coords[0].crval1;
+  *dec = DEG_RAD*delta;
+}
+
+RD_to_XY () {
+
+  sdp  = sin(RAD_DEG*coords[0].crval2);
+  cdp  = cos(RAD_DEG*coords[0].crval2);
+  salp = sin(RAD_DEG*(ra - coords[0].crval1));
+  calp = cos(RAD_DEG*(ra - coords[0].crval1));
+  sdel = sin(RAD_DEG*dec);
+  cdel = cos(RAD_DEG*dec);
+
+  stht = sdel*sdp + cdel*cdp*calp;    /* sin(theta) */
+  sphi = cdel*salp;                   /* = cos(theta)*sin(phi) */
+  cphi = cdel*sdp*calp - sdel*cdp;    /* = cos(theta)*cos(phi) */
+  if (stht < 0) status = FALSE;
+
+  X =  DEG_RAD * sphi / stht;
+  Y = -DEG_RAD * cphi / stht;
+  tmp_d = 1.0 / (coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1);
+  *x = tmp_d * (coords[0].pc2_2*X - coords[0].pc1_2*Y) / coords[0].cdelt1 + coords[0].crpix1;
+  *y = tmp_d * (coords[0].pc1_1*Y - coords[0].pc2_1*X) / coords[0].cdelt2 + coords[0].crpix2;
+
+}
Index: /tags/start/Ohana/src/libohana/doc/libohana.html
===================================================================
--- /tags/start/Ohana/src/libohana/doc/libohana.html	(revision 12606)
+++ /tags/start/Ohana/src/libohana/doc/libohana.html	(revision 12606)
@@ -0,0 +1,148 @@
+
+<h2> libohana API reference </h2>
+
+<h3> functions in string.c </h3>
+
+<pre> int get_argument (int argc, char **argv, char *arg); </pre>
+
+search argv, argc list (starting at argv[1]) for desired argument.
+returns entry number if found, 0 otherwise. 
+<hr>
+
+<pre> int remove_argument (int Narg, int &argc, char **argv); </pre>
+
+remove the given entry Narg from the argv list, adjusting argc
+appropriately. 
+<hr>
+
+<pre> int stripwhite (char *string); </pre>
+
+strip whitespace (space or tab) from start and end of string.
+<hr>
+
+<pre> int strnumcmp (char *str1, char *str2); </pre>
+
+compare str1 and str2 as strings, or as numbers if both are pure
+numeric values (base 10 only).  returns TRUE / FALSE.
+<hr>
+
+<pre> char *strcreate (char *string); </pre>
+<pre> char *strncreate (char *string, int Nbytes); </pre>
+<pre> int scan_line (FILE *f, char *line); </pre>
+<pre> int dparse (double *value, int Nentry, char *line); </pre>
+<pre> int fparse (double *value, int Nentry, char *line); </pre>
+<pre> char *_parse_nextword (char *string); </pre>
+
+<h3> functions in findexec.c </h3>
+
+<pre> char *pathname (char *file); </pre>
+<pre> char *filerootname (char *file); </pre>
+<pre> char *fileextname (char *file); </pre>
+<pre> char *filebasename (char *file); </pre>
+<pre> char *findexec (int argc, char **argv); </pre>
+<pre> int mkdirhier (char *path); </pre>
+<pre> char *getcwd_cfht (char *path, int size); </pre>
+
+<h3> functions in glockfile.c </h3>
+
+<pre> FILE *fsetlockfile (char *filename, double timeout, int type, int *state); </pre>
+<pre> int fclearlockfile (char *filename, FILE *f, int type, int *state); </pre>
+<pre> int setlockfile2 (char *filename, double timeout, int type, int *state); </pre>
+<pre> int clearlockfile2 (char *filename, double timeout, int type, int *state); </pre>
+
+<b> deprecated functions : are they all removed?  </b>
+<pre> int setlockfile (char *name, double timeout, int hard); </pre>
+<pre> int clearlockfile (char *name, int fd, int hard); </pre>
+<pre> int gnfsflush (char *filename); </pre>
+
+<h3> functions in Fread.c </h3>
+
+<pre> int Fread (char ptr, int size, int nitems, FILE *f, char *type); </pre>
+<pre> int Fwrite (char ptr, int size, int nitems, FILE *f, char *type); </pre>
+<pre> int ByteSwap (char *ptr, int size, int nitems, char *type); </pre>
+<pre> int ConvertStruct (char *buffer, int size, int nitems, char *type); </pre>
+
+<h3> functions in LoadPhotcodes.c </h3>
+
+<pre> int LoadPhotcodes (char *filename, PhotCodeData *photcodes); </pre>
+<pre> int FreePhotcodes (PhotCodeData *photcodes); </pre>
+<pre> int GetPhotcodebyName (PhotCodeData *photcodes, char *name); </pre>
+<pre> int GetPhotcodeRefs (PhotCodeData *photcodes, char *name, int *code, int *ref); </pre>
+<pre> int GetPhotcodeEquiv (PhotCodeData *photcodes, char *name, int *code, int *ref); </pre>
+<pre> char *GetPhotnamebyCode (PhotCodeData *photcodes, int code); </pre>
+
+<h3> functions in config.c </h3>
+
+<pre> char *SelectConfigFile (int *argc, char **argv, char *progname); </pre>
+<pre> char *LoadConfigFile (char *filename); </pre>
+<pre> char *ScanConfig (char *config, char *field, char *mode, int Nentry, ...); </pre>
+<pre> char *expandline (char *line, char *config); </pre>
+<pre> char *LoadRawConfigFile (char *filename, int options); </pre>
+
+<h3> functions in coordops.c </h3>
+
+<pre> int XY_to_RD (double *ra, double *dec, double x,  double y,   Coords *coords); </pre>
+<pre> int RD_to_XY (double *x,  double *y,   double ra, double dec, Coords *coords); </pre>
+<pre> int fXY_to_RD (float *ra, float *dec, float x,  float y,   Coords *coords); </pre>
+<pre> int fRD_to_XY (float *x,  float *y,   float ra, float dec, Coords *coords); </pre>
+<pre> int GetCoords (Coords *coords, Header *header); </pre>
+<pre> int coords_precess (double *ra, double *dec, double in_epoch, double out_epoch); </pre>
+
+<h3> functions in phot_catalog.c </h3>
+
+<pre> int lock_catalog (Catalog *catalog, int lockmode); </pre>
+<pre> int unlock_catalog (Catalog *catalog); </pre>
+<pre> int load_catalog (Catalog *catalog, char mode, int VERBOSE); </pre>
+<pre> int save_catalog (Catalog *catalog, char VERBOSE); </pre>
+<pre> Measure *FixOldMeasure (OldMeasure *in, int Nvalues); </pre>
+<pre> Average *FixOldAverage (OldAverage *in, int Nvalues); </pre>
+<pre> SecFilt *FixOldSecFilt (OldSecFilt *in, int Nvalues); </pre>
+
+<h3> functions in photfits.c </h3>
+
+<pre> short int putMi (double value); </pre>
+<pre> double getMi (short int value); </pre>
+<pre> void returnMcal (Image *image, double *c); </pre>
+<pre> void assignMcal (Image *image, double *c, int order); </pre>
+<pre> double applyMcal (Image *image, double x, double y); </pre>
+<pre> double findscatter (double *X, double *Y, double *M, double *dM, int N, double *c, int order); </pre>
+
+<h3> defined macros </h3>
+
+the ohana library includes the following macros:
+
+<pre>
+ALLOCATE (void *ptr, type, int Nelement)
+REALLOCATE (void *ptr, type, int Nelement)
+
+SIGN(X)  
+ROUND(X) 
+SQR(X)   
+SQ(X)    
+MIN(X,Y) 
+MAX(X,Y) 
+SWAP(X,Y) 
+
+whitespace (char c)
+</pre>
+
+<h3> defined constants </h3>
+
+<pre>
+TRUE
+FALSE
+
+LCK_SOFT - block writing
+LCK_XCLD - block reading and writing
+LCK_HARD - block reading and writing, persistent
+
+LCK_UNLOCK   - file is unlocked 
+LCK_ACCESS   - can't get access to file 
+LCK_TIMEOUT  - timeout setting lock 
+LCK_HARDLCK  - error setting hard lockfile 
+LCK_HUNLOCK  - error clearing hard lockfile 
+	    
+LCK_EMPTY    - locked file is empty 
+LCK_FULL     - locked file is not empty 
+LCK_UNKNOWN  - can't stat file to get size 
+</pre>
Index: /tags/start/Ohana/src/libohana/doc/load_catalog.c
===================================================================
--- /tags/start/Ohana/src/libohana/doc/load_catalog.c	(revision 12606)
+++ /tags/start/Ohana/src/libohana/doc/load_catalog.c	(revision 12606)
@@ -0,0 +1,263 @@
+# include <ohana.h>
+# include <loneos.h>
+
+/* the function in this file uses the old definition of Catalog,
+   and is deprecated by the new locking scheme */
+
+typedef struct {
+  Average *average;
+  Measure *measure; 
+  Missing *missing; 
+  SecFilt *secfilt;
+  Header  header;
+  int Naverage, Nmeasure, Nmissing, Nsecfilt;
+  int *found;
+  int *image;
+  float *X, *Y;
+} Catalog;
+
+Measure *FixOldMeasure (OldMeasure *in, int Nvalues) {
+
+  int i;
+  Measure *out;
+
+  ALLOCATE (out, Measure, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].dR = in[i].dR;
+    out[i].dD = in[i].dD;
+    out[i].M  = in[i].M;
+    out[i].dM = in[i].dM;
+    out[i].Mcal = in[i].Mcal;
+    out[i].dophot = in[i].dophot;
+    out[i].source = in[i].source;
+    out[i].t = in[i].t;
+
+    out[i].dt = 0xffff;
+    out[i].averef = in[i].average & 0x00ffffff;
+    out[i].flags  = (in[i].average & 0xff000000) >> 24;
+  }
+
+  free (in);
+  
+  return (out);
+}
+
+Average *FixOldAverage (OldAverage *in, int Nvalues) {
+
+  int i;
+  Average *out;
+
+  ALLOCATE (out, Average, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].R       = in[i].R;      
+    out[i].D       = in[i].D;      
+    out[i].M       = in[i].M;      
+    out[i].Xp      = in[i].Xp;     
+    out[i].Xm      = in[i].Xm;     
+    out[i].Nm      = in[i].Nm;     
+    out[i].Nn      = in[i].Nn;     
+    out[i].code    = in[i].code;   
+    out[i].offset  = in[i].offset; 
+    out[i].missing = in[i].missing;
+
+    out[i].dM = 0xffff;
+  }
+
+  free (in);
+  
+  return (out);
+}
+
+SecFilt *FixOldSecFilt (OldSecFilt *in, int Nvalues) {
+
+  int i;
+  SecFilt *out;
+
+  ALLOCATE (out, SecFilt, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].M    = in[i].M;      
+    out[i].Xm   = in[i].Xm;      
+
+    out[i].dM   = 0xffff;
+  }
+
+  free (in);
+  
+  return (out);
+}
+
+load_catalog (char *filename, Catalog *catalog, char mode, char VERBOSE) {
+  
+  int Nitems, nitems;
+  int i, Nmeas, Nmiss, size, ssize;
+  int NewMeasure, NewAverage, NewSecFilt;
+  FILE *f;
+  OldMeasure *tmpmeasure;
+  OldAverage *tmpaverage;
+  OldSecFilt *tmpsecfilt;
+  struct stat filestatus;
+
+  /* possible exit status: 
+     0 - serious failure
+     1 - success
+     2 - file non-existent */
+
+  /* read catalog header */
+  if (!fits_read_header (filename, &catalog[0].header)) {
+    if (VERBOSE) fprintf (stderr, "catalog file does not exist: %s\n", filename);
+    return (2);
+  }
+
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    if (VERBOSE) fprintf (stderr, "ERROR: can't read data from catalog file: %s\n", filename);
+    return (FALSE);
+  }
+  fseek (f, catalog[0].header.size, SEEK_SET); 
+
+  catalog[0].Naverage = catalog[0].Nmeasure = catalog[0].Nmissing = catalog[0].Nsecfilt = 0;
+  if (!fits_scan (&catalog[0].header, "NSTARS",   "%d", 1, &catalog[0].Naverage)) return (FALSE);
+  if (!fits_scan (&catalog[0].header, "NMEAS",    "%d", 1, &catalog[0].Nmeasure)) return (FALSE);
+  if (!fits_scan (&catalog[0].header, "NMISS",    "%d", 1, &catalog[0].Nmissing)) return (FALSE);
+  if (!fits_scan (&catalog[0].header, "NSECFILT", "%d", 1, &catalog[0].Nsecfilt)) catalog[0].Nsecfilt = 0;
+  if (!fits_scan (&catalog[0].header, "NEWMEAS",  "%t", 1, &NewMeasure)) NewMeasure = FALSE;
+  if (!fits_scan (&catalog[0].header, "NEWAVES",  "%t", 1, &NewAverage)) NewAverage = FALSE;
+  if (!fits_scan (&catalog[0].header, "NEWSECF",  "%t", 1, &NewSecFilt)) NewSecFilt = FALSE;
+
+  /* predicted file size */
+
+  size = 0;
+  ssize = NewAverage ? sizeof (Average) : sizeof (OldAverage);
+  size += ssize * catalog[0].Naverage;
+
+  ssize = NewMeasure ? sizeof (Measure) : sizeof (OldMeasure);
+  size += ssize * catalog[0].Nmeasure;
+
+  ssize = sizeof (Missing);
+  size += ssize * catalog[0].Nmissing;
+
+  ssize = NewSecFilt ? sizeof (SecFilt) : sizeof (OldSecFilt);
+  size += ssize * catalog[0].Nsecfilt * catalog[0].Naverage;
+
+  size += catalog[0].header.size;
+
+  /* check that file size makes sense */
+  if (stat (filename, &filestatus) == -1) {
+    fprintf (stderr, "ERROR: failed to get status of star catalog\n");
+    exit (1);
+  }
+  if (size != filestatus.st_size) {
+    fprintf (stderr, "ERROR: star catalog has inconsistent size\n");
+    exit (1);
+  } 
+
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars yet in catalog %s\n", filename);
+    fclose (f);
+    return (TRUE);
+  }
+
+  if (mode & LOAD_AVES) {
+    /* read average values */
+    if (NewAverage) {
+      ALLOCATE (catalog[0].average, Average, MAX (catalog[0].Naverage, 1));
+      Nitems = catalog[0].Naverage;
+      nitems = Fread (catalog[0].average, sizeof(Average), Nitems, f, "average");
+    } else {
+      ALLOCATE (tmpaverage, Average, MAX (catalog[0].Naverage, 1));
+      Nitems = catalog[0].Naverage;
+      nitems = Fread (tmpaverage, sizeof(OldAverage), Nitems, f, "oldaverage");
+      catalog[0].average = FixOldAverage (tmpaverage, Nitems);
+    }
+    if (nitems != Nitems) {
+      fprintf (stderr, "ERROR: failed to read averages from catalog file %s\n", filename);
+      fclose (f);
+      return (FALSE);
+    }
+  } else {
+    /* skip over averages */
+    fseek (f, catalog[0].Naverage * sizeof(Average), SEEK_CUR); 
+  }    
+  
+  if (mode & LOAD_MEAS) {
+    /* read measurements */
+    if (NewMeasure) {
+      ALLOCATE (catalog[0].measure, Measure, MAX (catalog[0].Nmeasure, 1));
+      Nitems = catalog[0].Nmeasure;
+      nitems = Fread (catalog[0].measure, sizeof(Measure), Nitems, f, "measure");
+    } else {
+      ALLOCATE (tmpmeasure, OldMeasure, MAX (catalog[0].Nmeasure, 1));
+      Nitems = catalog[0].Nmeasure;
+      nitems = Fread (tmpmeasure, sizeof(OldMeasure), Nitems, f, "oldmeasure");
+      catalog[0].measure = FixOldMeasure (tmpmeasure, Nitems);
+    }
+    if (nitems != Nitems) {
+      fprintf (stderr, "ERROR: failed to read measures from catalog file %s\n", filename);
+      fclose (f);
+      return (FALSE);
+    }
+  } else {
+    /* skip over measures */
+    fseek (f, catalog[0].Nmeasure * sizeof(Measure), SEEK_CUR); 
+  } 
+
+  if (mode & LOAD_MISS) {
+    /* read missing */
+    ALLOCATE (catalog[0].missing, Missing, MAX (catalog[0].Nmissing, 1));
+    Nitems = catalog[0].Nmissing;
+    nitems = Fread (catalog[0].missing, sizeof(Missing), Nitems, f, "missing");
+    if (nitems != Nitems) {
+      fprintf (stderr, "ERROR: failed to read missing from catalog file %s\n", filename);
+      fclose (f);
+      return (FALSE);
+    }
+  } else {
+    /* skip over missings */
+    fseek (f, catalog[0].Nmissing * sizeof(Missing), SEEK_CUR); 
+  }
+  
+  if (mode & LOAD_SECF) {
+    /* read missing */
+    if (NewSecFilt) {
+      Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
+      ALLOCATE (catalog[0].secfilt, SecFilt, MAX (Nitems, 1));
+      nitems = Fread (catalog[0].secfilt, sizeof(SecFilt), Nitems, f, "secfilt");
+    } else {
+      Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
+      ALLOCATE (tmpsecfilt, OldSecFilt, MAX (Nitems, 1));
+      nitems = Fread (tmpsecfilt, sizeof(OldSecFilt), Nitems, f, "oldsecfilt");
+      catalog[0].secfilt = FixOldSecFilt (tmpsecfilt, Nitems);
+    } 
+    if (nitems != Nitems) {
+      fprintf (stderr, "ERROR: failed to read secondary filters from catalog file %s\n", filename);
+      fclose (f);
+      return (FALSE);
+    }
+  } else {
+    /* skip over secfilts */
+    fseek (f, catalog[0].Naverage * catalog[0].Nsecfilt * sizeof(SecFilt), SEEK_CUR); 
+  }
+
+  fclose (f);
+  
+  if (VERBOSE) fprintf (stderr, "read %d stars from catalog file %s (%d measurements, %d missing, %d secondary filters)\n", 
+	   catalog[0].Naverage, filename, catalog[0].Nmeasure, catalog[0].Nmissing, catalog[0].Nsecfilt);
+
+  if (mode & LOAD_AVES) {
+    for (i = Nmeas = Nmiss = 0; i < catalog[0].Naverage; i++) {
+      Nmeas += catalog[0].average[i].Nm; 
+      Nmiss += catalog[0].average[i].Nn; 
+    }
+    if ((Nmeas != catalog[0].Nmeasure) || (Nmiss != catalog[0].Nmissing)) {
+      fprintf (stderr, "ERROR: data in catalog %s is corrupt, sums don't check\n", filename);
+      fprintf (stderr, "ERROR: Nmeas: %d, %d\n", Nmeas, catalog[0].Nmeasure);
+      fprintf (stderr, "ERROR: Nmiss: %d, %d\n", Nmiss, catalog[0].Nmissing);
+      return (FALSE);
+    }
+  }
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/libohana/doc/notes.txt
===================================================================
--- /tags/start/Ohana/src/libohana/doc/notes.txt	(revision 12606)
+++ /tags/start/Ohana/src/libohana/doc/notes.txt	(revision 12606)
@@ -0,0 +1,45 @@
+
+string / argv functions:
+
+int get_argument (int argc, char **argv, char *arg);
+int remove_argument (int Narg, int &argc, char **argv);
+int stripwhite (char *string);
+int strnumcmp (char *str1, char *str2);
+char *strcreate (char *string);
+char *strncreate (char *string, int Nbytes);
+int scan_line (FILE *f, char *line);
+int dparse (double *value, int Nentry, char *line);
+
+char *_parse_nextword (char *string);
+
+char *pathname (char *file);
+char *filerootname (char *file);
+char *fileextname (char *file);
+char *filebasename (char *file);
+char *findexec (int argc, char **argv);
+int mkdirhier (char *path);
+char *getcwd_cfht (char *path, int size);
+
+
+locking functions / catalog
+
+int setlockfile2 (char *filename, double timeout, int type, int *state);
+int clearlockfile2 (char *filename, double timeout, int type, int *state);
+
+int lock_catalog (Catalog *catalog, int lockmode);
+int unlock_catalog (Catalog *catalog);
+int load_catalog (Catalog *catalog, char mode, int VERBOSE);
+void save_catalog (Catalog *catalog, char VERBOSE);
+
+locks:
+
+LCK_SOFT - block writing
+LCK_XCLD - block reading and writing
+LCK_HARD - block reading and writing, persistent
+
+setlockfile (LCK_SOFT):
+
+errors:
+ HARD,XCLD: if file missing, create (666?) 
+ SOFT: if file missing: error LCK_ACCESS
+ 
Index: /tags/start/Ohana/src/libohana/doc/ohana.txt
===================================================================
--- /tags/start/Ohana/src/libohana/doc/ohana.txt	(revision 12606)
+++ /tags/start/Ohana/src/libohana/doc/ohana.txt	(revision 12606)
@@ -0,0 +1,57 @@
+
+these routines make up the ohana library.  to compile a program with
+them, include ohana.h and link with -libohana. 
+
+the ohana library includes the following macros:
+
+ALLOCATE (void *ptr, type, int Nelement)
+REALLOCATE (void *ptr, type, int Nelement)
+
+SIGN(X)  
+ROUND(X) 
+SQR(X)   
+SQ(X)    
+MIN(X,Y) 
+MAX(X,Y) 
+SWAP(X,Y) 
+
+whitespace (char c)
+
+the ohana library includes the following functions:
+
+int stripwhite (char *string)
+char *strcreate (char *string)
+char *strncreate (char *string, int n)
+int scan_line (FILE *f, char *line) 
+char *_parse_nextword (char *string)
+int dparse (double *X, int NX, char *line)
+
+int get_argument (int argc, char **argv, char *arg)
+int remove_argument (int N, int *argc, char **argv)
+
+int Fread (char ptr, int size, int nitems, FILE *f, char *type)
+int Fwrite (char ptr, int size, int nitems, FILE *f, char *type)
+int ByteSwap (char *ptr, int size, int nitems, char *type) 
+
+int _check_permissions (char *filename)
+char *pathname (char *name)
+char *filebasename (char *name)
+char *findexec (int argc, char **argv)
+
+char *SelectConfigFile (int *argc, char **argv, char *progname)
+char *LoadConfigFile (char *filename) 
+char *ScanConfig (char *config, char *field, char *mode, void *ptr)
+char *expandline (char *line, char *config)
+
+XY_to_RD (double *ra, double *dec, double x,  double y,   Coords *coords)
+RD_to_XY (double *x,  double *y,   double ra, double dec, Coords *coords)
+fXY_to_RD (float *ra, float *dec, float x,  float y,   Coords *coords)
+fRD_to_XY (float *x,  float *y,   float ra, float dec, Coords *coords)
+int GetCoords (Coords *coords, Header *header)
+
+save_catalog (char *filename, Catalog *catalog, char VERBOSE)
+load_catalog (char *filename, Catalog *catalog, char mode, char VERBOSE)
+
+LoadPhotcodes (char *filename, PhotCodeData *photcodes)
+GetPhotcodebyName (PhotCodeData *photcodes, char *name)
+double applyphot (PhotCode photcode, int Nphotcode, Average *ave, Measure *meas)
Index: /tags/start/Ohana/src/libohana/doc/save_catalog.c
===================================================================
--- /tags/start/Ohana/src/libohana/doc/save_catalog.c	(revision 12606)
+++ /tags/start/Ohana/src/libohana/doc/save_catalog.c	(revision 12606)
@@ -0,0 +1,89 @@
+# include <ohana.h>
+# include <loneos.h>
+
+/* the function in this file uses the old definition of Catalog,
+   and is deprecated by the new locking scheme */
+
+typedef struct {
+  Average *average;
+  Measure *measure; 
+  Missing *missing; 
+  SecFilt *secfilt;
+  Header  header;
+  int Naverage, Nmeasure, Nmissing, Nsecfilt;
+  int *found;
+  int *image;
+  float *X, *Y;
+} Catalog;
+
+save_catalog (char *filename, Catalog *catalog, char VERBOSE) {
+
+  int i, Nitems, nitems, mode;
+  FILE *f;
+
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (2);
+  }
+
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't create new catalog file: %s\n", filename);
+    return (0);
+  }
+
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  chmod (filename, mode);
+ 
+  fits_modify (&catalog[0].header, "NSTARS",   "%d", 1, catalog[0].Naverage);
+  fits_modify (&catalog[0].header, "NMEAS",    "%d", 1, catalog[0].Nmeasure);
+  fits_modify (&catalog[0].header, "NMISS",    "%d", 1, catalog[0].Nmissing);
+  fits_modify (&catalog[0].header, "NSECFILT", "%d", 1, catalog[0].Nsecfilt);
+  fits_modify (&catalog[0].header, "NEWMEAS",  "%t", 1, TRUE);
+  fits_modify (&catalog[0].header, "NEWAVES",  "%t", 1, TRUE);
+  fits_modify (&catalog[0].header, "NEWSECF",  "%t", 1, TRUE);
+
+  nitems = Fwrite (catalog[0].header.buffer, 1, catalog[0].header.size, f, "char");
+  if (nitems != catalog[0].header.size) {
+    fprintf (stderr, "ERROR: failed to write header\n");
+    return (0);
+  }
+
+  Nitems = catalog[0].Naverage;
+  nitems = Fwrite (catalog[0].average, sizeof(Average), Nitems, f, "average");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to write catalog file aves %s\n", filename);
+    return (0);
+  }
+  
+  Nitems = catalog[0].Nmeasure;
+  nitems = Fwrite (catalog[0].measure, sizeof(Measure), Nitems, f, "measure");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to write catalog file meas %s\n", filename);
+    return (0);
+  }
+
+  Nitems = catalog[0].Nmissing;
+  nitems = Fwrite (catalog[0].missing, sizeof(Missing), Nitems, f, "missing");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to write catalog file miss %s\n", filename);
+    return (0);
+  }
+
+  Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
+  nitems = Fwrite (catalog[0].secfilt, sizeof(SecFilt), Nitems, f, "secfilt");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to write catalog file secondary filters %s\n", filename);
+    return (0);
+  }
+
+  fclose (f);
+  return (1);
+
+}
+
+  /* possible exit status: 
+     0 - serious failure
+     1 - success
+     2 - data non-existent */
+
Index: /tags/start/Ohana/src/libohana/include/Xohana.h
===================================================================
--- /tags/start/Ohana/src/libohana/include/Xohana.h	(revision 12606)
+++ /tags/start/Ohana/src/libohana/include/Xohana.h	(revision 12606)
@@ -0,0 +1,8 @@
+# include <ohana.h>
+# include <X11/Xatom.h>
+# include <X11/Xlib.h>
+# include <X11/Xresource.h>
+# include <X11/Xutil.h>
+# include <X11/cursorfont.h>
+# include <X11/keysym.h>
+# include <X11/keysymdef.h>
Index: /tags/start/Ohana/src/libohana/include/loneos.h
===================================================================
--- /tags/start/Ohana/src/libohana/include/loneos.h	(revision 12606)
+++ /tags/start/Ohana/src/libohana/include/loneos.h	(revision 12606)
@@ -0,0 +1,445 @@
+
+# ifndef LONEOS_H
+# define LONEOS_H
+
+/* image data modes in RegImage */
+# define MODE_NONE   0  /* not defined */
+# define MODE_MEF    1  /* chip of mef image */
+# define MODE_SPLIT  2  /* chip of split image */
+# define MODE_SINGLE 3  /* single chip, not mosaic */
+# define MODE_CUBE   4  /* cube entry */
+# define MODE_SLICE  5  /* slice of a cube */
+# define MODE_MODES  6  /* not used? */
+
+# define TYPE_NONE   0
+# define TYPE_OBJECT 1
+# define TYPE_DARK   2
+# define TYPE_BIAS   3
+# define TYPE_FLAT   4
+
+/** these are no longer used by imregister-3.0 
+    status:imrough uses the imregister-3.0 values
+    status:imsearch should migrate to the imregister.h version 
+    or be removed!
+**/
+
+# define IMREG_DIST  0x01 /* image distributed, only imregister-3.0 */
+
+/* catalog values to be loaded */
+# define LOAD_AVES 0x01
+# define LOAD_MEAS 0x02
+# define LOAD_MISS 0x04
+# define LOAD_SECF 0x08
+
+/* invalid mag value */
+# define NO_MAG    0x7fff
+
+/* photometry code types */
+# define PHOT_PRI 0x01
+# define PHOT_SEC 0x02
+# define PHOT_DEP 0x03
+# define PHOT_REF 0x04
+# define PHOT_ALT 0x05  /* never stored, only for look-ups */
+
+/* Image.code values.  these are codes to note bad images */
+# define ID_IMAGE_NEW   0x0000  /* no nrphot attempted */
+# define ID_IMAGE_NOCAL 0x0001  /* used within nrphot to mean "don't apply fit" */
+# define ID_IMAGE_POOR  0x0002  /* relphot says image is bad */
+# define ID_IMAGE_SKIP  0x0004  /* external information image is bad */
+# define ID_IMAGE_FEW   0x0008  /* currently too few measurements for good value */
+
+/* Measure.flags values */
+# define ID_MEAS_NOCAL        0x0001
+# define ID_MEAS_POOR         0x0002
+# define ID_MEAS_SKIP         0x0004
+# define ID_MEAS_AREA         0x0008
+# define BLEND_IMAGE          0x0100 
+# define BLEND_CATALOG        0x0200
+# define BLEND_IMAGE_NEIGHBOR 0x1000
+# define ID_MEAS_TRAIL        0x2000
+# define ID_MEAS_GHOST        0x4000
+
+/* Average.code values */
+# define ID_STAR_FEW   0x0001 /* used within relphot: skip star */
+# define ID_STAR_POOR  0x0002 /* used within relphot: skip star */
+# define ID_PROPER     0x0400 /* star with large proper motion */
+# define ID_TRANSIENT  0x1000 /* is this mutually exclusive with USNO?  */
+# define ID_VARIABLE   0x2000 /* not currently set? */
+# define ID_ASTEROID   0x2000 /* identified with an asteroid */
+# define ID_BAD_OBJECT 0x4000 /* if all measurements are bad, set this bit */
+# define ID_MOVING     0x8000
+# define ID_ROCK       0xa000 /* 0x8000 + 0x2000 */
+# define ID_GHOST      0xc001 /* 0x8000 + 0x4000 + 0x0001 */
+# define ID_TRAIL      0xc002 /* 0x8000 + 0x4000 + 0x0002 */
+# define ID_BLEED      0xc003 /* 0x8000 + 0x4000 + 0x0003 */ 
+# define ID_COSMIC     0xc004 /* 0x8000 + 0x4000 + 0x0004 */ 
+
+/* 
+   BLEND_IMAGE: the star on an image is matched with more 
+      than one star in the catalog (image has worse seeing than catalog)
+   BLEND_CATALOG: the star in the catalog is matched with more 
+      than one star on the image (image has better seeing than catalog)
+   CALIBRATED: relative photometry has been performed on this measurement
+   BLEND_IMAGE_NEIGHBOR: the star on an image is matched with more 
+      than one star in the catalog, but not in the same catalog file.
+*/
+
+/* structure for data on a catalog region */
+typedef struct {
+  char filename[256];
+  double DEC[2], RA[2];
+} GSCRegion;
+
+/* structure for Image Registration Database */
+typedef struct {
+  char filename[64];
+  char pathname[128];
+  char filter[32];
+  char instrument[32];
+  char ccd;                        /* an identifier for CCD in mosaic (0 for single ccd) */
+  char mode;                       /* MEF, SINGLE, SPLIT */
+  char type;                       /* image type */
+  char flag;                       /* image status flags */
+  char junk[24];
+ 
+  float exptime;
+  float airmass;
+  float sky;
+  float bias;
+  float fwhm;
+
+  float telfocus;
+  float xprobe, yprobe, zprobe;
+  float dettemp;
+  float teltemp[4];
+  float rotangle;
+  float ra, dec;
+
+  unsigned long int obstime;
+  unsigned long int regtime;
+} RegImage;  /* 360 bytes / image */
+
+/* structure for Image Registration Database */
+typedef struct {
+  float sky;
+  float bias;
+  float fwhm;
+  float exptime;
+  float airmass;
+  unsigned long int obstime;
+  short int ccdnum;
+  char junk1, junk2;
+  char filter[32];
+} RufImage;  /* 60 bytes */
+
+/* Old Detrend Database structure */
+typedef struct {
+  unsigned long int tstart;
+  unsigned long int tstop;
+  unsigned long int treg;
+  float sigma, clipsigma;
+  int type;
+  int filter;
+  int ccd;
+  char filename[254];
+  char flag1, flag2;
+} DetRegOld;    /* 288 bytes */
+
+/* Detrend Database structure */
+typedef struct {
+  unsigned long int tstart;
+  unsigned long int tstop;
+  unsigned long int treg;
+  float exptime;
+  int type;
+  int filter;
+  int ccd;
+  int Nentry;
+  int Norder;
+  char mode;
+  char altpath;   /* true: data on alt db paths */
+  char dummy[58]; /* for future expansion */
+  char label[64];
+  char filename[256];
+} DetReg;    /* 416 bytes */
+
+/* Instant Zeropoint structure */
+typedef struct {
+  float ZP;                   /* measured zero point */
+  float ZPo;                  /* expected zero point */
+  float dZP;                  /* error on zero point */
+  float K;                    /* airmass term used */
+  float X;                    /* color term used */
+  unsigned long int tstart;   /* start time of observation */
+  unsigned long int tstop;    /* end time of observation */
+  short int c1;               /* photcode for color term */
+  short int c2;               /* photcode for color term */
+  short int photcode;         /* appropriate photcode */
+  char label[66];
+} OldPhotPars;    /* 100 bytes */
+
+/* Instant Zeropoint structure */
+typedef struct {
+  float ZP;                   /* measured zero point */
+  float ZPo;                  /* expected zero point */
+  float dZP;                  /* error on zero point */
+  float K;                    /* airmass term used */
+  float X;                    /* color term used */
+  unsigned long int tstart;   /* start time of observation */
+  unsigned long int tstop;    /* end time of observation */
+  short int c1;               /* photcode for color term */
+  short int c2;               /* photcode for color term */
+  short int photcode;         /* appropriate photcode */
+  char label[64];
+  short int refcode;          /* reference photometry system */
+  int Ntime;                  /* number of measurement times */
+  int Nmeas;                  /* number of data points */
+} PhotPars;    /* 108 bytes */
+
+/* average data as stored in the LONEOS database */
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm, Nn;  /* number of measurements, missing */
+  short int Xp;               /* scatter in 1/100 arcsec (-327.67 to +327.67 valid range) */
+  short int Xm;               /* chisq for primary mag [1000*value] */
+  unsigned short int code;    /* an ID code (ie, star, ghost, satelite, etc) */
+  signed int offset;          /* offset to first measurement */
+  signed int missing;         /* offset to first missing obs */
+  short int dM;               /* formal error on pri mag   [1000*log(value)] */
+  short int Xg;               /* 'best' chisq value */
+} Average; /* 32 bytes / Average */
+
+/* average data as stored in the LONEOS database -- must be translated on load */
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm, Nn;  /* number of measurements, missing */
+  short int Xp;               /* scatter in 1/100 arcsec (-327.67 to +327.67 valid range) */
+  short int Xm;               /* 1000*log(chisq) for magnitude measurement */
+  unsigned short int code;    /* an ID code (ie, star, ghost, satelite, etc) */
+  signed int offset;          /* offset to first measurement */
+  signed int missing;         /* offset to first missing obs */
+} OldAverage; /* 28 bytes / Average */
+
+/* data for individual measurement for each star */
+/* OLD LONEOS VERSION.  NOT BYTE COMPATIBLE WITH NEW VERSION 
+   (can be loaded with translation, losing the exptime,
+   and limited the number of Naverage to 0xffffff - in load_catalog) */
+typedef struct {
+  short int dR, dD;           /* 1/100 of arcsec (-327.67 to +327.67 valid range) */
+  short int M;                /* thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mcal;             /* image cal mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 to 0.255 valid range) */
+  char dophot;                /* dophot type (1-9) */
+  unsigned short int source;  /* code to identify photometry source */
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+  unsigned int average;       /* reference to corresponding average entry, upper byte of Measure.average stores flags */
+} OldMeasure; /* 20 bytes / Measure */
+
+/* data for individual measurement for each star */
+typedef struct {
+  short int dR, dD;           /* 1/100 of arcsec (-327.67 to +327.67 valid range) */
+  short int M;                /* thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mcal;             /* image cal mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mgal;             /* 'galaxy' mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  short int airmass;          /* (airmass - 1), thousandths of mag (-32.767 to 32.767 valid range) */
+  short int FWx;              /* object fwhm major axis - 1/100 of arcsec */
+  unsigned char dM;           /* thousandths of mag (0.000 to 0.255 valid range) */
+  unsigned char fwy, theta;   /* object fwhm minor/major axes ratio, angle wrt ccd X dir (0xff/360 deg precision) */
+  char dophot;                /* dophot type (1-9) */
+  unsigned short int source;  /* code to identify photometry source */
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+  unsigned int averef;        /* reference to corresponding average entry, upper byte of Measure.average stores flags */
+  short int dt;               /* exposure time in units of 2500*log(exptime) (millimags!) */
+  unsigned short int flags;   /* 16 bit-flags for various uses */ 
+} Measure; /* 32 bytes / Measure */
+
+# if (0)
+/* data for individual measurement for each star */
+typedef struct {
+  short int dR, dD;           /* 1/100 of arcsec (-327.67 to +327.67 valid range) */
+  short int M;                /* thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mcal;             /* image cal mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 to 0.255 valid range) */
+  char dophot;                /* dophot type (1-9) */
+  unsigned short int source;  /* code to identify photometry source */
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+  unsigned int averef;        /* reference to corresponding average entry, upper byte of Measure.average stores flags */
+  short int dt;               /* exposure time in units of 2500*log(exptime) (millimags!) */
+  unsigned short int flags;   /* 16 bit-flags for various uses */ 
+} Measure; /* 24 bytes / Measure */
+# endif
+
+/* data on missing stars */
+typedef struct {
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+} Missing; /* 4 byte / Missing */
+
+/* data on missing stars */
+typedef struct {
+  short int M;                /* other mags - thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Xm;               /* chisq on alt mag */
+  short int dM;               /* scatter on alt mag */
+} SecFilt; /* 6 byte / SecFilt */
+
+/* data on missing stars */
+typedef struct {
+  short int M;                /* other mags - thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Xm;               /* chisq on alt mag */
+} OldSecFilt; /* 4 byte / SecFilt */
+
+/* a catalog contains this data */
+typedef struct {
+  /* data in the file: */
+  Average *average;
+  Measure *measure; 
+  Missing *missing; 
+  SecFilt *secfilt;
+  Header  header;
+  int Naverage, Nmeasure, Nmissing, Nsecfilt;
+  /* description of the catalog file: */
+  char *filename;
+  int lockmode;
+  FILE *f;
+  /* pointers for data manipulation */
+  int *found;
+  int *image;
+  int *mosaic;
+  float *X;
+  float *Y;
+} Catalog;
+
+/* the standard astrometric coordinates structure */
+typedef struct {
+  double   crval1, crval2;
+  float    crpix1, crpix2;
+  float    cdelt1, cdelt2;
+  float    pc1_1, pc1_2;
+  float    pc2_1, pc2_2;
+  float    polyterms[7][2];
+  char     ctype[15];
+  char     Npolyterms;
+} Coords;  /* 120 bytes / Coords */
+
+typedef struct {
+  unsigned short int code;   /* code number (stored in Measure.source) */
+  char name[32];             /* name for filter combination */
+  char type;                 /* primary, secondary, dependent, reference */
+  short int C, dC, dX;       /* primary phot calibration terms (millimags) */
+  float K;                   /* secondary phot calibration terms (millimags) */
+  int  c1, c2;               /* color is average.M[c1] - average.M[c2] */
+  int  equiv;                /* this dependent filter is equivalent to equiv primary/secondary */
+  int  Nc;                   /* number of color terms */
+  float X[4];                /* color terms X[0]*mc + X[1]*mc^2 + X[2]*mc^3, etc */
+} PhotCode;
+
+typedef struct {
+  int Ncode;
+  int Nsecfilt;
+  int hashcode[0x10000];
+  int hashNsec[0x10000];
+  PhotCode *code;
+} PhotCodeData;
+
+/* image structure for binary data storage of image data */
+typedef struct {
+  Coords         coords;            /* 120 bytes */
+  unsigned int   tzero;             /* readout time row 0 in sec (0 - 142 years valid range) */
+  unsigned int   nstar;             /* number of stars on image */
+  short int      secz;              /* thousanths of airmass (valid range -32.000 -- 32.000) */
+  short int      NX, NY;            /* dimensions of image */
+  short int      apmifit, dapmifit; /* aperture correction and error in thousandths of mag */
+  short int      source;            /* identifier for CCD (each ever used will have a unique letter) */
+  short int      Mcal;              /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      dMcal;             /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      Xm;                /* 10*log(image chi-square) */
+  char           name[32];          /* name of original image */
+  unsigned char  detection_limit;   /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  saturation_limit;  /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  cerror;            /* astrometric error: 1/50 of arcsec (0 -- 5.12 valid range) */
+  unsigned char  fwhm_x, fwhm_y;    /* PSF terms in 25*arcsec (valid range 0.0 -- 10.2" ") */
+  unsigned char  trate;             /* 10000 * scan rate in sec/pix (0 -- 0.0256 valid range, 
+				       typically 0.0146. this is used only to determine the time
+				       of the observation, not to find the coordinates.  1 byte
+				       gives 0.11 sec accuracy */
+  float          exptime;           /* exposure time, seconds */
+  char           code;              /* flag to mark an image as bad or whatever */
+  unsigned char  ccdnum;            /* mosaic CCD ID number (IMAGEID) */ 
+  char           dummy[20];         /* extra space for the future */
+  short int      order;             /* number of terms used for Mrel */
+  short int      Mx, My;
+  short int      Mxx, Mxy, Myy;
+  short int      Mxxx, Mxxy, Mxyy, Myyy;
+  short int      Mxxxx, Mxxxy, Mxxyy, Mxyyy, Myyyy;
+} Image;  /* 240 bytes / Image */
+/* Image needs to be aligned with 8-byte boundaries on Suns */
+
+/**** prototypes ****/
+
+int lock_catalog (Catalog *catalog, int lockmode);
+int unlock_catalog (Catalog *catalog);
+int load_catalog (Catalog *catalog, char mode, int VERBOSE);
+int save_catalog (Catalog *catalog, char VERBOSE);
+Measure *FixOldMeasure (OldMeasure *in, int Nvalues);
+Average *FixOldAverage (OldAverage *in, int Nvalues);
+SecFilt *FixOldSecFilt (OldSecFilt *in, int Nvalues);
+
+int  XY_to_RD (double *ra, double *dec, double x,  double y,   Coords *coords);
+int  RD_to_XY (double *x,  double *y,   double ra, double dec, Coords *coords);
+int  fXY_to_RD (float *ra, float *dec, double x,  double y,   Coords *coords);
+int  fRD_to_XY (float *x,  float *y,   double ra, double dec, Coords *coords);
+int  GetCoords (Coords *coords, Header *header);
+short int putMi (double value);
+double getMi (short int value);
+void returnMcal (Image *image, double *c);
+void assignMcal (Image *image, double *c, int order);
+double applyMcal (Image *image, double x, double y);
+double findscatter (double *X, double *Y, double *M, double *dM, int N, double *c, int order);
+
+PhotCode *GetPhotcodebyName (char *name);
+PhotCode *GetPhotcodeEquivbyName (char *name);
+PhotCode *GetPhotcodebyCode (int code);
+PhotCode *GetPhotcodeEquivbyCode (int code);
+char *GetPhotcodeNamebyCode (int code);
+
+double PhotInst (Measure *measure);
+double PhotAbs (Measure *measure);
+double PhotCat (Measure *measure);
+double PhotSys (Measure *measure, Average *average, SecFilt *secfilt);
+double PhotRel (Measure *measure, Average *average, SecFilt *secfilt);
+double PhotCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
+double PhotAve (PhotCode *code, Average *average, SecFilt *secfilt);
+double PhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure);
+double PhotXm (PhotCode *code, Average *average, SecFilt *secfilt);
+double PhotdM (PhotCode *code, Average *average, SecFilt *secfilt);
+
+short iPhotInst (Measure *measure);
+short iPhotAbs (Measure *measure);
+short iPhotCat (Measure *measure);
+short iPhotSys (Measure *measure, Average *average, SecFilt *secfilt);
+short iPhotRel (Measure *measure, Average *average, SecFilt *secfilt);
+short iPhotCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
+short iPhotAve (PhotCode *code, Average *average, SecFilt *secfilt);
+short iPhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure);
+short iPhotXm (PhotCode *code, Average *average, SecFilt *secfilt);
+short iPhotdM (PhotCode *code, Average *average, SecFilt *secfilt);
+
+short iPhotColor (Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
+int PhotColor (Average *average, SecFilt *secfilt, Measure *measure, int c1, int c2, double *color);
+
+int LoadPhotcodes (char *filename);
+int GetPhotcodeCodebyName (char *name);
+int GetPhotcodeEquivCodebyName (char *name);
+int GetPhotcodeEquivCodebyCode (int code);
+int GetPhotcodeNsec (int code);
+int GetPhotcodeNsecfilt ();
+void SetZeroPoint (double ZP);
+int *GetPhotcodeEquivList (int code, int *nlist);
+void ParseColorTerms (char *terms, float *X, int *N);
+
+void coords_precess (double *ra, double *dec, double in_epoch, double out_epoch);
+
+# endif
Index: /tags/start/Ohana/src/libohana/include/ohana.h
===================================================================
--- /tags/start/Ohana/src/libohana/include/ohana.h	(revision 12606)
+++ /tags/start/Ohana/src/libohana/include/ohana.h	(revision 12606)
@@ -0,0 +1,148 @@
+# include <stdio.h>
+# include <fcntl.h>
+# include <malloc.h>
+# include <math.h>
+# include <errno.h>
+# include <time.h>
+# include <memory.h>
+# include <stdlib.h>
+# include <string.h>
+# include <sys/socket.h>
+# include <sys/time.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <sys/uio.h>
+# include <sys/un.h>
+# include <unistd.h>
+# include <stdarg.h> 
+# include <readline/history.h>
+# include <readline/readline.h>
+
+/* OHANA included stuff */
+# include <fitsio.h>              
+
+# ifndef OHANA_H
+# define OHANA_H
+
+extern double hypot();
+
+# define TRUE (1)
+# define FALSE (0)
+# define SIGN(X)  (((X) == 0) ? 0 : ((fabs((double)(X))) / (X)))
+# define ROUND(X) ((int) ((X) + 0.5*SIGN(X)))
+# define SQR(X)   (double) (((double)(X))*((double)(X)))
+# define SQ(X)    (double) (((double)(X))*((double)(X)))
+# define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+# define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+# define SWAP(X,Y) {double tmp=(X); (X) = (Y); (Y) = tmp;}
+
+# define LCK_UNLOCK  0   /* file is unlocked */
+# define LCK_ACCESS  1   /* can't get access to file */
+# define LCK_TIMEOUT 2   /* timeout setting lock */
+# define LCK_HARDLCK 3   /* error setting hard lockfile */
+# define LCK_HUNLOCK 4   /* error clearing hard lockfile */
+
+# define LCK_EMPTY   5   /* locked file is empty */
+# define LCK_FULL    6   /* locked file is not empty */
+# define LCK_UNKNOWN 7   /* can't stat file to get size */
+
+# define LCK_SOFT    10  /* soft lock */
+# define LCK_HARD    11  /* hard lock */
+# define LCK_XCLD    12  /* exclusive soft lock */
+
+# ifndef M_PI
+# define M_PI 3.14159265358979323846264
+# endif
+
+int setlockfile2 (char *filename, double timeout, int type, int *state);
+int clearlockfile2 (char *filename, int fd, int type, int *state);
+
+FILE *fsetlockfile (char *filename, double timeout, int type, int *state);
+int fclearlockfile (char *filename, FILE *f, int type, int *state);
+
+# ifndef PROTO
+#   define PROTO(A) A
+# endif
+
+/* 
+# else
+#   ifndef PROTO
+#   define PROTO(A) ()
+#   endif
+# include <varargs.h>
+# endif
+*/
+
+# ifndef ALLOCATE
+# define ALLOCATE(X,T,S)  \
+  X=(T *)malloc((unsigned) (MAX(((S)*sizeof(T)),1)));\
+  if(X==NULL) \
+    { \
+      fprintf(stderr,"failed to malloc X\n");\
+        exit (10);\
+    } 
+# define REALLOCATE(X,T,S) \
+  X=(T *)realloc(X,(unsigned) (MAX(((S)*sizeof(T)),1))); \
+  if(X==NULL) \
+    { \
+       fprintf(stderr,"failed to realloc X\n"); \
+       exit (10); \
+    }
+# endif /* ALLOCATE */
+
+# ifndef FOPEN 
+# define FOPEN(F,NAME) \
+  F = fopen (NAME, "r"); \
+  if (F == NULL) { \
+    fprintf (stderr, "failed to open %s\n", NAME); \
+    exit (0); \
+  }
+# endif /* FOPEN */
+
+# define DEG_RAD 57.295779513082322
+# define RAD_DEG  0.017453292519943
+
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+
+/* in string.c */
+int   stripwhite (char *string);
+int   strnumcmp (char *str1, char *str2);
+char *strcreate (char *string);
+char *strncreate (char *string, int n);
+int   scan_line (FILE *f, char *line); 
+int   dparse (double *X, int NX, char *line);
+int   fparse (float *X, int NX, char *line);
+int   get_argument (int argc, char **argv, char *arg);
+int   remove_argument (int N, int *argc, char **argv);
+
+int   Fread (void *ptr, int size, int nitems, FILE *f, char *type);
+int   Fwrite (void *ptr, int size, int nitems, FILE *f, char *type);
+int   ByteSwap (char *ptr, int size, int nitems, char *type);
+int   ConvertStruct (char *buffer, int size, int Nbytes, char *type);
+
+char *pathname (char *name);
+char *filebasename (char *name);
+char *filerootname (char *name);
+char *findexec (int argc, char **argv);
+int mkdirhier (char *path);
+
+FILE *fsetlockfile (char *filename, double timeout, int type, int *state);
+int fclearlockfile (char *filename, FILE *f, int type, int *state);
+int setlockfile2 (char *filename, double timeout, int type, int *state);
+int clearlockfile2 (char *filename, int fd, int type, int *state);
+
+char *SelectConfigFile (int *argc, char **argv, char *progname);
+char *LoadConfigFile (char *filename);
+char *ScanConfig (char *config, char *field, char *mode, int N,...);
+char *expandline (char *line, char *config);
+char *fileextname (char *file);
+char *LoadRawConfigFile (char *, int);
+
+/*
+#   define F_SETFL         4   
+#   define O_NONBLOCK      0200000  
+#   define AF_UNIX         1          
+#   define SOCK_STREAM     1
+*/
+
+# endif
Index: /tags/start/Ohana/src/libohana/src/Fread.c
===================================================================
--- /tags/start/Ohana/src/libohana/src/Fread.c	(revision 12606)
+++ /tags/start/Ohana/src/libohana/src/Fread.c	(revision 12606)
@@ -0,0 +1,466 @@
+# include <stdio.h>
+# include <string.h>
+int   ByteSwap (char *ptr, int size, int nitems, char *type);
+int   ConvertStruct (char *buffer, int size, int Nbytes, char *type);
+
+# define BYTE_EXCHANGE(X,Y) tmp = byte[X]; byte[X] = byte[Y]; byte[Y] = tmp;
+# define SWAP_BYTE(X) \
+  tmp = byte[X+0]; byte[X+0] = byte[X+1]; byte[X+1] = tmp;
+# define SWAP_WORD(X) \
+  tmp = byte[X+0]; byte[X+0] = byte[X+3]; byte[X+3] = tmp; \
+  tmp = byte[X+1]; byte[X+1] = byte[X+2]; byte[X+2] = tmp;
+# define SWAP_DBLE(X) \
+  tmp = byte[X+0]; byte[X+0] = byte[X+7]; byte[X+7] = tmp; \
+  tmp = byte[X+1]; byte[X+1] = byte[X+6]; byte[X+6] = tmp; \
+  tmp = byte[X+2]; byte[X+2] = byte[X+5]; byte[X+5] = tmp; \
+  tmp = byte[X+3]; byte[X+3] = byte[X+4]; byte[X+4] = tmp;
+# define IMAGE_SIZE 240
+# define OLDAVERAGE_SIZE 28
+# define AVERAGE_SIZE 32
+# define OLDMEASURE_SIZE 20
+# define MEASURE_SIZE 32
+# define MISSING_SIZE 4
+# define OLDSECFILT_SIZE 4
+# define SECFILT_SIZE 6
+# define REGIMAGE_SIZE 360
+# define SPECTRUM_SIZE 216
+# define RUFIMAGE_SIZE 60
+# define OLDDETREG_SIZE 288
+# define DETREG_SIZE 416
+# define PHOTPARS_SIZE 108
+# define OLDPHOTPARS_SIZE 100
+# define TRUE 1
+# define FALSE 0
+
+# ifdef linux
+# define BYTE_SWAP
+# endif
+
+# ifdef sid
+# define BYTE_SWAP
+# endif
+
+/* add other architectures here, ie dec, alpha, etc */ 
+# ifdef dec
+# define BYTE_SWAP
+# endif
+
+int Fread (char *ptr, int size, int nitems, FILE *f, char *type) {
+
+  int valid, status;
+
+  status = fread (ptr, size, nitems, f);
+
+  valid = ByteSwap (ptr, size, nitems, type);
+
+  if (!valid) return (FALSE);
+  return (status);
+}
+
+int Fwrite (char *ptr, int size, int nitems, FILE *f, char *type) {
+
+  int valid, status;
+
+  valid = ByteSwap (ptr, size, nitems, type);
+
+  if (!valid) return (FALSE);
+
+  status = fwrite (ptr, size, nitems, f);
+  return (status);
+}
+
+int ConvertStruct (char *buffer, int size, int nitems, char *type) {
+
+  int status; 
+  status = ByteSwap (buffer, size, nitems, type);
+  return (status);
+}
+
+int ByteSwap (char *ptr, int size, int nitems, char *type) {
+
+# ifdef BYTE_SWAP
+
+  int i, j, valid;
+  unsigned char *byte, *byte0, *byte1, *byte2, *byte3, *byte4, *byte5, *byte6, *byte7, tmp;
+
+  valid = FALSE;
+  if (!strcmp (type, "char")) {
+    valid = TRUE;
+  }
+
+  if (!strcmp (type, "short")) {
+    byte0 = (char *)ptr;
+    byte1 = (char *)ptr + 1;
+    for (i = 0; i < nitems; i++, byte0 += 2, byte1 += 2) {
+      tmp = *byte0;
+      *byte0 = *byte1;
+      *byte1 = tmp;
+    }
+    valid = TRUE;
+  }
+
+  if (!strcmp (type, "int") || !strcmp (type, "float")) {
+    byte0 = (char *)ptr;
+    byte1 = (char *)ptr + 1;
+    byte2 = (char *)ptr + 2;
+    byte3 = (char *)ptr + 3;
+    for (i = 0; i < nitems; i++, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+      tmp = *byte0;
+      *byte0 = *byte3;
+      *byte3 = tmp;
+      tmp = *byte1;
+      *byte1 = *byte2;
+      *byte2 = tmp;
+    }
+    valid = TRUE;
+  }
+
+  if (!strcmp (type, "double")) {
+    byte0 = (char *)ptr;
+    byte1 = (char *)ptr + 1;
+    byte2 = (char *)ptr + 2;
+    byte3 = (char *)ptr + 3;
+    byte4 = (char *)ptr + 4;
+    byte5 = (char *)ptr + 5;
+    byte6 = (char *)ptr + 6;
+    byte7 = (char *)ptr + 7;
+    for (i = 0; i < nitems; i++, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
+      tmp = *byte0;
+      *byte0 = *byte7;
+      *byte7 = tmp;
+      tmp = *byte1;
+      *byte1 = *byte6;
+      *byte6 = tmp;
+      tmp = *byte1;
+      *byte2 = *byte5;
+      *byte5 = tmp;
+      tmp = *byte1;
+      *byte3 = *byte4;
+      *byte4 = tmp;
+    }
+    valid = TRUE;
+  }
+
+  if (!strcmp (type, "average")) {
+    if (size != AVERAGE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Average) %d vs %d\n", size, AVERAGE_SIZE);
+      return (0);
+    }
+    byte = (char *)ptr;
+    for (i = 0; i < nitems; i++, byte += AVERAGE_SIZE) {
+      SWAP_WORD (0);   /* R */
+      SWAP_WORD (4);   /* D */
+      SWAP_BYTE (8);   /* M */
+      SWAP_BYTE (10);  /* Nm */
+      SWAP_BYTE (12);  /* Nn */
+      SWAP_BYTE (14);  /* Xp */
+      SWAP_BYTE (16);  /* Xm */
+      SWAP_BYTE (18);  /* code */
+      SWAP_WORD (20);  /* offset */
+      SWAP_WORD (24);  /* missing */
+      SWAP_BYTE (28);  /* dM */
+      SWAP_BYTE (30);  /* Xg */
+    }
+    valid = TRUE;
+  } 
+
+  if (!strcmp (type, "oldaverage")) {
+    if (size != OLDAVERAGE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (OldAverage) %d vs %d\n", size, OLDAVERAGE_SIZE);
+      return (0);
+    }
+    byte = (char *)ptr;
+    for (i = 0; i < nitems; i++, byte += OLDAVERAGE_SIZE) {
+      SWAP_WORD (0);   /* R */
+      SWAP_WORD (4);   /* D */
+      SWAP_BYTE (8);   /* M */
+      SWAP_BYTE (10); /* Nm */
+      SWAP_BYTE (12); /* Nn */
+      SWAP_BYTE (14); /* Xp */
+      SWAP_BYTE (16); /* Xm */
+      SWAP_BYTE (18); /* code */
+      SWAP_WORD (20); /* offset */
+      SWAP_WORD (24); /* missing */
+    }
+    valid = TRUE;
+  } 
+
+  if (!strcmp (type, "regimage")) {
+    if (size != REGIMAGE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (RegImage) %d vs %d\n", size, REGIMAGE_SIZE);
+      return (0);
+    }
+    byte = (char *)ptr;
+    for (i = 0; i < nitems; i++, byte += REGIMAGE_SIZE) {
+      SWAP_WORD (284); /* exptime */ 
+      SWAP_WORD (288); /* airmass */ 
+      SWAP_WORD (292); /* sky */     
+      SWAP_WORD (296); /* bias */    
+      SWAP_WORD (300); /* fwhm */    
+      SWAP_WORD (304); /* telfocus */ 
+      SWAP_WORD (308); /* xprobe */ 
+      SWAP_WORD (312); /* yprobe */ 
+      SWAP_WORD (316); /* zprobe */ 
+      SWAP_WORD (320); /* dettemp */ 
+      SWAP_WORD (324); /* teltemp[0] */ 
+      SWAP_WORD (328); /* teltemp[1] */  
+      SWAP_WORD (332); /* teltemp[2] */ 
+      SWAP_WORD (336); /* teltemp[3] */ 
+      SWAP_WORD (340); /* rotangle */
+      SWAP_WORD (344); /* ra */      
+      SWAP_WORD (348); /* dec */     
+      SWAP_WORD (352); /* obstime */ 
+      SWAP_WORD (356); /* regtime */  
+    }
+    valid = TRUE;
+  }
+
+  if (!strcmp (type, "spectrum")) {
+    if (size != SPECTRUM_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Spectrum) %d vs %d\n", size, SPECTRUM_SIZE);
+      return (0);
+    }
+    byte = (char *)ptr;
+    for (i = 0; i < nitems; i++, byte += SPECTRUM_SIZE) {
+      SWAP_WORD (0);  /* ra */ 
+      SWAP_WORD (4);  /* dec */ 
+      SWAP_WORD (8);  /* exptime */ 
+      SWAP_WORD (12); /* airmass */ 
+      SWAP_WORD (16); /* Ws */ 
+      SWAP_WORD (20); /* We */ 
+      SWAP_WORD (24); /* dW */ 
+      SWAP_WORD (28); /* Nspec */ 
+      SWAP_WORD (32); /* obstime */ 
+      SWAP_WORD (36); /* regtime */ 
+    }
+    valid = TRUE;
+  }
+
+  if (!strcmp (type, "rufimage")) {
+    if (size != RUFIMAGE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (RufImage) %d vs %d\n", size, RUFIMAGE_SIZE);
+      return (0);
+    }
+    byte = (char *)ptr;
+    for (i = 0; i < nitems; i++, byte += RUFIMAGE_SIZE) {
+      SWAP_WORD (0);   /* sky */
+      SWAP_WORD (4);   /* bias */
+      SWAP_WORD (8);  /* fwhm */
+      SWAP_WORD (12); /* exptime */
+      SWAP_WORD (16); /* airmass */
+      SWAP_WORD (20); /* obstime */
+      SWAP_BYTE (24); /* ccdnum */
+    }
+    valid = TRUE;
+  }
+
+  if (!strcmp (type, "olddetreg")) {
+    if (size != OLDDETREG_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (DetReg) %d vs %d\n", size, OLDDETREG_SIZE);
+      return (0);
+    }
+    byte = (char *)ptr;
+    for (i = 0; i < nitems; i++, byte += OLDDETREG_SIZE) {
+      SWAP_WORD (0);   /* tstart */
+      SWAP_WORD (4);   /* tstop */
+      SWAP_WORD (8);   /* treg */
+      SWAP_WORD (12);  /* sigma */
+      SWAP_WORD (16);  /* clipsigma */
+      SWAP_WORD (20);  /* type */
+      SWAP_WORD (24);  /* filter */
+      SWAP_WORD (28);  /* ccd */
+    }
+    valid = TRUE;
+  }
+
+  if (!strcmp (type, "detreg")) {
+    if (size != DETREG_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (DetReg) %d vs %d\n", size, DETREG_SIZE);
+      return (0);
+    }
+    byte = (char *)ptr;
+    for (i = 0; i < nitems; i++, byte += DETREG_SIZE) {
+      SWAP_WORD (0);   /* tstart */
+      SWAP_WORD (4);   /* tstop */
+      SWAP_WORD (8);   /* treg */
+      SWAP_WORD (12);  /* exptime */
+      SWAP_WORD (16);  /* type */
+      SWAP_WORD (20);  /* filter */
+      SWAP_WORD (24);  /* ccd */
+      SWAP_WORD (28);  /* Nentry */
+      SWAP_WORD (32);  /* Norder */
+    }
+    valid = TRUE;
+  }
+
+  if (!strcmp (type, "oldphotpars")) {
+    if (size != OLDPHOTPARS_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (OldPhotPars) %d vs %d\n", size, OLDPHOTPARS_SIZE);
+      return (0);
+    }
+    byte = (char *)ptr;
+    for (i = 0; i < nitems; i++, byte += OLDPHOTPARS_SIZE) {
+      SWAP_WORD (0);    /* ZP */
+      SWAP_WORD (4);    /* ZPo */
+      SWAP_WORD (8);    /* dZP */
+      SWAP_WORD (12);   /* K */
+      SWAP_WORD (16);   /* A */
+      SWAP_WORD (20);   /* tstart */
+      SWAP_WORD (24);   /* tstop */
+      SWAP_BYTE (28);   /* c1 */
+      SWAP_BYTE (30);   /* c2 */
+      SWAP_BYTE (32);   /* photcode */
+    }
+    valid = TRUE;
+  }
+
+  if (!strcmp (type, "photpars")) {
+    if (size != PHOTPARS_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (PhotPars) %d vs %d\n", size, PHOTPARS_SIZE);
+      return (0);
+    }
+    byte = (char *)ptr;
+    for (i = 0; i < nitems; i++, byte += PHOTPARS_SIZE) {
+      SWAP_WORD (0);    /* ZP */
+      SWAP_WORD (4);    /* ZPo */
+      SWAP_WORD (8);    /* dZP */
+      SWAP_WORD (12);   /* K */
+      SWAP_WORD (16);   /* A */
+      SWAP_WORD (20);   /* tstart */
+      SWAP_WORD (24);   /* tstop */
+      SWAP_BYTE (28);   /* c1 */
+      SWAP_BYTE (30);   /* c2 */
+      SWAP_BYTE (32);   /* photcode */
+      SWAP_WORD (100);   /* Ntime */
+      SWAP_WORD (104);   /* Nmeas */
+    }
+    valid = TRUE;
+  }
+
+  if (!strcmp (type, "oldmeasure")) {
+    if (size != OLDMEASURE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (OldMeasure) %d vs %d\n", size, OLDMEASURE_SIZE);
+      return (0);
+    }
+    byte = (char *)ptr;
+    for (i = 0; i < nitems; i++, byte += OLDMEASURE_SIZE) {
+      SWAP_BYTE (0);   /* dR */
+      SWAP_BYTE (2);   /* dD */
+      SWAP_BYTE (4);   /* M  */
+      SWAP_BYTE (6);   /* Mcal */
+      SWAP_BYTE (10);  /* source */
+      SWAP_WORD (12);  /* t */
+      SWAP_WORD (16);  /* average */
+    }
+    valid = TRUE;
+  }
+
+  if (!strcmp (type, "measure")) {
+    if (size != MEASURE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Measure) %d vs %d\n", size, MEASURE_SIZE);
+      return (0);
+    }
+    byte = (char *)ptr;
+    for (i = 0; i < nitems; i++, byte += MEASURE_SIZE) {
+      SWAP_BYTE (0);   /* dR */
+      SWAP_BYTE (2);   /* dD */
+      SWAP_BYTE (4);   /* M  */
+      SWAP_BYTE (6);   /* Mcal */
+      SWAP_BYTE (8);   /* Mgal */
+      SWAP_BYTE (10);  /* Map  */
+      SWAP_BYTE (12);  /* FWx */
+      /* 14, 15, 16, 17 - char */
+      SWAP_BYTE (18);  /* source */
+      SWAP_WORD (20);  /* t */
+      SWAP_WORD (24);  /* averef */
+      SWAP_BYTE (28);  /* dt */
+      SWAP_BYTE (30);  /* flags */
+    }
+    valid = TRUE;
+  }
+
+  if (!strcmp (type, "secfilt")) {
+    if (size != SECFILT_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (SecFilt) %d vs %d\n", size, SECFILT_SIZE);
+      return (0);
+    }
+    byte = (char *) ptr;
+    for (i = 0; i < nitems; i++, byte += SECFILT_SIZE) {
+      SWAP_BYTE (0);   /* M */
+      SWAP_BYTE (2);   /* Xm */
+      SWAP_BYTE (4);   /* dM */
+    }
+    valid = TRUE;
+  }
+
+  if (!strcmp (type, "oldsecfilt")) {
+    if (size != OLDSECFILT_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (OldSecFilt) %d vs %d\n", size, OLDSECFILT_SIZE);
+      return (0);
+    }
+    byte = (char *) ptr;
+    for (i = 0; i < nitems; i++, byte += OLDSECFILT_SIZE) {
+      SWAP_BYTE (0);   /* M */
+      SWAP_BYTE (2);   /* Xm */
+    }
+    valid = TRUE;
+  }
+
+  if (!strcmp (type, "missing")) {
+    if (size != MISSING_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Missing) %d vs %d\n", size, MISSING_SIZE);
+      return (0);
+    }
+    byte0 = (char *)ptr;
+    byte1 = (char *)ptr + 1;
+    byte2 = (char *)ptr + 2;
+    byte3 = (char *)ptr + 3;
+    for (i = 0; i < nitems; i++, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+      tmp = *byte0;
+      *byte0 = *byte3;
+      *byte3 = tmp;
+      tmp = *byte1;
+      *byte1 = *byte2;
+      *byte2 = tmp;
+    }
+    valid = TRUE;
+  }
+
+  if (!strcmp (type, "image")) {
+    if (size != IMAGE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Image) %d vs %d\n", size, IMAGE_SIZE);
+      return (0);
+    }
+    byte = (char *)ptr;
+    for (i = 0; i < nitems; i++, byte += IMAGE_SIZE) {
+      SWAP_DBLE (0); /* coords.crval1 */
+      SWAP_DBLE (8); /* coords.crval2 */
+      for (j = 16; j < 104; j+=4) { /* coords.crpix, delt, pc_ij, polyterms[7][2] */
+	SWAP_WORD (j);
+      }
+      SWAP_WORD (120); /* tzero */
+      SWAP_WORD (124); /* nstar */
+      for (j = 128; j < 146; j+=2) { /* sec z, NX, NY, apmifit, dapmifit, source, Mcal, dMcal, Xm */
+	SWAP_BYTE (j);
+      }
+      SWAP_WORD (184); /* exptime */
+      SWAP_WORD (210); /* order */
+      for (j = 212; j < 240; j+=2) {
+	SWAP_BYTE (j); /* Mx - Myyy */
+      }
+    }
+    valid = TRUE;
+  }
+
+  if (!valid) 
+    fprintf (stderr, "unknown type %s\n", type);
+
+  return (valid);
+
+# else
+
+  return (TRUE);
+
+# endif 
+
+}
Index: /tags/start/Ohana/src/libohana/src/LoadPhotcodes.c
===================================================================
--- /tags/start/Ohana/src/libohana/src/LoadPhotcodes.c	(revision 12606)
+++ /tags/start/Ohana/src/libohana/src/LoadPhotcodes.c	(revision 12606)
@@ -0,0 +1,793 @@
+# include <ohana.h>
+# include <loneos.h>
+
+# define NCTERMS 4
+
+static PhotCodeData *photcodes = NULL;
+static double ZERO_POINT;
+static short int iZERO_POINT;
+static short int Nseclist[0x10000];
+
+void SetZeroPoint (double ZP) {
+  ZERO_POINT = ZP;
+  iZERO_POINT = 1000 * ZP;
+}
+
+int LoadPhotcodes (char *filename) {
+  
+  FILE *f;
+  int i, Ns, Np, NPHOTCODE, Npri, Nfield;
+  PhotCode *photcode;
+  int code;
+  char *c;
+  char line[256];
+  char name[32], type[32], Zero[32], Airmass[32], Offset[32],
+    C1[32], C2[32], Slope[32], Color[32], Primary[32];
+  int c1, c2;
+
+  /* allocate space to photcode table, free existing data */
+  if (photcodes == NULL) {
+    ALLOCATE (photcodes, PhotCodeData, 1);
+    photcodes[0].code = NULL;
+  }
+  if (photcodes[0].code != NULL) free (photcodes[0].code);
+
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    photcodes[0].Ncode    = 0;
+    photcodes[0].Nsecfilt = 0;
+    photcodes[0].code     = (PhotCode *) NULL;
+    return (FALSE);
+  }
+
+  Np = 0;
+  NPHOTCODE = 10;
+  ALLOCATE (photcode, PhotCode, NPHOTCODE);
+  photcodes[0].Nsecfilt = 0;
+  for (i = 0; i < 0x10000; i++) {
+    photcodes[0].hashcode[i] = -1;
+    photcodes[0].hashNsec[i] = -1;
+  }
+
+  while (scan_line (f, line) != EOF) {
+    for (c = line; isspace (*c); c++);
+    if (*c == '#') continue;
+    Nfield = sscanf (c, "%d %s %s %s %s %s %s %s %s %s %s", 
+		     &code, name, type, Zero, Airmass, Offset, C1, C2, Slope, Color, Primary);
+    if (Nfield != 11) { continue; }
+    
+    c1 = atof (C1);
+    c2 = atof (C2);
+    if (!strcmp (C1, "-")) { c1 = 0; }
+    if (!strcmp (C2, "-")) { c2 = 0; }
+
+    photcode[Np].type = 0;
+    photcode[Np].code = code;
+    strcpy (photcode[Np].name, name);
+    if (!strncasecmp (type, "pri", 3)) {
+      photcode[Np].type  = PHOT_PRI;
+      photcode[Np].C     = 1000*atof (Zero);
+      photcode[Np].K     = atof (Airmass);
+      photcode[Np].dC    = 1000*atof (Offset);
+      photcode[Np].dX    = 1000*atof (Color);
+      photcode[Np].c1    = c1;
+      photcode[Np].c2    = c2;
+      photcode[Np].equiv = atoi (Primary);
+      ParseColorTerms (Slope, photcode[Np].X, &photcode[Np].Nc);
+      Nseclist[0] = Np;
+    }      
+    if (!strncasecmp (type, "sec", 3)) {
+      photcode[Np].type  = PHOT_SEC;
+      photcode[Np].C     = 1000*atof (Zero);
+      photcode[Np].K     = atof (Airmass);
+      photcode[Np].dC    = 1000*atof (Offset);
+      photcode[Np].dX    = 1000*atof (Color);
+      photcode[Np].c1    = c1;
+      photcode[Np].c2    = c2;
+      photcode[Np].equiv = atoi (Primary);
+      photcodes[0].Nsecfilt ++;
+      ParseColorTerms (Slope, photcode[Np].X, &photcode[Np].Nc);
+      Nseclist[photcodes[0].Nsecfilt] = Np;
+    }      
+    if (!strncasecmp (type, "dep", 3)) {
+      photcode[Np].type  = PHOT_DEP;
+      photcode[Np].C     = 1000*atof (Zero);    /* zero point in millimags */
+      photcode[Np].K     = atof (Airmass);      /* airmass coeff (millimag / millimag) */
+      photcode[Np].dC    = 1000*atof (Offset);  /* color ref z.p. (millimag) */
+      photcode[Np].dX    = 1000*atof (Color);   /* average color (millimag) */
+      photcode[Np].c1    = c1;
+      photcode[Np].c2    = c2;
+      photcode[Np].equiv = atoi (Primary);
+      ParseColorTerms (Slope, photcode[Np].X, &photcode[Np].Nc);
+    }      
+    if (!strncasecmp (type, "ref", 3)) {
+      photcode[Np].type  = PHOT_REF;
+      photcode[Np].C     = 0;
+      photcode[Np].K     = 0;
+      photcode[Np].dC    = 0;
+      photcode[Np].dX    = 0;
+      photcode[Np].c1    = 0;
+      photcode[Np].c2    = 0;
+      photcode[Np].equiv = 0;
+      photcode[Np].X[0]  = 0;
+      photcode[Np].Nc    = 0;
+    }
+
+    /* alt photcodes are a little different: they have the SAME photcode as an existing
+       pri/sec photcode, but define an alternate transformation for that code */
+    if (!strncasecmp (type, "alt", 3)) {
+      photcode[Np].type  = PHOT_ALT;
+      photcode[Np].C     = 1000*atof (Zero);    /* zero point in millimags */
+      photcode[Np].K     = atof (Airmass);      /* airmass coeff (millimag / millimag) */
+      photcode[Np].dC    = 1000*atof (Offset);  /* color ref z.p. (millimag) */
+      photcode[Np].dX    = 1000*atof (Color);   /* average color (millimag) */
+      photcode[Np].c1    = c1;
+      photcode[Np].c2    = c2;
+      photcode[Np].equiv = atoi (Primary);
+      ParseColorTerms (Slope, photcode[Np].X, &photcode[Np].Nc);
+    }
+    if (!photcode[Np].type) {
+      fprintf (stderr, "error in Photfile: unknown type %s\n", type);
+    }
+
+    Np++;
+    if (Np == NPHOTCODE) {
+      NPHOTCODE += 10;
+      REALLOCATE (photcode, PhotCode, NPHOTCODE);
+    }
+  }
+  fclose (f);
+  
+  /* set up hashcode for photcode refs:
+   * the hashcode gives the structure sequence for a given photcode:
+   * photcode[i].hashcode[photcode[i].code] == i
+   */
+
+  Ns = 0;
+  for (i = 0; i < Np; i++) {
+    if (photcode[i].type == PHOT_ALT) continue; /* no hashcode for ALT codes */
+    if (photcodes[0].hashcode[photcode[i].code] != -1) {
+      fprintf (stderr, "duplicate photcodes in file\n");
+      free (photcode);
+      return (FALSE);
+    }
+    photcodes[0].hashcode[photcode[i].code] = i;
+    if (photcode[i].type == PHOT_SEC) {
+      photcodes[0].hashNsec[photcode[i].code] = Ns;
+      Ns ++;
+    }
+  }
+  /* validity check for references */
+  for (i = 0; i < Np; i++) {
+    if (photcode[i].type == PHOT_DEP) {
+      Npri = photcodes[0].hashcode[photcode[i].equiv];
+      if ((Npri >= Np) || (Npri < 0)) {
+	fprintf (stderr, "reference for dependent photcode is not in photcodes\n");
+	free (photcode);
+	return (FALSE);
+      }
+      if ((photcode[Npri].type != PHOT_PRI) && (photcode[Npri].type != PHOT_SEC)) {
+	fprintf (stderr, "reference for dependent photcode is not a primary or secondary code\n");
+	free (photcode);
+	return (FALSE);
+      }
+    }
+    if (photcode[i].type == PHOT_ALT) {
+      Npri = photcodes[0].hashcode[photcode[i].code];
+      if ((Npri >= Np) || (Npri < 0)) {
+	fprintf (stderr, "reference for alternate photcode is not in photcodes\n");
+	free (photcode);
+	return (FALSE);
+      }
+      if ((photcode[Npri].type != PHOT_PRI) && (photcode[Npri].type != PHOT_SEC)) {
+	fprintf (stderr, "reference for alternate photcode is not a primary or secondary code\n");
+	free (photcode);
+	return (FALSE);
+      }
+    }
+  }
+  photcodes[0].code = photcode;
+  photcodes[0].Ncode = Np;
+
+  return (TRUE);
+
+}
+
+void ParseColorTerms (char *terms, float *X, int *N) {
+
+  int i;
+  char *p;
+
+  p = terms;
+
+  for (i = 0; (p != NULL) && (i < NCTERMS); i++) {
+    X[i] = atof (p);
+    p = strchr (p, ',');
+    if (p == (char *) NULL) continue;
+    p ++;
+  }
+  *N = i;
+}
+
+/********** photcode lookups **********/
+
+/* return photcode for given name */
+PhotCode *GetPhotcodebyName (char *name) {
+  
+  int i;
+
+  if (name == (char *) NULL ) return (NULL);
+  
+  for (i = 0; i < photcodes[0].Ncode; i++) {
+    if (!strcmp (photcodes[0].code[i].name, name)) {
+      return (&photcodes[0].code[i]);
+    }
+  }
+  return (NULL);
+}
+/* return photcode.code for given name */
+int GetPhotcodeCodebyName (char *name) {
+  
+  int i;
+  
+  if (name == (char *) NULL ) return (0);
+
+  for (i = 0; i < photcodes[0].Ncode; i++) {
+    if (!strcmp (photcodes[0].code[i].name, name)) {
+      return (photcodes[0].code[i].code);
+    }
+  }
+  return (0);
+}
+/* return equivalent photcode for given name */
+PhotCode *GetPhotcodeEquivbyName (char *name) {
+  
+  int i, equiv;
+  
+  if (name == (char *) NULL ) return (NULL);
+
+  for (i = 0; i < photcodes[0].Ncode; i++) {
+    if (!strcmp (photcodes[0].code[i].name, name)) {
+      if (photcodes[0].code[i].equiv == 0) return (NULL);
+      equiv = photcodes[0].hashcode[photcodes[0].code[i].equiv];
+      if (equiv == -1) return (NULL);
+      return (&photcodes[0].code[equiv]);
+    }
+  }
+  return (NULL);
+}
+/* return equivalent photcode.code for given name */
+int GetPhotcodeEquivCodebyName (char *name) {
+  
+  int i, equiv;
+  
+  if (name == (char *) NULL ) return (0);
+
+  for (i = 0; i < photcodes[0].Ncode; i++) {
+    if (!strcmp (photcodes[0].code[i].name, name)) {
+      if (photcodes[0].code[i].equiv == 0) return (0);
+      equiv = photcodes[0].hashcode[photcodes[0].code[i].equiv];
+      if (equiv == -1) return (0);
+      return (photcodes[0].code[equiv].code);
+    }
+  }
+  return (0);
+}
+
+/* return photcode for given code */
+PhotCode *GetPhotcodebyCode (int code) {
+  
+  int entry;
+  
+  if (code < 0) return (NULL);
+  if (code > 0x10000) return (NULL);
+
+  entry = photcodes[0].hashcode[code];
+  if (entry == -1) return (NULL);
+
+  return (&photcodes[0].code[entry]);
+}
+/* return photcode.code for given code */
+char *GetPhotcodeNamebyCode (int code) {
+  
+  int entry;
+  
+  if (code < 0) return (NULL);
+  if (code > 0x10000) return (NULL);
+
+  entry = photcodes[0].hashcode[code];
+  if (entry == -1) return (NULL);
+
+  return (photcodes[0].code[entry].name);
+}
+/* return equivalent photcode for given code */
+PhotCode *GetPhotcodeEquivbyCode (int code) {
+  
+  int entry, equiv;
+  
+  if (code < 0) return (NULL);
+  if (code > 0x10000) return (NULL);
+
+  entry = photcodes[0].hashcode[code];
+  if (entry == -1) return (NULL);
+
+  if (photcodes[0].code[entry].equiv == 0) return (NULL);
+  equiv = photcodes[0].hashcode[photcodes[0].code[entry].equiv];
+
+  if (equiv == -1) return (NULL);
+  return (&photcodes[0].code[equiv]);
+}
+/* return equivalent photcode.code for given code */
+int GetPhotcodeEquivCodebyCode (int code) {
+  
+  int entry;
+  
+  if (code < 0) return (0);
+  if (code > 0x10000) return (0);
+
+  entry = photcodes[0].hashcode[code];
+  if (entry == -1) return (0);
+  return (photcodes[0].code[entry].equiv);
+}
+
+int GetPhotcodeNsec (int code) {
+  
+  int Nsec;
+  
+  if (code < 0) return (-1);
+  if (code > 0x10000) return (-1);
+
+  Nsec = photcodes[0].hashNsec[code];
+  return (Nsec);
+}
+
+/* Nsec of 0 is PRI */
+PhotCode *GetPhotcodebyNsec (int Nsec) {
+  
+  if (Nsec > photcodes[0].Nsecfilt) return (NULL);
+  if (Nsec < 0) return (NULL);
+  
+  return (&photcodes[0].code[Nseclist[Nsec]]);
+}
+
+int GetPhotcodeNsecfilt () {
+  return (photcodes[0].Nsecfilt);
+}
+
+/* ALLOCATE and return list of all photcodes
+   with photcode.equiv == code */
+int *GetPhotcodeEquivList (int code, int *nlist) {
+
+  int i, Nlist;
+  int *list;
+
+  ALLOCATE (list, int, MAX (1, photcodes[0].Ncode));
+  Nlist = 0;
+  for (i = 0; i < photcodes[0].Ncode; i++) {
+    if (photcodes[0].code[i].equiv != code) continue;
+    list[Nlist] = photcodes[0].code[i].code;
+    Nlist ++;
+  }
+  REALLOCATE (list, int, MAX (1, Nlist));
+
+  *nlist = Nlist;
+  return (list);
+}
+
+/******** photometry conversions *********/
+double PhotInst (Measure *measure) {
+
+  short Mi;
+  double M;
+
+  Mi = iPhotInst (measure);
+  M = 0.001*Mi;
+  return (M);
+}
+
+/****/
+double PhotCat (Measure *measure) {
+
+  short Mi;
+  double M;
+
+  Mi = iPhotCat (measure);
+  M = 0.001*Mi;
+  return (M);
+}
+
+/****/
+double PhotSys (Measure *measure, Average *average, SecFilt *secfilt) {
+
+  short Mi;
+  double M;
+
+  Mi = iPhotSys (measure, average, secfilt);
+  M = 0.001*Mi;
+  return (M);
+}
+
+/****/
+double PhotRel (Measure *measure, Average *average, SecFilt *secfilt) {
+
+  short Mi;
+  double M;
+
+  Mi = iPhotRel (measure, average, secfilt);
+  M = 0.001*Mi;
+  return (M);
+}
+
+/****/
+double PhotCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code) {
+
+  short Mi;
+  double M;
+
+  Mi = iPhotCal (thisone, average, secfilt, measure, code);
+  M = 0.001*Mi;
+  return (M);
+}
+
+/****/
+double PhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure) {
+
+  short Mi;
+  double M;
+
+  Mi = iPhotRef (code, average, secfilt, measure);
+  M = 0.001*Mi;
+  return (M);
+}
+
+/****/
+double PhotAve (PhotCode *code, Average *average, SecFilt *secfilt) {
+
+  short Mi;
+  double M;
+
+  Mi = iPhotAve (code, average, secfilt);
+  M = 0.001*Mi;
+  return (M);
+}
+
+/****/
+double PhotdM (PhotCode *code, Average *average, SecFilt *secfilt) {
+
+  short Mi;
+  double M;
+
+  Mi = iPhotdM (code, average, secfilt);
+  M = 0.001*Mi;
+  return (M);
+}
+
+/****/
+double PhotXm (PhotCode *code, Average *average, SecFilt *secfilt) {
+
+  int Mi;
+  double Xm;
+
+  Mi = iPhotXm (code, average, secfilt);
+  Xm = (Mi == NO_MAG) ? -1.0 : pow (10.0, 0.01*Mi);
+  return (Xm);
+}
+
+/******** internal photometry conversions (keeps values in short int millimags) *********/
+short iPhotInst (Measure *measure) {
+
+  int Np;
+  short M;
+
+  Np = photcodes[0].hashcode[measure[0].source];
+  if (Np == -1) return (NO_MAG);
+
+  if (photcodes[0].code[Np].type == PHOT_REF) {
+    M = measure[0].M;
+    return (M);
+  }
+
+  M = measure[0].M - measure[0].dt - iZERO_POINT;
+	  
+  return (M);
+
+}
+
+short iPhotCat (Measure *measure) {
+
+  int Np;
+  short Mcat;
+  PhotCode *code;
+
+  Np = photcodes[0].hashcode[measure[0].source];
+  if (Np == -1) return (NO_MAG);
+
+  if (photcodes[0].code[Np].type == PHOT_REF) {
+    Mcat = measure[0].M;
+    return (Mcat);
+  }
+  code = &photcodes[0].code[Np];
+  Mcat = measure[0].M - iZERO_POINT + code[0].K*(measure[0].airmass - 1000) + code[0].C;
+  
+  return (Mcat);
+}
+
+short iPhotSys (Measure *measure, Average *average, SecFilt *secfilt) {
+
+  int i, Np;
+  short Mcat, Mcol, Msys, mc;
+  double Mc;
+  PhotCode *code;
+
+  Np = photcodes[0].hashcode[measure[0].source];
+  if (Np == -1) return (NO_MAG);
+
+  if (photcodes[0].code[Np].type == PHOT_REF) {
+    Msys = measure[0].M;
+    return (Msys);
+  }
+  code = &photcodes[0].code[Np];
+  Mcat = measure[0].M - iZERO_POINT + code[0].K*(measure[0].airmass - 1000.0) + code[0].C;
+
+  /* for DEP, color must be made of PRI/SEC */
+  mc = iPhotColor (average, secfilt, NULL, code);
+  if (mc == NO_MAG) return (Mcat);
+  mc = mc - code[0].dX;
+
+  Mc = mc;
+  Mcol = 0;
+  for (i = 0; i < code[0].Nc; i++) {
+    Mcol += code[0].X[i]*Mc;
+    Mc *= mc * 0.001;    /* the 0.001 is needed for higher order terms to keep the units mag = mag^n */
+  }
+  Msys = Mcat + Mcol;
+  return (Msys);
+}
+
+short iPhotRel (Measure *measure, Average *average, SecFilt *secfilt) {
+
+  int i, Np;
+  short Mcat, Mcol, Mrel, mc;
+  double Mc;
+  PhotCode *code;
+
+  Np = photcodes[0].hashcode[measure[0].source];
+  if (Np == -1) return (NO_MAG);
+
+  if (photcodes[0].code[Np].type == PHOT_REF) {
+    Mcat = measure[0].M;
+    return (Mcat);
+  }
+  code = &photcodes[0].code[Np];
+  Mrel = measure[0].M - iZERO_POINT + code[0].K*(measure[0].airmass - 1000.0) + code[0].C - measure[0].Mcal;
+
+  /* for DEP, color must be made of PRI/SEC */
+  mc = iPhotColor (average, secfilt, NULL, code);
+  if (mc == NO_MAG) return (Mrel);
+  mc = mc - code[0].dX;
+
+  Mc = mc;
+  Mcol = 0;
+  for (i = 0; i < code[0].Nc; i++) {
+    Mcol += code[0].X[i]*Mc;
+    Mc *= mc * 0.001;    /* the 0.001 is needed for higher order terms to keep the units mag = mag^n */
+  }
+  Mrel += Mcol;
+  return (Mrel);
+}
+
+/* return calibrated magnitude from measure for given photcode */
+short iPhotCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code) {
+
+  int i, Np; 
+  short Mcal, Mrel, Mcol, mc;
+  double Mc;
+
+  /* code must be the matching PRI/SEC code for this measurement or an equivalent ALT */
+  Np = photcodes[0].hashcode[thisone[0].source];
+  if (Np == -1) {
+    return (NO_MAG);
+  }
+
+  if (photcodes[0].code[Np].type == PHOT_REF) {
+    Mrel = thisone[0].M;
+    return (Mrel);
+  }
+  if (code[0].code != photcodes[0].code[Np].equiv) {
+    return (NO_MAG);
+  }
+
+  Mcal = iPhotRel (thisone, average, secfilt) + code[0].C;
+
+  mc = iPhotColor (average, secfilt, measure, code);
+  if (mc == NO_MAG) return (Mcal);
+  mc = mc - code[0].dX;
+
+  Mc = mc;
+  Mcol = 0;
+  for (i = 0; i < code[0].Nc; i++) {
+    Mcol += code[0].X[i]*Mc;
+    Mc *= mc * 0.001;    /* the 0.001 is needed for higher order terms to keep the units mag = mag^n */
+  }
+  Mcal += Mcol;
+  return (Mcal);
+}
+
+/* color term may not use DEP magnitude */
+short iPhotColor (Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code) {
+
+  int i, Ns1, Ns2, Ns;
+  short m1, m2, mc;
+  PhotCode *color;
+
+  m1 = m2 = NO_MAG;
+
+  if (measure == NULL) {
+    Ns1 = photcodes[0].hashNsec[code[0].c1];
+    Ns2 = photcodes[0].hashNsec[code[0].c2];
+  
+    m1 = (Ns1 == -1) ? average[0].M : secfilt[Ns1].M;
+    m2 = (Ns2 == -1) ? average[0].M : secfilt[Ns2].M;
+    mc = ((m1 == NO_MAG) || (m2 == NO_MAG)) ? NO_MAG : (m1 - m2);
+    return (mc);
+  }
+
+  /* find magnitude matching first color term */
+  color = GetPhotcodebyCode (code[0].c1);
+  if (color == NULL) return (NO_MAG);
+  if (color[0].type == PHOT_REF) {
+    for (i = 0; (i < average[0].Nm) && (m1 == NO_MAG); i++) {
+      if (measure[i].source == color[0].code) {
+	m1 = measure[i].M;
+      }
+    }
+  } else {
+    Ns = photcodes[0].hashNsec[color[0].code];
+    m1 = (Ns == -1) ? average[0].M : secfilt[Ns].M;
+  }	
+
+  /* find magnitude matching second color term */
+  color = GetPhotcodebyCode (code[0].c2);
+  if (color == NULL) return (NO_MAG);
+  if (color[0].type == PHOT_REF) {
+    for (i = 0; (i < average[0].Nm) && (m2 == NO_MAG); i++) {
+      if (measure[i].source == color[0].code) {
+	m2 = measure[i].M;
+      }
+    }
+  } else {
+    Ns = photcodes[0].hashNsec[color[0].code];
+    m2 = (Ns == -1) ? average[0].M : secfilt[Ns].M;
+  }	
+  mc = ((m1 == NO_MAG) || (m2 == NO_MAG)) ? NO_MAG : (m1 - m2);
+  return (mc);
+}
+
+/* return calibrated magnitude from average/secfilt for given photcode */
+short iPhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure) {
+
+  int i, Ns;
+  short Mave, Mref, Mcol, mc;
+  double Mc;
+
+  Ns = photcodes[0].hashNsec[code[0].code];
+  Mave = (Ns == -1) ? average[0].M : secfilt[Ns].M;
+  Mref = Mave + code[0].C;
+
+  mc = iPhotColor (average, secfilt, measure, code);
+  if (mc == NO_MAG) return (Mref);
+  mc = mc - code[0].dX;
+
+  Mc = mc;
+  Mcol = 0;
+  for (i = 0; i < code[0].Nc; i++) {
+    Mcol += code[0].X[i]*Mc;
+    Mc *= mc * 0.001;    /* the 0.001 is needed for higher order terms to keep the units mag = mag^n */
+  }
+  Mref += Mcol;
+  return (Mref);
+}
+
+/***/
+short iPhotAve (PhotCode *code, Average *average, SecFilt *secfilt) {
+
+  int Ns;
+  short Mave;
+
+  Ns = photcodes[0].hashNsec[code[0].code];
+  Mave = (Ns == -1) ? average[0].M : secfilt[Ns].M;
+  return (Mave);
+}
+
+/*** note that this is NOT a wrapper around iPhotdM ***/
+short iPhotdM (PhotCode *code, Average *average, SecFilt *secfilt) {
+
+  int Ns;
+  short dM;
+
+  Ns = photcodes[0].hashNsec[code[0].code];
+  dM  = (Ns == -1) ? average[0].dM : secfilt[Ns].dM;
+  return (dM);
+}
+
+/*** note that this is NOT a wrapper around iPhotXm ***/
+short iPhotXm (PhotCode *code, Average *average, SecFilt *secfilt) {
+
+  int Ns;
+  short Xm;
+
+  Ns = photcodes[0].hashNsec[code[0].code];
+  Xm = (Ns == -1) ? average[0].Xm : secfilt[Ns].Xm;
+  return (Xm);
+}
+
+/* given a photcode pair c1 & c2, return the color of this star (NaN if not found) */
+int PhotColor (Average *average, SecFilt *secfilt, Measure *measure, int c1, int c2, double *color) {
+
+  int i, Ns;
+  double M1, M2, dM;
+  PhotCode *code;
+  
+  code = GetPhotcodebyCode (c1);
+  if (code == NULL) return (FALSE);
+  if (code[0].type == PHOT_REF) {
+    for (i = 0; i < average[0].Nm; i++) {
+      if (measure[i].source == c1) {
+	M1 = 0.001*measure[i].M;
+	goto filter1;
+      }
+    }	
+    return (FALSE);
+  } else {
+    Ns = photcodes[0].hashNsec[code[0].code];
+    M1 = (Ns == -1) ? 0.001*average[0].M : 0.001*secfilt[Ns].M;
+  }	
+
+ filter1:
+  code = GetPhotcodebyCode (c2);
+  if (code == NULL) return (FALSE);
+  if (code[0].type == PHOT_REF) {
+    for (i = 0; i < average[0].Nm; i++) {
+      if (measure[i].source == c2) {
+	M2 = 0.001*measure[i].M;
+	goto filter2;
+      }
+    }	
+    return (FALSE);
+  } else {
+    Ns = photcodes[0].hashNsec[code[0].code];
+    M2 = (Ns == -1) ? 0.001*average[0].M : 0.001*secfilt[Ns].M;
+  }	
+  
+ filter2:
+
+  dM = M1 - M2;
+  *color = dM;
+  
+  return (TRUE);
+}
+
+/* photcode table should have the following format: 
+
+# code name     type  zero  airmass  offset  c1 c2  slope  <color>  primary
+  1    B        pri   24.0  0.15     -       -  -   -      -        -
+  2    B        pri   24.0  0.15     -       -  -   -      -        -
+  3    B1       sec   22.5  0.18     0.15    1  2   0.10   0.50     1
+  1000 USNO_B   ref   -     -        -       -  -   -      -        -
+
+*/
+
+
+/*
+  Nc1 = photcodes[0].code[Np].c1;
+  Ns1 = photcodes[0].hashNsec[Nc1];
+
+  Nc2 = photcodes[0].code[Np].c2;
+  Ns2 = photcodes[0].hashNsec[Nc2];
+
+  Xlam = photcodes[0].code[Np].X[0];
+  Klam = photcodes[0].code[Np].K;
+  
+  m1 = (Ns1 == -1) ? average[0].M : secfilt[Ns1].M;
+  m2 = (Ns2 == -1) ? average[0].M : secfilt[Ns2].M;
+*/
Index: /tags/start/Ohana/src/libohana/src/config.c
===================================================================
--- /tags/start/Ohana/src/libohana/src/config.c	(revision 12606)
+++ /tags/start/Ohana/src/libohana/src/config.c	(revision 12606)
@@ -0,0 +1,453 @@
+# include <ohana.h>
+# ifndef whitespace
+# define whitespace(c) (((c) == ' ') || ((c) == '\t'))
+# endif
+
+# define D_NBYTES 4096
+
+static char *ConfigVariable = (char *) NULL;
+static int NDefineVariable;
+static char **DefineVariable;
+static char **DefineValue;
+
+char *SelectConfigFile (int *argc, char **argv, char *progname) {
+  
+  /* 
+     config file selection rules (first ones override later ones):
+
+     1) -c Filename   : use Filename
+     2) PROGNAME      : use environment variable as config file
+     3) progname.rc   : use alternate name in local dir as config file
+     4) .prognamerc   : use rc file in local dir as config file
+     5) ~/.prognamerc : use rc file in homedir as config file
+
+     special variable definitions:
+     1) -C WORD       : set CONFIG variable to WORD
+     2) -D NAME WORD  : set NAME variable to WORD
+        -D overrides variables in param file
+
+     these command-line options are removed and a complete arg list left behind
+  */
+
+  char *filename, *find, *home;
+  struct stat filestat;
+  uid_t uid;
+  gid_t gid;
+  int i, N, NDEF, status;
+  
+  /* first look for -C CONFIG variable */
+  if ((N = get_argument (*argc, argv, "-C"))) {
+    remove_argument (N, argc, argv);
+    if (ConfigVariable != (char *) NULL) free (ConfigVariable);
+    ConfigVariable = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+    
+  /* next look for -D NAME WORD variables */
+  NDEF = 10;
+  ALLOCATE (DefineVariable, char *, NDEF);
+  ALLOCATE (DefineValue, char *, NDEF);
+  for (i = 0; (N = get_argument (*argc, argv, "-D")); i++) {
+    remove_argument (N, argc, argv);
+    DefineVariable[i] = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+    DefineValue[i] = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+    if (i == NDEF - 1) {
+      NDEF += 10;
+      REALLOCATE (DefineVariable, char *, NDEF);
+      REALLOCATE (DefineValue, char *, NDEF);
+    }      
+  }    
+  NDefineVariable = i;
+  REALLOCATE (DefineVariable, char *, MAX (1, i));
+    
+  /* look for -c FILENAME for config file */
+  if ((N = get_argument (*argc, argv, "-c"))) {
+    remove_argument (N, argc, argv);
+    filename = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+    return (filename);
+  }
+  
+  /* look for PROGNAME env var */
+  find = strcreate (progname);
+  for (i = 0; i < strlen(find); i++) find[i] = toupper (find[i]);
+  filename = getenv (find);
+  free (find);
+  if (filename != (char *) NULL) {
+    find = strcreate (filename);
+    return (find);
+  }
+
+  uid = getuid();
+  gid = getgid();
+  ALLOCATE (find, char, strlen(progname) + 32);
+
+  /* look for progname.rc */
+  sprintf (find, "%s.rc", progname);
+  status = stat (find, &filestat);
+  if (status == 0) { 
+    /* file exists, can we read it? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP)) || 
+	(                            (filestat.st_mode & S_IROTH))) {
+      return (find);
+    }
+  }
+  /* look for ./.prognamerc */
+  sprintf (find, ".%src", progname);
+  status = stat (find, &filestat);
+  if (status == 0) { 
+    /* file exists, can we read it? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP)) || 
+	(                            (filestat.st_mode & S_IROTH))) {
+      return (find);
+    }
+  }
+  free (find);
+
+  /* look for ~/.prognamerc */
+  home = getenv ("HOME");
+  if (home == (char *) NULL) { return ((char *) NULL); }
+  ALLOCATE (find, char, 1024);
+  sprintf (find, "%s/.%src", home, progname);
+  status = stat (find, &filestat);
+  if (status == 0) { 
+    /* file exists, can we read it? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP)) || 
+	(                            (filestat.st_mode & S_IROTH))) {
+      return (find);
+    }
+  }
+  free (find);
+  return ((char *) NULL);
+}
+
+char *LoadConfigFile (char *filename) {
+  
+  FILE *f;
+  int i, done, Nbytes, NBYTES, nbytes, Nout, Ncpy, INPUT, Nlevel;
+  char *ibuffer, *obuffer, *tbuffer;
+  char *last, *next;
+  char infile[256], line[256];
+  
+  /* open file */
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    return ((char *) NULL);
+  }
+ 
+  /* allocate tmp space, 2 extra bytes for a final return and EOL */
+  Nbytes = 0;
+  NBYTES = D_NBYTES;
+  ALLOCATE (ibuffer, char, NBYTES + 2);
+    
+  /* load data from file */
+  done = FALSE;
+  while ((nbytes = fread (&ibuffer[Nbytes], sizeof(char), D_NBYTES, f)) == D_NBYTES) {
+    Nbytes += nbytes;
+    NBYTES += D_NBYTES;
+    REALLOCATE (ibuffer, char, NBYTES + 2);
+  }
+  Nbytes += nbytes;
+  fclose (f);
+
+  /* add final return & EOL if non-existent */
+  if (ibuffer[Nbytes-1] != '\n') {
+    ibuffer[Nbytes] = '\n';
+    Nbytes ++;
+  }
+  if (ibuffer[Nbytes]) ibuffer[Nbytes] = 0;
+
+  /* add the optional variables to the end of the input buffer */
+  if (ConfigVariable != (char *) NULL) {
+    snprintf (line, 256, "%s %s\n", "CONFIG", ConfigVariable);
+    Ncpy = strlen (line);
+    if (Nbytes + Ncpy >= NBYTES - 1) {
+      NBYTES = Nbytes + Ncpy + D_NBYTES;
+      REALLOCATE (ibuffer, char, NBYTES);
+    }    
+    memcpy (&ibuffer[Nbytes], line, Ncpy);
+    Nbytes += Ncpy;
+    ibuffer[Nbytes] = 0;
+  }
+  for (i = 0; i < NDefineVariable; i++) {
+    snprintf (line, 256, "%s %s\n", DefineVariable[i], DefineValue[i]);
+    Ncpy = strlen (line);
+    if (Nbytes + Ncpy >= NBYTES - 1) {
+      NBYTES = Nbytes + Ncpy + D_NBYTES;
+      REALLOCATE (ibuffer, char, NBYTES);
+    }    
+    memcpy (&ibuffer[Nbytes], line, Ncpy);
+    Nbytes += Ncpy;
+    ibuffer[Nbytes] = 0;
+  }
+  
+  /* loop over input buffer, interpolating 'input' lines until none are added */
+  Nlevel = 0;
+  do {
+    INPUT = FALSE;
+
+    /* allocate output buffer & set counter */
+    NBYTES = Nbytes + D_NBYTES;
+    ALLOCATE (obuffer, char, NBYTES);
+    Nout = 0;
+    
+    /* copy from ibuffer to obuffer, interpolating 'input' lines */
+    last = next = ibuffer;
+    for (i = 1; (next = ScanConfig (ibuffer, "input", "%s", i, infile)) != (char *) NULL; i++) {
+      /* copy data from last point to before 'input' */ 
+      Ncpy = next - last - 5;
+      if (Nout + Ncpy >= NBYTES - 1) {
+	NBYTES = Nout + Ncpy + D_NBYTES;
+	REALLOCATE (obuffer, char, NBYTES);
+      }      
+      memcpy (&obuffer[Nout], last, Ncpy);
+      Nout += Ncpy;
+      obuffer[Nout] = 0;
+      
+      /* insert data from 'input' file */
+      tbuffer = LoadRawConfigFile (infile, FALSE);
+      if (tbuffer != (char *) NULL) {
+	Ncpy = strlen (tbuffer);
+	if (Nout + Ncpy >= NBYTES - 1) {
+	  NBYTES = Nout + Ncpy + D_NBYTES;
+	  REALLOCATE (obuffer, char, NBYTES);
+	}      
+	memcpy (&obuffer[Nout], tbuffer, Ncpy);
+	free (tbuffer);
+	Nout += Ncpy;
+	obuffer[Nout] = 0;
+      }
+      
+      /* pointer goes to end of input line */
+      last = strchr (next, '\n');
+      if (last == (char *) NULL) break;
+      last ++;
+      INPUT = TRUE;
+    }
+    /* last set of bytes after last input */
+    Ncpy = strlen (last);
+    if (Nout + Ncpy >= NBYTES - 1) {
+      NBYTES = Nout + Ncpy + D_NBYTES;
+      REALLOCATE (obuffer, char, NBYTES);
+    }      
+    memcpy (&obuffer[Nout], last, Ncpy);
+    Nout += Ncpy;
+    obuffer[Nout] = 0;
+    free (ibuffer);
+    ibuffer = obuffer;
+    Nlevel ++;
+  } while (INPUT && (Nlevel < 20));
+  if (Nlevel == 20) {
+    fprintf (stderr, "warning: config reached max depth of 20\n");
+  }
+
+  /* 'obuffer' now has complete set of interpolated lines from 'filename' */
+  return (obuffer);
+}
+
+char *ScanConfig (char *config, char *field, char *mode, int Nentry, ...) {
+  
+  int i;
+  char *p, *p2, *tmp, *tfield, *start, *expandline();
+  va_list argp;
+  double value;
+  
+  if (config == (char *) NULL) return ((char *) NULL);
+  va_start (argp, Nentry);
+
+  ALLOCATE (tfield, char, strlen (field) + 3);
+  sprintf (tfield, "\n%s", field);
+
+  /* we search for Nentry matching fields,
+     or until the end if Nentry == 0 */
+  p = (char *) NULL;
+  p2 = config;
+  for (i = 0; (i < Nentry) || !Nentry;) {
+    tmp = strstr (p2, tfield);
+    if (tmp == (char *) NULL) {
+      break;
+    }
+    p2 = tmp + strlen (tfield);
+    if (whitespace (*p2)) {
+      p = p2;
+      i++;
+    }
+  }
+  free (tfield);
+  if (Nentry && (i != Nentry)) {
+    p = va_arg (argp, char *);
+    p[0] = 0;
+    return ((char *) NULL);
+  }
+  if (p == (char *) NULL) {
+    p = va_arg (argp, char *);
+    p[0] = 0;
+    return ((char *) NULL);
+  }
+
+  start = p;
+  if (!strcmp (mode, "%s")) {
+    p2 = strchr (p, '\n');
+    if (p2 == (char *) NULL) p2 = config + strlen(config);
+    ALLOCATE (tmp, char, p2-p + 2);
+    memcpy (tmp, p, (p2-p));
+    tmp[(p2-p)] = 0;
+    stripwhite (tmp);
+    tmp = expandline (tmp, config);
+    p2 = va_arg (argp, char *);
+    strcpy (p2, tmp);
+    free (tmp);
+  } else {
+ 
+    /* try to get a numerical value from the field */
+    value = strtod (p, &p2);
+    if ((*p2 == 'd') || (*p2 == 'D')) 
+      value *= pow (10.0, atof (p2 + 1));
+    
+    if (!strcmp (mode, "%d"))  *va_arg (argp, int *)       = value;
+    if (!strcmp (mode, "%u"))  *va_arg (argp, unsigned *)  = value;
+    if (!strcmp (mode, "%ld")) *va_arg (argp, long *)      = value;
+    if (!strcmp (mode, "%hd")) *va_arg (argp, short *)     = value;
+    if (!strcmp (mode, "%f"))  *va_arg (argp, float *)     = value;
+    if (!strcmp (mode, "%lf")) *va_arg (argp, double *)    = value;
+    
+  }
+ 
+  va_end (argp);
+  return (start);
+  
+}
+
+
+char *expandline (char *line, char *config) {
+
+  int Nin, Nout, Ncpy, NBYTES;
+  char *p1, *p2, word[256], value[256];
+  char *outline;
+  
+  NBYTES = 256;
+  ALLOCATE (outline, char, NBYTES);
+  Nout = 0;
+  Nin  = 0;
+  while ((p1 = strchr (&line[Nin], '$')) != (char *) NULL) {
+    Ncpy = p1 - line - Nin;
+    if (Nout + Ncpy >= NBYTES) {
+      NBYTES = Nout + Ncpy + 256;
+      REALLOCATE (outline, char, NBYTES - 2);
+    }
+    memcpy (&outline[Nout], &line[Nin], Ncpy);
+    Nout += Ncpy;
+    
+    p1 ++;
+    for (p2 = p1; isalnum (*p2) || (*p2 == '_') || (*p2 == '-'); p2++);
+    memcpy (word, p1, p2 - p1);
+    word[p2-p1] = 0;
+    Nin += Ncpy + 1 + p2 - p1;
+    
+    /* search for last entry of word */
+    if (!ScanConfig (config, word, "%s", 0, value)) {
+      fprintf (stderr, "variable %s not found in config file\n", word);
+      return (line);
+    }
+    Ncpy = strlen(value);
+    if (Nout + Ncpy >= NBYTES - 2) {
+      NBYTES = Nout + Ncpy + 256;
+      REALLOCATE (outline, char, NBYTES);
+    }    
+    memcpy (&outline[Nout], value, Ncpy);
+    Nout += Ncpy;
+  }
+  Ncpy = strlen(&line[Nin]);
+  if (Nout + Ncpy >= NBYTES - 2) {
+    NBYTES = Nout + Ncpy + 256;
+    REALLOCATE (outline, char, NBYTES);
+  }  
+  memcpy (&outline[Nout], &line[Nin], Ncpy);
+  Nout += Ncpy;
+  outline[Nout] = 0;
+  free (line);
+  return (outline);
+
+}
+
+char *LoadRawConfigFile (char *filename, int options) {
+  
+  FILE *f;
+  int i, done, Nbytes, NBYTES, nbytes, Ncpy;
+  char *ibuffer;
+  char line[256];
+  
+  /* open file */
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    return ((char *) NULL);
+  }
+ 
+  /* allocate tmp space, 2 extra bytes for a final return and EOL */
+  Nbytes = 0;
+  NBYTES = D_NBYTES;
+  ALLOCATE (ibuffer, char, NBYTES + 2);
+    
+  /* load data from file */
+  done = FALSE;
+  while ((nbytes = fread (&ibuffer[Nbytes], sizeof(char), D_NBYTES, f)) == D_NBYTES) {
+    Nbytes += nbytes;
+    NBYTES += D_NBYTES;
+    REALLOCATE (ibuffer, char, NBYTES + 2);
+  }
+  Nbytes += nbytes;
+  fclose (f);
+
+  /* add final return & EOL, if non-existent */
+  if (ibuffer[Nbytes-1] != '\n') {
+    ibuffer[Nbytes] = '\n';
+    Nbytes ++;
+  }
+  if (ibuffer[Nbytes]) ibuffer[Nbytes] = 0;
+
+  if (options) {
+    /* write optional variables to bottom of buffer, overriding entries in the file */
+    if (ConfigVariable != (char *) NULL) {
+      snprintf (line, 256, "%s %s\n", "CONFIG", ConfigVariable);
+      Ncpy = strlen (line);
+      if (Nbytes + Ncpy >= NBYTES) {
+	NBYTES = Nbytes + Ncpy + D_NBYTES;
+	REALLOCATE (ibuffer, char, NBYTES + 2);
+      }    
+      memcpy (&ibuffer[Nbytes], line, Ncpy);
+      Nbytes += Ncpy;
+      ibuffer[Nbytes] = 0;
+    }
+    for (i = 0; i < NDefineVariable; i++) {
+      snprintf (line, 256, "%s %s\n", DefineVariable[i], DefineValue[i]);
+      Ncpy = strlen (line);
+      if (Nbytes + Ncpy >= NBYTES) {
+	NBYTES = Nbytes + Ncpy + D_NBYTES;
+	REALLOCATE (ibuffer, char, NBYTES + 2);
+      }    
+      memcpy (&ibuffer[Nbytes], line, Ncpy);
+      Nbytes += Ncpy;
+      ibuffer[Nbytes] = 0;
+    }
+  }
+
+  return (ibuffer);
+}
+
+/* 
+char *LoadConfigFile (char *filename) {
+  
+  char *config;
+
+  config = LoadSubConfigFile (filename, TRUE);
+
+  return (config);
+
+}
+
+*/
Index: /tags/start/Ohana/src/libohana/src/coordops.c
===================================================================
--- /tags/start/Ohana/src/libohana/src/coordops.c	(revision 12606)
+++ /tags/start/Ohana/src/libohana/src/coordops.c	(revision 12606)
@@ -0,0 +1,392 @@
+# include <ohana.h>
+# include <loneos.h>
+
+int XY_to_RD (double *ra, double *dec, double x, double y, Coords *coords) {
+
+  double L, M, X, Y, T, Z;
+  double R, sphi, cphi, stht, ctht;
+  double alpha, delta, salp, calp, sdel, sdp, cdp;
+  
+  *ra  = 0;
+  *dec = 0;
+  stht = ctht = 1;
+
+  /** convert pixel coordinates to cartesian system **/
+  X = coords[0].cdelt1*(x - coords[0].crpix1);
+  Y = coords[0].cdelt2*(y - coords[0].crpix2);
+  if (!strcmp(&coords[0].ctype[4], "-PLY")) {
+    if (coords[0].Npolyterms > 2) {
+      X += coords[0].cdelt1*(x*x*coords[0].polyterms[0][0] + x*y*coords[0].polyterms[1][0] + y*y*coords[0].polyterms[2][0]);
+      Y += coords[0].cdelt2*(x*x*coords[0].polyterms[0][1] + x*y*coords[0].polyterms[1][1] + y*y*coords[0].polyterms[2][1]);
+    }
+    if (coords[0].Npolyterms > 2) {
+      X += coords[0].cdelt1*(x*x*x*coords[0].polyterms[3][0] + x*x*y*coords[0].polyterms[4][0] + x*y*y*coords[0].polyterms[5][0] + y*y*y*coords[0].polyterms[6][0]);
+      Y += coords[0].cdelt2*(x*x*x*coords[0].polyterms[3][1] + x*x*y*coords[0].polyterms[4][1] + x*y*y*coords[0].polyterms[5][1] + y*y*y*coords[0].polyterms[6][1]);
+    }
+  }
+
+  L = (X*coords[0].pc1_1 + Y*coords[0].pc1_2);
+  M = (X*coords[0].pc2_1 + Y*coords[0].pc2_2);
+  /* in FITS ref, L,M = x, y  alpha, delta = phi, theta */
+
+  /**** Zenithal Projections ****/
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || 
+      !strcmp(&coords[0].ctype[4], "-TAN") || 
+      !strcmp(&coords[0].ctype[4], "-SIN") || 
+      !strcmp(&coords[0].ctype[4], "-ZEA") || 
+      !strcmp(&coords[0].ctype[0], "MM")) {
+    R = hypot (L,M);
+    if ((L == 0) && (M == 0)) {
+      sphi = 0;
+      cphi = 1;
+    }
+    else {
+      sphi =  L / R;
+      cphi = -M / R;
+    }
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || 
+	!strcmp(&coords[0].ctype[4], "-TAN")) {
+      if (R == 0) {
+	stht = 1.0;
+	ctht = 0.0;
+      }
+      else {
+	T = DEG_RAD / R;
+	stht =   T / sqrt ( 1.0 + T*T);
+	ctht = 1.0 / sqrt ( 1.0 + T*T);
+      }
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || 
+	!strcmp(&coords[0].ctype[0], "MM")) {
+      ctht = RAD_DEG * R;
+      stht = sqrt (1 - ctht*ctht);
+    }
+    if (!strcmp(&coords[0].ctype[4], "-ZEA")) {
+      stht = 1 - 0.5*SQ(R*RAD_DEG);
+      ctht = sqrt (1 - stht*stht);
+    }
+
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    
+    sdel = stht*sdp - ctht*cphi*cdp;
+    salp = ctht*sphi;
+    calp = stht*cdp + ctht*cphi*sdp;
+    alpha = atan2 (salp, calp);
+    delta = asin (sdel);
+    
+    *ra  = DEG_RAD*alpha + coords[0].crval1;
+    *dec = DEG_RAD*delta;
+  }
+  
+  /**** Locally Cartesian Projections ****/
+  if (!strcmp(&coords[0].ctype[4], "-LIN") || 
+      !strcmp(&coords[0].ctype[0], "GENE")) {
+    *ra  = L + coords[0].crval1;
+    *dec = M + coords[0].crval2;
+  }
+  
+  /**** Other Conventional Projections ****/
+  if (!strcmp(&coords[0].ctype[4], "-AIT")) {
+    Z = sqrt (1.0 - SQ(RAD_DEG*0.25*L) - SQ(RAD_DEG*0.5*M));
+    alpha = 2.0 * DEG_RAD * atan2 (RAD_DEG*0.5*Z*L, 2.0*SQ(Z) - 1.0);
+    delta = DEG_RAD * asin (RAD_DEG*M*Z);
+    *ra  = alpha + coords[0].crval1;
+    *dec = delta + coords[0].crval2;
+  }
+  if (!strcmp(&coords[0].ctype[4], "-GLS")) {
+    /* L,M in degrees, alpha,delta in degrees */
+    alpha = L / cos (RAD_DEG * M);
+    delta = M;
+    *ra  = alpha + coords[0].crval1;
+    *dec = delta + coords[0].crval2;
+  }
+  if (!strcmp(&coords[0].ctype[4], "-PAR")) {
+    /* L,M in degrees, alpha,delta in degrees */
+    alpha = L / (1.0 - SQ(2.0*M/180));
+    delta = 3 * DEG_RAD * asin (M/180.0);
+    *ra  = alpha + coords[0].crval1;
+    *dec = delta + coords[0].crval2;
+  }
+  return (TRUE);
+}
+
+int RD_to_XY (double *x, double *y, double ra, double dec, Coords *coords) {
+
+  double phi, theta;
+  double tmp_d;
+  double X, Y, sphi, cphi, stht;
+  double salp, calp, sdel, cdel, sdp, cdp;
+  double P, A, Rc;
+  int status;
+
+  if (!strcmp(&coords[0].ctype[4], "-PLY")) {
+    /* fprintf (stderr, "approximate to polynomial TAN plane fit\n");  */
+  }
+
+  X = Y = 1;
+  status = TRUE;
+  *x = 0;
+  *y = 0;
+
+  /**** Locally Cartesian Projections ****/
+  if (!strcmp(&coords[0].ctype[0], "GENE") || !strcmp(&coords[0].ctype[4], "-LIN")) {
+    X = (ra  - coords[0].crval1);
+    Y = (dec - coords[0].crval2);
+  }
+  
+  /**** Zenithal Projections ****/
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || 
+      !strcmp(&coords[0].ctype[4], "-TAN") || 
+      !strcmp(&coords[0].ctype[4], "-ZEA") || 
+      !strcmp(&coords[0].ctype[4], "-SIN") || 
+      !strcmp(&coords[0].ctype[0], "MM")) {
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    salp = sin(RAD_DEG*(ra - coords[0].crval1));
+    calp = cos(RAD_DEG*(ra - coords[0].crval1));
+    sdel = sin(RAD_DEG*dec);
+    cdel = cos(RAD_DEG*dec);
+
+    stht = sdel*sdp + cdel*cdp*calp;    /* sin(theta) */
+    sphi = cdel*salp;                   /* = cos(theta)*sin(phi) */
+    cphi = cdel*sdp*calp - sdel*cdp;    /* = cos(theta)*cos(phi) */
+    if (stht < 0) status = FALSE;
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") ) {
+      X =  DEG_RAD * sphi / stht;
+      Y = -DEG_RAD * cphi / stht;
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      X =  DEG_RAD * sphi;
+      Y = -DEG_RAD * cphi;
+    }
+    if (!strcmp(&coords[0].ctype[4], "-ZEA")) {
+      Rc = DEG_RAD * M_SQRT2 / sqrt (1 + stht);
+      X =  Rc * sphi;
+      Y = -Rc * cphi;
+      status = TRUE;
+    }
+  }
+
+  /**** Other Standard Projections ****/
+  if (!strcmp(&coords[0].ctype[4], "-AIT")) {
+    phi = RAD_DEG*(ra - coords[0].crval1);
+    theta = RAD_DEG*(dec - coords[0].crval2);
+    P = 1.0 + cos (theta) * cos (0.5*phi);
+    if (P != 0.0) {
+      A =  DEG_RAD * sqrt (2.0 / P);
+      X =  2.0 * A * cos (theta) * sin (0.5*phi);
+      Y =  A * sin (theta);
+    } else { 
+      X =  0.0;
+      Y =  0.0;
+    }	
+  }
+  if (!strcmp(&coords[0].ctype[4], "-GLS")) {
+    phi = ra - coords[0].crval1;
+    theta = dec - coords[0].crval2;
+    X = phi * cos(RAD_DEG * theta);
+    Y = theta;
+  }
+  if (!strcmp(&coords[0].ctype[4], "-PAR")) {
+    phi = ra - coords[0].crval1;
+    theta = dec - coords[0].crval2;
+    X = phi * (2.0*cos(2*RAD_DEG*theta/3.0) - 1);
+    Y = 180.0 * sin (RAD_DEG*theta/3.0);
+  }
+    
+  tmp_d = 1.0 / (coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1);
+  *x = tmp_d * (coords[0].pc2_2*X - coords[0].pc1_2*Y) / coords[0].cdelt1 + coords[0].crpix1;
+  *y = tmp_d * (coords[0].pc1_1*Y - coords[0].pc2_1*X) / coords[0].cdelt2 + coords[0].crpix2;
+
+  return (status);
+  
+}
+
+int fRD_to_XY (float *x, float *y, double ra, double dec, Coords *coords) {
+
+  int status;
+  double tmpx, tmpy;
+
+  status = RD_to_XY (&tmpx, &tmpy, ra, dec, coords);
+  *x = tmpx;
+  *y = tmpy;
+  
+  return (status);
+
+}
+
+int fXY_to_RD (float *ra, float *dec, double x, double y, Coords *coords) {
+
+  int status;
+  double tmpr, tmpd;
+
+  status = XY_to_RD (&tmpr, &tmpd, x, y, coords);
+  *ra = tmpr;
+  *dec = tmpd;
+  
+  return (status);
+
+}
+
+int GetCoords (Coords *coords, Header *header) {
+  
+  int status, itmp;
+  double rotate, scale;
+  double equinox;
+  
+  rotate = 0.0;
+  coords[0].crval1 = coords[0].crpix1 = coords[0].cdelt1 = 0.0;
+  coords[0].crval2 = coords[0].crpix2 = coords[0].cdelt2 = 0.0;
+  coords[0].pc1_1 = coords[0].pc2_2 = 1.0;
+  coords[0].pc2_1 = coords[0].pc1_2 = 0.0;
+  strcpy (coords[0].ctype, "NONE");
+  
+  status = FALSE; 
+  if (fits_scan (header, "CTYPE2", "%s", 1, coords[0].ctype)) {
+    status  = fits_scan (header, "CRVAL1", "%lf", 1, &coords[0].crval1);
+    status &= fits_scan (header, "CRPIX1", "%f", 1, &coords[0].crpix1);
+    status &= fits_scan (header, "CRVAL2", "%lf", 1, &coords[0].crval2);  
+    status &= fits_scan (header, "CRPIX2", "%f", 1, &coords[0].crpix2);
+
+    if (fits_scan (header, "CDELT1", "%f", 1, &coords[0].cdelt1)) {
+      status &= fits_scan (header, "CDELT2", "%f", 1, &coords[0].cdelt2);
+      if (fits_scan (header, "CROTA2", "%f", 1, &rotate)) {
+	coords[0].pc1_1 =  cos(rotate*RAD_DEG);
+	coords[0].pc1_2 = -sin(rotate*RAD_DEG);
+	coords[0].pc2_1 =  sin(rotate*RAD_DEG);
+	coords[0].pc2_2 =  cos(rotate*RAD_DEG);
+      }
+      if (fits_scan (header, "PC001001", "%f", 1, &coords[0].pc1_1)) {
+	status &= fits_scan (header, "PC001002", "%f", 1, &coords[0].pc1_2);
+	status &= fits_scan (header, "PC002001", "%f", 1, &coords[0].pc2_1);
+	status &= fits_scan (header, "PC002002", "%f", 1, &coords[0].pc2_2);
+      }
+      if (!strcmp (coords[0].ctype, "DEC--PLY")) {
+	if (fits_scan (header, "NPLYTERM", "%d", 1, &itmp)) {
+	  coords[0].Npolyterms = itmp;
+	} else {
+	  coords[0].Npolyterms = 3;
+	}
+	switch (coords[0].Npolyterms) {
+	  case 3:
+	    status &= fits_scan (header, "PCA1X3Y0", "%f", 1, &coords[0].polyterms[3][0]);
+	    status &= fits_scan (header, "PCA1X2Y1", "%f", 1, &coords[0].polyterms[4][0]);
+	    status &= fits_scan (header, "PCA1X1Y2", "%f", 1, &coords[0].polyterms[5][0]);
+	    status &= fits_scan (header, "PCA1X0Y3", "%f", 1, &coords[0].polyterms[6][0]);
+	    status &= fits_scan (header, "PCA2X3Y0", "%f", 1, &coords[0].polyterms[3][1]);
+	    status &= fits_scan (header, "PCA2X2Y1", "%f", 1, &coords[0].polyterms[4][1]);
+	    status &= fits_scan (header, "PCA2X1Y2", "%f", 1, &coords[0].polyterms[5][1]);
+	    status &= fits_scan (header, "PCA2X0Y3", "%f", 1, &coords[0].polyterms[6][1]);
+	  case 2:
+	    status &= fits_scan (header, "PCA1X2Y0", "%f", 1, &coords[0].polyterms[0][0]);
+	    status &= fits_scan (header, "PCA1X1Y1", "%f", 1, &coords[0].polyterms[1][0]);
+	    status &= fits_scan (header, "PCA1X0Y2", "%f", 1, &coords[0].polyterms[2][0]);
+	    status &= fits_scan (header, "PCA2X2Y0", "%f", 1, &coords[0].polyterms[0][1]);
+	    status &= fits_scan (header, "PCA2X1Y1", "%f", 1, &coords[0].polyterms[1][1]);
+	    status &= fits_scan (header, "PCA2X0Y2", "%f", 1, &coords[0].polyterms[2][1]);
+	  case 0:
+	  case 1:
+	    break;
+	}
+      }
+    } else {
+      if (fits_scan (header, "CD1_1", "%f", 1, &coords[0].pc1_1)) {
+	status &= fits_scan (header, "CD1_2", "%f", 1, &coords[0].pc1_2);
+	status &= fits_scan (header, "CD2_1", "%f", 1, &coords[0].pc2_1);
+	status &= fits_scan (header, "CD2_2", "%f", 1, &coords[0].pc2_2);
+	/* renormalize */
+	scale = hypot (coords[0].pc1_1, coords[0].pc1_2);
+	coords[0].cdelt1 = coords[0].cdelt2 = scale;
+	coords[0].pc1_1 /= scale;
+	coords[0].pc1_2 /= scale;
+	coords[0].pc2_1 /= scale;
+	coords[0].pc2_2 /= scale;
+      } else {
+	status = FALSE;
+      }
+    }
+  } else {
+    if (fits_scan (header, "RA_O", "%lf", 1, &coords[0].crval1)) {
+      status  = fits_scan (header, "RA_X", "%f", 1, &coords[0].pc1_1);
+      status &= fits_scan (header, "RA_Y", "%f", 1, &coords[0].pc1_2);
+      status &= fits_scan (header, "DEC_O", "%lf", 1, &coords[0].crval2);  
+      status &= fits_scan (header, "DEC_X", "%f", 1, &coords[0].pc2_1);
+      status &= fits_scan (header, "DEC_Y", "%f", 1, &coords[0].pc2_2);
+      coords[0].crpix1 = coords[0].crpix2 = 0.0;
+      coords[0].cdelt1 = coords[0].cdelt2 = 1.0;
+      strcpy (coords[0].ctype, "GENE");
+    }
+  }
+  if (status) {
+    if (!fits_scan (header, "EQUINOX", "%lf", 1, &equinox)) {
+      if (!fits_scan (header, "EPOCH", "%lf", 1, &equinox)) {
+	equinox = 2000.0;
+      }
+    }
+    if (fabs (equinox - 2000.0) > 0.1) {
+      coords_precess (&coords[0].crval1, &coords[0].crval2, equinox, 2000.0);
+    } 
+  }
+  if (!status) {
+    fprintf (stderr, "error getting all elements for coordinate mode %s\n", coords[0].ctype);
+    coords[0].crval1 = coords[0].crpix1 = coords[0].cdelt1 = 0.0;
+    coords[0].crval2 = coords[0].crpix2 = coords[0].cdelt2 = 0.0;
+    coords[0].pc1_1 = coords[0].pc2_2 = 1.0;
+    coords[0].pc2_1 = coords[0].pc1_2 = 0.0;
+    strcpy (coords[0].ctype, "NONE");
+  }
+  return (status);
+}
+
+void coords_precess (double *ra, double *dec, double in_epoch, double out_epoch) {
+
+  double T;
+  double A, D, RA, DEC, zeta, z, theta;
+  double SA, CA, SD, CD;
+  
+  T = (out_epoch - in_epoch) / 100.0;
+  
+  zeta  = RAD_DEG*(0.6406161*T + 0.0000839*T*T + 0.0000050*T*T*T);
+  theta = RAD_DEG*(0.5567530*T - 0.0001185*T*T - 0.0000116*T*T*T);
+  z     =          0.6406161*T + 0.0003041*T*T + 0.0000051*T*T*T;
+  
+  A = *ra;
+  D = *dec;
+  SD =  cos(RAD_DEG*A + zeta)*sin(theta)*cos(RAD_DEG*D) + cos(theta)*sin(RAD_DEG*D);
+  CD = sqrt (1 - SD*SD);
+  SA =  sin(RAD_DEG*A + zeta)*cos(RAD_DEG*D)/CD;
+  CA = (cos(RAD_DEG*A + zeta)*cos(theta)*cos(RAD_DEG*D) - sin(theta)*sin(RAD_DEG*D))/CD;
+  
+  DEC = DEG_RAD*asin(SD);
+  RA  = DEG_RAD*atan2(SA, CA) + z;
+  
+  if (RA < 0)
+    RA += 360;
+  
+  *ra = RA;
+  *dec = DEC; 
+}
+
+/* -PLY projection is an extrapolation of the -TAN projection. 
+   In addition to the usual linear terms of CRPIXi, PC00i00j, there are 
+   higher order polynomial terms (up to 3rd order):
+   Axis 1 terms:
+   PCA1X2Y0 = coords.polyterm[0][0] = x^2                                             
+   PCA1X1Y1 = coords.polyterm[1][0] = xy                                          
+   PCA1X0Y2 = coords.polyterm[2][0] = y^2                                             
+   PCA1X3Y0 = coords.polyterm[3][0] = x^3                                             
+   PCA1X2Y1 = coords.polyterm[4][0] = x^2 y                                             
+   PCA1X1Y2 = coords.polyterm[5][0] = x y^2                                             
+   PCA1X0Y3 = coords.polyterm[6][0] = y^2                                              
+   Axis 2 terms:
+   PCA2X2Y0 = coords.polyterm[0][1] = x^2                                               
+   PCA2X1Y1 = coords.polyterm[1][1] = xy                                                
+   PCA2X0Y2 = coords.polyterm[2][1] = y^2                                               
+   PCA2X3Y0 = coords.polyterm[3][1] = x^3                                               
+   PCA2X2Y1 = coords.polyterm[4][1] = x^2 y                                             
+   PCA2X1Y2 = coords.polyterm[5][1] = x y^2                                             
+   PCA2X0Y3 = coords.polyterm[6][1] = y^2                                               
+*/
Index: /tags/start/Ohana/src/libohana/src/findexec.c
===================================================================
--- /tags/start/Ohana/src/libohana/src/findexec.c	(revision 12606)
+++ /tags/start/Ohana/src/libohana/src/findexec.c	(revision 12606)
@@ -0,0 +1,251 @@
+# include <ohana.h>
+
+int _check_permissions (char *filename) {
+  
+  struct stat filestat;
+  uid_t uid;
+  gid_t gid;
+  int status;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to exec file */
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IXUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IXGRP)) || 
+	(                            (filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IXOTH))) {
+      return (TRUE);
+    } else {
+      return (FALSE);
+    }
+  }
+  return (FALSE);
+}
+
+/* pathname
+
+   given path/filename, returns path
+   given just filename, returns . 
+   given path1/path2/,  returns path1
+*/
+
+char *pathname (char *infile) {
+ 
+  int i;
+  char *c, *file;
+
+  /* make working version */
+  file = strcreate (infile);
+
+  /* strip off trailing / */
+  for (i = strlen (file); (i > 0) && (file[i] == '/'); i--) file[i] = 0;
+
+  c = strrchr (file, '/');
+  if (c == (char *) NULL) {
+    strcpy (file, ".");
+  } else {
+    *c = 0;
+  }
+  
+  return (file);
+  
+}
+
+/* filerootname
+
+   given /path/file.ext return file 
+   given /path/file return file 
+   given /path/file/ return file 
+*/
+
+char *filerootname (char *infile) {
+
+  int i;
+  char *file, *root, *p1, *p2;
+
+  /* make working version */
+  file = strcreate (infile);
+
+  /* strip off trailing / */
+  for (i = strlen (file); (i > 0) && (file[i] == '/'); i--) file[i] = 0;
+
+  /* find last / */
+  p1 = strrchr (file, '/');
+  if (p1 == (char *) NULL) 
+    p1 = file;
+  else
+  p1 ++;
+
+  /* find last . */
+  p2 = strrchr (file, '.');
+  if (p2 == (char *) NULL) p2 = p1 + strlen(p1);
+
+  /* create new string, free working space */
+  root = strncreate (p1, p2-p1);
+  free (file);
+
+  return (root);
+
+}  
+
+/* fileextname
+
+   given /path/file.ext return ext 
+   given /path/file return NULL 
+   given /path/file/ return NULL 
+   given file.ext return ext
+*/
+
+char *fileextname (char *file) {
+
+  char *root, *p1, *p2;
+
+  /* find last / */
+  p1 = strrchr (file, '/');
+  if (p1 == (char *) NULL) p1 = file;
+
+  /* find last . after p1 */
+  p2 = strrchr (p1, '.');
+  if (p2 == (char *) NULL) return ((char *) NULL);
+  p2 ++;
+
+  /* create new string, free working space */
+  root = strncreate (p2, strlen(p2));
+  return (root);
+
+}  
+
+/* given /path/file.ext return file.ext */
+char *filebasename (char *name) {
+ 
+  char *c, *file;
+
+  ALLOCATE (file, char, strlen(name) + 1);
+  strcpy (file, name);
+  c = strrchr (file, '/');
+  if (c == (char *) NULL) {
+    strcpy (file, name);
+  } else {
+    strcpy (file, c+1);
+  }
+  
+  return (file);
+  
+}
+
+char *findexec (int argc, char **argv) {
+
+  int i, N, done, status;
+  char *c, *e, *dir, path[1024], name[1024];
+
+  /* if given an absolute or relative path, use it */
+  if (strchr (argv[0], '/') != (char *) NULL) {
+    status = _check_permissions (argv[0]);
+    if (status) {
+      if (realpath (argv[0], path) == (char *) NULL) return ((char *) NULL);
+      dir = pathname (path);
+      return (dir);
+    } else {
+      return ((char *) NULL);
+    }
+  }
+  N = 0;
+  for (i = argc+1; argv[i] != (char *) NULL; i++) {
+    if (!strncmp (argv[i], "PATH", 4)) {
+      N = i;
+      break;
+    }
+  }
+
+  if (N) {
+    c = &argv[N][5];
+    e = strchr (c, ':');
+    done = FALSE;
+    i = 0;
+    while (!done) {
+      bzero (path, 1024);
+      if (e == (char *) NULL) {
+	done = TRUE;
+	strncpy (path, c, strlen(c));
+      } else {
+	strncpy (path, c, e-c);
+	c = e+1;
+	e = strchr (c, ':');
+      }
+      sprintf (name, "%s/%s", path, argv[0]);
+      status = _check_permissions (name);
+
+      if (status) {
+	if (realpath (name, path) == (char *) NULL) continue;
+	dir = pathname (path);
+	return (dir);
+      }
+    }
+  }
+  return ((char *) NULL);
+}
+
+int mkdirhier (char *path) {
+
+  char *tpath;
+
+  if (mkdir (path, 0777)) {
+    if (errno == ENOENT) { 
+      tpath = pathname (path);
+      if (!mkdirhier (tpath)) {
+	if (mkdir (path, 0777)) {
+	  return (-1);
+	} else {
+	  errno = 0;
+	  return (0);
+	}
+      } else {
+	return (-1);
+      }
+    } else {
+      return (-1);
+    }
+  } else {
+    return (0);
+  }
+}
+
+char *getcwd_cfht (char *path, int size) {
+  
+  char *hostname, *newpath, *p;
+
+  path = getcwd (path, size);
+  
+  if (!strncmp (path, "/local/data", strlen ("/local/data"))) {
+    
+    ALLOCATE (hostname, char, size);
+
+    if (gethostname (hostname, size-1)) {
+      fprintf (stderr, "ERROR: can't get hostname\n");
+      free (hostname);
+      return ((char *) NULL);
+    }
+    if ((p = strchr (hostname, '.')) != (char *) NULL) *p = 0;
+    
+    ALLOCATE (newpath, char, size);
+    /* path might be just /local/data or /local/data/ */
+       
+    p = path + strlen ("/local/data/");
+    if (strlen (path) <= strlen ("/local/data/")) {
+      snprintf (newpath, size, "/data/%s", hostname);
+    } else {
+      snprintf (newpath, size, "/data/%s/%s", hostname, p);
+    }      
+
+    free (hostname);
+    strcpy (path, newpath);
+
+    free (newpath);
+
+  }
+
+  return (path);
+
+}
Index: /tags/start/Ohana/src/libohana/src/glockfile.c
===================================================================
--- /tags/start/Ohana/src/libohana/src/glockfile.c	(revision 12606)
+++ /tags/start/Ohana/src/libohana/src/glockfile.c	(revision 12606)
@@ -0,0 +1,294 @@
+# include <ohana.h>
+
+/* lockfile concepts:
+   
+   set a lockfile on [path]/filename.  
+   we allow three types of locks: 
+   LCK_HARD - exclusive lock with persistent lock file
+   LCK_XCLD - exclusive lock, no persistent lock file
+   LCK_SOFT - shared lock
+
+   both lock types set a filesystem-level lock on the given file, 
+    using exclusive for hard and shared for soft locks
+
+   a hard lock also uses a lockfile to make the lock permanent:
+    the lockfile must be actively removed and will not vanish 
+    even if the locking program dies 
+
+   a soft lock will vanish if the locking program dies.
+
+   if a hard lock is set, both hard & soft locks will block
+   if a soft lock is set, a hard lock will block, but not a soft lock
+
+   the hard lockfile uses the file [path]/.filename.lck
+
+   setlockfile2 returns a file descriptor to an open READ/WRITE access file,
+     or -1 on failure, and sets state.
+*/
+
+FILE *fsetlockfile (char *filename, double timeout, int type, int *state) {
+  
+  int fd;
+  FILE *f;
+
+  fd = setlockfile2 (filename, timeout, type, state);
+  if (fd == -1) return ((FILE *) NULL);
+
+  /* setlockfile2 returns a pointer to a vile open for update */
+  f = fdopen (fd, "r+");
+  if (f == (FILE *) NULL) {
+    clearlockfile2 (filename, fd, type, state);
+    fprintf (stderr, "can't make stream from descriptor\n");
+    return ((FILE *) NULL);
+  }
+  return (f);
+}
+
+int fclearlockfile (char *filename, FILE *f, int type, int *state) {
+
+  int fd, status;
+
+  fflush (f);
+  fd = fileno (f);
+  status = clearlockfile2 (filename, fd, type, state);
+  fclose (f);
+  return (status);
+}
+
+int setlockfile2 (char *filename, double timeout, int type, int *state) {
+  
+  int i, done, nbytes, status;
+  char *lockname, buffer[64];
+  char *file, *path;
+  int fd, flock;
+  int filemode;
+  struct stat filestat;
+  struct flock filelock;
+  struct timeval now, then;
+
+  /* initial values at -1, close if the are set to another value */
+  fd = flock = -1;
+
+  file = path = lockname = (char *) NULL;
+  gettimeofday (&then, (void *) NULL);
+
+  /* define lock type */
+  filelock.l_start  = 0;
+  filelock.l_whence = SEEK_SET;
+  filelock.l_len    = 0;
+  filelock.l_pid    = getpid ();
+  switch (type) {
+  case LCK_HARD:
+  case LCK_XCLD:
+    filelock.l_type   = F_WRLCK;  /* set an exclusive lock */
+    filemode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    break;
+  case LCK_SOFT:
+    filelock.l_type   = F_RDLCK;  /* set a shared lock */
+    filemode = S_IRUSR | S_IRGRP | S_IROTH;
+    break;
+  default:
+    fprintf (stderr, "invalid lock type %d\n", type);
+  }
+
+  /* if soft & file does not exist, return LCK_ACCESS */
+  if (type == LCK_SOFT) {
+    status = stat (filename, &filestat);
+    if ((status == -1) && (errno == ENOENT)) {
+      *state = LCK_EMPTY;
+      goto failure;
+    } 
+  }
+  
+  /* try to open file */
+  fd = open (filename, O_RDWR | O_CREAT, filemode);
+  if (fd == -1) {
+    *state = LCK_ACCESS;
+    goto failure;
+  }
+
+  /* we first try to set a FS level lock on the file */
+  for (done = 0; !done; ) {
+
+    /* check for timeout */
+    gettimeofday (&now, (void *) NULL);
+    if (DTIME (now, then) > timeout) {
+      *state = LCK_TIMEOUT;
+      goto failure;
+    }
+    usleep (1000);
+
+    /* try to lock file */
+    if (fcntl (fd, F_SETLK, &filelock) != -1) done = 1;
+  }
+
+  if (type == LCK_HARD) {
+    /* we've locked filename, now check lockname */ 
+
+    /* locking the lockfile before checking / setting contents will 
+       ensure the data is synced across NFS */
+    
+    /* set up name to lockfile */
+    path = pathname (filename);
+    file = filebasename (filename);
+    ALLOCATE (lockname, char, strlen (path) + strlen (file) + 10);
+    sprintf (lockname, "%s/.%s.lck", path, file);
+
+    /* try to open lockfile */
+    flock = open (lockname, O_RDWR | O_CREAT, filemode);
+    if (flock == -1) {
+      *state = LCK_HARDLCK;
+      goto failure;
+    }
+    
+    /* try a few times to lock lockfile */
+    for (i = 0; (i < 20) && (fcntl (flock, F_SETLK, &filelock) == -1); i++) {
+      usleep (10000);
+    }
+    if (i == 20) {
+      *state = LCK_HARDLCK + 10;
+      goto failure;
+    }
+    
+    /* we've locked the file, now read the contents */
+    nbytes = read (flock, buffer, 4);
+    if (nbytes == 4) { /* lock file has a word in it */
+      buffer[4] = 0;
+      if (!strcmp (buffer, "BUSY")) { 
+	*state = LCK_HARDLCK + 20;
+	goto failure;
+      }
+    }
+    
+    /* we've really got the lock, write BUSY to protect it */
+    lseek (flock, 0, SEEK_SET);
+    write (flock, "BUSY", 4);
+    
+    /* now unlock lockfile */
+    filelock.l_type = F_UNLCK;
+    if (fcntl (flock, F_SETLK, &filelock) == -1) {
+      *state = LCK_HARDLCK + 30;
+      goto failure;
+    }
+    if (close (flock)) {
+      fprintf (stderr, "error closing lock\n");
+      goto failure;
+    }
+    flock = -1;
+  }
+
+  /* check if file is empty or not */
+  if (fstat (fd, &filestat)) {
+    *state = LCK_UNKNOWN;
+  } else {
+    if (filestat.st_size == 0) {
+      *state = LCK_EMPTY;
+    } else {
+      *state = LCK_FULL;
+    }
+  }
+
+  if (path != NULL) free (path);
+  if (file != NULL) free (file);
+  if (lockname != NULL) free (lockname);
+  return (fd);
+
+failure:
+  if (fd != -1) close (fd);
+  if (flock != -1) close (flock);
+  if (path != NULL) free (path);
+  if (file != NULL) free (file);
+  if (lockname != NULL) free (lockname);
+  return (-1);
+}
+  
+/* if we pass in -1, all we can do is clear the hardlock */
+int clearlockfile2 (char *filename, int fd, int type, int *state) {
+  
+  char *lockname;
+  int i, status;
+  char *path, *file;
+  int flock, filemode;
+  struct stat filestat;
+  struct flock filelock;
+
+  file = path = lockname = (char *) NULL;
+
+  /* define lock */
+  filelock.l_type   = F_UNLCK;
+  filelock.l_start  = 0;
+  filelock.l_whence = SEEK_SET;
+  filelock.l_len    = 0;
+  filelock.l_pid    = getpid ();
+  filemode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+
+  /* first clear hard lockfile */
+  if (type == LCK_HARD) {
+
+    /* define lockfile */
+    path = pathname (filename);
+    file = filebasename (filename);
+    ALLOCATE (lockname, char, strlen (path) + strlen (file) + 10);
+    sprintf (lockname, "%s/.%s.lck", path, file);
+    
+    /* check for lockfile existence */
+    status = stat (lockname, &filestat);
+    if (status == -1) {
+      *state = LCK_HUNLOCK;
+      goto failure;
+    } 
+  
+    /* open lockfile */
+    flock = open (lockname, O_RDWR | O_CREAT, filemode);
+    if (flock == -1) {
+      *state = LCK_HUNLOCK;
+      goto failure;
+    }
+
+    /* try a few times to lock lockfile */
+    filelock.l_type = F_WRLCK;
+    for (i = 0; (i < 20) && (fcntl (flock, F_SETLK, &filelock) == -1); i++) {
+      usleep (10000);
+    }
+    if (i == 20) {
+      *state = LCK_HUNLOCK;
+      goto failure;
+    }
+
+    /* set value to IDLE */
+    lseek (flock, 0, SEEK_SET);
+    write (flock, "IDLE", 4);
+
+    /* unlock lockfile */
+    filelock.l_type = F_UNLCK;
+    if (fcntl (flock, F_SETLK, &filelock) == -1) {
+      *state = LCK_HUNLOCK;
+      goto failure;
+    }
+    if (close (flock)) {
+      fprintf (stderr, "error closing lock\n");
+      goto failure;
+    }
+  }
+  
+  /* now unlock the file */
+  if (fd != -1) {
+    if (fcntl (fd, F_SETLK, &filelock) == -1) {
+      *state = LCK_HUNLOCK;
+      goto failure;
+    }
+  }
+
+  *state = LCK_UNLOCK;
+  if (path != NULL) free (path);
+  if (file != NULL) free (file);
+  if (lockname != NULL) free (lockname);
+  return (1);
+
+failure:
+  if (path != NULL) free (path);
+  if (file != NULL) free (file);
+  if (lockname != NULL) free (lockname);
+  return (0);
+
+}
Index: /tags/start/Ohana/src/libohana/src/phot_catalog.c
===================================================================
--- /tags/start/Ohana/src/libohana/src/phot_catalog.c	(revision 12606)
+++ /tags/start/Ohana/src/libohana/src/phot_catalog.c	(revision 12606)
@@ -0,0 +1,357 @@
+# include <ohana.h>
+# include <loneos.h>
+
+SecFilt *FixOldSecFilt (OldSecFilt *in, int Nvalues);
+Average *FixOldAverage (OldAverage *in, int Nvalues);
+Measure *FixOldMeasure (OldMeasure *in, int Nvalues);
+
+/* possible exit status for lock_catalog: 
+   0 - failure (including lock failure)
+   1 - success
+   2 - empty file (file may be open or closed!) 
+*/
+
+int lock_catalog (Catalog *catalog, int lockmode) {
+
+  int dbstate;
+
+  /* set lock on database, create stream f */
+  catalog[0].f  = (FILE *) NULL;
+  catalog[0].f = fsetlockfile (catalog[0].filename, 3600.0, lockmode, &dbstate);
+  if (dbstate == LCK_EMPTY) return (2);
+  if (catalog[0].f == (FILE *) NULL) return (0);
+
+  fseek (catalog[0].f, 0, SEEK_SET);
+  catalog[0].lockmode = lockmode;
+
+  return (1);
+}
+
+int unlock_catalog (Catalog *catalog) {
+
+  int dbstate;
+
+  if (catalog[0].f == (FILE *) NULL) return (2);
+  fclearlockfile (catalog[0].filename, catalog[0].f, catalog[0].lockmode, &dbstate);
+  return (1);
+}
+
+/* this is (a bit) dangerous: the load function will automatically
+   convert from the old (Loneos) format to the new (CFHT) format.
+   But, if you load an old-format catalog, then save the new-format
+   version, the new file will be corrupted unless you load all four
+   data components.  Actually, 'save_catalog' assumes you've loaded
+   all four anyway, so it is not such a problem... */
+
+int load_catalog (Catalog *catalog, char mode, int VERBOSE) {
+  
+  int Nitems, nitems;
+  int i, Nmeas, Nmiss, size, ssize;
+  int NewMeasure, NewAverage, NewSecFilt;
+  FILE *f;
+  OldMeasure *tmpmeasure;
+  OldAverage *tmpaverage;
+  OldSecFilt *tmpsecfilt;
+  struct stat filestatus;
+
+  f = catalog[0].f;
+  fseek (f, 0, SEEK_SET);
+
+  /* read catalog header */
+  if (!fits_load_header (f, &catalog[0].header)) {
+    if (VERBOSE) fprintf (stderr, "catalog file does not exist: %s\n", catalog[0].filename);
+    return (FALSE);
+  }
+
+  /* this is done by the load anyway... */
+  fseek (f, catalog[0].header.size, SEEK_SET); 
+
+  /* get the components from the header */
+  catalog[0].Naverage = catalog[0].Nmeasure = catalog[0].Nmissing = catalog[0].Nsecfilt = 0;
+  if (!fits_scan (&catalog[0].header, "NSTARS",   "%d", 1, &catalog[0].Naverage)) return (FALSE);
+  if (!fits_scan (&catalog[0].header, "NMEAS",    "%d", 1, &catalog[0].Nmeasure)) return (FALSE);
+  if (!fits_scan (&catalog[0].header, "NMISS",    "%d", 1, &catalog[0].Nmissing)) return (FALSE);
+  if (!fits_scan (&catalog[0].header, "NSECFILT", "%d", 1, &catalog[0].Nsecfilt)) catalog[0].Nsecfilt = 0;
+  if (!fits_scan (&catalog[0].header, "NEWMEAS",  "%t", 1, &NewMeasure)) NewMeasure = FALSE;
+  if (!fits_scan (&catalog[0].header, "NEWAVES",  "%t", 1, &NewAverage)) NewAverage = FALSE;
+  if (!fits_scan (&catalog[0].header, "NEWSECF",  "%t", 1, &NewSecFilt)) NewSecFilt = FALSE;
+
+  /* predicted file size - for double checking data validity */
+  size = catalog[0].header.size;
+  ssize = NewAverage ? sizeof (Average) : sizeof (OldAverage);
+  size += ssize * catalog[0].Naverage;
+  ssize = NewMeasure ? sizeof (Measure) : sizeof (OldMeasure);
+  size += ssize * catalog[0].Nmeasure;
+  ssize = sizeof (Missing);
+  size += ssize * catalog[0].Nmissing;
+  ssize = NewSecFilt ? sizeof (SecFilt) : sizeof (OldSecFilt);
+  size += ssize * catalog[0].Nsecfilt * catalog[0].Naverage;
+
+  /* check that file size makes sense */
+  if (stat (catalog[0].filename, &filestatus) == -1) {
+    if (VERBOSE) fprintf (stderr, "failed to get status of catalog\n");
+    return (FALSE);
+  }
+  if (size > filestatus.st_size) {
+    if (VERBOSE) {
+      fprintf (stderr, "star catalog has inconsistent size\n");
+      ssize = NewAverage ? sizeof (Average) : sizeof (OldAverage);
+      fprintf (stderr, "average: %d = %d bytes\n", catalog[0].Naverage, catalog[0].Naverage*ssize);
+      ssize = NewMeasure ? sizeof (Measure) : sizeof (OldMeasure);
+      fprintf (stderr, "measure: %d = %d bytes\n", catalog[0].Nmeasure, catalog[0].Nmeasure*ssize);
+      ssize = sizeof (Missing);
+      fprintf (stderr, "missing: %d = %d bytes\n", catalog[0].Nmissing, catalog[0].Nmissing*ssize);
+      ssize = NewSecFilt ? sizeof (SecFilt) : sizeof (OldSecFilt);
+      fprintf (stderr, "secfilt: %d = %d bytes\n", catalog[0].Nsecfilt, catalog[0].Nsecfilt*catalog[0].Naverage*ssize);
+      fprintf (stderr, "expect: %d, found: %d\n", size, (int)filestatus.st_size);
+    }
+    return (FALSE);
+  } 
+  if (size < filestatus.st_size) {
+    if (VERBOSE) fprintf (stderr, "warning: file larger than expected\n");
+  } 
+
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars yet in catalog %s\n", catalog[0].filename);
+    return (TRUE);
+  }
+
+  if (mode & LOAD_AVES) {
+    /* read average values */
+    if (NewAverage) {
+      ALLOCATE (catalog[0].average, Average, MAX (catalog[0].Naverage, 1));
+      Nitems = catalog[0].Naverage;
+      nitems = Fread (catalog[0].average, sizeof(Average), Nitems, f, "average");
+    } else {
+      ALLOCATE (tmpaverage, OldAverage, MAX (catalog[0].Naverage, 1));
+      Nitems = catalog[0].Naverage;
+      nitems = Fread (tmpaverage, sizeof(OldAverage), Nitems, f, "oldaverage");
+      catalog[0].average = FixOldAverage (tmpaverage, Nitems);
+    }
+    if (nitems != Nitems) {
+      if (VERBOSE) fprintf (stderr, "failed to read averages from catalog file %s (%d vs %d)\n", catalog[0].filename, nitems, Nitems);
+      return (FALSE);
+    }
+  } else {
+    /* skip over averages */
+    fseek (f, catalog[0].Naverage * sizeof(Average), SEEK_CUR); 
+  }    
+  
+  if (mode & LOAD_MEAS) {
+    /* read measurements */
+    if (NewMeasure) {
+      ALLOCATE (catalog[0].measure, Measure, MAX (catalog[0].Nmeasure, 1));
+      Nitems = catalog[0].Nmeasure;
+      nitems = Fread (catalog[0].measure, sizeof(Measure), Nitems, f, "measure");
+    } else {
+      ALLOCATE (tmpmeasure, OldMeasure, MAX (catalog[0].Nmeasure, 1));
+      Nitems = catalog[0].Nmeasure;
+      nitems = Fread (tmpmeasure, sizeof(OldMeasure), Nitems, f, "oldmeasure");
+      catalog[0].measure = FixOldMeasure (tmpmeasure, Nitems);
+    }
+    if (nitems != Nitems) {
+      if (VERBOSE) fprintf (stderr, "failed to read measures from catalog file %s (%d vs %d)\n", catalog[0].filename, nitems, Nitems);
+      return (FALSE);
+    }
+  } else {
+    /* skip over measures */
+    fseek (f, catalog[0].Nmeasure * sizeof(Measure), SEEK_CUR); 
+  } 
+
+  if (mode & LOAD_MISS) {
+    /* read missing */
+    ALLOCATE (catalog[0].missing, Missing, MAX (catalog[0].Nmissing, 1));
+    Nitems = catalog[0].Nmissing;
+    nitems = Fread (catalog[0].missing, sizeof(Missing), Nitems, f, "missing");
+    if (nitems != Nitems) {
+      if (VERBOSE) fprintf (stderr, "failed to read missing from catalog file %s (%d vs %d)\n", catalog[0].filename, nitems, Nitems);
+      return (FALSE);
+    }
+  } else {
+    /* skip over missings */
+    fseek (f, catalog[0].Nmissing * sizeof(Missing), SEEK_CUR); 
+  }
+  
+  if (mode & LOAD_SECF) {
+    /* read missing */
+    if (NewSecFilt) {
+      Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
+      ALLOCATE (catalog[0].secfilt, SecFilt, MAX (Nitems, 1));
+      nitems = Fread (catalog[0].secfilt, sizeof(SecFilt), Nitems, f, "secfilt");
+    } else {
+      Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
+      ALLOCATE (tmpsecfilt, OldSecFilt, MAX (Nitems, 1));
+      nitems = Fread (tmpsecfilt, sizeof(OldSecFilt), Nitems, f, "oldsecfilt");
+      catalog[0].secfilt = FixOldSecFilt (tmpsecfilt, Nitems);
+    } 
+    if (nitems != Nitems) {
+      if (VERBOSE) fprintf (stderr, "failed to read secondary filters from catalog file %s (%d vs %d)\n", catalog[0].filename, nitems, Nitems);
+      return (FALSE);
+    }
+  } else {
+    /* skip over secfilts */
+    fseek (f, catalog[0].Naverage * catalog[0].Nsecfilt * sizeof(SecFilt), SEEK_CUR); 
+  }
+
+  if (VERBOSE) fprintf (stderr, "read %d stars from catalog file %s (%d measurements, %d missing, %d secondary filters)\n", 
+	   catalog[0].Naverage, catalog[0].filename, catalog[0].Nmeasure, catalog[0].Nmissing, catalog[0].Nsecfilt);
+
+  /* check data integrity */
+  if (mode & LOAD_AVES) {
+    for (i = Nmeas = Nmiss = 0; i < catalog[0].Naverage; i++) {
+      Nmeas += catalog[0].average[i].Nm; 
+      Nmiss += catalog[0].average[i].Nn; 
+    }
+    if ((Nmeas != catalog[0].Nmeasure) || (Nmiss != catalog[0].Nmissing)) {
+      if (VERBOSE) {
+	fprintf (stderr, "****** data in catalog %s is corrupt, sums don't check\n", catalog[0].filename);
+	fprintf (stderr, "****** Nmeas: %d, %d\n", Nmeas, catalog[0].Nmeasure);
+	fprintf (stderr, "****** Nmiss: %d, %d\n", Nmiss, catalog[0].Nmissing);
+      }
+      return (FALSE);
+    }
+  }
+  return (TRUE);
+}
+
+/* this is not robust: an error will not return us to the original
+   state.  But, it is faster: only limited data written to disk? *
+*/
+
+int save_catalog (Catalog *catalog, char VERBOSE) {
+
+  int Nitems, nitems;
+  FILE *f;
+
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (TRUE);
+  }
+
+  /* make sure header is consistent with data */
+  fits_modify (&catalog[0].header, "NSTARS",   "%d", 1, catalog[0].Naverage);
+  fits_modify (&catalog[0].header, "NMEAS",    "%d", 1, catalog[0].Nmeasure);
+  fits_modify (&catalog[0].header, "NMISS",    "%d", 1, catalog[0].Nmissing);
+  fits_modify (&catalog[0].header, "NSECFILT", "%d", 1, catalog[0].Nsecfilt);
+  fits_modify (&catalog[0].header, "NEWMEAS",  "%t", 1, TRUE);
+  fits_modify (&catalog[0].header, "NEWAVES",  "%t", 1, TRUE);
+  fits_modify (&catalog[0].header, "NEWSECF",  "%t", 1, TRUE);
+
+  f = catalog[0].f;
+  /* rewind file pointers and truncate */
+  fseek (f, 0, SEEK_SET);
+  ftruncate (fileno (catalog[0].f), 0);
+
+  nitems = Fwrite (catalog[0].header.buffer, 1, catalog[0].header.size, f, "char");
+  if (nitems != catalog[0].header.size) {
+    if (VERBOSE) fprintf (stderr, "failed to write header\n");
+    return (FALSE);
+  }
+
+  Nitems = catalog[0].Naverage;
+  nitems = Fwrite (catalog[0].average, sizeof(Average), Nitems, f, "average");
+  if (nitems != Nitems) {
+    if (VERBOSE) fprintf (stderr, "failed to write catalog file aves %s\n", catalog[0].filename);
+    return (FALSE);
+  }
+  
+  Nitems = catalog[0].Nmeasure;
+  nitems = Fwrite (catalog[0].measure, sizeof(Measure), Nitems, f, "measure");
+  if (nitems != Nitems) {
+    if (VERBOSE) fprintf (stderr, "failed to write catalog file meas %s\n", catalog[0].filename);
+    return (FALSE);
+  }
+
+  Nitems = catalog[0].Nmissing;
+  nitems = Fwrite (catalog[0].missing, sizeof(Missing), Nitems, f, "missing");
+  if (nitems != Nitems) {
+    if (VERBOSE) fprintf (stderr, "failed to write catalog file miss %s\n", catalog[0].filename);
+    return (FALSE);
+  }
+
+  Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
+  nitems = Fwrite (catalog[0].secfilt, sizeof(SecFilt), Nitems, f, "secfilt");
+  if (nitems != Nitems) {
+    if (VERBOSE) fprintf (stderr, "failed to write catalog file secondary filters %s\n", catalog[0].filename);
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+/**** tools to convert between formats - this happens automatically in load_catalog */
+
+Measure *FixOldMeasure (OldMeasure *in, int Nvalues) {
+
+  int i;
+  Measure *out;
+
+  ALLOCATE (out, Measure, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].dR = in[i].dR;
+    out[i].dD = in[i].dD;
+    out[i].M  = in[i].M;
+    out[i].dM = in[i].dM;
+    out[i].Mcal = in[i].Mcal;
+    out[i].dophot = in[i].dophot;
+    out[i].source = in[i].source;
+    out[i].t = in[i].t;
+
+    out[i].dt = 0xffff;
+    out[i].averef = in[i].average & 0x00ffffff;
+    out[i].flags  = (in[i].average & 0xff000000) >> 24;
+  }
+
+  free (in);
+  
+  return (out);
+}
+
+Average *FixOldAverage (OldAverage *in, int Nvalues) {
+
+  int i;
+  Average *out;
+
+  ALLOCATE (out, Average, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].R       = in[i].R;      
+    out[i].D       = in[i].D;      
+    out[i].M       = in[i].M;      
+    out[i].Xp      = in[i].Xp;     
+    out[i].Xm      = in[i].Xm;     
+    out[i].Nm      = in[i].Nm;     
+    out[i].Nn      = in[i].Nn;     
+    out[i].code    = in[i].code;   
+    out[i].offset  = in[i].offset; 
+    out[i].missing = in[i].missing;
+
+    out[i].dM = 0xffff;
+  }
+
+  free (in);
+  
+  return (out);
+}
+
+SecFilt *FixOldSecFilt (OldSecFilt *in, int Nvalues) {
+
+  int i;
+  SecFilt *out;
+
+  ALLOCATE (out, SecFilt, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].M    = in[i].M;      
+    out[i].Xm   = in[i].Xm;      
+
+    out[i].dM   = 0xffff;
+  }
+
+  free (in);
+  
+  return (out);
+}
+
Index: /tags/start/Ohana/src/libohana/src/photfits.c
===================================================================
--- /tags/start/Ohana/src/libohana/src/photfits.c	(revision 12606)
+++ /tags/start/Ohana/src/libohana/src/photfits.c	(revision 12606)
@@ -0,0 +1,254 @@
+# include <ohana.h>
+# include <loneos.h>
+# define MAX_ORDER 3
+
+/* convert double to low-precision short int */
+short int putMi (double value) {
+  
+  double T;
+  unsigned int I;
+
+  if (value > 0) {
+    T = 1000 * log10 (value);
+    I = MAX (MIN (T, 16383), -16382) + 0x3fff;
+    return (I);
+  }
+  if (value < 0) {
+    T = -value;
+    T = 1000 * log10 (T);
+    I = MAX (MIN (T, 16383), -16382) + 0xbfff;
+    return (I);
+  }
+  if (value == 0) {
+    I = 0;
+    return (0);
+  }
+  return (NO_MAG);
+}
+
+/* convert low-precision short int to double */
+double getMi (short int value) {
+  
+  double T, V, sign;
+  short int I;
+
+  if (value == 0) {
+    return (0.0);
+  }
+  if (value & 0x8000) {
+    sign = -1;
+    I = value & 0x7fff;
+  } else {
+    sign = +1;
+    I = value;
+  }
+    
+  T = (I - 0x3fff) / 1000.0;
+  V = sign * pow (10.0, T);
+  return (V);
+}
+
+/* convert image parameters to c[i] coeffs */
+/* all terms of order > 0 are stored as 16bit floats 
+   the zero-order term is stored as a short int (-32k,+32k) */
+
+void returnMcal (Image *image, double *c) {
+
+  switch (image[0].order) {
+  case 0:
+    c[0] = image[0].Mcal;
+    return;
+  case 1:
+    c[0] = image[0].Mcal;
+    c[1] = getMi (image[0].Mx);
+    c[2] = getMi (image[0].My);
+    return;
+  case 2:
+    c[0] = image[0].Mcal;
+    c[1] = getMi (image[0].Mx);
+    c[2] = getMi (image[0].Mxx);
+    c[3] = getMi (image[0].My);
+    c[4] = getMi (image[0].Mxy);
+    c[5] = getMi (image[0].Myy);
+    return;
+  case 3:
+    c[0] = image[0].Mcal;
+    c[1] = getMi (image[0].Mx);
+    c[2] = getMi (image[0].Mxx);
+    c[3] = getMi (image[0].Mxxx);
+    c[4] = getMi (image[0].My);
+    c[5] = getMi (image[0].Mxy);
+    c[6] = getMi (image[0].Mxxy);
+    c[7] = getMi (image[0].Myy);
+    c[8] = getMi (image[0].Mxyy);
+    c[9] = getMi (image[0].Myyy);
+    return;
+  case 4:
+    c[0] = image[0].Mcal;
+    c[1] = getMi (image[0].Mx);
+    c[2] = getMi (image[0].Mxx);
+    c[3] = getMi (image[0].Mxxx);
+    c[4] = getMi (image[0].Mxxxx);
+    c[5] = getMi (image[0].My);
+    c[6] = getMi (image[0].Mxy);
+    c[7] = getMi (image[0].Mxxy);
+    c[8] = getMi (image[0].Mxxxy);
+    c[9] = getMi (image[0].Myy);
+    c[10] = getMi (image[0].Mxyy);
+    c[11] = getMi (image[0].Mxxyy);
+    c[12] = getMi (image[0].Myyy);
+    c[13] = getMi (image[0].Mxyyy);
+    c[14] = getMi (image[0].Myyyy);
+    return;
+  default:
+    c[0] = 0;
+    return;
+  }
+}
+
+void assignMcal (Image *image, double *c, int order) {
+
+  image[0].order = order;
+
+  switch (order) {
+  case 0:
+    image[0].Mcal = c[0];
+    return;
+  case 1:
+    image[0].Mcal = c[0];
+    image[0].Mx    = putMi(c[1]);
+    image[0].My    = putMi(c[2]);
+    return;
+  case 2:
+    image[0].Mcal = c[0];
+    image[0].Mx    = putMi(c[1]);
+    image[0].Mxx   = putMi(c[2]);
+    image[0].My    = putMi(c[3]);
+    image[0].Mxy   = putMi(c[4]);
+    image[0].Myy   = putMi(c[5]);
+    return;
+  case 3:
+    image[0].Mcal = c[0];
+    image[0].Mx    = putMi(c[1]);
+    image[0].Mxx   = putMi(c[2]);
+    image[0].Mxxx  = putMi(c[3]);
+    image[0].My    = putMi(c[4]);
+    image[0].Mxy   = putMi(c[5]);
+    image[0].Mxxy  = putMi(c[6]);
+    image[0].Myy   = putMi(c[7]);
+    image[0].Mxyy  = putMi(c[8]);
+    image[0].Myyy  = putMi(c[9]);
+    return;
+  case 4:
+    image[0].Mcal = c[0];
+    image[0].Mx    = putMi(c[1]);
+    image[0].Mxx   = putMi(c[2]);
+    image[0].Mxxx  = putMi(c[3]);
+    image[0].Mxxxx = putMi(c[4]);
+    image[0].My    = putMi(c[5]);
+    image[0].Mxy   = putMi(c[6]);
+    image[0].Mxxy  = putMi(c[7]);
+    image[0].Mxxxy = putMi(c[8]);
+    image[0].Myy   = putMi(c[9]);
+    image[0].Mxyy  = putMi(c[10]);
+    image[0].Mxxyy = putMi(c[11]);
+    image[0].Myyy  = putMi(c[12]);
+    image[0].Mxyyy = putMi(c[13]);
+    image[0].Myyyy = putMi(c[14]);
+    return;
+  default:
+    image[0].Mcal = 0.0;
+    image[0].order = 0;
+    return;
+  }
+}
+
+/* return value of image fit at x,y */
+double applyMcal (Image *image, double x, double y) {
+
+  double Mcal, c[15];
+
+  returnMcal (image, c);  /* convert image parameters to c[i] coeffs */
+  Mcal = 0.0;
+  switch (image[0].order) {
+  case 0:
+    Mcal = c[0];
+    break;
+  case 1:
+    Mcal = c[0] + x*c[1] + y*c[2];
+    break;
+  case 2:
+    Mcal = c[0] + x*(c[1] + x*c[2]) + y*(c[3] + x*c[4] + y*c[5]);
+    break;
+  case 3:
+    Mcal = c[0] + x*(c[1] + x*(c[2] + x*c[3])) + y*(c[4] + x*(c[5] + x*c[6]) + y*(c[7] + x*c[8] + y*c[9]));
+    break;
+  case 4:
+    Mcal = c[0] + x*(c[1] + x*(c[2] + x*(c[3] + x*c[4]))) + y*(c[5] + x*(c[6] + x*(c[7] + x*c[8])) + y*(c[9] + x*(c[10] + x*c[11]) + y*(c[12] + x*c[13] + y*c[14])));
+    break;
+  }
+  return (Mcal);
+}
+
+double findscatter (double *X, double *Y, double *M, double *dM, int N, double *c, int order) {
+  
+  int i;
+  double *x, *y, *m, *dm;
+  double S, S2, s, dS;
+
+  S2 = S = 0;
+  if (N < 2) {
+    return (0.0);
+  }
+  
+  x = X; y = Y; m = M; dm = dM;
+  switch (order) {
+  case 0:
+    for (i = 0; i < N; i++, m++, dm++) {
+      dS  = *m - c[0];
+      *dm = dS;
+      S  += dS;
+      S2 += dS*dS;
+    }
+    break;
+  case 1:
+    for (i = 0; i < N; i++, m++, x++, y++, dm++) {
+      s   = c[0] + *x*c[1] + *y*c[2];
+      dS  = *m - s;
+      *dm = dS;
+      S  += dS;
+      S2 += dS*dS;
+    }
+    break;
+  case 2:
+    for (i = 0; i < N; i++, m++, x++, y++, dm++) {
+      s   = c[0] + *x*(c[1] + *x*c[2]) + *y*(c[3] + *x*c[4] + *y*c[5]);
+      dS  = *m - s;
+      *dm = dS;
+      S  += dS;
+      S2 += dS*dS;
+    }
+    break;
+  case 3:
+    for (i = 0; i < N; i++, m++, x++, y++, dm++) {
+      s   = c[0] + *x*(c[1] + *x*(c[2] + *x*c[3])) + *y*(c[4] + *x*(c[5] + *x*c[6]) + *y*(c[7] + *x*c[8] + *y*c[9]));
+      dS  = *m - s;
+      *dm = dS;
+      S  += dS;
+      S2 += dS*dS;
+    }
+    break;
+  case 4:
+    for (i = 0; i < N; i++, m++, x++, y++, dm++) {
+      s   = c[0] + *x*(c[1] + *x*(c[2] + *x*(c[3] + *x*c[4]))) + *y*(c[5] + *x*(c[6] + *x*(c[7] + *x*c[8])) + *y*(c[9] + *x*(c[10] + *x*c[11]) + *y*(c[12] + *x*c[13] + *y*c[14])));
+      dS  = *m - s;
+      *dm = dS;
+      S  += dS;
+      S2 += dS*dS;
+    }
+    break;
+  }
+  S = S / N;
+  S2 = sqrt (S2 / N - S*S);
+  return (S2);
+}
Index: /tags/start/Ohana/src/libohana/src/skydb.c
===================================================================
--- /tags/start/Ohana/src/libohana/src/skydb.c	(revision 12606)
+++ /tags/start/Ohana/src/libohana/src/skydb.c	(revision 12606)
@@ -0,0 +1,400 @@
+
+typedef struct {
+  float r, d;
+} SkyCoord;
+
+/* each region is bounded on the sky by lines of constant RA & DEC.
+   the region represents a specified depth, and it may or may not have
+   children.  The start and end of the children in the array are childS and childE 
+   If the region at the given depth is populated with an object table, then 'object' is TRUE.
+   If the region at the given depth is populated with an image table, then 'image' is TRUE.
+*/   
+
+typedef struct {
+  char  name[16];
+  float Rmin, Rmax;
+  float Dmin, Dmax;
+  int   childS, childE;
+  char  depth, child;
+  char  object, image;
+} SkyRegion; /* 48 bytes */ 
+
+/* I have defined no accelerators other than the table hierarchy */
+
+/* find region which overlaps c at given depth (-1 : max depth) */
+SkyRegion *SkyFindPoint (SkyRegion *db, SkyCoord c, int depth) {
+  
+  Ns = 0;
+  Ne = 1;
+
+  while (1) {
+    No = -1;
+    for (i = Ns; (No == -1) && (i < Ne); i++) {
+      if (c.r < db[i].Rmin) continue;
+      if (c.r > db[i].Rmax) continue;
+      if (c.d < db[i].Dmin) continue;
+      if (c.d > db[i].Dmax) continue;
+      // got the needed region at this depth
+      No = i;
+    }
+    if (No == -1) return ((SkyRegion *) NULL);
+    if (depth == db[No].depth) return (&db[No]);
+    if ((depth > db[No].depth) && !db[No].child) return ((SkyRegion *) NULL);
+
+    /* need to check Ns, Ne, or guarantee valid range */
+    Ns = db[No].childS;
+    Ne = db[No].childE;
+
+    if ((depth > db[No].depth) && db[No].child) continue;
+    return (&db[No]);
+  }
+}
+
+/* find regions at all levels which overlap c */
+SkyRegion **SkyFindLevels (SkyRegion *db, SkyCoord c, int *Nregion) {
+
+  SkyRegion **region;
+  
+  Ns = 0;
+  Ne = 1;
+
+  N = 0;
+  NREGION = 10;
+  ALLOCATE (region, SkyRegion *, NREGION);
+
+  while (1) {
+    No = -1;
+    for (i = Ns; (No == -1) && (i < Ne); i++) {
+      if (c.r < db[i].Rmin) continue;
+      if (c.r > db[i].Rmax) continue;
+      if (c.d < db[i].Dmin) continue;
+      if (c.d > db[i].Dmax) continue;
+      // got the needed region at this depth
+      No = i;
+    }
+    if (No == -1) return ((SkyRegion *) NULL);
+
+    region[N] = &db[No];
+    N++;
+    if (N == NREGION) {
+      NREGION += 10;
+      REALLOCATE (region, SkyRegion *, NREGION);
+    }      
+
+    /* need to check Ns, Ne, or guarantee valid range */
+    if (db[No].child) {
+      Ns = db[No].childS;
+      Ne = db[No].childE;
+    } else {
+      *Nregion = N; 
+      return (region);
+    }
+  }
+}
+
+/* find regions contained within rectangular region  c1 - c2 */
+SkyRegion **SkyFindArea (SkyRegion *db, SkyCoord c1, SkyCoord c2, *nlist) {
+
+  int Nlist;
+  SkyRegion *list, *new, *sub;
+
+  while (c1.r > 360.0) c1.r -= 360.0;
+  while (c1.r <   0.0) c1.r += 360.0;
+  while (c2.r > 360.0) c2.r -= 360.0;
+  while (c2.r <   0.0) c2.r += 360.0;
+
+  /* check on c1.r > c2.r : cross boundary */
+  if (c1.r > c2.r) {
+    c0 = c2; c0.r = 360.0;
+    list1 = SkyFindArea (db, c1, c0, &Nlist1);
+    c0 = c1; c0.r = 0.0;
+    list2 = SkyFindArea (db, c0, c2, &Nlist2);
+    Nlist = Nlist1 + Nlist2;
+    ALLOCATE (list, SkyRegion *, Nlist);
+    memcpy (&list[0], list1, Nlist1*sizeof());
+    memcpy (&list[Nlist1], list2, Nlist2*sizeof());
+    free (list1);
+    free (list2);
+    *nlist = Nlist;
+    return (list);
+  }    
+
+  Nlist = 1;
+  ALLOCATE (list, SkyRegion *, 1);
+  list[0] = &db[0];
+  getchild = db[0].child;
+
+  while (getchild) {
+
+    getchild = FALSE;
+    Nnew = 0;
+    NNEW = Nlist + 100;
+    ALLOCATE (new, SkyRegion *, NNEW);
+
+    for (i = 0; i < Nlist; i++) {
+      if (list[i][0].child) {
+	sub = SkyFindAreaDB(db, list[i], c1, c2, &Nsub);
+	if (Nnew + Nsub == NNEW) {
+	  NNEW += 100;
+	  REALLOCATE (new, SkyRegion *, NNEW);
+	}
+	for (i = 0; i < Nsub; i++) {
+	  getchild |= sub[i][0].child;
+	  new[Nnew] = sub[i];
+	  Nnew++;
+	}
+	free (sub);
+      } else {
+	new[Nnew] = list[i];
+	Nnew ++;
+	if (Nnew == NNEW) {
+	  NNEW += 100;
+	  REALLOCATE (new, SkyRegion *, NNEW);
+	}
+      }
+    }
+
+    free (list);
+    list = new;
+    Nlist = Nnew;
+  }
+
+  return (list);
+  *nlist = Nlist;
+
+}
+
+/* ?? */
+SkyRegion *SkyFindAreaDB (SkyRegion *db, SkyRegion *ref, SkyCoord c1, SkyCoord c2, int *Nregion) {
+
+  SkyRegion **region;
+  
+  Ns = ref[0].childS;
+  Ne = ref[0].childE;
+
+  N = 0;
+  NREGION = 100;
+  ALLOCATE (region, SkyRegion *, NREGION);
+
+  /* c1 min, c2 max */
+
+  for (i = Ns; (No == -1) && (i < Ne); i++) {
+    if (c2.r < db[i].Rmin) continue;
+    if (c1.r > db[i].Rmax) continue;
+    if (c2.d < db[i].Dmin) continue;
+    if (c1.d > db[i].Dmax) continue;
+
+    region[N] = &db[i];
+    N++;
+    if (N == NREGION) {
+      NREGION += 100;
+      REALLOCATE (region, SkyRegion *, NREGION);
+    }      
+  }
+  *Nregion = N; 
+  return (region);
+}
+
+SkyRegion *SkyBuildTable (SkyRegion *seed, int Nseed, int level, int depth) {
+
+  /* given a table of Rmin, Dmin, Rmax, Dmax, name, at level 3, generate
+     all higher levels and 'depth' extra levels */
+
+  /* levels:
+     0 - fullsky.cpt
+     1 - n????.cpt / s????.cpt
+     2 - r????.cpt
+     3 - ????.cpt
+     4 - ????.??.cpt
+  */
+  
+  SkyRegion *db;
+
+  /* allocate at least 30 for levels 0 & 1 */
+  NREGION = 100;
+  ALLOCATE (db, SkyRegion, NREGION);
+
+  /* full sky */
+  strcpy (db[0].name, "fullsky.cpt");
+  db[0].Rmin =   0; db[0].Rmax = 360;
+  db[0].Dmin = -90; db[0].Dmax =  90;
+  db[0].depth = 0;
+  db[0].child = FALSE;
+  N = 1;
+
+  db[0].childS = N;
+  /* north dec bands */
+  for (dec = 0; dec < 90; dec += 7.5) {
+    sprintf (db[N].name, "n%04d.cpt", (int) 100*dec);
+    db[N].Rmin =   0; db[N].Rmax = 360;
+    db[N].Dmin = dec; db[N].Dmax = dec + 7.5;
+    db[N].depth = 1;
+    db[N].child = FALSE;
+    N++;
+  }
+  /* south dec bands */
+  for (dec = 0; dec > -90; dec -= 7.5) {
+    sprintf (db[N].name, "s%04d.cpt", (int) 100*dec);
+    db[N].Rmin =   0;       db[N].Rmax = 360;
+    db[N].Dmin = dec - 7.5; db[N].Dmax = dec;
+    db[N].depth = 1;
+    db[N].child = FALSE;
+    N++;
+  }
+  db[0].childE = N;
+
+  /* subdivide dec bands based on seed */
+  Rnumber = 0;
+  childS = db[0].childS;
+  childE = db[0].childE;
+  for (i = childS; i < childE; i++) {
+
+    Nnew = 0;
+    NNEW = 100;
+    ALLOCATE (new, SkyRegion, NNEW);
+
+    for (j = 0; j < Nseed; j++) {
+      if (seed[j].Rmin > db[i].Rmax) continue;
+      if (seed[j].Rmax < db[i].Rmin) continue;
+      if (seed[j].Dmin > db[i].Dmax) continue;
+      if (seed[j].Dmax < db[i].Dmin) continue;
+      
+      for (k = 0; k < Nnew; k++) {
+	if ((seed[j].Rmin == new[k].Rmin) && 
+	    (seed[j].Rmax == new[k].Rmax)) { 
+	  goto next_seed;
+	}
+	if ((seed[j].Rmin == new[k].Rmin) ^^ 
+	    (seed[j].Rmax != new[k].Rmax)) { 
+	  fprintf (stderr, "inconsistent blocks in seed file\n");
+	  return (NULL);
+	}
+      }	
+      new[Nnew].Rmin = seed[j].Rmin;
+      new[Nnew].Rmax = seed[j].Rmax;
+      new[Nnew].Dmin = db[i].Dmin;
+      new[Nnew].Dmax = db[i].Dmax;
+      new[Nnew].depth = 2;
+      new[Nnew].child = FALSE;
+      strncpy (root, db[i].name, 5); root[5] = 0;
+      sprintf (new[Nnew].name, "%s/r%04d.cpt", root, Rnumber);
+      Rnumber ++;      
+      Nnew ++;
+      if (Nnew == NNEW) {
+	NNEW += 100;
+	REALLOCATE (new, SkyRegion, NNEW);
+      }
+    next_seed:
+    }
+    /* update db list */
+    db[i].childS = N;
+    db[i].childE = N + Nnew;
+    NREGION = N + Nnew + 100;
+    REALLOCATE (db, SkyRegion, NREGION);
+    memcpy (&db[N], new, Nnew*sizeof(SkyRegion));
+    free (new);
+    N += Nnew;
+  }
+
+  /* subdivide ra strips based on seed */
+  childS = db[db[0].childS].childS;
+  childE = db[db[0].childE - 1].childE;
+  nextS = N;
+  for (i = childS; i < childE; i++) {
+
+    Nnew = 0;
+    NNEW = 100;
+    ALLOCATE (new, SkyRegion, NNEW);
+
+    for (j = 0; j < Nseed; j++) {
+      if (seed[j].Rmin > db[i].Rmax) continue;
+      if (seed[j].Rmax < db[i].Rmin) continue;
+      if (seed[j].Dmin > db[i].Dmax) continue;
+      if (seed[j].Dmax < db[i].Dmin) continue;
+      
+      for (k = 0; k < Nnew; k++) {
+	if ((seed[j].Dmin == new[k].Dmin) && 
+	    (seed[j].Dmax == new[k].Dmax)) { 
+	  goto next_seed;
+	}
+	if ((seed[j].Dmin == new[k].Dmin) ^^ 
+	    (seed[j].Dmax != new[k].Dmax)) { 
+	  fprintf (stderr, "inconsistent blocks in seed file\n");
+	  return (NULL);
+	}
+      }	
+      new[Nnew].Dmin = seed[j].Dmin;
+      new[Nnew].Dmax = seed[j].Dmax;
+      new[Nnew].Rmin = db[i].Rmin;
+      new[Nnew].Rmax = db[i].Rmax;
+      new[Nnew].depth = 3;
+      new[Nnew].child = FALSE;
+      strcpy (new[Nnew].name, seed[j].name);
+      Nnew ++;
+      if (Nnew == NNEW) {
+	NNEW += 100;
+	REALLOCATE (new, SkyRegion, NNEW);
+      }
+    next_seed:
+    }
+    
+    /* update db list */
+    db[i].childS = N;
+    db[i].childE = N + Nnew;
+    NREGION = N + Nnew + 100;
+    REALLOCATE (db, SkyRegion, NREGION);
+    memcpy (&db[N], new, Nnew*sizeof(SkyRegion));
+    free (new);
+    N += Nnew;
+  }
+  nextE = N;
+
+  /* subdivide entries once more */
+  childS = nextS;
+  childE = nextE;
+  for (i = childS; i < childE; i++) {
+    Rnumber = 0;
+    db[i].childS = N;
+    dDec = (db[i].Dmax - db[i].Dmin) / 5.0;
+    dRa  = (db[i].Rmax - db[i].Rmin) / 5.0;
+    for (nx = 0; nx < 5; nx++) {
+      for (ny = 0; ny < 5; ny++) {
+	db[N].Dmin = db[i].Dmin + dDec * (nx + 0);
+	db[N].Dmax = db[i].Dmax + dDec * (nx + 1);
+	db[N].Rmin = db[i].Rmin + dDec * (nx + 0);
+	db[N].Rmax = db[i].Rmax + dDec * (nx + 1);
+	db[N].depth = 3;
+	db[N].child = FALSE;
+	strncpy (root, db[i].name, 10); root[10] = 0;
+	sprintf (db[N].name, "%s.%02d.cpt", root, Rnumber);
+	Rnumber ++;
+	N ++;
+	if (N == NREGION) {
+	  NREGION += 100;
+	  REALLOCATE (new, SkyRegion, NREGION);
+	}
+      }
+    }
+  }
+
+}
+
+/* region is pointer to entry in db */
+SkyRegion *SkyExtend (SkyRegion *db, SkyRegion *region) {
+
+}
+
+/* region is pointer to entry in db */
+SkyRegion *SkyContract (SkyRegion *db, SkyRegion *region) {
+
+}
+
+SkyRegion *SkyFindGCircle (SkyRegion *db, SkyCoord c1, SkyCoord c2) {
+
+}
+
+
+/* is entire db in memory, or do we load from disk for each operation? 
+   10,000 at level 3, 100,000 @ 4 : 0.5MB, 5MB */
+
+
Index: /tags/start/Ohana/src/libohana/src/string.c
===================================================================
--- /tags/start/Ohana/src/libohana/src/string.c	(revision 12606)
+++ /tags/start/Ohana/src/libohana/src/string.c	(revision 12606)
@@ -0,0 +1,157 @@
+# include <ohana.h>
+
+#ifndef whitespace
+#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
+#endif
+
+/* Strip whitespace from the start and end of STRING. */
+int stripwhite (char *string) {
+
+  int i;
+
+  if (string == (char *) NULL) return (FALSE);
+
+  for (i = 0; whitespace (string[i]); i++);
+  if (i) memmove (string, string + i, strlen(string+i)+1);
+  for (i = strlen (string) - 1; (i > 0) && whitespace (string[i]); i--);
+  string[++i] = 0;
+  return (i);
+
+}
+
+/* compare two strings either as strings, or as numbers if both are
+   pure numeric strings (base 10) */
+int strnumcmp (char *str1, char *str2) {
+
+  char *end1;
+  char *end2;
+  int num1, num2;
+  int value;
+ 
+  value = FALSE;
+  num1 = strtol (str1, &end1, 10);
+  num2 = strtol (str2, &end2, 10);
+
+  if (!end1[0] && !end2[0] && (num1 == num2)) {
+    value = TRUE;
+  }
+  if (!strcmp (str1, str2)) {
+    value = TRUE;
+  }
+  
+  return (value);
+}
+
+/* create a new string from this string */
+char *strcreate (char *string) {
+
+  char *line;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+  
+  ALLOCATE (line, char, MAX (1, strlen(string)) + 1);
+  line = strcpy (line, string);
+
+  return (line);
+}
+
+/* create a new string of length n from this string */
+char *strncreate (char *string, int n) {
+
+  char *line;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+  
+  ALLOCATE (line, char, n + 1);
+  memcpy (line, string, n);
+  line[n] = 0;
+  return (line);
+}
+
+int scan_line (FILE *f, char *line) {
+
+  int i, status;
+  char c;
+  
+  status = EOF + 1;
+  
+  for (i = 0, c = 0; (c != '\n') && (status != EOF); i++) {
+    status = fscanf (f, "%c", &c);
+    line[i] = c;
+  }
+  line[i - 1] = 0;  /* this could make things crash! */
+
+  if (i > 1) {
+    status = EOF + 1;
+  }
+
+  return (status);
+}
+
+char *_parse_nextword (char *string) {
+
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (; isspace (*string); string++);
+  for (; (*string != 0) && !isspace (*string); string++);
+  for (; isspace (*string); string++);
+  return (string);
+}
+
+int dparse (double *X, int NX, char *line) {
+
+  int i;
+  char *word;
+  char *ptr;
+
+  word = line;
+  for (i = 0; i < NX - 1; i++)
+    word = _parse_nextword (word);
+
+  *X = strtod (word, &ptr);
+  if (ptr == word) return (FALSE);
+  if (word[0] == '-') return (-1);
+  return (1);
+}
+
+int fparse (float *X, int NX, char *line) {
+
+  int i;
+  char *word;
+  char *ptr;
+
+  word = line;
+  for (i = 0; i < NX - 1; i++)
+    word = _parse_nextword (word);
+
+  *X = strtod (word, &ptr);
+  if (ptr == word) return (FALSE);
+  if (word[0] == '-') return (-1);
+  return (1);
+}
+
+int get_argument (int argc, char **argv, char *arg) {
+
+  int i;
+
+  for (i = 0; i < argc; i++) {
+    if (!strcmp(argv[i], arg))
+      return (i);
+  }
+  
+  return ((int)NULL);
+}
+
+int remove_argument (int N, int *argc, char **argv) {
+
+  int i;
+
+  if ((N != (int)NULL) && (N != 0)) {
+    (*argc)--;
+    for (i = N; i < *argc; i++) {
+      argv[i] = argv[i+1];
+    }
+  }
+
+  return (N);
+}
Index: /tags/start/Ohana/src/lightcurve/Makefile
===================================================================
--- /tags/start/Ohana/src/lightcurve/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/Makefile	(revision 12606)
@@ -0,0 +1,53 @@
+include ../../Configure
+PROGRAM =	lightcurve
+HOME 	=	$(ROOT)/lightcurve
+
+default: $(PROGRAM)
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#  
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lohana -lFITS -lm 
+CFLAGS	=	-o $*.o $(INCS) 
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+OBJS = \
+$(SRC)/args.o 		$(SRC)/get_names.o \
+$(SRC)/get_stars.o 	$(SRC)/sort_stars.o \
+$(SRC)/get_unique.o 	$(SRC)/get_sources.o \
+$(SRC)/get_info.o 	$(SRC)/make_table.o \
+$(SRC)/lightcurve.o	\
+$(SRC)/sort_seq.o	\
+$(SRC)/help.o 
+
+$(OBJS): $(INC)/lightcurve.h
+
+$(PROGRAM):	$(BIN)/$(PROGRAM)
+
+$(BIN)/$(PROGRAM): $(OBJS)
+	$(CC) $(OBJS) -o $(BIN)/$(PROGRAM) $(CCFLAGS)
+
+# -----------------------
+install:
+	rm -f $(DESTBIN)/$(PROGRAM)
+#	rm -f $(DESTMAN)/$(PROGRAM).1
+	cp $(BIN)/$(PROGRAM)   $(DESTBIN)/
+#	cp $(MAN)/$(PROGRAM).1 $(DESTMAN)/
+
+clean:	
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+dist: clean
+	rm -f $(BIN)/$(PROGRAM)
+
Index: /tags/start/Ohana/src/lightcurve/include/lightcurve.h
===================================================================
--- /tags/start/Ohana/src/lightcurve/include/lightcurve.h	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/include/lightcurve.h	(revision 12606)
@@ -0,0 +1,67 @@
+# include <ohana.h>
+
+# define EMPTY          -1   
+# define END            (star_data_type *) -1
+
+# define C_LAMBDA       23.0
+# define MCAL(I,dR,dD) (((I.Mcal) + (dR)*(I.McalR) + (dD)*(I.McalD) + (dR)*(dR)*(I.McalR2) + (dD)*(dD)*(I.McalD2) + (dD)*(dR)*(I.McalRD)))
+
+int PRINT;
+int MIDAS;
+int EXTRASTARS;
+int PIXELS;
+int NLOOP;
+double RADIUS;
+double A_LAMBDA;
+double SIG;
+double COS;
+double MCUTOFF;
+char OUTFILE[100];
+char IMAGES[100];
+
+typedef struct Star {
+  double RA, Dec;
+  double ap, m, dm;
+  struct Star *next_this_unique;
+  struct Star *next_this_image;
+  int    image_number, star_number, unique_number;
+} Star;
+
+typedef struct {
+  char    name[50];
+  int     Nunique, Nstars;
+  int     fixed, empty;
+  Star   *first_this_image;
+  double  Mcal, dMcal;
+  double  exptime, airmass, clouds, Mtime, AmF, dAmF, JD;
+  double  RA_O, RA_X, RA_Y, DEC_O, DEC_X, DEC_Y;
+  double  McalR, McalD, McalR2, McalD2, McalRD;
+} Image;
+
+typedef struct {
+  double  Mrel, dMrel;
+  int     Nmeasurements;
+  Star   *first_this_unique;
+} Unique;
+
+
+/******************** PROTOTYPES ********************/
+void args             PROTO((int, char **));
+void get_names        PROTO((Image **, int  *));
+void get_sources      PROTO((Star **, int *));
+void get_stars        PROTO((Star  **, int  *, Image  *, int));
+void sort_stars       PROTO((int  **, Star *, int));
+void get_unique       PROTO((Unique **, int    *, Star *, int *, int, Star *, int));
+void count_unique     PROTO((Image *, int, int));
+void set_Mcal         PROTO((Image *, int));
+void get_Mrel         PROTO((Unique *, Image *, int)); 
+void get_Mcal         PROTO((Image *, Unique *, int));
+void ChiSquare        PROTO((Unique *, Image *, int, int));
+void get_Alam         PROTO((Unique *, Image *, int, int));
+void alter_headers    PROTO((Image *, int));
+void make_table       PROTO((Star *, int, Unique *, Image *, int));
+void get_info         PROTO((Image *));
+char *nextword        PROTO((char *));
+
+extern double hypot PROTO((double, double));
+
Index: /tags/start/Ohana/src/lightcurve/src/ChiSquare.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/ChiSquare.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/ChiSquare.c	(revision 12606)
@@ -0,0 +1,30 @@
+# include "lightcurve.h"
+
+void ChiSquare (unique, images, Nunique, Nimages)
+Unique    *unique;
+Image     *images;
+int        Nunique;
+int        Nimages;
+{
+
+  int    i, j;
+  Star   *this_star;
+  double m, dm, Mcal, Mrel, ChiSquare, Ndof;
+
+  Ndof = ChiSquare = 0.0;
+  for (i = 0; i < Nunique; i ++) {
+    this_star = unique[i].first_this_unique;
+    for (j = 0; j < unique[i].Nmeasurements; j ++) {
+      dm   = this_star[0].dm;
+      m    = this_star[0].m;
+      Mcal = images[this_star[0].image_number].Mcal;
+      Mrel = unique[i].Mrel;
+      Ndof += 1.0;
+      ChiSquare += SQ (m - Mcal - Mrel) / SQ (dm);
+      this_star = this_star[0].next_this_unique;
+    }
+  }
+  Ndof = Ndof - Nunique - Nimages;
+  fprintf (stderr, "Chi Square %9.2f  Ndof %6.0f  Reduced %6.3f  A_LAMBDA  %6.4f\n", 
+	   ChiSquare, Ndof, ChiSquare/Ndof, A_LAMBDA);
+}
Index: /tags/start/Ohana/src/lightcurve/src/alter_headers.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/alter_headers.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/alter_headers.c	(revision 12606)
@@ -0,0 +1,57 @@
+# include "relphot.h"
+
+void alter_headers  (images, Nimages)
+Image  *images;
+int     Nimages;
+{
+
+  int i;
+  Header header;
+  char line[1000], head[1000];
+  double clouds;
+  FILE *f;
+
+  if (!strcmp(IMFILE, "-")) {
+    fprintf (stderr, "using stderr\n");
+    f = stderr;
+  }
+  else {
+    fprintf (stderr, "using %s for image stats\n", IMFILE);
+    f = fopen (IMFILE, "w");
+    if (f == NULL) {
+      fprintf (stderr, "could not open output file, using stderr\n");
+      f = stderr;
+    }
+  }
+  
+  fprintf (f, "# name                Mcal    dMcal   [time]  airmass   clouds <ap-fit> Nstars  Nunique  fixed  empty\n");
+  for (i = 0; i < Nimages; i++) {
+    strcpy (head, images[i].name);
+    strcpy (strchr(head, '.'), ".head");
+    fits_read_header (head, &header);
+
+    sprintf (line, "mv %s %s~\0", head, head);
+    system (line);
+
+    images[i].clouds = images[i].Mcal + C_LAMBDA - A_LAMBDA*images[i].airmass + images[i].AmF;
+
+    fprintf (f, "%s  %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f  %6d   %6d      %1d      %1d\n",  
+	     images[i].name, images[i].Mcal, images[i].dMcal, images[i].Mtime, 
+	     images[i].airmass, images[i].clouds, images[i].AmF, images[i].Nstars, 
+	     images[i].Nunique, images[i].fixed, images[i].empty);
+
+    fits_modify (&header, "Mcal",   "%lf", 1, images[i].Mcal);
+    fits_modify (&header, "dMcal",  "%lf", 1, images[i].dMcal);
+    fits_modify (&header, "clouds", "%lf", 1, images[i].clouds);
+    fits_modify (&header, "NMcal",  "%d", 1,  images[i].Nstars);
+
+    fits_modify (&header, "Mcal",   "%C", 1, "relphot: calibration magnitude");
+    fits_modify (&header, "dMcal",  "%C", 1, "relphot: calibration error");
+    fits_modify (&header, "clouds", "%C", 1, "relphot: cloud level");
+    fits_modify (&header, "NMcal",  "%C", 1, "relphot: number of stars");
+
+    fits_write_header (head, &header);
+    fits_free_header (&header);
+  }
+  fclose (f);
+}
Index: /tags/start/Ohana/src/lightcurve/src/args.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/args.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/args.c	(revision 12606)
@@ -0,0 +1,78 @@
+# include "lightcurve.h"
+# define NARGS 1
+
+void args (argc, argv)
+int      argc;
+char   **argv;
+{
+  
+  int N;
+
+  /** mandatory arguments (see help.c) **/
+  if (N = get_argument (argc, argv, "-P")) {
+    remove_argument (N, &argc, argv);
+    RADIUS = atof (argv[N]);
+    PIXELS = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  else {
+    if (N = get_argument (argc, argv, "-A")) {
+      remove_argument (N, &argc, argv);
+      RADIUS = atof (argv[N]) / 3600.0;
+      PIXELS = FALSE;
+      remove_argument (N, &argc, argv);
+    }
+    else 
+      help (argv[0]);
+  }
+  
+  if (N = get_argument (argc, argv, "-im")) {
+    remove_argument(N, &argc, argv);
+    strcpy (IMAGES, argv[N]);
+    remove_argument(N, &argc, argv);
+  }
+  else
+    help (argv[0]);
+
+  /**** optional arguments (see help.c) ****/
+  if (N = get_argument (argc, argv, "-o")) {
+    remove_argument(N, &argc, argv);
+    strcpy (OUTFILE, argv[N]);
+    remove_argument(N, &argc, argv);
+  }
+  else
+    strcpy (OUTFILE, "-");
+
+  if (N = get_argument (argc, argv, "-midas")) {
+    remove_argument(N, &argc, argv);
+    MIDAS = TRUE;
+  }
+  else
+    MIDAS = FALSE;
+
+  if (N = get_argument (argc, argv, "-m")) {
+    remove_argument(N, &argc, argv);
+    MCUTOFF = atof(argv[N]);
+    remove_argument(N, &argc, argv);
+  }
+  else 
+    MCUTOFF = 0.05;
+
+  if (N = get_argument (argc, argv, "-X")) {
+    remove_argument(N, &argc, argv);
+    EXTRASTARS = TRUE;
+  }
+  else 
+    EXTRASTARS = FALSE;
+
+  if (remove_argument(get_argument (argc, argv, "-h"), &argc, argv) ||
+      remove_argument(get_argument (argc, argv, "-help"), &argc, argv))
+    help(argv[0]);
+
+  if (argc != NARGS) {
+    fprintf (stderr,  "%s%s%s", "USAGE: ", 
+	     argv[0], " (-P / -A) radius  (-im images) [-o file] [-midas]\n");
+    exit (0);
+  }
+}
+
Index: /tags/start/Ohana/src/lightcurve/src/count_unique.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/count_unique.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/count_unique.c	(revision 12606)
@@ -0,0 +1,23 @@
+# include "lightcurve.h"
+
+void count_unique (images, Nimages, Nstars)
+Image *images;
+int    Nimages; 
+int    Nstars;
+{
+
+  int i, j;
+  Star *this_star;
+
+  for (i = 0; i < Nimages; i++) {
+    images[i].Nunique = 0;
+    this_star = images[i].first_this_image;
+    for (j = 0; j < images[i].Nstars; j++) {
+      if (this_star[0].unique_number != EMPTY)
+	images[i].Nunique ++;
+      this_star = this_star[0].next_this_image;
+    }
+  }
+}
+
+    
Index: /tags/start/Ohana/src/lightcurve/src/fix_header.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/fix_header.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/fix_header.c	(revision 12606)
@@ -0,0 +1,59 @@
+# include "lightcurve.h"
+
+/* this repairs headers screwed up in the very specific way of 
+   astro_again: not 80 chars per line on new lines, and no padding
+   of the buffer.
+
+*/
+
+void
+  fix_header 
+  (Header     *header)
+{
+
+  int i, j, Nbytes, N;
+  char *p1, *p2;
+
+  Nbytes = 2880 * (int) (header[0].size / 2880 + 1);
+  reallocate (header[0].buffer, char, Nbytes);
+  bzero (&header[0].buffer[header[0].size], Nbytes - header[0].size - 1);
+
+  p1 = header[0].buffer - 1;
+  p2 = strchr (p1 + 1, RETURN);
+
+  while (p2 != NULL) {
+    if ((N = p2 - p1) != 80) {
+      bcopy (p2, p1 + 80, header[0].size - (p2 - header[0].buffer));
+      for (i = 0; i < 80 - N; i++) {
+	*(p2 + i) = ' ';
+      }
+      header[0].size += 80 - N;
+    }
+    p1 = strchr (p1 + 1, RETURN);
+    p2 = strchr (p1 + 1, RETURN);
+  }
+
+  header[0].size = Nbytes;
+  p1 = fits_header_field (header, "END", 1);
+  for (i = 3; i < 79; i++) 
+    *(p1 + i) = ' ';
+  *(p1 + 79) = RETURN;
+  
+  Nbytes = header[0].size - (p1 - header[0].buffer) - 80;
+  
+  for (i = 0; i < Nbytes; i++) {
+    for (j = 0; j < 79; j++, i++) 
+      *(p1 + i + 80) = '.';
+    *(p1 + i + 80) = RETURN;
+  }
+
+  Nbytes = header[0].size - (p1 - header[0].buffer) - 80;
+  while (Nbytes >= 2880) {
+    header[0].size -= 2880;
+    Nbytes = header[0].size - (p1 - header[0].buffer) - 80;
+  }
+
+  reallocate (header[0].buffer, char, header[0].size);
+}
+
+
Index: /tags/start/Ohana/src/lightcurve/src/get_Alam.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/get_Alam.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/get_Alam.c	(revision 12606)
@@ -0,0 +1,47 @@
+# include "lightcurve.h"
+
+void get_Alam (unique, images, Nunique, Nimages)
+Unique    *unique;
+Image     *images;
+int        Nunique;
+int        Nimages;
+{
+
+  int    i, j;
+  Star   *this_star;
+  double m, dm, Mcal, Mrel, Alm, R, zeta, clouds;
+  double Clouds, dClouds, R2, N;
+
+  R = R2 = N = 0.0;
+  for (i = 0; i < Nimages; i++) {
+    images[i].clouds = images[i].Mcal + C_LAMBDA - A_LAMBDA * images[i].airmass + images[i].AmF;
+    if (!images[i].empty && images[i].fixed) {
+      R  +=     images[i].clouds;
+      R2 += SQ (images[i].clouds);
+      N  += 1.0;
+    }
+  }
+
+  Clouds  = R / N;
+  dClouds = sqrt (R2 / N - Clouds*Clouds);
+  dClouds = MAX (0.0001, dClouds);
+
+  R = Alm = 0.0;
+  for (i = 0; i < Nunique; i ++) {
+    this_star = unique[i].first_this_unique;
+    for (j = 0; j < unique[i].Nmeasurements; j ++) {
+      dm   = this_star[0].dm;
+      m    = this_star[0].m;
+      Mrel = unique[i].Mrel;
+      zeta = images[this_star[0].image_number].airmass;
+      clouds = images[this_star[0].image_number].clouds;
+      if (fabs(clouds - Clouds) > SIG*dClouds) {
+	R   +=   zeta / SQ(dm);
+	Alm += zeta * (m + C_LAMBDA - clouds - Mrel) / SQ (dm);
+      }
+      this_star = this_star[0].next_this_unique;
+    }
+  }
+  if (R > 0) 
+    A_LAMBDA = (9.0*A_LAMBDA + Alm / R) / 10.0;
+}
Index: /tags/start/Ohana/src/lightcurve/src/get_Mcal.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/get_Mcal.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/get_Mcal.c	(revision 12606)
@@ -0,0 +1,43 @@
+# include "lightcurve.h"
+
+void get_Mcal (images, unique, Nimages)
+Image  *images;
+Unique *unique;
+int     Nimages;
+{
+  
+  int    i, j;
+  Star  *this_star;
+  double m, dm, Mrel, r, R, M, M2, N;
+  
+  for (i = 0; i < Nimages; i++) {
+    N = M = M2 = R = 0;
+    this_star = images[i].first_this_image;
+    for (j = 0; j < images[i].Nstars; j++) {
+      if (this_star[0].unique_number != EMPTY) {
+	dm   = this_star[0].dm;
+	m    = this_star[0].m;
+	Mrel = unique[this_star[0].unique_number].Mrel;
+	r    = 1.0 / (dm*dm);
+	R   += r;
+	M   +=    (m - Mrel) * r;
+	M2  +=  SQ(m - Mrel) * r;
+	N   += 1.0;
+      }
+      this_star = this_star[0].next_this_image;
+    }
+    if (R != 0) {
+      images[i].Mcal  = M / R;
+      images[i].dMcal = sqrt(fabs(M2 / R - SQ(M/R))) / sqrt (N);
+    }
+    else {
+      /* no multiple detections on this image! */
+      images[i].empty = TRUE;
+      images[i].Mcal  = 9.999;
+      images[i].dMcal = 9.999;
+    }
+  }
+}
+
+/* m (instrumental) = Mrel (star) + Mcal (image) */
+
Index: /tags/start/Ohana/src/lightcurve/src/get_Mrel.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/get_Mrel.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/get_Mrel.c	(revision 12606)
@@ -0,0 +1,46 @@
+# include "relphot.h"
+
+void get_Mrel (unique, images, Nunique)
+Unique   *unique;
+Image    *images;
+int       Nunique;
+{
+  
+  int    i, j;
+  Star  *this_star;
+  double dm, m, r, R, M, M2, Mcal, N;
+
+  for (i = 0; i < Nunique; i++) {
+    N = M = M2 = R = 0;
+    this_star = unique[i].first_this_unique;
+    for (j = 0; j < unique[i].Nmeasurements; j ++) {
+      dm   = this_star[0].dm;
+      m    = this_star[0].m;
+      Mcal = images[this_star[0].image_number].Mcal;
+      r    = 1.0 / (dm*dm);
+      R   += r;
+      M   +=    (m - Mcal) * r;
+      M2  +=  SQ(m - Mcal) * r;
+      N   += 1.0;
+      this_star = this_star[0].next_this_unique;
+    }
+    unique[i].Mrel  = M / R;
+    unique[i].dMrel = sqrt(fabs(M2 / R - SQ(M/R))) / sqrt (N);
+  }
+
+  for (i = 0; i < Nunique; i++) {
+    N = X2 = 0;
+    Mrel = unique[i].Mrel;
+    this_star = unique[i].first_this_unique;
+    for (j = 0; j < unique[i].Nmeasurements; j ++) {
+      dm   = this_star[0].dm;
+      m    = this_star[0].m;
+      Mcal = images[this_star[0].image_number].Mcal;
+      X2  += SQ((m - Mcal - Mrel) / dm);
+      this_star = this_star[0].next_this_unique;
+    }
+    unique[i].ChiSq = X2 / (N - 1);
+  }
+}
+
+/* m (instrumental) = Mrel (star) + Mcal (image) */
Index: /tags/start/Ohana/src/lightcurve/src/get_argument.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/get_argument.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/get_argument.c	(revision 12606)
@@ -0,0 +1,19 @@
+# include "lightcurve.h"
+
+int get_argument (argc, argv, arg)
+int    argc;
+char **argv;
+char  *arg;
+{
+
+  int i;
+
+  for (i = 0; i < argc; i++) {
+    if (!strcmp(argv[i], arg))
+      return (i);
+  }
+  
+  return ((int)NULL);
+}
+
+
Index: /tags/start/Ohana/src/lightcurve/src/get_info.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/get_info.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/get_info.c	(revision 12606)
@@ -0,0 +1,128 @@
+# include "lightcurve.h"
+
+void  get_info (images)
+Image *images;
+{
+
+  char head[500], line[500];
+  Header header;
+  int i, status;
+  double jd, days, hrs, min, sec, atof();
+
+  status = TRUE;
+
+  strcpy (head, images[0].name);
+  strcpy (strchr(head, '.'), ".head");
+
+  status = fits_read_header (head, &header);
+  if (!status) {
+    fprintf (stderr, "could not open header file %s\n", head);
+    exit (0);
+  }
+  status = TRUE;
+
+  switch (PIXELS) {
+  case 0:
+    status &= fits_scan (&header, "RA_O",    "%lf", 1, &images[0].RA_O);
+    status &= fits_scan (&header, "RA_X",    "%lf", 1, &images[0].RA_X);
+    status &= fits_scan (&header, "RA_Y",    "%lf", 1, &images[0].RA_Y);
+    status &= fits_scan (&header, "DEC_O",   "%lf", 1, &images[0].DEC_O);
+    status &= fits_scan (&header, "DEC_X",   "%lf", 1, &images[0].DEC_X);
+    status &= fits_scan (&header, "DEC_Y",   "%lf", 1, &images[0].DEC_Y);
+    COS = cos (RAD_DEG * images[0].DEC_O);
+    break;
+
+  case 1:
+    status &= fits_scan (&header, "X_O",    "%lf", 1, &images[0].RA_O);
+    status &= fits_scan (&header, "X_X",    "%lf", 1, &images[0].RA_X);
+    status &= fits_scan (&header, "X_Y",    "%lf", 1, &images[0].RA_Y);
+    status &= fits_scan (&header, "Y_O",    "%lf", 1, &images[0].DEC_O);
+    status &= fits_scan (&header, "Y_X",    "%lf", 1, &images[0].DEC_X);
+    status &= fits_scan (&header, "Y_Y",    "%lf", 1, &images[0].DEC_Y);
+    COS = 1;
+    break;
+  }
+  
+  fits_scan (&header, "ORIGIN", "%s", 1, line);
+  /* interpret the silly way ESO / La Palma stores exposure time and duration   */
+  if (!strcmp (line, "ESO-MIDAS")) { 
+    status &= fits_scan (&header, "DATE-OBS", "%s", 1, line);
+    stripwhite (line);
+    fprintf (stderr, "date line: %s\n", line);
+    line[2] = 0;
+    jd = atof(line);
+    line[0] = 0;
+    status = fits_scan (&header, "TM-START", "%lf", 1, &sec);
+    fprintf (stderr, "date: %f, sec: %f\n", jd, sec);
+    jd += (sec/86400.0) + 0.5;
+    images[0].JD =  jd;
+    fits_scan (&header, "EXPTIME", "%lf", 1, &images[0].exptime);
+  }
+  else {
+    status &= fits_scan (&header, "JD", "%lf", 1, &images[0].JD);
+    images[0].JD -= 2400000.5;   /* convert to MJD */
+    fits_scan (&header, "EXPTIME", "%lf", 1, &images[0].exptime);
+  }
+
+  status &= fits_scan (&header, "Mcal", "%lf", 1, &images[0].Mcal);
+  status &= fits_scan (&header, "McalR", "%lf", 1, &images[0].McalR);
+  status &= fits_scan (&header, "McalD", "%lf", 1, &images[0].McalD);
+  status &= fits_scan (&header, "McalR2", "%lf", 1, &images[0].McalR2);
+  status &= fits_scan (&header, "McalD2", "%lf", 1, &images[0].McalD2);
+  status &= fits_scan (&header, "McalRD", "%lf", 1, &images[0].McalRD);
+  status &= fits_scan (&header, "dMcal", "%lf", 1, &images[0].dMcal);
+
+  images[0].airmass = 1000;  
+  fits_scan (&header, "SECZ", "%lf", 1, &images[0].airmass);
+  fits_scan (&header, "AIRMASS", "%lf", 1, &images[0].airmass);
+  /* a stupid value as a flag (i hate flags!) but fits_scan will not alter the
+     value if it fails to find the entry.  try a couple possibilities */
+ 
+  fprintf (stderr, "%s: %10.6f %10.6f  %lf  %6.3f %8.2f %5.2f\n", 
+	   head, images[0].RA_O, images[0].DEC_O, images[0].JD, 
+	   images[0].Mcal, images[0].exptime, images[0].airmass);
+   
+  if (!status) {
+    fprintf (stderr, "error getting header info from %s\n", head);
+    exit(0);
+  }
+
+  if (images[0].airmass > 10) {
+    images[0].airmass = 1.1;
+    fprintf (stderr, "warning: no airmass info\n");
+  }
+  
+  images[0].Nstars  = 0;
+  images[0].fixed   = TRUE;
+  images[0].empty   = FALSE;
+  images[0].Mtime   = 2.5*log10(images[0].exptime);
+  images[0].clouds  = 0.0;
+
+  fits_free_header (&header);
+  
+}
+
+
+
+/* airmass formula (only used if needed) */
+/* page 264 of Kitchin */
+
+/*    z = 1 / ( .5294258 * sin(pi * d / 180.0) + .84835625 * cos(pi * d / 180.0) *
+ cos(pi * h / 12.0));
+
+n
+p status
+
+*/
+
+
+/*
+   code for using RA, DEC, ST info, if needed. 
+    status &= fits_scan (&header, "ST", "%lf", 1, &LST);
+    ra  =  info[0].RA_O  + info[0].RA_X *CCD_X/2.0 + info[0].RA_Y *CCD_Y/2.0;
+    dec =  info[0].DEC_O + info[0].DEC_X*CCD_X/2.0 + info[0].DEC_Y*CCD_Y/2.0;
+    temp1 = sin(OBS_LAT*DEG_RAD)*sin(dec*DEG_RAD);
+    temp2 = cos(OBS_LAT*DEG_RAD)*cos(dec*DEG_RAD);
+    temp3 = cos(((360./24.)*LST - ra)*DEG_RAD);
+    (info[0].airmass) = 1.0 / (temp1 + temp2*temp3);
+*/
Index: /tags/start/Ohana/src/lightcurve/src/get_names.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/get_names.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/get_names.c	(revision 12606)
@@ -0,0 +1,34 @@
+# include "lightcurve.h"
+# define D_NIMAGE 200
+  
+void get_names (images, Nimages)
+Image **images;
+int   *Nimages;
+{
+  
+  int N, i;
+  char line[500];
+  FILE *f;
+
+  f = fopen (IMAGES, "r"); 
+  if (f == NULL) { 
+    fprintf (stderr, "failed to open %s\n", IMAGES); 
+    exit (0); 
+  }
+  N = D_NIMAGE;
+  ALLOCATE (images[0], Image, N);
+
+  for (i = 0; (fscanf (f, "%s", line) != EOF); i++) { 
+    strcpy (images[0][i].name, line);
+    strcpy (strchr(images[0][i].name, '.'), ".obj_out");
+    if (i == N - 1) {
+      N += D_NIMAGE;
+      REALLOCATE (images[0], Image, N);
+    }
+  }
+  *Nimages = i;
+  fprintf (stderr, "Nimages: %d\n", *Nimages);
+  fclose (f);
+}
+
+
Index: /tags/start/Ohana/src/lightcurve/src/get_sources.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/get_sources.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/get_sources.c	(revision 12606)
@@ -0,0 +1,25 @@
+# include "lightcurve.h"
+# define D_NSOURCES 200
+
+void get_sources (sources, Nsources)
+Star  **sources;
+int    *Nsources;
+{
+  
+  int N, i;
+
+  ALLOCATE (sources[0], Star, D_NSOURCES);
+
+  for (i = 0; (fscanf (stdin, "%lf %lf", &sources[0][i].RA, &sources[0][i].Dec) != EOF); i++) { 
+    sources[0][i].unique_number = EMPTY;
+    if (i == D_NSOURCES - 1) {
+      fprintf (stderr, "No More Sources: %d\n", i);
+      break;
+    }
+  }
+  *Nsources = i;
+  fprintf (stderr, "Nsources: %d\n", *Nsources);
+}
+
+
+  
Index: /tags/start/Ohana/src/lightcurve/src/get_stars.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/get_stars.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/get_stars.c	(revision 12606)
@@ -0,0 +1,99 @@
+# include "lightcurve.h"
+# define D_NSTARS 1000
+
+void get_stars (stars, Nstars, images, Nimages)
+Star  **stars;
+int    *Nstars;
+Image   images[];
+int     Nimages;
+{
+
+  double type, mag, dmag, X, Y, ap, dap, AmF, A, A2, S;
+  int i, j, image_number;
+  int NSTARS, status, n, nperf;
+  FILE *f;
+  char line[200];
+
+  j = 0;
+  NSTARS = D_NSTARS;
+  ALLOCATE (stars[0], Star, NSTARS);
+
+  for (i = 0; i < Nimages; i++) { 
+    
+    get_info (&images[i]);
+    f = fopen (images[i].name, "r"); 
+    if (f == NULL) { 
+      fprintf (stderr, "failed to open %s\n", images[i].name); 
+      exit (0); 
+    }
+    nperf = A = A2 = S = 0;
+    for (n = 0; scan_line (f, line) != EOF; n++) {
+      status = TRUE;
+      status &= dparse (&type, 2, line);
+      status &= dparse (&X,    3, line);
+      status &= dparse (&Y,    4, line);
+      status &= dparse (&mag,  5, line);
+      status &= dparse (&dmag, 6, line);
+      status &= dparse (&ap,  12, line);
+      status &= dparse (&dap, 13, line);
+      status &= dparse (&AmF, 15, line);
+      if (!status) {
+	fprintf (stderr, "error on line %d in file %s\n", n, images[i].name);
+	continue;  /* go on to the next line */
+      }
+      stars[0][j].ap = 0;
+      if (ap < 99) {
+	nperf ++;
+	A  += AmF/SQ(dap);
+	A2 += SQ(AmF)/SQ(dap);
+	S  += 1.0/SQ(dap);
+	stars[0][j].ap = ap;    /* if the ap mag is good, use it, not the <ap-fit> adjusted value */
+      }
+      if ((dmag < MCUTOFF) && ((type == 1) || (EXTRASTARS && ((type == 2) || (type == 3) || (type == 4) || (type == 5) || (type == 7))))) {  /* for now, this uses only type 1s */
+	stars[0][j].RA  = images[i].RA_O  + X*images[i].RA_X  + Y*images[i].RA_Y;
+	stars[0][j].Dec = images[i].DEC_O + X*images[i].DEC_X + Y*images[i].DEC_Y;
+	stars[0][j].m   = mag + images[i].Mtime;
+	stars[0][j].dm  = sqrt (SQ(dmag) + SQ(images[i].dMcal));
+	
+	stars[0][j].next_this_unique = NULL;
+	stars[0][j].image_number     = i;
+	stars[0][j].star_number      = n;
+	stars[0][j].unique_number    = EMPTY;
+	
+	if (j == NSTARS - 1) {
+	  NSTARS += D_NSTARS;
+	  fprintf (stderr, "!");
+	  REALLOCATE (stars[0], Star, NSTARS);
+	}
+	j ++;
+	images[i].Nstars ++;   /* this is set to 0 in "get_info" */
+      }
+    }
+    if (nperf > 2) {
+      images[i].AmF = A / S;
+      images[i].dAmF = sqrt(A2/S - A*A/SQ(S));
+    }
+    else {
+      images[i].AmF = 0.0;
+      images[i].dAmF = 0.0;
+    }     
+    fclose (f);
+/*    images[i].Mcal    = - C_LAMBDA + A_LAMBDA*images[i].airmass - images[i].AmF; */
+    stars[0][j - 1].next_this_image = NULL;
+  }
+  
+  image_number = 0;
+  for (i = 0; i < j; ) {
+    images[image_number].first_this_image = &stars[0][i];
+    for (i++; ((stars[0][i].image_number == image_number) && (i < j)); i++)  {
+      stars[0][i - 1].next_this_image = &stars[0][i];
+    }
+    stars[0][i - 1].next_this_image = NULL;
+    image_number = stars[0][i].image_number;
+  }
+
+  *Nstars = j;
+  fprintf (stderr, "Nstars: %d\n", *Nstars);
+}
+
+  
Index: /tags/start/Ohana/src/lightcurve/src/get_unique.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/get_unique.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/get_unique.c	(revision 12606)
@@ -0,0 +1,186 @@
+# include "lightcurve.h"
+# define D_NUNIQUE 1000;
+
+void get_unique (unique, N, stars, radec, Nstars, sources, Nsources)
+Unique **unique;
+int    *N;
+Star   *stars;
+int    *radec;
+int     Nstars;
+Star   *sources;
+int     Nsources;
+{
+
+  int i, j, link, k, n, confused, Nchain, NUNIQUE, Nunique, first, NTEMP;
+  int Ntemp, Nclump, Nblobs;
+  Unique  temp_unique;
+  int    *templist;
+  Star   *next_unique, *this_unique;
+  double radius, dRA, dDec, RAo, DECo, dRA2, dDec2;
+  double dRo, dDo, dRo2, dDo2;
+
+  NUNIQUE = D_NUNIQUE;
+  ALLOCATE (unique[0], Unique, NUNIQUE);
+  NTEMP = 100;
+  ALLOCATE (templist, int, NTEMP);  
+  Nblobs = dRo = dDo = dRo2 = dDo2 = 0;
+
+  for (i = Nunique = 0; (i < Nstars - 1); i++) {
+    
+    /* check if this star is not already assigned to a clump */
+    if (stars[radec[i]].next_this_unique == NULL) {
+      
+      /* first, find all stars within 2*RADIUS of this star */
+      first = i;
+      Ntemp = 1;
+      dRA = 0;
+      templist[0] = radec[first];  
+      for (j = first + 1; (dRA <= 2.0*RADIUS) && (j < Nstars); j++) {
+	if (stars[radec[j]].next_this_unique != NULL)
+	  continue;
+	dRA  = COS * (stars[radec[j]].RA - stars[radec[first]].RA);  
+	dDec = stars[radec[j]].Dec - stars[radec[first]].Dec;
+	radius = hypot(dRA, dDec);
+	if (radius < 2.0*RADIUS) {
+	  /* add to templist: */
+	  templist[Ntemp] = radec[j];
+	  Ntemp ++;
+	  if (Ntemp == NTEMP - 1) {
+	    NTEMP += 100;
+	    REALLOCATE (templist, int, NTEMP); 
+	  }
+	}
+      }
+	     
+      if (Ntemp < 3) {
+	continue; /* check this pops out of the right level... */
+      }
+
+      /* next, find the centroid of this subset of stars */
+      dRA = dDec = dRA2 = dDec2 = 0;
+      for (j = 0; j < Ntemp; j++) {
+	dRA   += stars[templist[j]].RA;
+	dDec  += stars[templist[j]].Dec;
+	dRA2  += SQ(stars[templist[j]].RA);
+	dDec2 += SQ(stars[templist[j]].Dec);
+      }
+      RAo   = dRA / (double)Ntemp;
+      DECo  = dDec / (double)Ntemp;
+      dRA2  = sqrt(dRA2 / (double)Ntemp - SQ(RAo));
+      dDec2 = sqrt(dDec2 / (double)Ntemp - SQ(DECo));
+
+      /* then, find all stars within 1 RADIUS of this centroid */
+      Nclump = 0;
+      unique[0][Nunique].first_this_unique = (Star *) NULL;
+      for (j = 0; j < Ntemp; j++) {
+	dRA  = COS * (stars[templist[j]].RA - RAo);
+	dDec = stars[templist[j]].Dec - DECo;
+	radius = hypot(dRA, dDec);
+	if (radius < RADIUS) {
+	  if (Nclump != 0) {
+	    this_unique[0].next_this_unique = &stars[templist[j]];
+	    this_unique = &stars[templist[j]];
+	    this_unique[0].unique_number = Nunique;
+	  }
+	  else {
+	    unique[0][Nunique].first_this_unique = &stars[templist[j]];
+	    this_unique = &stars[templist[j]];
+	    this_unique[0].unique_number = Nunique;
+	  }
+	  Nclump ++;
+	}
+      }
+      
+      /* if too few in clump, eliminate, move on */
+      if (Nclump < 5) {
+	this_unique = unique[0][Nunique].first_this_unique;
+	unique[0][Nunique].first_this_unique = NULL;
+	while (this_unique != NULL) {
+	  next_unique = this_unique[0].next_this_unique;
+	  this_unique[0].unique_number = EMPTY;
+	  this_unique[0].next_this_unique = NULL;
+	  this_unique = next_unique;
+	}
+	continue;
+      }
+
+      /* count number of confused stars...
+      this_unique = unique[0][Nunique].first_this_unique;
+      for (j = 0, confused = FALSE; j < Nclump - 1; j++) {
+	next_unique = this_unique[0].next_this_unique;
+	for (k = j + 1; k < Nclump; k++) {
+	  if (this_unique[0].image_number == next_unique[0].image_number) {
+	    confused = TRUE;
+	  }
+	  next_unique = next_unique[0].next_this_unique;
+	}
+	this_unique = this_unique[0].next_this_unique;
+      } 
+       */
+
+      /* if this object is confused, ignore it and move on.  
+	 keep the "next_this_unique" values on, but remove
+	 the "unique_number" */
+
+      /*
+      
+      if (confused) {
+	this_unique = unique[0][Nunique].first_this_unique;
+	unique[0][Nunique].first_this_unique = NULL;
+	while (this_unique != NULL) {
+	  this_unique[0].unique_number = EMPTY;
+	  this_unique = this_unique[0].next_this_unique;
+	}
+	Nblobs ++;
+	continue;
+      }
+      */
+      
+      this_unique = unique[0][Nunique].first_this_unique;
+      for (j = 0; j < Nclump; j++) {
+	dRA   += this_unique[0].RA;
+	dDec  += this_unique[0].Dec;
+	dRA2  += SQ(this_unique[0].RA);
+	dDec2 += SQ(this_unique[0].Dec);
+	next_unique = this_unique[0].next_this_unique;
+      }
+      RAo   = dRA / (double)Nclump;
+      DECo  = dDec / (double)Nclump;
+      for (n = 0; n < Nsources; n++) {
+	dRA = COS * (RAo - sources[n].RA);
+	dDec = (DECo - sources[n].Dec);
+	radius = hypot(dRA, dDec);
+	if (radius < RADIUS) {
+	  sources[n].unique_number = Nunique;
+	  fprintf (stderr, "%d %d  %f %f  %f %f\n", 
+		   n, Nunique, RAo, DECo, sources[n].RA, sources[n].Dec);
+	  break;
+	}
+      } 
+      
+      unique[0][Nunique].Nmeasurements = Nclump;
+      unique[0][Nunique].Mrel = 0.0;
+      /* use only stars which show up on all images */
+      
+      dRo += dRA2;
+      dDo += dDec2;
+      dRo2 += dRA2*dRA2;
+      dDo2 += dDec2*dDec2;
+      Nunique ++;
+      if (Nunique == NUNIQUE - 1) { 
+	NUNIQUE += D_NUNIQUE;
+	REALLOCATE(unique[0], Unique, NUNIQUE);
+      }
+    }
+  } 
+
+  *N = Nunique;
+  dRo = dRo / (double)Nunique;
+  dDo = dDo / (double)Nunique;
+  dRo2 = sqrt(dRo2 / (double)Nunique - SQ(dRo));
+  dDo2 = sqrt(dDo2 / (double)Nunique - SQ(dDo));
+
+  fprintf (stderr, "%f   %f %f %f %f   %4d %3d\n", 3600*RADIUS, dRo, dDo, dRo2, dDo2, Nunique, Nblobs);
+
+}
+
Index: /tags/start/Ohana/src/lightcurve/src/help.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/help.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/help.c	(revision 12606)
@@ -0,0 +1,25 @@
+# include "lightcurve.h"
+
+void
+help (name)
+char name[];
+{
+  
+  fprintf (stderr, "%s%s%s%s%s%s%s%s%s%s%s%s%s",
+	   "USAGE: ", name, " (-P / -A) radius  \n",
+	   "\n",
+           "  Mandatory Flags:\n",
+           "  -P / -A      one of these must be used: \n",
+           "    -P  pixs     radius of search in pixels -- uses relative astrometry (rastro)\n",
+           "    -A  asec     radius of search in arcsec -- uses absolute astrometry  (astro)\n",
+           "  -im images   file with the list of images to use\n",
+           "\n",
+           "  Optional Flags:\n",
+           "  -o  file  output file for star data\n",
+           "  -midas    use MIDAS format time info from headers\n"
+           "  -h        print this list\n\n",
+	   "  ", name, " expects a series of (Ra,Dec) or (X,Y) pairs\n\n");
+  
+  exit (0);
+  
+}
Index: /tags/start/Ohana/src/lightcurve/src/imstats.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/imstats.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/imstats.c	(revision 12606)
@@ -0,0 +1,46 @@
+# include "lightcurve.h"
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+  
+  Image   *images;
+  Star    *stars, *sources;
+  Unique  *unique;
+  int     *radec;
+  int      Nimages, Nstars, Nunique, Nsources;
+  int      i, j;
+
+  /*** this still needs to be fixed / updated */
+  args (argc, argv);
+
+  get_names (&images, &Nimages);
+  get_sources (&sources, &Nsources);
+  get_stars  (&stars, &Nstars, images, Nimages);
+  sort_stars (&radec, stars, Nstars);
+
+  get_unique (&unique, &Nunique, stars, radec, Nstars, sources, Nsources);
+
+  make_table (sources, Nsources, unique, images, Nimages);
+  
+}
+
+
+/* 
+   list of system wide variables that are (should be) defined in relphot.h:
+
+   RADIUS  (radius of search in pixels or arcsec)
+   A_LAMBDA (airmass extinction coefficient)
+   C_LAMBDA (zero point C_\lambda)
+   NLOOP   (desired number of interations)
+   SIG     (number of sigma for cloudiness criterion)
+   OUTFILE (output file)
+   PRINT   (print processing info?)
+   PIXELS  (RADIUS in pixels (rastro) or degrees (astro))
+   COS     (RA scaling factor = cos(DEC(center of field)) if astro, 
+                              = 1 if rastro )
+
+*/
+
+   
Index: /tags/start/Ohana/src/lightcurve/src/jd.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/jd.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/jd.c	(revision 12606)
@@ -0,0 +1,72 @@
+      SUBROUTINE locate(xx,n,x,j)
+      INTEGER j,n
+      REAL x,xx(n)
+      INTEGER jl,jm,ju
+      jl=0
+      ju=n+1
+10    if(ju-jl.gt.1)then
+        jm=(ju+jl)/2
+        if((xx(n).gt.xx(1)).eqv.(x.gt.xx(jm)))then
+          jl=jm
+        else
+          ju=jm
+        endif
+      goto 10
+      endif
+      j=jl
+      return
+      END
+
+      FUNCTION julday(mm,id,iyyy)
+      INTEGER julday,id,iyyy,mm,IGREG
+      PARAMETER (IGREG=15+31*(10+12*1582))
+      INTEGER ja,jm,jy
+      jy=iyyy
+      if (jy.eq.0) pause 'julday: there is no year zero'
+      if (jy.lt.0) jy=jy+1
+      if (mm.gt.2) then
+        jm=mm+1
+      else
+        jy=jy-1
+        jm=mm+13
+      endif
+      julday=int(365.25*jy)+int(30.6001*jm)+id+1720995
+      if (id+31*(mm+12*iyyy).ge.IGREG) then
+        ja=int(0.01*jy)
+        julday=julday+2-ja+int(0.25*ja)
+      endif
+      return
+      END
+
+function mjd(yr,hr,sc)
+	implicit none
+	integer iyr, mn, n, jd, j, julday, idy
+	real*8 yr,hr,sc,mjd
+	real*4 month(12), dy
+	n = 12
+	data month/0,31,59,90,120,151,181,212,243,273,304,334/
+	iyr = yr
+	if((mod(iyr,4).eq.0.and.mod(iyr,100).ne.0).or.(mod(iyr,400).eq.0)) then
+	  dy = int(366.*(yr-iyr)+.0001) + 1
+	  do j = 3, 12
+	    month(j) = month(j) + 1.
+	  end do
+	else
+	  dy = int(365.*(yr-iyr)+.0001) + 1
+	end if
+c 
+c locate, from Numrec library
+c
+	call locate(month,n,dy,mn)
+	dy = dy - month(mn)
+	idy = dy
+c
+c julday, from Numrec library
+c
+	jd = julday(mn,idy,iyr)
+	mjd = jd - 2440000.5
+	mjd = mjd + hr / 24. + sc / 86400. / 2.
+	end
+
+
+z
Index: /tags/start/Ohana/src/lightcurve/src/lightcurve.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/lightcurve.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/lightcurve.c	(revision 12606)
@@ -0,0 +1,46 @@
+# include "lightcurve.h"
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+  
+  Image   *images;
+  Star    *stars, *sources;
+  Unique  *unique;
+  int     *radec;
+  int      Nimages, Nstars, Nunique, Nsources;
+  int      i, j;
+
+  /*** this still needs to be fixed / updated */
+  args (argc, argv);
+
+  get_names (&images, &Nimages);
+  get_sources (&sources, &Nsources);
+  get_stars  (&stars, &Nstars, images, Nimages);
+  sort_stars (&radec, stars, Nstars);
+
+  get_unique (&unique, &Nunique, stars, radec, Nstars, sources, Nsources);
+
+  make_table (sources, Nsources, unique, images, Nimages);
+  
+}
+
+
+/* 
+   list of system wide variables that are (should be) defined in relphot.h:
+
+   RADIUS  (radius of search in pixels or arcsec)
+   A_LAMBDA (airmass extinction coefficient)
+   C_LAMBDA (zero point C_\lambda)
+   NLOOP   (desired number of interations)
+   SIG     (number of sigma for cloudiness criterion)
+   OUTFILE (output file)
+   PRINT   (print processing info?)
+   PIXELS  (RADIUS in pixels (rastro) or degrees (astro))
+   COS     (RA scaling factor = cos(DEC(center of field)) if astro, 
+                              = 1 if rastro )
+
+*/
+
+   
Index: /tags/start/Ohana/src/lightcurve/src/make_table.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/make_table.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/make_table.c	(revision 12606)
@@ -0,0 +1,60 @@
+# include "lightcurve.h"
+
+void make_table (sources, Nsources, unique, images, Nimages)
+Star   *sources;
+int     Nsources;
+Unique *unique;
+Image  *images;
+int     Nimages;
+{
+
+  double  N, M, dM;
+  int     i, j, n, im;
+  Star   *next_measurement;
+  FILE   *f;
+  double  dR, dD;
+
+  if (!strcmp(OUTFILE, "-")) {
+    fprintf (stderr, "using stdout\n");
+    f = stdout;
+  }
+  else {
+    fprintf (stderr, "using %s for output\n", OUTFILE);
+    f = fopen (OUTFILE, "w");
+    if (f == NULL) {
+      fprintf (stderr, "could not open output file, using stdout\n");
+      f = stdout;
+    }
+  }
+  
+  fprintf (f, "# This is a table of data from relphot.\n");
+  fprintf (f, "# This table contains the following data:\n");
+  if (PIXELS) 
+    fprintf (f, "# star number, <X> dX  <Y> dY  <Mrel> dMrel  Nstars\n");
+  else
+    fprintf (f, "# star number, <RA> dRA  <Dec> dDec  <Mrel> dMrel  Nstars\n");
+
+  for (j = 0; j < Nsources; j++) {
+    fprintf (f, "%5d %10.6f %10.6f ", j, sources[j].RA, sources[j].Dec);
+    if (sources[j].unique_number == EMPTY) {
+      fprintf (f, "%5d\n", 0.0);
+      continue;
+    }
+    N = unique[sources[j].unique_number].Nmeasurements;
+    fprintf (f, "%5.0f\n", N);
+    next_measurement = unique[sources[j].unique_number].first_this_unique;
+    M = 100.0; dM = 0.0;
+    for (n = 0; n < N; n++) {
+      im = next_measurement[0].image_number;
+      dR = (next_measurement[0].RA - images[im].RA_O);
+      dD = (next_measurement[0].Dec - images[im].DEC_O);
+      M = next_measurement[0].m - MCAL(images[im], dR, dD);
+      dM = next_measurement[0].dm;
+      dR = (next_measurement[0].RA - sources[j].RA);
+      dD = (next_measurement[0].Dec - sources[j].Dec);
+      fprintf (f, "%-40s  %15.6f  %7.3f %7.3f  %7.3f %7.3f\n", images[im].name, images[im].JD, dR, dD, M, dM);
+      next_measurement = next_measurement[0].next_this_unique;
+    }
+  }
+  fclose (f);
+}
Index: /tags/start/Ohana/src/lightcurve/src/match_stars.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/match_stars.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/match_stars.c	(revision 12606)
@@ -0,0 +1,84 @@
+# include "relphot.h"
+# define D_NUNIQUE 1000;
+
+void match_stars (unique, N, stars, radec, Nstars, sources, Nsources)
+Unique **unique;
+int    *N;
+Star   *stars;
+int    *radec;
+int     Nstars;
+Source *sources;
+int     Nsources;
+{
+
+  int i, j, link, k, good, Nchain, NUNIQUE, Nunique;
+  Unique  temp_unique;
+  Star   *next_unique, *this_unique;
+  double radius, dRA, dDec;
+
+  NUNIQUE = D_NUNIQUE;
+  ALLOCATE (unique[0], Unique, NUNIQUE);
+
+  for (i = Nunique = 0; (i < Nstars - 1); i++) {
+    
+    dRA = COS * (stars[radec[i+1]].RA - stars[radec[i]].RA);
+
+    if (dRA < 0.0) {
+      fprintf (stderr, "stars out of order!!!  %d  %d  %f  %f\n", 
+	       radec[i+1], radec[i], stars[radec[i+1]].RA, stars[radec[i]].RA);
+    }
+
+    if ((fabs(dRA) < RADIUS) && (stars[radec[i]].next_this_unique == NULL)) {
+
+      /* set up the chain */
+      for (link = i, j = link + 1, Nchain = 1; (fabs(dRA) < RADIUS) && (j < Nstars); j++) {
+	dDec   = stars[radec[j]].Dec - stars[radec[link]].Dec;
+	radius = hypot(dRA, dDec);
+	if (radius < RADIUS) {
+	  stars[radec[link]].next_this_unique = &stars[radec[j]];
+	  link = j;
+	  Nchain ++;
+	}
+	if (j < Nstars - 1)
+	  dRA  = COS * (stars[radec[j + 1]].RA - stars[radec[link]].RA);
+      }
+
+      /* are any 2 links on the same image? */
+      this_unique = &stars[radec[i]];
+      for (j = 0, good = TRUE; j < Nchain - 1; j++) {
+	next_unique = this_unique[0].next_this_unique;
+	for (k = j + 1; k < Nchain; k++) {
+	  if (this_unique[0].image_number == next_unique[0].image_number) {
+	    good = FALSE;
+	    fprintf (stderr, "clump on image %d, stars %d and %d\n", 
+		     this_unique[0].image_number, 
+		     this_unique[0].star_number, 
+		     next_unique[0].star_number);
+	  }
+	  next_unique = next_unique[0].next_this_unique;
+	}
+	this_unique = this_unique[0].next_this_unique;
+      }
+
+      /* if not, add chain to unique[] */
+      if ((good) && (Nchain > 1)) {
+	this_unique = unique[0][Nunique].first_this_unique = &stars[radec[i]];
+	while (this_unique != NULL) {
+	  this_unique[0].unique_number = Nunique;
+	  this_unique = this_unique[0].next_this_unique;
+	}
+	unique[0][Nunique].Nmeasurements = Nchain;
+	Nunique ++;
+	if (Nunique == NUNIQUE - 1) { 
+	  NUNIQUE += D_NUNIQUE;
+	  REALLOCATE(unique[0], Unique, NUNIQUE);
+	}
+      }
+    }
+  } 
+
+  *N = Nunique;
+  fprintf (stderr, "Nunique: %d\n", Nunique);
+
+}
+
Index: /tags/start/Ohana/src/lightcurve/src/mjd.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/mjd.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/mjd.c	(revision 12606)
@@ -0,0 +1,42 @@
+# include "lightcurve.h"
+# define GREG (15+31*(10+12*1582))
+
+double mjd (year, hour, second)
+double year, hour, second;
+{
+
+  int iyear;
+  int Months[] = {0,31,59,90,120,151,181,212,243,273,304,334};
+
+  /* convert year, which contains year + day, into year, month, day */
+  iyear = year;
+  if ((!(iyear % 4) && (iyear % 100)) || !(iyear % 400)) { /* leap year */
+    day = 366*(year - iyear) + 1;
+    for (i = 2; i < 12; i++) 
+      Months[i]++;
+  }
+  else {
+    day = 365*(year - iyear) + 1;
+  }
+  for (i = 0; month[i] < day; i++);
+  month = Months[i-1];
+  
+  if (day + 31*(month + 12*iyear) >= GREG) 
+    extra = 2 - (int)(0.01*jy) + (int)(0.25*((int)(0.01*jy)));
+  else 
+    extra = 0;
+
+  if (year == 0) {
+    fprintf (stderr, "error: there is no year zero\n");
+    exit (0);
+  }
+  if (year < 0) 
+    year += 1.0;
+  if (month > 2) 
+    jmonth = month + 1;
+  else {
+    year -= 1;
+    month += 13;
+  }
+
+  julday = (int)(365.25*year)+int(30.6001*jm)+id+1720995
Index: /tags/start/Ohana/src/lightcurve/src/parse.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/parse.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/parse.c	(revision 12606)
@@ -0,0 +1,35 @@
+# include "lightcurve.h"
+
+int parse (X, NX, line)
+double *X;
+int NX;
+char *line;
+{
+
+  int i;
+  char *word;
+  char *ptr;
+
+  word = line;
+  for (i = 0; i < NX - 1; i++)
+    word = nextword (word);
+
+  *X = strtod (word, &ptr);
+  if (ptr == word)
+    return (FALSE);
+  else
+    return (TRUE);
+}
+
+
+char *nextword(string)
+char *string;
+{
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (; isspace (*string); string++);
+  for (; (*string != 0) && !isspace (*string); string++);
+  for (; isspace (*string); string++);
+  return (string);
+}
+
Index: /tags/start/Ohana/src/lightcurve/src/relphot.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/relphot.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/relphot.c	(revision 12606)
@@ -0,0 +1,57 @@
+# include "lightcurve.h"
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+  
+  Image   *images;
+  Star    *stars;
+  Unique  *unique;
+  int     *radec;
+  int      Nimages, Nstars, Nunique;
+  int      i, j;
+
+  /*** this still needs to be fixed / updated */
+  args (argc, argv);
+
+  get_names  (&images, &Nimages);
+  get_stars  (&stars, &Nstars, images, Nimages);
+  sort_stars (&radec, stars, Nstars);
+
+  get_unique (&unique, &Nunique, stars, radec, Nstars);
+  count_unique (images, Nimages, Nstars);
+
+  for (i = 0; i < NLOOP; i++) {
+    set_Mcal (images, Nimages);
+    get_Mrel (unique, images, Nunique);
+    get_Mcal (images, unique, Nimages);
+    ChiSquare (unique, images, Nunique, Nimages);
+  }  
+ 
+
+  if (PRINT) {
+    alter_headers (images, Nimages);
+    make_table (unique, images, Nunique);
+  }
+  
+}
+
+
+/* 
+   list of system wide variables that are (should be) defined in relphot.h:
+
+   RADIUS  (radius of search in pixels or arcsec)
+   A_LAMBDA (airmass extinction coefficient)
+   C_LAMBDA (zero point C_\lambda)
+   NLOOP   (desired number of interations)
+   SIG     (number of sigma for cloudiness criterion)
+   OUTFILE (output file)
+   PRINT   (print processing info?)
+   PIXELS  (RADIUS in pixels (rastro) or degrees (astro))
+   COS     (RA scaling factor = cos(DEC(center of field)) if astro, 
+                              = 1 if rastro )
+
+*/
+
+   
Index: /tags/start/Ohana/src/lightcurve/src/remove_argument.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/remove_argument.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/remove_argument.c	(revision 12606)
@@ -0,0 +1,21 @@
+# include "lightcurve.h"
+
+int remove_argument (N, argc, argv)
+int    N;
+int   *argc;
+char **argv;
+{
+
+  int i;
+
+  if ((N != (int)NULL) && (N != 0)) {
+    (*argc)--;
+    for (i = N; i < *argc; i++) {
+      argv[i] = argv[i+1];
+    }
+  }
+
+  return (N);
+    
+}
+
Index: /tags/start/Ohana/src/lightcurve/src/scan_line.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/scan_line.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/scan_line.c	(revision 12606)
@@ -0,0 +1,28 @@
+# include "lightcurve.h"
+
+/*************/
+int
+scan_line (f, line) 
+FILE *f;
+char line[];
+{
+
+  int i, status;
+  char c;
+  
+  status = EOF + 1;
+  
+  for (i = 0, c = 0; (c != '\n') && (status != EOF); i++) {
+    status = fscanf (f, "%c", &c);
+    line[i] = c;
+  }
+  line[i - 1] = 0;  /* this could make things crash! */
+
+  if (i > 1) {
+    status = EOF + 1;
+  }
+
+  return (status);
+
+}
+
Index: /tags/start/Ohana/src/lightcurve/src/set_Mcal.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/set_Mcal.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/set_Mcal.c	(revision 12606)
@@ -0,0 +1,53 @@
+# include "lightcurve.h"
+
+void set_Mcal (images, Nimages)
+Image    *images;
+int       Nimages;
+{
+
+  int i;
+  double clouds, Clouds, dClouds, R, R2, N;
+  
+  R = R2 = N = 0.0;
+  for (i = 0; i < Nimages; i++) {
+    images[i].clouds = images[i].Mcal + C_LAMBDA - A_LAMBDA * images[i].airmass + images[i].AmF;
+    if (!images[i].empty && images[i].fixed) {
+      R  +=     images[i].clouds;
+      R2 += SQ (images[i].clouds);
+      N  += 1.0;
+    }
+  }
+
+  Clouds  = R / N;
+  dClouds = sqrt (R2 / N - Clouds*Clouds);
+
+  fprintf (stderr, "Clouds = %f, dClouds = %f, N / Nimages: %f / %d\n", Clouds, dClouds, N, Nimages);
+
+  dClouds = MAX (0.0001, dClouds);
+
+  for (i = 0; i < Nimages; i++) {
+    if (fabs(images[i].clouds - Clouds) > SIG*dClouds) 
+      images[i].fixed = FALSE;
+    else {
+      images[i].fixed  = TRUE;
+      images[i].Mcal   = - C_LAMBDA + A_LAMBDA * images[i].airmass - images[i].AmF;
+      images[i].clouds = 0.0;
+    }
+  }
+}
+
+/*  BIG IMPORTANT NOTE:  equations (3) and (7) in Magnier et al 1992, A&A 96, 379
+    are not consistent with positive defined A_LAMBDA.  
+
+    the equations should read:
+
+    (3)  M_app = c_lambda + m - a_lambda*\zeta ... + clouds    (... is color term)
+    (7)  M_cal = -c_lambda + a_lambda*\zeta
+
+    The point is that a_lambda is a positive coeff, so as \zeta increases, the
+    image is *less* sensitive, so M_cal goes up.  conversely, c_lambda is also
+    a positive defined number, so as c_lambda increases, the image is *more* 
+    sensitive.  Since the a_lambda and c_lambda have opposite senses, they 
+    must have opposite signs.  
+
+*/
Index: /tags/start/Ohana/src/lightcurve/src/sort_seq.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/sort_seq.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/sort_seq.c	(revision 12606)
@@ -0,0 +1,39 @@
+# include "lightcurve.h"
+
+void sort_seq (seq, value, N) 
+int *seq;
+double *value;
+int N;
+{
+  int l,j,ir,i;
+  int temp;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      temp = seq[--l];
+    }
+    else {
+      temp = seq[ir];
+      seq[ir] = seq[0];
+      if (--ir == 0) {
+	seq[0] = temp;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && value[seq[j]] < value[seq[j+1]]) ++j;
+      if (value[temp] < value[seq[j]]) {
+	seq[i]=seq[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    seq[i] = temp;
+  }
+}
+
+
Index: /tags/start/Ohana/src/lightcurve/src/sort_stars.c
===================================================================
--- /tags/start/Ohana/src/lightcurve/src/sort_stars.c	(revision 12606)
+++ /tags/start/Ohana/src/lightcurve/src/sort_stars.c	(revision 12606)
@@ -0,0 +1,24 @@
+# include "lightcurve.h"
+
+void sort_stars (radec, stars, Nstars)
+int  **radec;
+Star  *stars;
+int    Nstars;
+{
+  
+  int i;
+  double *RAs;
+
+  ALLOCATE (radec[0], int, Nstars);
+  ALLOCATE (RAs, double, Nstars);
+  for (i = 0; i < Nstars; i++) {
+    radec[0][i] = i;
+    RAs[i] = stars[i].RA;
+  }
+
+  sort_seq (radec[0], RAs, Nstars);
+  free (RAs);
+
+}
+
+
Index: /tags/start/Ohana/src/markrock/Makefile
===================================================================
--- /tags/start/Ohana/src/markrock/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/markrock/Makefile	(revision 12606)
@@ -0,0 +1,66 @@
+include ../../Configure
+HOME 	=	$(ROOT)/src/markrock
+CONFIG  =	$(ROOT)/config
+PROGRAM =       markrock
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#  
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lohana -lFITS -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS)
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+MARKROCK = \
+$(SRC)/markrock.$(ARCH).o 	$(SRC)/gcatalog.$(ARCH).o   	\
+$(SRC)/coordops.$(ARCH).o	$(SRC)/sorts.$(ARCH).o 		\
+$(SRC)/ConfigInit.$(ARCH).o 	$(SRC)/photometry.$(ARCH).o \
+$(SRC)/check_lockfile.$(ARCH).o \
+$(SRC)/find_rocks.$(ARCH).o 	$(SRC)/wcatalog.$(ARCH).o	\
+$(SRC)/gcatstats.$(ARCH).o	$(SRC)/wrocks.$(ARCH).o 	\
+$(SRC)/check_permissions.$(ARCH).o \
+$(SRC)/gregions.$(ARCH).o \
+$(SRC)/aregion.$(ARCH).o \
+$(SRC)/find_bright_stars.$(ARCH).o \
+$(SRC)/load_gsc_data.$(ARCH).o \
+$(SRC)/count_neighbors.$(ARCH).o
+
+
+OBJ = $(MARKROCK)
+
+default: $(PROGRAM)
+
+$(MARKROCK): $(INC)/markrock.h
+
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:	
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
+
+
Index: /tags/start/Ohana/src/markrock/doc/example.txt
===================================================================
--- /tags/start/Ohana/src/markrock/doc/example.txt	(revision 12606)
+++ /tags/start/Ohana/src/markrock/doc/example.txt	(revision 12606)
@@ -0,0 +1,13 @@
+
+rats: foreach f ( */*.cpt )
+foreach? echo $f
+foreach? echo $f >> bright.log
+foreach? (markstar -v $f >> bright.dat) >>& bright.log
+foreach? end
+
+
+
+ echo $f
+ echo $f >> bright.log
+ (markstar -v $f >> bright.dat) >>& bright.log
+ end
Index: /tags/start/Ohana/src/markrock/include/markrock.h
===================================================================
--- /tags/start/Ohana/src/markrock/include/markrock.h	(revision 12606)
+++ /tags/start/Ohana/src/markrock/include/markrock.h	(revision 12606)
@@ -0,0 +1,44 @@
+# include <ohana.h>
+# include <loneos.h>
+
+typedef struct {
+  Coords coords;
+  float *X, *Y;
+  int *N;
+  double RA[2], DEC[2];
+  double Area, density, spacing;
+} CatStats;
+
+typedef struct {
+  double ra[3];
+  double dec[3];
+  double X[3];
+  double Y[3];
+  unsigned int t[3];
+  double mag[3];
+  int N[3];
+} Rocks;
+
+/* global variables set in parameter file */
+
+int    VERBOSE;
+int    RESET;
+int    FORCE_RUN;
+
+char   GSCFILE[256];
+char   GSCDIR[256];
+char   CATDIR[256];
+char   RockCat[256];
+
+double RADIUS;
+double MAX_RADIUS;
+double MAX_SPEED;
+double MAX_DELAY;
+double ZERO_POINT;
+
+double BRIGHT_HALO_MAG;
+double BRIGHT_HALO_SLOPE;
+double ROCK_NEIGHBOR_RADIUS;
+int    ROCK_NEIGHBOR_NMAX;
+
+PhotCodeData photcodes;
Index: /tags/start/Ohana/src/markrock/src/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/ConfigInit.c	(revision 12606)
@@ -0,0 +1,46 @@
+# include "markrock.h"
+
+ConfigInit (int *argc, char **argv) {
+
+  char *config, *file;
+  char PhotCodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  /* used in other pipeline functions */
+  ScanConfig (config, "CATDIR",                 "%s",  0, CATDIR);
+
+  /* unique to markrock */
+  ScanConfig (config, "ROCK_NEIGHBOR_RADIUS",   "%lf", 0, &ROCK_NEIGHBOR_RADIUS);
+  ScanConfig (config, "ROCK_NEIGHBOR_NMAX",     "%d",  0, &ROCK_NEIGHBOR_NMAX);
+
+  ScanConfig (config, "ROCK_RADIUS",            "%lf", 0, &RADIUS);
+  ScanConfig (config, "ROCK_MAX_RADIUS",        "%lf", 0, &MAX_RADIUS);
+  ScanConfig (config, "ROCK_MAX_SPEED",         "%lf", 0, &MAX_SPEED);
+  ScanConfig (config, "ROCK_MAX_DELAY",         "%lf", 0, &MAX_DELAY);
+  ScanConfig (config, "ROCK_CATALOG",           "%s",  0, RockCat);
+  ScanConfig (config, "PHOTCODE_FILE",          "%s",  0, PhotCodeFile);
+
+  ScanConfig (config, "BRIGHT_HALO_MAG",        "%lf", 0, &BRIGHT_HALO_MAG);
+  ScanConfig (config, "BRIGHT_HALO_SLOPE",      "%lf", 0, &BRIGHT_HALO_SLOPE);
+  ScanConfig (config, "GSCFILE",                "%s",  0, GSCFILE);
+  ScanConfig (config, "GSCDIR",                 "%s",  0, GSCDIR);
+  ScanConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
+
+  if (!LoadPhotcodes (PhotCodeFile, &photcodes)) {
+    fprintf (stderr, "error loading photcodes\n");
+    exit (0);
+  }
+
+  free (config);
+  free (file);
+
+}
Index: /tags/start/Ohana/src/markrock/src/aregion.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/aregion.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/aregion.c	(revision 12606)
@@ -0,0 +1,186 @@
+# include "markrock.h"
+
+double BigDecBounds[] = {0.0, 7.5, 15.0, 22.5, 30.0, 37.5, 45.0, 
+			 52.5, 60.0, 67.5, 75.0, 82.5, 90.0,
+			 0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, 
+			 -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+char *DecSections[] = {"N0000", "N0730", "N1500", "N2230", "N3000", "N3730", "N4500", 
+		       "N5230", "N6000", "N6730", "N7500", "N8230", "weirdness", 
+		       "S0000", "S0730", "S1500", "S2230", "S3000", "S3730", "S4500", 
+		       "S5230", "S6000", "S6730", "S7500", "S8230", "weirdness"};
+
+char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			"n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			"s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			"s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+char *disk[] = {"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", 
+		"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "weirdness", 
+		"disk 1", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", 
+		"disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "weirdness"};
+
+int NBigRASections [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3, 48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3};
+
+int NDecLines[] = {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 24, 
+                   0, 597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48};
+
+/* find region file which contains ra, dec */
+aregion (region, f, ra, dec) 
+GSCRegion region[];
+FILE *f;
+double ra, dec;
+{
+  
+  
+  char buffer[28800], temp[50], file[50];
+  double dr, dd;
+  double RA0, RA1, DEC0, DEC1;
+  int i, NBigDec, NLINES, done, nregion;
+  
+  while (ra < 0) { ra += 360.0; }
+  while (ra >= 360.0) { ra -= 360.0; }
+    
+  if (dec >= 86.25) {
+    sprintf (file, "%s/n8230/pole.cpt\0", GSCDIR);
+    region[0].DEC[0] = 86.25;
+    region[0].DEC[1] = 93.75;
+    region[0].RA[0] = -180.0;
+    region[0].RA[1] =  540.0;
+    strcpy (region[0].filename, file);
+    return;
+  }
+    
+  NBigDec = -1;
+  for (i = 0; i < 12; i++) {
+# ifdef DEBUG
+    fprintf (stderr, "%d %f %f %f\n", i, dec, BigDecBounds[i], BigDecBounds[i+1]);
+# endif
+    if ((dec >= BigDecBounds[i]) && (dec < BigDecBounds[i+1])) {
+      NBigDec = i;
+      break;
+    }
+  }
+  if (NBigDec < 0) {
+    for (i = 13; i < 24; i++) {
+# ifdef DEBUG
+      fprintf (stderr, "%d %f %f %f\n", i, dec, BigDecBounds[i], BigDecBounds[i+1]);
+# endif
+      if ((dec < BigDecBounds[i]) && (dec >= BigDecBounds[i+1])) {
+	NBigDec = i;
+	break;
+      }
+    }
+  }
+  if (NBigDec < 0) {
+    fprintf (stderr, "dec out of range: %f\n", dec);
+  }
+    
+  NLINES = 0;
+  for (i = 0; i < NBigDec; i++) {
+    NLINES += NDecLines[i];
+  }
+  fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+      
+  done = FALSE;
+  Fread (buffer, 1, 48*NDecLines[NBigDec], f, "char");
+  for (i = 0; !done && (i < NDecLines[NBigDec]); i++) {
+    strncpy (temp, &buffer[i*48], 48);
+    temp[49] = 0;
+    hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+    if (RA1 < RA0) RA1 += 360.0;
+# ifdef DEBUG
+    fprintf (stderr, "%f %f %f  %f %f %f  %s\n", DEC0, dec, DEC1, RA0, ra, RA1, temp);
+# endif
+    if ((dec >= 0) && (dec >= DEC0) && (dec < DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+    if ((dec < 0) && (dec < DEC0) && (dec >= DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+  }
+  if (!done) {
+    fprintf (stderr, "error in search: %f %f\n", ra, dec);
+    exit (0);
+  }
+  temp[5] = 0;
+  sprintf (file, "%s/%s/%s.cpt\0", GSCDIR, Dec2Sections[NBigDec],&temp[1]);
+  if (DEC0 < DEC1) {
+    region[0].DEC[0] = DEC0;
+    region[0].DEC[1] = DEC1;
+  } else {
+    region[0].DEC[0] = DEC1;
+    region[0].DEC[1] = DEC0;
+  }     
+  region[0].RA[0] = RA0;
+  region[0].RA[1] = RA1;
+  strcpy (region[0].filename, file);
+  return;
+}
+
+
+/**********/
+int hms_to_deg (h0, h1, d0, d1, string) 
+     char *string;
+     double *h0, *h1, *d0, *d1;
+{
+  
+  int flag_d0, flag_d1, flag_h0, flag_h1;
+  double tmp;
+  
+  *d0 = *h0 = *d1 = *h1 = 0;
+
+  flag_h0 = dparse (h0, 1, string);
+  flag_h1 = dparse (h1, 4, string);
+  flag_d0 = dparse (d0, 7, string);
+  flag_d1 = dparse (d1, 9, string);
+  *h0 *= flag_h0;
+  *h1 *= flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  dparse (&tmp, 2, string);
+  *h0 += tmp/60.0;
+  dparse (&tmp, 3, string);
+  *h0 += tmp/3600.0;
+  
+  dparse (&tmp, 5, string);
+  *h1 += tmp/60.0;
+  dparse (&tmp, 6, string);
+  *h1 += tmp/3600.0;
+  
+  dparse (&tmp, 8, string);
+  *d0 += tmp/60.0;
+
+  dparse (&tmp, 10, string);
+  *d1 += tmp/60.0;
+
+  *h0 *= 15*flag_h0;
+  *h1 *= 15*flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  return (TRUE);
+}
+
+
+/*
+      if (buffer[i*48 + 19] == ' ') continue;
+      strncpy (temp, &buffer[i*48 + 19], 20);       temp[20] = 0;
+      hms_to_deg (&RA,  &DEC, temp, ' ', 3);
+
+
+  dBigRA = 360.0 / (int)(0.5 + 48*cos(3.1415927*0.5*(BigDecBounds[NBigDec] + BigDecBounds[NBigDec + 1])/180.0));
+
+  NBigRA = ra / dBigRA;
+
+  NBig = NBigRA;
+  for (i = 0; (i < 12) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+  for (i = 13; (i < 24) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+
+
+  fprintf (stderr, "%d %d %d %d %f %f -> %f %f %f\n", NBigDec, NBigRA, NBigRASections[NBigDec], NBig, ra, dec, BigDecBounds[NBigDec], BigDecBounds[NBigDec + 1], dBigRA);
+*/
Index: /tags/start/Ohana/src/markrock/src/check_lockfile.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/check_lockfile.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/check_lockfile.c	(revision 12606)
@@ -0,0 +1,39 @@
+# include "markrock.h"
+
+check_lockfile ()
+{
+  
+  FILE *f;
+  char filename[128];
+  struct stat filestat;
+
+  sprintf (filename, "%s/lock\0", CATDIR);
+  if (stat (filename, &filestat) != -1) {
+    fprintf (stderr, "ERROR: catalog %s is locked, try again later\n", CATDIR);
+    exit (0);
+  }
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't set lock file %s\n", filename);
+    exit (0);
+  }
+  fclose (f);
+
+}
+
+clear_lockfile ()
+{
+  
+  char filename[128], line[256];
+  struct stat filestat;
+
+  sprintf (filename, "%s/lock\0", CATDIR);
+  if (stat (filename, &filestat) != -1) {
+    sprintf (line, "rm %s\0", filename);
+    system (line);
+  } else {
+    fprintf (stderr, "can't remove lockfile, why not?\n");
+  }
+
+}
Index: /tags/start/Ohana/src/markrock/src/check_permissions.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/check_permissions.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/check_permissions.c	(revision 12606)
@@ -0,0 +1,63 @@
+# include "markrock.h"
+
+check_permissions (char *basefile) {
+  
+  FILE *f;
+  char *c, dir[256], filename[256];
+  struct stat filestat;
+  uid_t fuid, uid;
+  gid_t fgid, gid;
+  int status;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to write to directory */
+  sprintf (filename, "%s\0", basefile);
+  c = strrchr (filename, '/');
+  if (c == (char *) NULL) {
+    strcpy (dir, ".");
+  } else {
+    *c = 0;
+    strcpy (dir, filename);
+  }
+  status = stat (dir, &filestat);
+  if (status == -1) {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (0);
+  } 
+  if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRWXU)) ||
+      ((gid == filestat.st_gid) && (filestat.st_mode & S_IRWXG)) || 
+      (filestat.st_mode & S_IRWXO)) {
+  } else {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (0);
+  }
+  
+  /* check permission to write to file */
+  sprintf (filename, "%s\0", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (0);
+    }
+  }
+  
+  /* check permission to write to backup file */
+  sprintf (filename, "%s~\0", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (0);
+    }
+  }
+  
+}
Index: /tags/start/Ohana/src/markrock/src/config.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/config.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/config.c	(revision 12606)
@@ -0,0 +1,110 @@
+# include <ohana.h>
+# define D_NBYTES 4096
+
+char *LoadConfigFile (filename) 
+char *filename; 
+{
+  
+  FILE *f;
+  int i, done, Nbytes, NBYTES, size;
+  char *config;
+  
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "couldn't find %s\n", filename);
+    return ((char *) NULL);
+  }
+ 
+  NBYTES = D_NBYTES;
+  ALLOCATE (config, char, NBYTES);
+ 
+  size = 0;
+  done = FALSE;
+  for (i = 0; !done; i++) {
+    Nbytes = Fread (&config[i*D_NBYTES], sizeof(char), D_NBYTES, f, "char");
+    size += Nbytes;
+    if (Nbytes < D_NBYTES) 
+      done = TRUE;
+    else {
+      NBYTES += D_NBYTES;
+      REALLOCATE (config, char, NBYTES);
+    }
+  }
+  
+  config[size] = '\n';
+  config[size+1] = 0;
+  REALLOCATE (config, char, size + 2);
+ 
+  fclose (f);
+
+  return (config);
+}
+
+int ScanConfig /* we expect one more field: the pointer to the value requested */
+# ifndef ANSI
+(config, field, mode, va_alist) 
+ char *config; char *field, *mode; va_dcl
+# else
+(char       config[],
+ char       field[],
+ char       mode[],...)
+# endif
+{
+ 
+  int i, j;
+  char *p, *p2, tmp[256];
+  va_list argp;
+  double value;
+  
+# ifndef ANSI
+  va_start (argp);
+# else
+  va_start (argp, N);
+# endif
+  
+  /* find the correct line with field */
+  p2 = config;
+  for (i = 0; ; i++) {
+    if (!strncmp (field, p2, strlen(field))) {
+      p = p2 + strlen (field);
+      break;
+    }
+    else {
+      p2 = strchr (p2, '\n');
+      if (p2 == (char *) NULL) {
+	fprintf (stderr, "entry %s not found in config file\n", field);
+	return (FALSE);
+      }
+      else p2++;
+    }
+  }
+  if (!strcmp (mode, "%s")) {
+    p2 = strchr (p, '\n');
+    if (p2 == (char *) NULL)
+      p2 = config + strlen(config);
+    bcopy (p, tmp, (p2-p));
+    tmp[(p2-p)] = 0;
+    stripwhite (tmp);
+    p2 = va_arg (argp, char *);
+    strcpy (p2, tmp);
+  }
+  else {
+ 
+    /* try to get a numerical value from the field */
+    value = strtod (p, &p2);
+    if ((*p2 == 'd') || (*p2 == 'D')) 
+      value *= pow (10.0, atof (p2 + 1));
+    
+    if (!strcmp (mode, "%d"))  *va_arg (argp, int *)       = value;
+    if (!strcmp (mode, "%u"))  *va_arg (argp, unsigned *)  = value;
+    if (!strcmp (mode, "%ld")) *va_arg (argp, long *)      = value;
+    if (!strcmp (mode, "%hd")) *va_arg (argp, short *)     = value;
+    if (!strcmp (mode, "%f"))  *va_arg (argp, float *)     = value;
+    if (!strcmp (mode, "%lf")) *va_arg (argp, double *)    = value;
+    
+  }
+ 
+  va_end (argp);
+  return (TRUE);
+  
+}
Index: /tags/start/Ohana/src/markrock/src/coordops.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/coordops.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/coordops.c	(revision 12606)
@@ -0,0 +1,342 @@
+# include "markrock.h"
+
+XY_to_RD (ra, dec, x, y, coords)
+double *ra, *dec;
+double  x, y;
+Coords coords[];
+{
+
+  double L, M, X, Y, T;
+  double R, sphi, cphi, stht, ctht;
+  double alpha, delta, salp, calp, sdel, sdp, cdp;
+  
+  *ra  = 0;
+  *dec = 0;
+
+# if 1
+  if (!strcmp(&coords[0].ctype[4], "-PLY")) {
+    X = coords[0].cdelt1*(x - coords[0].crpix1 + x*x*coords[0].polyterms[0][0] + x*y*coords[0].polyterms[1][0] + y*y*coords[0].polyterms[2][0]
+			  + x*x*x*coords[0].polyterms[3][0] + x*x*y*coords[0].polyterms[4][0] + x*y*y*coords[0].polyterms[5][0] + y*y*y*coords[0].polyterms[6][0]);
+    Y = coords[0].cdelt2*(y - coords[0].crpix2 + x*x*coords[0].polyterms[0][1] + x*y*coords[0].polyterms[1][1] + y*y*coords[0].polyterms[2][1]
+			  + x*x*x*coords[0].polyterms[3][1] + x*x*y*coords[0].polyterms[4][1] + x*y*y*coords[0].polyterms[5][1] + y*y*y*coords[0].polyterms[6][1]);
+  } else {
+# else
+  {
+# endif
+    X = coords[0].cdelt1*(x - coords[0].crpix1);
+    Y = coords[0].cdelt2*(y - coords[0].crpix2);
+  }    
+
+  L = (X*coords[0].pc1_1 + Y*coords[0].pc1_2);
+  M = (X*coords[0].pc2_1 + Y*coords[0].pc2_2);
+
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    R = hypot (L,M);
+    if ((L == 0) && (M == 0)) {
+      sphi = 0;
+      cphi = 1;
+    }
+    else {
+      sphi =  L / R;
+      cphi = -M / R;
+    }
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN")) {
+      if (R == 0) {
+	stht = 1.0;
+	ctht = 0.0;
+      }
+      else {
+	T = DEG_RAD / R;
+	stht =   T / sqrt ( 1.0 + T*T);
+	ctht = 1.0 / sqrt ( 1.0 + T*T);
+      }
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      ctht = RAD_DEG * R;
+      stht = sqrt (1 - ctht*ctht);
+    }
+
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    
+    sdel = stht*sdp - ctht*cphi*cdp;
+    salp = ctht*sphi;
+    calp = stht*cdp + ctht*cphi*sdp;
+    alpha = atan2 (salp, calp);
+    delta = asin (sdel);
+    
+    *ra  = DEG_RAD*alpha + coords[0].crval1;
+    *dec = DEG_RAD*delta;
+  }
+  if (!strcmp(&coords[0].ctype[4], "-LIN") || !strcmp(&coords[0].ctype[0], "GENE")) {
+    *ra  = L + coords[0].crval1;
+    *dec = M + coords[0].crval2;
+  }
+
+}
+
+
+fXY_to_RD (ra, dec, x, y, coords)
+float *ra, *dec;
+double  x, y;
+Coords coords[];
+{
+
+  double L, M, X, Y, T;
+  double R, sphi, cphi, stht, ctht;
+  double alpha, delta, salp, calp, sdel, sdp, cdp;
+  
+  *ra  = 0;
+  *dec = 0;
+
+  if (!strcmp(&coords[0].ctype[4], "-PLY")) {
+    X = coords[0].cdelt1*(x - coords[0].crpix1 + x*x*coords[0].polyterms[0][0] + x*y*coords[0].polyterms[1][0] + y*y*coords[0].polyterms[2][0]
+			  + x*x*x*coords[0].polyterms[3][0] + x*x*y*coords[0].polyterms[4][0] + x*y*y*coords[0].polyterms[5][0] + y*y*y*coords[0].polyterms[6][0]);
+    Y = coords[0].cdelt2*(y - coords[0].crpix2 + x*x*coords[0].polyterms[0][1] + x*y*coords[0].polyterms[1][1] + y*y*coords[0].polyterms[2][1]
+			  + x*x*x*coords[0].polyterms[3][1] + x*x*y*coords[0].polyterms[4][1] + x*y*y*coords[0].polyterms[5][1] + y*y*y*coords[0].polyterms[6][1]);
+  } else {
+    X = coords[0].cdelt1*(x - coords[0].crpix1);
+    Y = coords[0].cdelt2*(y - coords[0].crpix2);
+  }    
+  L = (X*coords[0].pc1_1 + Y*coords[0].pc1_2);
+  M = (X*coords[0].pc2_1 + Y*coords[0].pc2_2);
+
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    R = hypot (L,M);
+    if ((L == 0) && (M == 0)) {
+      sphi = 0;
+      cphi = 1;
+    }
+    else {
+      sphi =  L / R;
+      cphi = -M / R;
+    }
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") ) {
+      if (R == 0) {
+	stht = 1.0;
+	ctht = 0.0;
+      }
+      else {
+	T = DEG_RAD / R;
+	stht =   T / sqrt ( 1.0 + T*T);
+	ctht = 1.0 / sqrt ( 1.0 + T*T);
+      }
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      ctht = RAD_DEG * R;
+      stht = sqrt (1 - ctht*ctht);
+    }
+
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    
+    sdel = stht*sdp - ctht*cphi*cdp;
+    salp = ctht*sphi;
+    calp = stht*cdp + ctht*cphi*sdp;
+    alpha = atan2 (salp, calp);
+    delta = asin (sdel);
+    
+    *ra  = DEG_RAD*alpha + coords[0].crval1;
+    *dec = DEG_RAD*delta;
+  }
+  if (!strcmp(&coords[0].ctype[4], "-LIN") || !strcmp(&coords[0].ctype[0], "GENE")) {
+    *ra  = L + coords[0].crval1;
+    *dec = M + coords[0].crval2;
+  }
+
+}
+
+
+RD_to_XY (x, y, ra, dec, coords)
+double *x, *y;
+double  ra, dec;
+Coords coords[];
+{
+
+  double tmp_d;
+  double X, Y, sphi, cphi, stht;
+  double salp, calp, sdel, cdel, sdp, cdp;
+
+  if (!strcmp(&coords[0].ctype[4], "-PLY")) {
+    /* fprintf (stderr, "approximate to polynomial TAN plane fit\n");  */
+  }
+
+  *x = 0;
+  *y = 0;
+  if (!strcmp(&coords[0].ctype[0], "GENE") || !strcmp(&coords[0].ctype[4], "-LIN")) {
+    X = (ra  - coords[0].crval1);
+    Y = (dec - coords[0].crval2);
+  }
+  
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    salp = sin(RAD_DEG*(ra - coords[0].crval1));
+    calp = cos(RAD_DEG*(ra - coords[0].crval1));
+    sdel = sin(RAD_DEG*dec);
+    cdel = cos(RAD_DEG*dec);
+
+    stht = sdel*sdp + cdel*cdp*calp;  /* sin(theta) */
+    sphi = cdel*salp;  /* = cos(theta)*sin(phi) */
+    cphi = cdel*sdp*calp - sdel*cdp; /* = cos(theta)*cos(phi) */
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") ) {
+      X =  DEG_RAD * sphi / stht;
+      Y = -DEG_RAD * cphi / stht;
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      X =  DEG_RAD * sphi;
+      Y = -DEG_RAD * cphi;
+    }
+    X = X;
+    Y = Y;
+  }
+  
+  tmp_d = 1.0 / (coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1);
+  *x = tmp_d * (coords[0].pc2_2*X - coords[0].pc1_2*Y) / coords[0].cdelt1 + coords[0].crpix1;
+  *y = tmp_d * (coords[0].pc1_1*Y - coords[0].pc2_1*X) / coords[0].cdelt2 + coords[0].crpix2;
+ 
+}
+
+
+fRD_to_XY (x, y, ra, dec, coords)
+float *x, *y;
+double  ra, dec;
+Coords coords[];
+{
+
+  double tmp_d;
+  double X, Y, sphi, cphi, stht;
+  double salp, calp, sdel, cdel, sdp, cdp;
+
+  *x = 0;
+  *y = 0;
+  if (!strcmp(&coords[0].ctype[0], "GENE") || !strcmp(&coords[0].ctype[4], "-LIN")) {
+    X = (ra  - coords[0].crval1);
+    Y = (dec - coords[0].crval2);
+  }
+  
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    salp = sin(RAD_DEG*(ra - coords[0].crval1));
+    calp = cos(RAD_DEG*(ra - coords[0].crval1));
+    sdel = sin(RAD_DEG*dec);
+    cdel = cos(RAD_DEG*dec);
+
+    stht = sdel*sdp + cdel*cdp*calp;  /* sin(theta) */
+    sphi = cdel*salp;  /* = cos(theta)*sin(phi) */
+    cphi = cdel*sdp*calp - sdel*cdp; /* = cos(theta)*cos(phi) */
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") ) {
+      X =  DEG_RAD * sphi / stht;
+      Y = -DEG_RAD * cphi / stht;
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      X =  DEG_RAD * sphi;
+      Y = -DEG_RAD * cphi;
+    }
+    X = X;
+    Y = Y;
+  }
+  
+  tmp_d = 1.0 / (coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1);
+  *x = tmp_d * (coords[0].pc2_2*X - coords[0].pc1_2*Y) / coords[0].cdelt1 + coords[0].crpix1;
+  *y = tmp_d * (coords[0].pc1_1*Y - coords[0].pc2_1*X) / coords[0].cdelt2 + coords[0].crpix2;
+ 
+}
+
+
+
+GetCoords (coords, header) 
+Coords coords[];
+Header header[];
+{
+
+  int status;
+  double rotate;
+
+  rotate = 0.0;
+  coords[0].crval1 = coords[0].crpix1 = coords[0].cdelt1 = 0.0;
+  coords[0].crval2 = coords[0].crpix2 = coords[0].cdelt2 = 0.0;
+  coords[0].pc1_1 = coords[0].pc2_2 = 1.0;
+  coords[0].pc2_1 = coords[0].pc1_2 = 0.0;
+  strcpy (coords[0].ctype, "NONE");
+
+  status = TRUE; 
+  if (fits_scan (header, "CTYPE2", "%s", 1, coords[0].ctype)) {
+    status  = fits_scan (header, "CRVAL1", "%lf", 1, &coords[0].crval1);
+    status &= fits_scan (header, "CRPIX1", "%lf", 1, &coords[0].crpix1);
+    status &= fits_scan (header, "CRVAL2", "%lf", 1, &coords[0].crval2);  
+    status &= fits_scan (header, "CRPIX2", "%lf", 1, &coords[0].crpix2);
+    if (fits_scan (header, "CDELT1", "%lf", 1, &coords[0].cdelt1)) {
+      status &= fits_scan (header, "CDELT2", "%lf", 1, &coords[0].cdelt2);
+      if (fits_scan (header, "CROTA2", "%lf", 1, &rotate)) {
+	coords[0].pc1_1 =  cos(rotate*RAD_DEG);
+	coords[0].pc1_2 = -sin(rotate*RAD_DEG);
+	coords[0].pc2_1 =  sin(rotate*RAD_DEG);
+	coords[0].pc2_2 =  cos(rotate*RAD_DEG);
+      }
+      if (fits_scan (header, "PC001001", "%lf", 1, &coords[0].pc1_1)) {
+	status &= fits_scan (header, "PC001002", "%lf", 1, &coords[0].pc1_2);
+	status &= fits_scan (header, "PC002001", "%lf", 1, &coords[0].pc2_1);
+	status &= fits_scan (header, "PC002002", "%lf", 1, &coords[0].pc2_2);
+      }
+    }
+    else {
+      if (fits_scan (header, "CD1_1", "%lf", 1, &coords[0].pc1_1)) {
+	status &= fits_scan (header, "CD1_2", "%lf", 1, &coords[0].pc1_2);
+	status &= fits_scan (header, "CD2_1", "%lf", 1, &coords[0].pc2_1);
+	status &= fits_scan (header, "CD2_2", "%lf", 1, &coords[0].pc2_2);
+	coords[0].cdelt1 = coords[0].cdelt2 = 1.0;
+      }
+      else {
+	status = FALSE;
+      }
+    }
+  }
+  else {
+    if (fits_scan (header, "RA_O", "%lf", 1, &coords[0].crval1)) {
+      status  = fits_scan (header, "RA_X", "%lf", 1, &coords[0].pc1_1);
+      status &= fits_scan (header, "RA_Y", "%lf", 1, &coords[0].pc1_2);
+      status &= fits_scan (header, "DEC_O", "%lf", 1, &coords[0].crval2);  
+      status &= fits_scan (header, "DEC_X", "%lf", 1, &coords[0].pc2_1);
+      status &= fits_scan (header, "DEC_Y", "%lf", 1, &coords[0].pc2_2);
+      coords[0].crpix1 = coords[0].crpix2 = 0.0;
+      coords[0].cdelt1 = coords[0].cdelt2 = 1.0;
+      strcpy (coords[0].ctype, "GENE");
+    }
+  }
+  if (!status) {
+    fprintf (stderr, "error getting all elements for coordinate mode %d\n", coords[0].ctype);
+    coords[0].crval1 = coords[0].crpix1 = coords[0].cdelt1 = 0.0;
+    coords[0].crval2 = coords[0].crpix2 = coords[0].cdelt2 = 0.0;
+    coords[0].pc1_1 = coords[0].pc2_2 = 1.0;
+    coords[0].pc2_1 = coords[0].pc1_2 = 0.0;
+    strcpy (coords[0].ctype, "NONE");
+  }
+}
+
+
+  /* -PLY projection is an extrapolation of the -TAN projection. 
+     In addition to the usual linear terms of CRPIXi, PC00i00j, there are 
+     higher order polynomial terms (up to 3rd order):
+     Axis 1 terms:
+     PCA1X2Y0 = coords.polyterm[0][0] = x^2                                             
+     PCA1X1Y1 = coords.polyterm[1][0] = xy                                          
+     PCA1X0Y2 = coords.polyterm[2][0] = y^2                                             
+     PCA1X3Y0 = coords.polyterm[3][0] = x^3                                             
+     PCA1X2Y1 = coords.polyterm[4][0] = x^2 y                                             
+     PCA1X1Y2 = coords.polyterm[5][0] = x y^2                                             
+     PCA1X0Y3 = coords.polyterm[6][0] = y^2                                              
+     Axis 2 terms:
+     PCA2X2Y0 = coords.polyterm[0][1] = x^2                                               
+     PCA2X1Y1 = coords.polyterm[1][1] = xy                                                
+     PCA2X0Y2 = coords.polyterm[2][1] = y^2                                               
+     PCA2X3Y0 = coords.polyterm[3][1] = x^3                                               
+     PCA2X2Y1 = coords.polyterm[4][1] = x^2 y                                             
+     PCA2X1Y2 = coords.polyterm[5][1] = x y^2                                             
+     PCA2X0Y3 = coords.polyterm[6][1] = y^2                                               
+  */
Index: /tags/start/Ohana/src/markrock/src/count_neighbors.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/count_neighbors.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/count_neighbors.c	(revision 12606)
@@ -0,0 +1,32 @@
+# include "markrock.h"
+
+count_neighbors (rocks, Nrocks, catalog, catstats)
+Rocks *rocks;
+int Nrocks;
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  float *x, *y;
+  double X, Y, dx, dy, dr;
+  int i, j, k;
+
+  x = catstats[0].X;
+  y = catstats[0].Y;
+
+  for (i = 0; i < Nrocks; i++) {
+    for (k = 0; k < 3; k++) {
+      X = rocks[i].X[k];
+      Y = rocks[i].Y[k];
+      rocks[i].N[k] = 0;
+      for (j = 0; j < catalog[0].Naverage; j++) {
+	if ((dx = X - x[j]) > ROCK_NEIGHBOR_RADIUS) continue;
+	if (dx < -ROCK_NEIGHBOR_RADIUS) break;
+	dy = Y - y[j];
+	dr = hypot (dx, dy);
+	if (dr > ROCK_NEIGHBOR_RADIUS) continue;
+	rocks[i].N[k] ++;
+      }
+    }
+  }
+}
Index: /tags/start/Ohana/src/markrock/src/find_bright_stars.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/find_bright_stars.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/find_bright_stars.c	(revision 12606)
@@ -0,0 +1,147 @@
+# include "markrock.h"
+
+find_bright_stars (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  int i, j, n, m, first_j, Nave, Ngsc, Nmark;
+  Catalog GSCdata;
+  double MinRA, MinDEC, MaxRA, MaxDEC, RaCenter, DecCenter;
+  Coords *tcoords;
+  float *X1, *Y1, *X2, *Y2;
+  int *N1, *N2;
+  char *mark;
+  double dX, dY, dR, MaxDist, MaxDist1, MaxRadius, radius, radius2;
+
+  load_gsc_data (&GSCdata, catstats);
+
+  Nave = catalog[0].Naverage;
+  Ngsc = GSCdata.Naverage;
+    
+  /* in the function below, it is better to have the catalog with
+     more stars associated with index 2 (j) */ 
+  X2 = catstats[0].X;
+  Y2 = catstats[0].Y;
+  N2 = catstats[0].N;
+  ALLOCATE (X1, float, Ngsc);
+  ALLOCATE (Y1, float, Ngsc);
+  ALLOCATE (N1, int, Ngsc);
+  ALLOCATE (mark, char, Nave);
+  bzero (mark, Nave);
+
+  tcoords = &catstats[0].coords;
+  for (i = 0; i < Ngsc; i++) {
+    fRD_to_XY (&X1[i], &Y1[i], GSCdata.average[i].R, GSCdata.average[i].D, tcoords);
+    N1[i] = i;
+  }
+  if (Ngsc > 1) sort_lists (X1, Y1, N1, Ngsc);
+  
+  /* first find stellar halos */
+  /* max radius (mag = -1) */
+  /** the j index moves quickly and is better associated with the catalog with more stars */
+  MaxRadius = BRIGHT_HALO_SLOPE * (-1.0 - BRIGHT_HALO_MAG); 
+  /** find catalog stars near GSC stars **/
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -2*MaxRadius) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*MaxRadius) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    radius = MAX (BRIGHT_HALO_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_HALO_MAG), 0.0);
+    if (radius == 0) {
+      i++; 
+      continue;
+    }
+    radius2 = radius*radius;
+    for (; (dX > -2*radius) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < radius2) {  /* new measurement of this star */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+# if (0)
+  /* next find y spikes */
+  /** find catalog stars near GSC stars **/
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -BRIGHT_YTRAIL_WIDTH) {
+      i++;
+      continue;
+    }
+    if (dX >= BRIGHT_YTRAIL_WIDTH) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    MaxDist = MAX (BRIGHT_YTRAIL_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_YTRAIL_MAG), 0.0);
+    for (; (dX > -BRIGHT_YTRAIL_WIDTH) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      if ((fabs(dX) < BRIGHT_YTRAIL_WIDTH) && (fabs(dY) < MaxDist)) {  /* star on spike */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+  /* next find x spikes */
+  /** find catalog stars near GSC stars **/
+  MaxDist = MAX (BRIGHT_XTRAIL_SLOPE * (-1.0 - BRIGHT_XTRAIL_MAG), 0.0);
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -MaxDist) {
+      i++;
+      continue;
+    }
+    if (dX >= MaxDist) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    MaxDist1 = MAX (BRIGHT_XTRAIL_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_XTRAIL_MAG), 0.0);
+    for (; (dX > -MaxDist1) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      if ((fabs(dY) < BRIGHT_XTRAIL_WIDTH) && (fabs(dX) < MaxDist1)) {  /* star on spike */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+# endif
+
+  /* done with search, mark selected stars */
+  Nmark = 0;
+  for (i = 0; i < Nave; i++) {
+    if (mark[i]) {
+      Nmark ++;
+      catalog[0].average[N2[i]].code = ID_BLEED;
+    }
+  } 
+  fprintf (stderr, "marked %d stars for bright star\n", Nmark);
+  
+  free (X1);
+  free (Y1);
+  free (N1);
+  free (mark);
+  free (GSCdata.average);
+
+}
+
Index: /tags/start/Ohana/src/markrock/src/find_ghosts.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/find_ghosts.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/find_ghosts.c	(revision 12606)
@@ -0,0 +1,70 @@
+# include "markrock.h"
+
+find_ghosts (catalog, catstats, filename, image, Nimage)
+Catalog catalog[];
+CatStats catstats[];
+char *filename;
+Image image[];
+int Nimage;
+{
+
+  int i, j, first_j, Nave, Ngsc, Nregions;
+  Catalog GSCdata, Ghostdata;
+  double MinRA, MinDEC, MaxRA, MaxDEC, RaCenter, DecCenter;
+  Coords *tcoords;
+  float *X1, *Y1, *X2, *Y2;
+  int *N1, *N2, *match;
+  char *mark;
+  double dX, dY, dR, RADIUS2, BRIGHT_RADIUS, radius, X, Y, R, D;
+  Image timage;
+  GSCRegion *region, *gregions();
+
+  for (i = 0; i < Nimage; i++) {
+    
+    /* coords structure for ghost image */
+    timage = image[i];
+    timage.coords.cdelt1 = -1*image[i].coords.cdelt1;
+    timage.coords.cdelt2 = -1*image[i].coords.cdelt2;
+    timage.coords.crpix1 = 2*OPTICAL_AXIS1 - image[i].coords.crpix1;
+    timage.coords.crpix2 = 2*OPTICAL_AXIS2 - image[i].coords.crpix2;
+
+    region = gregions2 (&timage, &Nregions);
+    
+    /* find ghost stars */
+    load_gsc_data_ghost (&GSCdata, region, Nregions, &timage);
+
+    /* refect ghost stars to find locations of ghosts */
+    ALLOCATE (Ghostdata.average, Average, MAX (GSCdata.Naverage, 1));
+    for (j = 0; j < GSCdata.Naverage; j++) {
+      RD_to_XY (&X, &Y, GSCdata.average[j].R, GSCdata.average[j].D, &timage);
+      fXY_to_RD (&Ghostdata.average[j].R, &Ghostdata.average[j].D, X, Y, &image[i]);
+      Ghostdata.average[j].M = GSCdata.average[j].M;
+    }    
+    Ghostdata.Naverage = GSCdata.Naverage;
+
+    /* match ghosts and image stars, mark ghosts */
+    find_matches (catalog, catstats, &Ghostdata, i);
+
+    free (Ghostdata.average);
+    free (GSCdata.average);
+  }
+
+}
+
+/* 
+
+   just to be clear on some of the terms:
+
+   the "ghost" is the fuzzy patch of light on an image caused by
+     a reflected star
+
+   the "ghost star" is the star in the sky which causes a ghost
+
+   the "ghost image" is the image location on the sky 
+     where ghost stars may come from.
+
+   the "image stars" are observed stars at the location of the
+     ghost - these are detections of the ghost
+
+
+*/
Index: /tags/start/Ohana/src/markrock/src/find_group.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/find_group.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/find_group.c	(revision 12606)
@@ -0,0 +1,69 @@
+# include "markrock.h"
+
+find_group (catstats, mark, Npts, i, ANGLE)
+     CatStats catstats[];
+     double *ANGLE;
+     int i, Npts;
+     char *mark;
+{
+ 
+  float *R, *D;
+  int j, N, bin, Ndegbin;
+  unsigned short int *A;
+  double Ra, De, dR, dD, angle, limit;
+
+   /* assign some parameter values */
+  
+  R = catstats[0].X;
+  D = catstats[0].Y;
+  limit = 10.0*sqrt((double)(M_PI*RADIUS*RADIUS*catstats[0].density)/(double)(NBINS));
+  Ndegbin = NBINS / 180.0;
+  ALLOCATE (A, unsigned short int, NBINS)
+  bzero (A, NBINS*sizeof(short));
+
+  /* look for points concentrated in an angle bin */
+  if (mark[i]) return (FALSE);
+  Ra = R[i];
+  De = D[i];
+  N = 0;
+  /* points east */
+  for (j = i + 1; (j < Npts) && (R[j] - Ra < RADIUS); j++) {
+    if (mark[j]) continue;
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) 
+	continue;
+      if (angle < 0) angle += M_PI;
+      bin = 1 + angle*DEG_RAD*Ndegbin;
+      A[bin] ++;
+      if (A[bin] > limit) {
+	*ANGLE = (bin - 1.0) / (DEG_RAD*Ndegbin);
+	return (TRUE);
+      }
+      N ++;
+    }
+  }
+  /* points west */
+  for (j = i - 1; (j >= 0) && (Ra - R[j] < RADIUS); j--) {
+    if (mark[j]) continue;
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) 
+	continue;
+      if (angle < 0) angle += M_PI;
+      bin = 1 + angle*DEG_RAD*Ndegbin;
+      A[bin] ++;	
+      if (A[bin] > limit) {
+	*ANGLE = (bin - 1.0) / (DEG_RAD*Ndegbin);
+	return (TRUE);
+      }
+      N ++;
+    }
+  }
+  return (FALSE);
+}
+  
Index: /tags/start/Ohana/src/markrock/src/find_rocks.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/find_rocks.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/find_rocks.c	(revision 12606)
@@ -0,0 +1,193 @@
+# include "markrock.h"
+
+Rocks *find_rocks (catalog, catstats, nrocks)
+Catalog catalog[];
+CatStats catstats[];
+int *nrocks;
+{
+
+  int i, j, k, n, m, N, M, first_j, NOBJECT, Nobject, Nrocks, NROCKS;
+  double X, Y, RADIUS2;
+  float *X1, *Y1;
+  float dX, dY, dR;
+  float dtime;
+  int *N1, *N0;
+  unsigned int Tref;
+  int *T1, Ttmp;
+  int Nstar, Nghost, Ng;
+  unsigned int flags;
+  unsigned short NotRock, IsProper;
+  Coords *tcoords;
+  double ax, ay, cx, cy, dt, dt1, dt2, dt3, dX1, dX2, speed, distance;
+  Rocks *rocks;
+  struct timeval now, then;  
+  double MaxSeparation;
+
+  gettimeofday (&then, (void *) NULL);
+
+  Nstar = catalog[0].Naverage;
+
+  NOBJECT = 1000;
+  ALLOCATE (X1, float, NOBJECT);
+  ALLOCATE (Y1, float, NOBJECT);
+  ALLOCATE (T1, int,   NOBJECT);
+  ALLOCATE (N1, int,   NOBJECT);
+  Nobject = 0;
+  N0 = catstats[0].N;
+
+  NROCKS = 3000;
+  ALLOCATE (rocks, Rocks, NROCKS);
+  Nrocks = 0;
+
+  Tref = 0;
+  NotRock = (ID_ROCK ^ 0xffff);
+  IsProper = ID_USNO | ID_PROPER;
+  for (i = 0; i < Nstar; i++) {
+    N = N0[i];
+    if (RESET && ((catalog[0].average[N].code & ID_ROCK) == ID_ROCK)) {
+      /* resets both relevant bits */
+      catalog[0].average[N].code &= NotRock;
+    }
+    if (RESET && (catalog[0].average[N].code == ID_COSMIC)) {
+      /* resets both relevant bits */
+      catalog[0].average[N].code = 0;
+    }
+    /* accept a measurement if it is either unmarked or marked as a proper motion star */
+    if ((catalog[0].average[N].Nm == 1) && (catalog[0].average[N].Nn > 0) && ((catalog[0].average[N].code == 0) || ((catalog[0].average[N].code & IsProper) == IsProper))) {
+      if (Tref == 0) Tref = catalog[0].measure[catalog[0].average[N].offset].t;
+      X1[Nobject] = catstats[0].X[i];
+      Y1[Nobject] = catstats[0].Y[i];
+      if (catalog[0].measure[catalog[0].average[N].offset].t > Tref) 
+	T1[Nobject] = catalog[0].measure[catalog[0].average[N].offset].t - Tref;
+      else {
+	Ttmp = Tref - catalog[0].measure[catalog[0].average[N].offset].t;
+	T1[Nobject] = -Ttmp;
+      }      
+      N1[Nobject] = N;
+      Nobject ++;
+      if (Nobject == NOBJECT - 1) {
+	NOBJECT += 1000;
+	REALLOCATE (X1, float, NOBJECT);
+	REALLOCATE (Y1, float, NOBJECT);
+	REALLOCATE (T1, int, NOBJECT);
+	REALLOCATE (N1, int,   NOBJECT);
+      }
+    }
+  }
+  REALLOCATE (X1, float, Nobject);
+  REALLOCATE (Y1, float, Nobject);
+  REALLOCATE (T1, int, Nobject);
+  REALLOCATE (N1, int,   Nobject);
+  if (Nobject > 1) sort_set (X1, Y1, T1, N1, Nobject);
+
+  fprintf (stderr, "Nobj: %d\n", Nobject);
+
+  MaxSeparation = MAX_SPEED * MAX_DELAY;
+  fprintf (stderr, "%f %f %f %f %f\n", MaxSeparation, MAX_RADIUS, RADIUS, MAX_SPEED, MAX_DELAY);
+
+  /** find 3 rocks in a line **/
+  for (i = 0; i < Nobject - 2; i++) {
+    fprintf (stderr, ".");
+    for (j = i + 1; j < Nobject - 1; j++) {
+      if (X1[j] - X1[i] > MaxSeparation) goto NEXTi;
+      if (X1[i] - X1[j] > MaxSeparation) goto NEXTj;
+      if (T1[i] == T1[j]) continue;
+      dt = (int)(T1[j] - T1[i]);
+      if (fabs(dt) > MAX_DELAY) continue;
+      ax = (X1[j] - X1[i])/dt;
+      cx = (X1[i]*T1[j] - X1[j]*T1[i])/dt;
+      ay = (Y1[j] - Y1[i])/dt;
+      cy = (Y1[i]*T1[j] - Y1[j]*T1[i])/dt;
+      speed = hypot (ax, ay);
+      if (speed > MAX_SPEED) continue;
+      for (k = j + 1; k < Nobject; k++) {
+	if (X1[k] - X1[j] > MaxSeparation) goto NEXTj;
+	if (X1[j] - X1[k] > MaxSeparation) goto NEXTk;
+	if (T1[i] == T1[k]) continue;
+	if (T1[j] == T1[k]) continue;
+	dt1 = fabs(dt);
+	dt2 = fabs ((int)(T1[i] - T1[k]));
+	dt3 = fabs ((int)(T1[j] - T1[k]));
+	dt1 = MIN(MIN(dt1,dt2),dt3);
+	dt3 = MAX(MAX(dt1,dt2),dt3);
+	if (fabs(dt3) > MAX_DELAY) continue;
+	/* errors are too large by this point */
+	if (RADIUS * dt3 / dt1 > MAX_RADIUS) continue; 
+	dX1 = T1[k]*ax - X1[k] + cx;
+	dX2 = T1[k]*ay - Y1[k] + cy;
+	distance = hypot (dX1, dX2);
+	/*
+        fprintf (stderr, "%d %d %d %f %f %d %f %f\n", i, j, k, ax, cx, T1[k], X1[k], dX1);
+	if (k > 100) exit (0);
+	*/
+	if (distance < RADIUS){
+	  catalog[0].average[N1[i]].code |= ID_ROCK;
+	  catalog[0].average[N1[j]].code |= ID_ROCK;
+	  catalog[0].average[N1[k]].code |= ID_ROCK;
+
+	  rocks[Nrocks].X[0]     = X1[i];
+	  rocks[Nrocks].Y[0]     = Y1[i];
+	  rocks[Nrocks].ra[0]    = catalog[0].average[N1[i]].R;
+	  rocks[Nrocks].dec[0]   = catalog[0].average[N1[i]].D;
+
+	  m = catalog[0].average[N1[i]].offset;
+	  rocks[Nrocks].mag[0]   = PhotRel (&catalog[0].measure[m], &photcodes, ZERO_POINT);
+	  rocks[Nrocks].t[0]     = catalog[0].measure[m].t;
+
+	  rocks[Nrocks].X[1]     = X1[j];
+	  rocks[Nrocks].Y[1]     = Y1[j];
+	  rocks[Nrocks].ra[1]    = catalog[0].average[N1[j]].R;
+	  rocks[Nrocks].dec[1]   = catalog[0].average[N1[j]].D;
+
+	  m = catalog[0].average[N1[j]].offset;
+	  rocks[Nrocks].mag[1]   = PhotRel (&catalog[0].measure[m], &photcodes, ZERO_POINT);
+	  rocks[Nrocks].t[1]     = catalog[0].measure[m].t;
+
+	  rocks[Nrocks].X[2]     = X1[k];
+	  rocks[Nrocks].Y[2]     = Y1[k];
+	  rocks[Nrocks].ra[2]    = catalog[0].average[N1[k]].R;
+	  rocks[Nrocks].dec[2]   = catalog[0].average[N1[k]].D;
+
+	  m = catalog[0].average[N1[k]].offset;
+	  rocks[Nrocks].mag[2]   = PhotRel (&catalog[0].measure[m], &photcodes, ZERO_POINT);
+	  rocks[Nrocks].t[2]     = catalog[0].measure[m].t;
+
+	  fprintf (stderr, "*");
+	  Nrocks ++;
+	  if (Nrocks >= NROCKS) {
+	    NROCKS += 3000;
+	    REALLOCATE (rocks, Rocks, NROCKS);
+	  }
+	}
+      NEXTk:
+      }
+    NEXTj:
+    }
+    gettimeofday (&now, (void *) NULL);
+    dtime = (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec);
+    if (dtime > 200) {
+      fprintf (stderr, "taking too long to find all rocks, giving up...\n");
+      goto escape_loop;
+    }
+  NEXTi:
+  }
+
+escape_loop:
+  for (i = 0; i < Nobject; i++) {
+    if ((catalog[0].average[N1[i]].code == 0) && (catalog[0].average[N1[i]].Nn >= 2)) {
+      catalog[0].average[N1[i]].code = ID_COSMIC;
+    }
+  }
+
+  fprintf (stderr, "found %d rocks\n", Nrocks);
+
+  free (T1);
+  free (X1);
+  free (Y1);
+  free (N1);
+
+  REALLOCATE (rocks, Rocks, MAX (1, Nrocks));
+  *nrocks = Nrocks;
+  return (rocks);
+
+}
Index: /tags/start/Ohana/src/markrock/src/find_slow_rocks.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/find_slow_rocks.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/find_slow_rocks.c	(revision 12606)
@@ -0,0 +1,135 @@
+# include "markrock.h"
+
+Rocks *find_slow_rocks (catalog, catstats, nrocks)
+Catalog catalog[];
+CatStats catstats[];
+int *nrocks;
+{
+
+  int i, j, k, m, N, Nm, NOBJECT, Nobject, Nrocks, NROCKS;
+  double RADIUS2;
+  double *R1, *D1, *X1, *Y1, *M1;
+  double R, D, X, Y, M;
+  double dX, dY, dR;
+  int *N1, *N0;
+  unsigned int *T1, T;
+  int Nstar, Nghost, Ng, Nmax;
+  unsigned int flags;
+  Coords *tcoords;
+  double ax, ay, cx, cy, dt, dX1, dX2, speed, distance;
+  Rocks *rocks;
+  unsigned short IsProper;
+
+  Nstar = catalog[0].Naverage;
+
+  NOBJECT = 1000;
+  ALLOCATE (N1, int,   NOBJECT);
+  Nobject = 0;
+  N0 = catstats[0].N;
+
+  NROCKS = 3000;
+  ALLOCATE (rocks, Rocks, NROCKS);
+  Nrocks = 0;
+
+  Nmax = 0;
+  IsProper = ID_USNO | ID_PROPER;
+  for (i = 0; i < Nstar; i++) {
+    N = N0[i];
+    /* accept a measurement if it is either unmarked or marked as a proper motion star and may have multiple measurements */
+    if ((catalog[0].average[N].code == 0) || (catalog[0].average[N].code & IsProper == IsProper)) {
+      Nmax = MAX (catalog[0].average[N].Nm, Nmax);
+      N1[Nobject] = N;
+      Nobject ++;
+      if (Nobject == NOBJECT - 1) {
+	NOBJECT += 1000;
+	REALLOCATE (N1, int,   NOBJECT);
+      }
+    }
+  }
+  REALLOCATE (N1, int,   Nobject);
+  fprintf (stderr, "Nobj: %d\n", Nobject);
+
+  ALLOCATE (R1, double, Nmax);
+  ALLOCATE (D1, double, Nmax);
+  ALLOCATE (X1, double, Nmax);
+  ALLOCATE (Y1, double, Nmax);
+  ALLOCATE (T1, unsigned int, Nmax);
+  ALLOCATE (M1, double, Nmax);
+  /** find multiple measured objects, find additional measurements along that line */
+
+  for (i = 0; i < Nobject; i++) {
+    fprintf (stderr, ",");
+    if (catalog[0].average[N1[i]].Nm > 1) {
+      N = N1[i];
+      Nm = catalog[0].average[N].Nm;
+      m = catalog[0].average[N].offset;
+      for (j = 0; j < 2; j++) {
+	R1[j] = catalog[0].average[N].R - catalog[0].measure[m+j].dR/360000.0;
+	D1[j] = catalog[0].average[N].D - catalog[0].measure[m+j].dD/360000.0;
+	RD_to_XY (&X1[j], &Y1[j], R1[j], D1[j], &catstats[0].coords);
+	T1[j] = catalog[0].measure[m+j].t;
+	M1[j] = catalog[0].measure[m+j].M - catalog[0].measure[m+j].Mcal;
+      }
+      dt = T1[1] - T1[0];
+      ax = (X1[1] - X1[0])/dt;
+      cx = (X1[0]*T1[1] - X1[1]*T1[0])/dt;
+      ay = (Y1[1] - Y1[0])/dt;
+      cy = (Y1[0]*T1[1] - Y1[1]*T1[0])/dt;
+      speed = hypot (ax, ay);
+      for (k = 0; k < Nobject; k++) {
+	N = N1[k];
+	Nm = catalog[0].average[N].Nm;
+	m = catalog[0].average[N].offset;
+	for (j = 0; j < Nm; j++) {
+	  R = catalog[0].average[N].R - catalog[0].measure[m+j].dR/360000.0;
+	  D = catalog[0].average[N].D - catalog[0].measure[m+j].dD/360000.0;
+	  RD_to_XY (&X, &Y, R, D, &catstats[0].coords);
+	  T = catalog[0].measure[m+j].t;
+	  M = catalog[0].measure[m+j].M - catalog[0].measure[m+j].Mcal;
+	  if (T1[0] == T) continue;
+	  if (T1[1] == T) continue;
+	  dX1 = T*ax - X + cx;
+	  dX2 = T*ay - Y + cy;
+	  distance = hypot (dX1, dX2);
+	  if (distance < RADIUS){
+	    catalog[0].average[N1[i]].code |= ID_ROCK;
+	    catalog[0].average[N1[k]].code |= ID_ROCK;
+	    rocks[Nrocks].ra    = R1[0];
+	    rocks[Nrocks].dec   = D1[0];
+	    rocks[Nrocks].mag   = M1[0];
+	    rocks[Nrocks].t     = T1[0];
+	    rocks[Nrocks+1].ra  = R1[1];
+	    rocks[Nrocks+1].dec = D1[1];
+	    rocks[Nrocks+1].mag = T1[1];
+	    rocks[Nrocks+1].t   = M1[1];
+	    rocks[Nrocks+2].ra  = R;
+	    rocks[Nrocks+2].dec = D;
+	    rocks[Nrocks+2].mag = M;
+	    rocks[Nrocks+2].t   = T;
+	    fprintf (stderr, "%f %f %f %d   %f\n", rocks[Nrocks].ra, rocks[Nrocks].dec, rocks[Nrocks].mag, rocks[Nrocks].t, speed);
+	    Nrocks += 3;
+	    if (Nrocks > NROCKS - 3) {
+	      NROCKS += 3000;
+	      REALLOCATE (rocks, Rocks, NROCKS);
+	    }
+	  }
+	}
+      }
+    }
+  }
+
+  fprintf (stderr, "found %d rocks\n", Nrocks);
+
+  free (R1);
+  free (D1);
+  free (M1);
+  free (T1);
+  free (X1);
+  free (Y1);
+  free (N1);
+
+  REALLOCATE (rocks, Rocks, Nrocks);
+  *nrocks = Nrocks;
+  return (rocks);
+
+}
Index: /tags/start/Ohana/src/markrock/src/gcatalog.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/gcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/gcatalog.c	(revision 12606)
@@ -0,0 +1,31 @@
+# include "markrock.h"
+
+gcatalog (Catalog *catalog) {
+  
+  char filename[128];
+  int i, status, mode;
+  unsigned int NotTrail;
+  unsigned short NotBad;
+
+  mode = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+
+  if (!load_catalog (catalog, mode, VERBOSE)) {
+    fprintf (stderr, "ERROR: failure loading catalog\n");
+    exit (1);
+  }
+
+  if (RESET) {
+    NotBad = (0xffff ^ 0xc003);
+    for (i = 0; i < catalog[0].Naverage; i++) {
+      if ((catalog[0].average[i].code & ID_MOVING) &&
+	  (catalog[0].average[i].code & ID_BAD_OBJECT) &&
+	  (catalog[0].average[i].code & 0x0003)) {
+	/* this will set the correct bit for each to 0 */ 
+	catalog[0].average[i].code &= NotBad;
+      }
+    }
+    for (i = 0; i < catalog[0].Nmeasure; i++) {
+      catalog[0].measure[i].flags &= ~PART_OF_TRAIL;
+    }
+  }
+}
Index: /tags/start/Ohana/src/markrock/src/gcatstats.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/gcatstats.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/gcatstats.c	(revision 12606)
@@ -0,0 +1,54 @@
+# include "markrock.h"
+
+gcatstats (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  int i;
+  double RaCenter, DecCenter;
+  double MinRA, MaxRA, MinDEC, MaxDEC;
+  float *X1, *Y1;
+  int *N1;
+  Coords tcoords;
+  
+  fits_scan (&catalog[0].header, "RA0", "%lf", 1, &MinRA);
+  fits_scan (&catalog[0].header, "RA1", "%lf", 1, &MaxRA);
+  fits_scan (&catalog[0].header, "DEC0", "%lf", 1, &MinDEC);
+  fits_scan (&catalog[0].header, "DEC1", "%lf", 1, &MaxDEC);
+
+ /* double check on region RA and DEC ranges */
+  DecCenter = 0.5*(MinDEC + MaxDEC);
+  RaCenter = 0.5*(MinRA + MaxRA);
+
+  catstats[0].RA[0] = MinRA;
+  catstats[0].RA[1] = MaxRA;
+  catstats[0].DEC[0] = MinDEC;
+  catstats[0].DEC[1] = MaxDEC;
+  /* number of stars per square arcsec */
+
+  /** allocate local arrays **/
+  ALLOCATE (catstats[0].X, float, catalog[0].Naverage);
+  ALLOCATE (catstats[0].Y, float, catalog[0].Naverage);
+  ALLOCATE (catstats[0].N, int,   catalog[0].Naverage);
+
+  /* project onto rectilinear grid with 1 arcsec pixels, sort by X */
+  /* reference for coords is center of field  */
+  catstats[0].coords.crval1 = RaCenter;
+  catstats[0].coords.crval2 = DecCenter;
+  catstats[0].coords.crpix1 = catstats[0].coords.crpix2 = 0.0;
+  catstats[0].coords.cdelt1 = catstats[0].coords.cdelt2 = 1.0 / 3600.0;
+  catstats[0].coords.pc1_1 = catstats[0].coords.pc2_2 = 1.0;
+  catstats[0].coords.pc1_2 = catstats[0].coords.pc2_1 = 0.0;
+  strcpy (catstats[0].coords.ctype, "RA---TAN");
+
+  X1 = catstats[0].X;
+  Y1 = catstats[0].Y;
+  for (i = 0; i < catalog[0].Naverage; i++, X1++, Y1++) {
+    fRD_to_XY (X1, Y1, catalog[0].average[i].R, catalog[0].average[i].D, &catstats[0].coords);
+    catstats[0].N[i] = i;
+  }
+  if (catalog[0].Naverage > 1) sort_lists (catstats[0].X, catstats[0].Y, catstats[0].N, catalog[0].Naverage);
+  
+}
+
Index: /tags/start/Ohana/src/markrock/src/gregions.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/gregions.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/gregions.c	(revision 12606)
@@ -0,0 +1,134 @@
+# include "markrock.h"
+
+GSCRegion *gregions1 (catstats, Nregions)
+CatStats catstats[];
+int *Nregions;
+{
+  
+  GSCRegion *region;
+  int i, j, k, x, y, done, nregion, nregion2, NREGION;
+  double ra, dec, dx, dy, Xo[4], Yo[4];
+  FILE *f;
+
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: could not open GSC region file %s\n", GSCFILE);
+    exit (0);
+  }
+  nregion = 0;
+  NREGION = 10;
+  ALLOCATE (region, GSCRegion, NREGION);
+
+  if (catstats[0].DEC[0] == 86.25) { /* pole region */
+    dec = 86.0;
+    for (ra = 0.1; ra < 370; ra+= 30.0) {
+      aregion (&region[nregion], f, ra, dec);
+      done = FALSE;
+      for (j = 0; (j < nregion - 1) && !done; j++) {
+	if (!strcmp (region[nregion].filename, region[j].filename)) {
+	  nregion --;
+	  done = TRUE;
+	}
+      }
+      nregion ++;
+      if (nregion == NREGION) {
+	NREGION += 10;
+	REALLOCATE (region, GSCRegion, NREGION);
+      }
+    }
+  } else {
+    for (x = 0; x < 2; x++) {
+      for (y = 0; y < 2; y++) {
+	for (dx = -0.1; dx <= 0.1; dx += 0.2) {
+	  for (dy = -0.1; dy <= 0.1; dy += 0.2) {
+	    ra  = catstats[0].RA[x] + dx;
+	    dec = catstats[0].DEC[y] + dy;
+	    aregion (&region[nregion], f, ra, dec);
+	    done = FALSE;
+	    for (j = 0; (j < nregion) && !done; j++) {
+	      if (!strcmp (region[nregion].filename, region[j].filename)) {
+		done = TRUE;
+	      }
+	    }
+	    if (!done) {
+	      nregion ++;
+	    } 
+	    if (nregion == NREGION) {
+	      NREGION += 10;
+	      REALLOCATE (region, GSCRegion, NREGION);
+	    }
+	  }
+	}
+      }
+    }
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "using %d regions\n", nregion);
+    for (i = 0; i < nregion; i++) {
+      fprintf (stderr, "region %d: %f %f  %f %f\n", i, region[i].RA[0], region[i].RA[1], region[i].DEC[0], region[i].DEC[1]);
+    } 
+  }
+
+  REALLOCATE (region, GSCRegion, MAX (nregion, 1));
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (region);
+  
+}
+
+GSCRegion *gregions2 (image, Nregions)
+Image *image;
+int *Nregions;
+{
+  
+  GSCRegion *region;
+  FILE *f;
+  double x, y;
+  double dr, dd, dec, ra;
+  int i, j, done, nregion, NREGION;
+  
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find GSC region file %s\n", GSCFILE);
+    exit (0);
+  }
+  
+  /* find regions at image corners */
+  NREGION = 10;
+  ALLOCATE (region, GSCRegion, NREGION);
+  nregion = 0;
+
+  /* look for new regions on grid across image */ 
+  for (x = 0.0; x <= 1.0; x+=0.25) {
+    for (y = 0.0; y <= 1.0; y+=0.25) {
+      XY_to_RD (&ra, &dec, image[0].NX*(1.1*x - 0.05), image[0].NY*(1.1*y - 0.05), &image[0].coords);
+      aregion (&region[nregion], f, ra, dec);
+      done = FALSE;
+      for (j = 0; (j < nregion) && !done; j++) {
+	if (!strcmp (region[nregion].filename, region[j].filename)) {
+	  nregion --;
+	  done = TRUE;
+	}
+      }
+      nregion ++;
+      if (nregion == NREGION) {
+	NREGION += 10;
+	REALLOCATE (region, GSCRegion, NREGION);
+      }
+    }
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "found %d region files:\n", nregion);
+    for (i = 0; i < nregion; i++) {
+      fprintf (stderr, "  %d %s\n", i, region[i].filename);
+    }
+  }
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (region);
+  
+}
Index: /tags/start/Ohana/src/markrock/src/load_gsc_data.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/load_gsc_data.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/load_gsc_data.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include "markrock.h"
+# define NBYTES 160000
+# define BYTES_STAR 23
+# define BLOCK 1000
+# define DNSTARS 1000
+
+load_gsc_data (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  /* load data from the GSC files */
+  char filename[128];
+  char *tbuffer;
+  int nstar, NSTARS;
+  int i, j, Nbytes, nbytes, Nregions;
+  double R, D, M, MagLimit;
+  FILE *f;
+  GSCRegion *region, *gregions1(), *gregions2();
+  
+  region = gregions1 (catstats, &Nregions);
+
+  MagLimit = 25;
+  nstar = 0;
+  NSTARS = DNSTARS;
+  ALLOCATE (tbuffer, char, (BLOCK*BYTES_STAR));
+  ALLOCATE (catalog[0].average, Average, NSTARS);
+  Nbytes = BLOCK*BYTES_STAR;
+  
+  for (j = 0; j < Nregions; j++) {
+    f = fopen (region[j].filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "GSC file for region %s missing\n", region[j].filename);
+      exit (0);
+    }
+    
+    while ((nbytes = fread (tbuffer, 1, Nbytes, f)) > 0) {
+      for (i = 0; i < nbytes / BYTES_STAR; i++) {
+	dparse (&M, 3, &tbuffer[i*BYTES_STAR]);
+	if (M > MagLimit) continue;
+	dparse (&R, 1, &tbuffer[i*BYTES_STAR]);
+	dparse (&D, 2, &tbuffer[i*BYTES_STAR]);
+	catalog[0].average[nstar].R = R;
+	catalog[0].average[nstar].D = D;
+	catalog[0].average[nstar].M = M * 1000.0;
+	nstar++;
+	if (nstar == NSTARS - 1) {
+	  NSTARS += DNSTARS;
+	  REALLOCATE (catalog[0].average, Average, NSTARS);
+	}
+      }
+    }
+    fclose (f);
+  }
+
+  free (tbuffer);
+  REALLOCATE (catalog[0].average, Average, nstar);
+  catalog[0].Naverage = nstar;
+  
+}
+
Index: /tags/start/Ohana/src/markrock/src/markrock.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/markrock.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/markrock.c	(revision 12606)
@@ -0,0 +1,80 @@
+# include "markrock.h"
+
+main (int argc, char **argv) {
+  
+  int i, Nrocks1, Nrocks2;
+  Catalog catalog;
+  CatStats catstats;
+  Rocks *rocks1, *rocks2, *find_rocks(), *find_slow_rocks();
+  struct timeval now, then;  
+  
+  gettimeofday (&then, (void *) NULL);
+  ConfigInit (&argc, argv);
+  
+  VERBOSE = FALSE;
+  if ((i = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  FORCE_RUN = FALSE;
+  if ((i = get_argument (argc, argv, "-f"))) {
+    FORCE_RUN = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  RESET = FALSE;
+  if ((i = get_argument (argc, argv, "-reset"))) {
+    RESET = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  if (argc < 2) {
+    fprintf (stderr, "ERROR: Usage: markstar (catalog)\n");
+    exit (0);
+  }
+
+  /* if lockfile exists, program will complain and quit */
+  check_permissions (argv[1]);
+  check_permissions (RockCat);
+
+  catalog.filename = argv[1];
+  switch (lock_catalog (&catalog, LCK_XCLD)) {
+  case 0:
+    fprintf (stderr, "ERROR: can't lock file\n");
+    exit (1);
+  case 1:
+    gcatalog (&catalog); /* load from disk */
+    break;
+  case 2:
+    fprintf (stderr, "no data in %s, skipping\n", catalog.filename);
+    catalog.Naverage = 0;
+    catalog.Nmeasure = 0;
+    unlock_catalog (&catalog);
+    exit (0);
+  default:
+    fprintf (stderr, "weird lock_catalog exit state\n");
+    exit (1);
+  }
+
+  gcatstats (&catalog, &catstats);
+
+  find_bright_stars (&catalog, &catstats); 
+
+  rocks1 = find_rocks (&catalog, &catstats, &Nrocks1); 
+  count_neighbors (rocks1, Nrocks1, &catalog, &catstats);
+
+  /* rocks2 = find_slow_rocks (&catalog, &catstats, &Nrocks2);  */
+
+  wcatalog (&catalog);
+  wrocks (rocks1, Nrocks1);
+
+  unlock_catalog (&catalog);
+  /* wrocks (rocks2, Nrocks2); */
+
+  if (VERBOSE) {
+    gettimeofday (&now, (void *) NULL);
+    fprintf (stderr, "%s: elapsed time = %.2f sec\n", argv[1], 
+	     (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec));
+  }
+
+  fprintf (stderr, "SUCCESS\n");
+}
+
Index: /tags/start/Ohana/src/markrock/src/old/add_unfound.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/add_unfound.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/add_unfound.c	(revision 12606)
@@ -0,0 +1,35 @@
+  /* incorporate unmatched image stars -- after all catalogs searched... */
+  for (i = 0; i < Nstars; i++) {
+    if (!found[i]) {
+      catalog[0].average[Nave].R = stars[N1[i]].R;
+      catalog[0].average[Nave].D = stars[N1[i]].D;
+      catalog[0].average[Nave].M = 1000.0*stars[N1[i]].M;
+      catalog[0].average[Nave].Nm = 1;
+      catalog[0].average[Nave].Xp = catalog[0].average[Nave].Xm = 0.0;
+      catalog[0].average[Nave].offset = Nmeas;
+      catalog[0].measure[Nmeas].dR  = 0.0;
+      catalog[0].measure[Nmeas].dD  = 0.0;
+      catalog[0].measure[Nmeas].M   = 1000.0*stars[N1[i]].M;
+      catalog[0].measure[Nmeas].dM  = stars[N1[i]].dM;
+      catalog[0].measure[Nmeas].t  = 3600.0 + stars[N1[i]].Y*0.1;
+      catalog[0].measure[Nmeas].average = (0x00ffffff & Nave);
+      /* time of star = time of image + offset + Y*rate */
+      Nave ++;
+      if (Nave == 0x1000000) {
+	fprintf (stderr, "too many stars in catalog\n");
+	clear_lockfile ();
+	exit (0);
+      }
+      if (Nave == NAVE) {
+	NAVE = Nave + 1000;
+	REALLOCATE (next, int, NAVE);
+	REALLOCATE (catalog[0].average, Average, NAVE);
+      }
+      Nmeas ++;
+      if (Nmeas == NMEAS) {
+	NMEAS = Nmeas + 1000;
+	REALLOCATE (next, int, NMEAS);
+	REALLOCATE (catalog[0].measure, Measure, NMEAS);
+      }
+    }
+  }
Index: /tags/start/Ohana/src/markrock/src/old/addstar.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/addstar.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/addstar.c	(revision 12606)
@@ -0,0 +1,70 @@
+# include "addstar.h"
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  FILE *f;
+  int i, Nstars, Nimage, Nregions, Nmissed;
+  Stars *stars, *gstars();
+  Image image, *pimage, *gimages();
+  Catalog catalog;
+  GSCRegion *region, *gregions();
+  struct timeval now, then;  
+  
+  gettimeofday (&then, (void *) NULL);
+  ConfigInit (argc, argv);
+
+  VERBOSE = FALSE;
+  if ((i = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  if (argc < 2) {
+    fprintf (stderr, "ERROR: Usage: addstar filename\n");
+    exit (0);
+  }
+
+  /* if lockfile exists, program will complain and quit */
+  check_lockfile ();
+
+  stars = gstars (argv[1], &Nstars, &image);
+
+  pimage = gimages (&image, &Nimage);
+  region = gregions (&image, &Nregions);
+
+  for (i = 0; i < Nregions; i++) {
+    gcatalog (&region[i], &catalog);
+    find_matches (&region[i], stars, Nstars, &catalog, &image, pimage, Nimage);
+    wcatalog (&region[i], &catalog);
+  }
+  
+  for (Nmissed = i = 0; i < Nstars; i++) {
+    if (stars[i].found == -1) {
+      fprintf (stderr, "%d %f %f %f %f\n", i, stars[i].R, stars[i].D, stars[i].M, stars[i].dM);
+      Nmissed ++;
+    }
+  }
+  if (Nmissed) fprintf (stderr, "WARNING: %d stars in image were missed!\n", Nmissed);
+
+  wimage (argv[1], &image, Nstars);
+
+  if (VERBOSE) {
+    gettimeofday (&now, (void *) NULL);
+    fprintf (stderr, "%s: elapsed time = %.2f sec\n", argv[1], 
+	     (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec));
+  }
+  clear_lockfile ();
+  fprintf (stderr, "SUCCESS\n");
+}
+
+
+  /* stars within a file are not all within 1 region file:
+     1) check if unfound stars are in current region 
+     2) if not, keep unfound for next pass */
+
+
+/* input star lists should be adjusted so 1 e/sec is mag 25.000 */ 
+
+
Index: /tags/start/Ohana/src/markrock/src/old/aregion.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/aregion.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/aregion.c	(revision 12606)
@@ -0,0 +1,189 @@
+# include "markstar.h"
+
+double BigDecBounds[] = {0.0, 7.5, 15.0, 22.5, 30.0, 37.5, 45.0, 
+			 52.5, 60.0, 67.5, 75.0, 82.5, 90.0,
+			 0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, 
+			 -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+char *DecSections[] = {"N0000", "N0730", "N1500", "N2230", "N3000", "N3730", "N4500", 
+		       "N5230", "N6000", "N6730", "N7500", "N8230", "weirdness", 
+		       "S0000", "S0730", "S1500", "S2230", "S3000", "S3730", "S4500", 
+		       "S5230", "S6000", "S6730", "S7500", "S8230", "weirdness"};
+
+char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			"n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			"s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			"s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+char *disk[] = {"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", 
+		"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "weirdness", 
+		"disk 1", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", 
+		"disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "weirdness"};
+
+int NBigRASections [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3, 48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3};
+
+int NDecLines[] = {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 24, 
+                   0, 597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48};
+
+/* find region file which contains ra, dec */
+aregion (region, f, ra, dec) 
+GSCRegion region[];
+FILE *f;
+double ra, dec;
+{
+
+  
+  
+  char buffer[28800], temp[50], file[50];
+  double dr, dd;
+  double RA0, RA1, DEC0, DEC1;
+  int i, NBigDec, NLINES, done, nregion;
+  
+  while (ra < 0) {
+    ra += 360.0;
+  }
+    
+  if (dec >= 86.25) {
+    sprintf (file, "%s/n8230/pole.cpt\0", GSCDIR);
+    region[0].DEC[0] = 86.25;
+    region[0].DEC[1] = 93.75;
+    region[0].RA[0] = -180.0;
+    region[0].RA[1] =  540.0;
+    strcpy (region[0].filename, file);
+    return;
+  }
+    
+  NBigDec = -1;
+  for (i = 0; i < 12; i++) {
+# ifdef DEBUG
+    fprintf (stderr, "%d %f %f %f\n", i, dec, BigDecBounds[i], BigDecBounds[i+1]);
+# endif
+    if ((dec >= BigDecBounds[i]) && (dec < BigDecBounds[i+1])) {
+      NBigDec = i;
+      break;
+    }
+  }
+  if (NBigDec < 0) {
+    for (i = 13; i < 24; i++) {
+# ifdef DEBUG
+      fprintf (stderr, "%d %f %f %f\n", i, dec, BigDecBounds[i], BigDecBounds[i+1]);
+# endif
+      if ((dec < BigDecBounds[i]) && (dec >= BigDecBounds[i+1])) {
+	NBigDec = i;
+	break;
+      }
+    }
+  }
+  if (NBigDec < 0) {
+    fprintf (stderr, "dec out of range: %f\n", dec);
+  }
+    
+  NLINES = 0;
+  for (i = 0; i < NBigDec; i++) {
+    NLINES += NDecLines[i];
+  }
+  fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+      
+  done = FALSE;
+  Fread (buffer, 1, 48*NDecLines[NBigDec], f, "char");
+  for (i = 0; !done && (i < NDecLines[NBigDec]); i++) {
+    strncpy (temp, &buffer[i*48], 48);
+    temp[49] = 0;
+    hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+    if (RA1 < RA0) RA1 += 360.0;
+# ifdef DEBUG
+    fprintf (stderr, "%f %f %f  %f %f %f  %s\n", DEC0, dec, DEC1, RA0, ra, RA1, temp);
+# endif
+    if ((dec >= 0) && (dec >= DEC0) && (dec < DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+    if ((dec < 0) && (dec < DEC0) && (dec >= DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+  }
+  if (!done) {
+    fprintf (stderr, "error in search: %f %f\n", ra, dec);
+    clear_lockfile ();
+    exit (0);
+  }
+  temp[5] = 0;
+  sprintf (file, "%s/%s/%s.cpt\0", GSCDIR, Dec2Sections[NBigDec],&temp[1]);
+  if (DEC0 < DEC1) {
+    region[0].DEC[0] = DEC0;
+    region[0].DEC[1] = DEC1;
+  } else {
+    region[0].DEC[0] = DEC1;
+    region[0].DEC[1] = DEC0;
+  }     
+  region[0].RA[0] = RA0;
+  region[0].RA[1] = RA1;
+  strcpy (region[0].filename, file);
+  return;
+}
+
+
+/**********/
+int hms_to_deg (h0, h1, d0, d1, string) 
+     char *string;
+     double *h0, *h1, *d0, *d1;
+{
+  
+  int flag_d0, flag_d1, flag_h0, flag_h1;
+  double tmp;
+  
+  *d0 = *h0 = *d1 = *h1 = 0;
+
+  flag_h0 = dparse (h0, 1, string);
+  flag_h1 = dparse (h1, 4, string);
+  flag_d0 = dparse (d0, 7, string);
+  flag_d1 = dparse (d1, 9, string);
+  *h0 *= flag_h0;
+  *h1 *= flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  dparse (&tmp, 2, string);
+  *h0 += tmp/60.0;
+  dparse (&tmp, 3, string);
+  *h0 += tmp/3600.0;
+  
+  dparse (&tmp, 5, string);
+  *h1 += tmp/60.0;
+  dparse (&tmp, 6, string);
+  *h1 += tmp/3600.0;
+  
+  dparse (&tmp, 8, string);
+  *d0 += tmp/60.0;
+
+  dparse (&tmp, 10, string);
+  *d1 += tmp/60.0;
+
+  *h0 *= 15*flag_h0;
+  *h1 *= 15*flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  return (TRUE);
+}
+
+
+/*
+      if (buffer[i*48 + 19] == ' ') continue;
+      strncpy (temp, &buffer[i*48 + 19], 20);       temp[20] = 0;
+      hms_to_deg (&RA,  &DEC, temp, ' ', 3);
+
+
+  dBigRA = 360.0 / (int)(0.5 + 48*cos(3.1415927*0.5*(BigDecBounds[NBigDec] + BigDecBounds[NBigDec + 1])/180.0));
+
+  NBigRA = ra / dBigRA;
+
+  NBig = NBigRA;
+  for (i = 0; (i < 12) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+  for (i = 13; (i < 24) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+
+
+  fprintf (stderr, "%d %d %d %d %f %f -> %f %f %f\n", NBigDec, NBigRA, NBigRASections[NBigDec], NBig, ra, dec, BigDecBounds[NBigDec], BigDecBounds[NBigDec + 1], dBigRA);
+*/
Index: /tags/start/Ohana/src/markrock/src/old/dumpcat.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/dumpcat.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/dumpcat.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include "addstar.h"
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  int i, j, Nstars, Nimage, Nregions;
+  Average *average;
+  Measure *measure;
+  Missing *missing;
+  Catalog catalog;
+  GSCRegion region;
+  FILE *f;
+  
+  if (argc < 4) {
+    fprintf (stderr, "USAGE: dumpcat catalog output mode(0,1,2,3)\n");
+    clear_lockfile ();
+    exit (0);
+  }
+
+  strcpy (region.filename, argv[1]);
+
+  gcatalog (&region, &catalog);
+
+  f = fopen (argv[2], "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "failed to open file %s for write\n", argv[2]);
+    clear_lockfile ();
+    exit (0);
+  }
+
+  average = catalog.average;
+  for (i = 0; i < catalog.Naverage; i++) {
+    fprintf (f, "%10.6f %10.6f %7.3f %3d %3d %8d %d\n", average[i].R, average[i].D, 
+	     0.001*average[i].M, average[i].Nm, average[i].Nn, average[i].offset, catalog.measure[average[i].offset].t);
+    if ((atof(argv[3]) == 1) || (atof(argv[3]) == 3)) {
+      measure = &catalog.measure[average[i].offset];
+      for (j = 0; j < average[i].Nm; j++) {
+	fprintf (f, "  %d %d %f %f %d\n", measure[j].dR, measure[j].dD, 0.001*measure[j].M, 
+		  measure[j].t, measure[j].average);
+      }
+    }
+    if ((atof(argv[3]) == 2) || (atof(argv[3]) == 3)) {
+      if (average[i].Nn > 0) {
+	missing = &catalog.missing[average[i].missing];
+	for (j = 0; j < average[i].Nn; j++) {
+	  fprintf (f, "  %f\n", missing[j].t);
+	}
+      } else { 
+	fprintf (f, "no missing obs\n");
+      }
+    }
+  }
+
+    
+
+  fclose (f);
+    
+
+}
Index: /tags/start/Ohana/src/markrock/src/old/find_bright_stars.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/find_bright_stars.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/find_bright_stars.c	(revision 12606)
@@ -0,0 +1,142 @@
+# include "markstar.h"
+
+find_bright_stars (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  int i, j, n, m, first_j, Nave, Ngsc;
+  Catalog GSCdata;
+  double MinRA, MinDEC, MaxRA, MaxDEC, RaCenter, DecCenter;
+  Coords *tcoords;
+  float *X1, *Y1, *X2, *Y2;
+  int *N1, *N2;
+  char *mark;
+  double dX, dY, dR, MaxDist, MaxDist1, MaxRadius, radius, radius2;
+
+  load_gsc_data (&GSCdata, catstats);
+
+  Nave = catalog[0].Naverage;
+  Ngsc = GSCdata.Naverage;
+    
+  /* in the function below, it is better to have the catalog with
+     more stars associated with index 2 (j) */ 
+  X2 = catstats[0].X;
+  Y2 = catstats[0].Y;
+  N2 = catstats[0].N;
+  ALLOCATE (X1, float, Ngsc);
+  ALLOCATE (Y1, float, Ngsc);
+  ALLOCATE (N1, int, Ngsc);
+  ALLOCATE (mark, char, Nave);
+  bzero (mark, Nave);
+
+  tcoords = &catstats[0].coords;
+  for (i = 0; i < Ngsc; i++) {
+    fRD_to_XY (&X1[i], &Y1[i], GSCdata.average[i].R, GSCdata.average[i].D, tcoords);
+    N1[i] = i;
+  }
+  if (Ngsc > 1) sort_lists (X1, Y1, N1, Ngsc);
+  
+  /* first find stellar halos */
+  /* max radius (mag = -1) */
+  /** the j index moves quickly and is better associated with the catalog with more stars */
+  MaxRadius = BRIGHT_HALO_SLOPE * (-1.0 - BRIGHT_HALO_MAG); 
+  /** find catalog stars near GSC stars **/
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -2*MaxRadius) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*MaxRadius) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    radius = MAX (BRIGHT_HALO_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_HALO_MAG), 0.0);
+    if (radius == 0) {
+      i++; 
+      continue;
+    }
+    radius2 = radius*radius;
+    for (; (dX > -2*radius) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < radius2) {  /* new measurement of this star */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+  /* next find y spikes */
+  /** find catalog stars near GSC stars **/
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -BRIGHT_YTRAIL_WIDTH) {
+      i++;
+      continue;
+    }
+    if (dX >= BRIGHT_YTRAIL_WIDTH) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    MaxDist = MAX (BRIGHT_YTRAIL_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_YTRAIL_MAG), 0.0);
+    for (; (dX > -BRIGHT_YTRAIL_WIDTH) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      if ((fabs(dX) < BRIGHT_YTRAIL_WIDTH) && (fabs(dY) < MaxDist)) {  /* star on spike */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+  /* next find x spikes */
+  /** find catalog stars near GSC stars **/
+  MaxDist = MAX (BRIGHT_XTRAIL_SLOPE * (-1.0 - BRIGHT_XTRAIL_MAG), 0.0);
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -MaxDist) {
+      i++;
+      continue;
+    }
+    if (dX >= MaxDist) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    MaxDist1 = MAX (BRIGHT_XTRAIL_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_XTRAIL_MAG), 0.0);
+    for (; (dX > -MaxDist1) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      if ((fabs(dY) < BRIGHT_XTRAIL_WIDTH) && (fabs(dX) < MaxDist1)) {  /* star on spike */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+
+  /* done with search, mark selected stars */
+  for (i = 0; i < Nave; i++) {
+    if (mark[i]) {
+      catalog[0].average[N2[i]].code = ID_BLEED;
+    }
+  } 
+  
+  free (X1);
+  free (Y1);
+  free (N1);
+  free (mark);
+  free (GSCdata.average);
+
+}
+
Index: /tags/start/Ohana/src/markrock/src/old/find_bright_stars_test.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/find_bright_stars_test.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/find_bright_stars_test.c	(revision 12606)
@@ -0,0 +1,106 @@
+# include "markstar.h"
+
+find_bright_stars (catalog, catstats, filename)
+Catalog catalog[];
+CatStats catstats[];
+char *filename;
+{
+
+  int i, j, first_j, Nave, Ngsc;
+  Catalog GSCdata;
+  double MinRA, MinDEC, MaxRA, MaxDEC, RaCenter, DecCenter;
+  Coords *tcoords;
+  float *X1, *Y1, *X2, *Y2;
+  int *N1, *N2, *match;
+  char *mark;
+  double dX, dY, dR, RADIUS2, BRIGHT_RADIUS, radius;
+
+  load_gsc_data (&GSCdata, filename);
+
+  Nave = catalog[0].Naverage;
+  Ngsc = GSCdata.Naverage;
+    
+  X1 = catstats[0].X;
+  Y1 = catstats[0].Y;
+  N1 = catstats[0].N;
+  ALLOCATE (mark, char, Nave);
+  ALLOCATE (match, int, Nave);
+  ALLOCATE (X2, float, Ngsc);
+  ALLOCATE (Y2, float, Ngsc);
+  ALLOCATE (N2, int, Ngsc);
+  bzero (mark, Nave);
+
+  tcoords = &catstats[0].coords;
+  for (i = 0; i < Ngsc; i++) {
+    fRD_to_XY (&X2[i], &Y2[i], GSCdata.average[i].R, GSCdata.average[i].D, tcoords);
+    N2[i] = i;
+  }
+  if (Ngsc > 1) sort_lists (X2, Y2, N2, Ngsc);
+  
+  /* max radius (mag = -1) */
+  BRIGHT_RADIUS = BRIGHT_SLOPE * (-1.0 - BRIGHT_MAG);
+
+  /** find catalog stars near GSC stars **/
+  for (i = j = 0; (i < Nave) && (j < Ngsc); ) {
+    
+    dX = X1[i] - X2[j];
+
+    if (dX <= -2*BRIGHT_RADIUS) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*BRIGHT_RADIUS) {
+      j++;
+      continue;
+    }
+
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    for (; (dX > -2*BRIGHT_RADIUS) && (j < Ngsc); j++) {
+      radius = MAX (BRIGHT_SLOPE * (0.001*GSCdata.average[N2[j]].M - BRIGHT_MAG), 0.0);
+      RADIUS2 = radius*radius;
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < RADIUS2) {  /* new measurement of this star */
+	mark[i] = TRUE;
+	match[i] = N2[j];
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+  /* done with search, mark selected stars */
+  
+  for (i = 0; i < Nave; i++) {
+    if (mark[i]) {
+      catalog[0].average[N1[i]].code = ID_BLEED;
+    }
+  } 
+  
+}
+
+	/* for test purposes, like determining the parameters, uncomment this 
+	n = N1[i];
+	m = N2[j];
+	fprintf (stdout, "%f %f %f %f %f %f\n", 
+GSCdata.average[m].R, GSCdata.average[m].D, 
+		 0.001*GSCdata.average[m].M, 
+catalog[0].average[n].R, catalog[0].average[n].D, 0.001*catalog[0].average[n].M); */
+  
+  /* for test purposes, like determining the parameters, uncomment this 
+  clear_lockfile (); 
+  fprintf (stderr, "SUCCESS\n");
+  exit (0); */
+
+
+
+	n = N1[i];
+	m = N2[j];
+	RD_to_XY (&X, &Y, Ghostdata[0].average[m].R, Ghostdata[0].average[m].D, &image[0].coords);
+	fprintf (stdout, "%f %f %f %f %f %f %d %f %f\n",
+		 Ghostdata[0].average[m].R, Ghostdata[0].average[m].D, 
+		 0.001*Ghostdata[0].average[m].M, catalog[0].average[n].R, 
+		 catalog[0].average[n].D, 0.001*catalog[0].average[n].M, 
+		 catalog[0].average[n].Nm, X, Y);
Index: /tags/start/Ohana/src/markrock/src/old/find_images.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/find_images.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/find_images.c	(revision 12606)
@@ -0,0 +1,175 @@
+# include "markstar.h"
+double opening_angle ();
+
+Image *find_images (catstats, Nimages)
+CatStats catstats[];
+int *Nimages;
+{
+  
+  Header header;
+  Image *timage, *image;
+  int i, j, k, found, nimage, Nimage, NIMAGE, NTIMAGE, Nloop, Nlast;
+  int n, Nim, status;
+  FILE *f;
+  double Xc[5], Yc[5], Xi[5], Yi[5], r, d;
+  Coords *tcoords;
+
+  /* we make positional comparisons in the projection of catalog */
+  tcoords = &catstats[0].coords;
+  /* define catalog corners */
+  Xc[0] = catstats[0].RA[0]; Yc[0] = catstats[0].DEC[0];
+  Xc[1] = catstats[0].RA[1]; Yc[1] = catstats[0].DEC[0];
+  Xc[2] = catstats[0].RA[1]; Yc[2] = catstats[0].DEC[1];
+  Xc[3] = catstats[0].RA[0]; Yc[3] = catstats[0].DEC[1];
+  Xc[4] = catstats[0].RA[0]; Yc[4] = catstats[0].DEC[0];
+  for (j = 0; j < 5; j++) {
+    r = Xc[j]; d = Yc[j];
+    RD_to_XY (&Xc[j], &Yc[j], r, d, tcoords);
+  }
+
+  /* check if image datafile exists, get header, number of images */
+  if (!fits_read_header (ImageCat, &header)) {
+    fprintf (stderr, "ERROR: No images in catalog %s (1)\n", ImageCat);
+    clear_lockfile ();
+    exit (0);
+  }
+  Nimage = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+  if (Nimage == 0) {
+    fprintf (stderr, "ERROR: No images in catalog %s (1)\n", ImageCat);
+    clear_lockfile ();
+    exit (0);
+  }
+
+  /* get ready to read data on images */ 
+  f = fopen (ImageCat, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: trouble opening Image catalog: %s (2)\n", ImageCat);
+    clear_lockfile ();
+    exit (0);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* set up buffers for images, temporary storage */
+  NTIMAGE = 100;
+  ALLOCATE (timage, Image, NTIMAGE);
+  NIMAGE = 100;
+  ALLOCATE (image, Image, NIMAGE);
+  nimage = 0;
+  Nloop = Nimage / NTIMAGE + 1;
+  Nlast = Nimage % NTIMAGE;
+  
+  /* read in images in groups of NTIMAGE (100) */
+  for (n = 0; n < Nloop; n++) {
+    Nim = (n == Nloop - 1) ? Nlast : NTIMAGE;
+    status = Fread (timage, sizeof(Image), Nim, f, "image");
+    if (status != Nim) {
+      fprintf (stderr, "ERROR: couldn't read images from image catalog: %s\n", ImageCat);
+      clear_lockfile ();
+      exit (0);
+    }
+    /* test each image in block */
+    for (i = 0; i < Nim; i++) {
+      /* define image corners */
+      Xi[0] = 0;            Yi[0] = 0;
+      Xi[1] = timage[i].NX; Yi[1] = 0;
+      Xi[2] = timage[i].NX; Yi[2] = timage[i].NY;
+      Xi[3] = 0;            Yi[3] = timage[i].NY;
+      Xi[4] = 0.5*timage[i].NX; Yi[4] = 0.5*timage[i].NY;
+      found = FALSE;
+      /* transform to tcoords */
+      for (j = 0; j < 5; j++) {
+	XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+	RD_to_XY (&Xi[j], &Yi[j], r, d, tcoords);
+      }
+      /* check if edges cross */
+      for (j = 0; (j < 4) && !found; j++) {
+	for (k = 0; (k < 4) && !found; k++) {
+	  found |= edge_check (&Xi[j], &Yi[j], &Xc[k], &Yc[k]);
+	}
+      }
+      if (found) {
+	image[nimage] = timage[i]; 
+	image[nimage].code = 0;
+	nimage ++;
+	if (nimage == NIMAGE) {
+	  NIMAGE += 100;
+	  REALLOCATE (image, Image, NIMAGE);
+	}
+      }
+    }
+  }
+      
+  if (VERBOSE) { 
+    for (i = 0; i < nimage; i++) {
+      XY_to_RD (&r, &d, 0.5*image[i].NX, 0.5*image[i].NY, &image[i].coords);
+      fprintf (stderr, "associated images: %d %8.4f %8.4f %10d %6d  %5.3f %6.3f %6.3f\n", 
+	       i, r, d, image[i].tzero, image[i].nstar, 0.001*image[i].secz, 
+	       0.001*image[i].Mcal, 0.001*image[i].dMcal);
+    }
+  }
+
+  REALLOCATE (image, Image, MAX (nimage, 1));
+  free (timage);
+  *Nimages = nimage;
+  fclose (f);
+  return (image);
+}
+
+int edge_check (x1, y1, x2, y2)
+double *x1, *y1, *x2, *y2;
+{
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+double opening_angle (x1, y1, x2, y2, x3, y3)
+double x1, y1, x2, y2, x3, y3;
+{
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
+
Index: /tags/start/Ohana/src/markrock/src/old/find_line.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/find_line.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/find_line.c	(revision 12606)
@@ -0,0 +1,161 @@
+# include "markstar.h"
+
+find_line (catstats, mark, Npts, i, M, B, Angle)
+     CatStats catstats[];
+     double *M, *B, Angle;
+     int i, Npts;
+     char *mark;
+{
+  
+  float *R, *D;
+  int j, N;
+  double X, Y, X2, Y2, XY, m, b, det;
+  double dR, dD, Ra, De, angle;
+  char Flipped;
+  
+  R = catstats[0].X;
+  D = catstats[0].Y;
+
+  /* fit a line to points near line */
+  Ra = R[i];
+  De = D[i];
+  X = Ra;
+  Y = De;
+  X2 = Ra*Ra;
+  Y2 = De*De;
+  XY = Ra*De;
+  N = 1;
+  /* points to the east */
+  for (j = i + 1; (j < Npts) && (R[j] - Ra < RADIUS); j++) {
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) continue;
+      if (angle < 0) angle += M_PI;
+      if (fabs(angle - Angle) < RAD_DEG) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* points to the west */
+  for (j = i - 1; !mark[i] && (j >= 0) && (Ra - R[j] < RADIUS); j--) {
+    if (mark[j]) continue;
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) continue;
+      if (angle < 0) angle += M_PI;
+      if (fabs(angle - Angle) < RAD_DEG) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* determine coeffs */
+  Flipped = 0;
+  det = 1.0 / (X2*N - X*X);
+  m = det * (XY*N - X*Y);
+  b = det * (X2*Y - XY*X);
+  if (fabs(m) > 1.1) { /* use a line of R = m*D + b instead */
+    /* fprintf (stderr, "high slope object: %f %f  -> ", m, b); */
+    det = 1.0 / (Y2*N - Y*Y);
+    m = det * (XY*N - X*Y);
+    b = det * (Y2*X - XY*Y);
+    Flipped = 1;
+    /* fprintf (stderr, "%f %f\n", m, b); */
+  }
+
+  *M = m;
+  *B = b;
+  return (Flipped);
+
+}
+
+
+find_better_line (catstats, mark, Npts, i, M, B, axis)
+     CatStats catstats[];
+     double *M, *B;
+     int i, Npts, axis;
+     char *mark;
+{
+  
+  float *R, *D;
+  int j, N;
+  double X, Y, X2, Y2, XY, m, b, det;
+  double dR, dD, Ra, De, delta;
+  
+  R = catstats[0].X;
+  D = catstats[0].Y;
+
+  /* fit a line to points near line */
+  Ra = R[i];
+  De = D[i];
+  X = Y = X2 = Y2 = XY = N = 0;
+  m = *M;  b = *B;
+
+  /* points to the east */
+  for (j = i; (j < Npts) && (R[j] - Ra < RADIUS); j++) {
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      if (axis == 1) 
+	delta = R[j] - m*D[j] - b;
+      else
+	delta = D[j] - m*R[j] - b;
+      if (fabs(delta) < 2*TRAIL_WIDTH) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* points to the west */
+  for (j = i - 1; (j >= 0) && (Ra - R[j] < RADIUS); j--) {
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      if (axis == 1) 
+	delta = R[j] - m*D[j] - b;
+      else
+	delta = D[j] - m*R[j] - b;
+      if (fabs(delta) < 2*TRAIL_WIDTH) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* determine coeffs */
+  if (axis == 0) {
+    det = 1.0 / (X2*N - X*X);
+    m = det * (XY*N - X*Y);
+    b = det * (X2*Y - XY*X);
+  } else {
+    det = 1.0 / (Y2*N - Y*Y);
+    m = det * (XY*N - X*Y);
+    b = det * (Y2*X - XY*Y);
+  }
+
+  /* fprintf (stderr, "%f %f %d\n", m, b, N); */
+
+  *M = m;
+  *B = b;
+
+}
Index: /tags/start/Ohana/src/markrock/src/old/find_matches.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/find_matches.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/find_matches.c	(revision 12606)
@@ -0,0 +1,87 @@
+# include "markstar.h"
+
+find_matches (catalog, catstats, Ghostdata, Nimage)
+CatStats catstats[];
+Catalog catalog[], Ghostdata[];
+int Nimage;
+{
+
+  int i, j, k, n, m, N, M, first_j;
+  double X, Y, RADIUS, RADIUS2;
+  float *X1, *Y1, *X2, *Y2;
+  float dX, dY, dR;
+  int *N1, *N2;
+  int Nstar, Nghost, Ng;
+  unsigned int flags;
+  Coords *tcoords;
+
+  Nstar = catalog[0].Naverage;
+  Nghost = Ghostdata[0].Naverage;
+
+  if (Nghost < 1) return (0);
+
+  /* it is better to have the catalog with fewer stars
+     assigned to the X1 set */
+  X2 = catstats[0].X;
+  Y2 = catstats[0].Y;
+  N2 = catstats[0].N;
+
+  ALLOCATE (X1, float, Nghost);
+  ALLOCATE (Y1, float, Nghost);
+  ALLOCATE (N1, int, Nghost);
+
+  /* project ghosts to the frame of the catalog */
+  tcoords = &catstats[0].coords;
+  for (i = 0; i < Nghost; i++) {
+    fRD_to_XY (&X1[i], &Y1[i], Ghostdata[0].average[i].R, Ghostdata[0].average[i].D, tcoords);
+    N1[i] = i;
+  }
+  if (Nghost > 1) sort_lists (X1, Y1, N1, Nghost);
+
+  /* choose a radius for matches */
+  RADIUS2 = GHOST_RADIUS*GHOST_RADIUS;
+
+  /** find matched stars **/
+  for (i = j = 0; (i < Nghost) && (j < Nstar); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -2*GHOST_RADIUS) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*GHOST_RADIUS) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    for (; (dX > -2*GHOST_RADIUS) && (j < Nstar); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < RADIUS2) {  
+	/* this object may be a ghost star, 
+	   but only mark those measurements on the correct image */
+	M = N2[j];
+	m = catalog[0].average[M].offset;
+	Ng = 0;
+	for (k = 0; k < catalog[0].average[M].Nm; k++) {
+	  if (catalog[0].image[m+k] == Nimage) {
+	    catalog[0].measure[m+k].average |= GHOST_DATA;
+	    Ng ++;
+	  }
+	}
+	/* all measurements are ghosts */
+	if (catalog[0].average[M].Nm == Ng) {
+	  catalog[0].average[M].code = ID_GHOST;
+	}
+      }
+    }
+    j = first_j;
+    i++;
+  }
+
+  free (X1);
+  free (Y1);
+  free (N1);
+
+}
Index: /tags/start/Ohana/src/markrock/src/old/find_trails.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/find_trails.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/find_trails.c	(revision 12606)
@@ -0,0 +1,41 @@
+# include "markstar.h"
+
+find_trails (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  int i, j, N, Nave, axis, marked;
+  double density, spacing, Area, Angle, m, b, RaCenter, DecCenter;
+  double MinRA, MaxRA, MinDEC, MaxDEC;
+  float *X1, *Y1;
+  char *mark;
+  int *N1;
+  Coords tcoords;
+  
+  Nave = catalog[0].Naverage;
+  N1 = catstats[0].N;
+
+  ALLOCATE (mark, char, Nave);
+  bzero (mark, Nave);
+
+  for (i = 0; i < Nave; i++) {
+    /* already marked, ignore */
+    if ((mark[i]) || 
+	(catalog[0].average[N1[i]].code == ID_BLEED) || 
+	(catalog[0].average[N1[i]].code == ID_GHOST))
+      continue;
+    /* a good star, ignore */
+    if ((catalog[0].average[N1[i]].Nm > 3) && 
+	(catalog[0].average[N1[i]].Nm > 4*catalog[0].average[N1[i]].Nn)) {
+      continue;
+    }
+    if (find_group (catstats, mark, Nave, i, &Angle)) {
+      /* this point has an excess nearby concentration, find the line */
+      axis = find_line (catstats, mark, Nave, i, &m, &b, Angle);
+      find_better_line (catstats, mark, Nave, i, &m, &b, axis);
+      mark_trail (catstats, mark, Nave, i, m, b, axis, catalog);
+    }
+  }
+}
+
Index: /tags/start/Ohana/src/markrock/src/old/gimages.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/gimages.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/gimages.c	(revision 12606)
@@ -0,0 +1,214 @@
+# include "addstar.h"
+double opening_angle ();
+
+Image *gimages (image, Npimage)
+Image image[];
+int *Npimage;
+{
+  
+  int i, j, k, NIMAGE, Nimage, addtolist;
+  int NTIMAGE, Ntimage, ntimage;
+  int NPIMAGE, npimage;
+  FILE *f;
+  Image *timage, *pimage;
+  Coords tcoords;
+  Header header;
+  double r, d;
+  double Xi[5], Yi[5], Xo[5], Yo[5];  /* image and original corners */
+
+  /* check if image datafile exists, get header */
+  if (!fits_read_header (ImageCat, &header)) {
+    if (VERBOSE) fprintf (stderr, "New image catalog %s (1)\n", ImageCat);
+    *Npimage = 0;
+    return ((Image *) NULL);
+  }
+
+  /* project onto rectilinear grid with 1 arcsec pixels */
+  /* we keep the original crpix1,2 and crref1,2 */
+  tcoords = image[0].coords;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1 = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2 = tcoords.pc2_1 = 0.0;
+  strcpy (tcoords.ctype, "RA---TAN");
+
+  /* define original corners */
+  Xo[0] = 0;           Yo[0] = 0;
+  Xo[1] = image[0].NX; Yo[1] = 0;
+  Xo[2] = image[0].NX; Yo[2] = image[0].NY;
+  Xo[3] = 0;           Yo[3] = image[0].NY;
+  Xo[4] = 0;           Yo[4] = 0;  /* so we can make a loop easily */
+  for (j = 0; j < 5; j++) {
+    XY_to_RD (&r, &d, Xo[j], Yo[j], &image[0].coords);
+    RD_to_XY (&Xo[j], &Yo[j], r, d, &tcoords);
+  }
+  
+  /* get ready to read data on images */ 
+  f = fopen (ImageCat, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "New image catalog: %s (2)\n", ImageCat);
+    free (header.buffer);
+    *Npimage = 0;
+    return ((Image *) NULL);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  Nimage = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+
+  NTIMAGE = 100;
+  ALLOCATE (timage, Image, NTIMAGE);
+
+  npimage = 0;
+  NPIMAGE = 20;
+  ALLOCATE (pimage, Image, NPIMAGE);
+
+  for (Ntimage = 0; Ntimage < Nimage; Ntimage += ntimage) {
+    ntimage = Fread (timage, sizeof(Image), NTIMAGE, f, "image");
+    for (i = 0; i < ntimage; i++) {
+      addtolist = FALSE;
+      /* define image corners */
+      Xi[0] = 0;            Yi[0] = 0;
+      Xi[1] = timage[i].NX; Yi[1] = 0;
+      Xi[2] = timage[i].NX; Yi[2] = timage[i].NY;
+      Xi[3] = 0;            Yi[3] = timage[i].NY;
+      Xi[4] = 0;            Yi[4] = 0;  /* so we can make a loop easily */
+      /* transform to tcoords */
+      for (j = 0; j < 5; j++) {
+	XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+	RD_to_XY (&Xi[j], &Yi[j], r, d, &tcoords);
+      }
+      /* check if any edges cross */
+      for (j = 0; j < 4; j++) {
+	for (k = 0; k < 4; k++) {
+	  addtolist |= edge_check (&Xi[j], &Yi[j], &Xo[k], &Yo[k]);
+	}
+      }
+      
+      /*
+      fprintf (stderr, "%f %f %f %d %f %f %d %d %d %f %f %s: %d\n", 0.1*timage[i].detection_limit, 0.1*timage[i].saturation_limit, 0.02*timage[i].cerror, 
+	       timage[i].tzero, 1e-4*timage[i].trate, 
+	       0.001*timage[i].secz, timage[i].nstar, timage[i].NX, timage[i].NY, 0.001*timage[i].Mcal, 0.1*timage[i].Xm, timage[i].name, addtolist);
+      
+      fprintf (stderr, "%s\n", timage[i].coords.ctype);
+      fprintf (stderr, "%f %f\n", timage[i].coords.crval1, timage[i].coords.crval2);
+      fprintf (stderr, "%f %f\n", timage[i].coords.crpix1, timage[i].coords.crpix2);
+      fprintf (stderr, "%f %f\n", timage[i].coords.pc1_1, timage[i].coords.pc1_2);
+      fprintf (stderr, "%f %f\n", timage[i].coords.pc2_1, timage[i].coords.pc2_2);
+      fprintf (stderr, "%f %f\n", timage[i].coords.cdelt1, timage[i].coords.cdelt2);      
+      */
+
+      if (addtolist) {
+	pimage[npimage] = timage[i];
+	npimage ++;
+	if (npimage == NPIMAGE) {
+	  NPIMAGE += 20;
+	  REALLOCATE (pimage, Image, NPIMAGE);
+	}
+      }
+    }
+
+    if (ntimage == 0) {
+      fprintf (stderr, "ERROR: expected %d images, only found %d\n", Nimage, Ntimage);
+      clear_lockfile ();
+      exit (0);
+    }
+  }
+
+  if (VERBOSE) fprintf (stderr, "found %d overlapping images\n", npimage);
+
+  fclose (f);
+  *Npimage = npimage;
+  return (pimage);
+
+}
+  
+int edge_check (x1, y1, x2, y2)
+double *x1, *y1, *x2, *y2;
+{
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+double opening_angle (x1, y1, x2, y2, x3, y3)
+double x1, y1, x2, y2, x3, y3;
+{
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
+
+
+
+
+/* probably not needed now 
+char *_parse_nextword();
+
+
+int fparse (X, NX, line)
+float *X;
+int NX;
+char *line;
+{
+
+  int i;
+  char *word;
+  char *ptr;
+
+  word = line;
+  for (i = 0; i < NX - 1; i++)
+    word = _parse_nextword (word);
+
+  *X = strtod (word, &ptr);
+  if (ptr == word)
+    return (FALSE);
+  else {
+    if (word[0] == '-') 
+      return (-1);
+    else
+      return (1);
+  }
+}
+
+*/
Index: /tags/start/Ohana/src/markrock/src/old/gregions.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/gregions.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/gregions.c	(revision 12606)
@@ -0,0 +1,135 @@
+# include "markstar.h"
+
+GSCRegion *gregions1 (catstats, Nregions)
+CatStats catstats[];
+int *Nregions;
+{
+  
+  GSCRegion *region;
+  int i, j, k, x, y, done, nregion, nregion2, NREGION;
+  double ra, dec, dx, dy, Xo[4], Yo[4];
+  FILE *f;
+
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: could not open GSC region file %s\n", GSCFILE);
+    exit (0);
+  }
+  nregion = 0;
+  NREGION = 10;
+  ALLOCATE (region, GSCRegion, NREGION);
+
+  if (catstats[0].DEC[0] == 86.25) { /* pole region */
+    dec = 86.0;
+    for (ra = 0.1; ra < 370; ra+= 30.0) {
+      aregion (&region[nregion], f, ra, dec);
+      done = FALSE;
+      for (j = 0; (j < nregion - 1) && !done; j++) {
+	if (!strcmp (region[nregion].filename, region[j].filename)) {
+	  nregion --;
+	  done = TRUE;
+	}
+      }
+      nregion ++;
+      if (nregion == NREGION) {
+	NREGION += 10;
+	REALLOCATE (region, GSCRegion, NREGION);
+      }
+    }
+  } else {
+    for (x = 0; x < 2; x++) {
+      for (y = 0; y < 2; y++) {
+	for (dx = -0.1; dx <= 0.1; dx += 0.2) {
+	  for (dy = -0.1; dy <= 0.1; dy += 0.2) {
+	    ra  = catstats[0].RA[x] + dx;
+	    dec = catstats[0].DEC[y] + dy;
+	    aregion (&region[nregion], f, ra, dec);
+	    done = FALSE;
+	    for (j = 0; (j < nregion) && !done; j++) {
+	      if (!strcmp (region[nregion].filename, region[j].filename)) {
+		done = TRUE;
+	      }
+	    }
+	    if (!done) {
+	      nregion ++;
+	    } 
+	    if (nregion == NREGION) {
+	      NREGION += 10;
+	      REALLOCATE (region, GSCRegion, NREGION);
+	    }
+	  }
+	}
+      }
+    }
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "using %d regions\n", nregion);
+    for (i = 0; i < nregion; i++) {
+      fprintf (stderr, "region %d: %f %f  %f %f\n", i, region[i].RA[0], region[i].RA[1], region[i].DEC[0], region[i].DEC[1]);
+    } 
+  }
+
+  REALLOCATE (region, GSCRegion, MAX (nregion, 1));
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (region);
+  
+}
+
+GSCRegion *gregions2 (image, Nregions)
+Image *image;
+int *Nregions;
+{
+  
+  GSCRegion *region;
+  FILE *f;
+  double x, y;
+  double dr, dd, dec, ra;
+  int i, j, done, nregion, NREGION;
+  
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find GSC region file %s\n", GSCFILE);
+    clear_lockfile ();
+    exit (0);
+  }
+  
+  /* find regions at image corners */
+  NREGION = 10;
+  ALLOCATE (region, GSCRegion, NREGION);
+  nregion = 0;
+
+  /* look for new regions on grid across image */ 
+  for (x = 0.0; x <= 1.0; x+=0.25) {
+    for (y = 0.0; y <= 1.0; y+=0.25) {
+      XY_to_RD (&ra, &dec, image[0].NX*(1.1*x - 0.05), image[0].NY*(1.1*y - 0.05), &image[0].coords);
+      aregion (&region[nregion], f, ra, dec);
+      done = FALSE;
+      for (j = 0; (j < nregion) && !done; j++) {
+	if (!strcmp (region[nregion].filename, region[j].filename)) {
+	  nregion --;
+	  done = TRUE;
+	}
+      }
+      nregion ++;
+      if (nregion == NREGION) {
+	NREGION += 10;
+	REALLOCATE (region, GSCRegion, NREGION);
+      }
+    }
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "found %d region files:\n", nregion);
+    for (i = 0; i < nregion; i++) {
+      fprintf (stderr, "  %d %s\n", i, region[i].filename);
+    }
+  }
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (region);
+  
+}
Index: /tags/start/Ohana/src/markrock/src/old/gstars.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/gstars.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/gstars.c	(revision 12606)
@@ -0,0 +1,186 @@
+# include "addstar.h"
+# define D_NSTARS 1000
+# define BYTES_STAR 31
+# define BLOCK 1000
+#include <sys/time.h>
+#include <time.h>
+
+Stars *gstars (file, NSTARS, image) 
+char file[];
+int *NSTARS;
+Image *image;
+{
+
+  FILE *f;
+  Header header;
+  int i, j, nstar;
+  int nbytes, Nbytes;
+  Stars *stars;
+  char *buffer, line[64], *c;
+  struct tm timeptr;
+  double tmp;
+
+  if (!fits_read_header (file, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s\n", file);
+    clear_lockfile ();
+    exit(0);
+  }
+
+  /* open file */
+  f = fopen (file, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find data file %s\n", file);
+    clear_lockfile ();
+    exit(0);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  c = strrchr (file, 0x2f);
+  if (c == (char *) NULL) {
+    strcpy (image[0].name, file);
+  } else { 
+    strcpy (image[0].name, (c+1));
+  }
+  /* get astrometry information */
+  strcpy (image[0].coords.ctype, "NONE");
+  fits_scan (&header, "CTYPE1",   "%s",  1, image[0].coords.ctype);
+  if (strcmp (image[0].coords.ctype, "RA---PLY")) {
+    fprintf (stderr, "ERROR: wrong astrometric info in header\n");
+    clear_lockfile ();
+    exit (0);
+  }
+  fits_scan (&header, "CDELT1",   "%f", 1, &image[0].coords.cdelt1); 
+  fits_scan (&header, "CDELT2",   "%f", 1, &image[0].coords.cdelt2);
+  fits_scan (&header, "CRVAL1",   "%lf", 1, &image[0].coords.crval1);
+  fits_scan (&header, "CRVAL2",   "%lf", 1, &image[0].coords.crval2);  
+  fits_scan (&header, "CRPIX1",   "%f", 1, &image[0].coords.crpix1);
+  fits_scan (&header, "CRPIX2",   "%f", 1, &image[0].coords.crpix2);
+  fits_scan (&header, "PC001001", "%f", 1, &image[0].coords.pc1_1);
+  fits_scan (&header, "PC001002", "%f", 1, &image[0].coords.pc1_2);
+  fits_scan (&header, "PC002001", "%f", 1, &image[0].coords.pc2_1);
+  fits_scan (&header, "PC002002", "%f", 1, &image[0].coords.pc2_2);
+  fits_scan (&header, "CERROR",   "%lf", 1, &tmp);
+  /* RA Terms */
+  fits_scan (&header, "PCA1X2Y0", "%f", 1, &image[0].coords.polyterms[0][0]);
+  fits_scan (&header, "PCA1X1Y1", "%f", 1, &image[0].coords.polyterms[1][0]);
+  fits_scan (&header, "PCA1X0Y2", "%f", 1, &image[0].coords.polyterms[2][0]);
+  fits_scan (&header, "PCA1X3Y0", "%f", 1, &image[0].coords.polyterms[3][0]);
+  fits_scan (&header, "PCA1X2Y1", "%f", 1, &image[0].coords.polyterms[4][0]);
+  fits_scan (&header, "PCA1X1Y2", "%f", 1, &image[0].coords.polyterms[5][0]);
+  fits_scan (&header, "PCA1X0Y3", "%f", 1, &image[0].coords.polyterms[6][0]);
+  /* Dec Terms */
+  fits_scan (&header, "PCA2X2Y0", "%f", 1, &image[0].coords.polyterms[0][1]);
+  fits_scan (&header, "PCA2X1Y1", "%f", 1, &image[0].coords.polyterms[1][1]);
+  fits_scan (&header, "PCA2X0Y2", "%f", 1, &image[0].coords.polyterms[2][1]);
+  fits_scan (&header, "PCA2X3Y0", "%f", 1, &image[0].coords.polyterms[3][1]);
+  fits_scan (&header, "PCA2X2Y1", "%f", 1, &image[0].coords.polyterms[4][1]);
+  fits_scan (&header, "PCA2X1Y2", "%f", 1, &image[0].coords.polyterms[5][1]);
+  fits_scan (&header, "PCA2X0Y3", "%f", 1, &image[0].coords.polyterms[6][1]);
+  image[0].coords.Npolyterms = 2; /* how many do we use? */
+  /* CERROR in data file is in pixels, convert to 20*arcsec */
+  image[0].cerror = tmp * 50.0 * image[0].coords.cdelt1 * 3600.0;
+  while (image[0].coords.crval1 < 0) image[0].coords.crval1 += 360.0;
+  while (image[0].coords.crval1 > 360.0) image[0].coords.crval1 -= 360.0;
+ 
+  fits_scan (&header, "NAXIS1",   "%hd", 1, &image[0].NX); 
+  fits_scan (&header, "NAXIS2",   "%hd", 1, &image[0].NY);
+  fits_scan (&header, "PHOTCODE", "%hd", 1, &image[0].source);
+  image[0].NX -= XOVERSCAN;
+  image[0].NY -= YOVERSCAN;
+
+  tmp = 0;
+  fits_scan (&header, "FLIMIT",   "%lf", 1, &tmp);
+  image[0].detection_limit = tmp * 10.0;
+
+  tmp = 0;
+  fits_scan (&header, "FSATUR",   "%lf", 1, &tmp);
+  image[0].saturation_limit = tmp * 10.0;
+
+  if (!fits_scan (&header, "TZERO",   "%d",  1, &image[0].tzero)) {
+    fits_scan (&header, "UT",   "%s",  1, line);
+    /* remove : characters */
+    for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (c, 0x3a))
+      *c = ' ';
+    sscanf (line, "%d %d %d", &timeptr.tm_hour, &timeptr.tm_min, &timeptr.tm_sec);
+    fits_scan (&header, "DATE-UT",   "%s",  1, line);
+    for (c = strchr (line, 0x2f); c != (char *) NULL; c = strchr (c, 0x2f))
+      *c = ' ';
+    sscanf (line, "%d %d %d", &timeptr.tm_year, &timeptr.tm_mon, &timeptr.tm_mday);
+    if (timeptr.tm_year < 90) { /* correct for year 2000 turnover */
+      timeptr.tm_year += 100;
+    }
+    image[0].tzero = mktime (&timeptr);
+  }
+
+  tmp = 0;
+  fits_scan (&header, "TRATE",   "%lf", 1, &tmp);
+  image[0].trate = 10000 * tmp;
+
+  tmp = 0;
+  fits_scan (&header, "AIRMASS", "%lf", 1, &tmp);
+  image[0].secz = 1000*tmp;
+
+  /* secz is in units milli-airmass */
+  image[0].Mcal =  ALPHA*(image[0].secz - 1000);
+  image[0].Xm   = 30.0;
+  image[0].code = 0;
+  bzero (image[0].dummy, sizeof(image[0].dummy));
+
+  /* find number of stars */
+  fits_scan (&header, "NSTARS", "%d", 1, &image[0].nstar);
+  if (image[0].nstar == 0) {
+    fprintf (stderr, "ERROR: can't get NSTARS from header\n");
+    clear_lockfile ();
+    exit (0);
+  }
+  ALLOCATE (stars, Stars, image[0].nstar);
+  Nbytes = image[0].nstar*BYTES_STAR;
+
+  /* load in stars by blocks of 1000 */
+  nstar = 0;
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR));
+  for (i = 0; i < (int)(Nbytes / (BLOCK*BYTES_STAR)); i++) {
+    nbytes = Fread (buffer, 1, (BLOCK*BYTES_STAR), f, "char");
+    if (nbytes != BLOCK*BYTES_STAR) {
+      fprintf (stderr, "ERROR: failed to read in stars (1)\n");
+      clear_lockfile ();
+      exit (0);
+    }
+    for (j = 0; j < BLOCK; j++, nstar++) {
+      dparse (&stars[nstar].X,  1, &buffer[j*BYTES_STAR]);
+      dparse (&stars[nstar].Y,  2, &buffer[j*BYTES_STAR]);
+      dparse (&stars[nstar].M,  3, &buffer[j*BYTES_STAR]);
+      dparse (&stars[nstar].dM, 4, &buffer[j*BYTES_STAR]);
+      XY_to_RD (&stars[nstar].R, &stars[nstar].D, stars[nstar].X, stars[nstar].Y, &image[0].coords);
+      stars[nstar].found = -1;
+    }
+  }
+  /* left over fraction of a block */
+  nbytes = Fread (buffer, 1, (Nbytes % (BLOCK*BYTES_STAR)), f, "char");
+  if (nbytes != (Nbytes % (BLOCK*BYTES_STAR))) {
+    fprintf (stderr, "ERROR: failed to read in stars (2)\n");
+    clear_lockfile ();
+    exit (0);
+  }
+  for (j = 0; j < nbytes / BYTES_STAR; j++, nstar++) {
+    dparse (&stars[nstar].X, 1, &buffer[j*BYTES_STAR]);
+    dparse (&stars[nstar].Y, 2, &buffer[j*BYTES_STAR]);
+    dparse (&stars[nstar].M, 3, &buffer[j*BYTES_STAR]);
+    dparse (&stars[nstar].dM, 4, &buffer[j*BYTES_STAR]);
+    XY_to_RD (&stars[nstar].R, &stars[nstar].D, stars[nstar].X, stars[nstar].Y, &image[0].coords);
+    stars[nstar].found = -1;
+  }
+
+  if (image[0].nstar != nstar) {
+    fprintf (stderr, "ERROR: failed to read in all stars (%d != %d)\n", image[0].nstar, nstar);
+    clear_lockfile ();
+    exit (0);
+  }
+  free (header.buffer);
+  free (buffer);
+ 
+  if (VERBOSE) fprintf (stderr, "read %d stars from target file\n", image[0].nstar);
+  *NSTARS = image[0].nstar;
+
+  return (stars);
+}
Index: /tags/start/Ohana/src/markrock/src/old/load_gsc_data.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/load_gsc_data.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/load_gsc_data.c	(revision 12606)
@@ -0,0 +1,62 @@
+# include "markstar.h"
+# define NBYTES 160000
+# define BYTES_STAR 23
+# define BLOCK 1000
+# define DNSTARS 1000
+
+load_gsc_data (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  /* load data from the GSC files */
+  char filename[128];
+  char *tbuffer;
+  int nstar, NSTARS;
+  int i, j, Nbytes, nbytes, Nregions;
+  double R, D, M, MagLimit;
+  FILE *f;
+  GSCRegion *region, *gregions();
+  
+  region = gregions1 (catstats, &Nregions);
+
+  MagLimit = MAX (MAX (BRIGHT_HALO_MAG, BRIGHT_XTRAIL_MAG), BRIGHT_YTRAIL_MAG); 
+  nstar = 0;
+  NSTARS = DNSTARS;
+  ALLOCATE (tbuffer, char, (BLOCK*BYTES_STAR));
+  ALLOCATE (catalog[0].average, Average, NSTARS);
+  Nbytes = BLOCK*BYTES_STAR;
+  
+  for (j = 0; j < Nregions; j++) {
+    f = fopen (region[j].filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "no stars in %s, skipping\n", region[j].filename);
+      clear_lockfile ();
+      exit (0);
+    }
+    
+    while ((nbytes = fread (tbuffer, 1, Nbytes, f)) > 0) {
+      for (i = 0; i < nbytes / BYTES_STAR; i++) {
+	dparse (&M, 3, &tbuffer[i*BYTES_STAR]);
+	if (M > MagLimit) continue;
+	dparse (&R, 1, &tbuffer[i*BYTES_STAR]);
+	dparse (&D, 2, &tbuffer[i*BYTES_STAR]);
+	catalog[0].average[nstar].R = R;
+	catalog[0].average[nstar].D = D;
+	catalog[0].average[nstar].M = M * 1000.0;
+	nstar++;
+	if (nstar == NSTARS - 1) {
+	  NSTARS += DNSTARS;
+	  REALLOCATE (catalog[0].average, Average, NSTARS);
+	}
+      }
+    }
+    fclose (f);
+  }
+
+  free (tbuffer);
+  REALLOCATE (catalog[0].average, Average, nstar);
+  catalog[0].Naverage = nstar;
+  
+}
+
Index: /tags/start/Ohana/src/markrock/src/old/load_gsc_data_ghost.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/load_gsc_data_ghost.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/load_gsc_data_ghost.c	(revision 12606)
@@ -0,0 +1,75 @@
+# include "markstar.h"
+# define NBYTES 160000
+# define BYTES_STAR 23
+# define BLOCK 1000
+# define DNSTARS 1000
+
+/* this routine is basically identical to load_gsc_data, but
+   it is not limited to a single region file, and it merges the 
+   results */
+
+load_gsc_data_ghost (catalog, region, Nregion, image)
+Catalog catalog[];
+GSCRegion *region;
+int Nregion;
+Image image[];
+{
+
+  /* load data from the GSC files */
+  char filename[128];
+  char *tbuffer;
+  int nstar, NSTARS;
+  int i, j, Nbytes, nbytes;
+  double R, D, M, X, Y;
+  FILE *f;
+  Coords *tcoords;
+  int MinX, MinY, MaxX, MaxY;
+  
+  nstar = 0;
+  NSTARS = DNSTARS;
+  ALLOCATE (tbuffer, char, (BLOCK*BYTES_STAR));
+  ALLOCATE (catalog[0].average, Average, NSTARS);
+  tcoords = &image[0].coords;
+  MinX = 0;
+  MinY = 0;
+  MaxX = image[0].NX;
+  MaxY = image[0].NY;
+  
+  for (j = 0; j < Nregion; j++) {
+    
+    f = fopen (region[j].filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "no stars in %s, skipping\n", region[j].filename);
+      clear_lockfile ();
+      exit (0);
+    }
+    
+    Nbytes = BLOCK*BYTES_STAR;
+    while ((nbytes = fread (tbuffer, 1, Nbytes, f)) > 0) {
+      for (i = 0; i < nbytes / BYTES_STAR; i++) {
+	dparse (&M, 3, &tbuffer[i*BYTES_STAR]);
+	if (M > GHOST_MAG) continue;
+	dparse (&R, 1, &tbuffer[i*BYTES_STAR]);
+	dparse (&D, 2, &tbuffer[i*BYTES_STAR]);
+	RD_to_XY (&X, &Y, R, D, tcoords);
+	if ((X < MinX) || (X > MaxX) || (Y < MinY) || (Y > MaxY)) continue;
+	catalog[0].average[nstar].R = R;
+	catalog[0].average[nstar].D = D;
+	catalog[0].average[nstar].M = M * 1000.0;
+	nstar++;
+	if (nstar == NSTARS - 1) {
+	  NSTARS += DNSTARS;
+	  REALLOCATE (catalog[0].average, Average, NSTARS);
+	}
+      }
+    }
+
+  }
+
+  free (tbuffer);
+  REALLOCATE (catalog[0].average, Average, MAX (nstar, 1));
+  catalog[0].Naverage = nstar;
+
+}
+
+
Index: /tags/start/Ohana/src/markrock/src/old/mark_trail.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/mark_trail.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/mark_trail.c	(revision 12606)
@@ -0,0 +1,250 @@
+# include "markstar.h"
+int *make_common_list ();
+int *check_common_list ();
+
+mark_trail (catstats, mark, Nave, i, m, b, axis, catalog)
+     CatStats catstats[];
+     char *mark;
+     int i, Nave, axis;
+     double m, b;
+     Catalog catalog[];
+{
+
+  float *R, *D;
+  int j, k, jj, kk, N, NPTS, marked, start, end, Nm;
+  int *good, *seq, *N1;
+  double *dist, *dist2;
+  double d2, di, Di, dD, n, Dist, scale, norm;
+  double spacing;
+  int *list, Nlist;
+  int M, Nmeas, thisimage;
+
+  R = catstats[0].X;
+  D = catstats[0].Y;
+  N1 = catstats[0].N;
+  spacing = catstats[0].spacing;
+
+  NPTS = 200;
+  ALLOCATE (good, int, NPTS);
+  ALLOCATE (dist, double, NPTS);
+  ALLOCATE (dist2, double, NPTS);
+  ALLOCATE (seq, int, NPTS);
+
+  /* Find all points which lie near line */
+  /* save the entry number and distance along line */
+  N = 0;
+  scale = sqrt (1.0 + m*m);
+
+  if (axis == 1) {
+    for (j = 0; j < Nave; j++) {
+      norm = scale * fabs(R[j] - m*D[j] - b);
+      if (!mark[j] && (norm < TRAIL_WIDTH)) {
+	good[N] = j;
+	dist[N] = scale * (D[j] - D[i] + m*(R[j] - R[i]));
+	seq[N] = N;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 200;
+	  REALLOCATE (good, int, NPTS);
+	  REALLOCATE (dist, double, NPTS);
+	  REALLOCATE (dist2, double, NPTS);
+	  REALLOCATE (seq, int, NPTS);
+	}
+      }
+    }
+  } else {
+    for (j = 0; j < Nave; j++) {
+      norm = scale * fabs(D[j] - m*R[j] - b);
+      if (!mark[j] && (norm < TRAIL_WIDTH)) {
+	good[N] = j;
+	dist[N] = scale * (R[j] - R[i] + m*(D[j] - D[i]));
+	seq[N] = N;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 200;
+	  REALLOCATE (good, int, NPTS);
+	  REALLOCATE (dist, double, NPTS);
+	  REALLOCATE (dist2, double, NPTS);
+	  REALLOCATE (seq, int, NPTS);
+	}
+      }
+    }
+  }
+  
+  if (N < NPTSINLINE) 
+    return (0);
+
+  sort_seq (dist, seq, N);
+  
+  start = -1; end = -1;
+  for (j = 0; j < N-1; j++) {
+    /* if we have part of a line, and next point is in the line, check for common images */
+    if ((start != -1) && (fabs(dist[j] - dist[j+1]) < spacing)) {
+      list = check_common_list (list, N1[good[seq[j+1]]], &Nlist, catalog);
+      if (Nlist == 0) { /* if no common images, dump list and continue */
+	end = j + 1;
+	if (end - start > NPTSINLINE) {
+	  if (axis == 0)
+	    fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", m, b, N, end-start, start, end, dist[start], dist[end-1]);
+	  else
+	    fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", 1.0/m, -1.0*b/m, N, end-start, start, end, dist[start], dist[end-1]);
+	  for (k = start; k < end; k++) {
+	    M = N1[good[seq[k]]];
+	    mark[good[seq[k]]] = TRUE;
+	    /* we need to mark measurements from all images in common on the line */
+	    Nm = 0;
+	    for (jj = 0; jj < catalog[0].average[M].Nm; jj++) {
+	      Nmeas = catalog[0].average[M].offset + jj;
+	      thisimage = catalog[0].image[Nmeas];
+	      for (kk = 0; kk < Nlist; kk++) {
+		if (thisimage == list[kk]) {
+		  catalog[0].measure[Nmeas].average |= PART_OF_TRAIL;
+		  Nm ++;
+		}
+	      }
+	    }
+	    /* if there is only 1 measurement, mark object as bad */
+	    if (catalog[0].average[M].Nm == Nm) {
+	      catalog[0].average[M].code = ID_TRAIL;
+	    }
+	    catalog[0].average[M].code = ID_TRAIL;
+	  }
+	}
+	start = -1;
+	end = -1;
+      }
+    }
+    /* if we haven't yet found a line segment, check for the beginning */
+    if ((start < 0) && (fabs(dist[j] - dist[j+1]) < spacing)) {
+      start = j;
+      list = make_common_list (N1[good[seq[j]]], N1[good[seq[j+1]]], &Nlist, catalog);
+      if (Nlist == 0) { /* if no common images, move on */
+	start = -1;
+	free (list);
+      }
+    }
+    /* if we have a complete line, check for validity.  if it has enough members,
+	 mark them and continue searching for lines */
+    if ((start != -1) && ((fabs(dist[j] - dist[j+1]) >= spacing) || (j == N-2))) {
+      end = j + 1;
+      if (end - start > NPTSINLINE) {
+	if (axis == 0)
+	  fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", m, b, N, end-start, start, end, dist[start], dist[end-1]);
+	else
+	  fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", 1.0/m, -1.0*b/m, N, end-start, start, end, dist[start], dist[end-1]);
+	for (k = start; k < end; k++) {
+	  M = N1[good[seq[k]]];
+	  mark[good[seq[k]]] = TRUE;
+	  if (catalog[0].average[M].code == ID_BLEED) continue;
+	  /* we need to mark measurements from all images in common on the line */
+	  Nm = 0;
+	  for (jj = 0; jj < catalog[0].average[M].Nm; jj++) {
+	    Nmeas = catalog[0].average[M].offset + jj;
+	    thisimage = catalog[0].image[Nmeas];
+	    for (kk = 0; kk < Nlist; kk++) {
+	      if (thisimage == list[kk]) {
+		catalog[0].measure[Nmeas].average |= PART_OF_TRAIL;
+		Nm ++;
+	      }
+	    }
+	  }
+	  /* if there is only 1 measurement, mark object as bad */
+	  if (catalog[0].average[M].Nm == Nm) {
+	    catalog[0].average[M].code = ID_TRAIL;
+	  }
+	  catalog[0].average[M].code = ID_TRAIL;
+	}
+      }
+      free (list);
+      start = -1;
+      end = -1;
+    }
+  }
+}
+
+
+/* I is Average seq number for star 1, J for star 2 */
+int *make_common_list (I, J, Nlist, catalog)
+int I, J, *Nlist;
+Catalog catalog[];
+{
+
+  int i, j, N1, N2, nlist, NLIST;
+  int *list;
+
+  NLIST = 50;
+  ALLOCATE (list, int, NLIST);
+  nlist = 0;
+
+  for (i = 0; i < catalog[0].average[I].Nm; i++) {
+    N1 = catalog[0].average[I].offset + i;
+    if (catalog[0].image[N1] == -1)
+      continue; /* not a real measurement */
+    for (j = 0; j < catalog[0].average[J].Nm; j++) {
+      N2 = catalog[0].average[J].offset + j;
+      if (catalog[0].image[N2] == -1)
+	continue; /* not a real measurement */
+      if (catalog[0].image[N1] == catalog[0].image[N2]) {
+	list[nlist] = catalog[0].image[N1];
+	nlist ++;
+	if (nlist == NLIST - 1) {
+	  NLIST += 50;
+	  REALLOCATE (list, int, NLIST);
+	}
+      }
+    }
+  }
+  
+  REALLOCATE (list, int, MAX(nlist, 1));
+  *Nlist = nlist;
+  return (list);
+
+}
+
+
+
+/* J is Average seq number for star */
+int *check_common_list (inlist, J, Nlist, catalog)
+int *inlist, J, *Nlist;
+Catalog catalog[];
+{
+
+  int i, j, N2, Ninlist;
+  int *list, NLIST, nlist;
+
+  NLIST = 50;
+  ALLOCATE (list, int, NLIST);
+  nlist = 0;
+  Ninlist = *Nlist;
+
+  for (i = 0; i < Ninlist; i++) {
+    for (j = 0; j < catalog[0].average[J].Nm; j++) {
+      N2 = catalog[0].average[J].offset + j;
+      if (catalog[0].image[N2] == -1)
+	continue; /* not a real measurement */
+      if (inlist[i] == catalog[0].image[N2]) {
+	list[nlist] = inlist[i];
+	nlist ++;
+	if (nlist == NLIST - 1) {
+	  NLIST += 50;
+	  REALLOCATE (list, int, NLIST);
+	}
+      }
+    }
+  }
+  
+  /* if there are no common images, return the input list */
+  if (nlist != 0) {
+    free (inlist);
+    REALLOCATE (list, int, MAX(nlist, 1));
+    *Nlist = nlist;
+    return (list);
+  } else {
+    return (inlist);
+  }
+
+}
+
+
+/* measurements associated with image number -1 are not 
+   measurements we made, but are added, like USNO */
Index: /tags/start/Ohana/src/markrock/src/old/markstar.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/markstar.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/markstar.c	(revision 12606)
@@ -0,0 +1,60 @@
+# include "markstar.h"
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  FILE *f;
+  int i, Nstars, Nimage, Nregions, Nmissed;
+  Image *image, *find_images();
+  Catalog catalog;
+  CatStats catstats;
+  struct timeval now, then;  
+  
+  gettimeofday (&then, (void *) NULL);
+  ConfigInit (argc, argv);
+
+  VERBOSE = FALSE;
+  if ((i = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  RESET = FALSE;
+  if ((i = get_argument (argc, argv, "-reset"))) {
+    RESET = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  if (argc < 2) {
+    fprintf (stderr, "ERROR: Usage: markstar (catalog)\n");
+    exit (0);
+  }
+
+  /* if lockfile exists, program will complain and quit */
+  check_lockfile (); 
+
+  gcatalog (argv[1], &catalog);
+
+  gcatstats (&catalog, &catstats);
+
+  image = find_images (&catstats, &Nimage);
+
+  match_images (&catalog, image, Nimage);
+    
+  find_bright_stars (&catalog, &catstats); 
+
+  find_ghosts (&catalog, &catstats, argv[1], image, Nimage);  
+
+  find_trails (&catalog, &catstats);  
+
+  wcatalog (argv[1], &catalog);
+
+  if (VERBOSE) {
+    gettimeofday (&now, (void *) NULL);
+    fprintf (stderr, "%s: elapsed time = %.2f sec\n", argv[1], 
+	     (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec));
+  }
+  clear_lockfile (); 
+  fprintf (stderr, "SUCCESS\n");
+}
+
Index: /tags/start/Ohana/src/markrock/src/old/match_images.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/match_images.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/match_images.c	(revision 12606)
@@ -0,0 +1,58 @@
+# include "markstar.h"
+
+match_images (catalog, image, Nimage)
+Catalog catalog[];
+Image   image[];
+int Nimage;
+{
+  
+  int j, k, found;
+  unsigned int *start, *stop;
+
+  /* this must be allocated so future free will not fail */
+  ALLOCATE (catalog[0].image, int, MAX (catalog[0].Nmeasure, 1));
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (FALSE);
+  }
+
+  ALLOCATE (start, unsigned int, Nimage);
+  ALLOCATE (stop,  unsigned int, Nimage);
+  for (j = 0; j < Nimage; j++) {
+    start[j] = image[j].tzero - MAX(0.05*image[j].trate*image[j].NY, 1);
+    stop[j]  = image[j].tzero + MAX(1.05*image[j].trate*image[j].NY, 1);
+  }
+
+  for (j = 0; j < catalog[0].Nmeasure; j++) {
+    found = FALSE;
+    if (catalog[0].measure[j].t == 0) {
+      catalog[0].image[j] = -1;
+      found = TRUE;
+    }
+    for (k = 0; (k < Nimage) && !found; k++) {
+      if ((catalog[0].measure[j].t >= start[k]) && 
+	  (catalog[0].measure[j].t <= stop[k])) {
+	catalog[0].image[j] = k;
+	found = TRUE;
+      }
+    }
+    if (!found) {
+      fprintf (stderr, "ERROR: can't find source image for this measurement: %d\n",
+	       catalog[0].measure[j].t);
+      clear_lockfile ();
+      exit (0);
+    }
+  }
+  free (start);
+  free (stop);
+}
+
+  /* this routine uses the time of each measurement to match the
+measurement with an image.  Since the measurement is only store to 1
+sec accuracy, which corresponds to roughly 30 rows at nominal speed,
+we can't tell exactly which image the star come from.  However, this
+doesn't matter, and in fact this helps a bit: a measurement from the
+top of one image is the same as from the bottom of the next.
+Therefore, we intentionally blur the edges of the images by 5%, which
+will help to tie together neighboring images... */
+
Index: /tags/start/Ohana/src/markrock/src/old/photometry.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/photometry.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/photometry.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include "markrock.h"
+
+double PhotRel (Measure *measure, PhotCodeData *photcodes, double ZP) {
+
+  int Np;
+  double Mrel, Klam;
+
+  Np = photcodes[0].hashcode[measure[0].source];
+
+  if (photcodes[0].code[Np].type == PHOT_REF) {
+    Mrel = 0.001 * measure[0].M;
+    return (Mrel);
+  }
+
+  Klam = photcodes[0].code[Np].K;
+  
+  Mrel = 0.001*(measure[0].M + Klam*(measure[0].airmass - 1000) + photcodes[0].code[Np].C - measure[0].Mcal) - ZP;
+	  
+  return (Mrel);
+
+}
+
+double PhotInst (Measure *measure, PhotCodeData *photcodes, double ZP) {
+
+  int Np;
+  double M, Klam;
+
+  Np = photcodes[0].hashcode[measure[0].source];
+
+  if (photcodes[0].code[Np].type == PHOT_REF) {
+    M = 0.001 * measure[0].M;
+    return (M);
+  }
+
+  M = 0.001*(measure[0].M - measure[0].dt);
+	  
+  return (M);
+
+}
+
+double PhotAbs (Measure *measure, PhotCodeData *photcodes, double ZP) {
+
+  int Np;
+  double Mabs, Klam;
+
+  Np = photcodes[0].hashcode[measure[0].source];
+
+  if (photcodes[0].code[Np].type == PHOT_REF) {
+    Mabs = 0.001 * measure[0].M;
+    return (Mabs);
+  }
+
+  Klam = photcodes[0].code[Np].K;
+  
+  /* Mabs = 0.001*(measure[0].M + Klam*(measure[0].airmass - 1000) + photcodes[0].code[Np].C) - ZP; */
+
+  Mabs = 0.001*(measure[0].M + Klam*(measure[0].airmass - 1000) + photcodes[0].code[Np].C) - ZP;
+  
+  return (Mabs);
+	  
+}
Index: /tags/start/Ohana/src/markrock/src/old/sort_lists.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/sort_lists.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/sort_lists.c	(revision 12606)
@@ -0,0 +1,48 @@
+
+sort_lists (X, Y, S, N) 
+float *X, *Y;
+int *S, N;
+{
+  int l,j,ir,i;
+  double tX, tY, tS;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    S[i] = tS;
+  }
+}
Index: /tags/start/Ohana/src/markrock/src/old/sort_stars.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/sort_stars.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/sort_stars.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include "relphot.h"
+
+void sort_stars (radec, stars, Nstars)
+int  **radec;
+Star  *stars;
+int    Nstars;
+{
+  
+  int i;
+  double *RAs;
+
+  ALLOCATE (radec[0], int, Nstars);
+  ALLOCATE (RAs, double, Nstars);
+  for (i = 0; i < Nstars; i++) {
+    radec[0][i] = i;
+    RAs[i] = stars[i].RA;
+  }
+
+  sort_seq (radec[0], RAs, Nstars);
+  free (RAs);
+
+}
+
+
+void sort_seq (seq, value, N) 
+int *seq;
+double *value;
+int N;
+{
+  int l,j,ir,i;
+  int temp;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      temp = seq[--l];
+    }
+    else {
+      temp = seq[ir];
+      seq[ir] = seq[0];
+      if (--ir == 0) {
+	seq[0] = temp;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && value[seq[j]] < value[seq[j+1]]) ++j;
+      if (value[temp] < value[seq[j]]) {
+	seq[i]=seq[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    seq[i] = temp;
+  }
+}
+
+
Index: /tags/start/Ohana/src/markrock/src/old/string.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/string.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/string.c	(revision 12606)
@@ -0,0 +1,64 @@
+# include <stdio.h>
+# include <math.h>
+# define TRUE  1
+# define FALSE 0
+
+int scan_line (f, line) 
+FILE *f;
+char line[];
+{
+
+  int i, status;
+  char c;
+  
+  status = EOF + 1;
+  
+  for (i = 0, c = 0; (c != '\n') && (status != EOF); i++) {
+    status = fscanf (f, "%c", &c);
+    line[i] = c;
+  }
+  line[i - 1] = 0;  /* this could make things crash! */
+
+  if (i > 1) {
+    status = EOF + 1;
+  }
+
+  return (status);
+
+}
+
+char *_parse_nextword(string)
+char *string;
+{
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (; isspace (*string); string++);
+  for (; (*string != 0) && !isspace (*string); string++);
+  for (; isspace (*string); string++);
+  return (string);
+}
+
+int dparse (X, NX, line)
+double *X;
+int NX;
+char *line;
+{
+
+  int i;
+  char *word;
+  char *ptr;
+
+  word = line;
+  for (i = 0; i < NX - 1; i++)
+    word = _parse_nextword (word);
+
+  *X = strtod (word, &ptr);
+  if (ptr == word)
+    return (FALSE);
+  else {
+    if (word[0] == '-') 
+      return (-1);
+    else
+      return (1);
+  }
+}
Index: /tags/start/Ohana/src/markrock/src/old/wimage.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/old/wimage.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/old/wimage.c	(revision 12606)
@@ -0,0 +1,67 @@
+# include "addstar.h"
+
+wimage (filename, image, Nstars)
+char *filename;
+Image image[];
+int Nstars;
+{
+  
+  int Nimages, status;
+  FILE *f;
+  Header header;
+
+  if (!fits_read_header (ImageCat, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't find %s, creating a new one\n", ImageCat);
+    if (!fits_read_header (ImageTemplate, &header)) {
+      fprintf (stderr, "ERROR: can't find template header %s\n", ImageTemplate);
+      clear_lockfile ();
+      exit (0);
+    }
+    f = fopen (ImageCat, "w");
+    if (f == NULL) {
+      fprintf (stderr, "ERROR: can't create/open image catalog file: %s\n", ImageCat);
+      clear_lockfile ();
+      exit (0);
+    }
+  }
+  
+  Nimages = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimages);
+  Nimages ++;
+  fits_modify (&header, "NIMAGES", "%d", 1, Nimages);
+
+  f = fopen (ImageCat, "r+");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't create/open image catalog file: %s\n", ImageCat);
+    clear_lockfile ();
+    exit (0);
+  }
+
+  /* position to begining of file to write header */
+  fseek (f, 0, SEEK_SET);
+  status = Fwrite (header.buffer, 1, header.size, f, "char");
+  if (status != header.size) {
+    fprintf (stderr, "ERRPR: failed writing data to image header\n");
+    clear_lockfile ();
+    exit (0);
+  }
+
+  fseek (f, 0, SEEK_END);
+  fprintf (stderr, "Image: %d\n", sizeof(Image));
+  status = Fwrite (image, sizeof(Image), 1, f, "image");
+  if (status != 1) {
+    fprintf (stderr, "ERRPR: failed writing data to image catalog\n");
+    clear_lockfile ();
+    exit (0);
+  }
+
+  fclose (f);
+  
+
+}
+
+/* the image we add in this routine is always a new image.  
+   We only need to do two things:
+     1) append the data for the image to the end of the file
+     2) update the NIMAGES field in the header (which means, read in header, re-write)
+ */
Index: /tags/start/Ohana/src/markrock/src/sorts.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/sorts.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/sorts.c	(revision 12606)
@@ -0,0 +1,231 @@
+
+sort_set (X, Y, T, S, N) 
+float *X, *Y;
+int *S, N;
+int *T;
+{
+  int l,j,ir,i;
+  unsigned int tT;
+  double tX, tY, tS;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tT = T[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tT = T[ir];
+      T[ir] = T[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	T[0] = tT;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	T[i] = T[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    T[i] = tT;
+    S[i] = tS;
+  }
+}
+
+
+sort_lists (X, Y, S, N) 
+float *X, *Y;
+int *S, N;
+{
+  int l,j,ir,i;
+  double tX, tY, tS;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    S[i] = tS;
+  }
+}
+
+sort_entries (X, Y, N) 
+     double *X, *Y;
+     int N;
+{
+  int l,j,ir,i;
+  double tX, tY;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+  }
+}
+
+
+
+sort (X, N) 
+     double *X;
+     int N;
+{
+  int l,j,ir,i;
+  double tX;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+  }
+}
+
+
+sort_seq (X, S, N) 
+     double *X;
+     int *S;
+     int N;
+{
+  int l,j,ir,i;
+  int tS;
+  double tX;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    S[i] = tS;
+  }
+}
+
Index: /tags/start/Ohana/src/markrock/src/wcatalog.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/wcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/wcatalog.c	(revision 12606)
@@ -0,0 +1,41 @@
+# include "markrock.h"
+
+wcatalog (Catalog *catalog) {
+  
+  int status;
+  char filename[256];
+
+  fits_modify (&catalog[0].header, "MARKROCK", "%t", 1, TRUE);
+
+  save_catalog (catalog, VERBOSE);
+
+  if (catalog[0].Naverage) {
+    free (catalog[0].average); 
+    catalog[0].Naverage = 0;
+  }
+  if (catalog[0].Nmeasure) {
+    free (catalog[0].measure); 
+    catalog[0].Nmeasure = 0;
+  }
+  if (catalog[0].Nmissing) {
+    free (catalog[0].missing); 
+    catalog[0].Nmissing = 0;
+  }
+  if (catalog[0].Nsecfilt) {
+    free (catalog[0].secfilt); 
+    catalog[0].Nsecfilt = 0;
+  }
+
+  switch (status) {
+  case 0:
+    fprintf (stderr, "error saving catalog\n");
+    exit (0);
+  case 1:
+  case 2:
+    return (status);
+  default:
+    fprintf (stderr, "unknown exit status for save_catalog\n");
+    return (FALSE);
+  }
+}
+
Index: /tags/start/Ohana/src/markrock/src/wrocks.c
===================================================================
--- /tags/start/Ohana/src/markrock/src/wrocks.c	(revision 12606)
+++ /tags/start/Ohana/src/markrock/src/wrocks.c	(revision 12606)
@@ -0,0 +1,71 @@
+# include "markrock.h"
+
+wrocks (Rocks *rocks, int Nrocks) {
+  
+  int i, j;
+  FILE *f;
+  double X, Y, t, dSx, dSy, dS, speed;
+  double Sx, Sy, Sxt, Syt, St, St2, Sn;
+  double Mx, Bx, My, By, D;
+  unsigned int Tref;
+
+  f = fopen (RockCat, "a+");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't create/open rock catalog file: %s\n", RockCat);
+    exit (0);
+  }
+  /* position to begining of file to write header */
+  fseek (f, 0, SEEK_END);
+
+  /* get statistics on rocks */
+
+  for (i = 0; i< Nrocks; i++) {
+    /* fit a line to the three points, the ask for the scatter about the solution */
+    Tref = rocks[i].t[0];
+    Sx = Sy = Sxt = Syt = St = St2 = Sn = 0;
+    for (j = 0; j < 3; j++) {
+      X = rocks[i].X[j];
+      Y = rocks[i].Y[j];
+      if (rocks[i].t[j] > Tref) 
+	t = rocks[i].t[j] - Tref;
+      else
+	t = -1*((double)(Tref - rocks[i].t[j]));
+      Sx  += X;
+      Sy  += Y;
+      Sxt += X*t;
+      Syt += Y*t;
+      St  += t;
+      St2 += t*t;
+      Sn  += 1;
+    }
+    D = St2*Sn - St*St;
+    My = (Syt*Sn - Sy*St) / D;
+    By = (Sy*St2 - Syt*St) / D;
+    Mx = (Sxt*Sn - Sx*St) / D;
+    Bx = (Sx*St2 - Sxt*St) / D;
+    
+    dS = 0;
+    for (j = 0; j < 3; j++) {
+      X = rocks[i].X[j];
+      Y = rocks[i].Y[j];
+      if (rocks[i].t[j] > Tref) 
+	t = rocks[i].t[j] - Tref;
+      else 
+	t = -1*((double)(Tref - rocks[i].t[j]));
+      dSx = (Mx*t + Bx - X);
+      dSy = (My*t + By - Y);
+      dS += dSx*dSx + dSy*dSy;
+    }
+    dS = sqrt (dS/3);
+    speed = hypot (Mx, My);
+    fprintf (f, "%5.2f %9.4e ", dS, speed);
+    for (j = 0; j < 3; j++) {
+      fprintf (f, "%10d %10.6f %10.6f %6.3f ", rocks[i].t[j], rocks[i].ra[j], rocks[i].dec[j], rocks[i].mag[j]);
+    }
+    /* fprintf (f, "%3d %3d %3d\n", rocks[i].N[0], rocks[i].N[1], rocks[i].N[2]); */
+    fprintf (f, "\n");
+  }
+  fclose (f);
+  
+
+}
Index: /tags/start/Ohana/src/markstar/Makefile
===================================================================
--- /tags/start/Ohana/src/markstar/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/markstar/Makefile	(revision 12606)
@@ -0,0 +1,66 @@
+include ../../Configure
+HOME 	=	$(ROOT)/src/markstar
+CONFIG  =	$(ROOT)/config
+PROGRAM =       markstar
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#  
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lFITS -lohana -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS)
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+MARKSTAR = \
+$(SRC)/markstar.$(ARCH).o 	$(SRC)/gcatalog.$(ARCH).o   \
+$(SRC)/coordops.$(ARCH).o	$(SRC)/sorts.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o 	\
+$(SRC)/check_lockfile.$(ARCH).o \
+$(SRC)/find_trails.$(ARCH).o	$(SRC)/find_group.$(ARCH).o \
+$(SRC)/find_line.$(ARCH).o	$(SRC)/mark_trail.$(ARCH).o \
+$(SRC)/load_gsc_data.$(ARCH).o	$(SRC)/find_bright_stars.$(ARCH).o \
+$(SRC)/wcatalog.$(ARCH).o	$(SRC)/find_images.$(ARCH).o	\
+$(SRC)/load_gsc_data_ghost.$(ARCH).o	$(SRC)/find_ghosts.$(ARCH).o \
+$(SRC)/gcatstats.$(ARCH).o	$(SRC)/match_images.$(ARCH).o	\
+$(SRC)/gregions.$(ARCH).o	$(SRC)/aregion.$(ARCH).o	\
+$(SRC)/find_matches.$(ARCH).o	$(SRC)/check_permissions.$(ARCH).o
+
+
+OBJ = $(MARKSTAR)
+
+default: $(PROGRAM)
+
+$(MARKSTAR): $(INC)/markstar.h
+
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:	
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
+
+
Index: /tags/start/Ohana/src/markstar/doc/example.txt
===================================================================
--- /tags/start/Ohana/src/markstar/doc/example.txt	(revision 12606)
+++ /tags/start/Ohana/src/markstar/doc/example.txt	(revision 12606)
@@ -0,0 +1,13 @@
+
+rats: foreach f ( */*.cpt )
+foreach? echo $f
+foreach? echo $f >> bright.log
+foreach? (markstar -v $f >> bright.dat) >>& bright.log
+foreach? end
+
+
+
+ echo $f
+ echo $f >> bright.log
+ (markstar -v $f >> bright.dat) >>& bright.log
+ end
Index: /tags/start/Ohana/src/markstar/doc/process.txt
===================================================================
--- /tags/start/Ohana/src/markstar/doc/process.txt	(revision 12606)
+++ /tags/start/Ohana/src/markstar/doc/process.txt	(revision 12606)
@@ -0,0 +1,69 @@
+
+hi chad,
+
+the process i use is a bit complex, but makes some reasonable
+comprimises about distance between points in a line and processing
+time.  
+
+First, the process I am about to describe is run on every "star" in
+the image.  However, the whole process gets speeded up in part because
+entries which are known stars can be ignored and entries which are
+already identified as part of a line associated with an earlier entry
+get ignored as well.  In fact, this step is done for a new part of the
+sky before the USNO stars are identified without much reduction in the
+processing speed, so the fact that you don't identify fixed stars in
+your data should not really be an issue.
+
+In the following, I use the term "star" to mean any detected object
+in the image frame.
+
+So, let me now discuss the process for a given test star, call it
+S(0).  
+
+The first step is to find likely directions with trails.  I first look
+at all other stars within a specific radius (say 100") around that
+star, call them S(i).  For each star S(i), I find the angle between
+S(i) and S(0).  I accumulate a histogram of these angles, a bin size
+of say a degree. (Note, both the Radius and the BinSize should be
+parameters that might change depending on the density of stars).  If
+any of the angle bins have a significant number of entries, then this
+is the likely direction of a trail.  There are three things to note
+about this process.  First, it makes processing the lists much quicker
+if you have the stars sorted by X or Y (or RA or DEC) and use that
+information in your search for the stars within 100".  Second, I
+define a significance cutoff for an angle bin based on the density of
+stars in the field (this is a useful parameter for all of the
+comparisons I discuss).  Once any of the angle bins surpasses the
+significance criterion, I stop searching around this test star and
+just work on the identified angle.  I assume that if the test star
+just happens to lie at the intersection of two lines, the other line
+will be identified by another test star.  Finally, the angle histogram
+only needs to run from 0 to 180, and angles in the range 180 to 360
+should be reflected back into the first half to increase the number
+statistics.  In general, your test star will be somewhere in the
+middle of a line.
+
+Once an angle of interest is found, I fit a line to all of the points
+in that angle bin, then narrow down improve the fit by refitting to
+all points within a fixed distance of the line.  You can itereate on
+the second step if the line is not well determined the first time
+around.  One point of interest:  for the line fits, if the angle of
+the line is 0 - 45 deg, I fit the line Y = mX + b, but if the angle is
+45 - 90 deg, I fit the line X = mY + b, to keep the slope near 1.  
+
+Once I have a good fit to a line, I try to decide if the line is
+really a trail or if it is just a coincidence of points.  I demand 
+both a minimum linear density of points in the line (related to the
+density of stars in the frame) and a minimum number of points in the
+line.  Another thing to watch out for is including points well beyond
+the end of the line which just happen to lie along the line.  I demand
+that the distance between points be less than some distance related to
+the linear density.  
+
+I hope this is a helpful description.  The routine I run is quite
+quick.  It takes about 10 seconds for a 1 degree region (about 10,000
+real stars) to do the line search, the bright star wings, and the
+search for ghosts on a 300 MHz Pentium II.  
+
+good luck
+gene
Index: /tags/start/Ohana/src/markstar/include/markstar.h
===================================================================
--- /tags/start/Ohana/src/markstar/include/markstar.h	(revision 12606)
+++ /tags/start/Ohana/src/markstar/include/markstar.h	(revision 12606)
@@ -0,0 +1,43 @@
+# include <ohana.h>
+# include <loneos.h>
+
+int    VERBOSE;
+int    RESET;
+int    FORCE_RUN;
+
+/* global variables set in parameter file */
+char   CATDIR[256];
+char   GSCDIR[256];
+char   ImageCat[256];
+char   GSCFILE[256];
+
+double RADIUS;
+double TRAIL_WIDTH;
+int    NBINS;
+int    NPTSINLINE;
+double MIN_DENSITY;
+double NSIGMA;
+
+double BRIGHT_HALO_MAG;
+double BRIGHT_HALO_SLOPE;
+double BRIGHT_XTRAIL_WIDTH;
+double BRIGHT_XTRAIL_MAG;
+double BRIGHT_XTRAIL_SLOPE;
+double BRIGHT_YTRAIL_WIDTH;
+double BRIGHT_YTRAIL_MAG;
+double BRIGHT_YTRAIL_SLOPE;
+
+double GHOST_MAG;
+double GHOST_RADIUS;
+double OPTICAL_AXIS1;
+double OPTICAL_AXIS2;
+
+typedef struct {
+  Coords coords;
+  float *X, *Y;
+  int *N;
+  double RA[2], DEC[2];
+  double Area, density, spacing;
+} CatStats;
+
+PhotCodeData photcodes;
Index: /tags/start/Ohana/src/markstar/src/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/ConfigInit.c	(revision 12606)
@@ -0,0 +1,53 @@
+# include "markstar.h"
+
+ConfigInit (int *argc, char **argv) {
+
+  char *config, *file;
+  char PhotCodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  /* used in other pipeline functions */
+  ScanConfig (config, "IMAGE_CATALOG",   "%s",  0, ImageCat);
+  ScanConfig (config, "CATDIR",          "%s",  0, CATDIR);
+  ScanConfig (config, "GSCDIR",          "%s",  0, GSCDIR);
+  ScanConfig (config, "GSCFILE",         "%s",  0, GSCFILE);
+  /* unique to markstar */
+  ScanConfig (config, "SEARCH_RADIUS",   "%lf", 0, &RADIUS);
+  ScanConfig (config, "TRAIL_WIDTH",     "%lf", 0, &TRAIL_WIDTH);
+  ScanConfig (config, "NANGLE_BINS",     "%d",  0, &NBINS);
+  ScanConfig (config, "NPTSINLINE",      "%d",  0, &NPTSINLINE);
+  ScanConfig (config, "MIN_DENSITY",     "%lf", 0, &MIN_DENSITY);
+  ScanConfig (config, "SPACE_SIGMA",     "%lf", 0, &NSIGMA); 
+
+  ScanConfig (config, "BRIGHT_HALO_MAG",     "%lf", 0, &BRIGHT_HALO_MAG);
+  ScanConfig (config, "BRIGHT_HALO_SLOPE",   "%lf", 0, &BRIGHT_HALO_SLOPE);
+  ScanConfig (config, "BRIGHT_XTRAIL_WIDTH", "%lf", 0, &BRIGHT_XTRAIL_WIDTH);
+  ScanConfig (config, "BRIGHT_XTRAIL_MAG",   "%lf", 0, &BRIGHT_XTRAIL_MAG);
+  ScanConfig (config, "BRIGHT_XTRAIL_SLOPE", "%lf", 0, &BRIGHT_XTRAIL_SLOPE);
+  ScanConfig (config, "BRIGHT_YTRAIL_WIDTH", "%lf", 0, &BRIGHT_YTRAIL_WIDTH);
+  ScanConfig (config, "BRIGHT_YTRAIL_MAG",   "%lf", 0, &BRIGHT_YTRAIL_MAG);
+  ScanConfig (config, "BRIGHT_YTRAIL_SLOPE", "%lf", 0, &BRIGHT_YTRAIL_SLOPE);
+
+  ScanConfig (config, "GHOST_MAG",       "%lf", 0, &GHOST_MAG);
+  ScanConfig (config, "GHOST_RADIUS",    "%lf", 0, &GHOST_RADIUS);
+  ScanConfig (config, "OPTICAL_AXIS1",   "%lf", 0, &OPTICAL_AXIS1);
+  ScanConfig (config, "OPTICAL_AXIS2",   "%lf", 0, &OPTICAL_AXIS2);
+  ScanConfig (config, "PHOTCODE_FILE",          "%s", 0, PhotCodeFile);
+ 
+  if (!LoadPhotcodes (PhotCodeFile, &photcodes)) {
+    fprintf (stderr, "error loading photcodes\n");
+    exit (0);
+  }
+
+  free (config);
+  free (file);
+}
Index: /tags/start/Ohana/src/markstar/src/aregion.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/aregion.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/aregion.c	(revision 12606)
@@ -0,0 +1,186 @@
+# include "markstar.h"
+
+double BigDecBounds[] = {0.0, 7.5, 15.0, 22.5, 30.0, 37.5, 45.0, 
+			 52.5, 60.0, 67.5, 75.0, 82.5, 90.0,
+			 0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, 
+			 -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+char *DecSections[] = {"N0000", "N0730", "N1500", "N2230", "N3000", "N3730", "N4500", 
+		       "N5230", "N6000", "N6730", "N7500", "N8230", "weirdness", 
+		       "S0000", "S0730", "S1500", "S2230", "S3000", "S3730", "S4500", 
+		       "S5230", "S6000", "S6730", "S7500", "S8230", "weirdness"};
+
+char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			"n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			"s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			"s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+char *disk[] = {"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", 
+		"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "weirdness", 
+		"disk 1", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", 
+		"disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "weirdness"};
+
+int NBigRASections [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3, 48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3};
+
+int NDecLines[] = {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 24, 
+                   0, 597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48};
+
+/* find region file which contains ra, dec */
+aregion (region, f, ra, dec) 
+GSCRegion region[];
+FILE *f;
+double ra, dec;
+{
+  
+  
+  char buffer[28800], temp[50], file[50];
+  double dr, dd;
+  double RA0, RA1, DEC0, DEC1;
+  int i, NBigDec, NLINES, done, nregion;
+  
+  while (ra < 0) { ra += 360.0; }
+  while (ra >= 360.0) { ra -= 360.0; }
+    
+  if (dec >= 86.25) {
+    sprintf (file, "%s/n8230/pole.cpt\0", GSCDIR);
+    region[0].DEC[0] = 86.25;
+    region[0].DEC[1] = 93.75;
+    region[0].RA[0] = -180.0;
+    region[0].RA[1] =  540.0;
+    strcpy (region[0].filename, file);
+    return;
+  }
+    
+  NBigDec = -1;
+  for (i = 0; i < 12; i++) {
+# ifdef DEBUG
+    fprintf (stderr, "%d %f %f %f\n", i, dec, BigDecBounds[i], BigDecBounds[i+1]);
+# endif
+    if ((dec >= BigDecBounds[i]) && (dec < BigDecBounds[i+1])) {
+      NBigDec = i;
+      break;
+    }
+  }
+  if (NBigDec < 0) {
+    for (i = 13; i < 24; i++) {
+# ifdef DEBUG
+      fprintf (stderr, "%d %f %f %f\n", i, dec, BigDecBounds[i], BigDecBounds[i+1]);
+# endif
+      if ((dec < BigDecBounds[i]) && (dec >= BigDecBounds[i+1])) {
+	NBigDec = i;
+	break;
+      }
+    }
+  }
+  if (NBigDec < 0) {
+    fprintf (stderr, "dec out of range: %f\n", dec);
+  }
+    
+  NLINES = 0;
+  for (i = 0; i < NBigDec; i++) {
+    NLINES += NDecLines[i];
+  }
+  fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+      
+  done = FALSE;
+  Fread (buffer, 1, 48*NDecLines[NBigDec], f, "char");
+  for (i = 0; !done && (i < NDecLines[NBigDec]); i++) {
+    strncpy (temp, &buffer[i*48], 48);
+    temp[49] = 0;
+    hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+    if (RA1 < RA0) RA1 += 360.0;
+# ifdef DEBUG
+    fprintf (stderr, "%f %f %f  %f %f %f  %s\n", DEC0, dec, DEC1, RA0, ra, RA1, temp);
+# endif
+    if ((dec >= 0) && (dec >= DEC0) && (dec < DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+    if ((dec < 0) && (dec < DEC0) && (dec >= DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+  }
+  if (!done) {
+    fprintf (stderr, "error in search: %f %f\n", ra, dec);
+    exit (0);
+  }
+  temp[5] = 0;
+  sprintf (file, "%s/%s/%s.cpt\0", GSCDIR, Dec2Sections[NBigDec],&temp[1]);
+  if (DEC0 < DEC1) {
+    region[0].DEC[0] = DEC0;
+    region[0].DEC[1] = DEC1;
+  } else {
+    region[0].DEC[0] = DEC1;
+    region[0].DEC[1] = DEC0;
+  }     
+  region[0].RA[0] = RA0;
+  region[0].RA[1] = RA1;
+  strcpy (region[0].filename, file);
+  return;
+}
+
+
+/**********/
+int hms_to_deg (h0, h1, d0, d1, string) 
+     char *string;
+     double *h0, *h1, *d0, *d1;
+{
+  
+  int flag_d0, flag_d1, flag_h0, flag_h1;
+  double tmp;
+  
+  *d0 = *h0 = *d1 = *h1 = 0;
+
+  flag_h0 = dparse (h0, 1, string);
+  flag_h1 = dparse (h1, 4, string);
+  flag_d0 = dparse (d0, 7, string);
+  flag_d1 = dparse (d1, 9, string);
+  *h0 *= flag_h0;
+  *h1 *= flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  dparse (&tmp, 2, string);
+  *h0 += tmp/60.0;
+  dparse (&tmp, 3, string);
+  *h0 += tmp/3600.0;
+  
+  dparse (&tmp, 5, string);
+  *h1 += tmp/60.0;
+  dparse (&tmp, 6, string);
+  *h1 += tmp/3600.0;
+  
+  dparse (&tmp, 8, string);
+  *d0 += tmp/60.0;
+
+  dparse (&tmp, 10, string);
+  *d1 += tmp/60.0;
+
+  *h0 *= 15*flag_h0;
+  *h1 *= 15*flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  return (TRUE);
+}
+
+
+/*
+      if (buffer[i*48 + 19] == ' ') continue;
+      strncpy (temp, &buffer[i*48 + 19], 20);       temp[20] = 0;
+      hms_to_deg (&RA,  &DEC, temp, ' ', 3);
+
+
+  dBigRA = 360.0 / (int)(0.5 + 48*cos(3.1415927*0.5*(BigDecBounds[NBigDec] + BigDecBounds[NBigDec + 1])/180.0));
+
+  NBigRA = ra / dBigRA;
+
+  NBig = NBigRA;
+  for (i = 0; (i < 12) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+  for (i = 13; (i < 24) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+
+
+  fprintf (stderr, "%d %d %d %d %f %f -> %f %f %f\n", NBigDec, NBigRA, NBigRASections[NBigDec], NBig, ra, dec, BigDecBounds[NBigDec], BigDecBounds[NBigDec + 1], dBigRA);
+*/
Index: /tags/start/Ohana/src/markstar/src/check_lockfile.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/check_lockfile.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/check_lockfile.c	(revision 12606)
@@ -0,0 +1,39 @@
+# include "markstar.h"
+
+check_lockfile ()
+{
+  
+  FILE *f;
+  char filename[128];
+  struct stat filestat;
+
+  sprintf (filename, "%s/lock\0", CATDIR);
+  if (stat (filename, &filestat) != -1) {
+    fprintf (stderr, "ERROR: catalog %s is locked, try again later\n", CATDIR);
+    exit (0);
+  }
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't set lock file %s\n", filename);
+    exit (0);
+  }
+  fclose (f);
+
+}
+
+clear_lockfile ()
+{
+  
+  char filename[128], line[256];
+  struct stat filestat;
+
+  sprintf (filename, "%s/lock\0", CATDIR);
+  if (stat (filename, &filestat) != -1) {
+    sprintf (line, "rm %s\0", filename);
+    system (line);
+  } else {
+    fprintf (stderr, "can't remove lockfile, why not?\n");
+  }
+
+}
Index: /tags/start/Ohana/src/markstar/src/check_permissions.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/check_permissions.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/check_permissions.c	(revision 12606)
@@ -0,0 +1,63 @@
+# include "markstar.h"
+
+check_permissions (char *basefile) {
+  
+  FILE *f;
+  char *c, dir[256], filename[256];
+  struct stat filestat;
+  uid_t fuid, uid;
+  gid_t fgid, gid;
+  int status;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to write to directory */
+  sprintf (filename, "%s\0", basefile);
+  c = strrchr (filename, '/');
+  if (c == (char *) NULL) {
+    strcpy (dir, ".");
+  } else {
+    *c = 0;
+    strcpy (dir, filename);
+  }
+  status = stat (dir, &filestat);
+  if (status == -1) {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (0);
+  } 
+  if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRWXU)) ||
+      ((gid == filestat.st_gid) && (filestat.st_mode & S_IRWXG)) || 
+      (filestat.st_mode & S_IRWXO)) {
+  } else {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (0);
+  }
+  
+  /* check permission to write to file */
+  sprintf (filename, "%s\0", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (0);
+    }
+  }
+  
+  /* check permission to write to backup file */
+  sprintf (filename, "%s~\0", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (0);
+    }
+  }
+  
+}
Index: /tags/start/Ohana/src/markstar/src/config.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/config.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/config.c	(revision 12606)
@@ -0,0 +1,110 @@
+# include <ohana.h>
+# define D_NBYTES 4096
+
+char *LoadConfigFile (filename) 
+char *filename; 
+{
+  
+  FILE *f;
+  int i, done, Nbytes, NBYTES, size;
+  char *config;
+  
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "couldn't find %s\n", filename);
+    return ((char *) NULL);
+  }
+ 
+  NBYTES = D_NBYTES;
+  ALLOCATE (config, char, NBYTES);
+ 
+  size = 0;
+  done = FALSE;
+  for (i = 0; !done; i++) {
+    Nbytes = Fread (&config[i*D_NBYTES], sizeof(char), D_NBYTES, f, "char");
+    size += Nbytes;
+    if (Nbytes < D_NBYTES) 
+      done = TRUE;
+    else {
+      NBYTES += D_NBYTES;
+      REALLOCATE (config, char, NBYTES);
+    }
+  }
+  
+  config[size] = '\n';
+  config[size+1] = 0;
+  REALLOCATE (config, char, size + 2);
+ 
+  fclose (f);
+
+  return (config);
+}
+
+int ScanConfig /* we expect one more field: the pointer to the value requested */
+# ifndef ANSI
+(config, field, mode, va_alist) 
+ char *config; char *field, *mode; va_dcl
+# else
+(char       config[],
+ char       field[],
+ char       mode[],...)
+# endif
+{
+ 
+  int i, j;
+  char *p, *p2, tmp[256];
+  va_list argp;
+  double value;
+  
+# ifndef ANSI
+  va_start (argp);
+# else
+  va_start (argp, N);
+# endif
+  
+  /* find the correct line with field */
+  p2 = config;
+  for (i = 0; ; i++) {
+    if (!strncmp (field, p2, strlen(field))) {
+      p = p2 + strlen (field);
+      break;
+    }
+    else {
+      p2 = strchr (p2, '\n');
+      if (p2 == (char *) NULL) {
+	fprintf (stderr, "entry %s not found in config file\n", field);
+	return (FALSE);
+      }
+      else p2++;
+    }
+  }
+  if (!strcmp (mode, "%s")) {
+    p2 = strchr (p, '\n');
+    if (p2 == (char *) NULL)
+      p2 = config + strlen(config);
+    bcopy (p, tmp, (p2-p));
+    tmp[(p2-p)] = 0;
+    stripwhite (tmp);
+    p2 = va_arg (argp, char *);
+    strcpy (p2, tmp);
+  }
+  else {
+ 
+    /* try to get a numerical value from the field */
+    value = strtod (p, &p2);
+    if ((*p2 == 'd') || (*p2 == 'D')) 
+      value *= pow (10.0, atof (p2 + 1));
+    
+    if (!strcmp (mode, "%d"))  *va_arg (argp, int *)       = value;
+    if (!strcmp (mode, "%u"))  *va_arg (argp, unsigned *)  = value;
+    if (!strcmp (mode, "%ld")) *va_arg (argp, long *)      = value;
+    if (!strcmp (mode, "%hd")) *va_arg (argp, short *)     = value;
+    if (!strcmp (mode, "%f"))  *va_arg (argp, float *)     = value;
+    if (!strcmp (mode, "%lf")) *va_arg (argp, double *)    = value;
+    
+  }
+ 
+  va_end (argp);
+  return (TRUE);
+  
+}
Index: /tags/start/Ohana/src/markstar/src/coordops.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/coordops.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/coordops.c	(revision 12606)
@@ -0,0 +1,331 @@
+# include "markstar.h"
+
+XY_to_RD (ra, dec, x, y, coords)
+double *ra, *dec;
+double  x, y;
+Coords coords[];
+{
+
+  double L, M, X, Y, T, Z;
+  double R, sphi, cphi, stht, ctht;
+  double alpha, delta, salp, calp, sdel, sdp, cdp;
+  
+  *ra  = 0;
+  *dec = 0;
+
+  /** convert pixel coordinates to cartesian system **/
+  stht = ctht = 1;
+  if (!strcmp(&coords[0].ctype[4], "-PLY")) {
+    X = coords[0].cdelt1*(x - coords[0].crpix1 + x*x*coords[0].polyterms[0][0] + x*y*coords[0].polyterms[1][0] + y*y*coords[0].polyterms[2][0]
+			  + x*x*x*coords[0].polyterms[3][0] + x*x*y*coords[0].polyterms[4][0] + x*y*y*coords[0].polyterms[5][0] + y*y*y*coords[0].polyterms[6][0]);
+    Y = coords[0].cdelt2*(y - coords[0].crpix2 + x*x*coords[0].polyterms[0][1] + x*y*coords[0].polyterms[1][1] + y*y*coords[0].polyterms[2][1]
+			  + x*x*x*coords[0].polyterms[3][1] + x*x*y*coords[0].polyterms[4][1] + x*y*y*coords[0].polyterms[5][1] + y*y*y*coords[0].polyterms[6][1]);
+  } else {
+    X = coords[0].cdelt1*(x - coords[0].crpix1);
+    Y = coords[0].cdelt2*(y - coords[0].crpix2);
+  }    
+
+  L = (X*coords[0].pc1_1 + Y*coords[0].pc1_2);
+  M = (X*coords[0].pc2_1 + Y*coords[0].pc2_2);
+  /* in FITS ref, L,M = x, y  alpha, delta = phi, theta */
+
+  /**** Zenithal Projections ****/
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || 
+      !strcmp(&coords[0].ctype[4], "-TAN") || 
+      !strcmp(&coords[0].ctype[4], "-SIN") || 
+      !strcmp(&coords[0].ctype[4], "-ZEA") || 
+      !strcmp(&coords[0].ctype[0], "MM")) {
+    R = hypot (L,M);
+    if ((L == 0) && (M == 0)) {
+      sphi = 0;
+      cphi = 1;
+    }
+    else {
+      sphi =  L / R;
+      cphi = -M / R;
+    }
+
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || 
+	!strcmp(&coords[0].ctype[4], "-TAN")) {
+      if (R == 0) {
+	stht = 1.0;
+	ctht = 0.0;
+      }
+      else {
+	T = DEG_RAD / R;
+	stht =   T / sqrt ( 1.0 + T*T);
+	ctht = 1.0 / sqrt ( 1.0 + T*T);
+      }
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || 
+	!strcmp(&coords[0].ctype[0], "MM")) {
+      ctht = RAD_DEG * R;
+      stht = sqrt (1 - ctht*ctht);
+    }
+    if (!strcmp(&coords[0].ctype[4], "-ZEA")) {
+      stht = 1 - 0.5*SQ(R*RAD_DEG);
+      ctht = sqrt (1 - stht*stht);
+    }
+
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    
+    sdel = stht*sdp - ctht*cphi*cdp;
+    salp = ctht*sphi;
+    calp = stht*cdp + ctht*cphi*sdp;
+    alpha = atan2 (salp, calp);
+    delta = asin (sdel);
+    
+    *ra  = DEG_RAD*alpha + coords[0].crval1;
+    *dec = DEG_RAD*delta;
+  }
+
+  /**** Locally Cartesian Projections ****/
+  if (!strcmp(&coords[0].ctype[4], "-LIN") || !strcmp(&coords[0].ctype[0], "GENE")) {
+    *ra  = L + coords[0].crval1;
+    *dec = M + coords[0].crval2;
+  }
+
+  /**** Other Conventional Projections ****/
+  if (!strcmp(&coords[0].ctype[4], "-AIT")) {
+    Z = sqrt (1.0 - SQ(RAD_DEG*0.25*L) - SQ(RAD_DEG*0.5*M));
+    alpha = 2.0 * DEG_RAD * atan2 (RAD_DEG*0.5*Z*L, 2.0*SQ(Z) - 1.0);
+    delta = DEG_RAD * asin (RAD_DEG*M*Z);
+    *ra  = alpha + coords[0].crval1;
+    *dec = delta + coords[0].crval2;
+  }
+  if (!strcmp(&coords[0].ctype[4], "-GLS")) {
+    /* L,M in degrees, alpha,delta in degrees */
+    alpha = L / cos (RAD_DEG * M);
+    delta = M;
+    *ra  = alpha + coords[0].crval1;
+    *dec = delta + coords[0].crval2;
+  }
+  if (!strcmp(&coords[0].ctype[4], "-PAR")) {
+    /* L,M in degrees, alpha,delta in degrees */
+    alpha = L / (1.0 - SQ(2.0*M/180));
+    delta = 3 * DEG_RAD * asin (M/180.0);
+    *ra  = alpha + coords[0].crval1;
+    *dec = delta + coords[0].crval2;
+  }
+}
+
+
+
+RD_to_XY (x, y, ra, dec, coords)
+double *x, *y;
+double  ra, dec;
+Coords coords[];
+{
+
+  double phi, theta;
+  double tmp_d;
+  double X, Y, sphi, cphi, stht;
+  double salp, calp, sdel, cdel, sdp, cdp;
+  double P, CP, A, Rc;
+  int status;
+
+  X = Y = 1;
+  status = TRUE;
+  if (!strcmp(&coords[0].ctype[4], "-PLY")) {
+    /* fprintf (stderr, "approximate to polynomial TAN plane fit\n"); */
+  }
+
+  *x = 0;
+  *y = 0;
+
+  /**** Locally Cartesian Projections ****/
+  if (!strcmp(&coords[0].ctype[0], "GENE") || !strcmp(&coords[0].ctype[4], "-LIN")) {
+    X = (ra  - coords[0].crval1);
+    Y = (dec - coords[0].crval2);
+  }
+  
+  /**** Zenithal Projections ****/
+  if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") || !strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    salp = sin(RAD_DEG*(ra - coords[0].crval1));
+    calp = cos(RAD_DEG*(ra - coords[0].crval1));
+    sdel = sin(RAD_DEG*dec);
+    cdel = cos(RAD_DEG*dec);
+
+    stht = sdel*sdp + cdel*cdp*calp;  /* sin(theta) */
+    sphi = cdel*salp;  /* = cos(theta)*sin(phi) */
+    cphi = cdel*sdp*calp - sdel*cdp; /* = cos(theta)*cos(phi) */
+    if (stht < 0) status = FALSE;
+    
+    if (!strcmp(&coords[0].ctype[4], "-PLY") || !strcmp(&coords[0].ctype[4], "-TAN") ) {
+      X =  DEG_RAD * sphi / stht;
+      Y = -DEG_RAD * cphi / stht;
+    }
+    if (!strcmp(&coords[0].ctype[4], "-SIN") || !strcmp(&coords[0].ctype[0], "MM")) {
+      X =  DEG_RAD * sphi;
+      Y = -DEG_RAD * cphi;
+    }
+    if (!strcmp(&coords[0].ctype[4], "-ZEA")) {
+      Rc = DEG_RAD * M_SQRT2 / sqrt (1 + stht);
+      X =  Rc * sphi;
+      Y = -Rc * cphi;
+    }
+  }
+
+  /**** Other Standard Projections ****/
+  if (!strcmp(&coords[0].ctype[4], "-AIT")) {
+    phi = RAD_DEG*(ra - coords[0].crval1);
+    theta = RAD_DEG*(dec - coords[0].crval2);
+    P = 1.0 + cos (theta) * cos (0.5*phi);
+    if (P != 0.0) {
+      A =  DEG_RAD * sqrt (2.0 / P);
+      X =  2.0 * A * cos (theta) * sin (0.5*phi);
+      Y =  A * sin (theta);
+    } else { 
+      X =  0.0;
+      Y =  0.0;
+    }	
+  }
+  if (!strcmp(&coords[0].ctype[4], "-GLS")) {
+    phi = ra - coords[0].crval1;
+    theta = dec - coords[0].crval2;
+    X = phi * cos(RAD_DEG * theta);
+    Y = theta;
+  }
+  if (!strcmp(&coords[0].ctype[4], "-PAR")) {
+    phi = ra - coords[0].crval1;
+    theta = dec - coords[0].crval2;
+    X = phi * (2.0*cos(2*RAD_DEG*theta/3.0) - 1);
+    Y = 180.0 * sin (RAD_DEG*theta/3.0);
+  }
+   
+  tmp_d = 1.0 / (coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1);
+  *x = tmp_d * (coords[0].pc2_2*X - coords[0].pc1_2*Y) / coords[0].cdelt1 + coords[0].crpix1;
+  *y = tmp_d * (coords[0].pc1_1*Y - coords[0].pc2_1*X) / coords[0].cdelt2 + coords[0].crpix2;
+
+  return (status);
+ 
+}
+
+
+fRD_to_XY (x, y, ra, dec, coords)
+float *x, *y;
+double  ra, dec;
+Coords coords[];
+{
+
+  int status;
+  double tmpx, tmpy;
+
+  status = RD_to_XY (&tmpx, &tmpy, ra, dec, coords);
+  *x = tmpx;
+  *y = tmpy;
+  
+  return (status);
+
+}
+
+fXY_to_RD (ra, dec, x, y, coords)
+float *ra, *dec;
+double  x, y;
+Coords coords[];
+{
+
+  int status;
+  double tmpr, tmpd;
+
+  status = XY_to_RD (&tmpr, &tmpd, x, y, coords);
+  *ra = tmpr;
+  *dec = tmpd;
+  
+  return (status);
+
+}
+
+GetCoords (coords, header) 
+Coords coords[];
+Header header[];
+{
+
+  int status;
+  double rotate;
+
+  rotate = 0.0;
+  coords[0].crval1 = coords[0].crpix1 = coords[0].cdelt1 = 0.0;
+  coords[0].crval2 = coords[0].crpix2 = coords[0].cdelt2 = 0.0;
+  coords[0].pc1_1 = coords[0].pc2_2 = 1.0;
+  coords[0].pc2_1 = coords[0].pc1_2 = 0.0;
+  strcpy (coords[0].ctype, "NONE");
+
+  status = TRUE; 
+  if (fits_scan (header, "CTYPE2", "%s", 1, coords[0].ctype)) {
+    status  = fits_scan (header, "CRVAL1", "%lf", 1, &coords[0].crval1);
+    status &= fits_scan (header, "CRPIX1", "%lf", 1, &coords[0].crpix1);
+    status &= fits_scan (header, "CRVAL2", "%lf", 1, &coords[0].crval2);  
+    status &= fits_scan (header, "CRPIX2", "%lf", 1, &coords[0].crpix2);
+    if (fits_scan (header, "CDELT1", "%lf", 1, &coords[0].cdelt1)) {
+      status &= fits_scan (header, "CDELT2", "%lf", 1, &coords[0].cdelt2);
+      if (fits_scan (header, "CROTA2", "%lf", 1, &rotate)) {
+	coords[0].pc1_1 =  cos(rotate*RAD_DEG);
+	coords[0].pc1_2 = -sin(rotate*RAD_DEG);
+	coords[0].pc2_1 =  sin(rotate*RAD_DEG);
+	coords[0].pc2_2 =  cos(rotate*RAD_DEG);
+      }
+      if (fits_scan (header, "PC001001", "%lf", 1, &coords[0].pc1_1)) {
+	status &= fits_scan (header, "PC001002", "%lf", 1, &coords[0].pc1_2);
+	status &= fits_scan (header, "PC002001", "%lf", 1, &coords[0].pc2_1);
+	status &= fits_scan (header, "PC002002", "%lf", 1, &coords[0].pc2_2);
+      }
+    }
+    else {
+      if (fits_scan (header, "CD1_1", "%lf", 1, &coords[0].pc1_1)) {
+	status &= fits_scan (header, "CD1_2", "%lf", 1, &coords[0].pc1_2);
+	status &= fits_scan (header, "CD2_1", "%lf", 1, &coords[0].pc2_1);
+	status &= fits_scan (header, "CD2_2", "%lf", 1, &coords[0].pc2_2);
+	coords[0].cdelt1 = coords[0].cdelt2 = 1.0;
+      }
+      else {
+	status = FALSE;
+      }
+    }
+  }
+  else {
+    if (fits_scan (header, "RA_O", "%lf", 1, &coords[0].crval1)) {
+      status  = fits_scan (header, "RA_X", "%lf", 1, &coords[0].pc1_1);
+      status &= fits_scan (header, "RA_Y", "%lf", 1, &coords[0].pc1_2);
+      status &= fits_scan (header, "DEC_O", "%lf", 1, &coords[0].crval2);  
+      status &= fits_scan (header, "DEC_X", "%lf", 1, &coords[0].pc2_1);
+      status &= fits_scan (header, "DEC_Y", "%lf", 1, &coords[0].pc2_2);
+      coords[0].crpix1 = coords[0].crpix2 = 0.0;
+      coords[0].cdelt1 = coords[0].cdelt2 = 1.0;
+      strcpy (coords[0].ctype, "GENE");
+    }
+  }
+  if (!status) {
+    fprintf (stderr, "error getting all elements for coordinate mode %d\n", coords[0].ctype);
+    coords[0].crval1 = coords[0].crpix1 = coords[0].cdelt1 = 0.0;
+    coords[0].crval2 = coords[0].crpix2 = coords[0].cdelt2 = 0.0;
+    coords[0].pc1_1 = coords[0].pc2_2 = 1.0;
+    coords[0].pc2_1 = coords[0].pc1_2 = 0.0;
+    strcpy (coords[0].ctype, "NONE");
+  }
+}
+
+
+  /* -PLY projection is an extrapolation of the -TAN projection. 
+     In addition to the usual linear terms of CRPIXi, PC00i00j, there are 
+     higher order polynomial terms (up to 3rd order):
+     Axis 1 terms:
+     PCA1X2Y0 = coords.polyterm[0][0] = x^2                                             
+     PCA1X1Y1 = coords.polyterm[1][0] = xy                                          
+     PCA1X0Y2 = coords.polyterm[2][0] = y^2                                             
+     PCA1X3Y0 = coords.polyterm[3][0] = x^3                                             
+     PCA1X2Y1 = coords.polyterm[4][0] = x^2 y                                             
+     PCA1X1Y2 = coords.polyterm[5][0] = x y^2                                             
+     PCA1X0Y3 = coords.polyterm[6][0] = y^2                                              
+     Axis 2 terms:
+     PCA2X2Y0 = coords.polyterm[0][1] = x^2                                               
+     PCA2X1Y1 = coords.polyterm[1][1] = xy                                                
+     PCA2X0Y2 = coords.polyterm[2][1] = y^2                                               
+     PCA2X3Y0 = coords.polyterm[3][1] = x^3                                               
+     PCA2X2Y1 = coords.polyterm[4][1] = x^2 y                                             
+     PCA2X1Y2 = coords.polyterm[5][1] = x y^2                                             
+     PCA2X0Y3 = coords.polyterm[6][1] = y^2                                               
+  */
Index: /tags/start/Ohana/src/markstar/src/find_bright_stars.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/find_bright_stars.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/find_bright_stars.c	(revision 12606)
@@ -0,0 +1,142 @@
+# include "markstar.h"
+
+find_bright_stars (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  int i, j, n, m, first_j, Nave, Ngsc;
+  Catalog GSCdata;
+  double MinRA, MinDEC, MaxRA, MaxDEC, RaCenter, DecCenter;
+  Coords *tcoords;
+  float *X1, *Y1, *X2, *Y2;
+  int *N1, *N2;
+  char *mark;
+  double dX, dY, dR, MaxDist, MaxDist1, MaxRadius, radius, radius2;
+
+  load_gsc_data (&GSCdata, catstats);
+
+  Nave = catalog[0].Naverage;
+  Ngsc = GSCdata.Naverage;
+    
+  /* in the function below, it is better to have the catalog with
+     more stars associated with index 2 (j) */ 
+  X2 = catstats[0].X;
+  Y2 = catstats[0].Y;
+  N2 = catstats[0].N;
+  ALLOCATE (X1, float, Ngsc);
+  ALLOCATE (Y1, float, Ngsc);
+  ALLOCATE (N1, int, Ngsc);
+  ALLOCATE (mark, char, Nave);
+  bzero (mark, Nave);
+
+  tcoords = &catstats[0].coords;
+  for (i = 0; i < Ngsc; i++) {
+    fRD_to_XY (&X1[i], &Y1[i], GSCdata.average[i].R, GSCdata.average[i].D, tcoords);
+    N1[i] = i;
+  }
+  if (Ngsc > 1) sort_lists (X1, Y1, N1, Ngsc);
+  
+  /* first find stellar halos */
+  /* max radius (mag = -1) */
+  /** the j index moves quickly and is better associated with the catalog with more stars */
+  MaxRadius = BRIGHT_HALO_SLOPE * (-1.0 - BRIGHT_HALO_MAG); 
+  /** find catalog stars near GSC stars **/
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -2*MaxRadius) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*MaxRadius) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    radius = MAX (BRIGHT_HALO_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_HALO_MAG), 0.0);
+    if (radius == 0) {
+      i++; 
+      continue;
+    }
+    radius2 = radius*radius;
+    for (; (dX > -2*radius) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < radius2) {  /* new measurement of this star */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+  /* next find y spikes */
+  /** find catalog stars near GSC stars **/
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -BRIGHT_YTRAIL_WIDTH) {
+      i++;
+      continue;
+    }
+    if (dX >= BRIGHT_YTRAIL_WIDTH) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    MaxDist = MAX (BRIGHT_YTRAIL_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_YTRAIL_MAG), 0.0);
+    for (; (dX > -BRIGHT_YTRAIL_WIDTH) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      if ((fabs(dX) < BRIGHT_YTRAIL_WIDTH) && (fabs(dY) < MaxDist)) {  /* star on spike */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+  /* next find x spikes */
+  /** find catalog stars near GSC stars **/
+  MaxDist = MAX (BRIGHT_XTRAIL_SLOPE * (-1.0 - BRIGHT_XTRAIL_MAG), 0.0);
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -MaxDist) {
+      i++;
+      continue;
+    }
+    if (dX >= MaxDist) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    MaxDist1 = MAX (BRIGHT_XTRAIL_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_XTRAIL_MAG), 0.0);
+    for (; (dX > -MaxDist1) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      if ((fabs(dY) < BRIGHT_XTRAIL_WIDTH) && (fabs(dX) < MaxDist1)) {  /* star on spike */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+
+  /* done with search, mark selected stars */
+  for (i = 0; i < Nave; i++) {
+    if (mark[i]) {
+      catalog[0].average[N2[i]].code = ID_BLEED;
+    }
+  } 
+  
+  free (X1);
+  free (Y1);
+  free (N1);
+  free (mark);
+  free (GSCdata.average);
+
+}
+
Index: /tags/start/Ohana/src/markstar/src/find_ghosts.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/find_ghosts.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/find_ghosts.c	(revision 12606)
@@ -0,0 +1,70 @@
+# include "markstar.h"
+
+find_ghosts (catalog, catstats, filename, image, Nimage)
+Catalog catalog[];
+CatStats catstats[];
+char *filename;
+Image image[];
+int Nimage;
+{
+
+  int i, j, first_j, Nave, Ngsc, Nregions;
+  Catalog GSCdata, Ghostdata;
+  double MinRA, MinDEC, MaxRA, MaxDEC, RaCenter, DecCenter;
+  Coords *tcoords;
+  float *X1, *Y1, *X2, *Y2;
+  int *N1, *N2, *match;
+  char *mark;
+  double dX, dY, dR, RADIUS2, BRIGHT_RADIUS, radius, X, Y, R, D;
+  Image timage;
+  GSCRegion *region, *gregions2();
+
+  for (i = 0; i < Nimage; i++) {
+    
+    /* coords structure for ghost image */
+    timage = image[i];
+    timage.coords.cdelt1 = -1*image[i].coords.cdelt1;
+    timage.coords.cdelt2 = -1*image[i].coords.cdelt2;
+    timage.coords.crpix1 = 2*OPTICAL_AXIS1 - image[i].coords.crpix1;
+    timage.coords.crpix2 = 2*OPTICAL_AXIS2 - image[i].coords.crpix2;
+
+    region = gregions2 (&timage, &Nregions);
+    
+    /* find ghost stars */
+    load_gsc_data_ghost (&GSCdata, region, Nregions, &timage);
+
+    /* refect ghost stars to find locations of ghosts */
+    ALLOCATE (Ghostdata.average, Average, MAX (GSCdata.Naverage, 1));
+    for (j = 0; j < GSCdata.Naverage; j++) {
+      RD_to_XY (&X, &Y, GSCdata.average[j].R, GSCdata.average[j].D, &timage);
+      fXY_to_RD (&Ghostdata.average[j].R, &Ghostdata.average[j].D, X, Y, &image[i]);
+      Ghostdata.average[j].M = GSCdata.average[j].M;
+    }    
+    Ghostdata.Naverage = GSCdata.Naverage;
+
+    /* match ghosts and image stars, mark ghosts */
+    find_matches (catalog, catstats, &Ghostdata, i);
+
+    free (Ghostdata.average);
+    free (GSCdata.average);
+  }
+
+}
+
+/* 
+
+   just to be clear on some of the terms:
+
+   the "ghost" is the fuzzy patch of light on an image caused by
+     a reflected star
+
+   the "ghost star" is the star in the sky which causes a ghost
+
+   the "ghost image" is the image location on the sky 
+     where ghost stars may come from.
+
+   the "image stars" are observed stars at the location of the
+     ghost - these are detections of the ghost
+
+
+*/
Index: /tags/start/Ohana/src/markstar/src/find_group.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/find_group.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/find_group.c	(revision 12606)
@@ -0,0 +1,65 @@
+# include "markstar.h"
+
+find_group (catstats, mark, Npts, i, ANGLE)
+     CatStats catstats[];
+     double *ANGLE;
+     int i, Npts;
+     char *mark;
+{
+ 
+  float *R, *D;
+  int j, N, bin, Ndegbin;
+  unsigned short int *A;
+  double Ra, De, dR, dD, angle, limit;
+
+   /* assign some parameter values */
+  
+  R = catstats[0].X;
+  D = catstats[0].Y;
+  Ndegbin = NBINS / 180.0;
+  ALLOCATE (A, unsigned short int, NBINS + 1)
+  bzero (A, (NBINS+1)*sizeof(short));
+
+  /* look for points concentrated in an angle bin */
+  if (mark[i]) return (FALSE);
+  Ra = R[i];
+  De = D[i];
+  N = 0;
+  /* points east */
+  for (j = i + 1; (j < Npts) && (R[j] - Ra < RADIUS); j++) {
+    if (mark[j]) continue;
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) continue;  /* only NaN if dD = dR = 0 */
+      if (angle < 0) angle += M_PI;
+      bin = angle*DEG_RAD*Ndegbin;
+      A[bin] ++;
+      N ++;
+    }
+  }
+  /* points west */
+  for (j = i - 1; (j >= 0) && (Ra - R[j] < RADIUS); j--) {
+    if (mark[j]) continue;
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) continue;
+      if (angle < 0) angle += M_PI;
+      bin = angle*DEG_RAD*Ndegbin;
+      A[bin] ++;	
+      N ++;
+    }
+  }
+  limit = NSIGMA*sqrt((double)(N)/(double)(NBINS));
+  for (j = 0; j < NBINS; j++) {
+    if (A[j] > limit) {
+      *ANGLE = j / (DEG_RAD*Ndegbin);
+      return (TRUE);
+    }
+  }
+  return (FALSE);
+}
+  
Index: /tags/start/Ohana/src/markstar/src/find_images.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/find_images.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/find_images.c	(revision 12606)
@@ -0,0 +1,213 @@
+# include "markstar.h"
+double opening_angle ();
+
+Image *find_images (catstats, Nimages)
+CatStats catstats[];
+int *Nimages;
+{
+  
+  Header header;
+  Image *timage, *image;
+  int i, j, k, found, nimage, Nimage, NIMAGE, NTIMAGE, Nloop, Nlast;
+  int n, Nim, status, InRange;
+  FILE *f;
+  double Xc[6], Yc[6], Xi[6], Yi[6], r, d, x, y, dx, dy;
+  Coords *tcoords;
+
+  /* we make positional comparisons in the projection of catalog */
+  tcoords = &catstats[0].coords;
+  /* define catalog corners */
+  Xc[0] = catstats[0].RA[0]; Yc[0] = catstats[0].DEC[0];
+  Xc[1] = catstats[0].RA[1]; Yc[1] = catstats[0].DEC[0];
+  Xc[2] = catstats[0].RA[1]; Yc[2] = catstats[0].DEC[1];
+  Xc[3] = catstats[0].RA[0]; Yc[3] = catstats[0].DEC[1];
+  Xc[4] = catstats[0].RA[0]; Yc[4] = catstats[0].DEC[0];
+  for (j = 0; j < 5; j++) {
+    r = Xc[j]; d = Yc[j];
+    RD_to_XY (&Xc[j], &Yc[j], r, d, tcoords);
+  }
+
+  /* check if image datafile exists, get header, number of images */
+  if (!fits_read_header (ImageCat, &header)) {
+    fprintf (stderr, "ERROR: No images in catalog %s (1)\n", ImageCat);
+    exit (0);
+  }
+  Nimage = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+  if (Nimage == 0) {
+    fprintf (stderr, "ERROR: No images in catalog %s (1)\n", ImageCat);
+    exit (0);
+  }
+
+  /* get ready to read data on images */ 
+  f = fopen (ImageCat, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: trouble opening Image catalog: %s (2)\n", ImageCat);
+    exit (0);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* set up buffers for images, temporary storage */
+  NTIMAGE = 100;
+  ALLOCATE (timage, Image, NTIMAGE);
+  NIMAGE = 100;
+  ALLOCATE (image, Image, NIMAGE);
+  nimage = 0;
+  Nloop = Nimage / NTIMAGE + 1;
+  Nlast = Nimage % NTIMAGE;
+  
+  /* read in images in groups of NTIMAGE (100) */
+  for (n = 0; n < Nloop; n++) {
+    Nim = (n == Nloop - 1) ? Nlast : NTIMAGE;
+    status = Fread (timage, sizeof(Image), Nim, f, "image");
+    if (status != Nim) {
+      fprintf (stderr, "ERROR: couldn't read images from image catalog: %s\n", ImageCat);
+      exit (0);
+    }
+    /* test each image in block */
+    for (i = 0; i < Nim; i++) {
+      /* define image corners */
+      Xi[0] = 0;            Yi[0] = 0;
+      Xi[1] = timage[i].NX; Yi[1] = 0;
+      Xi[2] = timage[i].NX; Yi[2] = timage[i].NY;
+      Xi[3] = 0;            Yi[3] = timage[i].NY;
+      Xi[4] = 0;            Yi[4] = 0;
+      found = FALSE;
+      /* transform to tcoords */
+      if (catstats[0].DEC[1] > 86.25) { /* pole */
+	for (j = 0; j < 5; j++) {
+	  XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+	  if (d > catstats[0].DEC[0] - 0.5) found = TRUE;
+	}
+      } else {
+	for (j = 0; j < 6; j++) {
+	  XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+	  InRange = RD_to_XY (&Xi[j], &Yi[j], r, d, tcoords);
+	  if (!InRange) {
+	    /* if RD_to_XY returns false, the coords are ~180 away from
+	       the projection center */ 
+	    goto imskip;
+	  }
+	}
+	/* check if image corner inside catalog */
+	for (j = 0; (j < 4) && !found; j++) {
+	  found |= corner_check (&Xi[j], &Yi[j], &Xc[0], &Yc[0]);
+	}
+	/* check if catalog corner inside image */
+	for (j = 0; (j < 4) && !found; j++) {
+	  found |= corner_check (&Xc[j], &Yc[j], &Xi[0], &Yi[0]);
+	}
+	/* check if edges cross */
+	for (j = 0; (j < 4) && !found; j++) {
+	  for (k = 0; (k < 4) && !found; k++) {
+	    found |= edge_check (&Xi[j], &Yi[j], &Xc[k], &Yc[k]);
+	  }
+	}
+      }
+      if (found) {
+	image[nimage] = timage[i]; 
+	image[nimage].code = 0;
+	nimage ++;
+	if (nimage == NIMAGE) {
+	  NIMAGE += 100;
+	  REALLOCATE (image, Image, NIMAGE);
+	}
+      }
+    imskip:
+    }
+  }
+      
+  if (VERBOSE) { 
+    for (i = 0; i < nimage; i++) {
+      XY_to_RD (&r, &d, 0.5*image[i].NX, 0.5*image[i].NY, &image[i].coords);
+      fprintf (stderr, "associated images: %d %8.4f %8.4f %10d %6d  %5.3f %6.3f %6.3f\n", 
+	       i, r, d, image[i].tzero, image[i].nstar, 0.001*image[i].secz, 
+	       0.001*image[i].Mcal, 0.001*image[i].dMcal);
+    }
+  }
+
+  REALLOCATE (image, Image, MAX (nimage, 1));
+  free (timage);
+  *Nimages = nimage;
+  fclose (f);
+  return (image);
+}
+
+int edge_check (x1, y1, x2, y2)
+double *x1, *y1, *x2, *y2;
+{
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+/* returns the opening angle between the three points (2 is in middle) 
+   in range -pi to pi */
+double opening_angle (x1, y1, x2, y2, x3, y3)
+double x1, y1, x2, y2, x3, y3;
+{
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
+
+/* check if point x1,y1 is in box formed by x2[0-4] */
+int corner_check (x1, y1, x2, y2)
+double *x1, *y1, *x2, *y2;
+{
+
+  int i;
+  double theta;
+
+  theta = 0;
+
+  for (i = 0; i < 4; i++) {
+    theta += opening_angle (x2[i], y2[i], x1[0], y1[0], x2[i+1], y2[i+1]); 
+  }
+  if (fabs(theta) > 6) {
+    return (TRUE);
+  } else {
+    return (FALSE);
+  }
+}
Index: /tags/start/Ohana/src/markstar/src/find_line.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/find_line.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/find_line.c	(revision 12606)
@@ -0,0 +1,161 @@
+# include "markstar.h"
+
+find_line (catstats, mark, Npts, i, M, B, Angle)
+     CatStats catstats[];
+     double *M, *B, Angle;
+     int i, Npts;
+     char *mark;
+{
+  
+  float *R, *D;
+  int j, N;
+  double X, Y, X2, Y2, XY, m, b, det;
+  double dR, dD, Ra, De, angle;
+  char Flipped;
+  
+  R = catstats[0].X;
+  D = catstats[0].Y;
+
+  /* fit a line to points near line */
+  Ra = R[i];
+  De = D[i];
+  X = Ra;
+  Y = De;
+  X2 = Ra*Ra;
+  Y2 = De*De;
+  XY = Ra*De;
+  N = 1;
+  /* points to the east */
+  for (j = i + 1; (j < Npts) && (R[j] - Ra < RADIUS); j++) {
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) continue;
+      if (angle < 0) angle += M_PI;
+      if (fabs(angle - Angle) < RAD_DEG) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* points to the west */
+  for (j = i - 1; !mark[i] && (j >= 0) && (Ra - R[j] < RADIUS); j--) {
+    if (mark[j]) continue;
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) continue;
+      if (angle < 0) angle += M_PI;
+      if (fabs(angle - Angle) < RAD_DEG) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* determine coeffs */
+  Flipped = 0;
+  det = 1.0 / (X2*N - X*X);
+  m = det * (XY*N - X*Y);
+  b = det * (X2*Y - XY*X);
+  if (fabs(m) > 1.1) { /* use a line of R = m*D + b instead */
+    /* fprintf (stderr, "high slope object: %f %f  -> ", m, b); */
+    det = 1.0 / (Y2*N - Y*Y);
+    m = det * (XY*N - X*Y);
+    b = det * (Y2*X - XY*Y);
+    Flipped = 1;
+    /* fprintf (stderr, "%f %f\n", m, b); */
+  }
+
+  *M = m;
+  *B = b;
+  return (Flipped);
+
+}
+
+
+find_better_line (catstats, mark, Npts, i, M, B, axis)
+     CatStats catstats[];
+     double *M, *B;
+     int i, Npts, axis;
+     char *mark;
+{
+  
+  float *R, *D;
+  int j, N;
+  double X, Y, X2, Y2, XY, m, b, det;
+  double dR, dD, Ra, De, delta;
+  
+  R = catstats[0].X;
+  D = catstats[0].Y;
+
+  /* fit a line to points near line */
+  Ra = R[i];
+  De = D[i];
+  X = Y = X2 = Y2 = XY = N = 0;
+  m = *M;  b = *B;
+
+  /* points to the east */
+  for (j = i; (j < Npts) && (R[j] - Ra < RADIUS); j++) {
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      if (axis == 1) 
+	delta = R[j] - m*D[j] - b;
+      else
+	delta = D[j] - m*R[j] - b;
+      if (fabs(delta) < 2*TRAIL_WIDTH) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* points to the west */
+  for (j = i - 1; (j >= 0) && (Ra - R[j] < RADIUS); j--) {
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      if (axis == 1) 
+	delta = R[j] - m*D[j] - b;
+      else
+	delta = D[j] - m*R[j] - b;
+      if (fabs(delta) < 2*TRAIL_WIDTH) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* determine coeffs */
+  if (axis == 0) {
+    det = 1.0 / (X2*N - X*X);
+    m = det * (XY*N - X*Y);
+    b = det * (X2*Y - XY*X);
+  } else {
+    det = 1.0 / (Y2*N - Y*Y);
+    m = det * (XY*N - X*Y);
+    b = det * (Y2*X - XY*Y);
+  }
+
+  /* fprintf (stderr, "%f %f %d\n", m, b, N); */
+
+  *M = m;
+  *B = b;
+
+}
Index: /tags/start/Ohana/src/markstar/src/find_matches.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/find_matches.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/find_matches.c	(revision 12606)
@@ -0,0 +1,87 @@
+# include "markstar.h"
+
+find_matches (catalog, catstats, Ghostdata, Nimage)
+CatStats catstats[];
+Catalog catalog[], Ghostdata[];
+int Nimage;
+{
+
+  int i, j, k, n, m, N, M, first_j;
+  double X, Y, RADIUS, RADIUS2;
+  float *X1, *Y1, *X2, *Y2;
+  float dX, dY, dR;
+  int *N1, *N2;
+  int Nstar, Nghost, Ng;
+  unsigned int flags;
+  Coords *tcoords;
+
+  Nstar = catalog[0].Naverage;
+  Nghost = Ghostdata[0].Naverage;
+
+  if (Nghost < 1) return (0);
+
+  /* it is better to have the catalog with fewer stars
+     assigned to the X1 set */
+  X2 = catstats[0].X;
+  Y2 = catstats[0].Y;
+  N2 = catstats[0].N;
+
+  ALLOCATE (X1, float, Nghost);
+  ALLOCATE (Y1, float, Nghost);
+  ALLOCATE (N1, int, Nghost);
+
+  /* project ghosts to the frame of the catalog */
+  tcoords = &catstats[0].coords;
+  for (i = 0; i < Nghost; i++) {
+    fRD_to_XY (&X1[i], &Y1[i], Ghostdata[0].average[i].R, Ghostdata[0].average[i].D, tcoords);
+    N1[i] = i;
+  }
+  if (Nghost > 1) sort_lists (X1, Y1, N1, Nghost);
+
+  /* choose a radius for matches */
+  RADIUS2 = GHOST_RADIUS*GHOST_RADIUS;
+
+  /** find matched stars **/
+  for (i = j = 0; (i < Nghost) && (j < Nstar); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -2*GHOST_RADIUS) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*GHOST_RADIUS) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    for (; (dX > -2*GHOST_RADIUS) && (j < Nstar); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < RADIUS2) {  
+	/* this object may be a ghost star, 
+	   but only mark those measurements on the correct image */
+	M = N2[j];
+	m = catalog[0].average[M].offset;
+	Ng = 0;
+	for (k = 0; k < catalog[0].average[M].Nm; k++) {
+	  if (catalog[0].image[m+k] == Nimage) {
+	    catalog[0].measure[m+k].average |= GHOST_DATA;
+	    Ng ++;
+	  }
+	}
+	/* all measurements are ghosts */
+	if (catalog[0].average[M].Nm == Ng) {
+	  catalog[0].average[M].code = ID_GHOST;
+	}
+      }
+    }
+    j = first_j;
+    i++;
+  }
+
+  free (X1);
+  free (Y1);
+  free (N1);
+
+}
Index: /tags/start/Ohana/src/markstar/src/find_trails.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/find_trails.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/find_trails.c	(revision 12606)
@@ -0,0 +1,41 @@
+# include "markstar.h"
+
+find_trails (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  int i, j, N, Nave, axis, marked;
+  double density, spacing, Area, Angle, m, b, RaCenter, DecCenter;
+  double MinRA, MaxRA, MinDEC, MaxDEC;
+  float *X1, *Y1;
+  char *mark;
+  int *N1;
+  Coords tcoords;
+  
+  Nave = catalog[0].Naverage;
+  N1 = catstats[0].N;
+
+  ALLOCATE (mark, char, Nave);
+  bzero (mark, Nave);
+
+  for (i = 0; i < Nave; i++) {
+    /* already marked, ignore */
+    if ((mark[i]) || 
+	(catalog[0].average[N1[i]].code == ID_BLEED) || 
+	(catalog[0].average[N1[i]].code == ID_GHOST))
+      continue;
+    /* a good star, ignore */
+    if ((catalog[0].average[N1[i]].Nm > 3) && 
+	(catalog[0].average[N1[i]].Nm > 4*catalog[0].average[N1[i]].Nn)) {
+      continue;
+    }
+    if (find_group (catstats, mark, Nave, i, &Angle)) {
+      /* this point has an excess nearby concentration, find the line */
+      axis = find_line (catstats, mark, Nave, i, &m, &b, Angle);
+      find_better_line (catstats, mark, Nave, i, &m, &b, axis);
+      mark_trail (catstats, mark, Nave, i, m, b, axis, catalog);
+    }
+  }
+}
+
Index: /tags/start/Ohana/src/markstar/src/gcatalog.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/gcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/gcatalog.c	(revision 12606)
@@ -0,0 +1,41 @@
+# include "markstar.h"
+
+gcatalog (char *catname, Catalog *catalog) {
+  
+  char filename[128];
+  int i, status, mode;
+  unsigned int NotTrail;
+  unsigned short NotBad;
+
+  sprintf (filename, "%s/%s\0", CATDIR, catname);
+
+  mode = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+  status = load_catalog (filename, catalog, mode, VERBOSE);
+
+  switch (status) {
+  case 2:
+  case 0:
+    exit (0);
+  case 1:
+    break;
+  } 
+  if (catalog[0].Nsecfilt != photcodes.Nsecfilt) {
+    fprintf (stderr, "ERROR: mismatch in secondary photometry values\n");
+    exit (0);
+  }
+
+  if (RESET) {
+    NotBad = (0xffff ^ 0xc003);
+    for (i = 0; i < catalog[0].Naverage; i++) {
+      if ((catalog[0].average[i].code & ID_MOVING) &&
+	  (catalog[0].average[i].code & ID_BAD_OBJECT) &&
+	  (catalog[0].average[i].code & 0x0003)) {
+	/* this will set the correct bit for each to 0 */ 
+	catalog[0].average[i].code &= NotBad;
+      }
+    }
+    for (i = 0; i < catalog[0].Nmeasure; i++) {
+      catalog[0].measure[i].average &= ~PART_OF_TRAIL;
+    }
+  }
+}
Index: /tags/start/Ohana/src/markstar/src/gcatstats.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/gcatstats.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/gcatstats.c	(revision 12606)
@@ -0,0 +1,67 @@
+# include "markstar.h"
+
+gcatstats (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  int i;
+  double RaCenter, DecCenter;
+  double MinRA, MaxRA, MinDEC, MaxDEC;
+  float *X1, *Y1;
+  int *N1;
+  Coords tcoords;
+  
+  fits_scan (&catalog[0].header, "RA0", "%lf", 1, &MinRA);
+  fits_scan (&catalog[0].header, "RA1", "%lf", 1, &MaxRA);
+  fits_scan (&catalog[0].header, "DEC0", "%lf", 1, &MinDEC);
+  fits_scan (&catalog[0].header, "DEC1", "%lf", 1, &MaxDEC);
+
+  /* double check on region RA and DEC ranges */
+  DecCenter = 0.5*(MinDEC + MaxDEC);
+  RaCenter = 0.5*(MinRA + MaxRA);
+  if (MaxDEC > 86.25) {  /* we are on the pole */
+    DecCenter = 90.0;
+    RaCenter = 0.0;
+  }
+
+  catstats[0].RA[0] = MinRA;
+  catstats[0].RA[1] = MaxRA;
+  catstats[0].DEC[0] = MinDEC;
+  catstats[0].DEC[1] = MaxDEC;
+  catstats[0].Area = (MaxDEC - MinDEC)*(MaxRA - MinRA) / cos (RAD_DEG*DecCenter);
+  if (MaxDEC > 86.25) {  /* we are on the pole */
+    catstats[0].Area = 44.2;
+  }
+  catstats[0].density = catalog[0].Naverage / (3600*3600*catstats[0].Area);
+  /* catstats[0].density = MIN_DENSITY; */
+  catstats[0].spacing = 1.0 / (NSIGMA * catstats[0].density * 2*TRAIL_WIDTH);
+  fprintf (stderr, "Area, density, spacing: %f %f %f\n", catstats[0].Area, 
+	   catstats[0].density, catstats[0].spacing);
+  /* number of stars per square arcsec */
+
+  /** allocate local arrays **/
+  ALLOCATE (catstats[0].X, float, catalog[0].Naverage);
+  ALLOCATE (catstats[0].Y, float, catalog[0].Naverage);
+  ALLOCATE (catstats[0].N, int,   catalog[0].Naverage);
+
+  /* project onto rectilinear grid with 1 arcsec pixels, sort by X */
+  /* reference for coords is center of field  */
+  catstats[0].coords.crval1 = RaCenter;
+  catstats[0].coords.crval2 = DecCenter;
+  catstats[0].coords.crpix1 = catstats[0].coords.crpix2 = 0.0;
+  catstats[0].coords.cdelt1 = catstats[0].coords.cdelt2 = 1.0 / 3600.0;
+  catstats[0].coords.pc1_1 = catstats[0].coords.pc2_2 = 1.0;
+  catstats[0].coords.pc1_2 = catstats[0].coords.pc2_1 = 0.0;
+  strcpy (catstats[0].coords.ctype, "RA---TAN");
+
+  X1 = catstats[0].X;
+  Y1 = catstats[0].Y;
+  for (i = 0; i < catalog[0].Naverage; i++, X1++, Y1++) {
+    fRD_to_XY (X1, Y1, catalog[0].average[i].R, catalog[0].average[i].D, &catstats[0].coords);
+    catstats[0].N[i] = i;
+  }
+  if (catalog[0].Naverage > 1) sort_lists (catstats[0].X, catstats[0].Y, catstats[0].N, catalog[0].Naverage);
+  
+}
+
Index: /tags/start/Ohana/src/markstar/src/gregions.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/gregions.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/gregions.c	(revision 12606)
@@ -0,0 +1,134 @@
+# include "markstar.h"
+
+GSCRegion *gregions1 (catstats, Nregions)
+CatStats catstats[];
+int *Nregions;
+{
+  
+  GSCRegion *region;
+  int i, j, k, x, y, done, nregion, nregion2, NREGION;
+  double ra, dec, dx, dy, Xo[4], Yo[4];
+  FILE *f;
+
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: could not open GSC region file %s\n", GSCFILE);
+    exit (0);
+  }
+  nregion = 0;
+  NREGION = 10;
+  ALLOCATE (region, GSCRegion, NREGION);
+
+  if (catstats[0].DEC[0] == 86.25) { /* pole region */
+    dec = 86.0;
+    for (ra = 0.1; ra < 370; ra+= 30.0) {
+      aregion (&region[nregion], f, ra, dec);
+      done = FALSE;
+      for (j = 0; (j < nregion - 1) && !done; j++) {
+	if (!strcmp (region[nregion].filename, region[j].filename)) {
+	  nregion --;
+	  done = TRUE;
+	}
+      }
+      nregion ++;
+      if (nregion == NREGION) {
+	NREGION += 10;
+	REALLOCATE (region, GSCRegion, NREGION);
+      }
+    }
+  } else {
+    for (x = 0; x < 2; x++) {
+      for (y = 0; y < 2; y++) {
+	for (dx = -0.1; dx <= 0.1; dx += 0.2) {
+	  for (dy = -0.1; dy <= 0.1; dy += 0.2) {
+	    ra  = catstats[0].RA[x] + dx;
+	    dec = catstats[0].DEC[y] + dy;
+	    aregion (&region[nregion], f, ra, dec);
+	    done = FALSE;
+	    for (j = 0; (j < nregion) && !done; j++) {
+	      if (!strcmp (region[nregion].filename, region[j].filename)) {
+		done = TRUE;
+	      }
+	    }
+	    if (!done) {
+	      nregion ++;
+	    } 
+	    if (nregion == NREGION) {
+	      NREGION += 10;
+	      REALLOCATE (region, GSCRegion, NREGION);
+	    }
+	  }
+	}
+      }
+    }
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "using %d regions\n", nregion);
+    for (i = 0; i < nregion; i++) {
+      fprintf (stderr, "region %d: %f %f  %f %f\n", i, region[i].RA[0], region[i].RA[1], region[i].DEC[0], region[i].DEC[1]);
+    } 
+  }
+
+  REALLOCATE (region, GSCRegion, MAX (nregion, 1));
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (region);
+  
+}
+
+GSCRegion *gregions2 (image, Nregions)
+Image *image;
+int *Nregions;
+{
+  
+  GSCRegion *region;
+  FILE *f;
+  double x, y;
+  double dr, dd, dec, ra;
+  int i, j, done, nregion, NREGION;
+  
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find GSC region file %s\n", GSCFILE);
+    exit (0);
+  }
+  
+  /* find regions at image corners */
+  NREGION = 10;
+  ALLOCATE (region, GSCRegion, NREGION);
+  nregion = 0;
+
+  /* look for new regions on grid across image */ 
+  for (x = 0.0; x <= 1.0; x+=0.25) {
+    for (y = 0.0; y <= 1.0; y+=0.25) {
+      XY_to_RD (&ra, &dec, image[0].NX*(1.1*x - 0.05), image[0].NY*(1.1*y - 0.05), &image[0].coords);
+      aregion (&region[nregion], f, ra, dec);
+      done = FALSE;
+      for (j = 0; (j < nregion) && !done; j++) {
+	if (!strcmp (region[nregion].filename, region[j].filename)) {
+	  nregion --;
+	  done = TRUE;
+	}
+      }
+      nregion ++;
+      if (nregion == NREGION) {
+	NREGION += 10;
+	REALLOCATE (region, GSCRegion, NREGION);
+      }
+    }
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "found %d region files:\n", nregion);
+    for (i = 0; i < nregion; i++) {
+      fprintf (stderr, "  %d %s\n", i, region[i].filename);
+    }
+  }
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (region);
+  
+}
Index: /tags/start/Ohana/src/markstar/src/load_gsc_data.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/load_gsc_data.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/load_gsc_data.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include "markstar.h"
+# define NBYTES 160000
+# define BYTES_STAR 23
+# define BLOCK 1000
+# define DNSTARS 1000
+
+load_gsc_data (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  /* load data from the GSC files */
+  char filename[128];
+  char *tbuffer;
+  int nstar, NSTARS;
+  int i, j, Nbytes, nbytes, Nregions;
+  double R, D, M, MagLimit;
+  FILE *f;
+  GSCRegion *region, *gregions1(), *gregions2();
+  
+  region = gregions1 (catstats, &Nregions);
+
+  MagLimit = MAX (MAX (BRIGHT_HALO_MAG, BRIGHT_XTRAIL_MAG), BRIGHT_YTRAIL_MAG); 
+  nstar = 0;
+  NSTARS = DNSTARS;
+  ALLOCATE (tbuffer, char, (BLOCK*BYTES_STAR));
+  ALLOCATE (catalog[0].average, Average, NSTARS);
+  Nbytes = BLOCK*BYTES_STAR;
+  
+  for (j = 0; j < Nregions; j++) {
+    f = fopen (region[j].filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "GSC file for region %s missing\n", region[j].filename);
+      exit (0);
+    }
+    
+    while ((nbytes = fread (tbuffer, 1, Nbytes, f)) > 0) {
+      for (i = 0; i < nbytes / BYTES_STAR; i++) {
+	dparse (&M, 3, &tbuffer[i*BYTES_STAR]);
+	if (M > MagLimit) continue;
+	dparse (&R, 1, &tbuffer[i*BYTES_STAR]);
+	dparse (&D, 2, &tbuffer[i*BYTES_STAR]);
+	catalog[0].average[nstar].R = R;
+	catalog[0].average[nstar].D = D;
+	catalog[0].average[nstar].M = M * 1000.0;
+	nstar++;
+	if (nstar == NSTARS - 1) {
+	  NSTARS += DNSTARS;
+	  REALLOCATE (catalog[0].average, Average, NSTARS);
+	}
+      }
+    }
+    fclose (f);
+  }
+
+  free (tbuffer);
+  REALLOCATE (catalog[0].average, Average, nstar);
+  catalog[0].Naverage = nstar;
+  
+}
+
Index: /tags/start/Ohana/src/markstar/src/load_gsc_data_ghost.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/load_gsc_data_ghost.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/load_gsc_data_ghost.c	(revision 12606)
@@ -0,0 +1,75 @@
+# include "markstar.h"
+# define NBYTES 160000
+# define BYTES_STAR 23
+# define BLOCK 1000
+# define DNSTARS 1000
+
+/* this routine is basically identical to load_gsc_data, but
+   it is not limited to a single region file, and it merges the 
+   results */
+
+load_gsc_data_ghost (catalog, region, Nregion, image)
+Catalog catalog[];
+GSCRegion *region;
+int Nregion;
+Image image[];
+{
+
+  /* load data from the GSC files */
+  char filename[128];
+  char *tbuffer;
+  int nstar, NSTARS;
+  int i, j, Nbytes, nbytes;
+  double R, D, M, X, Y;
+  FILE *f;
+  Coords *tcoords;
+  int MinX, MinY, MaxX, MaxY;
+  
+  nstar = 0;
+  NSTARS = DNSTARS;
+  ALLOCATE (tbuffer, char, (BLOCK*BYTES_STAR));
+  ALLOCATE (catalog[0].average, Average, NSTARS);
+  tcoords = &image[0].coords;
+  MinX = 0;
+  MinY = 0;
+  MaxX = image[0].NX;
+  MaxY = image[0].NY;
+  
+  for (j = 0; j < Nregion; j++) {
+    
+    f = fopen (region[j].filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "no GSC file for region %s (2)\n", region[j].filename);
+      exit (0);
+    }
+    
+    Nbytes = BLOCK*BYTES_STAR;
+    while ((nbytes = fread (tbuffer, 1, Nbytes, f)) > 0) {
+      for (i = 0; i < nbytes / BYTES_STAR; i++) {
+	dparse (&M, 3, &tbuffer[i*BYTES_STAR]);
+	if (M > GHOST_MAG) continue;
+	dparse (&R, 1, &tbuffer[i*BYTES_STAR]);
+	dparse (&D, 2, &tbuffer[i*BYTES_STAR]);
+	RD_to_XY (&X, &Y, R, D, tcoords);
+	if ((X < MinX) || (X > MaxX) || (Y < MinY) || (Y > MaxY)) continue;
+	catalog[0].average[nstar].R = R;
+	catalog[0].average[nstar].D = D;
+	catalog[0].average[nstar].M = M * 1000.0;
+	nstar++;
+	if (nstar == NSTARS - 1) {
+	  NSTARS += DNSTARS;
+	  REALLOCATE (catalog[0].average, Average, NSTARS);
+	}
+      }
+    }
+    fclose (f);
+
+  }
+
+  free (tbuffer);
+  REALLOCATE (catalog[0].average, Average, MAX (nstar, 1));
+  catalog[0].Naverage = nstar;
+
+}
+
+
Index: /tags/start/Ohana/src/markstar/src/mark_trail.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/mark_trail.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/mark_trail.c	(revision 12606)
@@ -0,0 +1,272 @@
+# include "markstar.h"
+int *make_common_list ();
+int *check_common_list ();
+
+mark_trail (catstats, mark, Nave, i, m, b, axis, catalog)
+     CatStats catstats[];
+     char *mark;
+     int i, Nave, axis;
+     double m, b;
+     Catalog catalog[];
+{
+
+  float *R, *D;
+  int j, k, jj, kk, N, NPTS, marked, start, end, Nm;
+  int *good, *seq, *N1;
+  double *dist, *dist2;
+  double d2, di, Di, dD, n, Dist, scale, norm;
+  double spacing;
+  int *list, Nlist;
+  int M, Nmeas, thisimage;
+
+  R = catstats[0].X;
+  D = catstats[0].Y;
+  N1 = catstats[0].N;
+  spacing = catstats[0].spacing;
+
+  NPTS = 200;
+  ALLOCATE (good, int, NPTS);
+  ALLOCATE (dist, double, NPTS);
+  ALLOCATE (dist2, double, NPTS);
+  ALLOCATE (seq, int, NPTS);
+
+  /* Find all points which lie near line */
+  /* save the entry number and distance along line */
+  N = 0;
+  scale = sqrt (1.0 + m*m);
+
+  if (axis == 1) {
+    for (j = 0; j < Nave; j++) {
+      norm = scale * fabs(R[j] - m*D[j] - b);
+      if (!mark[j] && (norm < TRAIL_WIDTH)) {
+	good[N] = j;
+	dist[N] = scale * (D[j] - D[i] + m*(R[j] - R[i]));
+	seq[N] = N;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 200;
+	  REALLOCATE (good, int, NPTS);
+	  REALLOCATE (dist, double, NPTS);
+	  REALLOCATE (dist2, double, NPTS);
+	  REALLOCATE (seq, int, NPTS);
+	}
+      }
+    }
+  } else {
+    for (j = 0; j < Nave; j++) {
+      norm = scale * fabs(D[j] - m*R[j] - b);
+      if (!mark[j] && (norm < TRAIL_WIDTH)) {
+	good[N] = j;
+	dist[N] = scale * (R[j] - R[i] + m*(D[j] - D[i]));
+	seq[N] = N;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 200;
+	  REALLOCATE (good, int, NPTS);
+	  REALLOCATE (dist, double, NPTS);
+	  REALLOCATE (dist2, double, NPTS);
+	  REALLOCATE (seq, int, NPTS);
+	}
+      }
+    }
+  }
+  
+  if (N < NPTSINLINE) 
+    return (0);
+
+  sort_seq (dist, seq, N);
+  
+  start = -1; end = -1;
+  for (j = 0; j < N-1; j++) {
+    /* if we have part of a line, and next point is in the line, check for common images */
+    if ((start != -1) && (fabs(dist[j] - dist[j+1]) < spacing)) {
+      list = check_common_list (list, N1[good[seq[j+1]]], &Nlist, catalog);
+      if (Nlist == 0) { /* if no common images, dump list and continue */
+	end = j + 1;
+	if (end - start > NPTSINLINE) {
+	  if (axis == 0)
+	    fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", m, b, N, end-start, start, end, dist[start], dist[end-1]);
+	  else
+	    fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", 1.0/m, -1.0*b/m, N, end-start, start, end, dist[start], dist[end-1]);
+	  for (k = start; k < end; k++) {
+	    M = N1[good[seq[k]]];
+	    mark[good[seq[k]]] = TRUE;
+	    /* we need to mark measurements from all images in common on the line */
+	    Nm = 0;
+	    for (jj = 0; jj < catalog[0].average[M].Nm; jj++) {
+	      Nmeas = catalog[0].average[M].offset + jj;
+	      thisimage = catalog[0].image[Nmeas];
+	      for (kk = 0; kk < Nlist; kk++) {
+		if (thisimage == list[kk]) {
+		  catalog[0].measure[Nmeas].average |= PART_OF_TRAIL;
+		  Nm ++;
+		}
+	      }
+	    }
+	    /* if there is only 1 measurement, mark object as bad */
+	    if (catalog[0].average[M].Nm == Nm) {
+	      catalog[0].average[M].code = ID_TRAIL;
+	    }
+	    catalog[0].average[M].code = ID_TRAIL;
+	  }
+	}
+	start = -1;
+	end = -1;
+      }
+    }
+    /* if we haven't yet found a line segment, check for the beginning */
+    if ((start < 0) && (fabs(dist[j] - dist[j+1]) < spacing)) {
+      start = j;
+      list = make_common_list (N1[good[seq[j]]], N1[good[seq[j+1]]], &Nlist, catalog);
+      if (Nlist == 0) { /* if no common images, move on */
+	start = -1;
+	free (list);
+      }
+    }
+    /* if we have a complete line, check for validity.  if it has enough members,
+	 mark them and continue searching for lines */
+    if ((start != -1) && ((fabs(dist[j] - dist[j+1]) >= spacing) || (j == N-2))) {
+      end = j + 1;
+      if (end - start > NPTSINLINE) {
+	if (axis == 0)
+	  fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", m, b, N, end-start, start, end, dist[start], dist[end-1]);
+	else
+	  fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", 1.0/m, -1.0*b/m, N, end-start, start, end, dist[start], dist[end-1]);
+	for (k = start; k < end; k++) {
+	  M = N1[good[seq[k]]];
+	  mark[good[seq[k]]] = TRUE;
+	  if (catalog[0].average[M].code == ID_BLEED) continue;
+	  /* we need to mark measurements from all images in common on the line */
+	  Nm = 0;
+	  for (jj = 0; jj < catalog[0].average[M].Nm; jj++) {
+	    Nmeas = catalog[0].average[M].offset + jj;
+	    thisimage = catalog[0].image[Nmeas];
+	    for (kk = 0; kk < Nlist; kk++) {
+	      if (thisimage == list[kk]) {
+		catalog[0].measure[Nmeas].average |= PART_OF_TRAIL;
+		Nm ++;
+	      }
+	    }
+	  }
+	  /* if there is only 1 measurement, mark object as bad */
+	  if (catalog[0].average[M].Nm == Nm) {
+	    catalog[0].average[M].code = ID_TRAIL;
+	  }
+	  catalog[0].average[M].code = ID_TRAIL;
+	}
+      }
+      free (list);
+      start = -1;
+      end = -1;
+    }
+  }
+}
+
+
+/* I is Average seq number for star 1, J for star 2 */
+/* make a list of images in common between two measurements */
+int *make_common_list (I, J, Nlist, catalog)
+int I, J, *Nlist;
+Catalog catalog[];
+{
+
+  int i, j, N1, N2, nlist, NLIST;
+  int *list;
+  int k, already;
+
+  NLIST = 50;
+  ALLOCATE (list, int, NLIST);
+  nlist = 0;
+
+  for (i = 0; i < catalog[0].average[I].Nm; i++) {
+    N1 = catalog[0].average[I].offset + i;
+    if (catalog[0].image[N1] == -1)
+      continue; /* not a real measurement */
+    for (j = 0; j < catalog[0].average[J].Nm; j++) {
+      N2 = catalog[0].average[J].offset + j;
+      if (catalog[0].image[N2] == -1)
+	continue; /* not a real measurement */
+      if (catalog[0].image[N1] == catalog[0].image[N2]) {
+	already = FALSE; 
+	for (k = 0; !already && (k < nlist); k++) {
+	  if (catalog[0].image[N1] == list[k]) { 
+	    already = TRUE;
+	  }
+	}
+	if (!already) {
+	  list[nlist] = catalog[0].image[N1];
+	  nlist ++;
+	  if (nlist == NLIST - 1) {
+	    NLIST += 50;
+	    REALLOCATE (list, int, NLIST);
+	  }
+	}
+      }
+    }
+  }
+  
+  REALLOCATE (list, int, MAX(nlist, 1));
+  *Nlist = nlist;
+  return (list);
+
+}
+
+
+
+/* J is Average seq number for star */
+
+int *check_common_list (inlist, J, Nlist, catalog)
+int *inlist, J, *Nlist;
+Catalog catalog[];
+{
+
+  int i, j, N2, Ninlist;
+  int *list, NLIST, nlist;
+  int already, found, k;
+
+  NLIST = 50;
+  ALLOCATE (list, int, NLIST);
+  nlist = 0;
+  Ninlist = *Nlist;
+
+  for (j = 0; j < catalog[0].average[J].Nm; j++) {
+    N2 = catalog[0].average[J].offset + j;
+    found = FALSE;
+    for (i = 0; !found && (i < Ninlist); i++) {
+      if (catalog[0].image[N2] == -1)
+	continue; /* not a real measurement */
+      if (inlist[i] == catalog[0].image[N2]) {
+	found = TRUE;
+	already = FALSE; 
+	for (k = 0; !already && (k < nlist); k++) {
+	  if (inlist[i] == list[k]) {
+	    already = TRUE;
+	  }
+	}
+	if (!already) {
+	  list[nlist] = inlist[i];
+	  nlist ++;
+	  if (nlist == NLIST - 1) {
+	    NLIST += 50;
+	    REALLOCATE (list, int, NLIST);
+	  }
+	}
+      }
+    }
+  }
+  
+  /* if there are no common images, return the input list */
+  if (nlist != 0) {
+    free (inlist);
+    REALLOCATE (list, int, MAX(nlist, 1));
+    *Nlist = nlist;
+    return (list);
+  } else {
+    return (inlist);
+  }
+
+}
+
+
+/* measurements associated with image number -1 are not 
+   measurements we made, but are added, like USNO */
Index: /tags/start/Ohana/src/markstar/src/markstar.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/markstar.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/markstar.c	(revision 12606)
@@ -0,0 +1,67 @@
+# include "markstar.h"
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  FILE *f;
+  int i, Nstars, Nimage, Nregions, Nmissed;
+  Image *image, *find_images();
+  Catalog catalog;
+  CatStats catstats;
+  struct timeval now, then;  
+  
+  gettimeofday (&then, (void *) NULL);
+  ConfigInit (&argc, argv);
+
+  VERBOSE = FALSE;
+  if ((i = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  FORCE_RUN = FALSE;
+  if ((i = get_argument (argc, argv, "-f"))) {
+    FORCE_RUN = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  RESET = FALSE;
+  if ((i = get_argument (argc, argv, "-reset"))) {
+    RESET = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  if (argc < 2) {
+    fprintf (stderr, "ERROR: Usage: markstar (catalog)\n");
+    exit (0);
+  }
+
+  /* if lockfile exists, program will complain and quit */
+  check_lockfile (); 
+  check_permissions (argv[1]);
+
+  gcatalog (argv[1], &catalog);
+
+  gcatstats (&catalog, &catstats);
+
+  image = find_images (&catstats, &Nimage);
+
+  match_images (&catalog, image, Nimage);
+    
+  find_trails (&catalog, &catstats, i);  
+
+  /* find_bright_stars (&catalog, &catstats);  */
+
+  /* find_ghosts (&catalog, &catstats, argv[1], image, Nimage); */
+
+
+  wcatalog (argv[1], &catalog);
+
+  if (VERBOSE) {
+    gettimeofday (&now, (void *) NULL);
+    fprintf (stderr, "%s: elapsed time = %.2f sec\n", argv[1], 
+	     (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec));
+  }
+  clear_lockfile (); 
+  fprintf (stderr, "SUCCESS\n");
+}
+
Index: /tags/start/Ohana/src/markstar/src/match_images.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/match_images.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/match_images.c	(revision 12606)
@@ -0,0 +1,62 @@
+# include "markstar.h"
+
+match_images (catalog, image, Nimage)
+Catalog catalog[];
+Image   image[];
+int Nimage;
+{
+  
+  int j, k, found;
+  unsigned int *start, *stop;
+  short int *source;
+
+  /* this must be allocated so future free will not fail */
+  ALLOCATE (catalog[0].image, int, MAX (catalog[0].Nmeasure, 1));
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (FALSE);
+  }
+
+  ALLOCATE (start, unsigned int, Nimage);
+  ALLOCATE (stop,  unsigned int, Nimage);
+  ALLOCATE (source, short int, Nimage);
+  for (j = 0; j < Nimage; j++) {
+    start[j] = image[j].tzero - MAX(0.05*image[j].trate*image[j].NY, 1);
+    stop[j]  = image[j].tzero + MAX(1.05*image[j].trate*image[j].NY, 1);
+    source[j] = image[j].source;
+  }
+
+  for (j = 0; j < catalog[0].Nmeasure; j++) {
+    found = FALSE;
+    if (catalog[0].measure[j].t == 0) {
+      catalog[0].image[j] = -1;
+      found = TRUE;
+    }
+    for (k = 0; (k < Nimage) && !found; k++) {
+      if ((catalog[0].measure[j].t >= start[k]) && 
+	  (catalog[0].measure[j].t <= stop[k])  &&
+	  (catalog[0].measure[j].source == source[k])) {
+	catalog[0].image[j] = k;
+	found = TRUE;
+      }
+    }
+    if (!found) {
+      fprintf (stderr, "ERROR: can't find source image for this measurement: %d %d)\n",
+	       catalog[0].measure[j].t, catalog[0].measure[j].source);
+      exit (0);
+    }
+  }
+  free (start);
+  free (stop);
+  free (source);
+}
+
+  /* this routine uses the time of each measurement to match the
+measurement with an image.  Since the measurement is only store to 1
+sec accuracy, which corresponds to roughly 30 rows at nominal speed,
+we can't tell exactly which image the star come from.  However, this
+doesn't matter, and in fact this helps a bit: a measurement from the
+top of one image is the same as from the bottom of the next.
+Therefore, we intentionally blur the edges of the images by 5%, which
+will help to tie together neighboring images... */
+
Index: /tags/start/Ohana/src/markstar/src/old/add_unfound.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/old/add_unfound.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/old/add_unfound.c	(revision 12606)
@@ -0,0 +1,35 @@
+  /* incorporate unmatched image stars -- after all catalogs searched... */
+  for (i = 0; i < Nstars; i++) {
+    if (!found[i]) {
+      catalog[0].average[Nave].R = stars[N1[i]].R;
+      catalog[0].average[Nave].D = stars[N1[i]].D;
+      catalog[0].average[Nave].M = 1000.0*stars[N1[i]].M;
+      catalog[0].average[Nave].Nm = 1;
+      catalog[0].average[Nave].Xp = catalog[0].average[Nave].Xm = 0.0;
+      catalog[0].average[Nave].offset = Nmeas;
+      catalog[0].measure[Nmeas].dR  = 0.0;
+      catalog[0].measure[Nmeas].dD  = 0.0;
+      catalog[0].measure[Nmeas].M   = 1000.0*stars[N1[i]].M;
+      catalog[0].measure[Nmeas].dM  = stars[N1[i]].dM;
+      catalog[0].measure[Nmeas].t  = 3600.0 + stars[N1[i]].Y*0.1;
+      catalog[0].measure[Nmeas].average = (0x00ffffff & Nave);
+      /* time of star = time of image + offset + Y*rate */
+      Nave ++;
+      if (Nave == 0x1000000) {
+	fprintf (stderr, "too many stars in catalog\n");
+	clear_lockfile ();
+	exit (0);
+      }
+      if (Nave == NAVE) {
+	NAVE = Nave + 1000;
+	REALLOCATE (next, int, NAVE);
+	REALLOCATE (catalog[0].average, Average, NAVE);
+      }
+      Nmeas ++;
+      if (Nmeas == NMEAS) {
+	NMEAS = Nmeas + 1000;
+	REALLOCATE (next, int, NMEAS);
+	REALLOCATE (catalog[0].measure, Measure, NMEAS);
+      }
+    }
+  }
Index: /tags/start/Ohana/src/markstar/src/old/addstar.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/old/addstar.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/old/addstar.c	(revision 12606)
@@ -0,0 +1,70 @@
+# include "addstar.h"
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  FILE *f;
+  int i, Nstars, Nimage, Nregions, Nmissed;
+  Stars *stars, *gstars();
+  Image image, *pimage, *gimages();
+  Catalog catalog;
+  GSCRegion *region, *gregions();
+  struct timeval now, then;  
+  
+  gettimeofday (&then, (void *) NULL);
+  ConfigInit (argc, argv);
+
+  VERBOSE = FALSE;
+  if ((i = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  if (argc < 2) {
+    fprintf (stderr, "ERROR: Usage: addstar filename\n");
+    exit (0);
+  }
+
+  /* if lockfile exists, program will complain and quit */
+  check_lockfile ();
+
+  stars = gstars (argv[1], &Nstars, &image);
+
+  pimage = gimages (&image, &Nimage);
+  region = gregions (&image, &Nregions);
+
+  for (i = 0; i < Nregions; i++) {
+    gcatalog (&region[i], &catalog);
+    find_matches (&region[i], stars, Nstars, &catalog, &image, pimage, Nimage);
+    wcatalog (&region[i], &catalog);
+  }
+  
+  for (Nmissed = i = 0; i < Nstars; i++) {
+    if (stars[i].found == -1) {
+      fprintf (stderr, "%d %f %f %f %f\n", i, stars[i].R, stars[i].D, stars[i].M, stars[i].dM);
+      Nmissed ++;
+    }
+  }
+  if (Nmissed) fprintf (stderr, "WARNING: %d stars in image were missed!\n", Nmissed);
+
+  wimage (argv[1], &image, Nstars);
+
+  if (VERBOSE) {
+    gettimeofday (&now, (void *) NULL);
+    fprintf (stderr, "%s: elapsed time = %.2f sec\n", argv[1], 
+	     (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec));
+  }
+  clear_lockfile ();
+  fprintf (stderr, "SUCCESS\n");
+}
+
+
+  /* stars within a file are not all within 1 region file:
+     1) check if unfound stars are in current region 
+     2) if not, keep unfound for next pass */
+
+
+/* input star lists should be adjusted so 1 e/sec is mag 25.000 */ 
+
+
Index: /tags/start/Ohana/src/markstar/src/old/dumpcat.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/old/dumpcat.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/old/dumpcat.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include "addstar.h"
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  int i, j, Nstars, Nimage, Nregions;
+  Average *average;
+  Measure *measure;
+  Missing *missing;
+  Catalog catalog;
+  GSCRegion region;
+  FILE *f;
+  
+  if (argc < 4) {
+    fprintf (stderr, "USAGE: dumpcat catalog output mode(0,1,2,3)\n");
+    clear_lockfile ();
+    exit (0);
+  }
+
+  strcpy (region.filename, argv[1]);
+
+  gcatalog (&region, &catalog);
+
+  f = fopen (argv[2], "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "failed to open file %s for write\n", argv[2]);
+    clear_lockfile ();
+    exit (0);
+  }
+
+  average = catalog.average;
+  for (i = 0; i < catalog.Naverage; i++) {
+    fprintf (f, "%10.6f %10.6f %7.3f %3d %3d %8d %d\n", average[i].R, average[i].D, 
+	     0.001*average[i].M, average[i].Nm, average[i].Nn, average[i].offset, catalog.measure[average[i].offset].t);
+    if ((atof(argv[3]) == 1) || (atof(argv[3]) == 3)) {
+      measure = &catalog.measure[average[i].offset];
+      for (j = 0; j < average[i].Nm; j++) {
+	fprintf (f, "  %d %d %f %f %d\n", measure[j].dR, measure[j].dD, 0.001*measure[j].M, 
+		  measure[j].t, measure[j].average);
+      }
+    }
+    if ((atof(argv[3]) == 2) || (atof(argv[3]) == 3)) {
+      if (average[i].Nn > 0) {
+	missing = &catalog.missing[average[i].missing];
+	for (j = 0; j < average[i].Nn; j++) {
+	  fprintf (f, "  %f\n", missing[j].t);
+	}
+      } else { 
+	fprintf (f, "no missing obs\n");
+      }
+    }
+  }
+
+    
+
+  fclose (f);
+    
+
+}
Index: /tags/start/Ohana/src/markstar/src/old/find_bright_stars_test.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/old/find_bright_stars_test.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/old/find_bright_stars_test.c	(revision 12606)
@@ -0,0 +1,106 @@
+# include "markstar.h"
+
+find_bright_stars (catalog, catstats, filename)
+Catalog catalog[];
+CatStats catstats[];
+char *filename;
+{
+
+  int i, j, first_j, Nave, Ngsc;
+  Catalog GSCdata;
+  double MinRA, MinDEC, MaxRA, MaxDEC, RaCenter, DecCenter;
+  Coords *tcoords;
+  float *X1, *Y1, *X2, *Y2;
+  int *N1, *N2, *match;
+  char *mark;
+  double dX, dY, dR, RADIUS2, BRIGHT_RADIUS, radius;
+
+  load_gsc_data (&GSCdata, filename);
+
+  Nave = catalog[0].Naverage;
+  Ngsc = GSCdata.Naverage;
+    
+  X1 = catstats[0].X;
+  Y1 = catstats[0].Y;
+  N1 = catstats[0].N;
+  ALLOCATE (mark, char, Nave);
+  ALLOCATE (match, int, Nave);
+  ALLOCATE (X2, float, Ngsc);
+  ALLOCATE (Y2, float, Ngsc);
+  ALLOCATE (N2, int, Ngsc);
+  bzero (mark, Nave);
+
+  tcoords = &catstats[0].coords;
+  for (i = 0; i < Ngsc; i++) {
+    fRD_to_XY (&X2[i], &Y2[i], GSCdata.average[i].R, GSCdata.average[i].D, tcoords);
+    N2[i] = i;
+  }
+  if (Ngsc > 1) sort_lists (X2, Y2, N2, Ngsc);
+  
+  /* max radius (mag = -1) */
+  BRIGHT_RADIUS = BRIGHT_SLOPE * (-1.0 - BRIGHT_MAG);
+
+  /** find catalog stars near GSC stars **/
+  for (i = j = 0; (i < Nave) && (j < Ngsc); ) {
+    
+    dX = X1[i] - X2[j];
+
+    if (dX <= -2*BRIGHT_RADIUS) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*BRIGHT_RADIUS) {
+      j++;
+      continue;
+    }
+
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    for (; (dX > -2*BRIGHT_RADIUS) && (j < Ngsc); j++) {
+      radius = MAX (BRIGHT_SLOPE * (0.001*GSCdata.average[N2[j]].M - BRIGHT_MAG), 0.0);
+      RADIUS2 = radius*radius;
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < RADIUS2) {  /* new measurement of this star */
+	mark[i] = TRUE;
+	match[i] = N2[j];
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+  /* done with search, mark selected stars */
+  
+  for (i = 0; i < Nave; i++) {
+    if (mark[i]) {
+      catalog[0].average[N1[i]].code = ID_BLEED;
+    }
+  } 
+  
+}
+
+	/* for test purposes, like determining the parameters, uncomment this 
+	n = N1[i];
+	m = N2[j];
+	fprintf (stdout, "%f %f %f %f %f %f\n", 
+GSCdata.average[m].R, GSCdata.average[m].D, 
+		 0.001*GSCdata.average[m].M, 
+catalog[0].average[n].R, catalog[0].average[n].D, 0.001*catalog[0].average[n].M); */
+  
+  /* for test purposes, like determining the parameters, uncomment this 
+  clear_lockfile (); 
+  fprintf (stderr, "SUCCESS\n");
+  exit (0); */
+
+
+
+	n = N1[i];
+	m = N2[j];
+	RD_to_XY (&X, &Y, Ghostdata[0].average[m].R, Ghostdata[0].average[m].D, &image[0].coords);
+	fprintf (stdout, "%f %f %f %f %f %f %d %f %f\n",
+		 Ghostdata[0].average[m].R, Ghostdata[0].average[m].D, 
+		 0.001*Ghostdata[0].average[m].M, catalog[0].average[n].R, 
+		 catalog[0].average[n].D, 0.001*catalog[0].average[n].M, 
+		 catalog[0].average[n].Nm, X, Y);
Index: /tags/start/Ohana/src/markstar/src/old/gimages.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/old/gimages.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/old/gimages.c	(revision 12606)
@@ -0,0 +1,214 @@
+# include "addstar.h"
+double opening_angle ();
+
+Image *gimages (image, Npimage)
+Image image[];
+int *Npimage;
+{
+  
+  int i, j, k, NIMAGE, Nimage, addtolist;
+  int NTIMAGE, Ntimage, ntimage;
+  int NPIMAGE, npimage;
+  FILE *f;
+  Image *timage, *pimage;
+  Coords tcoords;
+  Header header;
+  double r, d;
+  double Xi[5], Yi[5], Xo[5], Yo[5];  /* image and original corners */
+
+  /* check if image datafile exists, get header */
+  if (!fits_read_header (ImageCat, &header)) {
+    if (VERBOSE) fprintf (stderr, "New image catalog %s (1)\n", ImageCat);
+    *Npimage = 0;
+    return ((Image *) NULL);
+  }
+
+  /* project onto rectilinear grid with 1 arcsec pixels */
+  /* we keep the original crpix1,2 and crref1,2 */
+  tcoords = image[0].coords;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1 = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2 = tcoords.pc2_1 = 0.0;
+  strcpy (tcoords.ctype, "RA---TAN");
+
+  /* define original corners */
+  Xo[0] = 0;           Yo[0] = 0;
+  Xo[1] = image[0].NX; Yo[1] = 0;
+  Xo[2] = image[0].NX; Yo[2] = image[0].NY;
+  Xo[3] = 0;           Yo[3] = image[0].NY;
+  Xo[4] = 0;           Yo[4] = 0;  /* so we can make a loop easily */
+  for (j = 0; j < 5; j++) {
+    XY_to_RD (&r, &d, Xo[j], Yo[j], &image[0].coords);
+    RD_to_XY (&Xo[j], &Yo[j], r, d, &tcoords);
+  }
+  
+  /* get ready to read data on images */ 
+  f = fopen (ImageCat, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "New image catalog: %s (2)\n", ImageCat);
+    free (header.buffer);
+    *Npimage = 0;
+    return ((Image *) NULL);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  Nimage = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+
+  NTIMAGE = 100;
+  ALLOCATE (timage, Image, NTIMAGE);
+
+  npimage = 0;
+  NPIMAGE = 20;
+  ALLOCATE (pimage, Image, NPIMAGE);
+
+  for (Ntimage = 0; Ntimage < Nimage; Ntimage += ntimage) {
+    ntimage = Fread (timage, sizeof(Image), NTIMAGE, f, "image");
+    for (i = 0; i < ntimage; i++) {
+      addtolist = FALSE;
+      /* define image corners */
+      Xi[0] = 0;            Yi[0] = 0;
+      Xi[1] = timage[i].NX; Yi[1] = 0;
+      Xi[2] = timage[i].NX; Yi[2] = timage[i].NY;
+      Xi[3] = 0;            Yi[3] = timage[i].NY;
+      Xi[4] = 0;            Yi[4] = 0;  /* so we can make a loop easily */
+      /* transform to tcoords */
+      for (j = 0; j < 5; j++) {
+	XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+	RD_to_XY (&Xi[j], &Yi[j], r, d, &tcoords);
+      }
+      /* check if any edges cross */
+      for (j = 0; j < 4; j++) {
+	for (k = 0; k < 4; k++) {
+	  addtolist |= edge_check (&Xi[j], &Yi[j], &Xo[k], &Yo[k]);
+	}
+      }
+      
+      /*
+      fprintf (stderr, "%f %f %f %d %f %f %d %d %d %f %f %s: %d\n", 0.1*timage[i].detection_limit, 0.1*timage[i].saturation_limit, 0.02*timage[i].cerror, 
+	       timage[i].tzero, 1e-4*timage[i].trate, 
+	       0.001*timage[i].secz, timage[i].nstar, timage[i].NX, timage[i].NY, 0.001*timage[i].Mcal, 0.1*timage[i].Xm, timage[i].name, addtolist);
+      
+      fprintf (stderr, "%s\n", timage[i].coords.ctype);
+      fprintf (stderr, "%f %f\n", timage[i].coords.crval1, timage[i].coords.crval2);
+      fprintf (stderr, "%f %f\n", timage[i].coords.crpix1, timage[i].coords.crpix2);
+      fprintf (stderr, "%f %f\n", timage[i].coords.pc1_1, timage[i].coords.pc1_2);
+      fprintf (stderr, "%f %f\n", timage[i].coords.pc2_1, timage[i].coords.pc2_2);
+      fprintf (stderr, "%f %f\n", timage[i].coords.cdelt1, timage[i].coords.cdelt2);      
+      */
+
+      if (addtolist) {
+	pimage[npimage] = timage[i];
+	npimage ++;
+	if (npimage == NPIMAGE) {
+	  NPIMAGE += 20;
+	  REALLOCATE (pimage, Image, NPIMAGE);
+	}
+      }
+    }
+
+    if (ntimage == 0) {
+      fprintf (stderr, "ERROR: expected %d images, only found %d\n", Nimage, Ntimage);
+      clear_lockfile ();
+      exit (0);
+    }
+  }
+
+  if (VERBOSE) fprintf (stderr, "found %d overlapping images\n", npimage);
+
+  fclose (f);
+  *Npimage = npimage;
+  return (pimage);
+
+}
+  
+int edge_check (x1, y1, x2, y2)
+double *x1, *y1, *x2, *y2;
+{
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+double opening_angle (x1, y1, x2, y2, x3, y3)
+double x1, y1, x2, y2, x3, y3;
+{
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
+
+
+
+
+/* probably not needed now 
+char *_parse_nextword();
+
+
+int fparse (X, NX, line)
+float *X;
+int NX;
+char *line;
+{
+
+  int i;
+  char *word;
+  char *ptr;
+
+  word = line;
+  for (i = 0; i < NX - 1; i++)
+    word = _parse_nextword (word);
+
+  *X = strtod (word, &ptr);
+  if (ptr == word)
+    return (FALSE);
+  else {
+    if (word[0] == '-') 
+      return (-1);
+    else
+      return (1);
+  }
+}
+
+*/
Index: /tags/start/Ohana/src/markstar/src/old/gstars.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/old/gstars.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/old/gstars.c	(revision 12606)
@@ -0,0 +1,186 @@
+# include "addstar.h"
+# define D_NSTARS 1000
+# define BYTES_STAR 31
+# define BLOCK 1000
+#include <sys/time.h>
+#include <time.h>
+
+Stars *gstars (file, NSTARS, image) 
+char file[];
+int *NSTARS;
+Image *image;
+{
+
+  FILE *f;
+  Header header;
+  int i, j, nstar;
+  int nbytes, Nbytes;
+  Stars *stars;
+  char *buffer, line[64], *c;
+  struct tm timeptr;
+  double tmp;
+
+  if (!fits_read_header (file, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s\n", file);
+    clear_lockfile ();
+    exit(0);
+  }
+
+  /* open file */
+  f = fopen (file, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find data file %s\n", file);
+    clear_lockfile ();
+    exit(0);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  c = strrchr (file, 0x2f);
+  if (c == (char *) NULL) {
+    strcpy (image[0].name, file);
+  } else { 
+    strcpy (image[0].name, (c+1));
+  }
+  /* get astrometry information */
+  strcpy (image[0].coords.ctype, "NONE");
+  fits_scan (&header, "CTYPE1",   "%s",  1, image[0].coords.ctype);
+  if (strcmp (image[0].coords.ctype, "RA---PLY")) {
+    fprintf (stderr, "ERROR: wrong astrometric info in header\n");
+    clear_lockfile ();
+    exit (0);
+  }
+  fits_scan (&header, "CDELT1",   "%f", 1, &image[0].coords.cdelt1); 
+  fits_scan (&header, "CDELT2",   "%f", 1, &image[0].coords.cdelt2);
+  fits_scan (&header, "CRVAL1",   "%lf", 1, &image[0].coords.crval1);
+  fits_scan (&header, "CRVAL2",   "%lf", 1, &image[0].coords.crval2);  
+  fits_scan (&header, "CRPIX1",   "%f", 1, &image[0].coords.crpix1);
+  fits_scan (&header, "CRPIX2",   "%f", 1, &image[0].coords.crpix2);
+  fits_scan (&header, "PC001001", "%f", 1, &image[0].coords.pc1_1);
+  fits_scan (&header, "PC001002", "%f", 1, &image[0].coords.pc1_2);
+  fits_scan (&header, "PC002001", "%f", 1, &image[0].coords.pc2_1);
+  fits_scan (&header, "PC002002", "%f", 1, &image[0].coords.pc2_2);
+  fits_scan (&header, "CERROR",   "%lf", 1, &tmp);
+  /* RA Terms */
+  fits_scan (&header, "PCA1X2Y0", "%f", 1, &image[0].coords.polyterms[0][0]);
+  fits_scan (&header, "PCA1X1Y1", "%f", 1, &image[0].coords.polyterms[1][0]);
+  fits_scan (&header, "PCA1X0Y2", "%f", 1, &image[0].coords.polyterms[2][0]);
+  fits_scan (&header, "PCA1X3Y0", "%f", 1, &image[0].coords.polyterms[3][0]);
+  fits_scan (&header, "PCA1X2Y1", "%f", 1, &image[0].coords.polyterms[4][0]);
+  fits_scan (&header, "PCA1X1Y2", "%f", 1, &image[0].coords.polyterms[5][0]);
+  fits_scan (&header, "PCA1X0Y3", "%f", 1, &image[0].coords.polyterms[6][0]);
+  /* Dec Terms */
+  fits_scan (&header, "PCA2X2Y0", "%f", 1, &image[0].coords.polyterms[0][1]);
+  fits_scan (&header, "PCA2X1Y1", "%f", 1, &image[0].coords.polyterms[1][1]);
+  fits_scan (&header, "PCA2X0Y2", "%f", 1, &image[0].coords.polyterms[2][1]);
+  fits_scan (&header, "PCA2X3Y0", "%f", 1, &image[0].coords.polyterms[3][1]);
+  fits_scan (&header, "PCA2X2Y1", "%f", 1, &image[0].coords.polyterms[4][1]);
+  fits_scan (&header, "PCA2X1Y2", "%f", 1, &image[0].coords.polyterms[5][1]);
+  fits_scan (&header, "PCA2X0Y3", "%f", 1, &image[0].coords.polyterms[6][1]);
+  image[0].coords.Npolyterms = 2; /* how many do we use? */
+  /* CERROR in data file is in pixels, convert to 20*arcsec */
+  image[0].cerror = tmp * 50.0 * image[0].coords.cdelt1 * 3600.0;
+  while (image[0].coords.crval1 < 0) image[0].coords.crval1 += 360.0;
+  while (image[0].coords.crval1 > 360.0) image[0].coords.crval1 -= 360.0;
+ 
+  fits_scan (&header, "NAXIS1",   "%hd", 1, &image[0].NX); 
+  fits_scan (&header, "NAXIS2",   "%hd", 1, &image[0].NY);
+  fits_scan (&header, "PHOTCODE", "%hd", 1, &image[0].source);
+  image[0].NX -= XOVERSCAN;
+  image[0].NY -= YOVERSCAN;
+
+  tmp = 0;
+  fits_scan (&header, "FLIMIT",   "%lf", 1, &tmp);
+  image[0].detection_limit = tmp * 10.0;
+
+  tmp = 0;
+  fits_scan (&header, "FSATUR",   "%lf", 1, &tmp);
+  image[0].saturation_limit = tmp * 10.0;
+
+  if (!fits_scan (&header, "TZERO",   "%d",  1, &image[0].tzero)) {
+    fits_scan (&header, "UT",   "%s",  1, line);
+    /* remove : characters */
+    for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (c, 0x3a))
+      *c = ' ';
+    sscanf (line, "%d %d %d", &timeptr.tm_hour, &timeptr.tm_min, &timeptr.tm_sec);
+    fits_scan (&header, "DATE-UT",   "%s",  1, line);
+    for (c = strchr (line, 0x2f); c != (char *) NULL; c = strchr (c, 0x2f))
+      *c = ' ';
+    sscanf (line, "%d %d %d", &timeptr.tm_year, &timeptr.tm_mon, &timeptr.tm_mday);
+    if (timeptr.tm_year < 90) { /* correct for year 2000 turnover */
+      timeptr.tm_year += 100;
+    }
+    image[0].tzero = mktime (&timeptr);
+  }
+
+  tmp = 0;
+  fits_scan (&header, "TRATE",   "%lf", 1, &tmp);
+  image[0].trate = 10000 * tmp;
+
+  tmp = 0;
+  fits_scan (&header, "AIRMASS", "%lf", 1, &tmp);
+  image[0].secz = 1000*tmp;
+
+  /* secz is in units milli-airmass */
+  image[0].Mcal =  ALPHA*(image[0].secz - 1000);
+  image[0].Xm   = 30.0;
+  image[0].code = 0;
+  bzero (image[0].dummy, sizeof(image[0].dummy));
+
+  /* find number of stars */
+  fits_scan (&header, "NSTARS", "%d", 1, &image[0].nstar);
+  if (image[0].nstar == 0) {
+    fprintf (stderr, "ERROR: can't get NSTARS from header\n");
+    clear_lockfile ();
+    exit (0);
+  }
+  ALLOCATE (stars, Stars, image[0].nstar);
+  Nbytes = image[0].nstar*BYTES_STAR;
+
+  /* load in stars by blocks of 1000 */
+  nstar = 0;
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR));
+  for (i = 0; i < (int)(Nbytes / (BLOCK*BYTES_STAR)); i++) {
+    nbytes = Fread (buffer, 1, (BLOCK*BYTES_STAR), f, "char");
+    if (nbytes != BLOCK*BYTES_STAR) {
+      fprintf (stderr, "ERROR: failed to read in stars (1)\n");
+      clear_lockfile ();
+      exit (0);
+    }
+    for (j = 0; j < BLOCK; j++, nstar++) {
+      dparse (&stars[nstar].X,  1, &buffer[j*BYTES_STAR]);
+      dparse (&stars[nstar].Y,  2, &buffer[j*BYTES_STAR]);
+      dparse (&stars[nstar].M,  3, &buffer[j*BYTES_STAR]);
+      dparse (&stars[nstar].dM, 4, &buffer[j*BYTES_STAR]);
+      XY_to_RD (&stars[nstar].R, &stars[nstar].D, stars[nstar].X, stars[nstar].Y, &image[0].coords);
+      stars[nstar].found = -1;
+    }
+  }
+  /* left over fraction of a block */
+  nbytes = Fread (buffer, 1, (Nbytes % (BLOCK*BYTES_STAR)), f, "char");
+  if (nbytes != (Nbytes % (BLOCK*BYTES_STAR))) {
+    fprintf (stderr, "ERROR: failed to read in stars (2)\n");
+    clear_lockfile ();
+    exit (0);
+  }
+  for (j = 0; j < nbytes / BYTES_STAR; j++, nstar++) {
+    dparse (&stars[nstar].X, 1, &buffer[j*BYTES_STAR]);
+    dparse (&stars[nstar].Y, 2, &buffer[j*BYTES_STAR]);
+    dparse (&stars[nstar].M, 3, &buffer[j*BYTES_STAR]);
+    dparse (&stars[nstar].dM, 4, &buffer[j*BYTES_STAR]);
+    XY_to_RD (&stars[nstar].R, &stars[nstar].D, stars[nstar].X, stars[nstar].Y, &image[0].coords);
+    stars[nstar].found = -1;
+  }
+
+  if (image[0].nstar != nstar) {
+    fprintf (stderr, "ERROR: failed to read in all stars (%d != %d)\n", image[0].nstar, nstar);
+    clear_lockfile ();
+    exit (0);
+  }
+  free (header.buffer);
+  free (buffer);
+ 
+  if (VERBOSE) fprintf (stderr, "read %d stars from target file\n", image[0].nstar);
+  *NSTARS = image[0].nstar;
+
+  return (stars);
+}
Index: /tags/start/Ohana/src/markstar/src/old/sort_lists.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/old/sort_lists.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/old/sort_lists.c	(revision 12606)
@@ -0,0 +1,48 @@
+
+sort_lists (X, Y, S, N) 
+float *X, *Y;
+int *S, N;
+{
+  int l,j,ir,i;
+  double tX, tY, tS;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    S[i] = tS;
+  }
+}
Index: /tags/start/Ohana/src/markstar/src/old/sort_stars.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/old/sort_stars.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/old/sort_stars.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include "relphot.h"
+
+void sort_stars (radec, stars, Nstars)
+int  **radec;
+Star  *stars;
+int    Nstars;
+{
+  
+  int i;
+  double *RAs;
+
+  ALLOCATE (radec[0], int, Nstars);
+  ALLOCATE (RAs, double, Nstars);
+  for (i = 0; i < Nstars; i++) {
+    radec[0][i] = i;
+    RAs[i] = stars[i].RA;
+  }
+
+  sort_seq (radec[0], RAs, Nstars);
+  free (RAs);
+
+}
+
+
+void sort_seq (seq, value, N) 
+int *seq;
+double *value;
+int N;
+{
+  int l,j,ir,i;
+  int temp;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      temp = seq[--l];
+    }
+    else {
+      temp = seq[ir];
+      seq[ir] = seq[0];
+      if (--ir == 0) {
+	seq[0] = temp;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && value[seq[j]] < value[seq[j+1]]) ++j;
+      if (value[temp] < value[seq[j]]) {
+	seq[i]=seq[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    seq[i] = temp;
+  }
+}
+
+
Index: /tags/start/Ohana/src/markstar/src/old/string.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/old/string.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/old/string.c	(revision 12606)
@@ -0,0 +1,64 @@
+# include <stdio.h>
+# include <math.h>
+# define TRUE  1
+# define FALSE 0
+
+int scan_line (f, line) 
+FILE *f;
+char line[];
+{
+
+  int i, status;
+  char c;
+  
+  status = EOF + 1;
+  
+  for (i = 0, c = 0; (c != '\n') && (status != EOF); i++) {
+    status = fscanf (f, "%c", &c);
+    line[i] = c;
+  }
+  line[i - 1] = 0;  /* this could make things crash! */
+
+  if (i > 1) {
+    status = EOF + 1;
+  }
+
+  return (status);
+
+}
+
+char *_parse_nextword(string)
+char *string;
+{
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (; isspace (*string); string++);
+  for (; (*string != 0) && !isspace (*string); string++);
+  for (; isspace (*string); string++);
+  return (string);
+}
+
+int dparse (X, NX, line)
+double *X;
+int NX;
+char *line;
+{
+
+  int i;
+  char *word;
+  char *ptr;
+
+  word = line;
+  for (i = 0; i < NX - 1; i++)
+    word = _parse_nextword (word);
+
+  *X = strtod (word, &ptr);
+  if (ptr == word)
+    return (FALSE);
+  else {
+    if (word[0] == '-') 
+      return (-1);
+    else
+      return (1);
+  }
+}
Index: /tags/start/Ohana/src/markstar/src/old/wimage.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/old/wimage.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/old/wimage.c	(revision 12606)
@@ -0,0 +1,67 @@
+# include "addstar.h"
+
+wimage (filename, image, Nstars)
+char *filename;
+Image image[];
+int Nstars;
+{
+  
+  int Nimages, status;
+  FILE *f;
+  Header header;
+
+  if (!fits_read_header (ImageCat, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't find %s, creating a new one\n", ImageCat);
+    if (!fits_read_header (ImageTemplate, &header)) {
+      fprintf (stderr, "ERROR: can't find template header %s\n", ImageTemplate);
+      clear_lockfile ();
+      exit (0);
+    }
+    f = fopen (ImageCat, "w");
+    if (f == NULL) {
+      fprintf (stderr, "ERROR: can't create/open image catalog file: %s\n", ImageCat);
+      clear_lockfile ();
+      exit (0);
+    }
+  }
+  
+  Nimages = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimages);
+  Nimages ++;
+  fits_modify (&header, "NIMAGES", "%d", 1, Nimages);
+
+  f = fopen (ImageCat, "r+");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't create/open image catalog file: %s\n", ImageCat);
+    clear_lockfile ();
+    exit (0);
+  }
+
+  /* position to begining of file to write header */
+  fseek (f, 0, SEEK_SET);
+  status = Fwrite (header.buffer, 1, header.size, f, "char");
+  if (status != header.size) {
+    fprintf (stderr, "ERRPR: failed writing data to image header\n");
+    clear_lockfile ();
+    exit (0);
+  }
+
+  fseek (f, 0, SEEK_END);
+  fprintf (stderr, "Image: %d\n", sizeof(Image));
+  status = Fwrite (image, sizeof(Image), 1, f, "image");
+  if (status != 1) {
+    fprintf (stderr, "ERRPR: failed writing data to image catalog\n");
+    clear_lockfile ();
+    exit (0);
+  }
+
+  fclose (f);
+  
+
+}
+
+/* the image we add in this routine is always a new image.  
+   We only need to do two things:
+     1) append the data for the image to the end of the file
+     2) update the NIMAGES field in the header (which means, read in header, re-write)
+ */
Index: /tags/start/Ohana/src/markstar/src/sorts.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/sorts.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/sorts.c	(revision 12606)
@@ -0,0 +1,175 @@
+
+
+sort_lists (X, Y, S, N) 
+float *X, *Y;
+int *S, N;
+{
+  int l,j,ir,i;
+  double tX, tY, tS;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    S[i] = tS;
+  }
+}
+
+sort_entries (X, Y, N) 
+     double *X, *Y;
+     int N;
+{
+  int l,j,ir,i;
+  double tX, tY;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+  }
+}
+
+
+
+sort (X, N) 
+     double *X;
+     int N;
+{
+  int l,j,ir,i;
+  double tX;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+  }
+}
+
+
+sort_seq (X, S, N) 
+     double *X;
+     int *S;
+     int N;
+{
+  int l,j,ir,i;
+  int tS;
+  double tX;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    S[i] = tS;
+  }
+}
+
Index: /tags/start/Ohana/src/markstar/src/wcatalog.c
===================================================================
--- /tags/start/Ohana/src/markstar/src/wcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/markstar/src/wcatalog.c	(revision 12606)
@@ -0,0 +1,41 @@
+# include "markstar.h"
+
+wcatalog (char *catname, Catalog *catalog) {
+  
+  int status;
+  char filename[256];
+
+  fits_modify (&catalog[0].header, "MARKSTAR", "%t", 1, TRUE);
+
+  sprintf (filename, "%s/%s\0", CATDIR, catname);
+  status = save_catalog (filename, catalog, VERBOSE);
+
+  if (catalog[0].Naverage) {
+    free (catalog[0].average); 
+    catalog[0].Naverage = 0;
+  }
+  if (catalog[0].Nmeasure) {
+    free (catalog[0].measure); 
+    catalog[0].Nmeasure = 0;
+  }
+  if (catalog[0].Nmissing) {
+    free (catalog[0].missing); 
+    catalog[0].Nmissing = 0;
+  }
+  if (catalog[0].Nsecfilt) {
+    free (catalog[0].secfilt); 
+    catalog[0].Nsecfilt = 0;
+  }
+
+  switch (status) {
+  case 0:
+    exit (0);
+  case 1:
+  case 2:
+    return (status);
+  default:
+    fprintf (stderr, "unknown exit status for save_catalog\n");
+    return (FALSE);
+  }
+}
+
Index: /tags/start/Ohana/src/misc/Makefile
===================================================================
--- /tags/start/Ohana/src/misc/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/misc/Makefile	(revision 12606)
@@ -0,0 +1,87 @@
+include ../../Configure
+HOME 	=	$(ROOT)/src/misc
+
+default: misc
+
+BIN	=	$(HOME)/bin
+LIB	= 	$(HOME)/lib
+SRC	=	$(HOME)/src
+INC	=	$(HOME)/include
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#  
+INCS	= 	-I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH) -Wunused
+LIBS	= 	-L$(LLIB) -lFITS -lohana -lm
+CFLAGS	=	
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+PROGRAMS = gconfig mknames fhead ftable fields list_astro glockfile \
+radec mktemp precess csystem fits_insert mkgauss \
+medianfilter mefhead mkfringetable gtfringetable ckfits applyscat fiximg
+
+CFHT = cfhtlog
+
+$(CFHT): 
+	make $(BIN)/$@.$(ARCH)
+
+$(PROGRAMS):
+	make $(BIN)/$@.$(ARCH)
+
+misc: $(PROGRAMS)
+
+clean:
+	for i in $(PROGRAMS); do make $$i.clean; done
+	rm -f */*~
+	rm -f */#*
+	rm -f *~
+	rm -f #*
+
+install:
+	for i in $(PROGRAMS); do make $$i.install; done
+
+# special rules for specific targets
+dbtest: src/dbtest.$(ARCH).o src/glockfile2.$(ARCH).o
+	$(CC) -o dbtest src/dbtest.$(ARCH).o src/glockfile2.$(ARCH).o $(LIBS) $(CCFLAGS)
+
+FAKESRC = $(SRC)/fakestars.$(ARCH).o $(SRC)/random.$(ARCH).o
+
+$(BIN)/fakestars.$(ARCH): $(FAKESRC)
+	$(CC) -o $(BIN)/fakestars.$(ARCH) $(FAKESRC) $(LIBS) $(CCFLAGS)
+
+fakestars: $(BIN)/fakestars.$(ARCH)
+	cp $(BIN)/fakestars.$(ARCH) $(DESTBIN)/fakestars
+
+$(BESTBIN)/cfhtlog: $(SRC)/cfhtlog.$(ARCH)
+	cp $(SRC)/cfhtlog.$(ARCH) $(DESTBIN)/
+
+cfhtlog: $(SRC)/cfhtlog.$(ARCH)
+$(SRC)/cfhtlog.$(ARCH): $(SRC)/cfhtlog.c
+	$(CC) -I/cfht/include -L/cfht/lib -o $(SRC)/cfhtlog.$(ARCH) $(SRC)/cfhtlog.c -lcfht 
+
+# RULES for making & installing
+
+%.$(ARCH).o : %.c
+	$(CC) $(INCS) -o $*.$(ARCH).o -c $< 
+
+$(SRC)/%.$(ARCH).o : %.c
+	$(CC) $(INCS) -o $*.$(ARCH).o -c $< 
+
+$(BIN)/%.$(ARCH) : $(SRC)/%.$(ARCH).o
+	echo $(CC)
+	$(CC) $^ -o $@ $(LIBS)
+	echo done building $@
+
+$(DESTBIN)/%: $(BIN)/%.$(ARCH)
+	rm -f $(DESTBIN)/$*
+	cp $(BIN)/$*.$(ARCH) $(DESTBIN)/$*
+
+%.install:
+	make $(DESTBIN)/$*
+
+%.clean:
+	rm -f $(SRC)/$*.$(ARCH).o
+	rm -f $(BIN)/$*.$(ARCH)
Index: /tags/start/Ohana/src/misc/include/cfht/cfht.h
===================================================================
--- /tags/start/Ohana/src/misc/include/cfht/cfht.h	(revision 12606)
+++ /tags/start/Ohana/src/misc/include/cfht/cfht.h	(revision 12606)
@@ -0,0 +1,793 @@
+/* Copyright (C) 1991-1999  Canada-France-Hawaii Telescope Corp.         */
+/* This program is distributed WITHOUT any warranty, and is under the    */
+/* terms of the GNU General Public License, see the file COPYING         */
+/*****************************************************************************
+ *
+ * file: cfht.h
+ * $Id: cfht.h,v 1.1.1.1 2004-11-24 04:39:33 eugene Exp $
+ * $Locker:  $
+ *
+ * This file is the main include file for the generic library.
+ *
+ *
+ * HISTORY
+ *
+ * who       when          what
+ * -------   -----------   ----------------------------------------------
+ * jab       27 Jan 1988   Original coding
+ * jab        1 Mar 1988   Added config file stuff
+ * jab       12 Mar 1988   Added logging stuff
+ * jk        22 Mar 1988   Added cfht_od()
+ * jk/jab    24 Mar 1988   Added CFHT_TAPE and CFHT_DISPLAY
+ * jab        6 Apr 1988   Added puma link device
+ * jab       29 Apr 1988   Added already included check
+ * sss       08 May 1988   Added CFHT_NPIPE
+ * jk        17 May 1988   Modified tape and display because of collision
+ * jk        06 Oct 1988   added cfht_resetetimer as a define
+ * sss       17 Mar 1989   added cfht_log() support stuffs
+ * sss       11 Apr 1989   added real time defines for detectors,etc.
+ * sss       24 Oct 1989   added CFHT_RELEASE define for .,config access
+ * sss        3 Jan 1990   added CFHT_*SESSIONHOST defines for env. vars
+ * jrw       01 Oct 1990   added stuff for cfht_number
+ * jrw       02 Nov 1990   added CFHT_STR_* defines
+ * jk        27 Feb 1991   cfht_exec unions not used anymore
+ * sss       27 Mar 1991   added cfht_basename()
+ * jrw       09 May 1991   added function definitions (ANSI and crufty flavors)
+ * jk        29 Aug 1991   changed cfht_errno from BOOLEAN to int
+ *
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1  2001/07/25 02:59:23  eugene
+ * import Ohana
+ *
+ * Revision 1.44  2000/04/10  11:28:40  isani
+ * Added prototype for cfht_log_proxy.
+ * 
+ * Revision 1.43  2000/02/10 13:19:08  isani
+ * Added include of sys/types.h whenever pid_t is needed.
+ *
+ * Revision 1.42  1999/12/02 21:40:30  thomas
+ * Added PFVint
+ *
+ * Revision 1.41  1999/07/25 06:29:57  thomas
+ * Added UTDATE/TIME and PFDATE defs
+ *
+ * Revision 1.40  1999/04/29 17:18:00  thomas
+ * Added @ ( # ) to RCSID string for what(1) to find
+ * Added non-gcc but STDC version of above
+ * Added changes for switch to /cfht
+ *
+ * Revision 1.39  99/02/17  13:55:15  13:55:15  thomas (Jim Thomas)
+ * Added cfht_cfhthome
+ * 
+ * Revision 1.38  98/12/11  18:23:20  18:23:20  thomas (Jim Thomas)
+ * Added CFHT_*OBSERVERPATH
+ * 
+ * Revision 1.37  98/10/22  17:52:44  17:52:44  thomas (Jim Thomas)
+ * Added CFHT_ESESSION
+ * 
+ * Revision 1.36  98/07/16  15:53:32  15:53:32  thomas (Jim Thomas)
+ * Added cfht_system
+ * 
+ * Revision 1.35  98/07/07  12:52:47  12:52:47  thomas (Jim Thomas)
+ * Added CFHTPATH , IOCONFDIR , and CONFDIR definitions
+ * 
+ * Revision 1.34  98/04/09  17:52:20  17:52:20  thomas (Jim Thomas)
+ * Added cfht_argsToString
+ * 
+ * Revision 1.33  98/02/25  16:35:00  16:35:00  thomas (Jim Thomas)
+ * Added prototype for cfht_logpv
+ * 
+ * Revision 1.32  97/12/09  00:11:48  00:11:48  healey (SueAnn Healey)
+ * added CFHT_LIBSSX
+ * 
+ * Revision 1.31  1997/12/01 16:03:29  isani
+ * Moved missing protos to separate file.
+ * Added extern "C" declarations for C++ projects.
+ *
+ * Revision 1.30  1997/09/17 13:48:31  thomas
+ * Added CFHT_EXEC_NOT_EXITED and CFHT_EXEC_FAILED
+ * Documented bogus use of FAIL in exp_controller_t
+ *
+ * Revision 1.29  97/06/29  15:41:07  15:41:07  isani (Sidik Isani)
+ * Had to fiddle with some of the includes to get to compile with GCC
+ *   on the sparc engines.
+ * 
+ * Revision 1.28  97/05/28  02:51:35  isani
+ * added CFHT_SIG_ defines for handler argument of cfht_signal()
+ * 
+ * Revision 1.27  97/04/07  20:10:26  thomas
+ * Added LIBOMS, changed cfht_signal event prototypes
+ * 
+ * Revision 1.26  96/11/22  02:36:44  02:36:44  isani (Sidik Isani)
+ * added macro for TEMP_FAILURE_RETRY, in case anyone wants to use it
+ * changed cfht_delay(n) into a macro that calls cfht_sleep(n,1)
+ * 
+ * Revision 1.25  96/11/19  22:24:19  isani
+ * moved P() and Q() macros closer to top of file
+ * added RCSID() macro
+ * define volatile to nothing on compilers where everything is volatile
+ * define UNUSED for use with gcc, or nothing on compilers that don't care
+ * added a few more missing libcfht prototypes
+ * concentrated most of the old-sun hacks here rather than in each file
+ *   (protos for getenv, putenv, different name for mktime, etc.)
+ * fixed order of arguments in cfht_fromjulian prototype
+ * 
+ * Revision 1.24  96/08/14  13:01:17  13:01:17  thomas (Jim Thomas)
+ * Added TCS_ConsolePrompt error return code
+ * 
+ * Revision 1.23  96/05/20  16:01:16  16:01:16  thomas (Jim Thomas)
+ * Added LIBCX, TCS_CommandFailed,
+ * Fixed F4 cfht_errno definitions
+ * 
+ * Revision 1.22  96/02/21  11:16:07  11:16:07  isani (Sidik Isani)
+ * cfht_errno codes for gecko and f4 server
+ * 
+ * Revision 1.21  1995/07/19 12:48:00  thomas
+ * Added AOB cfht_errno codes
+ *
+ * Revision 1.20  95/06/29  11:38:38  11:38:38  thomas (Jim Thomas)
+ * Added cfht_errno codes for IDS
+ * 
+ * Revision 1.19  95/06/13  12:03:06  12:03:06  thomas (Jim Thomas)
+ * Added environment variables and cfht_log_who entries for CS, DUCK, HELP,
+ * IDS, PIXD, TCS, and UI libraries
+ * 
+ * Revision 1.18  95/06/07  17:22:30  17:22:30  thomas (Jim Thomas)
+ * Added typedef for cfht_errno codes
+ * 
+ * Revision 1.17  94/12/28  17:06:51  17:06:51  thomas (Jim Thomas)
+ * Moved strerror definition for suns here from cfp.h (for cfht_logv)
+ * 
+ * Revision 1.16  94/12/21  10:35:46  10:35:46  john (John Kerr)
+ * add pid_t.
+ * 
+ * Revision 1.15  94/12/15  10:46:42  10:46:42  john (John Kerr)
+ * modified pid in cfht_exec_data to be a pid_t type.
+ * 
+ * Revision 1.14  94/12/14  10:50:01  10:50:01  thomas (Jim Thomas)
+ * Added CFHT_LIBMUSIC, CFHT_VALUE_SIZE, Q macro
+ * Deleted BYTE
+ * 
+ * Revision 1.13  94/09/20  18:40:45  18:40:45  thomas (Jim Thomas)
+ * added CFHT_LOGONLY, CFHT_LIBOCS
+ * reworked symbols related to cfht_log
+ * 
+ * Revision 1.12  94/08/14  10:27:17  10:27:17  jwright (Jim Wright)
+ * add warning log messages and color messages
+ * 
+ * Revision 1.11  94/07/11  15:48:53  15:48:53  veran (Jean-Pierre Veran)
+ * AAdded net logging capabilities
+ * 
+ * Revision 1.10  94/02/02  14:08:00  14:08:00  jwright (Jim Wright)
+ * remove typedef of FILE_ID form cfp.h and put it in cfht.h.  reason is
+ * that cfht_exec() has an argument of type FILE_ID and thus needs to have
+ * this type visible so that it can correctly declare an ANSI prototype.
+ * it is presumed that any file including cfp.h will first have included
+ * cfht.h.
+ * 
+ * Revision 1.9  94/01/20  20:35:13  20:35:13  jwright (Jim Wright)
+ * fix enum
+ * 
+ * Revision 1.8  94/01/20  04:51:31  04:51:31  jwright (Jim Wright)
+ * add enumeration for controller types
+ * 
+ * Revision 1.7  93/11/26  10:14:09  10:14:09  jwright (Jim Wright)
+ * added definitions to retrieve info from net.par
+ * 
+ * Revision 1.6  93/05/19  08:45:49  08:45:49  steve (Steven Smith)
+ * added cfht_logv TIMING define
+ * 
+ * Revision 1.5  93/02/16  16:21:15  16:21:15  john (John Kerr)
+ * added a CFHT_INSTRUMENT_TYPE
+ * 
+ * Revision 1.4  92/12/01  19:21:47  19:21:47  steve (Steven Smith)
+ * added CFHT_ELOGHOST for cfht_log() net based
+ * 
+ * Revision 1.3  92/11/09  13:11:03  13:11:03  john (John Kerr)
+ * added void cfht_goDaemon()
+ * 
+ * Revision 1.2  91/11/15  10:07:52  10:07:52  jwright (Jim Wright)
+ * add macro to handle both ansi and k&r style parameters
+ * in function declarations; convert declarations to use macro
+ * 
+ * Revision 1.1  91/09/24  15:59:31  15:59:31  steve (Steven S Smith)
+ * Initial revision
+ * 
+ ****************************************************************************/
+
+#ifndef CFHTDOTH
+#define CFHTDOTH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef pid_t
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#endif /* pid_t */
+
+/******************************************************************
+ * macro to declare prototypes for ansi, but still works with k&r *
+ *                                                                *
+ * define prototype like                                          *
+ *        int foo P((int a, char c))                              *
+ *                                                                *
+ * note that the space before the P and the doubled parentheses   *
+ *      are needed                                                *
+ ******************************************************************/
+
+#ifndef P
+#ifdef __STDC__
+#define P(args) args
+#else
+#define P(args) ()
+#endif
+#endif
+
+/********************************************************************
+ * macro to declare routine parameters for ansi that works with k&r *
+ *                                                                  *
+ * define actual routine like                                       *
+ *        int foo Q((int a, char c), (a, c), int a; char c;) {      *
+ *                                                                  *
+ * note that inner parentheses are needed on the ansi parameters    *
+ *                                 needed on the K&R parameters     *
+ *                             and must not be there on the K&R     *
+ *                                          type definition         *
+ *           there must be a space before the Q                     *
+ *           the arguments to Q can be on separate lines like       *
+ *                         int foo Q((int a, char c),               *
+ *                                   (a, c),                        *
+ *                                   int a; char c;)                *
+ *                         {                                        *
+ ********************************************************************/
+
+#ifndef Q
+#ifdef __STDC__
+#define Q(ansi, karparm, kartype) ansi
+#else
+#define Q(ansi, karparm, kartype) karparm kartype
+#endif
+#endif
+
+/*
+ * UNUSED attribute to tell Gnu compiler not to warn
+ * and define volatile to nothing for compilers where everything
+ * is volatile (We hope!)
+ */
+#ifdef __STDC__
+#ifdef __GNUC__
+#define UNUSED __attribute__ ((__unused__))
+#else
+#define UNUSED
+#endif
+#else
+#define UNUSED
+#define volatile
+#endif
+
+/*
+ * Macro to use for inserting rcs id's 
+ */
+
+#ifdef __LINT__
+#define RCSID(string) extern int lint_rcs_id_dummy
+#else
+#if defined(__GNUC__) && defined(__STDC__)
+#define RCSID(string) \
+  static const char rcs_id[] __attribute__ ((__unused__)) = "@(#) " string
+#else
+#if defined(__STDC__)
+#define RCSID(string) static char rcs_id[] = "@(#) " string
+#else
+#define RCSID(string) static char rcs_id[] = string
+#endif
+#endif
+#endif
+
+/*********************
+ * type definitions *
+ ********************/
+
+typedef int BOOLEAN;           /* should only contain TRUE, or FALSE */
+typedef double ANGLE;          /* floating pt. arc seconds */
+typedef double TIME;           /* floating pt. seconds */
+typedef double JDATE;          /* julian day number */
+typedef char *DATE;            /* ascii string date */
+typedef int PASSFAIL;          /* for functions that return PASS, or FAIL */
+typedef void (*PFV) P((void));   /* pointer to function that returns void */
+typedef void (*PFVint) P((int));   /*  ditto, with int parameter */
+typedef void (*PFVui) P((int,int,void*));  /* used for ui callbacks */
+typedef void (*PFVexec) P((pid_t,int));    /* used by cfht_exec() */
+
+enum exp_controller_t {       /* valid detector controller types */
+    FAIL = -1,			  /* NOTE - depends on define below :-( */
+    CONTROLLER_GENIII,
+    CONTROLLER_CC200,
+    CONTROLLER_FTS,
+    CONTROLLER_RETICON
+};
+
+typedef int FILE_ID;              /* used for parse file instance handles */
+
+/*************
+ * constants *
+ *************/
+
+#define PASS  0           /* function returning with no error */
+#define FAIL  -1          /* function returning an error in errno */
+			  /* lots of things depend on FAIL being negative!! */
+
+#define TRUE  1           /* 'C' boolean */
+#define FALSE 0           /* 'C' boolean */
+
+#ifndef NULL              /* make sure it's not already defined */
+#define NULL  0           /* used mostly for null string pointers */
+#endif  /* NULL */
+
+#define CFHTLOCKS  "/tmp/cfhtlocks"
+
+/********************
+ * real time defs   *
+ ********************/
+
+#define CFHT_RT_DETECTOR 65    /* about 1/2 */
+#define CFHT_RT_MOMMA    75    /* not as fast */
+#define CFHT_RT_HANDLER  85    /* slower yet */
+
+/********************
+ * exec definitions *
+ ********************/
+
+#define CFHT_EXEC_NUM    10    /* number of pending deaths allowed */
+#define CFHT_EXEC         1    /* straight exec */
+#define CFHT_EXECFG       2    /* wait and return exit code */
+#define CFHT_EXECBG       3    /* dont wait and dont ever bother me */
+#define CFHT_EXECBGC      4    /* dont wait but deposit exit code when ... */
+#define CFHT_EXECBGH      5    /* dont wait but call handler when ... */
+                               /* (handler is called with pid and exit code */
+#define CFHT_EXEC_NOT_EXITED -1 /* initial value of exit code */
+#define CFHT_EXEC_FAILED -2    /*  exit code if ran but failed to exit */
+/* #define CFHT_EXEC_EXITED (8 bits of system exit code) */ /* normal exit */
+
+#define CFHT_ARGV_NUM   100    /* size of cfht_argv() arg list */
+#define CFHT_ARGS_SIZE 1024    /* size of string to make args out of */
+#define CFHT_VALUE_SIZE 256    /* max length of a value (as in name=value) */
+
+union cfht_exec_addr {
+    volatile int *code;        /* exit code (-1 -> not yet exited) */
+    PFV func;                  /* handler to call */
+};
+
+struct cfht_exec_data {
+    volatile pid_t pid;        /* process id (0 -> unused) */
+    volatile int type;         /* CFHT_EXECBGC, or CFHT_EXECBGH (0 -> ignore) */
+    volatile void *addr;       /* union not used anymore */
+};
+
+extern int cfht_exec_rtprio;
+
+/*
+ * paths and file names
+ * CFHT_E* is the name in the environment, without the E is the actual value
+ * at the moment - so try not to use these (unfortunately that means programs
+ * don't work outside the session, sigh, so they appear in cfp_file.c and
+ * roll.c at least :-(
+ */
+/*
+ * The original path to everything started at /usr/local/cfht .  To get things
+ * out from under /usr/local , we created an automount collection for /cfht .
+ * To make things more consistent with other packages, we changed from
+ * /usr/local/cfht/dev to /cfht/src for the top of the source tree.  While
+ * both paths still exist, handle both possibilities here (and nowhere else in
+ * any c code please :-)
+ */
+#if defined(HPUX10) || defined(Solaris)
+#define CFHT_ECFHTPATH   "cfhtdir"			/* top of our tree */
+#define CFHT_CFHTPATH    "/cfht"			/*   which is */
+#define CFHT_CONFDIR     "src/conf"			/* dir for par files */
+#define CFHT_IOCONFDIR   "conf"				/*   except ioconfig */
+#define CFHT_ECONFPATH   "CFHTCONFPATH"			/* path to par files */
+#define CFHT_CONFPATH    "/cfht/src/conf"		/*   which is */
+#else
+#define CFHT_ECFHTPATH   "cfhtdir"			/* top of our tree */
+#define CFHT_CFHTPATH    "/usr/local/cfht"		/*   which is */
+#define CFHT_CONFDIR     "dev/conf"			/* dir for par files */
+#define CFHT_IOCONFDIR   "conf"				/*   except ioconfig */
+#define CFHT_ECONFPATH   "CFHTCONFPATH"                 /* path to par files */
+#define CFHT_CONFPATH    "/usr/local/cfht/dev/conf"     /*   which is */
+#endif /* HPUX10 or Solaris */
+#define CFHT_ECONFNAME   "CFHTCONFNAME"                 /* name for .,config */
+#define CFHT_CONFNAME    "config"                       /*   which is */
+#define CFHT_ESESSION    "Session"			/* master session name */
+#define CFHT_EOBSERVERPATH "observer"                   /* path to top of homes */
+#define CFHT_OBSERVERPATH "/users/observer"             /*   which is */
+
+/* identifiers within config file */
+#define CFHT_DETECTOR    "detector"                     /* e.g. th1 */
+#define CFHT_RELEASE     "release"                      /* e.g. 901231 */
+#define CFHT_INSTRUMENT  "instrument"                   /* 'who am i' */
+#define CFHT_INSTRUMENT_TYPE  "instrument_type"         /* e.g. FTS */
+#define CFHT_HANDLERS    "handlers"                     /* e.g. tcsh, ccdh */
+#define CFHT_FOCUS       "focus"                        /* e.g. prime */
+#define CFHT_DISPLAY     "display_guy"                  /* display handler */
+#define CFHT_TAPE        "tape_guy"                     /* tape handler */
+#define CFHT_SESSION     "session"                      /* e.g. ccd, focam */
+
+/*****************
+ * net.par stuff *
+ *****************/
+
+#define CFHT_CCDSERVER	"ccdserver"
+#define CFHT_F4SERVER	"f4server"
+#define CFHT_FOCAMSERVER "focamserver"
+#define CFHT_GENSERVER	"genserver"
+#define CFHT_LOGSERVER	"logserver"
+#define CFHT_RFSERVER	"rfserver"
+#define CFHT_TCSSERVER	"tcsserver"
+#define CFHT_TRAFFIC	"traffic"
+
+/**********************
+ * session host stuff *
+ **********************/
+
+#define CFHT_ESESSIONHOST    "SESSIONHOST"    /* used in xstart files */
+#define CFHT_SESSIONHOST     "moe"            /* perhaps hostname()? */
+
+/*****************
+ * logging stuff *
+ *****************/
+
+/* environment variables */
+
+/*
+ * The following are viewed as boolean flags.  For each, the indicated setting
+ * has the described effect (e.g., "setenv CFHTERROR off" will cause error
+ * messages not to appear in the feedback window), and the inverse setting or
+ * no setting has the opposite effect (e.g., otherwise error messages appear
+ * in the feedback window).
+ */
+#define CFHT_EERROR     "CFHTERROR"     /* Off -> no error messages to
+					 * feedback window */
+#define CFHT_EWARN      "CFHTWARN"      /* Off -> no warning messages to
+					 * feedback window */
+#define CFHT_ENODISP    "CFHTNODISP"    /* On -> no START/STATUS/DONE messages
+					 * to feedback window */
+#define CFHT_EDEBUG     "CFHTDEBUG"     /* On -> CFHT_MAIN debug messages to
+					 * log file */
+#define CFHT_ELIB       "CFHTLIB"       /* On -> unknown lib debug messages to
+					 * log file */
+#define CFHT_ELIBCAMAC  "CFHTLIBCAMAC"  /* On -> libcamac debug to log file */
+#define CFHT_ELIBCCD    "CFHTLIBCCD"    /* On -> libccd debug to log file */
+#define CFHT_ELIBCFHT   "CFHTLIBCFHT"   /* On -> libcfht debug to log file */
+#define CFHT_ELIBCFP    "CFHTLIBCFP"    /* On -> libcfp debug to log file */
+#define CFHT_ELIBCS     "CFHTLIBCS"     /* On -> libcs debug to log file */
+#define CFHT_ELIBCX     "CFHTLIBCX"     /* On -> libcx debug to log file */
+#define CFHT_ELIBDUCK   "CFHTLIBDUCK"   /* On -> libduck debug to log file */
+#define CFHT_ELIBFF     "CFHTLIBFF"     /* On -> libff debug to log file */
+#define CFHT_ELIBHELP   "CFHTLIBHELP"   /* On -> libhelp debug to log file */
+#define CFHT_ELIBHH     "CFHTLIBHH"     /* On -> libhh debug to log file */
+#define CFHT_ELIBIDS    "CFHTLIBIDS"    /* On -> libids debug to log file */
+#define CFHT_ELIBMUSIC  "CFHTLIBMUSIC"  /* On -> libmusic debug to log file */
+#define CFHT_ELIBOCS    "CFHTLIBOCS"    /* On -> libocs debug to log file */
+#define CFHT_ELIBOMS    "CFHTLIBOMS"    /* On -> liboms debug to log file */
+#define CFHT_ELIBPIXD   "CFHTLIBPIXD"   /* On -> libpixd debug to log file */
+#define CFHT_ELIBRET    "CFHTLIBRET"    /* On -> libret debug to log file */
+#define CFHT_ELIBRET    "CFHTLIBRET"    /* On -> libret debug to log file */
+#define CFHT_ELIBSSX    "CFHTLIBSSX"    /* On -> libssx debug to log file */
+#define CFHT_ELIBTCS    "CFHTLIBTCS"    /* On -> libtcs debug to log file */
+#define CFHT_ELIBUI     "CFHTLIBUI"     /* On -> libui debug to log file */
+
+#define CFHT_ECOLORLOG	"CFHTCOLORLOG" 	/* Off -> no color on user log */
+
+#define CFHT_LOGU       "CFHTLOGU"      /* user log messages file name */
+#define CFHT_LOGS       "CFHTLOGS"      /* system log messages file name */
+#define CFHT_ELOGHOST	"CFHTLOGHOST" 	/* host for netbased logging */
+
+/* who  (NOTE, should be alphabetized only at release time) */
+typedef enum {
+    CFHT_MAIN = 0,		  /* caller is end user */
+    CFHT_LIB,			  /* caller is undefined library */
+    CFHT_LIBCAMAC,		  /* caller is CAMAC library */
+    CFHT_LIBCCD,		  /* caller is ccd library */
+    CFHT_LIBCFHT,		  /* caller is CFHT library */
+    CFHT_LIBCFP,		  /* caller is CFP library */
+    CFHT_LIBFF,			  /* caller is FITS library */
+    CFHT_LIBHH,			  /* caller is high level HPIB library */
+    CFHT_LIBMUSIC,		  /* caller is music library */
+    CFHT_LIBOCS,		  /* caller is OCS library */
+    CFHT_LIBRET,		  /* caller is reticon library */
+    CFHT_LIBCS,			  /* caller is client/server library */
+    CFHT_LIBDUCK,		  /* caller is DUCK library */
+    CFHT_LIBHELP,		  /* caller is Pegasus help library */
+    CFHT_LIBIDS,		  /* caller is IDS communication library */
+    CFHT_LIBPIXD,		  /* caller is pixel library */
+    CFHT_LIBTCS,		  /* caller is Telescope Control System */
+    CFHT_LIBUI,			  /* caller is user interface library */
+    CFHT_LIBCX,			  /* caller is coordinate transform library */
+    CFHT_LIBOMS,		  /* caller is OMS library */
+    CFHT_LIBSSX			  /* caller is ssx controller library */
+} cfht_log_who;
+
+/* type */
+typedef enum {
+    CFHT_LOG_ID = 0,		  /* client side initialization msg type */
+    CFHT_START,			  /* program is starting */
+    CFHT_STATUS,		  /* something interesting to the user */
+    CFHT_ERROR,			  /* error */
+    CFHT_FATAL = CFHT_ERROR,	  /* obsolete - about to exit due to error */
+    CFHT_ERRNO,			  /* do not use - error with errno message */
+    CFHT_WARN,			  /* warning - something's wrong */
+    CFHT_DONE,			  /* about to exit normally */
+    CFHT_LOGONLY,		  /* operational diagnositc info */
+    CFHT_DEBUG,			  /* program trace info */
+    CFHT_TIMING,		  /* print elapsed + delta times */
+    CFHT_FEEDINIT,		  /* init a feedback type output sink */
+    CFHT_FEEDQUIT,		  /* free up fd's, etc for feedback sinks */
+    CFHT_ROLLINIT,		  /* start up another roll type output sink */
+    CFHT_ROLLQUIT,		  /* shut down roll type output sinks */
+    CFHT_SHOWSINKS,		  /* used by developer to debug...  */
+    CFHT_SERVINIT		  /* re-init da logserver without killing it */
+} cfht_log_type;
+
+#define CFHT_DATE_SIZE 29	  /* size needed for cfht_date result */
+#define CFHT_UTDATE_SIZE 11	  /* size needed for cfht_UTdate result */
+#define CFHT_PFDATE_SIZE 11	  /* size needed for cfht_PFdate result */
+#define CFHT_TIME_SIZE 12	  /* size needed for cfht_time result */
+#define CFHT_UTTIME_SIZE 12	  /* size needed for cfhtUTtime result */
+
+/***********************
+ * parsing definitions *
+ ***********************/
+
+#define CFHT_STR_MATCH     1  /* check if input matches one of set of strings */
+#define CFHT_STR_INCLUDE   2  /* only pass through characters mentioned */
+#define CFHT_STR_EXCLUDE   3  /* only pass through characters not mentioned */
+#define CFHT_STR_NOWHITE   4  /* remove all white space from string */
+#define CFHT_STR_NOTRAIL   5  /* remove all trailing white space */
+#define CFHT_STR_ESCAPE    6  /* convert non-printing chars to escape codes */
+#define CFHT_STR_UNESCAPE  7  /* convert escape codes to chars */
+
+/**************************
+ * cfht_errno definitions *
+ **************************/
+
+typedef enum {
+    /* general error numbers */
+    CHECK_ERRNO = -1,		  /* check unix(tm) errno variable for reason */
+
+    /* unfortunately, some code stuffs errno into cfht_errno (e.g., old libids) */
+    /* so we need to use 0 but skip all low positive values */
+
+    NO_ERROR = 0,		  /* success */
+    NOT_A_TTY = 1000,		  /* historical uses, and general laziness */
+    PARSE_FAILED,		  /* unable to cope with input */
+    TOO_BIG,			  /* input exceeds hardware limit */
+    OUT_OF_RANGE,		  /* input exceeds software restriction */
+    TYPE_ERROR,			  /* incompatible or unexpected type */
+    UNIMPLEMENTED,		  /* feature not yet implemented */
+    BAD_OPTION,			  /* option passed in to routine was invalid */
+    INVALID_RANGE,		  /* range structure malformed or illegal */
+
+    /* OCS error codes */
+
+    OCS_FAILURE = 1100,		  /* internal OCS problem, e.g., buffers*/
+    OCS_NoSuchServer,		  /* requested non-existent server name */
+    OCS_SERVER_BUSY,		  /* couldn't get server's attention */
+    OCS_SERVER_T_REJECTED,	  /* task rejected by the server */
+    OCS_SERVER_T_FAILED,	  /* task didn't complete successfully */
+    OCS_NOTIFYCLOSED,		  /* server quit during transactions */
+    OCS_SERVER_TIMEOUT,		  /* server time-out on request */
+    OCS_ERROR,			  /* catchall */
+
+    /* OCS stuffs music's merrno in, so those should be here too */
+
+    M_NOSTART = 1200,		  /* did not call mstart() */
+    M_BODYTOOBIG,		  /* body overflow */
+    M_WRITERR,			  /* system error during write */
+    M_PARTWRITE,		  /* wrote partial message */
+    M_READERR,			  /* system error during read */
+    M_READCLOSED,		  /* read a closed fd */
+    M_BODYTOOSHORT,		  /* not enough in body for mget() */
+    M_BADMAGIC,			  /* bad magic numbers in header */
+    M_TIMEOUT,			  /* mread_until() timed-out */
+    M_NOQMSG,			  /* nothing to read on msg queue */
+
+    /* ids error codes */
+    IDS_openError = 1300,	  /* problem opening terminal */
+    IDS_termioError,		  /* problem doing termio ioctl */
+    IDS_FlushError,		  /* problem flushing buffer */
+    IDS_writeError,		  /* problem on write */
+    IDS_TimeOut,		  /* no response */
+    IDS_read0Bytes,		  /* read got nothing */
+    IDS_readError,		  /* read failed - not time out */
+
+    /* Client/Server codes */
+    CS_FakeMode = 1400,		  /* server is in fake mode */
+    CS_Disabled,		  /* server is disabled */
+
+    /* TCS error return codes */
+    TCS_InvalidCommand = 1500,	  /* invalid command sent to TCS */
+    TCS_InvalidArgument,	  /* invalid command argument sent to TCS */
+    TCS_NotTracking,		  /* TCS ignored command 'cause it's not on */
+    TCS_CommandFailed,		  /* TCS did command, but it did not work */
+    TCS_ConsolePrompt,		  /* TCS command prompt is probably up */
+    TCS_UnknownStatus,		  /* we don't understand returned code */
+
+    /* AOB error return codes */
+    AOB_UnknownCommand = 1600,	  /* we do not understand the command */
+    AOB_UnlockNotLocked,	  /* unlock when not locked */
+    AOB_NotLockOwner,		  /* unlock attempt by someone else? */
+    AOB_CurrentlyLocked,	  /* OMBA locked by another process */
+    AOB_BadArgValue,		  /* some argument was bad */
+
+    /* Coude f/4 and Gecko server conditions */
+    F4_UnknownCommand = 1700,	  /* empty / badly formed command */
+    F4_UnlockNotLocked,		  /* (NYI) already unlocked */
+    F4_NotLockOwner,		  /* (NYI) not server lock owner */
+    F4_CurrentlyLocked,		  /* (NYI) server locked by another process */
+    F4_BadArgValue,		  /* (NYI) server got bad argument */
+    F4_NotInitialized,		  /* no answer from the instrument hardware */
+    F4_TrafficError,		  /* server had trouble with ocs */
+    F4_DuckCommandError,	  /* problem sending to duck */
+    F4_DuckResponseError,	  /* problem with duck response */
+
+    cfht_errno_codes_filler	  /* ending dummy entry with no comma */
+} cfht_errno_CodesType;
+
+/*************************
+ * structure definitions *
+ *************************/
+
+struct cfht_rng_double {
+    double min;
+    double max;
+    BOOLEAN min_inclusive;
+    BOOLEAN max_inclusive;
+};
+struct cfht_rng_int {
+    int min;
+    int max;
+    BOOLEAN min_inclusive;
+    BOOLEAN max_inclusive;
+};
+struct cfht_rng_string {
+    char **string_array;
+};
+struct cfht_rng_char {
+    char *list_of_chars;
+};
+union cfht_ranges {
+    struct cfht_rng_double cfht_double_range;
+    struct cfht_rng_int cfht_int_range;
+    struct cfht_rng_string cfht_string_range;
+    struct cfht_rng_char cfht_char_range;
+};
+
+typedef union cfht_ranges *cfht_range_t;
+
+/*********************
+ * global references *
+ *********************/
+
+extern BOOLEAN cfht_debug;
+extern BOOLEAN cfht_error;
+extern BOOLEAN cfht_lib;
+extern BOOLEAN cfht_nodisp;
+extern int cfht_errno;
+
+extern union cfht_ranges *CFHT_RNG_RA;
+extern union cfht_ranges *CFHT_RNG_DEC;
+
+#define cfht_resetetimer() cfht_etimer(TRUE)
+#define cfht_delay(millisec) (void)cfht_sleep((millisec),1)
+
+/*
+ * Macro to put around system calls that might be interrupted by a signal.
+ * This is ripped from glibc.  It will keep re-trying systems calls until
+ * at least a partial success, or fatal error is encountered.  Note that
+ * read might still return FEWER BYTES than you told it to read if it is
+ * interrupted!
+ */
+#ifndef TEMP_FAILURE_RETRY
+#define TEMP_FAILURE_RETRY(expression)               \
+({ long int __result;                                \
+     do __result = (long int) (expression);          \
+     while (__result == -1L && errno == EINTR);      \
+     __result; })
+#endif
+
+/*
+ * Special values that can be passed to cfht_signal()'s arg2
+ */
+
+#include <signal.h> /* for SIG_DFL and SIG_IGN */
+
+#define CFHT_SIG_TRAP ((PFV)cfht_signal_handler)
+  /* %%% The protos for CFHT_SIG_DFL et al are defined in terms of
+   *     SIG_DFL et al defined in signal.h, but unfortunately these
+   *     are not properly prototyped either :-(  Overriding them here
+   *     is kind of dangerous, and should be checked carefully.
+   */
+#undef  CFHT_SIG_DFL
+#undef  CFHT_SIG_IGN
+#define CFHT_SIG_DFL ((PFV)(0))
+#define CFHT_SIG_IGN ((PFV)(1))
+/*
+#define CFHT_SIG_DFL  ((PFV)SIG_DFL)
+#define CFHT_SIG_IGN  ((PFV)SIG_IGN)
+*/
+
+/*********************************************
+ * complete (?) list of all cfht_* functions *
+ *********************************************/
+
+char    *cfht_argsToString P((int argc, char *argv[]));
+void	cfht_awake P((double when_from_now, double how_often));
+char	*cfht_basename P((char *dest, char *filename, char *suffix));
+char	*cfht_cfhthome P((void));
+char	*cfht_date P((long *clockp));
+char	*cfht_PFdate P((int  days));
+char	*cfht_UTdate P((long *clockp));
+char	*cfht_UTtime P((long *clockp));
+char	*cfht_doupper P((char *str));
+double	cfht_dtime P((void));
+char	*cfht_fre P((unsigned char *src, unsigned char *dest, int *dsize));
+char	*cfht_toe P((unsigned char *src, unsigned char *dest, int ssize));
+double	cfht_etimer P((BOOLEAN reset));
+void	cfht_signal P((int signo, PFV handler));
+void	cfht_signal_block P((int signo));
+void	cfht_signal_unblock P((int signo));
+void    cfht_signal_handler P((int));
+BOOLEAN	cfht_signal_event P((int signo));
+BOOLEAN	cfht_signal_peek P((int signo));
+int	cfht_exec P((FILE_ID id, char *string, int type, volatile void *addr));
+int	cfht_system P((char *string));
+char	*cfht_frs P((char *dest, double val, int scale, int prec));
+void	cfht_genh P((int argc, char **argv, char **envp));
+void	usage P((char **msg));
+void	getcurdeath P((char *what));
+double	cfht_julian P((int year, int month, int day, int hour, int minute, double sec));
+void    cfht_fromjulian P((double jd, int *year, int *month, int *day, int *hour, int *minute, double *sec));
+char	*cfht_Mjulian P((long *clockp));
+char	*cfht_LocalSidTime P((long *clockp));
+BOOLEAN	cfht_checksem P((int semid));
+int	cfht_initsem P((char *path, char id));
+PASSFAIL cfht_setsem P((int semid));
+PASSFAIL cfht_setsemwait P((int semid, BOOLEAN sigign));
+PASSFAIL cfht_relsem P((int semid));
+PASSFAIL cfht_waitsemrel P((int semid, BOOLEAN sigign));
+PASSFAIL cfht_waitsemset P((int semid, BOOLEAN sigign));
+BOOLEAN cfht_checklock P((int fd));
+int	cfht_initlock P((char *path, char id));
+PASSFAIL cfht_setlock P((int fd));
+PASSFAIL cfht_setlockwait P((int fd, BOOLEAN sigign));
+PASSFAIL cfht_rellock P((int fd));
+PASSFAIL cfht_waitlockrel P((int fd, BOOLEAN sigign));
+PASSFAIL cfht_waitlockset P((int fd, BOOLEAN sigign));
+void	cfht_logv P((int who, int type, char *fmt, ...));
+void	cfht_logpv P((int who, int type, char *fmt, ...));
+void	cfht_log P((int who, int type, char *mess));
+void	cfht_log_proxy P((int who, int type, char *mess, char* id, int pid));
+PASSFAIL cfht_int P((char *in_str, int *out_addr, cfht_range_t rangeinfo));
+PASSFAIL cfht_double P((char *in_str, double *out_addr, cfht_range_t rangeinfo));
+long	cfht_od P((void));
+int	cfht_sleep P((int msec, int igsig));
+char	*cfht_string P((char *in_str, int operation, cfht_range_t rangeinfo));
+char	*cfht_time P((long *clockp));
+BOOLEAN	cfht_tob P((char *string));
+char	*cfht_tok P((char *string, char *sep, char **tail));
+void	cfht_goDaemon P((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * See comments in missing_protos.h
+ */
+#include <missing_protos.h>
+
+#endif /* CFHTDOTH */
Index: /tags/start/Ohana/src/misc/include/cfht/exits.h
===================================================================
--- /tags/start/Ohana/src/misc/include/cfht/exits.h	(revision 12606)
+++ /tags/start/Ohana/src/misc/include/cfht/exits.h	(revision 12606)
@@ -0,0 +1,61 @@
+/* Copyright (C) 1991, 94, 96    Canada-France-Hawaii Telescope Corp.    */
+/* This program is distributed WITHOUT any warranty, and is under the    */
+/* terms of the GNU General Public License, see the file COPYING    */
+/*****************************************************************************
+ *
+ * file: exits.h
+ * $Header: /cvsroot/pan-starrs/datasys/IPP/Ohana/src/misc/include/cfht/exits.h,v 1.1.1.1 2004-11-24 04:39:33 eugene Exp $
+ * $Locker:  $
+ *
+ * This file defines the various exit codes for controllers and handlers.
+ *
+ * NOTE: please see ui/listexits.c also when you change this !!!!!!!!!
+ *       The values of these exit codes are available symbolically in
+ *       shell scripts by using ". setexits".
+ *
+ * HISTORY
+ *
+ * who       when           what
+ * ------    -----------    ----------------------------------------------
+ * jk        24 Mar 1988    Original
+ *
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1  2001/07/25 02:59:24  eugene
+ * import Ohana
+ *
+ * Revision 1.4  96/08/12  15:30:00  15:30:00  thomas (Jim Thomas)
+ * Added AOB exit codes and some comments
+ * 
+ * Revision 1.3  94/12/14  17:27:07  17:27:07  thomas (Jim Thomas)
+ * Added pinger exit codes
+ * 
+ * Revision 1.2  93/06/26  17:59:06  17:59:06  steve (Steven Smith)
+ * added define for environment var to pass exit code of data taking handlers
+ * (ccdh, etc) for passing to all interested -E handlers.
+ * 
+ * Revision 1.1  91/09/24  17:38:54  17:38:54  steve (Steven Smith)
+ * Original checkin
+ * 
+ *****************************************************************************/
+
+#define EXIT_ENV_NAME	"CFHT_EXPOSURE_EXIT"
+#define EXIT_PASS 0		  /* everything is OK */
+#define EXIT_FAIL 1		  /* there was a real problem */
+#define EXIT_EXP_IN_PROGRESS 2	  /* can't do request - exposure already on */
+#define EXIT_EXP_ABORTED 3	  /* exposure trashed by user */
+#define EXIT_EXP_STOPPED 4	  /* exposure stopped by user */
+#define EXIT_CANCEL 5		  /* they hit the cancel button */
+
+/* pinger exit codes */
+#define PNG_EXIT_PASS EXIT_PASS	  /* service is healthy */
+#define PNG_EXIT_BUSY 1		  /* service is busy */
+#define PNG_EXIT_FAKE 2		  /* service is there but in FAKE mode */
+#define PNG_EXIT_NOTTHERE 3	  /* service isn't there at all */
+#define PNG_EXIT_NOTRAFFIC 4	  /* traffic isn't there */
+#define PNG_EXIT_ERROR 5	  /* some program or argument error happened */
+#define PNG_EXIT_HELP 6		  /* typed out the help message */
+
+/* AOB exit codes */
+#define AOB_EXIT_PASS EXIT_PASS	  /* things OK */
+#define AOB_EXIT_FAIL EXIT_FAIL	  /* real problem */
+#define AOB_EXIT_SEPARATION 2	  /* guide and object too far apart */
Index: /tags/start/Ohana/src/misc/include/missing_protos.h
===================================================================
--- /tags/start/Ohana/src/misc/include/missing_protos.h	(revision 12606)
+++ /tags/start/Ohana/src/misc/include/missing_protos.h	(revision 12606)
@@ -0,0 +1,303 @@
+/* Copyright (C) 1997-1999  Canada-France-Hawaii Telescope Corp.         */
+/* This program is distributed WITHOUT any warranty, and is under the    */
+/* terms of the GNU General Public License, see the file COPYING         */
+/*****************************************************************************
+ *
+ * missing_protos.h - ANSI prototypes for systems that lack complete ANSI
+ *                    system header files (especially SunOS 4.x).  This file
+ *                    should be included with `#include <missing_protos.h>'
+ *                    from "cfht/cfht.h" so that it does not show up in
+ *                    the dependencies generated by "gcc -MM".  Proper ANSI
+ *                    systems should not need anything from this file anyway,
+ *                    and thus will not be tempted to re-compile everything
+ *                    which depends on this file every time we need to add
+ *                    a new prototype for the SunOS machines.
+ * $Id: missing_protos.h,v 1.1.1.1 2004-11-24 04:39:33 eugene Exp $
+ * $Locker:  $
+ *
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1  2001/07/25 02:59:23  eugene
+ * import Ohana
+ *
+ * Revision 1.11  2000/02/10 13:52:23  isani
+ * Added a few more prototypes.
+ * Changed to new way of doing SELECT() call.
+ *
+ * Revision 1.10  1999/07/30 22:14:51  thomas
+ * HP added openlog/syslog in 10.X, if it out there
+ *
+ * Revision 1.9  1999/07/13 21:27:28  thomas
+ * Added WCOREDUMP for SunOS
+ *
+ * Revision 1.8  1999/07/13 00:17:24  thomas
+ * Fix 1.7, Sidik's model was not sufficient, plus GNU rcs would not let me
+ * cancel it ???
+ *
+ * Revision 1.7  1999/07/03 04:10:58  thomas
+ * Changed select for 10.20
+ *
+ * Revision 1.6  98/07/10  10:38:35  10:38:35  thomas (Jim Thomas)
+ * Added perror, strerror, memset, drand48 to SunOS prototypes
+ * 
+ * Revision 1.5  97/12/18  21:28:43  21:28:43  thomas (Jim Thomas)
+ * Put floatingpoint.h back in, added strtol, changed __STDC__ to __GNUC__
+ * 
+ * Revision 1.4  97/12/18  02:38:20  02:38:20  isani (Sidik Isani)
+ * Added redefinition of CFHT_SIG_{DFL,IGN} for SunOS
+ * 
+ * Revision 1.3  1997/12/05 20:49:44  thomas
+ * Added definition of const if not ANSI C
+ *
+ * Revision 1.2  97/12/05  20:20:44  20:20:44  jcc (Jean-Charles Cuillandre)
+ * Added include of resource.h
+ * 
+ * Revision 1.1  1997/11/23 11:29:04  isani
+ * Initial revision
+ *
+ ****************************************************************************/
+
+#ifndef _INCLUDED_missing_protos
+#define _INCLUDED_missing_protos 1
+
+/*
+ * Make.Common defines *one* of the following:
+ *             SUNOS, SOLARIS, HPUX, LINUX, VXWORKS, or CYGWIN32
+ * We will use these here, but for projects where Make.Include is used
+ * instead of Make.Common, check for some other predefined symbols like
+ * __sun__ to try to figure out the system type.
+ */
+
+#if defined(SunOS) && !defined(SUNOS)
+#define SUNOS
+#endif
+
+#if (defined(Linux) || defined(linux)) && !defined(LINUX)
+#define LINUX
+#endif
+
+/*
+ * First, make sure SUNOS didn't get defined by accident for a Solaris box.
+ * We use SOLARIS instead, because they are really different OS's.
+ */
+
+#if defined(SUNOS) && defined(__svr4__)
+#undef SUNOS
+#ifndef SOLARIS
+#define SOLARIS
+#endif
+#endif
+
+#if !defined(SUNOS) && !defined(SOLARIS) && !defined(HPUX) && !defined(LINUX) && !defined(CYGWIN32) && !defined(VXWORKS)
+/*
+ * If Make.Common isn't being used ...
+ */
+#if defined(__sun__) || defined(sun)
+#ifndef sun
+#define sun
+#endif
+#ifdef __svr4__
+#define SOLARIS
+#else
+#define SUNOS
+#endif
+#else
+#if defined(__hpux__) || defined(hpux)
+#ifndef hpux
+#define hpux
+#endif
+#define HPUX
+#else
+error: Unknown system type!
+error: This software has not been tested on this platform.
+error: (comment out this block to compile anyway).
+#endif /* __hpux__ */
+#endif /* __sun__ */
+#endif /* !SUNOS && !SOLARIS && !HPUX ... */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* "const" has been added to a bunch of definitions, but that is ANSI :-( */
+#ifndef __STDC__
+#define const
+#endif
+
+/*
+ * Here are the hacks for the old suns, so we don't have to include them
+ * in each source file.  Solaris 2.x does not need any of this stuff...
+ */
+
+#ifdef SUNOS
+#define mktime timelocal
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+#ifndef WCOREDUMP
+#define WCOREDUMP(n) 0
+#endif
+#include <malloc.h>
+#include <unistd.h>
+#ifdef __GNUC__
+#include <float.h>             /* for DBL_MIN and DBL_MAX */
+#else
+#include <values.h>
+#ifndef DBL_MIN
+#define DBL_MIN MINDOUBLE
+#define DBL_MAX MAXDOUBLE
+#endif
+#endif /* !__GNUC__ */
+#ifdef __GNUC__
+void    perror(const char *s);
+char	*strerror(int);
+int     ioctl(int, int, ...);
+int     select(int, fd_set*, fd_set*, fd_set*, struct timeval*);
+/* bzero is not ANSI, but the FD_ macros for select need it, so we need a
+ * proto here to prevent warnings.  Use memset() in your own code instead!
+ */
+void    bzero(char*, int);
+void*   memset(void*, int, size_t);
+int     socket(int, int, int);
+int     bind(int,  struct sockaddr*, int);
+int     listen(int, int);
+int     connect(int, struct sockaddr*, int);
+int     accept(int, struct sockaddr*, int*);
+int     shutdown(int, int);
+int     getsockname(int,struct sockaddr*,int*);
+int     getpeername(int,struct sockaddr*,int*);
+int     setsockopt(int,int,int,const void*,int);
+int     socketpair(int,int,int,int [2]);
+int     getrlimit(int,struct rlimit*);
+int     setrlimit(int,const struct rlimit*);
+int     gettimeofday(struct timeval *tp, struct timezone *tzp);
+int     rename(const char*, const char*);
+int     symlink(const char*, const char*);
+int     readlink(const char*, char*, int);
+int     lstat(const char*, struct stat*);
+int     openlog(const char*, int, int);
+int     syslog(int, const char*, ...);
+int     getitimer(int, struct itimerval*);
+int     setitimer(int, const struct itimerval*, struct itimerval*);
+int	fchmod(int, int);
+int	getdtablesize(void);
+int	semop(int, struct sembuf*, unsigned int);
+key_t	ftok(const char *, int);
+int	semget(key_t, int, int);
+int	lockf(int, int, off_t);
+int	ftruncate(int, off_t);
+/* %%% The protos for CFHT_SIG_DFL et al are defined in terms of
+ *     SIG_DFL et al defined in signal.h, but unfortunately these
+ *     are not properly prototyped either :-(  Overriding them here
+ *     is kind of dangerous, and should be checked carefully.
+ */
+#undef  CFHT_SIG_DFL
+#undef  CFHT_SIG_IGN
+#define CFHT_SIG_DFL ((PFV)(0))
+#define CFHT_SIG_IGN ((PFV)(1))
+#else  /* not __GNUC__ */
+#include <floatingpoint.h>
+void perror();
+char *strerror();
+void *memset();
+double drand48();
+long strtol();
+#endif /* __GNUC__ */
+#endif /* SUNOS */
+
+/*
+ * Here are the hacks that are also needed on the newer Solaris 2.x machines.
+ */
+#if defined(SUNOS) || defined(SOLARIS)
+#include <unistd.h>
+#ifdef __STDC__
+int	gethostname(char*, int);
+int     seteuid(uid_t euid);
+int     setegid(gid_t egid);
+int	setreuid(uid_t, uid_t);
+int	setregid(gid_t, gid_t);
+char*   crypt(const char*, const char*);
+#endif
+extern char** environ;
+#endif
+
+/*
+ * HPUX has some quirks too.
+ */
+#ifdef HPUX
+#if defined(OSVersion) && (OSVersion < 10)
+/*
+ * Make.Common defines HACK_SELECT directly and doesn't use this.
+ * See #if/not HACK_SELECT below also.
+ */
+#define HACK_SELECT
+#endif
+
+/* HP 10.20 seems not to define socklen_t */
+
+#define socklen_t int
+
+/* See comments above under SUNOS */
+#undef  CFHT_SIG_DFL
+#undef  CFHT_SIG_IGN
+#define CFHT_SIG_DFL ((PFV)(0))
+#define CFHT_SIG_IGN ((PFV)(1))
+
+#define seteuid(euid) setresuid(-1,(euid),-1)
+#define setegid(egid) setresgid(-1,(egid),-1)
+#ifdef __STDC__
+/* HP-UX 9 needed these.  Shouldn't hurt under 10.20 as long as they match. */
+void openlog(const char *, int, int);
+void syslog(int, const char *, ...);
+#endif
+#else /* not HP */
+#ifdef __STDC__
+/* only HP provides a prealloc function */
+int	prealloc(int fildes, unsigned size);
+#endif
+#endif
+
+/*
+ * CYGWIN32 is still in beta, so probably much of this stuff
+ * will need to be removed once this compiler stabilizes.
+ */
+#ifdef CYGWIN32
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#define seteuid(x) (0)
+#define setegid(x) (0)
+#define setuid(x)  (0)
+#define setgid(x)  (0)
+int readlink(const char*, char*, int);
+int select(int,fd_set*,fd_set*,fd_set*,struct timeval*);
+int lstat(const char*, struct stat*);
+int gettimeofday(struct timeval*, struct timezone*);
+const char* crypt(const char*, const char*);
+#endif
+
+/*
+ * Before version 10, HP defines fd_set, but doesn't use it in the prototype
+ * for select().  Also the count is size_t (which is right, why did ANSI
+ * lose that one?  I guess because C does not really support types :-( ).
+ * So do select() like this to avoid warnings on HP
+ *
+ *   Status = SELECT(n, read, write, error, &timestruct);
+ */
+#ifdef HACK_SELECT
+#define SELECT(n, read, write, error, tp)        \
+        select((size_t) (n), (int *) (read),     \
+               (int *) (write), (int *) (error), \
+	       (tp))
+#else
+/* Let the compiler check against a real prototype. */
+#define SELECT select
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !_INCLUDED_missing_protos */
Index: /tags/start/Ohana/src/misc/src/SAOobjects.c
===================================================================
--- /tags/start/Ohana/src/misc/src/SAOobjects.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/SAOobjects.c	(revision 12606)
@@ -0,0 +1,87 @@
+# include "ohana.h"
+# include "loneos.h"
+
+main (int argc, char **argv) {
+
+  FILE *f;
+  char line[256], name[256];
+  Header header;
+  Coords coords;
+  double R, D, dR, dD;
+  double X, Y, dX, dY;
+  double angle;
+  int Nfield;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: %s (image.fits) (input)\n", argv[0]);
+    exit (1);
+  }
+
+  if (!fits_read_header (argv[1], &header)) {
+    fprintf (stderr, "can't read header from file %s\n", argv[1]);
+    exit (1);
+  }
+
+  if (!GetCoords (&coords, &header)) {
+    fprintf (stderr, "can't find appropriate astrometry in image header\n");
+    exit (1);
+  }
+
+  /* load in the object description list */
+
+  /* fields for each line should be:
+     name (string)
+     Ra (dec. degrees)
+     Dec (dec. degrees)
+     dRa (arcsec)
+     dDec (arcsec)
+     angle (degrees)
+  */
+
+  if (argv[2][0] == '-') {
+    f = stdin;
+  } else {
+    f = fopen (argv[2], "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "can't open input data file\n");
+      exit (1);
+    }
+  }
+
+  while (scan_line (f, line) != EOF) {
+    Nfield = sscanf (line, "%s %lf %lf %lf %lf %lf", name, &R, &D, &dR, &dD, &angle);
+    
+    if (Nfield < 4) {
+      fprintf (stderr, "*");
+      continue;
+    }
+    
+    RD_to_XY (&X, &Y, R, D, &coords);
+
+    /* we won't worry about the case of cdelt1 != cdelt2,
+       in which case we don't have to worry about rotation 
+       between RA,DEC and X,Y for the calculation of the
+       slit lenghts.  Note that this assumption does not 
+       cause errors with the varying projected slitlength in
+       RA units, that is taken care of by the projection.
+       But, we are not taking into account a rotated slit */
+
+    dX = dR / 3600.0 / coords.cdelt1;
+    dY = dD / 3600.0 / coords.cdelt2;
+
+    switch (Nfield) {
+    case 4:
+      fprintf (stdout, "%s(%f,%f,%f)\n", name, X, Y, dX);
+      break;
+    case 5:
+      fprintf (stdout, "%s(%f,%f,%f,%f)\n", name, X, Y, dX, dY);
+      break;
+    case 6:
+      fprintf (stdout, "%s(%f,%f,%f,%f,%f)\n", name, X, Y, dX, dY, angle);
+      break;
+    }
+  }
+
+  if (f != stdin) fclose (f);
+
+}
Index: /tags/start/Ohana/src/misc/src/addastro.c
===================================================================
--- /tags/start/Ohana/src/misc/src/addastro.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/addastro.c	(revision 12606)
@@ -0,0 +1,105 @@
+# include <ohana.h>
+# define BLOCK 0x1000
+
+main (int argc, char **argv) {
+
+  /* USAGE: addastro (cmp) (ref) */
+
+  int i, j, nbytes, itmp, oldsize;
+  double tmp;
+  Header header, refhead;
+  FILE *f, *g;
+  char filename[1024];
+  char buffer[0x1000];
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: addastro (cmp) (ref)\n");
+    exit (1);
+  }
+
+  if (!fits_read_header (argv[1], &header)) {
+    fprintf (stderr, "ERROR: can't read header for %s\n", argv[1]);
+    exit (1);
+  }
+  oldsize = header.size;
+
+  if (!fits_read_header (argv[2], &refhead)) {
+    fprintf (stderr, "ERROR: can't read header for %s\n", argv[2]);
+    exit (1);
+  }
+
+  fits_scan   (&refhead, "CDELT1",   "%lf", 1, &tmp);
+  fits_modify (&header,  "CDELT1",   "%le", 1, tmp);
+  fits_scan   (&refhead, "CDELT2",   "%lf", 1, &tmp);
+  fits_modify (&header,  "CDELT2",   "%le", 1, tmp);
+  fits_scan   (&refhead, "CRVAL1",   "%lf", 1, &tmp);
+  fits_modify (&header,  "CRVAL1",   "%lf", 1, tmp);
+  fits_scan   (&refhead, "CRVAL2",   "%lf", 1, &tmp);
+  fits_modify (&header,  "CRVAL2",   "%lf", 1, tmp);
+  fits_scan   (&refhead, "CRPIX1",   "%lf", 1, &tmp);
+  fits_modify (&header,  "CRPIX1",   "%lf", 1, tmp);
+  fits_scan   (&refhead, "CRPIX2",   "%lf", 1, &tmp);
+  fits_modify (&header,  "CRPIX2",   "%lf", 1, tmp);
+  fits_scan   (&refhead, "PC001001", "%lf", 1, &tmp);
+  fits_modify (&header,  "PC001001", "%le", 1, tmp);
+  fits_scan   (&refhead, "PC001002", "%lf", 1, &tmp);
+  fits_modify (&header,  "PC001002", "%le", 1, tmp);
+  fits_scan   (&refhead, "PC002001", "%lf", 1, &tmp);
+  fits_modify (&header,  "PC002001", "%le", 1, tmp);
+  fits_scan   (&refhead, "PC002002", "%lf", 1, &tmp);
+  fits_modify (&header,  "PC002002", "%le", 1, tmp);
+  fits_scan   (&refhead, "NPLYTERM", "%d",  1, &itmp);
+  fits_modify (&header,  "NPLYTERM", "%d",  1, itmp);
+  fits_scan   (&refhead, "NASTRO",   "%d",  1, &itmp);
+  fits_modify (&header,  "NASTRO",   "%d",  1, itmp);
+  fits_scan   (&refhead, "CERROR",   "%lf", 1, &tmp);
+  fits_modify (&header,  "CERROR",   "%lf", 1, tmp);
+  fits_scan   (&refhead, "CPRECISE", "%lf", 1, &tmp);
+  fits_modify (&header,  "CPRECISE", "%lf", 1, tmp);
+
+  fits_modify (&header, "CERROR", "%C", 1, "scatter in astrometry soln (arcsec)");
+  fits_modify (&header, "CPRECISE", "%C", 1, "precision of astrometry soln (arcsec)");
+
+  /* write to file */
+  sprintf (filename, "%s.tmp", argv[1]);
+  if (!fits_write_header (filename, &header)) {
+    fprintf (stderr, "ERROR: can't write header for %s\n", filename);
+    exit (1);
+  }
+  g = fopen (filename, "w");
+  if (g == NULL) {
+    fprintf (stderr, "ERROR: can't read write to %s\n", filename);
+    exit (1);
+  }
+  nbytes = fwrite (header.buffer, 1, header.size, g);
+  fseek (g, header.size, SEEK_SET); 
+
+  /* read date from file */
+  f = fopen (argv[1], "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't read data from %s\n", argv[1]);
+    exit (1);
+  }
+  fseek (f, oldsize, SEEK_SET); 
+
+  while ((nbytes = fread (buffer, 1, BLOCK, f)) > 0) {
+    if (nbytes != fwrite (buffer, 1, nbytes, g)) {
+      fprintf (stderr, "ERROR: failure writing output data file\n");
+      exit (0);
+    }
+  }
+  
+  fclose (f);
+  fclose (g);
+
+  sprintf (buffer, "mv %s %s~\n", argv[1], argv[1]);
+  system (buffer);
+
+  sprintf (buffer, "mv %s %s\n", filename, argv[1]);
+  system (buffer);
+
+  fprintf (stdout, "SUCCESS\n");
+
+
+}
+
Index: /tags/start/Ohana/src/misc/src/applyscat.c
===================================================================
--- /tags/start/Ohana/src/misc/src/applyscat.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/applyscat.c	(revision 12606)
@@ -0,0 +1,133 @@
+# include <ohana.h>
+# define BYTES_STAR 66
+
+typedef struct {
+  double X;
+  double Y;
+  double M;
+} Stars;
+
+int main (int argc, char **argv) {
+
+  Header header;
+  Matrix matrix;
+  Stars *stars;
+  int Nstar, Nbytes, nbytes;
+  FILE *f;
+  char *buffer, line[10];
+  double dmag, ratio;
+  int i, x, y;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: applyscat (input) (scatter) (output)\n");
+    exit (1);
+  }
+
+  /* read smp header */
+  if (!fits_read_header (argv[1], &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s\n", argv[1]);
+    exit (1);
+  }
+
+  /* open file for star data */
+  f = fopen (argv[1], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't read data from %s\n", argv[1]);
+    exit (1);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* find expected number of stars */
+  fits_scan (&header, "NSTARS", "%d", 1, &Nstar);
+  if (Nstar == 0) {
+    fprintf (stderr, "ERROR: can't get NSTARS from header\n");
+    exit (1);
+  }
+
+  /* allocate work space */
+  Nbytes = Nstar*BYTES_STAR;
+  ALLOCATE (stars, Stars, Nstar);
+  ALLOCATE (buffer, char, Nbytes + 1);
+
+  /* load in data */
+  nbytes = Fread (buffer, 1, Nbytes, f, "char");
+  if (nbytes != Nbytes) {
+    fprintf (stderr, "ERROR: can't load in all stars\n");
+    exit (1);
+  }
+  buffer[Nbytes] = 0;
+  fclose (f);
+  
+  for (i = 0; i < Nstar; i++) {
+    dparse (&stars[i].X,  1, &buffer[i*BYTES_STAR]);
+    dparse (&stars[i].Y,  2, &buffer[i*BYTES_STAR]);
+    dparse (&stars[i].M,  3, &buffer[i*BYTES_STAR]);
+  }
+
+  if (!fits_read_matrix (argv[2], &matrix)) {
+    fprintf (stderr, "ERROR: can't open scatter image file %s\n", argv[2]);
+    exit (1);
+  }
+  
+  /* flat' = flat*ratio
+     flux' = flux / ratio
+     mag'  = mag - dmag
+     dmag = -2.5*log10(ratio) 
+
+     ie, ratio = 1.1
+     flux' = 0.9*flux (flux' < flux)
+     dmag = -0.103
+     mag' = mag + 0.103 (mag' > mag)
+  */
+
+  for (i = 0; i < Nstar; i++) {
+    x = stars[i].X;
+    y = stars[i].Y;
+    ratio = fits_get_matrix_value (&matrix, x, y);
+    dmag = -2.5*log10(ratio);
+    dmag = (dmag > +1.0) ? 0.0 : dmag;
+    dmag = (dmag < -1.0) ? 0.0 : dmag;
+    stars[i].M -= dmag;
+  }
+
+  /* full format line: "%6.1f %6.1f %6.3f %03d %2d %3.1f %6.3f %6.3f %6.2f %6.2f %5.1f", X, Y, M, dM, dophot, sky, Mgal, Map, fx, fy, df */
+  for (i = 0; i < Nstar; i++) {
+    sprintf (line, "%6.3f", stars[i].M);
+    memcpy (&buffer[i*BYTES_STAR+14], line, 6);
+  }
+
+  /* write smp header */
+  if (!fits_write_header (argv[3], &header)) {
+    fprintf (stderr, "ERROR: can't write output file header %s\n", argv[3]);
+    exit (1);
+  }
+
+  /* open file for star data */
+  f = fopen (argv[3], "a");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't open output file %s\n", argv[3]);
+    exit (1);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* load in data */
+  nbytes = Fwrite (buffer, 1, Nbytes, f, "char");
+  if (nbytes != Nbytes) {
+    fprintf (stderr, "ERROR: problem writing stars\n");
+    exit (1);
+  }
+  fclose (f);
+
+  exit (0);
+}
+
+
+
+
+/* load in smp header
+   load in smp stars
+   load in scatter frame
+   apply corrections
+   write smp header
+   write smp stars
+*/
Index: /tags/start/Ohana/src/misc/src/ckfits.c
===================================================================
--- /tags/start/Ohana/src/misc/src/ckfits.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/ckfits.c	(revision 12606)
@@ -0,0 +1,57 @@
+# include <ohana.h>
+
+int main (int argc, char **argv) {
+
+  int i, Nbytes, nbytes, Ndata, Ntotal, nskip, status;
+  Header header;
+  FILE *f;
+  char *buffer;
+
+  if (argc != 2) {
+    fprintf (stdout, "USAGE: ckfits (filename)\n");
+    exit (2);
+  }
+
+  status = fits_read_header (argv[1], &header);
+  if (!status) { 
+    fprintf (stdout, "%s: header\n", argv[1]);
+    exit (1);
+  }
+
+  Ntotal = fits_matrix_size (&header);
+
+  Ndata = abs(header.bitpix / 8);
+  for (i = 0; i < header.Naxes; i++) Ndata *= header.Naxis[i];
+
+  nbytes = Ntotal - Ndata;
+  nskip = Ndata + header.size;
+
+  f = fopen (argv[1], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stdout, "%s: open\n", argv[1]);
+    exit (1);
+  }
+
+  ALLOCATE (buffer, char, MAX (nbytes, 1));
+  fseek (f, nskip, SEEK_SET);
+  Nbytes = fread (buffer, 1, nbytes, f);
+  fclose (f);
+
+  if (Nbytes != nbytes) {
+    fprintf (stdout, "%s: short\n", argv[1]);
+    exit (1);
+  }
+
+  for (i = 0; i < nbytes; i++) {
+    if (buffer[i]) {
+      fprintf (stdout, "%s: padding\n", argv[1]);
+      exit (1);
+    }
+  }
+
+  fprintf (stdout, "%s: ok\n", argv[1]);
+  exit (0);
+
+}
+
+
Index: /tags/start/Ohana/src/misc/src/csystem.c
===================================================================
--- /tags/start/Ohana/src/misc/src/csystem.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/csystem.c	(revision 12606)
@@ -0,0 +1,98 @@
+# include <ohana.h>
+
+/* csystem: convert between celestial, galactic, ecliptic, and
+   hoziron systems */
+
+int main (int argc, char **argv) {
+
+  /* USAGE: csystem [C/G/E/H] [C/G/E/H] [epoch] */
+  double x, y, X, Y, Xo, xo, phi, T;
+  double sin_x, sin_y, cos_x, cos_y;
+  
+  if (((argc == 3) && ((argv[1][0] == 'E') || (argv[2][0] == 'E'))) || 
+      ((argc == 4) && ((argv[1][0] != 'E') && (argv[2][0] != 'E'))) ||
+      ((argc != 3) && (argc != 4))) {
+    fprintf (stderr, "USAGE: csystems [C/G/E/H] [C/G/E/H] [epoch]\n");
+    exit (2);
+  }
+
+  switch (argv[1][0]) {
+  case 'C':
+    switch (argv[2][0]) {
+    case 'C': 
+      phi = Xo = xo = 0.0;
+      break;
+    case 'G':
+      phi = -62.6*RAD_DEG;
+      Xo = 282.25;
+      xo = 33;
+      break;
+    case 'E':
+      T = (atof (argv[3]) - 1900) / 100.0;
+      phi = -1*(23.452294 - 0.013013*T - 0.000001639*T*T + 0.000000503*T*T*T);
+      phi *= RAD_DEG;
+      Xo = xo = 0.0;
+      break;
+    }
+    break;
+  case 'E':
+    switch (argv[2][0]) {
+    case 'C': 
+      T = (atof (argv[3]) - 1900) / 100.0;
+      phi = 23.452294 - 0.013013*T - 0.000001639*T*T + 0.000000503*T*T*T;
+      phi *= RAD_DEG;
+      Xo = xo = 0.0;
+      break;
+    case 'G':
+      fprintf (stderr, "error: not working!\n");
+      exit (1);
+      phi = -62.6*RAD_DEG;
+      Xo = 282.25;
+      xo = 33;
+      break;
+    case 'E':
+      phi = Xo = xo = 0.0;
+      break;
+    }
+    break;
+  case 'G':
+    switch (argv[2][0]) {
+    case 'C': 
+      phi = 62.6*RAD_DEG;
+      Xo = 33;
+      xo = 282.25;
+      break;
+    case 'G':
+      phi = Xo = xo = 0.0;
+      break;
+    case 'E':
+      fprintf (stderr, "error: not working!\n");
+      exit (1);
+      phi = -1*(23.452294 - 0.013013*T - 0.000001639*T*T + 0.000000503*T*T*T);
+      Xo = xo = 0.0;
+      break;
+    }
+  }
+ 
+  Xo *= RAD_DEG;
+  for (; fscanf (stdin, "%lf %lf", &X, &Y) == 2;) {
+    
+    X *= RAD_DEG;
+    Y *= RAD_DEG;
+
+    sin_y = cos(Y)*sin(X - Xo)*sin(phi) + sin(Y)*cos(phi);
+    cos_y = sqrt (1 - sin_y*sin_y);
+    sin_x = (cos(Y)*sin(X - Xo)*cos(phi) - sin(Y)*sin(phi)) /  cos_y;
+    cos_x = cos(Y)*cos(X - Xo) / cos_y;
+/*    fprintf (stderr, "%f %f   %f %f   %f %f\n", X, Y, sin_x, cos_x, sin_y, cos_y); */
+    
+    x = (DEG_RAD * atan2 (sin_x, cos_x) + xo + 360);
+    
+    while (x >= 360.0)
+      x -= 360;
+    y = DEG_RAD * atan2 (sin_y, cos_y);
+    
+    fprintf (stdout, "%10.6f %10.6f\n", x, y);
+  }
+  exit (0);
+}
Index: /tags/start/Ohana/src/misc/src/cubefilter.c
===================================================================
--- /tags/start/Ohana/src/misc/src/cubefilter.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/cubefilter.c	(revision 12606)
@@ -0,0 +1,146 @@
+# include <ohana.h>
+# define D_NFILES 100
+
+main (int argc, char **argv) {
+
+  int i, j, k, n, Npixels, Npixin, Npixrd, Npixlast, N;
+  int Npass, NFILES, Nfiles;
+
+  char **filename;
+  Header head, *tmphead;
+  Matrix out,  *tmpmatr;
+  float *list, *v, *O;
+  float fmin, fmax, Nval, sum;
+
+  FT_UNSIGN_MODE = FALSE;
+  if (N = get_argument (argc, argv, "-unsign")) {
+    remove_argument (N, &argc, argv);
+    FT_UNSIGN_MODE = TRUE;
+  }
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: minmaxfilter infile outfile fmin fmax\n");
+    exit (0);
+  }
+  fmin = atof (argv[2]); 
+  fmax = atof (argv[3]); 
+
+  /* read in the filenames */
+  NFILES = D_NFILES;
+  ALLOCATE (filename, char *, NFILES);
+  ALLOCATE (filename[0], char, 1024);
+  for (i = 0; fscanf (stdin, "%s", filename[i]) != EOF; i++) {
+    if (i == NFILES - 1) {
+      NFILES += D_NFILES;
+      REALLOCATE (filename, char *, NFILES);
+    }
+    ALLOCATE (filename[i+1], char, 1024);
+  }
+  Nfiles = i;
+  REALLOCATE (filename, char *, Nfiles);
+
+  /* load a header, setup output header, matrix */
+  fits_read_header (filename[0], &head);
+  fits_create_matrix (&head, &out);
+  fits_convert_format (&head, &out, -32, 1.0, 0.0, FALSE);
+
+  /* find size of temporary images */
+  Npixels = head.Naxis[0]*head.Naxis[1];
+  Npixin = Npixels / Nfiles;
+  Npixlast = Npixels - Npixin*Nfiles;
+  if (Npixlast == 0) {
+    Npass = Nfiles;
+    Npixlast = Npixin;
+    fprintf (stderr, "operating on %d pixels per pass\n", Npixin);
+  } else {
+    Npass = Nfiles + 1;
+    fprintf (stderr, "operating on %d pixels per pass, %d in last\n", Npixin, Npixlast);
+  }
+  
+  ALLOCATE (tmphead, Header, Nfiles);
+  ALLOCATE (tmpmatr, Matrix, Nfiles);
+  ALLOCATE (list, float, Nfiles);
+  Nval = 0;
+  for (k = fmin*Nfiles; k < fmax*Nfiles; k++) {
+    Nval += 1.0;
+  }
+
+  O = (float *) out.buffer;
+  for (n = 0; n < Npass; n++) {
+    fprintf (stderr, "pass %d\n", n);
+    Npixrd = (n == Npass - 1) ? Npixlast : Npixin;
+    for (i = 0; i < Nfiles; i++) {
+      fprintf (stderr, ".");
+      if (!fits_read_header  (filename[i], &tmphead[i])) {
+	fprintf (stderr, "trouble reading file %s\n", filename[i]);
+	exit (1);
+      }
+      fits_read_portion (filename[i], &tmpmatr[i], n*Npixin, Npixrd);
+      tmphead[i].Naxis[0] = 1;
+      tmphead[i].Naxis[1] = Npixrd;
+      fits_convert_format (&tmphead[i], &tmpmatr[i], -32, 1.0, 0.0, FALSE);
+    }
+    
+    fprintf (stderr, "starting sorts\n");
+    for (j = 0; j < Npixrd; j++, O++) {
+      for (k = 0; k < Nfiles; k++) {
+	v = (float *)tmpmatr[k].buffer;
+	list[k] = v[j];
+      }
+      fsort (list, Nfiles);
+      sum = 0;
+      for (k = fmin*Nfiles; k < fmax*Nfiles; k++) {
+	sum += list[k];
+      }
+      *O = (sum / Nval);
+    }
+
+    for (i = 0; i < Nfiles; i++) {
+      fprintf (stderr, ",");
+      fits_free_header (&tmphead[i]);
+      fits_free_matrix (&tmpmatr[i]);
+    }
+    
+  }
+
+  fits_write_header (argv[1], &head);
+  fits_write_matrix (argv[1], &out);
+
+  return (0);
+
+}
+
+fsort (value, N) 
+float value[];
+int N;
+{
+  int l,j,ir,i;
+  float temp;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      temp = value[--l];
+    }
+    else {
+      temp = value[ir];
+      value[ir] = value[0];
+      if (--ir == 0) {
+	value[0] = temp;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && value[j] < value[j+1]) ++j;
+      if (temp < value[j]) {
+	value[i]=value[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    value[i] = temp;
+  }
+}
Index: /tags/start/Ohana/src/misc/src/dastro.c
===================================================================
--- /tags/start/Ohana/src/misc/src/dastro.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/dastro.c	(revision 12606)
@@ -0,0 +1,112 @@
+# include <ohana.h>
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  
+  int status, REL, N;
+  Header header, refhead;
+  char  filename[1024], reffile[1024], *p;
+  double X_O, X_X, X_Y, Y_O, Y_X, Y_Y;
+  double RA_O, RA_X, RA_Y, DEC_O, DEC_X, DEC_Y;
+  double ra_o, ra_x, ra_y, dec_o, dec_x, dec_y;
+  double dRA, dDEC, dX, dY, dra, ddec;
+  
+  if (N = get_argument (argc, argv, "-rel")) {
+    remove_argument (N, &argc, argv);
+    REL = TRUE;
+  }
+  else {
+    REL = FALSE;
+  }
+  
+  while (fscanf (stdin, "%s", filename) != EOF) {
+    
+    status = fits_read_header (filename, &header);
+    if (!status) {
+      fprintf (stderr, "error opening file %s\n", filename);
+      continue;
+    }
+    status = fits_scan (&header, "rREF", "%s", 1, reffile);
+    status &= fits_scan (&header, "X_O", "%lf", 1, &X_O);
+    status &= fits_scan (&header, "X_X", "%lf", 1, &X_X);
+    status &= fits_scan (&header, "X_Y", "%lf", 1, &X_Y);
+    status &= fits_scan (&header, "Y_O", "%lf", 1, &Y_O);
+    status &= fits_scan (&header, "Y_X", "%lf", 1, &Y_X);
+    status &= fits_scan (&header, "Y_Y", "%lf", 1, &Y_Y);
+    status &= fits_scan (&header, "dX", "%lf", 1, &dX);
+    status &= fits_scan (&header, "dY", "%lf", 1, &dY);
+    if (!status) {
+      fprintf (stderr, "file missing rastro info: %s\n", filename);
+      fits_free_header (&header);
+      continue;
+    }
+
+    while ((p = strstr (reffile, "'")) != NULL) {
+      *p = ' ';
+    }
+    stripwhite (reffile);
+    if ((p = strrchr(reffile, '.')) != NULL)
+      strcpy(p, ".head");
+    else 
+      strcat(reffile, ".head");
+
+    if (!strcmp (reffile, filename)) {
+      fprintf (stderr, "%s is %s, not altering\n", reffile, filename);
+      continue;
+    }
+
+    status  = fits_read_header (reffile, &refhead);
+    if (!status) {
+      fprintf (stderr, "error opening file %s\n", reffile);
+      continue;
+    }
+    status &= fits_scan (&refhead, "RA_O", "%lf", 1, &RA_O);
+    status &= fits_scan (&refhead, "RA_X", "%lf", 1, &RA_X);
+    status &= fits_scan (&refhead, "RA_Y", "%lf", 1, &RA_Y);
+    status &= fits_scan (&refhead, "DEC_O", "%lf", 1, &DEC_O);
+    status &= fits_scan (&refhead, "DEC_X", "%lf", 1, &DEC_X);
+    status &= fits_scan (&refhead, "DEC_Y", "%lf", 1, &DEC_Y);
+    status &= fits_scan (&refhead, "dRA",   "%lf", 1, &dRA);
+    status &= fits_scan (&refhead, "dDEC",  "%lf", 1, &dDEC);
+    if (!status) {
+      fprintf (stderr, "file missing rastro info: %s\n", reffile);
+      fits_free_header (&header);
+      fits_free_header (&refhead);
+      continue;
+    }
+
+    fprintf (stderr, "%f %f %f\n%f %f %f\n", RA_O, RA_X, RA_Y, DEC_O, DEC_X, DEC_Y);
+    fprintf (stderr, "\n%f %f %f\n%f %f %f\n", X_O, X_X, X_Y, Y_O, Y_X, Y_Y);
+    
+    ra_o = RA_X*X_O + RA_Y*Y_O + RA_O;
+    dec_o = DEC_X*X_O + DEC_Y*Y_O + DEC_O;
+    
+    ra_x = RA_X*X_X + RA_Y*Y_X;
+    ra_y = RA_X*X_Y + RA_Y*Y_Y;
+    dec_x = DEC_X*X_X + DEC_Y*Y_X;
+    dec_y = DEC_X*X_Y + DEC_Y*Y_Y;
+    
+    fprintf (stderr, "%f %f %f\n%f %f %f\n", ra_o, ra_x, ra_y, dec_o, dec_x, dec_y);
+
+    dra = sqrt(dRA*dRA + SQ(3600*dX*RA_X) + SQ(3600*dY*RA_Y));
+    ddec = sqrt(dDEC*dDEC + SQ(3600*dX*DEC_X) + SQ(3600*dY*DEC_Y));
+			   
+    status &= fits_modify (&header, "RA_O", "%lf", 1, ra_o);
+    status &= fits_modify (&header, "RA_X", "%le", 1, ra_x);
+    status &= fits_modify (&header, "RA_Y", "%le", 1, ra_y);
+    status &= fits_modify (&header, "DEC_O", "%lf", 1, dec_o);
+    status &= fits_modify (&header, "DEC_X", "%le", 1, dec_x);
+    status &= fits_modify (&header, "DEC_Y", "%le", 1, dec_y);
+    status &= fits_modify (&header, "dRA",   "%lf", 1, dra);
+    status &= fits_modify (&header, "dDEC",  "%lf", 1, ddec);
+    
+    fits_write_header (filename, &header);
+    fits_free_header (&header);
+    fits_free_header (&refhead);
+    
+  }
+
+}
+
Index: /tags/start/Ohana/src/misc/src/dbrshtest.c
===================================================================
--- /tags/start/Ohana/src/misc/src/dbrshtest.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/dbrshtest.c	(revision 12606)
@@ -0,0 +1,150 @@
+# include <ohana.h>
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+
+static char dbhost[] = "kiawe.cfht.hawaii.edu";
+static char dbfile[] = "/h/eugene/d4/flattest/test.db";
+
+void main (int argc, char **argv) {
+
+  char buffer[10000], hostname[1025];
+  int vbuffer[10000];
+  FILE *f;
+  int i, j, Nrun, status, fd, pid, Remote;
+  struct timeval now, then;  
+  double dtime;
+  
+  /* check cmd line args */
+  Remote = FALSE;
+  if (argc > 1) {
+    if (!strcmp (argv[1], "-check")) {
+      f = fopen (dbfile, "r");
+      if (f == (FILE *) NULL) {
+	fprintf (stderr, "ERROR: can't open file\n");
+	exit (0);
+      }
+      status = fread (buffer, 1, 5000, f);
+      if (status != 5000) {
+	fprintf (stderr, "ERROR: can't read header\n");
+	exit (0);
+      }
+      sscanf (&buffer[500], "%*s %*s %*s %d", &Nrun);
+      for (j = 0 ; j < Nrun; j++) {
+	status = fread (vbuffer, 4, 1000, f);
+	if (status != 1000) {
+	  fprintf (stderr, "ERROR: can't read data\n");
+	  exit (0);
+	}
+	for (i = 0; i < 1000; i++) {
+	  if (vbuffer[i] != j) {
+	    fprintf (stderr, "ERROR: invalid data %d/%d,  %d - %d\n", j, Nrun, i, vbuffer[i]);
+	    exit (0);
+	  }
+	}
+      }
+      fprintf (stderr, "Data is good\n");
+      exit (0);
+    }
+    if (!strcmp (argv[1], "-remote")) {
+      Remote = TRUE;
+    }
+  }	  
+
+  /* if lockfile exists, program will complain and quit */
+  if (!Remote && ((fd = setlockfile (dbfile, 60.0)) == -1)) {
+    fprintf (stderr, "ERROR: can't set lock on %s\n", dbfile);
+    exit (1);
+  }
+
+  /* check if we are on correct machine, or fork to it */
+  if (gethostname (hostname, 1024)) {
+    fprintf (stderr, "ERROR: can't get hostname\n");
+    exit (1);
+  }
+  if (strcmp (hostname, dbhost)) {
+
+    gettimeofday (&then, (void *) NULL);
+    pid = fork ();
+    if (!pid) { /* must be child process */
+      status = execlp ("rsh", "rsh", dbhost, "dbtest", "-remote", 0); 
+      fprintf (stderr, "error starting remote shell process\n");
+      exit (1);
+    }
+    wait (0);
+
+    /**  
+    inetd has a maximum connection rate of 40 / 60 seconds it will
+    block for 10 min if this rate is exceeded.  this is here because
+    we have to hold the lock long enough that the connection rate does
+    not get exceeded.  We actually use 3.0 seconds to avoid stealing
+    too many rsh slots. 
+    **/
+    
+    gettimeofday (&now, (void *) NULL);
+    dtime = 1e6*(3.0 - DTIME(now,then));
+    fprintf (stderr, "dtime %f\n", dtime);
+    if (dtime > 0) usleep (dtime);
+
+    clearlockfile (dbfile, fd);
+    exit (0);
+
+  }
+
+  /* read the header block, change one line, write the header block */
+  /* write a block to EOF */
+
+  f = fopen (dbfile, "r");
+  if (f == (FILE *) NULL) {
+    /* make a header block */
+    for (i = 0; i < 50; i++) {
+      memset (&buffer[100*i], 65+i, 99);
+      buffer[100*i + 99] = '\n';
+    }
+    sprintf (&buffer[500], "THIS IS TEST    0   \n");
+    Nrun = 0;
+  } else {
+    status = fread (buffer, 1, 5000, f);
+    if (status != 5000) {
+      fprintf (stderr, "ERROR: can't read data\n");
+      exit (0);
+    }
+    
+    sscanf (&buffer[500], "%*s %*s %*s %d", &Nrun);
+    Nrun ++;
+    sprintf (&buffer[500], "THIS IS TEST    %d   \n", Nrun);
+  }
+
+  f = fopen (dbfile, "r+");
+  if (f == NULL) {
+    f = fopen (dbfile, "w");
+    if (f == NULL) {
+      fprintf (stderr, "ERROR: can't create/open file %s\n", dbfile);
+      exit (0);
+    }
+  }
+
+  /* position to begining of file to write header */
+  fseek (f, 0, SEEK_SET);
+  status = fwrite (buffer, 1, 5000, f);
+  if (status != 5000) {
+    fprintf (stderr, "ERROR: failed writing data to header\n");
+    exit (0);
+  }
+
+  for (i = 0; i < 1000; i++) vbuffer[i] = Nrun;
+
+  fseek (f, 0, SEEK_END);
+  status = fwrite (vbuffer, 4, 1000, f);
+  if (status != 1000) {
+    fprintf (stderr, "ERROR: failed writing data to file\n");
+    exit (0);
+  }
+
+  fclose (f);
+
+  if (!gnfsflush (dbfile)) {
+    fprintf (stderr, "ERROR: failed to flush image catalog\n");
+    exit (0);
+  }
+
+  
+}
Index: /tags/start/Ohana/src/misc/src/dbtest.c
===================================================================
--- /tags/start/Ohana/src/misc/src/dbtest.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/dbtest.c	(revision 12606)
@@ -0,0 +1,142 @@
+# include <ohana.h>
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+
+# define LCK_ACCESS  1   /* can't get access to file */
+# define LCK_TIMEOUT 2   /* timeout setting lock */
+# define LCK_HARDLCK 3   /* error setting hard lockfile */
+# define LCK_HUNLOCK 4   /* error clearing hard lockfile */
+
+# define LCK_EMPTY   5   /* locked file is empty */
+# define LCK_FULL    6   /* locked file is not empty */
+# define LCK_UNKNOWN 7   /* can't stat file to get size */
+
+# define LCK_SOFT    10  /* soft lock */
+# define LCK_HARD    11  /* hard lock */
+# define LCK_XCLD    12  /* exclusive soft lock */
+
+int clearlockfile2 (char *filename, int fd, int hard, int *state);
+int setlockfile2 (char *filename, double timeout, int hard, int *state);
+
+static char dbfile[] = "/h/eugene/kiawe/test.db";
+
+void main (int argc, char **argv) {
+
+  char buffer[10000], hostname[1025];
+  int vbuffer[10000];
+  FILE *f;
+  int i, j, Nrun, status, fd, pid, Remote;
+  int dbstate;
+  struct timeval now, then;  
+  double dtime;
+  
+  /* check cmd line args */
+  if (argc > 1) {
+    if (!strcmp (argv[1], "-check")) {
+      f = fopen (dbfile, "r");
+      if (f == (FILE *) NULL) {
+	fprintf (stderr, "ERROR: can't open file\n");
+	exit (0);
+      }
+      status = fread (buffer, 1, 5000, f);
+      if (status != 5000) {
+	fprintf (stderr, "ERROR: can't read header\n");
+	exit (0);
+      }
+      sscanf (&buffer[500], "%*s %*s %*s %d", &Nrun);
+      for (j = 0 ; j < Nrun; j++) {
+	status = fread (vbuffer, 4, 1000, f);
+	if (status != 1000) {
+	  fprintf (stderr, "ERROR: can't read data\n");
+	  exit (0);
+	}
+	for (i = 0; i < 1000; i++) {
+	  if (vbuffer[i] != j) {
+	    fprintf (stderr, "ERROR: invalid data %d/%d,  %d - %d\n", j, Nrun, i, vbuffer[i]);
+	    exit (0);
+	  }
+	}
+      }
+      fprintf (stderr, "Data is good, %d entries\n", Nrun);
+      exit (0);
+    }
+  }	  
+
+  /* set hard lock on dbfile */
+  if ((fd = setlockfile2 (dbfile, 60.0, LCK_HARD, &dbstate)) == -1) {
+    fprintf (stderr, "ERROR: can't set lock on %s, state is %d\n", dbfile, dbstate);
+    exit (1);
+  }
+
+  /* setlock will return an fd to an open file ready for read/write access */
+
+  /* first pass test, use only fd */
+  /* read the header block, change one line, write the header block */
+  /* write a block to EOF */
+
+  /* for new file, create header block with value of 0 */
+  if (dbstate == LCK_EMPTY) {
+    for (i = 0; i < 50; i++) {
+      memset (&buffer[100*i], 65+i, 99);
+      buffer[100*i + 99] = '\n';
+    }
+    sprintf (&buffer[500], "THIS IS TEST    0   \n");
+    Nrun = 0;
+  } else {
+    status = read (fd, buffer, 5000);
+    /* status = fread (buffer, 1, 5000, f); */
+    if (status != 5000) {
+      fprintf (stderr, "ERROR: can't read data\n");
+      exit (0);
+    }
+    /* check on current number of entries */
+    sscanf (&buffer[500], "%*s %*s %*s %d", &Nrun);
+    Nrun ++;
+    sprintf (&buffer[500], "THIS IS TEST    %d   \n", Nrun);
+  }
+
+
+# define STREAMS 1
+
+  /* position to begining of file to write header */
+# if (STREAMS)
+  f = fdopen (fd, "r+"); 
+
+  if (Nrun == 20) {
+    freopen (f, 
+  fseek (f, 0, SEEK_SET);
+  status = fwrite (buffer, 1, 5000, f);
+# else 
+  lseek (fd, 0, SEEK_SET);
+  status = write (fd, buffer, 5000);
+# endif
+
+  if (status != 5000) {
+    fprintf (stderr, "ERROR: failed writing data to header\n");
+    exit (0);
+  }
+
+  for (i = 0; i < 1000; i++) vbuffer[i] = Nrun;
+
+# if (STREAMS)
+  fseek (f, 0, SEEK_END);
+  status = fwrite (vbuffer, 1, 4000, f);
+# else 
+  lseek (fd, 0, SEEK_END);
+  status = write (fd, vbuffer, 4000);
+# endif
+
+  if (status != 4000) {
+    fprintf (stderr, "ERROR: failed writing data to file\n");
+    exit (0);
+  }
+
+  clearlockfile2 (dbfile, fd, LCK_HARD, &dbstate);
+# if (STREAMS)
+  fclose (f);
+# else 
+  close (fd);
+# endif
+
+
+}
+
Index: /tags/start/Ohana/src/misc/src/dbtest.c.failed
===================================================================
--- /tags/start/Ohana/src/misc/src/dbtest.c.failed	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/dbtest.c.failed	(revision 12606)
@@ -0,0 +1,106 @@
+# include <ohana.h>
+
+static char dbfile[] = "/h/eugene/d4/flattest/test.db";
+
+void main (int argc, char **argv) {
+
+  char buffer[10000];
+  int vbuffer[10000];
+  FILE *f;
+  int i, j, Nrun, status, fd;
+
+  if (argc > 1) {
+    if (!strcmp (argv[1], "-check")) {
+      f = fopen (dbfile, "r");
+      if (f == (FILE *) NULL) {
+	fprintf (stderr, "ERROR: can't open file\n");
+	exit (0);
+      }
+      status = fread (buffer, 1, 5000, f);
+      if (status != 5000) {
+	fprintf (stderr, "ERROR: can't read header\n");
+	exit (0);
+      }
+      sscanf (&buffer[500], "%*s %*s %*s %d", &Nrun);
+      for (j = 0 ; j < Nrun; j++) {
+	status = fread (vbuffer, 4, 1000, f);
+	if (status != 1000) {
+	  fprintf (stderr, "ERROR: can't read data\n");
+	  exit (0);
+	}
+	for (i = 0; i < 1000; i++) {
+	  if (vbuffer[i] != j) {
+	    fprintf (stderr, "ERROR: invalid data %d/%d,  %d - %d\n", j, Nrun, i, vbuffer[i]);
+	    exit (0);
+	  }
+	}
+      }
+      fprintf (stderr, "Data is good\n");
+      exit (0);
+    }
+  }	  
+
+  /* read the header block, change one line, write the header block */
+  /* write a block to EOF */
+
+  /* if lockfile exists, program will complain and quit */
+  if ((fd = setlockfile (dbfile, 60.0)) == -1) {
+    fprintf (stderr, "ERROR: can't set lock on %s\n", dbfile);
+    exit (1);
+  }
+
+  f = fopen (dbfile, "r");
+  if (f == (FILE *) NULL) {
+    /* make a header block */
+    for (i = 0; i < 50; i++) {
+      memset (&buffer[100*i], 65+i, 99);
+      buffer[100*i + 99] = '\n';
+    }
+    sprintf (&buffer[500], "THIS IS TEST    0   \n");
+    Nrun = 0;
+  } else {
+    status = fread (buffer, 1, 5000, f);
+    if (status != 5000) {
+      fprintf (stderr, "ERROR: can't read data\n");
+      exit (0);
+    }
+    
+    sscanf (&buffer[500], "%*s %*s %*s %d", &Nrun);
+    Nrun ++;
+    sprintf (&buffer[500], "THIS IS TEST    %d   \n", Nrun);
+  }
+
+  f = fopen (dbfile, "r+");
+  if (f == NULL) {
+    f = fopen (dbfile, "w");
+    if (f == NULL) {
+      fprintf (stderr, "ERROR: can't create/open file %s\n", dbfile);
+      exit (0);
+    }
+  }
+
+  /* position to begining of file to write header */
+  fseek (f, 0, SEEK_SET);
+  status = fwrite (buffer, 1, 5000, f);
+  if (status != 5000) {
+    fprintf (stderr, "ERROR: failed writing data to header\n");
+    exit (0);
+  }
+
+  for (i = 0; i < 1000; i++) vbuffer[i] = Nrun;
+
+  fseek (f, 0, SEEK_END);
+  status = fwrite (vbuffer, 4, 1000, f);
+  if (status != 1000) {
+    fprintf (stderr, "ERROR: failed writing data to file\n");
+    exit (0);
+  }
+
+  if (!gnfsflush (dbfile)) {
+    fprintf (stderr, "ERROR: failed to flush image catalog\n");
+    exit (0);
+  }
+
+  clearlockfile (dbfile, fd);
+
+}
Index: /tags/start/Ohana/src/misc/src/doscript.c
===================================================================
--- /tags/start/Ohana/src/misc/src/doscript.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/doscript.c	(revision 12606)
@@ -0,0 +1,179 @@
+# include <ohana.h>
+
+void args(), error();
+int COLDSTART, OUTIMAGE;
+double THRESHOLD;
+
+main (argc, argv) 
+     int argc;
+     char **argv;
+{
+  
+  FILE *f, *ft;
+  char name[128], root[128], line[256];
+  double psfx, psfy, sky, tilt;
+
+  args (argc, argv);
+
+  while (fscanf (stdin, "%s", root) != EOF) {
+    if (COLDSTART) {
+      fscanf (stdin, "%lf %lf", &psfx, &sky);
+    }
+    else {
+      fscanf (stdin, "%lf %lf %lf %lf", &psfx, &psfy, &tilt, &sky);
+    }
+
+    /* we demand that the image names have the *.f extension */
+    if (strncmp (&root[strlen(root) - 2], ".f", 2)) {
+      fprintf (stderr, "valid image names are *.f\n");
+      exit (0);
+    }
+
+    ft = fopen (root, "r");
+    if (ft == NULL) {
+      fprintf (stderr, "image %s does not exist\n", root);
+      continue;
+    }
+    fclose(ft);
+
+    /* root contains *.f, remove the .f portion: */
+    root[strlen(root) - 2] = 0;
+
+    strcpy (name, root);
+    strcat (name, ".par_in");
+    f = fopen (name, "w");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "couldn't write to parameter file %s\n", name);
+      continue;
+    }
+    fprintf (f, "FWHM = %f\n", psfx);
+    fprintf (f, "SKY = %f\n", sky);
+    if (!COLDSTART) {
+      fprintf (f, "AXIS_RATIO = %f\n", psfy/psfx);
+      fprintf (f, "TILT = %f\n", tilt);
+    }
+    fprintf (f, "=\n");
+    fprintf (f, "PARAMS_DEFAULT = 'dophot.params'\n");
+    fprintf (f, "PARAMS_OUT = '%s.par_out'\n", root);
+    if (THRESHOLD) {
+      fprintf (f, "AUTOTHRESH = 'NO'\n");     
+      fprintf (f, "THRESHMIN = %f\n", THRESHOLD);
+    }
+    else {
+      fprintf (f, "AUTOTHRESH = 'YES'\n");     
+    }
+    fprintf (f, "=\n");
+    fprintf (f, "IMAGE_IN = '%s.f'\n", root);
+    if (OUTIMAGE) 
+      fprintf (f, "IMAGE_OUT = '%s.s'\n", root);
+    else
+      fprintf (f, "IMAGE_OUT = ' '\n");
+    if (!COLDSTART) {
+      strcpy (name, root);
+      strcat (name, ".obj_out");
+      ft = fopen (name, "r");
+      if (ft != (FILE *) NULL) {
+	fclose (ft);
+	sprintf (line, "mv %s.obj_out %s.obj_in\0", root, root);
+	system (line);
+	fprintf (f, "OBJECTS_IN = '%s.obj_in'\n", root);
+      }
+      else {
+	fprintf (f, "OBJECTS_IN = ' '\n");
+      }
+    }
+    else {
+      fprintf (f, "OBJECTS_IN = ' '\n");
+    }
+    fprintf (f, "OBJECTS_OUT = '%s.obj_out'\n", root);
+    fprintf (f, "=\n");
+
+    if (!COLDSTART) {
+      strcpy (name, root);
+      strcat (name, ".shd_out");
+      ft = fopen (name, "r");
+      if (ft != (FILE *) NULL) {
+	fclose (ft);
+	sprintf (line, "mv %s.shd_out %s.shd_in\0", root, root);
+	system (line);
+	fprintf (f, "SHADOWFILE_IN = '%s.shd_in'\n", root);
+      }
+      else {
+	fprintf (f, "SHADOWFILE_IN = ' '\n");
+      }
+    }
+    else {
+      fprintf (f, "SHADOWFILE_IN = ' '\n");
+    }
+    fprintf (f, "SHADOWFILE_OUT = '%s.shd_out'\n", root);
+    
+    fprintf (f, "END\n");
+    fclose (f);
+
+    fprintf (stdout, "dophot << END > %s.dout\n", root);
+    fprintf (stdout, "%s.par_in\n", root);
+    fprintf (stdout, "END\n");
+  }
+}
+
+/* 
+  original image: image
+  flattened im:   image.f
+  star sub image: image.s
+  dp params in:   image.par_in
+  dp params out:  image.par_out
+  dp objects in:  image.obj_in
+  dp objects out: image.obj_out
+  dp shadow in:   image.shd_in
+  dp shadow out:  image.shd_out
+*/
+
+void args (argc, argv)
+     int      argc;
+     char   **argv;
+{
+  
+  int N;
+  
+  if (get_argument (argc, argv, "-h") || get_argument (argc, argv, "-help")) {
+    error ();
+  }
+
+  COLDSTART = TRUE;
+  if (N = get_argument (argc, argv, "-w")) {
+    remove_argument (N, &argc, argv);
+    COLDSTART = FALSE;
+  }
+  if (N = get_argument (argc, argv, "-warm")) {
+    remove_argument (N, &argc, argv);
+    COLDSTART = FALSE;
+  }
+  
+  OUTIMAGE = FALSE;
+  if (N = get_argument (argc, argv, "-sub")) {
+    remove_argument (N, &argc, argv);
+    OUTIMAGE = TRUE;
+  }
+
+  THRESHOLD = 0;
+  if (N = get_argument (argc, argv, "-t")) {
+    remove_argument (N, &argc, argv);
+    if (N < argc) {
+      THRESHOLD = atof (argv[N]);
+    } 
+    else {
+      error ();
+    }   
+  }
+}
+
+void error ()
+{
+  fprintf (stderr, "USAGE:\n");
+  fprintf (stderr, "  doscript [-w/-warm] [-sub] [-t threshold]\n");
+  fprintf (stderr, "    default is coldstart -- takes from stdin: filename FWHM sky\n");
+  fprintf (stderr, "    -w, -warm: warmstart -- takes from stdin: filename FWHMx FWHMy angle sky'\n");
+  fprintf (stderr, "    -t: set minimum threshold, also sets AUTOTHRESH = 'NO'\n");
+  fprintf (stderr, "    -sub: generate star-substracted images\n");
+  exit (0);
+}
Index: /tags/start/Ohana/src/misc/src/dostat.c
===================================================================
--- /tags/start/Ohana/src/misc/src/dostat.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/dostat.c	(revision 12606)
@@ -0,0 +1,84 @@
+# include <ohana.h>
+
+main() {
+
+  FILE *f, *fopen();
+  char file[50];
+  int N,n1,n2,n3,n4,n5,n6,n7,n8,nperf,type,status;
+  double Fx,Fy,alpha, FWHMx,FWHMy,angle, ap, F, S, sky;
+  double dtype, A, A2, Ap, Ap2, apmifit, df, S2;
+  char line[512];
+
+  while (fscanf (stdin, "%s", file) != EOF) {
+    f = fopen (file, "r");
+    if (f == NULL) {
+      fprintf (stderr, "file %s not found\n", file);
+      continue;
+    }
+    n1 = n2 = n3 = n4 = n5 = n6 = n7 = n8 = nperf = 0;
+    S2 = S = Fx = Fy = alpha = A = A2 = 0;
+    while (scan_line (f, line) != EOF) {
+      status = TRUE;
+      status &= dparse (&dtype, 2, line);
+      status &= dparse (&df,   6, line);
+      status &= dparse (&sky,   7, line);
+      status &= dparse (&FWHMx, 8, line);
+      status &= dparse (&FWHMy, 9, line);
+      status &= dparse (&angle, 10, line);
+      status &= dparse (&ap,      12, line);
+      status &= dparse (&apmifit, 15, line);
+      if (!status) {
+	fprintf (stderr, "error in file %s, line %d\n", file, n1+n2+n3+n4+n5+n6+n7+n8);
+	continue;
+      }
+      type = dtype;
+      switch (type) {
+      case 1:
+	n1 ++;
+	S += sky;
+	if (ap < 99) {
+	  nperf ++;
+	  A += apmifit/(df*df);
+	  A2 += apmifit*apmifit/(df*df);
+	  S2 += 1.0/(df*df);
+	}
+	Fx = FWHMx;
+	Fy = FWHMy;
+	alpha = angle;
+	break;
+      case 2:
+	n2 ++;
+	break;
+      case 3:
+	n3 ++;
+	break;
+      case 4:
+	n4 ++;
+	break;
+      case 5:
+	n5 ++;
+	break;
+      case 6:
+	n6 ++;
+	break;
+      case 7:
+	n7 ++;
+	break;
+      case 8:
+	n8 ++;
+	break;
+      }
+    }
+    S= S / (1.0*n1);
+    F = nperf / (1.0 * n1);
+    N = n1+n2+n3+n4+n5+n6+n7+n8;
+    Ap = A / S2;
+    Ap2 = sqrt(A2 / (S2) - Ap*Ap);
+    fprintf (stdout, "%s: %5d %5d %5d %5d %5d %5d %5d %5d",
+	     file,n1,n2,n3,n4,n5,n6,n7,n8);
+    fprintf (stdout, "  %5d %5d  %5.3f %7.2f %7.2f %7.1f %7.1f %7.3f %7.3f\n",
+	     N, nperf, F, Fx, Fy, alpha, S, Ap, Ap2);
+    fclose(f);
+  }
+}
+
Index: /tags/start/Ohana/src/misc/src/fakecmp.c
===================================================================
--- /tags/start/Ohana/src/misc/src/fakecmp.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/fakecmp.c	(revision 12606)
@@ -0,0 +1,137 @@
+# include <ohana.h>
+static char reserved[] = "COMMENT  Reserved space.  This line can be used to add a new FITS card.";
+
+void main (int argc, char **argv) {
+
+  int i, j, N, status;
+  int Nreserved, start_size;
+  char *p, keyword[16], line[256];
+  FILE *f;
+  Header header;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: fits_insert (input) (template) (output)\n");
+    exit (2);
+  }
+  
+  /*
+    input file consists of: RA DEC MAG dMAG
+    we generate an artificial image with 1 arcsec/pix
+    and the pixel (0,0) at (<RA>,<DEC>)
+    
+    1) find <RA>, <DEC>
+    2) convert X,Y to R,D using <RA>,<DEC> (ra---sin)
+    3) fix template entries: CRVAL1, CRVAL2, NSTARS, (JD)
+    4) write out template
+    5) write out infile in correct format:
+    X     Y      M      dM   T S   Ma     Mb        Fx     Fy  Th
+    237.2 2646.1 16.748 085  1 2.0 17.930 17.768    nan    nan -48.0
+  */
+
+  /* allocate data space */
+  NSTARS = 1000;
+  ALLOCATE (ra, double, NSTARS);
+  ALLOCATE (dec, double, NSTARS);
+  ALLOCATE (mag, double, NSTARS);
+  ALLOCATE (dmag, double, NSTARS);
+
+  /* open data file */
+  f = fopen (argv[1], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open data file %s\n", argv[1]);
+    exit (1);
+  }
+
+  /* load data file into array */
+  for (i = 0;
+       fscanf (f, "%lf %lf %lf %lf", &ra[i], &dec[i], &mag[i], &dmag[i]) != EOF;
+       i++) {
+    
+    if (i == NSTARS - 1) {
+      NSTARS += 1000;
+      REALLOCATE (ra, double, NSTARS);
+      REALLOCATE (dec, double, NSTARS);
+      REALLOCATE (mag, double, NSTARS);
+      REALLOCATE (dmag, double, NSTARS);
+    }
+  }
+  NSTARS = i;
+
+  /* calculate <ra>, <dec> */
+  RA = DEC = 0;
+  for (i = 0; i < NSTARS; i++) {
+    RA += ra[i];
+    
+
+  /* load header from image file */
+  if (!fits_read_header (argv[1], &header)) {
+    fprintf (stderr, "can't open fits file %s\n", argv[1]);
+    exit (1);
+  }
+  start_size = header.size;
+
+  /* run through the lines in the header data file */
+  while (scan_line (f, line) != EOF) {
+    
+    /* fill in end of line with blanks, force end at 80 */
+    for (N = strlen (line); N < 80; N++) {
+      line[N] = ' ';
+    }
+    line[80] = 0;
+    bzero (keyword, 10);
+    strncpy (keyword, line, 8);
+    
+    /* replace existing keywords, unless this is a COMMENT or HISTORY field */
+    if (strncmp (keyword, "COMMENT ", 8) && strncmp (keyword, "HISTORY ", 8)) {
+      p = fits_header_field (&header, keyword, 1);
+      if (p != (char *) NULL) {
+	strncpy (p, line, 80);
+	continue;
+      }
+    }
+
+    /* find first line with the reserved line */
+    p = (char *) NULL;
+    Nreserved = strlen (reserved);
+    for (i = 0; (i < header.size) && (p == (char *) NULL) ; i+= FT_LINE_LENGTH) {
+      if (!strncmp (&header.buffer[i], reserved, Nreserved)) {
+	p = &header.buffer[i];
+      }
+    }
+    if (p == (char *) NULL) {
+      fprintf (stderr, "no more reserved spaces!\n");
+      exit (1);
+    }
+
+    /* insert the new line here */
+    strncpy (p, line, 80);
+  }
+
+  fclose (f);
+
+  /* now write the new header on top of the old one. 
+     check first that the header size has not changed.
+  */
+
+  if (header.size != start_size) {
+    fprintf (stderr, "header changed size: should not happen!\n");
+    exit (1);
+  }
+
+  f = fopen (argv[1], "r+");
+  if (f == NULL) {
+    fprintf (stderr, "can't open file for update %s\n", argv[1]);
+    exit (1);
+  }
+
+  fseek (f, 0, SEEK_SET);
+  status = fwrite (header.buffer, 1, header.size, f);
+  if (status != header.size) {
+    fprintf (stderr, "failed to write data to image header\n");
+    exit (1);
+  }
+  fclose (f);
+
+  exit (0);
+}
+    
Index: /tags/start/Ohana/src/misc/src/fakedist.c
===================================================================
--- /tags/start/Ohana/src/misc/src/fakedist.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/fakedist.c	(revision 12606)
@@ -0,0 +1,547 @@
+# include <ohana.h>
+
+# define NGAUSS 2048
+double drand48();
+double gaussint[NGAUSS];
+double gaussian();
+double rnd_gauss();
+
+# define MMIN 1.0
+# define MMAX 120.0
+double rnd_mass();
+double MassTerm;
+
+# define NMASS 87
+# define DMASS 0.05
+# define NPARMAX 30
+int N_Av, N_dist, N_alpha, N_age, NSTARS, NTRY;
+double Av[NPARMAX], dist[NPARMAX], alpha[NPARMAX], age[NPARMAX];
+
+double dVo, dVref, dMo;   /* determine the noise distribution */
+
+double ldA, lAo, ldM, lMo;
+double UV0, V0, DV, DUV;
+Header header, UV_h, V_h, mass_h, age_h;
+Matrix matrix, UV_i, V_i, mass_i, age_i;
+int UV_NX, UV_NY;
+float *UVbuffer, *Vbuffer;
+int MS_NX, MS_NY;
+float *Mbuffer, *Abuffer;
+
+char fakefile[256], magfile[256], colorfile[256], massfile[256], agefile[256];
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+
+  int i, j, m, n, M, A, Nstars;
+  double mag, color, mass, noise, inflation;
+  float *in;
+  char line[1024];
+
+  load_parameters (argc, argv);
+
+  init_outmatrix (); 
+ 
+  gauss_init ();
+
+  read_datafiles ();
+
+  fits_modify (&header, "SFR", "%s", 1, "Star Formation Rate (Mo / Myr)");
+  for (i = 0; i < N_Av; i++) {
+    for (j = 0; j < N_dist; j++) {
+      for (m = 0; m < N_alpha; m++) {
+	
+	MassTerm = (pow((MMAX/MMIN), -alpha[m]) - 1.0);
+	for (n = 0; n < N_age; n++) {
+	  fprintf (stderr, "age: %d %f -- %f\n", n, age[n], age[n+1]);
+	  
+	  mass = 0;
+	  for (Nstars = 0; Nstars < NSTARS; Nstars++) {
+	    fakestar (Av[i], dist[j], alpha[m], age[n], age[n+1], 
+		      &mag, &color, &mass, &noise);
+	    
+	    magtomass (Av[i], dist[j], mag, color, noise, &M, &A, &inflation);
+
+	    if (inflation > 0.0) add_to_outmatrix (i, j, m, n, A, M, inflation);
+	    
+	  }
+	  /* store the parameters and total mass for this Mass*Age matrix in the (N_age) column */
+	  /* mass is the total mass generated between 1 and 120 Mo for the NSTARS points in this matrix */
+	  sprintf (line, "SFR_%0d\0", n);
+	  fits_modify (&header, line, "%lf", 1, mass / (age[n+1] - age[n]));
+	  add_to_outmatrix (i, j, m, n, N_age, 0, mass);
+	  add_to_outmatrix (i, j, m, n, N_age, 1, Av[i]);
+	  add_to_outmatrix (i, j, m, n, N_age, 2, dist[j]);
+	  add_to_outmatrix (i, j, m, n, N_age, 3, alpha[m]);
+	  add_to_outmatrix (i, j, m, n, N_age, 4, age[n]);
+	  add_to_outmatrix (i, j, m, n, N_age, 5, age[n+1]);
+	  
+	}
+      }
+    }
+  }
+
+  /* 
+  in = (float *)matrix.buffer;
+  for (i = 0; i < matrix.Naxis[0]; i++) {
+    for (j = 0; j < matrix.Naxis[1]; j++) {
+      mass = in[i + matrix.Naxis[0]*(j + matrix.Naxis[1]*2)];
+      fprintf (stderr, "%f ", mass);
+    }
+    fprintf (stderr, "\n");
+  }
+  */
+
+  fits_write_header (fakefile, &header);
+  fits_write_matrix (fakefile, &matrix);
+}
+
+/*****************************************************************************/
+
+load_parameters (argc, argv)
+int argc;
+char **argv;
+{
+
+  int i, stat, test_dVo, test_dVref, test_dMo;
+  int Ffile, Mfile, Cfile, Afile, MSfile;
+  FILE *f;
+  char line[1024];
+  double N_stars, N_try, Ntotal, time;
+
+  if (argc < 2) {
+    fprintf (stderr, "USAGE: %s pfile\n", argv[0]);
+    exit (0);
+  }
+
+  f = fopen (argv[1], "r");
+  if (f == NULL) {
+    fprintf (stderr, "parameter file %s not found\n", argv[1]);
+    exit (0);
+  }
+
+  N_Av = N_dist = N_alpha = N_age = N_stars = N_try = 0.0;
+  test_dVo = test_dVref = test_dMo = FALSE;
+  Ffile = Mfile = Cfile = Afile = MSfile = FALSE;
+  while (scan_line (f, line) != EOF) {
+    if (!stripwhite (line)) continue;
+    if (line[0] == '#') continue;
+    
+    if (!strncmp (line, "Av ", strlen ("Av "))) {
+      for (i = 0; (i < NPARMAX) && (stat = dparse (&Av[i], i+2, line)); i++);
+      if (i == NPARMAX) {
+	fprintf (stderr, "maximum of %d parameter values per parameter\n", NPARMAX);
+	exit (0);
+      }
+      N_Av = i;
+    }
+
+    if (!strncmp (line, "dist ", strlen ("dist "))) {
+      for (i = 0; (i < NPARMAX) && dparse (&dist[i], i+2, line); i++);
+      if (i == NPARMAX) {
+	fprintf (stderr, "maximum of %d parameter values per parameter\n", NPARMAX);
+	exit (0);
+      }
+      N_dist = i;
+    }
+
+    if (!strncmp (line, "alpha ", strlen ("alpha "))) {
+      for (i = 0; (i < NPARMAX) && dparse (&alpha[i], i+2, line); i++);
+      if (i == NPARMAX) {
+	fprintf (stderr, "maximum of %d parameter values per parameter\n", NPARMAX);
+	exit (0);
+      }
+      N_alpha = i;
+    }
+
+    if (!strncmp (line, "age ", strlen ("age "))) {
+      for (i = 0; (i < NPARMAX) && dparse (&age[i], i+2, line); i++);
+      if (i == NPARMAX) {
+	fprintf (stderr, "maximum of %d parameter values per parameter\n", NPARMAX);
+	exit (0);
+      }
+      N_age = MAX (0, i - 1);
+    }
+
+    if (!strncmp (line, "dVo ", strlen ("dVo "))) {
+      dparse (&dVo, 2, line);
+      test_dVo = TRUE;
+    }
+    
+    if (!strncmp (line, "dVref ", strlen ("dVref "))) {
+      dparse (&dVref, 2, line);
+      test_dVref = TRUE;
+    }
+    
+    if (!strncmp (line, "dMo ", strlen ("dMo "))) {
+      dparse (&dMo, 2, line);
+      test_dMo = TRUE;
+    }
+    
+    if (!strncmp (line, "nstars ", strlen ("nstars "))) {
+      dparse (&N_stars, 2, line);
+      NSTARS = N_stars;
+    }
+    
+    if (!strncmp (line, "ntry ", strlen ("ntry "))) {
+      dparse (&N_try, 2, line);
+      NTRY = N_try;
+    }
+    
+    if (!strncmp (line, "magfile ", strlen ("magfile "))) {
+      sscanf (line, "%*s %s", magfile);
+      fprintf (stderr, "magfile: %s\n", magfile);
+      Mfile = TRUE;
+    }
+    
+    if (!strncmp (line, "colorfile ", strlen ("colorfile "))) {
+      sscanf (line, "%*s %s", colorfile);
+      fprintf (stderr, "colorfile: %s\n", colorfile);
+      Cfile = TRUE;
+    }
+    
+    if (!strncmp (line, "agefile ", strlen ("agefile "))) {
+      sscanf (line, "%*s %s", agefile);
+      fprintf (stderr, "agefile: %s\n", agefile);
+      Afile = TRUE;
+    }
+    
+    if (!strncmp (line, "massfile ", strlen ("massfile "))) {
+      sscanf (line, "%*s %s", massfile);
+      fprintf (stderr, "massfile: %s\n", massfile);
+      MSfile = TRUE;
+    }
+    
+    if (!strncmp (line, "fakefile ", strlen ("fakefile "))) {
+      sscanf (line, "%*s %s", fakefile);
+      fprintf (stderr, "fakefile: %s\n", fakefile);
+      Ffile = TRUE;
+    }
+    
+    if (N_Av && N_dist && N_alpha && N_age && N_stars && N_try && 
+	test_dVo && test_dVref && test_dMo &&
+	Ffile && Mfile && Cfile && Afile && MSfile) {
+      Ntotal = N_Av * N_dist * N_alpha * N_age * N_stars * N_try;
+      time = (Ntotal / 1250000.0);
+      fprintf (stderr, "%.0f iterations\n", Ntotal);
+      fprintf (stderr, "process should take about %.1f minutes\n", time);
+      return;
+    }
+  }
+  
+  if (!(N_Av && N_dist && N_alpha && N_age && NSTARS && NTRY && 
+	test_dVo && test_dVref && test_dMo && 
+	Ffile && Mfile && Cfile && Afile && MSfile)) {
+    fprintf (stderr, "failed to get all parameter lines\n");
+    fprintf (stderr, "N_Av: %d\n", N_Av);
+    fprintf (stderr, "N_dist: %d\n", N_dist);
+    fprintf (stderr, "N_alpha: %d\n", N_alpha);
+    fprintf (stderr, "N_age: %d\n", N_age);
+    fprintf (stderr, "N_stars: %d\n", NSTARS);
+    fprintf (stderr, "N_try: %d\n", NTRY);
+    fprintf (stderr, "dVo: %f (%d)\n", dVo, test_dVo);
+    fprintf (stderr, "dVref: %f (%d)\n", dVref, test_dVref);
+    fprintf (stderr, "dMo: %f (%d)\n", dMo, test_dMo);
+    fprintf (stderr, "Ffile: %d\n", Ffile);
+    fprintf (stderr, "Mfile: %d\n", Mfile);
+    fprintf (stderr, "Cfile: %d\n", Cfile);
+    fprintf (stderr, "Afile: %d\n", Afile);
+    fprintf (stderr, "MSfile: %d\n", MSfile);
+    exit (0);
+  }
+  
+}
+
+/*****************************************************************************/
+
+
+init_outmatrix () 
+{
+
+  int i;
+  char line[32];
+  double value;
+
+  header.bitpix = -32;
+  header.Naxes = 7;
+  header.Naxis[0] = NMASS;
+  header.Naxis[1] = N_age + 1;
+  header.Naxis[2] = N_age;
+  header.Naxis[3] = N_alpha;
+  header.Naxis[4] = N_dist;
+  header.Naxis[5] = N_Av;
+  header.Naxis[6] = 2;
+  header.bzero = 0.0;
+  header.bscale = 1.0;
+  header.unsign = FALSE;
+  header.extend = FALSE;
+
+  fits_create_header (&header);
+  fits_create_matrix (&header, &matrix);
+
+  fits_modify (&header, "PAR_1", "%s", 1, "mass (Mo)");
+  for (i = 0; i < NMASS + 1; i++) {
+    sprintf (line, "PAR_1_%0d\0", i);
+    value = 10.0 / SQ(4.5 - DMASS*i);
+    fits_modify (&header, line, "%lf", 1, value);
+  }
+  
+  fits_modify (&header, "PAR_2", "%s", 1, "age out (Myr)");
+  for (i = 0; i < N_age + 1; i++) {
+    sprintf (line, "PAR_2_%0d\0", i);
+    fits_modify (&header, line, "%lf", 1, age[i]);
+  }
+
+  fits_modify (&header, "PAR_3", "%s", 1, "age in (Myr)");
+  for (i = 0; i < N_age + 1; i++) {
+    sprintf (line, "PAR_3_%0d\0", i);
+    fits_modify (&header, line, "%lf", 1, age[i]);
+  }
+  
+  fits_modify (&header, "PAR_4", "%s", 1, "alpha");
+  for (i = 0; i < N_alpha; i++) {
+    sprintf (line, "PAR_4_%0d\0", i);
+    fits_modify (&header, line, "%lf", 1, alpha[i]);
+  }
+
+  fits_modify (&header, "PAR_5", "%s", 1, "dist (mag)");
+  for (i = 0; i < N_dist; i++) {
+    sprintf (line, "PAR_5_%0d\0", i);
+    fits_modify (&header, line, "%lf", 1, dist[i]);
+  }
+
+  fits_modify (&header, "PAR_6", "%s", 1, "A_V (mag)");
+  for (i = 0; i < N_Av; i++) {
+    sprintf (line, "PAR_6_%0d\0", i);
+    fits_modify (&header, line, "%lf", 1, Av[i]);
+  }
+
+}
+
+
+/*****************************************************************************/
+
+fakestar (A_V, Dist, Alpha, AgeS, AgeE, mag, color, Mass, Noise)
+double A_V, Dist, Alpha, AgeS, AgeE;
+double *Mass, *mag, *color, *Noise;
+{
+
+  int X, Y, i;
+  double mass, Age, v, uv, noise;
+
+  for (i = 0; i < 500; i++) {
+    mass = rnd_mass (Alpha);
+    Age = (AgeE - AgeS)*drand48() + AgeS;
+    *Mass += mass;
+    
+    /* find star in color, mag images */
+    X = (log10(Age) - lAo) / ldA;
+    Y = (log10(mass) - lMo) / ldM;
+    if ((X >= 0) && (X < UV_NX) && (Y >= 0) && (Y < UV_NY)) {
+      uv = UVbuffer[X + UV_NX*Y];
+      if (uv != 100.0) {
+	uv += 0.7*A_V;   /***** this depends on the extinction law and colors U-V ***/
+	v = Vbuffer[X + UV_NX*Y] + Dist + A_V; 
+	noise = dVo*sqrt(1.0 + pow (10.0, (0.4*(v - dVref)))); 
+	if (noise < dMo) {
+	  *Noise = noise;
+	  *mag = rnd_gauss (v, noise);
+	  *color = rnd_gauss (uv, 1.4*noise);
+	  return;
+	}
+      }
+    }
+  }
+  fprintf (stderr, "problem with generating stars:  none land in safe zone\n");
+  exit (0);
+}
+
+
+
+/* rnd_mass only returns stars with masses in the range MMIN to MMAX */
+double
+rnd_mass (Alpha)
+double Alpha;
+{
+  
+  double dP, x;
+  
+  x = (MMAX + 1);
+  while (x > MMAX) {
+    dP = drand48();
+    x = MMIN * pow ((dP*MassTerm + 1.0), 1.0 / (-Alpha));
+  }
+  return (x);
+
+}
+
+/*****************************************************************************/
+
+read_datafiles ()
+{
+
+  fits_read_header (colorfile, &UV_h);
+  fits_read_matrix (colorfile, &UV_i);
+  fits_read_header (magfile, &V_h);
+  fits_read_matrix (magfile, &V_i); 
+  UV_NX = UV_h.Naxis[0];
+  UV_NY = UV_h.Naxis[1];
+  UVbuffer = (float *)UV_i.buffer;
+  Vbuffer = (float *)V_i.buffer;
+
+  fits_scan (&UV_h, "RA_O",  "%lf", 1, &lAo);
+  fits_scan (&UV_h, "RA_X",  "%lf", 1, &ldA);
+  fits_scan (&UV_h, "DEC_O", "%lf", 1, &lMo);
+  fits_scan (&UV_h, "DEC_Y", "%lf", 1, &ldM);
+
+  fits_read_header (massfile, &mass_h);
+  fits_read_matrix (massfile, &mass_i);
+  fits_read_header (agefile, &age_h);
+  fits_read_matrix (agefile, &age_i); 
+  MS_NX = mass_h.Naxis[0];
+  MS_NY = mass_h.Naxis[1];
+  Mbuffer = (float *)mass_i.buffer;
+  Abuffer = (float *)age_i.buffer;
+
+  fits_scan (&mass_h, "RA_O",  "%lf", 1, &UV0);
+  fits_scan (&mass_h, "RA_X",  "%lf", 1, &DUV);
+  fits_scan (&mass_h, "DEC_O", "%lf", 1, &V0);
+  fits_scan (&mass_h, "DEC_Y", "%lf", 1, &DV);
+} 
+
+/*****************************************************************************/
+
+double
+rnd_gauss (mean, sigma)
+double mean, sigma; 
+{
+
+  int i;
+  double y;
+
+  y = drand48();
+  i = NGAUSS*y;
+  y = gaussint[i]*sigma + mean;
+
+  return (y);
+
+}
+
+gauss_init ()
+{
+
+  int i;
+  long A, B;
+  double val, x, dx, dx1, dx2, dx3, df;
+  double mean, sigma;
+
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+
+  val = 0;
+  dx = 0.001;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+  mean = 0.0;
+  sigma = 1.0;
+
+  for (i = 0, x = -7.0; (i < NGAUSS) && (x < 7.0); x += dx)  {
+    df = (3.0*gaussian(x    , mean, sigma) + 
+	  9.0*gaussian(x+dx1, mean, sigma) +
+	  9.0*gaussian(x+dx2, mean, sigma) + 
+	  3.0*gaussian(x+dx3, mean, sigma)) * (dx1/8.0);
+    val += df;
+    if (val > (i / (double) NGAUSS)) {
+      gaussint[i] = x + dx / 2.0;
+      i++;
+    }
+  }
+  return (x + dx / 2.0);
+}
+
+double 
+gaussian (x, mean, sigma) 
+double x, mean, sigma; 
+{
+
+  double f, X;
+
+  f = exp (-0.5 * SQ(x - mean) / SQ(sigma)) / sqrt(2 * M_PI * SQ(sigma));
+
+  return (f);
+
+}
+
+/*****************************************************************************/
+
+magtomass (A_V, Dist, mag, color, noise, M, A, inflation)
+double A_V, Dist, mag, color, noise;
+int *M, *A;
+double *inflation;
+{
+
+  int x, y, I, J, i, j, k;
+  double mass, Age, v, uv, Ngood;
+
+  *inflation = 0.0;
+  x = (color - UV0 - 0.7*A_V) / DUV;   /* again, depends on U-V and extinction */
+  y = (mag - Dist - V0 - A_V) / DV;
+  if ((x > 0) && (x < MS_NX) && (y > 0) && (y < MS_NY)) {
+    mass = Mbuffer[x + MS_NX*y];
+    if (mass > 0.0) {
+      Age = Abuffer[x + MS_NX*y];
+      /* age[i]: i = 0,N_age */
+      if ((Age < age[0]) || (Age > age[N_age])) {
+	*inflation = 0.0;
+	return;
+      }
+      for (I = 0; (I < N_age) && (Age > age[I+1]); I++);
+      J = MAX (MIN ((4.5 - sqrt(10.0/mass)) / DMASS, NMASS - 1), 0);
+      Ngood = 1.0;
+      for (k = 0; k < NTRY; k++) {
+	v = rnd_gauss (mag, noise);
+	uv = rnd_gauss (color, 1.4*noise);
+	x = (uv - UV0 - 0.7*A_V) / DUV;
+	y = (v - V0 - Dist - A_V) / DV;
+	if ((x > 0) && (x < MS_NX) && (y > 0) && (y < MS_NY)) {
+	  mass = Mbuffer[x + MS_NX*y];
+	  if (mass > 0.0) {
+	    Age = Abuffer[x + MS_NX*y];
+	    for (i = -1; (i < N_age) && (Age > age[i+1]); i++);
+	    j = MAX (MIN ((4.5 - sqrt(10.0/mass)) / DMASS, NMASS - 1), 0);
+	    if ((i == I) && (j == J)) {
+	      Ngood += 1.0;
+	    }
+	  }
+	}
+      }
+      *inflation = (NTRY / Ngood);
+      *M = J;
+      *A = I;
+    }
+  }
+  if (mass == 0.0) *inflation = 0.0;
+}
+ 
+
+/*****************************************************************************/
+
+add_to_outmatrix (AV, DIST, ALPHA, AGE_IN, AGE_OUT, MASS, value)
+int AV, DIST, ALPHA, AGE_IN, AGE_OUT, MASS;
+double value;
+{
+
+  float *buffer;
+
+  buffer = (float *)matrix.buffer;
+  
+  /* elements in the (N_age) row of each Mass*Age matrix contain special numbers for the matrix */
+  buffer[MASS + NMASS*(AGE_OUT + (N_age + 1)*(AGE_IN + N_age*(ALPHA + N_alpha*(DIST + N_dist*(AV + N_Av*(0))))))] += value;
+  buffer[MASS + NMASS*(AGE_OUT + (N_age + 1)*(AGE_IN + N_age*(ALPHA + N_alpha*(DIST + N_dist*(AV + N_Av*(1))))))] += 1.0;
+
+}
+
Index: /tags/start/Ohana/src/misc/src/fakedump.c
===================================================================
--- /tags/start/Ohana/src/misc/src/fakedump.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/fakedump.c	(revision 12606)
@@ -0,0 +1,69 @@
+# include <ohana.h>
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+
+  Header in_h, out_h;
+  Matrix in_m, out_m;
+  int i, j;
+  int Nage, Nalpha, Ndist, NAv;
+  float *in, *out;
+
+  if (argc < 7) {
+    fprintf (stderr, "USAGE fakedump infile outfile Nage Nalpha Ndist NAv\n");
+    exit (0);
+  }
+  Nage = atof(argv[3]);
+  Nalpha = atof(argv[4]);
+  Ndist = atof(argv[5]);
+  NAv = atof(argv[6]);
+
+  fits_read_header (argv[1], &in_h);
+  fits_read_matrix (argv[1], &in_m);
+
+  if (Nage > in_h.Naxis[2] - 1) {
+    fprintf (stderr, "Nage too big (%d, %d)\n", Nage, in_h.Naxis[2] - 1);
+    exit (0);
+  }
+
+  if (Nalpha > in_h.Naxis[3] - 1) {
+    fprintf (stderr, "Nalpha too big (%d, %d)\n", Nalpha, in_h.Naxis[3] - 1);
+    exit (0);
+  }
+
+  if (Ndist > in_h.Naxis[4] - 1) {
+    fprintf (stderr, "Ndist too big (%d, %d)\n", Ndist, in_h.Naxis[4] - 1);
+    exit (0);
+  }
+
+  if (NAv > in_h.Naxis[5] - 1) {
+    fprintf (stderr, "NAv too big (%d, %d)\n", NAv, in_h.Naxis[5] - 1);
+    exit (0);
+  }
+
+  out_h.bitpix = -32;
+  out_h.Naxes = 2;
+  out_h.Naxis[0] = in_h.Naxis[0];
+  out_h.Naxis[1] = in_h.Naxis[1] - 1;
+  out_h.bzero = 0.0;
+  out_h.bscale = 1.0;
+  out_h.unsign = FALSE;
+  out_h.extend = FALSE;
+  fits_create_header (&out_h);
+  fits_create_matrix (&out_h, &out_m);
+  
+  in = (float *)in_m.buffer;
+  out = (float *)out_m.buffer;
+  for (i = 0; i < out_h.Naxis[0]; i++) {
+    for (j = 0; j < out_h.Naxis[1]; j++) {
+      out[i + out_h.Naxis[0]*j] = in[i + in_h.Naxis[0]*(j + in_h.Naxis[1]*(Nage + in_h.Naxis[2]*(Nalpha + in_h.Naxis[3]*(Ndist + in_h.Naxis[4]*(NAv + in_h.Naxis[5] * 0)))))];
+      fprintf (stderr, "%f ", out[i + out_h.Naxis[0]*j]);
+    }
+    fprintf (stderr, "\n");
+  }
+  
+  fits_write_header (argv[2], &out_h);
+  fits_write_matrix (argv[2], &out_m);
+}
Index: /tags/start/Ohana/src/misc/src/fakepop.c
===================================================================
--- /tags/start/Ohana/src/misc/src/fakepop.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/fakepop.c	(revision 12606)
@@ -0,0 +1,293 @@
+# include <ohana.h>
+# define MMIN 1.0
+# define MMAX 120.0
+extern double drand48();
+extern double rnd_mass();
+double rnd_mass();
+double term;
+extern double rnd_gauss();
+extern double rnd_integrate ();
+extern double gaussian ();
+
+double gaussian();
+double rnd_gauss();
+double rnd_integrate();
+
+# define NGAUSS 2048
+double gaussint[NGAUSS];
+
+double AgeS, AgeE, alpha, d, Av, dMo, dVo, dVref;
+char colorfile[256], magfile[256];
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+
+  Header UV_h, V_h;
+  Matrix UV_i, V_i;
+  double Mtot, M, mass;
+  double age, noise, v, uv, V, UV;
+  double lAo, ldA, lMo, ldM, stage;
+  int X, Y;
+  long A, B;
+  
+  load_parameters (argc, argv);
+  Mtot = atof (argv[2]);
+  term = (pow((MMAX/MMIN), -alpha) - 1.0);
+  
+  fits_read_header (colorfile, &UV_h);
+  fits_read_matrix (colorfile, &UV_i);
+  fits_read_header (magfile, &V_h);
+  fits_read_matrix (magfile, &V_i); 
+
+  fits_scan (&UV_h, "RA_O",  "%lf", 1, &lAo);
+  fits_scan (&UV_h, "RA_X",  "%lf", 1, &ldA);
+  fits_scan (&UV_h, "DEC_O", "%lf", 1, &lMo);
+  fits_scan (&UV_h, "DEC_Y", "%lf", 1, &ldM);
+  
+  gauss_init ();
+
+  fprintf (stderr, "beginning main loop\n");
+  
+  stage = 1;
+  for (M = 0; M < Mtot; ) {
+    age = (AgeE - AgeS)*drand48() + AgeS;
+    X = (log10(age) - lAo) / ldA;
+    if (M > stage * Mtot / 10.0) {
+      fprintf (stderr, "M: %f\n", M);
+      stage += 1.0;
+    }
+    mass = rnd_mass (alpha);
+    Y = (log10(mass) - lMo) / ldM;
+    if ((X >= 0) && (X < UV_h.Naxis[0]) &&
+	(Y >= 0) && (Y < UV_h.Naxis[1])) {
+      uv = fits_get_matrix_value (&UV_i, X, Y); 
+      if (uv != 100.0) {
+	uv += 0.7*Av;
+	v = fits_get_matrix_value (&V_i, X, Y) + d + Av; 
+	noise = dVo*sqrt(1.0 + pow (10.0, (0.4*(v - dVref)))); 
+	V = rnd_gauss (v, noise);
+	UV = rnd_gauss (uv, 1.4*noise);
+	if (noise < dMo) {
+	  fprintf (stdout, "%f %f   %f %f   %f  %f\n", V, noise, V+UV, noise, mass, age);
+	}
+      }
+    }
+    M += mass;
+  }
+}
+
+/* rnd_mass only returns stars with masses in the range MMIN to MMAX */
+double
+rnd_mass (alpha)
+double alpha;
+{
+  
+  double dP, x;
+  
+  x = (MMAX + 1);
+  while (x > MMAX) {
+    dP = drand48();
+    x = MMIN * pow ((dP*term + 1.0), 1.0 / (-alpha));
+  }
+  return (x);
+
+}
+
+
+double
+rnd_gauss (mean, sigma)
+double mean, sigma; 
+{
+
+  int i;
+  double y;
+
+  y = drand48();
+  i = NGAUSS*y;
+  y = gaussint[i]*sigma + mean;
+
+  return (y);
+
+}
+
+
+gauss_init ()
+{
+
+  int i;
+  long A, B;
+  double val, x, dx, dx1, dx2, dx3, df;
+  double mean, sigma;
+
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+
+  val = 0;
+  dx = 0.001;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+  mean = 0.0;
+  sigma = 1.0;
+
+  for (i = 0, x = -7.0; (i < NGAUSS) && (x < 7.0); x += dx)  {
+    df = (3.0*gaussian(x    , mean, sigma) + 
+	  9.0*gaussian(x+dx1, mean, sigma) +
+	  9.0*gaussian(x+dx2, mean, sigma) + 
+	  3.0*gaussian(x+dx3, mean, sigma)) * (dx1/8.0);
+    val += df;
+    if (val > (i / (double) NGAUSS)) {
+      gaussint[i] = x + dx / 2.0;
+      i++;
+    }
+  }
+  return (x + dx / 2.0);
+}
+
+double 
+rnd_integrate (function, range, mean, sigma) 
+double (*function) ();
+double range, mean, sigma;
+{
+
+  double val, x, dx, dx1, dx2, dx3, df;
+
+  range += 0.0001;
+  val = 0;
+  dx = sigma / 10.0;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+
+  for (x = mean - 7*sigma; (val < range) && (x < mean + 7*sigma); x += dx)  {
+    df = (3.0*function(x    , mean, sigma) + 
+	  9.0*function(x+dx1, mean, sigma) +
+	  9.0*function(x+dx2, mean, sigma) + 
+	  3.0*function(x+dx3, mean, sigma)) * (dx1/8.0);
+    val += df;
+  }
+  return (x + dx / 2.0);
+}
+
+double 
+gaussian (x, mean, sigma) 
+double x, mean, sigma; 
+{
+
+  double f, X;
+
+  f = exp (-0.5 * SQ(x - mean) / SQ(sigma)) / sqrt(2 * M_PI * SQ(sigma));
+
+  return (f);
+
+}
+
+
+/*****************************************************************************/
+
+load_parameters (argc, argv)
+int argc;
+char **argv;
+{
+
+  int test_dVo, test_dVref, test_dMo;
+  int test_Age, test_Av, test_alpha, test_d;
+  int Mfile, Cfile;
+  FILE *f;
+  char line[1024];
+
+  if (argc < 3) {
+    fprintf (stderr, "USAGE: %s pfile Mtot\n", argv[0]);
+    exit (0);
+  }
+
+  f = fopen (argv[1], "r");
+  if (f == NULL) {
+    fprintf (stderr, "parameter file %s not found\n", argv[1]);
+    exit (0);
+  }
+
+  test_Age = test_Av = test_alpha = test_d = FALSE;
+  test_dVo = test_dVref = test_dMo = FALSE;
+  Mfile = Cfile = FALSE;
+  while (scan_line (f, line) != EOF) {
+    if (!stripwhite (line)) continue;
+    if (line[0] == '#') continue;
+    
+    fprintf (stderr, "%s\n", line);
+    if (!strncmp (line, "Av ", strlen ("Av "))) {
+      dparse (&Av, 2, line);
+      test_Av = TRUE;
+    }
+
+    if (!strncmp (line, "dist ", strlen ("dist "))) {
+      dparse (&d, 2, line);
+      test_d = TRUE;
+    }
+
+    if (!strncmp (line, "alpha ", strlen ("alpha "))) {
+      dparse (&alpha, 2, line);
+      test_alpha = TRUE;
+    }
+
+    if (!strncmp (line, "age ", strlen ("age "))) {
+      test_Age  = dparse (&AgeS, 2, line);
+      test_Age &= dparse (&AgeE, 3, line);
+    }
+
+    if (!strncmp (line, "dVo ", strlen ("dVo "))) {
+      dparse (&dVo, 2, line);
+      test_dVo = TRUE;
+    }
+    
+    if (!strncmp (line, "dVref ", strlen ("dVref "))) {
+      dparse (&dVref, 2, line);
+      test_dVref = TRUE;
+    }
+    
+    if (!strncmp (line, "dMo ", strlen ("dMo "))) {
+      dparse (&dMo, 2, line);
+      test_dMo = TRUE;
+    }
+    
+    if (!strncmp (line, "magfile ", strlen ("magfile "))) {
+      sscanf (line, "%*s %s", magfile);
+      fprintf (stderr, "magfile: %s\n", magfile);
+      Mfile = TRUE;
+    }
+    
+    if (!strncmp (line, "colorfile ", strlen ("colorfile "))) {
+      sscanf (line, "%*s %s", colorfile);
+      fprintf (stderr, "colorfile: %s\n", colorfile);
+      Cfile = TRUE;
+    }
+    
+    if (test_Age && test_Av && test_d && test_alpha && 
+	test_dVo && test_dVref && test_dMo &&
+	Mfile && Cfile) {
+      return;
+    }
+  }
+  
+  if (!(test_Age && test_Av && test_d && test_alpha && 
+	test_dVo && test_dVref && test_dMo && 
+	Mfile && Cfile)) {
+    fprintf (stderr, "failed to get all parameter lines\n");
+    fprintf (stderr, "test_Av: %d\n", test_Av);
+    fprintf (stderr, "test_d: %d\n", test_d);
+    fprintf (stderr, "test_alpha: %d\n", test_alpha);
+    fprintf (stderr, "test_age: %d\n", test_Age);
+    fprintf (stderr, "dVo: %f (%d)\n", dVo, test_dVo);
+    fprintf (stderr, "dVref: %f (%d)\n", dVref, test_dVref);
+    fprintf (stderr, "dMo: %f (%d)\n", dMo, test_dMo);
+    fprintf (stderr, "Mfile: %d\n", Mfile);
+    fprintf (stderr, "Cfile: %d\n", Cfile);
+    exit (0);
+  }
+  
+}
+
+/*****************************************************************************/
Index: /tags/start/Ohana/src/misc/src/fakestars.c
===================================================================
--- /tags/start/Ohana/src/misc/src/fakestars.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/fakestars.c	(revision 12606)
@@ -0,0 +1,121 @@
+# include <ohana.h>
+# define NCHAR 66 /* 65 char EXCLUDING return */
+# define D_NSTARS 1000
+# define BYTES_STAR 66
+# define BLOCK 1000
+
+typedef struct {
+  double X;
+  double Y;
+  double R;
+  double D;
+  double M, dM;
+  char   dophot;
+  double sky;
+  double fx, fy, df;
+  double Mgal, Map;
+  int found;
+} Stars;
+
+void   gauss_init ();
+double gaussian (double x, double mean, double sigma);
+double rnd_gauss (double mean, double sigma);
+
+  /* 
+     load in a list of stars in cmp format
+     generate a new list of stars in cmp format
+     new measurements should have the requested noise characteristics */
+
+int main (int argc, char **argv) {
+
+  int Nstar, N, Nbytes, nbytes, i;
+  FILE *f;
+  char *input, *output, *buffer, line[NCHAR];
+  Header header;
+  Stars *stars;
+  double tmp, dMs, dMr, dMo, dM, offset;
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: fakestars (input) (output) (syserr) (offset)\n");
+    exit (2);
+  }
+  input  = argv[1];
+  output = argv[2];
+  dMs    = atof (argv[3]);
+  offset = atof (argv[4]);
+
+  gauss_init ();
+
+  /* load header, open file */
+  if (!fits_read_header (input, &header)) {
+    fprintf (stderr, "ERROR: can't read header for %s\n", input);
+    exit (1);
+  }
+  f = fopen (input, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't read data from %s\n", input);
+    exit (1);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* find expected number of stars */
+  fits_scan (&header, "NSTARS", "%d", 1, &Nstar);
+  if (Nstar == 0) {
+    fprintf (stderr, "ERROR: can't get NSTARS from header\n");
+    exit (1);
+  }
+  ALLOCATE (stars, Stars, Nstar);
+
+  /* load in stars */
+  Nbytes = Nstar*BYTES_STAR;
+  ALLOCATE (buffer, char, Nbytes + 1);
+  nbytes = Fread (buffer, 1, Nbytes, f, "char");
+  if (nbytes != Nbytes) {
+    fprintf (stderr, "ERROR: failed to read in %d stars\n", Nstar);
+    exit (1);
+  }
+  buffer[Nbytes] = 0;
+
+  for (i = 0; i < Nstar; i++) {
+    Nbytes = i*BYTES_STAR;
+    dparse (&stars[i].X,    1, &buffer[Nbytes]);
+    dparse (&stars[i].Y,    2, &buffer[Nbytes]);
+    dparse (&stars[i].M,    3, &buffer[Nbytes]);
+    dparse (&stars[i].dM,   4, &buffer[Nbytes]);
+    dparse (&stars[i].Mgal, 7, &buffer[Nbytes]);
+    dparse (&stars[i].Map,  8, &buffer[Nbytes]);
+    dparse (&stars[i].fx,   9, &buffer[Nbytes]);
+    dparse (&stars[i].fy,  10, &buffer[Nbytes]);
+    dparse (&stars[i].df,  11, &buffer[Nbytes]);
+    
+    dparse (&tmp,           5, &buffer[Nbytes]);
+    stars[i].dophot = tmp;
+  }
+  fclose (f);
+
+  /* error per star is hypot of systematic & poisson */
+  for (i = 0; i < Nstar; i++) {
+    dMr = 0.001 * stars[i].dM;
+    dMo = hypot (dMs, dMr);
+    dM  = rnd_gauss (0.0, dMo);
+    stars[i].M += dM + offset;
+  }
+
+  fits_write_header (output, &header);
+  f = fopen (output, "a");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open file for output: %s\n", output);
+    exit (1);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  for (i = 0; i < Nstar; i++) {
+    snprintf (line, NCHAR, "%6.1f %6.1f %6.3f %03d %2d %3.1f %6.3f %6.3f %6.2f %6.2f %5.1f", 
+	      stars[i].X, stars[i].Y, stars[i].M, 
+	      (int)stars[i].dM, stars[i].dophot, stars[i].sky, 
+	      stars[i].Mgal, stars[i].Map, stars[i].fx, stars[i].fy, stars[i].df);
+    fprintf (f, "%s\n", line);
+  }
+  fclose (f);
+}
+
Index: /tags/start/Ohana/src/misc/src/findexec.c
===================================================================
--- /tags/start/Ohana/src/misc/src/findexec.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/findexec.c	(revision 12606)
@@ -0,0 +1,121 @@
+# include <stdio.h>
+# include <strings.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <stdlib.h>
+
+# define TRUE 1
+# define FALSE 0
+
+# ifndef ALLOCATE
+# define ALLOCATE(X,T,S)  \
+  X=(T *)malloc((unsigned) ((S)*sizeof(T)));\
+  if(X==NULL) \
+    { \
+      fprintf(stderr,"failed to malloc X\n");\
+        exit(0);\
+    } 
+# define REALLOCATE(X,T,S) \
+  X=(T *)realloc(X,(unsigned) ((S)*sizeof(T))); \
+  if(X==NULL) \
+    { \
+       fprintf(stderr,"failed to realloc X\n"); \
+       exit(0); \
+    }
+# endif /* ALLOCATE */
+
+int _check_permissions (char *filename) {
+  
+  FILE *f;
+  struct stat filestat;
+  uid_t fuid, uid;
+  gid_t fgid, gid;
+  int status;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to exec file */
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IXUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IXGRP)) || 
+	(                            (filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IXOTH))) {
+      return (TRUE);
+    } else {
+      fprintf (stderr, "can't exec %s\n", filename);
+      return (FALSE);
+    }
+  }
+  fprintf (stderr, "no such file %s\n", filename);
+  return (FALSE);
+}
+
+char *pathname (char *name) {
+ 
+  char *c, *path;
+
+  ALLOCATE (path, char, strlen(name) + 1);
+  strcpy (path, name);
+  c = strrchr (path, '/');
+  if (c == (char *) NULL) {
+    strcpy (path, ".");
+  } else {
+    *c = 0;
+  }
+  
+  return (path);
+  
+}
+
+char *findexec (int argc, char **argv) {
+
+  int i, N, done, status;
+  char *c, *e, *dir, path[1024], name[1024];
+  struct stat state;
+
+  if (argv[0][0] == '/') {
+    status = _check_permissions (argv[0]);
+    if (status) {
+      realpath (argv[0], path);
+      dir = pathname (path);
+      return (dir);
+    }
+  }
+
+  N = 0;
+  for (i = argc+1; argv[i] != (char *) NULL; i++) {
+    if (!strncmp (argv[i], "PATH", 4)) {
+      N = i;
+      break;
+    }
+  }
+
+  if (N) {
+    c = &argv[N][5];
+    e = strchr (c, ':');
+    done = FALSE;
+    i = 0;
+    while (!done && (i < 50)) {
+      if (e == (char *) NULL) {
+	done = TRUE;
+	bzero (path, 256);
+	strncpy (path, c, strlen(c));
+      } else {
+	bzero (path, 256);
+	strncpy (path, c, e-c);
+	c = e+1;
+	e = strchr (c, ':');
+      }
+      sprintf (name, "%s/%s", path, argv[0]);
+      status = _check_permissions (name);
+
+      if (status) {
+	realpath (name, path);
+	dir = pathname (path);
+	return (dir);
+      }
+    }
+    i++;
+  }
+}
Index: /tags/start/Ohana/src/misc/src/fitdist.c
===================================================================
--- /tags/start/Ohana/src/misc/src/fitdist.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/fitdist.c	(revision 12606)
@@ -0,0 +1,708 @@
+# include <ohana.h>
+
+# define NGAUSS 2048
+double drand48();
+double gaussint[NGAUSS];
+double gaussian();
+double rnd_gauss();
+
+# define MMIN 1.0
+# define MMAX 120.0
+double rnd_mass();
+double MassTerm;
+
+# define NPARMAX 30
+int Nmass, N_Av, N_dist, N_alpha, N_age, NTRY;
+double *Mass, Av[NPARMAX], dist[NPARMAX], alpha[NPARMAX], age[NPARMAX];
+
+int COL1, COL2;
+double *mag, *color, *noise;
+double *obsdata;
+
+double UV0, V0, DV, DUV;
+Header fake_h, mass_h, age_h;
+Matrix fake_m, mass_i, age_i;
+int MS_NX, MS_NY;
+float *Mbuffer, *Abuffer;
+
+char datafile[256], fakefile[256], massfile[256], agefile[256];
+
+double get_obs(), get_fake(), get_error(), get_fake_err(), get_chisq();
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+  
+  Header header;
+  Matrix matrix;
+  int i, j, m, n, M, A, Nstars, I, J, k, done, grid, tries;
+  double mass, inflation, sumterm, errterm;
+  double dm, a1, a2, chisq_0, chisq_1, chisq_min, Ndof, *delta;
+  double temp_Factor, *Factor, *dFactor, *SFR, dFactor1, dFactor2;
+
+  load_parameters (argc, argv);
+  fprintf (stderr, "read in parameters\n");
+
+  gauss_init ();
+
+  read_datafiles ();
+  fprintf (stderr, "read in data files (%d x %d)\n", Nmass, N_age);
+
+  Nstars = load_realstars ();
+  fprintf (stderr, "read in %d real stars\n", Nstars);
+
+  ALLOCATE (SFR, double, N_age);
+  ALLOCATE (Factor, double, N_age);
+  ALLOCATE (dFactor, double, N_age);
+  ALLOCATE (delta, double, N_age);
+
+  fprintf (stdout, "# Av   dist   alpha  chisq Ndof");
+  for (n = 0; n < N_age; n++) {
+    fprintf (stdout, " %3.0f My ", age[n]);
+  }
+  fprintf (stdout, "\n");
+
+  for (i = 0; i < N_Av; i++) {
+    for (j = 0; j < N_dist; j++) {
+      
+      /* unique obs. matrix for each Av, dist value only */
+      bzero (obsdata, sizeof(double) * N_age*Nmass*2);
+      for (k = 0; k < Nstars; k++) {
+	magtomass (Av[i], dist[j], mag[k], color[k], noise[k], &M, &A, &inflation);
+	if (inflation > 0.0) add_obs (A, M, inflation);
+      }
+      
+      /* now fit to fake matrices */
+      for (m = 0; m < N_alpha; m++) {
+
+	for (n = 0; n < N_age; n++) {
+	  dm = get_fake (i, j, m, n, N_age, 0);
+	  a1 = get_fake (i, j, m, n, N_age, 4);
+	  a2 = get_fake (i, j, m, n, N_age, 5);
+	  SFR[n] = dm / (a2 - a1);
+	  delta[n] = 0.1;
+	  Factor[n] = 0.0;
+	}	
+	
+	chisq_1 = get_chisq (Factor, i, j, m, &Ndof);
+	chisq_0 = 2*chisq_1;
+	done = FALSE;
+	/* 	while (!done) { */
+	for (tries = 0; ((fabs (chisq_1 - chisq_0) / Ndof > 0.001) && (tries < 100)); tries++) {
+	  chisq_0 = chisq_1;
+	  for (n = 0; n < N_age; n++) {
+	    Factor[n] += delta[n];
+	    chisq_1 = get_chisq (Factor, i, j, m, &Ndof);
+	    dFactor1 = MAX (0.0, MIN (0.5*delta[n], 5.0 * delta[n] * (1.0 - chisq_1/chisq_0)));
+	    Factor[n] -= 2*delta[n];
+	    chisq_1 = get_chisq (Factor, i, j, m, &Ndof);
+	    dFactor2 = MIN (0.0, MAX (-0.5*delta[n], -5.0 * delta[n] * (1.0 - chisq_1/chisq_0)));
+	    if (dFactor1 > fabs(dFactor2)) {
+	      dFactor[n] = dFactor1;
+	    }
+	    else {
+	      dFactor[n] = dFactor2;
+	    }
+	    Factor[n] += delta[n];
+	    if ((delta[n] > 0.001) && (!(tries % 5) || (fabs(dFactor[n]) < 0.01 * delta[n]))) {
+	      /* small grid search */
+	      dFactor1 = temp_Factor = Factor[n];
+	      chisq_min = chisq_0;
+	      for (grid = 0, Factor[n] = MAX (0.0, Factor[n] - 2*delta[n]); grid < 5; grid ++, Factor[n] += delta[n]) {
+		chisq_1 = get_chisq (Factor, i, j, m, &Ndof);
+		if (chisq_1 < chisq_min) {
+		  dFactor1 = Factor[n];
+		  chisq_min = chisq_1;
+		}
+	      }
+	      if (dFactor1 == temp_Factor) {
+		delta[n] = delta[n] / 2.0;
+	      }
+	      Factor[n] = dFactor1;
+	    }
+	  }
+	  done = TRUE; 
+	  for (n = 0; n < N_age; n++) {
+	    Factor[n] += dFactor[n];
+	    Factor[n] = MAX (0.0, Factor[n]);  /* negative star formation is unphysical */
+	    if ((Factor[n] > 0.0) && (fabs(dFactor[n]) == delta[n])) {
+	      delta[n] = MIN (0.1, delta[n] * 1.5);
+	    }
+	  }
+	  chisq_1 = get_chisq (Factor, i, j, m, &Ndof);
+	  /*
+	  fprintf (stderr, "%f %f ", chisq_0, chisq_1);
+	  for (n = 0; n < N_age; n++) {
+	    fprintf (stderr, "%f ", Factor[n]);
+	  }
+	  fprintf (stderr, "\n");
+	  fprintf (stderr, "                       ");
+	  for (n = 0; n < N_age; n++) {
+	    fprintf (stderr, "%f ", delta[n]);
+	  }
+	  fprintf (stderr, "\n");
+	  */
+	}
+
+	chisq_0 = chisq_1;
+	for (n = 0; n < N_age; n++) {
+	  temp_Factor = Factor[n];
+	  for (; chisq_1 < chisq_0 + 1; Factor[n] += 0.1*delta[n])
+	    chisq_1 = get_chisq (Factor, i, j, m, &Ndof);
+	  dFactor[n] = Factor[n] - temp_Factor;
+	  /* fprintf (stderr, "%d %f %f\n", n, Factor[n], dFactor[n]); */
+	  Factor[n] = temp_Factor;
+	  chisq_1 = chisq_0;
+	  for (; chisq_1 < chisq_0 + 1; Factor[n] -= 0.1*delta[n])
+	    chisq_1 = get_chisq (Factor, i, j, m, &Ndof);
+	  dFactor[n] =  0.5 * (dFactor[n] + temp_Factor  - Factor[n]);
+	  Factor[n] = temp_Factor;
+	}
+	if (tries == 100) {
+	  fprintf (stdout, "*** failed to converge *** \n");
+	}
+	fprintf (stdout, "%5.2f %6.2f %4.1f   %6.2f  %.0f ", Av[i], dist[j], alpha[m], chisq_1/Ndof, Ndof);
+	for (n = 0; n < N_age; n++) {
+	  fprintf (stdout, "%7.0f ", SFR[n]*Factor[n]);
+	}
+	fprintf (stdout, "\n");
+	fprintf (stdout, "                               ");
+	for (n = 0; n < N_age; n++) {
+	  fprintf (stdout, "%7.0f ", SFR[n]*dFactor[n]);
+	}
+	fprintf (stdout, "\n");
+      }
+    }
+  }
+}
+
+
+/*****************************************************************************/
+
+double get_chisq (Factor, AV, DIST, ALPHA, Ndof)
+double *Factor;
+int AV, DIST, ALPHA;
+double *Ndof;
+{
+
+  double chisq, sumterm, errterm;
+  int I, J, n;
+
+  *Ndof = chisq = 0.0;
+  for (I = 0; I < Nmass; I++) {
+    for (J = 0; J < N_age; J++) {
+      errterm = get_error (J, I);
+      sumterm = get_obs (J, I);
+      for (n = 0; n < N_age; n++) {
+	sumterm -= Factor[n]*get_fake (AV, DIST, ALPHA, n, J, I);
+	errterm += Factor[n]*get_fake_err (AV, DIST, ALPHA, n, J, I);
+      }
+      if (errterm > 0.0) {
+	chisq += SQ (sumterm) / errterm;
+	*Ndof += 1.0;
+      }
+    }
+  }
+  *Ndof -= N_age + N_Av + N_dist + N_alpha;
+
+  return (chisq);
+}
+
+/*****************************************************************************/
+
+load_parameters (argc, argv)
+int argc;
+char **argv;
+{
+
+  int i;
+  int Dfile, Ffile, Afile, MSfile;
+  FILE *f;
+  char line[1024];
+  double tmp;
+
+  if (argc < 2) {
+    fprintf (stderr, "USAGE: %s pfile\n", argv[0]);
+    exit (0);
+  }
+
+  f = fopen (argv[1], "r");
+  if (f == NULL) {
+    fprintf (stderr, "parameter file %s not found\n", argv[1]);
+    exit (0);
+  }
+
+  COL1 = COL1 = NTRY = 0.0;
+  Dfile = Ffile = Afile = MSfile = FALSE;
+  while (scan_line (f, line) != EOF) {
+    if (!stripwhite (line)) continue;
+    if (line[0] == '#') continue;
+        
+    if (!strncmp (line, "ntry ", strlen ("ntry "))) {
+      dparse (&tmp, 2, line);
+      NTRY = tmp;
+    }
+  
+    if (!strncmp (line, "col1 ", strlen ("col1 "))) {
+      dparse (&tmp, 2, line);
+      COL1 = tmp;
+    }
+  
+    if (!strncmp (line, "col2 ", strlen ("col2 "))) {
+      dparse (&tmp, 2, line);
+      COL2 = tmp;
+    }
+  
+    if (!strncmp (line, "agefile ", strlen ("agefile "))) {
+      sscanf (line, "%*s %s", agefile);
+      fprintf (stderr, "agefile: %s\n", agefile);
+      Afile = TRUE;
+    }
+    
+    if (!strncmp (line, "massfile ", strlen ("massfile "))) {
+      sscanf (line, "%*s %s", massfile);
+      fprintf (stderr, "massfile: %s\n", massfile);
+      MSfile = TRUE;
+    }
+    
+    if (!strncmp (line, "datafile ", strlen ("datafile "))) {
+      sscanf (line, "%*s %s", datafile);
+      fprintf (stderr, "datafile: %s\n", datafile);
+      Dfile = TRUE;
+    }
+    
+    if (!strncmp (line, "fakefile ", strlen ("fakefile "))) {
+      sscanf (line, "%*s %s", fakefile);
+      fprintf (stderr, "fakefile: %s\n", fakefile);
+      Ffile = TRUE;
+    }
+    
+    if (COL1 && COL2 && NTRY && Dfile && Ffile && Afile && MSfile) {
+      return;
+    }
+  }
+  
+  if (!(COL1 && COL2 && NTRY && Dfile && Ffile && Afile && MSfile)) {
+    fprintf (stderr, "failed to get all parameter lines\n");
+    fprintf (stderr, "NTRY: %d\n", NTRY);
+    fprintf (stderr, "COL1: %d\n", COL1);
+    fprintf (stderr, "COL2: %d\n", COL2);
+    fprintf (stderr, "Dfile: %d\n", Dfile);
+    fprintf (stderr, "Ffile: %d\n", Ffile);
+    fprintf (stderr, "Afile: %d\n", Afile);
+    fprintf (stderr, "MSfile: %d\n", MSfile);
+    exit (0);
+  }
+  
+}
+
+/*****************************************************************************/
+
+read_datafiles ()
+{
+
+  int i;
+  char line[1024];
+
+  fits_read_header (massfile, &mass_h);
+  fits_read_matrix (massfile, &mass_i);
+  fits_read_header (agefile, &age_h);
+  fits_read_matrix (agefile, &age_i); 
+  MS_NX = mass_h.Naxis[0];
+  MS_NY = mass_h.Naxis[1];
+  Mbuffer = (float *)mass_i.buffer;
+  Abuffer = (float *)age_i.buffer;
+
+  fits_scan (&mass_h, "RA_O",  "%lf", 1, &UV0);
+  fits_scan (&mass_h, "RA_X",  "%lf", 1, &DUV);
+  fits_scan (&mass_h, "DEC_O", "%lf", 1, &V0);
+  fits_scan (&mass_h, "DEC_Y", "%lf", 1, &DV);
+
+  fits_read_header (fakefile, &fake_h);
+  fits_read_matrix (fakefile, &fake_m);
+  Nmass = fake_h.Naxis[0];
+  ALLOCATE (Mass, double, Nmass + 1);
+  for (i = 0; i < Nmass + 1; i++) {
+    sprintf (line, "PAR_1_%0d\0", i);
+    fits_scan (&fake_h, line, "%lf", 1, &Mass[i]);
+  }
+  
+  N_age = fake_h.Naxis[1] - 1;
+  for (i = 0; i < N_age + 1; i++) {
+    sprintf (line, "PAR_2_%0d\0", i);
+    fits_scan (&fake_h, line, "%lf", 1, &age[i]);
+  }
+
+  N_alpha = fake_h.Naxis[3];
+  for (i = 0; i < N_alpha; i++) {
+    sprintf (line, "PAR_4_%0d\0", i);
+    fits_scan (&fake_h, line, "%lf", 1, &alpha[i]);
+  }
+
+  N_dist = fake_h.Naxis[4];
+  for (i = 0; i < N_dist; i++) {
+    sprintf (line, "PAR_5_%0d\0", i);
+    fits_scan (&fake_h, line, "%lf", 1, &dist[i]);
+  }
+
+  N_Av = fake_h.Naxis[5];
+  for (i = 0; i < N_Av; i++) {
+    sprintf (line, "PAR_6_%0d\0", i);
+    fits_scan (&fake_h, line, "%lf", 1, &Av[i]);
+  }
+
+  ALLOCATE (obsdata, double, Nmass*N_age*2);
+
+}
+ 
+
+/*****************************************************************************/
+
+double
+rnd_gauss (mean, sigma)
+double mean, sigma; 
+{
+
+  int i;
+  double y;
+
+  y = drand48();
+  i = NGAUSS*y;
+  y = gaussint[i]*sigma + mean;
+
+  return (y);
+
+}
+
+gauss_init ()
+{
+
+  int i;
+  long A, B;
+  double val, x, dx, dx1, dx2, dx3, df;
+  double mean, sigma;
+
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+
+  val = 0;
+  dx = 0.001;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+  mean = 0.0;
+  sigma = 1.0;
+
+  for (i = 0, x = -7.0; (i < NGAUSS) && (x < 7.0); x += dx)  {
+    df = (3.0*gaussian(x    , mean, sigma) + 
+	  9.0*gaussian(x+dx1, mean, sigma) +
+	  9.0*gaussian(x+dx2, mean, sigma) + 
+	  3.0*gaussian(x+dx3, mean, sigma)) * (dx1/8.0);
+    val += df;
+    if (val > (i / (double) NGAUSS)) {
+      gaussint[i] = x + dx / 2.0;
+      i++;
+    }
+  }
+  return (x + dx / 2.0);
+}
+
+double 
+gaussian (x, mean, sigma) 
+double x, mean, sigma; 
+{
+
+  double f, X;
+
+  f = exp (-0.5 * SQ(x - mean) / SQ(sigma)) / sqrt(2 * M_PI * SQ(sigma));
+
+  return (f);
+
+}
+
+/*****************************************************************************/
+
+magtomass (A_V, Dist, Mag, Color, Noise, M, A, inflation)
+double A_V, Dist, Mag, Color, Noise;
+int *M, *A;
+double *inflation;
+{
+
+  int x, y, I, J, i, j, k;
+  double mass, Age, v, uv, Ngood;
+
+  *inflation = 0.0;
+  x = (Color - UV0 - 0.7*A_V) / DUV;   /* again, depends on U-V and extinction */
+  y = (Mag - Dist - V0 - A_V) / DV;
+  if ((x > 0) && (x < MS_NX) && (y > 0) && (y < MS_NY)) {
+    mass = Mbuffer[x + MS_NX*y];
+    if (mass > 0.0) {
+      Age = Abuffer[x + MS_NX*y];
+      if ((Age < age[0]) || (Age > age[N_age])) {
+	*inflation = 0.0;
+	return;
+      }
+      for (I = 0; (I < N_age) && (Age > age[I+1]); I++);
+      if ((mass < Mass[0]) || (mass > Mass[Nmass])) {
+	*inflation = 0.0;
+	return;
+      }
+      for (J = 0; (J < Nmass) && (mass > Mass[J+1]); J++);
+      Ngood = 1.0;
+      for (k = 0; k < NTRY; k++) {
+	v = rnd_gauss (Mag, Noise);
+	uv = rnd_gauss (Color, 1.4*Noise);
+	x = (uv - UV0 - 0.7*A_V) / DUV;
+	y = (v - V0 - Dist - A_V) / DV;
+	if ((x > 0) && (x < MS_NX) && (y > 0) && (y < MS_NY)) {
+	  mass = Mbuffer[x + MS_NX*y];
+	  if (mass > 0.0) {
+	    Age = Abuffer[x + MS_NX*y];
+	    for (i = -1; (i < N_age) && (Age > age[i+1]); i++);
+	    for (j = -1; (j < Nmass) && (mass > Mass[j+1]); j++);
+	    if ((i == I) && (j == J)) {
+	      Ngood += 1.0;
+	    }
+	  }
+	}
+      }
+      *inflation = (NTRY / Ngood);
+      *M = J;
+      *A = I;
+    }
+  }
+  if (mass == 0.0) *inflation = 0.0;
+}
+ 
+
+/*****************************************************************************/
+
+add_obs (AGE, MASS, value)
+int AGE, MASS;
+double value;
+{
+
+  if (value == 0.0) {
+    fprintf (stderr, "error: %d %d %f\n", AGE, MASS, value);
+  }
+  else {
+    obsdata[MASS + Nmass*(AGE        )] += value;
+    obsdata[MASS + Nmass*(AGE + N_age)] += 1.0;
+  }
+}
+
+
+/*****************************************************************************/
+
+double get_obs (AGE, MASS)
+int AGE, MASS;
+{
+
+  double value;
+
+  value = obsdata[MASS + Nmass*(AGE)];
+
+  return (value);
+
+}
+
+/*****************************************************************************/
+
+double get_error (AGE, MASS)
+int AGE, MASS;
+{
+
+  double value;
+
+  if (obsdata[MASS + Nmass*(AGE + N_age)] > 5) {
+    value = SQ (obsdata[MASS + Nmass*(AGE)]) / obsdata[MASS + Nmass*(AGE + N_age)];
+    return (value);
+  }
+  if ((obsdata[MASS + Nmass*(AGE + N_age)] < 1) && (obsdata[MASS + Nmass*(AGE)] > 0)) {
+    fprintf (stderr, "error: %d %d %e %e\n", AGE, MASS, 
+	     obsdata[MASS + Nmass*(AGE + 0)], obsdata[MASS + Nmass*(AGE + 1)]);
+  }
+  if (obsdata[MASS + Nmass*(AGE + N_age)] > 0) {
+    value = SQ (3.0 * obsdata[MASS + Nmass*(AGE)] / obsdata[MASS + Nmass*(AGE + N_age)]);
+    return (value);
+  }
+  value = 0.0;
+  return (value);
+
+}
+
+
+/*****************************************************************************/
+
+double get_fake (AV, DIST, ALPHA, AGE_IN, AGE_OUT, MASS)
+int AV, DIST, ALPHA, AGE_IN, AGE_OUT, MASS;
+{
+
+  double value;
+  float *buffer;
+
+  buffer = (float *)fake_m.buffer;
+  
+  /* elements in the (N_age) row of each Mass*Age matrix contain special numbers for the matrix */
+  value = buffer[MASS + Nmass*(AGE_OUT + (N_age + 1)*(AGE_IN + N_age*(ALPHA + N_alpha*(DIST + N_dist*(AV + N_Av*(0))))))];
+  /* buffer[MASS + Nmass*(AGE_OUT + (N_age + 1)*(AGE_IN + N_age*(ALPHA + N_alpha*(DIST + N_dist*(AV + N_Av*(1))))))] += 1.0; */
+
+  return (value);
+
+}
+
+/*****************************************************************************/
+
+double get_fake_err (AV, DIST, ALPHA, AGE_IN, AGE_OUT, MASS)
+int AV, DIST, ALPHA, AGE_IN, AGE_OUT, MASS;
+{
+
+  double value;
+  float *buffer;
+  int pix1, pix2;
+
+  buffer = (float *)fake_m.buffer;
+  
+  /* elements in the (N_age) row of each Mass*Age matrix contain special numbers for the matrix */
+  pix1 = MASS + Nmass*(AGE_OUT + (N_age + 1)*(AGE_IN + N_age*(ALPHA + N_alpha*(DIST + N_dist*(AV + N_Av*(0))))));
+  pix2 = MASS + Nmass*(AGE_OUT + (N_age + 1)*(AGE_IN + N_age*(ALPHA + N_alpha*(DIST + N_dist*(AV + N_Av*(1))))));
+
+  if (buffer[pix2] > 5) {
+    value = SQ (buffer[pix1]) / buffer[pix2];
+    return (value);
+  }
+
+  if (buffer[pix2] > 0) {
+    value = SQ (3.0 * buffer[pix1] / buffer[pix2]);
+    return (value);
+  }
+
+  value = 0.0;
+  return (value);
+
+}
+
+/***************************************************************************/
+
+int load_realstars () 
+
+{
+
+  char line[1024];
+  FILE *f;
+  double U;
+  int i, Nstars;
+
+  f = fopen (datafile, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "couldn't find data file %s\n", datafile);
+    exit (0);
+  }
+  
+  Nstars = 1000;
+  ALLOCATE (mag, double, Nstars);
+  ALLOCATE (color, double, Nstars);
+  ALLOCATE (noise, double, Nstars);
+  
+  /* need to fix allocations */
+  for (i = 0; scan_line (f, line) != EOF; i++) {
+    if (!stripwhite (line)) continue;
+    if (line[0] == '#') continue;
+    dparse (&mag[i], COL1, line);
+    dparse (&noise[i], (COL1+1), line);
+    dparse (&U, COL2, line);
+    color[i] = U - mag[i];
+    if (i == Nstars - 1) {
+      Nstars += 1000;
+      REALLOCATE (mag, double, Nstars);
+      REALLOCATE (color, double, Nstars);
+      REALLOCATE (noise, double, Nstars);
+    }
+  }
+
+  return (i);
+  
+}
+
+
+/***************************************************************************/
+
+int
+gaussj (a, n, b, m)
+double **a, **b;
+int n,m;
+{
+  int *indxc,*indxr,*ipiv;
+  int i, icol, irow, j, k, l, ll, status;
+  double big,dum,pivinv;
+  
+  ALLOCATE (indxc, int, n);
+  ALLOCATE (indxr, int, n);
+  ALLOCATE (ipiv, int, n);
+  for (j = 0; j < n; j++) 
+    ipiv[j] = 0;
+ 
+  for (i = 0; i < n; i++) {
+    big = 0.0;
+    for (j = 0; j < n; j++) {
+      if (ipiv[j] != 1) {
+        for (k = 0; k < n; k++) {
+          if (ipiv[k] == 0) {
+            if (fabs (a[j][k]) >= big) {
+              big  = fabs (a[j][k]);
+              irow = j;
+              icol = k;
+            }
+          } 
+          else 
+            if (ipiv[k] > 1) {
+              fprintf (stderr, "GAUSSJ: Singular Matrix! (1)\n");
+              return (0);
+            }
+        }
+      }
+    }
+    ipiv[icol]++;
+    if (irow != icol) {
+      for (l = 0; l < n; l++) 
+        SWAP (a[irow][l], a[icol][l]);
+      for (l = 0; l < m; l++) 
+        SWAP (b[irow][l], b[icol][l]);
+    }
+    indxr[i] = irow;
+    indxc[i] = icol;
+    if (a[icol][icol] == 0.0) {
+      fprintf (stderr, "GAUSSJ: Singular Matrix! (2)\n");
+      return (0);
+    }
+    pivinv = 1.0 / a[icol][icol];
+    a[icol][icol] = 1.0;
+    for (l = 0; l < n; l++) 
+      a[icol][l] *= pivinv;
+    for (l = 0; l < m; l++) 
+      b[icol][l] *= pivinv;
+    for (ll = 0; ll < n; ll++) {
+      if (ll != icol) {
+        dum = a[ll][icol];
+        a[ll][icol] = 0.0;
+        for (l = 0; l < n; l++) 
+          a[ll][l] -= a[icol][l]*dum;
+        for (l = 0; l < m; l++) 
+          b[ll][l] -= b[icol][l]*dum;
+      }
+    }
+  }
+ 
+  for (l = n - 1; l >= 0; l--) {
+    if (indxr[l] != indxc[l])
+      for (k = 0; k < n; k++)
+        SWAP (a[k][indxr[l]], a[k][indxc[l]]);
+  }
+  free (ipiv);
+  free (indxr);
+  free (indxc);
+  return (1);
+}
+ 
Index: /tags/start/Ohana/src/misc/src/fits_insert.c
===================================================================
--- /tags/start/Ohana/src/misc/src/fits_insert.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/fits_insert.c	(revision 12606)
@@ -0,0 +1,159 @@
+# include <ohana.h>
+
+static char reserved[] =  "COMMENT  Reserved space.  This line can be used to add a new FITS card.         ";
+static char blankline[] = "                                                                                ";
+
+int main (int argc, char **argv) {
+
+  int i, N, status, EXTNUM, Nbytes, skip;
+  int Nreserved, start_size;
+  char *p, keyword[16], line[256];
+  FILE *f;
+  Header header;
+  int COMMENT, Cnumber;
+  char *Cline;
+
+  /* check for command line options */
+  COMMENT = FALSE;
+  if ((N = get_argument (argc, argv, "-comment"))) {
+    COMMENT = TRUE;
+    remove_argument (N, &argc, argv);
+    Cnumber = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    Cline = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* check for command line options */
+  EXTNUM = -1; /* -1 is primary header */
+  if ((N = get_argument (argc, argv, "-X"))) {
+    remove_argument (N, &argc, argv);
+    EXTNUM = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: fits_insert (image.fits) (header.hdx) [-X N] [-comment N line]\n");
+    exit (2);
+  }
+  
+  /* load header from image file */
+  Nbytes = fits_read_Xheader (argv[1], &header, EXTNUM);
+  if (!Nbytes) {
+    fprintf (stderr, "can't open fits file %s\n", argv[1]);
+    exit (1);
+  }
+  start_size = header.size;
+  skip = Nbytes - header.size;
+
+  /* open header data file */
+  f = fopen (argv[2], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open header data file %s\n", argv[2]);
+    exit (1);
+  }
+
+  /* wipe out COMMENT N and replace with given line */ 
+  if (COMMENT) {
+
+    /* create a pristine FITS line */
+    snprintf (line, 81, "COMMENT  %-71s", Cline);
+
+    p = fits_header_field (&header, "COMMENT", Cnumber);
+    if (p != (char *) NULL) {
+      strncpy (p, line, 80);
+    }
+  }
+
+  /* run through the lines in the header data file */
+  while (scan_line (f, line) != EOF) {
+    
+    /* fill in end of line with blanks, force end at 80 */
+    for (N = strlen (line); N < 80; N++) {
+      line[N] = ' ';
+    }
+    line[80] = 0;
+    bzero (keyword, 10);
+    strncpy (keyword, line, 8);
+    
+    /* replace existing keywords, unless this is a COMMENT or HISTORY field */
+    if (strncmp (keyword, "COMMENT ", 8) && strncmp (keyword, "HISTORY ", 8)) {
+      p = fits_header_field (&header, keyword, 1);
+      if (p != (char *) NULL) {
+	strncpy (p, line, 80);
+	continue;
+      }
+    }
+
+    /* check that the line does not already exist */
+    p = (char *) NULL;
+    for (i = 0; (i < header.size) && (p == (char *) NULL) ; i+= FT_LINE_LENGTH) {
+      if (!strncmp (&header.buffer[i], line, 80)) {
+	p = &header.buffer[i];
+      }
+    }
+    if (p != (char *) NULL) continue;
+
+    /* find first line with the reserved line */
+    p = (char *) NULL;
+    Nreserved = strlen (reserved);
+    for (i = 0; (i < header.size) && (p == (char *) NULL) ; i+= FT_LINE_LENGTH) {
+      if (!strncmp (&header.buffer[i], "END     ", 8)) break;
+      if (!strncmp (&header.buffer[i], reserved, Nreserved)) {
+	p = &header.buffer[i];
+      }
+      if (!strncmp (&header.buffer[i], blankline, Nreserved)) {
+	p = &header.buffer[i];
+      }
+    }
+    if (p == (char *) NULL) {
+      fprintf (stdout, "no more reserved spaces, trying for extra space in block\n");
+      p = fits_header_field (&header, "END", 1);
+      if (p == (char *) NULL) {
+	fprintf (stderr, "header is missing END\n");
+	exit (1);
+      }
+      if (p - header.buffer + 80 == header.size) {
+	fprintf (stderr, "no free space in block, can't insert keyword\n");
+	exit (1);
+      }
+      strncpy (p+80, "END", 3);
+      for (i = 3; i < 80; i++) { p[80+i] = ' '; }
+    }
+    /* insert the new line here */
+    strncpy (p, line, 80);
+  }
+  if (fclose (f)) {
+    fprintf (stderr, "error reading new keywords\n");
+    exit (1);
+  }
+
+  /* now write the new header on top of the old one. 
+     check first that the header size has not changed.
+  */
+
+  if (header.size != start_size) {
+    fprintf (stderr, "header changed size: should not happen!\n");
+    exit (1);
+  }
+
+  f = fopen (argv[1], "r+");
+  if (f == NULL) {
+    fprintf (stderr, "can't open file for update %s\n", argv[1]);
+    exit (1);
+  }
+
+  fseek (f, skip, SEEK_SET);
+  status = fwrite (header.buffer, 1, header.size, f);
+  if (status != header.size) {
+    fprintf (stderr, "failed to write data to image header\n");
+    exit (1);
+  }
+  if (fclose (f)) {
+    fprintf (stderr, "error writing data to disk\n");
+    exit (1);
+  }
+
+  exit (0);
+}
+    
Index: /tags/start/Ohana/src/misc/src/fixcpt.c
===================================================================
--- /tags/start/Ohana/src/misc/src/fixcpt.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/fixcpt.c	(revision 12606)
@@ -0,0 +1,271 @@
+# include <ohana.h>
+# include <loneos.h>
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  char filename[64], line[64];
+  int Nitems, nitems, status;
+  int i, Nmeas, Nmiss, Naverage, Nmeasure, Nmissing;
+  FILE *f;
+  Average *average;
+  Measure *measure;
+  Missing *missing;
+  Header header;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: fixcpt (filename)\n");
+    exit (1);
+  }
+
+  check_permissions (argv[1]);
+
+  /* read catalog header */
+  if (!fits_read_header (argv[1], &header)) {
+    fprintf (stderr, "error loading file %s\n", argv[1]);
+    exit (1);
+  }
+
+  f = fopen (argv[1], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't open catalog file: %s\n", argv[1]);
+    exit (1);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /** find number of stars, measurements **/
+  Nmissing = Naverage = Nmeasure = 0;
+  fits_scan (&header, "NSTARS", "%d", 1, &Naverage);
+  fits_scan (&header, "NMEAS", "%d", 1, &Nmeasure);
+  fits_scan (&header, "NMISS", "%d", 1, &Nmissing);
+  ALLOCATE (average, Average, MAX (Naverage, 1));
+  ALLOCATE (measure, Measure, MAX (Nmeasure, 1));
+  ALLOCATE (missing, Missing, MAX (Nmissing, 1));
+  if (Naverage == 0) {
+    fprintf (stderr, "no stars yet in catalog %s\n", argv[1]);
+    fclose (f);
+    exit (0);
+  }
+
+  /* read average values */
+  Nitems = Naverage;
+  nitems = Fread (average, sizeof(Average), Nitems, f, "average");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to read data from catalog file %s (1)\n", argv[1]);
+    exit (1);
+  }
+  
+  /* read measurements */
+  Nitems = Nmeasure;
+  nitems = Fread (measure, sizeof(Measure), Nitems, f, "measure");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to read data from catalog file %s (2)\n", argv[1]);
+    exit (1);
+  }
+  
+  /* read missing */
+  Nitems = Nmissing;
+  nitems = Fread (missing, sizeof(Missing), Nitems, f, "missing");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to read data from catalog file %s (3)\n", argv[1]);
+    exit (1);
+  }
+  
+  fprintf (stderr, "read %d stars from catalog file %s (%d measurements, %d missing)\n", 
+	   Naverage, argv[1], Nmeasure, Nmissing);
+
+  for (i = Nmeas = Nmiss = 0; i < Naverage; i++) {
+    Nmeas += average[i].Nm; 
+    Nmiss += average[i].Nn; 
+  }
+  if ((Nmeas != Nmeasure) || (Nmiss != Nmissing)) {
+    fprintf (stderr, "ERROR: data in catalog %s is corrupt, sums don't check\n");
+    fprintf (stderr, "ERROR: Nmeas: %d, %d\n", Nmeas, Nmeasure);
+    fprintf (stderr, "ERROR: Nmiss: %d, %d\n", Nmiss, Nmissing);
+    exit (1);
+  }
+  fclose (f);
+
+
+  for (i = 0; i < Nmeasure; i++) {
+    if (measure[i].t > 0) {
+      fixtime (&measure[i].t);
+    }
+  }
+
+  for (i = 0; i < Nmissing; i++) {
+    if (missing[i].t > 0) {
+      fixtime (&missing[i].t);
+    }
+  }
+
+  /* write out file */
+  /* save old file */
+  sprintf (line, "mv %s %s.UT\0", argv[1], argv[1]);
+  status = system (line);
+  if (status) {
+    fprintf (stderr, "ERROR: unable to create %s.UT, exiting\n", argv[1]);
+    exit (1);
+  }
+
+  f = fopen (argv[1], "w");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't create new catalog file: %s\n", argv[1]);
+    exit (1);
+  }
+  
+  nitems = Fwrite (header.buffer, 1, header.size, f, "char");
+  if (nitems != header.size) {
+    fprintf (stderr, "ERROR: failed to write header\n");
+    exit (1);
+  }
+
+  Nitems = Naverage;
+  nitems = Fwrite (average, sizeof(Average), Nitems, f, "average");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to write catalog file aves %s\n", argv[1]);
+    exit (1);
+  }
+  
+  Nitems = Nmeasure;
+  nitems = Fwrite (measure, sizeof(Measure), Nitems, f, "measure");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to write catalog file meas %s\n", argv[1]);
+    exit (1);
+  }
+
+  Nitems = Nmissing;
+  nitems = Fwrite (missing, sizeof(Missing), Nitems, f, "missing");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to write catalog file miss %s\n", argv[1]);
+    exit (1);
+  }
+
+  fclose (f);
+
+  exit (0);
+
+}
+
+  
+
+
+check_permissions (char *basefile) {
+  
+  FILE *f;
+  char *c, dir[256], filename[256];
+  struct stat filestat;
+  uid_t fuid, uid;
+  gid_t fgid, gid;
+  int status;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to write to directory */
+  sprintf (filename, "%s\0", basefile);
+  c = strrchr (filename, '/');
+  if (c == (char *) NULL) {
+    strcpy (dir, ".");
+  } else {
+    *c = 0;
+    strcpy (dir, filename);
+  }
+  status = stat (dir, &filestat);
+  if (status == -1) {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (1);
+  } 
+  if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRWXU)) ||
+      ((gid == filestat.st_gid) && (filestat.st_mode & S_IRWXG)) || 
+      (filestat.st_mode & S_IRWXO)) {
+  } else {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (1);
+  }
+  
+  /* check permission to write to file */
+  sprintf (filename, "%s\0", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (1);
+    }
+  }
+  
+  /* check permission to write to backup file */
+  sprintf (filename, "%s.UT\0", basefile);
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, we should exit! */
+    fprintf (stderr, "ERROR: %s already exists, already fixed times\n", filename);
+    exit (1);
+  }
+  
+}
+
+
+fixtime (unsigned int *T) {
+
+  struct tm now, *gmt;
+  unsigned int t, Nsec;
+  double jd;
+
+  t = *T;
+
+  gmt   = gmtime (&t);
+  now = gmt[0];
+
+  /* fix problems with DST dates */
+  if (((now.tm_mon == 3) && (now.tm_mday >  5)) || 
+      ((now.tm_mon >  3) && (now.tm_mon  <  9)) || 
+      ((now.tm_mon == 9) && (now.tm_mday < 26))) {
+    now.tm_hour += 1;
+  }
+
+  /* now subtract one month to get original month */
+  
+  now.tm_mon -= 1;
+  /* fix year error */
+  if (now.tm_mon == -1) {
+    now.tm_mon = 11;
+    now.tm_year -= 1;
+  }
+
+  /* special days:
+     980331 -> 98 04 01 --> 98 02 31
+     980131 -> 98 02 03 --> 98 00 31 
+     */
+
+  if ((now.tm_mon == 4) && (now.tm_mday == 1)) {
+    now.tm_mon = 2;
+    now.tm_mday = 31;
+  }
+
+  if ((now.tm_mon == 2) && (now.tm_mday == 3)) {
+    now.tm_mon = 0;
+    now.tm_mday = 31;
+  }
+
+  /* we now have year,mon-1,mday,hour,min,sec all correct.
+     now convert to JD and from there to seconds. */
+
+  jd = now.tm_mday - 32075 + (int)(1461*(1900 + now.tm_year + 4800 + (int)(((now.tm_mon+1)-14)/12))/4)
+    + (int)(367*((now.tm_mon+1) - 2 - (int)(((now.tm_mon+1) - 14)/12)*12)/12)
+    - (int)(3*(int)((1900 + now.tm_year + 4900 + (int)(((now.tm_mon+1) - 14)/12))/100)/4) - 0.5;
+  
+  Nsec = (jd - 2440587.5)*86400 + 3600.0*now.tm_hour + now.tm_min*60.0 + now.tm_sec;
+  *T = Nsec;
+
+  /*
+  fprintf (stderr, "%d -> %02d/%02d/%02d %02d:%02d:%02d -> %d\n",
+	   t, 
+	   now.tm_year, now.tm_mon+1, now.tm_mday, 
+	   now.tm_hour, now.tm_min, now.tm_sec, Nsec);
+	   */
+}
Index: /tags/start/Ohana/src/misc/src/fiximg.c
===================================================================
--- /tags/start/Ohana/src/misc/src/fiximg.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/fiximg.c	(revision 12606)
@@ -0,0 +1,48 @@
+# include <ohana.h>
+# include <loneos.h>
+
+int main (int argc, char **argv) {
+
+  char *p;
+  int i, N;
+  Matrix matrix;
+  Header header;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: fiximg (input) (output)\n");
+    exit (1);
+  }
+
+  /* read catalog header */
+  if (!fits_read_header (argv[1], &header)) {
+    fprintf (stderr, "error loading file %s\n", argv[1]);
+    exit (1);
+  }
+  if (!fits_read_matrix (argv[1], &matrix)) {
+    fprintf (stderr, "error loading file %s\n", argv[1]);
+    exit (1);
+  }
+
+  N = 0;
+  while (fits_header_field (&header, "COMMENT", 1) != (char *) NULL) {
+    N++;
+    fits_delete (&header, "COMMENT", 1);
+  }
+  fprintf (stderr, "deleted %d comments\n", N);
+  p = fits_header_field (&header, "END", 1);
+  for (i = 3; i < header.size - (int) (p - header.buffer); i++) { 
+    p[i] = ' '; 
+  }
+
+  /* read catalog header */
+  if (!fits_write_header (argv[2], &header)) {
+    fprintf (stderr, "error writing file %s\n", argv[2]);
+    exit (1);
+  }
+  if (!fits_write_matrix (argv[2], &matrix)) {
+    fprintf (stderr, "error writing file %s\n", argv[2]);
+    exit (1);
+  }
+  exit (0);
+
+}
Index: /tags/start/Ohana/src/misc/src/fixsimple.c
===================================================================
--- /tags/start/Ohana/src/misc/src/fixsimple.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/fixsimple.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include <ohana.h>
+# include <loneos.h>
+
+main (int argc, char **argv) {
+
+  char *p;
+  int i, N;
+  Matrix matrix;
+  Header header;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: fixsimple (input) (output)\n");
+    exit (1);
+  }
+
+  /* read header */
+  if (!fits_read_header (argv[1], &header)) {
+    fprintf (stderr, "error loading file %s\n", argv[1]);
+    exit (1);
+  }
+
+  N = 0;
+  while (fits_header_field (&header, "COMMENT", 1) != (char *) NULL) {
+    N++;
+    fits_delete (&header, "COMMENT", 1);
+  }
+  fprintf (stderr, "deleted %d comments\n", N);
+  p = fits_header_field (&header, "END", 1);
+  for (i = 3; i < header.size - (int) (p - header.buffer); i++) { 
+    p[i] = ' '; 
+  }
+
+  /* read catalog header */
+  if (!fits_write_header (argv[2], &header)) {
+    fprintf (stderr, "error writing file %s\n", argv[2]);
+    exit (1);
+  }
+  if (!fits_write_matrix (argv[2], &matrix)) {
+    fprintf (stderr, "error writing file %s\n", argv[2]);
+    exit (1);
+  }
+  exit (0);
+
+  f = fopen (argv[1], "r+");
+  if (f == NULL) {
+    fprintf (stderr, "can't open file for update %s\n", argv[1]);
+    exit (1);
+  }
+
+  fseek (f, skip, SEEK_SET);
+  status = fwrite (header.buffer, 1, header.size, f);
+  if (status != header.size) {
+    fprintf (stderr, "failed to write data to image header\n");
+    exit (1);
+  }
+  if (fclose (f)) {
+    fprintf (stderr, "error writing data to disk\n");
+    exit (1);
+  }
+
+}
Index: /tags/start/Ohana/src/misc/src/ftable.c
===================================================================
--- /tags/start/Ohana/src/misc/src/ftable.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/ftable.c	(revision 12606)
@@ -0,0 +1,366 @@
+# include <ohana.h>
+
+char *print_table_row (char *row, Header *header);
+FILE *load_extension (char *file, int Nextend, char *Extname, Header *header);
+void print_column (FTable *table, int Column, char *Colname);
+void usage();
+void list_extnames (char *file);
+void print_layout (Header *header);
+int Binary;
+
+int main (int argc, char **argv) {
+
+  int i, N, Nx, Ny, Nbytes, Nread;
+  int Nextend, Column, Row, ListExtname, Layout;
+  char *Extname, *Colname, *line, ttype[80];
+  FTable table;
+  Header header;
+  FILE *f;
+
+  if (get_argument (argc, argv, "-h")) usage ();
+  if (get_argument (argc, argv, "--help")) usage ();
+
+  Nextend = 0;
+  if ((N = get_argument (argc, argv, "-x"))) {
+    remove_argument (N, &argc, argv);
+    Nextend = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Extname = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    if (Nextend) usage ();
+    remove_argument (N, &argc, argv);
+    Extname = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Row = 0;
+  if ((N = get_argument (argc, argv, "-row"))) {
+    remove_argument (N, &argc, argv);
+    Row = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Column = 0;
+  if ((N = get_argument (argc, argv, "-ncolumn"))) {
+    remove_argument (N, &argc, argv);
+    Column = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Colname = 0;
+  if ((N = get_argument (argc, argv, "-column"))) {
+    if (Column) usage ();
+    remove_argument (N, &argc, argv);
+    Colname = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  ListExtname = FALSE;
+  if ((N = get_argument (argc, argv, "-list"))) {
+    remove_argument (N, &argc, argv);
+    ListExtname = TRUE;
+  }
+
+  Layout = FALSE;
+  if ((N = get_argument (argc, argv, "-layout"))) {
+    remove_argument (N, &argc, argv);
+    Layout = TRUE;
+  }
+
+  if (argc != 2) usage ();
+
+  if (ListExtname) list_extnames (argv[1]);
+
+  /* load header */
+  table.header = &header;
+  f = load_extension (argv[1], Nextend, Extname, table.header);
+
+  if (Layout) print_layout (table.header);
+
+  Binary = FALSE;
+  fits_scan (table.header, "XTENSION", "%s", 1, ttype);
+  if (!strcmp (ttype, "BINTABLE")) Binary = TRUE;
+
+  /* load table data array */
+  Nbytes = fits_matrix_size (table.header);
+  ALLOCATE (table.buffer, char, Nbytes);
+  Nread = fread (table.buffer, sizeof (char), Nbytes, f);
+  if (Nread != Nbytes) {
+    fprintf (stderr, "failed to read all table data\n");
+    exit (1);
+  }
+  table.size = Nbytes;
+
+  fits_scan (table.header, "NAXIS1",  "%d", 1, &Nx);
+  fits_scan (table.header, "NAXIS2",  "%d", 1, &Ny);
+
+  /* print a column */
+  if (Column || (Colname != (char *) NULL)) print_column (&table, Column, Colname);
+
+  /* print a row */
+  if (Row) {
+    line = print_table_row (&table.buffer[Nx*Row], table.header);
+    fprintf (stdout, "%s\n", line);
+    free (line);
+    exit (0);
+  }
+
+  /* print complete table */
+  for (i = 0; i < Ny; i++) {
+    line = print_table_row (&table.buffer[Nx*i], table.header);
+    fprintf (stdout, "%s\n", line);
+    free (line);
+  }    
+  exit (0);
+}
+
+/* print an ASCII table to a row with single spaces separating value */
+char *print_table_row (char *row, Header *header) {
+  
+  int i, j, Nx, Nfields, Nbytes, Nvals, Oout, Oin;
+  char field[16], type[16], format[16], *line;
+
+  fits_scan (header, "NAXIS1",  "%d", 1, &Nx);
+  fits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+
+  /* assume we have one space per byte column */
+  ALLOCATE (line, char, 2*Nx + 1);
+
+  Oin = Oout = 0;
+  for (i = 1; i <= Nfields; i++) {
+    sprintf (field, "TFORM%d", i);
+    fits_scan (header, field, "%s", 1, format); /* get field format */
+    fits_table_format (format, type, &Nvals, &Nbytes);    /* convert to c-style */
+    memcpy (&line[Oout], &row[Oin], Nvals*Nbytes);
+    for (j = 0; j < Nvals*Nbytes; j++) if (line[Oout+j] == 0) line[Oout+j] = ' ';
+    line[Oout+Nvals*Nbytes] = ' ';
+    Oout += Nvals*Nbytes + 1;
+    Oin += Nvals*Nbytes;
+  }
+
+  return (line);
+}
+
+void usage () {
+    fprintf (stderr, "USAGE: [-h] [-N N] (table.fits)\n");
+    fprintf (stderr, " -x N:       operate on extension N (0 is default)\n");
+    fprintf (stderr, " -n EXTNAME: operate on named extension (incompatible with -x)\n");
+    fprintf (stderr, " -row N:     print row number N\n");
+    fprintf (stderr, " -column n:  print column named n\n");
+    fprintf (stderr, " -ncolumn N: print column number N\n");
+    fprintf (stderr, " -list:      print extension names\n");
+    exit (2);
+}
+
+void list_extnames (char *file) {
+
+  FILE *f;
+  int Nx, Ny, extend, Nbytes;
+  char extname[82];
+  Header header;
+
+  f = fopen (file, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open file %s\n", file);
+    exit (1);
+  }
+
+  if (!fits_fread_header (f, &header)) {
+    fprintf (stderr, "can't read header from %s\n", file);
+    exit (1);
+  }
+
+  extend = FALSE;
+  fits_scan (&header, "EXTEND", "%t", 1, &extend);
+  if (!extend) {
+    fprintf (stderr, "no extensions listed in file\n");
+  }
+
+  Nbytes = fits_matrix_size (&header);
+  fseek (f, Nbytes, SEEK_CUR);
+
+  while (fits_fread_header (f, &header)) {
+    fits_scan (&header, "EXTNAME", "%s", 1, extname);
+    fits_scan (&header, "NAXIS1",  "%d", 1, &Nx);
+    fits_scan (&header, "NAXIS2",  "%d", 1, &Ny);
+    fprintf (stdout, "%-30s %6d %6d\n", extname, Nx, Ny);
+
+    Nbytes = fits_matrix_size (&header);
+    fseek (f, Nbytes, SEEK_CUR);
+  }
+  fclose (f);
+  exit (0);
+}
+
+FILE *load_extension (char *file, int Nextend, char *Extname, Header *header) {
+
+  int i, extend, Nbytes;
+  char extname[82];
+  FILE *f;
+
+  /* find extension of interest */
+  if (!Nextend && (Extname == (char *) NULL)) Nextend = 1;
+
+  /* open file */
+  f = fopen (file, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open file %s\n", file);
+    exit (1);
+  }
+
+  /* read PHU */
+  if (!fits_fread_header (f, header)) {
+    fprintf (stderr, "can't read header from %s\n", file);
+    exit (1);
+  }
+
+  /* check for existence of extensions */
+  extend = FALSE;
+  fits_scan (header, "EXTEND", "%t", 1, &extend);
+  if (!extend) {
+    fprintf (stderr, "no extensions listed in file\n");
+  }
+
+  /* skip first data array */
+  Nbytes = fits_matrix_size (header);
+  fseek (f, Nbytes, SEEK_CUR);
+
+  /* search for extension of interest */
+  for (i = 1; fits_fread_Theader (f, header); i++) {
+    if (Nextend && (Nextend == i)) return (f);
+
+    fits_scan (header, "EXTNAME", "%s", 1, extname);
+    if ((Extname != (char *) NULL) && (!strcmp (Extname, extname))) return (f);
+
+    Nbytes = fits_matrix_size (header);
+    fseek (f, Nbytes, SEEK_CUR);
+    fits_free_header (header);
+  }
+  fclose (f);
+
+  fprintf (stderr, "failed to load extension of interest\n");
+  exit (1);
+}
+
+void print_column (FTable *table, int Column, char *Colname) {
+  
+  int i, j, Nfields, Nstart, Nv, Nb, Nx, Ny;
+  Header *header;
+  char format[16], field[16], type[16], *line, *data;
+  int *Ti;
+  float *Tf;
+
+  header =  table[0].header;
+  data   =  table[0].buffer;
+
+  fits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  fits_scan (header, "NAXIS1",  "%d", 1, &Nx);
+  fits_scan (header, "NAXIS2",  "%d", 1, &Ny);
+
+  if (Colname != (char *) NULL) {
+    /* find matching column entry */
+    for (i = 1; i <= Nfields; i++) {
+      sprintf (field, "TTYPE%d", i);
+      fits_scan (header, field, "%s", 1, type);
+      if (!strcmp (type, Colname)) {
+	Column = i;
+	break;
+      }
+    }
+    if (!Column) {
+      fprintf (stderr, "column %s not found\n", Colname);
+      exit (1);
+    }
+  } else {
+    /* check if Column is in range */
+    if (Column > Nfields) {
+      fprintf (stderr, "-ncolumn %d too large, only %d columns\n", Column, Nfields);
+      exit (1);
+    }
+  }
+
+  /* scan columns to find insert point */
+  Nstart = 0;
+  for (i = 1; i < Column; i++) {
+    sprintf (field, "TFORM%d", i);
+    fits_scan (header, field, "%s", 1, format);
+    if (Binary) 
+      fits_table_format (format, type, &Nv, &Nb);
+    else 
+      fits_bintable_format (format, type, &Nv, &Nb);
+    Nstart += Nv*Nb;
+  }
+
+  sprintf (field, "TFORM%d", Column);
+  fits_scan (header, field, "%s", 1, format);
+  if (Binary) 
+    fits_bintable_format (format, type, &Nv, &Nb);    /* convert to c-style */
+  else 
+    fits_table_format (format, type, &Nv, &Nb);    /* convert to c-style */
+
+  ALLOCATE (line, char, Nv*Nb + 1);
+
+  if (Binary) {
+    if (!fits_get_bintable_column_type (header, Colname, type, &Nv)) return;
+    if (!strcmp (type, "char")) return;
+    if (!fits_get_bintable_column (header, table, Colname, (void **)&data)) return;
+
+    for (i = 0; i < Ny; i++) {
+      if (!strcmp (type, "char")) {
+	memcpy (line, &data[i*Nx + Nstart], Nv*Nb);
+	fprintf (stdout, "%s\n", line);
+      } else {
+	for (j = 0; j < Nv; j++) {
+	  if (!strcmp (type, "int")) {
+	    memcpy (line, &data[i*Nx + Nstart + Nb*j], Nb);
+	    ByteSwap (line, Nb, 1, "int");
+	    Ti = (int *)line;
+	    fprintf (stdout, "%d ", Ti[0]);
+	  }
+	  if (!strcmp (type, "float")) {
+	    memcpy (line, &data[i*Nx + Nstart + Nb*j], Nb);
+	    ByteSwap (line, Nb, 1, "float");
+	    Tf = (float *)line;
+	    fprintf (stdout, "%f ", Tf[0]);
+	  }
+	}
+	fprintf (stdout, "\n");
+      }
+    }
+  } else {
+    for (i = 0; i < Ny; i++) {
+      memcpy (line, &data[i*Nx + Nstart], Nv*Nb);
+      sprintf (format, "%%%ds\n", Nv*Nb);
+      fprintf (stdout, format, line);
+    }
+  }
+  exit (0);
+}
+
+void print_layout (Header *header) {
+
+  int i, Nfields;
+  char field[16], type[80], comment[80], format[80], unit[80], null[80], nval[80];
+
+  fits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+
+  for (i = 1; i <= Nfields; i++) {
+    sprintf (field, "TTYPE%d", i);
+    fits_scan (header, field, "%s", 1, type);
+    fits_scan (header, field, "%C", 1, comment);
+    sprintf (field, "TFORM%d", i);
+    fits_scan (header, field, "%s", 1, format);
+    sprintf (field, "TUNIT%d", i);
+    fits_scan (header, field, "%s", 1, unit);
+    sprintf (field, "TNULL%d", i);
+    fits_scan (header, field, "%s", 1, null);
+    sprintf (field, "TNVAL%d", i);
+    fits_scan (header, field, "%s", 1, nval);
+
+    fprintf (stdout, "%-18s %-32s %-18s %-6s %-8s %-8s\n", 
+	  type, comment, unit, format, null, nval); 
+  }
+  exit (0);
+}
Index: /tags/start/Ohana/src/misc/src/gconfig.c
===================================================================
--- /tags/start/Ohana/src/misc/src/gconfig.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/gconfig.c	(revision 12606)
@@ -0,0 +1,66 @@
+# include "ohana.h"
+void usage ();
+
+int main (int argc, char **argv) {
+
+  char *config, *file;
+  char word[256];
+  int i, N, VERBOSE, status;
+
+  if ((N = get_argument (argc, argv, "-h"))) { usage (); }
+  if ((N = get_argument (argc, argv, "-help"))) { usage (); }
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (&argc, argv, "ptolemy");
+
+  /* dump raw config file (no interpolation of input files */
+  if ((N = get_argument (argc, argv, "-raw"))) {
+    config = LoadRawConfigFile (file, TRUE);
+    fwrite (config, 1, strlen(config), stdout);
+    exit (0);
+  }
+
+  /* load complete config info from file(s) */
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (1);
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = TRUE;
+  }
+  if ((N = get_argument (argc, argv, "-q"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = FALSE;
+  }
+
+  /* if no keywords, dump entire config file */
+  if (argc == 1) {
+    fwrite (config, 1, strlen(config), stdout);
+    exit (0);
+  }
+
+  status = 0;
+  for (i = 1; i < argc; i++) {
+    if (ScanConfig (config, argv[i], "%s", 0,  word) == (char *) NULL) {
+      strcpy (word, "not found");
+      status = 1;
+    }
+    if (VERBOSE) {
+      fprintf (stdout, "%s %s\n", argv[i], word);
+    } else {
+      fprintf (stdout, "%s\n", word);
+    }
+  }
+  exit (status);
+}
+
+void usage () {
+  fprintf (stderr, "gconfig: print elixir config information\n");
+  fprintf (stderr, " USAGE: gconfig [keywords...] [-c file] [-C config] [-D keyword value]\n");
+  exit (2);
+}
Index: /tags/start/Ohana/src/misc/src/get_argument.c
===================================================================
--- /tags/start/Ohana/src/misc/src/get_argument.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/get_argument.c	(revision 12606)
@@ -0,0 +1,18 @@
+# include <stdio.h>
+
+int
+get_argument (argc, argv, arg)
+int argc;
+char *argv[];
+char arg[];
+{
+
+  int i;
+
+  for (i = 0; i < argc; i++) {
+    if (!strcmp(argv[i], arg))
+      return (i);
+  }
+  
+  return ((int)NULL);
+}
Index: /tags/start/Ohana/src/misc/src/glock.c
===================================================================
--- /tags/start/Ohana/src/misc/src/glock.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/glock.c	(revision 12606)
@@ -0,0 +1,301 @@
+# include <stdio.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <errno.h>
+# include <fcntl.h>
+# include <sys/time.h>
+# include <unistd.h>
+# include <stdlib.h>
+
+# define LCK_ACCESS  1   /* can't get access to file */
+# define LCK_TIMEOUT 2   /* timeout setting lock */
+# define LCK_HARDLCK 3   /* error setting hard lockfile */
+# define LCK_HUNLOCK 4   /* error clearing hard lockfile */
+
+# define LCK_EMPTY   5   /* locked file is empty */
+# define LCK_FULL    6   /* locked file is not empty */
+# define LCK_UNKNOWN 7   /* can't stat file to get size */
+
+# define LCK_SOFT    10  /* soft lock */
+# define LCK_HARD    11  /* hard lock */
+# define LCK_XCLD    12  /* exclusive soft lock */
+
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+
+extern int errno;
+extern char *pathname (), *filebasename ();
+
+# ifndef ALLOCATE
+# define ALLOCATE(X,T,S)  \
+  X=(T *)malloc((unsigned) ((S)*sizeof(T)));\
+  if(X==NULL) \
+    { \
+      fprintf(stderr,"failed to malloc X\n");\
+        exit(0);\
+    } 
+# define REALLOCATE(X,T,S) \
+  X=(T *)realloc(X,(unsigned) ((S)*sizeof(T))); \
+  if(X==NULL) \
+    { \
+       fprintf(stderr,"failed to realloc X\n"); \
+       exit(0); \
+    }
+# endif /* ALLOCATE */
+
+main (int argc, char **argv) {
+
+  int i, status, done, nbytes, type;
+  char *lockname, *filename, buffer[64];
+  char *file, *path;
+  int fd, flock;
+  int filemode, state, holdtime;
+  double timeout;
+  struct stat filestat;
+  struct flock filelock;
+  struct timeval now, then;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: glock (filename) (type) (holdtime)\n");
+    exit (1);
+  }
+
+  filename = argv[1];
+  timeout = 1.0;
+
+  holdtime = atoi (argv[3]);
+
+  type = 0;
+  if (!strcasecmp (argv[2], "hard")) {
+    type = LCK_HARD;
+  }
+  if (!strcasecmp (argv[2], "soft")) {
+    type = LCK_SOFT;
+  }
+  if (!strcasecmp (argv[2], "xcld")) {
+    type = LCK_XCLD;
+  }
+
+  file = path = lockname = (char *) NULL;
+  gettimeofday (&then, (void *) NULL);
+
+  /* define lock type */
+  filelock.l_start  = 0;
+  filelock.l_whence = SEEK_SET;
+  filelock.l_len    = 0;
+  filelock.l_pid    = getpid ();
+  switch (type) {
+  case LCK_HARD:
+  case LCK_XCLD:
+    filelock.l_type   = F_WRLCK;  /* set an exclusive lock */
+    break;
+  case LCK_SOFT:
+    filelock.l_type   = F_RDLCK;  /* set a shared lock */
+    break;
+  default:
+    fprintf (stderr, "invalid lock type %d\n", type);
+  }
+  filemode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+
+  /* try to open file */
+  fd = open (filename, O_RDWR | O_CREAT, filemode);
+  if (fd == -1) {
+    state = LCK_ACCESS;
+    goto failure;
+  }
+
+  /* we first try to set a FS level lock on the file */
+  for (done = 0; !done; ) {
+
+    /* check for timeout */
+    gettimeofday (&now, (void *) NULL);
+    if (DTIME (now, then) > timeout) {
+      state = LCK_TIMEOUT;
+      fcntl (fd, F_GETLK, &filelock);
+      fprintf (stderr, "lock held:\n");
+      fprintf (stderr, "pid: %d\n", filelock.l_pid);
+      fprintf (stderr, "lock stats: %d %d %d\n", filelock.l_start, filelock.l_whence, filelock.l_len);
+      goto failure;
+    }
+    usleep (1000);
+
+    /* try to lock file */
+    if (fcntl (fd, F_SETLK, &filelock) != -1) done = 1;
+  }
+
+  if (type == LCK_HARD) {
+    /* we've locked filename, now check lockname */ 
+
+    /* locking the lockfile before checking / setting contents will 
+       ensure the data is synced across NFS */
+    
+    /* set up name to lockfile */
+    path = pathname (filename);
+    file = filebasename (filename);
+    ALLOCATE (lockname, char, strlen (path) + strlen (file) + 10);
+    sprintf (lockname, "%s/.%s.lck", path, file);
+
+    /* try to open lockfile */
+    flock = open (lockname, O_RDWR | O_CREAT, filemode);
+    if (flock == -1) {
+      state = LCK_HARDLCK;
+      goto failure;
+    }
+    
+    /* try a few times to lock lockfile */
+    for (i = 0; (i < 20) && (fcntl (flock, F_SETLK, &filelock) == -1); i++) {
+      usleep (10000);
+    }
+    if (i == 20) {
+      state = LCK_HARDLCK + 10;
+      goto failure;
+    }
+    
+    /* we've locked the file, now read the contents */
+    nbytes = read (flock, buffer, 4);
+    if (nbytes == 4) { /* lock file has a word in it */
+      buffer[4] = 0;
+      if (!strcmp (buffer, "BUSY")) { 
+	state = LCK_HARDLCK + 20;
+	goto failure;
+      }
+    }
+    
+    /* we've really got the lock, write BUSY to protect it */
+    lseek (flock, 0, SEEK_SET);
+    write (flock, "BUSY", 4);
+    
+    /* now unlock lockfile */
+    filelock.l_type = F_UNLCK;
+    if (fcntl (flock, F_SETLK, &filelock) == -1) {
+      state = LCK_HARDLCK + 30;
+      goto failure;
+    }
+    if (close (flock)) {
+      fprintf (stderr, "error closing lock\n");
+      goto failure;
+    }
+  }
+
+  /* check if file is empty or not */
+  if (fstat (fd, &filestat)) {
+    state = LCK_UNKNOWN;
+  } else {
+    if (filestat.st_size == 0) {
+      state = LCK_EMPTY;
+    } else {
+      state = LCK_FULL;
+    }
+  }
+
+  fprintf (stderr, "file is locked...\n");
+  for (i = holdtime; i > 0; i--) {
+    fprintf (stderr, "%d ", i);
+    usleep (1000000);
+  }
+  
+  clearlockfile2 (filename, fd, type, &state);
+  fprintf (stderr, "file unlocked...\n");
+   
+
+  if (path != NULL) free (path);
+  if (file != NULL) free (file);
+  if (lockname != NULL) free (lockname);
+  exit (0);
+
+failure:
+  if (path != NULL) free (path);
+  if (file != NULL) free (file);
+  if (lockname != NULL) free (lockname);
+  exit (1);
+}
+  
+
+/* if we pass in -1, all we can do is clear the hardlock */
+int clearlockfile2 (char *filename, int fd, int type, int *state) {
+  
+  char *lockname;
+  int i, status;
+  char *path, *file;
+  int flock, filemode;
+  struct stat filestat;
+  struct flock filelock;
+
+  file = path = lockname = (char *) NULL;
+
+  /* define lock */
+  filelock.l_type   = F_UNLCK;
+  filelock.l_start  = 0;
+  filelock.l_whence = SEEK_SET;
+  filelock.l_len    = 0;
+  filelock.l_pid    = getpid ();
+  filemode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+
+  /* first clear hard lockfile */
+  if (type == LCK_HARD) {
+
+    /* define lockfile */
+    path = pathname (filename);
+    file = filebasename (filename);
+    ALLOCATE (lockname, char, strlen (path) + strlen (file) + 10);
+    sprintf (lockname, "%s/.%s.lck", path, file);
+    
+    /* check for lockfile existence */
+    status = stat (lockname, &filestat);
+    if (status == -1) {
+      *state = LCK_HUNLOCK;
+      goto failure;
+    } 
+  
+    /* open lockfile */
+    flock = open (lockname, O_RDWR | O_CREAT, filemode);
+    if (flock == -1) {
+      *state = LCK_HUNLOCK;
+      goto failure;
+    }
+
+    /* try a few times to lock lockfile */
+    filelock.l_type = F_WRLCK;
+    for (i = 0; (i < 20) && (fcntl (flock, F_SETLK, &filelock) == -1); i++) {
+      usleep (10000);
+    }
+    if (i == 20) {
+      *state = LCK_HUNLOCK;
+      goto failure;
+    }
+
+    /* set value to IDLE */
+    lseek (flock, 0, SEEK_SET);
+    write (flock, "IDLE", 4);
+
+    /* unlock lockfile */
+    filelock.l_type = F_UNLCK;
+    if (fcntl (flock, F_SETLK, &filelock) == -1) {
+      *state = LCK_HUNLOCK;
+      goto failure;
+    }
+    if (close (flock)) {
+      fprintf (stderr, "error closing lock\n");
+      goto failure;
+    }
+  }
+  
+  /* now unlock the file */
+  if (fd != -1) {
+    if (fcntl (fd, F_SETLK, &filelock) == -1) {
+      *state = LCK_HUNLOCK;
+      goto failure;
+    }
+  }
+
+  if (path != NULL) free (path);
+  if (file != NULL) free (file);
+  if (lockname != NULL) free (lockname);
+  return (1);
+
+failure:
+  if (path != NULL) free (path);
+  if (file != NULL) free (file);
+  if (lockname != NULL) free (lockname);
+  return (0);
+
+}
Index: /tags/start/Ohana/src/misc/src/glockfile.c
===================================================================
--- /tags/start/Ohana/src/misc/src/glockfile.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/glockfile.c	(revision 12606)
@@ -0,0 +1,41 @@
+# include <ohana.h>
+
+int main (int argc, char **argv) {
+
+  char *filename;
+  double timeout;
+  int holdtime, state, type, fd;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: glock (filename) (type) (holdtime)\n");
+    exit (1);
+  }
+
+  filename = argv[1];
+  timeout = 120.0;
+
+  holdtime = atoi (argv[3]);
+
+  type = 0;
+  if (!strcasecmp (argv[2], "hard")) {
+    type = LCK_HARD;
+  }
+  if (!strcasecmp (argv[2], "soft")) {
+    type = LCK_SOFT;
+  }
+  if (!strcasecmp (argv[2], "xcld")) {
+    type = LCK_XCLD;
+  }
+
+  fd = setlockfile2 (filename, timeout, type, &state);
+  if (fd == -1) {
+    fprintf (stderr, "ERROR: can't lock file %s\n", filename);
+    exit (1);
+  }
+
+  sleep (holdtime);
+  
+  clearlockfile2 (filename, fd, type, &state);
+
+  exit (0);
+}
Index: /tags/start/Ohana/src/misc/src/glockfile2.c
===================================================================
--- /tags/start/Ohana/src/misc/src/glockfile2.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/glockfile2.c	(revision 12606)
@@ -0,0 +1,286 @@
+# include <stdio.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <errno.h>
+# include <fcntl.h>
+# include <sys/time.h>
+# include <unistd.h>
+# include <stdlib.h>
+
+# define LCK_ACCESS  1   /* can't get access to file */
+# define LCK_TIMEOUT 2   /* timeout setting lock */
+# define LCK_HARDLCK 3   /* error setting hard lockfile */
+# define LCK_HUNLOCK 4   /* error clearing hard lockfile */
+
+# define LCK_EMPTY   5   /* locked file is empty */
+# define LCK_FULL    6   /* locked file is not empty */
+# define LCK_UNKNOWN 7   /* can't stat file to get size */
+
+# define LCK_SOFT    10  /* soft lock */
+# define LCK_HARD    11  /* hard lock */
+# define LCK_XCLD    12  /* exclusive soft lock */
+
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+
+extern int errno;
+extern char *pathname (), *filebasename ();
+
+# ifndef ALLOCATE
+# define ALLOCATE(X,T,S)  \
+  X=(T *)malloc((unsigned) ((S)*sizeof(T)));\
+  if(X==NULL) \
+    { \
+      fprintf(stderr,"failed to malloc X\n");\
+        exit(0);\
+    } 
+# define REALLOCATE(X,T,S) \
+  X=(T *)realloc(X,(unsigned) ((S)*sizeof(T))); \
+  if(X==NULL) \
+    { \
+       fprintf(stderr,"failed to realloc X\n"); \
+       exit(0); \
+    }
+# endif /* ALLOCATE */
+
+/* 
+   set a lockfile on [path]/filename.  
+   we allow two types of locks: hard & soft
+
+   both lock types set a filesystem-level lock on the given file, 
+    using exclusive for hard and shared for soft locks
+
+   a hard lock also uses a lockfile to make the lock permanent:
+    the lockfile must be actively removed and will not vanish 
+    even if the locking program dies 
+
+   a soft lock will vanish if the locking program dies.
+
+   if a hard lock is set, both hard & soft locks will block
+   if a soft lock is set, a hard lock will block, but not a soft lock
+
+   the hard lockfile uses the file [path]/.filename.lck
+
+   setlockfile returns a file descriptor to an open READ/WRITE access file,
+     or -1 on failure, and sets state.
+*/
+
+int setlockfile2 (char *filename, double timeout, int type, int *state) {
+  
+  int i, status, done, nbytes;
+  char *lockname, buffer[64];
+  char *file, *path;
+  int fd, flock;
+  int filemode;
+  struct stat filestat;
+  struct flock filelock;
+  struct timeval now, then;
+
+  file = path = lockname = (char *) NULL;
+  gettimeofday (&then, (void *) NULL);
+
+  /* define lock type */
+  filelock.l_start  = 0;
+  filelock.l_whence = SEEK_SET;
+  filelock.l_len    = 0;
+  filelock.l_pid    = getpid ();
+  switch (type) {
+  case LCK_HARD:
+  case LCK_XCLD:
+    filelock.l_type   = F_WRLCK;  /* set an exclusive lock */
+    break;
+  case LCK_SOFT:
+    filelock.l_type   = F_RDLCK;  /* set a shared lock */
+    break;
+  default:
+    fprintf (stderr, "invalid lock type %d\n", type);
+  }
+  filemode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+
+  /* try to open file */
+  fd = open (filename, O_RDWR | O_CREAT, filemode);
+  if (fd == -1) {
+    *state = LCK_ACCESS;
+    goto failure;
+  }
+
+  /* we first try to set a FS level lock on the file */
+  for (done = 0; !done; ) {
+
+    /* check for timeout */
+    gettimeofday (&now, (void *) NULL);
+    if (DTIME (now, then) > timeout) {
+      *state = LCK_TIMEOUT;
+      goto failure;
+    }
+    usleep (1000);
+
+    /* try to lock file */
+    if (fcntl (fd, F_SETLK, &filelock) != -1) done = 1;
+  }
+
+  if (type == LCK_HARD) {
+    /* we've locked filename, now check lockname */ 
+
+    /* locking the lockfile before checking / setting contents will 
+       ensure the data is synced across NFS */
+    
+    /* set up name to lockfile */
+    path = pathname (filename);
+    file = filebasename (filename);
+    ALLOCATE (lockname, char, strlen (path) + strlen (file) + 10);
+    sprintf (lockname, "%s/.%s.lck", path, file);
+
+    /* try to open lockfile */
+    flock = open (lockname, O_RDWR | O_CREAT, filemode);
+    if (flock == -1) {
+      *state = LCK_HARDLCK;
+      goto failure;
+    }
+    
+    /* try a few times to lock lockfile */
+    for (i = 0; (i < 20) && (fcntl (flock, F_SETLK, &filelock) == -1); i++) {
+      usleep (10000);
+    }
+    if (i == 20) {
+      *state = LCK_HARDLCK + 10;
+      goto failure;
+    }
+    
+    /* we've locked the file, now read the contents */
+    nbytes = read (flock, buffer, 4);
+    if (nbytes == 4) { /* lock file has a word in it */
+      buffer[4] = 0;
+      if (!strcmp (buffer, "BUSY")) { 
+	*state = LCK_HARDLCK + 20;
+	goto failure;
+      }
+    }
+    
+    /* we've really got the lock, write BUSY to protect it */
+    lseek (flock, 0, SEEK_SET);
+    write (flock, "BUSY", 4);
+    
+    /* now unlock lockfile */
+    filelock.l_type = F_UNLCK;
+    if (fcntl (flock, F_SETLK, &filelock) == -1) {
+      *state = LCK_HARDLCK + 30;
+      goto failure;
+    }
+    if (close (flock)) {
+      fprintf (stderr, "error closing lock\n");
+      goto failure;
+    }
+  }
+
+  /* check if file is empty or not */
+  if (fstat (fd, &filestat)) {
+    *state = LCK_UNKNOWN;
+  } else {
+    if (filestat.st_size == 0) {
+      *state = LCK_EMPTY;
+    } else {
+      *state = LCK_FULL;
+    }
+  }
+
+  if (path != NULL) free (path);
+  if (file != NULL) free (file);
+  if (lockname != NULL) free (lockname);
+  return (fd);
+
+failure:
+  if (path != NULL) free (path);
+  if (file != NULL) free (file);
+  if (lockname != NULL) free (lockname);
+  return (-1);
+}
+  
+/* if we pass in -1, all we can do is clear the hardlock */
+int clearlockfile2 (char *filename, int fd, int type, int *state) {
+  
+  char *lockname;
+  int i, status;
+  char *path, *file;
+  int flock, filemode;
+  struct stat filestat;
+  struct flock filelock;
+
+  file = path = lockname = (char *) NULL;
+
+  /* define lock */
+  filelock.l_type   = F_UNLCK;
+  filelock.l_start  = 0;
+  filelock.l_whence = SEEK_SET;
+  filelock.l_len    = 0;
+  filelock.l_pid    = getpid ();
+  filemode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+
+  /* first clear hard lockfile */
+  if (type == LCK_HARD) {
+
+    /* define lockfile */
+    path = pathname (filename);
+    file = filebasename (filename);
+    ALLOCATE (lockname, char, strlen (path) + strlen (file) + 10);
+    sprintf (lockname, "%s/.%s.lck", path, file);
+    
+    /* check for lockfile existence */
+    status = stat (lockname, &filestat);
+    if (status == -1) {
+      *state = LCK_HUNLOCK;
+      goto failure;
+    } 
+  
+    /* open lockfile */
+    flock = open (lockname, O_RDWR | O_CREAT, filemode);
+    if (flock == -1) {
+      *state = LCK_HUNLOCK;
+      goto failure;
+    }
+
+    /* try a few times to lock lockfile */
+    filelock.l_type = F_WRLCK;
+    for (i = 0; (i < 20) && (fcntl (flock, F_SETLK, &filelock) == -1); i++) {
+      usleep (10000);
+    }
+    if (i == 20) {
+      *state = LCK_HUNLOCK;
+      goto failure;
+    }
+
+    /* set value to IDLE */
+    lseek (flock, 0, SEEK_SET);
+    write (flock, "IDLE", 4);
+
+    /* unlock lockfile */
+    filelock.l_type = F_UNLCK;
+    if (fcntl (flock, F_SETLK, &filelock) == -1) {
+      *state = LCK_HUNLOCK;
+      goto failure;
+    }
+    if (close (flock)) {
+      fprintf (stderr, "error closing lock\n");
+      goto failure;
+    }
+  }
+  
+  /* now unlock the file */
+  if (fd != -1) {
+    if (fcntl (fd, F_SETLK, &filelock) == -1) {
+      *state = LCK_HUNLOCK;
+      goto failure;
+    }
+  }
+
+  if (path != NULL) free (path);
+  if (file != NULL) free (file);
+  if (lockname != NULL) free (lockname);
+  return (1);
+
+failure:
+  if (path != NULL) free (path);
+  if (file != NULL) free (file);
+  if (lockname != NULL) free (lockname);
+  return (0);
+
+}
Index: /tags/start/Ohana/src/misc/src/gunlock.c
===================================================================
--- /tags/start/Ohana/src/misc/src/gunlock.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/gunlock.c	(revision 12606)
@@ -0,0 +1,18 @@
+# include <stdio.h>
+
+main (int argc, char **argv) {
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: gunlock (filename)\n");
+    exit (1);
+  }
+
+  if (!clearlockfile (argv[1], -1, 1)) {
+    fprintf (stdout, "LOCK NOT REMOVED\n");
+    exit (1);
+  }
+  
+  fprintf (stdout, "LOCK REMOVED\n");
+  exit (0);
+
+}
Index: /tags/start/Ohana/src/misc/src/list_astro.c
===================================================================
--- /tags/start/Ohana/src/misc/src/list_astro.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/list_astro.c	(revision 12606)
@@ -0,0 +1,202 @@
+# include <ohana.h>
+
+int main (int argc, char **argv) {
+
+  float *ra1, *ra2, *dec1, *dec2;
+  float x, y, x2, y2, xy, R, D, Rx, Ry, Dx, Dy, N;
+  float x3, x2y, x4, Rx2;
+  float DEC, RA, DX, DY, RX, RY, d2RA, d2DEC, dRA, dDEC;
+  float Sx2, Sy2, Sxy, Srx, Sry, Sdx, Sdy;
+  int i, Npairs, NPAIR;
+
+  NPAIR = 100;
+  ALLOCATE (ra1, float, NPAIR);
+  ALLOCATE (ra2, float, NPAIR);
+  ALLOCATE (dec1, float, NPAIR);
+  ALLOCATE (dec2, float, NPAIR);
+
+/*
+  ALLOCATE (a, double *, 3);
+  ALLOCATE (a[0], double, 3);
+  ALLOCATE (a[1], double, 3);
+  ALLOCATE (a[2], double, 3);
+  ALLOCATE (a[3], double, 4);
+  ALLOCATE (b, double *, 3);
+  ALLOCATE (b[0], double, 1);
+  ALLOCATE (b[1], double, 1);
+  ALLOCATE (b[2], double, 1);
+  ALLOCATE (b[3], double, 1);
+*/
+
+  if (argc > 1) {
+    fprintf (stderr, "USAGE: list_astro x\nTakes list from the stdin in the");
+    fprintf (stderr, " format:\n  X Y RA DEC\nReturns:\n  RA, RX, RY, dRA\n  DEC, DX, DY, dDEC\n");
+    exit(0);
+  }
+    
+  for (i = 0; fscanf (stdin, "%f %f %f %f", &ra1[i], &dec1[i], &ra2[i], &dec2[i]) != EOF; i++) {
+    if (i == NPAIR - 1) {
+      NPAIR += 50;
+      REALLOCATE (ra1, float, NPAIR);
+      REALLOCATE (ra2, float, NPAIR);
+      REALLOCATE (dec1, float, NPAIR);
+      REALLOCATE (dec2, float, NPAIR);
+    }
+  }
+
+  
+  
+  N = x = y = x2 = y2 = xy = R = D = Rx = Ry = Dx = Dy = 0;
+  Npairs = i;
+  for (i = 0; i < Npairs; i++) {
+    x  += ra1[i];
+    y  += dec1[i];
+    x2 += ra1[i]*ra1[i];
+    y2 += dec1[i]*dec1[i];
+    xy += ra1[i]*dec1[i];
+    x3 += ra1[i]*ra1[i]*ra1[i];
+    x2y += ra1[i]*ra1[i]*dec1[i];
+    x4 += ra1[i]*ra1[i]*ra1[i]*ra1[i];
+    R  += ra2[i];
+    D  += dec2[i];
+    Rx += ra2[i]*ra1[i];
+    Ry += ra2[i]*dec1[i];
+    Rx2 += ra2[i]*ra1[i]*ra1[i];
+    Dx += dec2[i]*ra1[i];
+    Dy += dec2[i]*dec1[i];
+    N  += 1.0;
+  }
+
+/*
+  a[0][0] = N;
+  a[0][1] = a[1][0] = x;
+  a[0][2] = a[2][0] = y;
+  a[0][3] = a[3][0] = x2;
+  a[1][1] = x2;
+  a[1][2] = a[2][1] = xy;
+  a[1][3] = a[3][1] = x3;
+  a[2][2] = y2;
+  a[2][3] = a[3][2] = x2y;
+  a[3][3] = x4;
+  b[0][0] = R;
+  b[1][0] = Rx;
+  b[2][0] = Ry;
+  b[1][0] = Rx2;
+*/
+
+  Sx2 = x2 - x*x/N;
+  Sy2 = y2 - y*y/N;
+  Sxy = xy - x*y/N;
+  Srx = Rx - R*x/N;
+  Sry = Ry - R*y/N;
+  Sdx = Dx - D*x/N;
+  Sdy = Dy - D*y/N;
+  
+  RX = (Srx*Sy2 - Sry*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  RY = (Sry*Sx2 - Srx*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  RA = R/N - RX*x/N - RY*y/N;
+
+/*
+  gaussj (a, 4, b, 1);
+
+  RA = b[0][0];
+  RX = b[1][0];
+  RY = b[2][0];
+  RX2 = b[3][0];
+*/
+  
+  DX  = (Sdx*Sy2 - Sdy*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  DY  = (Sdy*Sx2 - Sdx*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  DEC = D/N - DX*x/N - DY*y/N;
+
+  d2RA = d2DEC = N = 0;
+  N = x = y = x2 = y2 = xy = R = D = Rx = Ry = Dx = Dy = 0;
+  for (i = 0; i < Npairs; i++) {
+    d2RA += pow((ra2[i] - RA - RX*ra1[i] - RY*dec1[i]), 2.0);
+    d2DEC += pow((dec2[i] - DEC - DX*ra1[i] - DY*dec1[i]), 2.0);
+    N += 1.0;
+  }
+
+  dRA  = 3600.0*sqrt(d2RA / (N - 3.0));
+  dDEC = 3600.0*sqrt(d2DEC / (N - 3.0));
+
+  fprintf (stdout, " %12.9f %12.9e %12.9e %12.9f\n", RA, RX, RY, dRA);
+  fprintf (stdout, " %12.9f %12.9e %12.9e %12.9f\n", DEC, DX, DY, dDEC);
+  exit (0);
+}
+
+
+int gaussj (double **a, int n, double **b, int m) {
+
+  int *indxc,*indxr,*ipiv;
+  int i, icol, irow, j, k, l, ll;
+  double big,dum,pivinv;
+  
+  ALLOCATE (indxc, int, n);
+  ALLOCATE (indxr, int, n);
+  ALLOCATE (ipiv, int, n);
+  for (j = 0; j < n; j++) 
+    ipiv[j] = 0;
+
+  for (i = 0; i < n; i++) {
+    big = 0.0;
+    for (j = 0; j < n; j++) {
+      if (ipiv[j] != 1) {
+	for (k = 0; k < n; k++) {
+	  if (ipiv[k] == 0) {
+	    if (fabs (a[j][k]) >= big) {
+	      big  = fabs (a[j][k]);
+	      irow = j;
+	      icol = k;
+	    }
+	  } 
+	  else 
+	    if (ipiv[k] > 1) {
+	      fprintf (stderr, "GAUSSJ: Singular Matrix! (1)\n");
+	      return (0);
+	    }
+	}
+      }
+    }
+    ipiv[icol]++;
+    if (irow != icol) {
+      for (l = 0; l < n; l++) 
+	SWAP (a[irow][l], a[icol][l]);
+      for (l = 0; l < m; l++) 
+	SWAP (b[irow][l], b[icol][l]);
+    }
+    indxr[i] = irow;
+    indxc[i] = icol;
+    if (a[icol][icol] == 0.0) {
+      fprintf (stderr, "GAUSSJ: Singular Matrix! (2)\n");
+      return (0);
+    }
+    pivinv = 1.0 / a[icol][icol];
+    a[icol][icol] = 1.0;
+    for (l = 0; l < n; l++) 
+      a[icol][l] *= pivinv;
+    for (l = 0; l < m; l++) 
+      b[icol][l] *= pivinv;
+    for (ll = 0; ll < n; ll++) {
+      if (ll != icol) {
+	dum = a[ll][icol];
+	a[ll][icol] = 0.0;
+	for (l = 0; l < n; l++) 
+	  a[ll][l] -= a[icol][l]*dum;
+	for (l = 0; l < m; l++) 
+	  b[ll][l] -= b[icol][l]*dum;
+      }
+    }
+  }
+
+  for (l = n - 1; l >= 0; l--) {
+    if (indxr[l] != indxc[l])
+      for (k = 0; k < n; k++)
+	SWAP (a[k][indxr[l]], a[k][indxc[l]]);
+  }
+  free (ipiv);
+  free (indxr);
+  free (indxc);
+  return (1);
+}
+
Index: /tags/start/Ohana/src/misc/src/magtoage.c
===================================================================
--- /tags/start/Ohana/src/misc/src/magtoage.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/magtoage.c	(revision 12606)
@@ -0,0 +1,221 @@
+# include <ohana.h>
+# define MMIN 1.0
+# define MMAX 120.0
+extern double drand48();
+extern double rnd_gauss();
+extern double rnd_integrate ();
+extern double gaussian ();
+
+double gaussian();
+double rnd_gauss();
+double rnd_integrate();
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+
+  Header mass_h, age_h;
+  Matrix mass_i, age_i;
+  double UV0, V0, DV, DUV;
+  double Uo, Vo;
+  double U, V, dUV, dU, dV, mass, age, d, a, da;
+  double M, dM, Ms, M2, m, dm, ldM, lMo, ldA, lAo;
+  double u, v, uv, Av, f, top, bot, alpha;
+  double **Masses, *maxmass, *minmass;
+  double **Ages;
+  int x, y, i, j, Ntry, NAGE, N;
+  char line[1024];
+  long A, B;
+  
+  lAo =   0.0;
+  ldA =   1.0;
+  NAGE =  320;
+  if (N = get_argument (argc, argv, "-age")) {
+    remove_argument (N, &argc, argv);
+    lAo = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    ldA = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    NAGE = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 9) {
+    fprintf (stderr, "USAGE: magtoage massfile agefile d Av Ntry Uo Vo alpha ldM\n");
+    exit (0);
+  }
+  d = atof (argv[3]);
+  Av = atof (argv[4]);
+  Ntry = atof (argv[5]);
+  Uo = atof (argv[6]);
+  Vo = atof (argv[7]);
+  alpha = atof (argv[8]);
+  /*
+  ldM   = atof (argv[9]);
+  lMo = 0.0;
+  */
+  
+  fits_read_header (argv[1], &mass_h);
+  fits_read_matrix (argv[1], &mass_i);
+  fits_read_header (argv[2], &age_h);
+  fits_read_matrix (argv[2], &age_i); 
+
+  fits_scan (&mass_h, "RA_O",  "%lf", 1, &UV0);
+  fits_scan (&mass_h, "RA_X",  "%lf", 1, &DUV);
+  fits_scan (&mass_h, "DEC_O", "%lf", 1, &V0);
+  fits_scan (&mass_h, "DEC_Y", "%lf", 1, &DV);
+
+  ALLOCATE (Ages, double *, (Ntry+2));
+  ALLOCATE (maxmass, double, NAGE);
+  ALLOCATE (minmass, double, NAGE);
+  for (i = 0; i < Ntry + 2; i++) {
+    ALLOCATE (Ages[i], double, NAGE);
+    bzero (Ages[i], sizeof(double) * NAGE);
+  }
+
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+
+  /* find max and min masses for each age bin */
+  for (i = 0; i < NAGE; i++) {
+    maxmass[i] = 0.0;
+    minmass[i] = 1000.0;
+  }
+  for (x = 0; x < age_h.Naxis[0]; x++) {
+    for (y = 0; y < age_h.Naxis[1]; y++) {
+      mass = fits_get_matrix_value (&mass_i, x, y);
+      if (mass == 0.0) continue;
+      age  = fits_get_matrix_value (&age_i, x, y);
+      uv = x*DUV + UV0 + 0.7*Av;
+      v  = y*DV + V0 + Av + d;
+      u  = v + uv;
+      if ((u <= Uo) && (v <= Vo)) {
+	i = (age - lAo) / ldA;
+	if ((i > 0) && (i < NAGE)) {
+	  maxmass[i] = MAX(mass, maxmass[i]);
+	  minmass[i] = MIN(mass, minmass[i]);
+	}
+      }
+    }
+  }
+
+  fprintf (stderr, "beginning main loop\n");
+  while (scan_line (stdin, line) != EOF) {
+    if (!stripwhite (line)) continue;
+    if (line[0] == '#') continue;
+    dparse (&V, 8, line);
+    dparse (&dV, 9, line);
+    dparse (&U, 12, line);
+    dparse (&dU, 13, line);
+    dUV = sqrt (dU*dU + dV*dV);
+    for (i = 0; i < Ntry + 1; i++) {
+      if (i == 0) {
+	fprintf (stderr, ".");
+	v = V;
+	uv = U - V;
+      }
+      else {
+	v = rnd_gauss (V, dV);
+	uv = rnd_gauss ((U-V), dUV);
+      }
+      x = (uv - UV0 - 0.7*Av) / DUV;
+      y = (v - d - V0 - Av) / DV;
+      if ((x > 0) && (x < mass_h.Naxis[0]) &&
+	  (y > 0) && (y < mass_h.Naxis[1])) {
+	mass = fits_get_matrix_value (&mass_i, x, y);
+	if (mass > 0.0) {
+	  age = fits_get_matrix_value (&age_i, x, y); 
+	  j = (age - lAo) / ldA;
+	  if ((j >= 0) && (j < NAGE))
+	    Ages[i][j] += pow(mass, alpha);
+	}
+      }
+    }
+  }
+
+  top = pow (MMAX, 1.0 - alpha) - pow (MMIN, 1.0 - alpha);
+  fprintf (stderr, "finding scatter per bin\n");
+  for (j = 0; j < NAGE; j++) {
+    Ms = M2 = 0.0;
+    for (i = 1; i < Ntry + 1; i++) {
+      Ms += Ages[i][j];
+      M2 += (Ages[i][j]*Ages[i][j]);
+    }
+    M = dM = 0.0;
+    if (Ms > 0) {
+      M  = Ms / (1.0*Ntry);
+      dM = sqrt (M2 / (1.0*Ntry) - M*M);
+    }
+    Ages[1][j] = M;
+    Ages[2][j] = dM;
+    /*
+    a = pow (10.0, j*ldA + lAo);
+    da = pow (10.0, (j+1)*ldA + lAo) - a;
+    */
+    a = j*ldA + lAo;
+    da = ldA;
+    f = 0.0;
+    if (maxmass[j] > minmass[j]) {
+      bot = pow (maxmass[j], 1.0 - alpha) - pow (minmass[j], 1.0 - alpha);
+      if (bot != 0.0) 
+	f = top * top / ((1.0 - alpha) * bot * 2.30158509);
+    }
+    fprintf (stdout, "%d %f %f %f %f %f %f %f\n", j, a, da, Ages[0][j], Ages[1][j], Ages[2][j], f, Ages[1][j]*f/da);
+  }
+}
+
+double
+rnd_gauss (mean, sigma)
+double mean, sigma; 
+{
+
+  double range, x;
+
+  range = drand48();
+  x = rnd_integrate (*gaussian, range, mean, sigma);
+
+  return (x);
+
+}
+
+
+double 
+rnd_integrate (function, range, mean, sigma) 
+double (*function) ();
+double range, mean, sigma;
+{
+
+  double val, x, dx, dx1, dx2, dx3, df;
+
+  range += 0.0001;
+  val = 0;
+  dx = sigma / 10.0;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+
+  for (x = mean - 7*sigma; (val < range) && (x < mean + 7*sigma); x += dx)  {
+    df = (3.0*function(x    , mean, sigma) + 
+	  9.0*function(x+dx1, mean, sigma) +
+	  9.0*function(x+dx2, mean, sigma) + 
+	  3.0*function(x+dx3, mean, sigma)) * (dx1/8.0);
+    val += df;
+  }
+  return (x + dx / 2.0);
+}
+
+double 
+gaussian (x, mean, sigma) 
+double x, mean, sigma; 
+{
+
+  double f, X;
+
+  f = exp (-0.5 * SQ(x - mean) / SQ(sigma)) / sqrt(2 * M_PI * SQ(sigma));
+
+  return (f);
+
+}
+
Index: /tags/start/Ohana/src/misc/src/magtomass.c
===================================================================
--- /tags/start/Ohana/src/misc/src/magtomass.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/magtomass.c	(revision 12606)
@@ -0,0 +1,292 @@
+# include <ohana.h>
+extern double drand48();
+extern double rnd_gauss();
+extern double rnd_integrate ();
+extern double gaussian ();
+# define NEWWAY 1
+
+double gaussian();
+double rnd_gauss();
+double rnd_integrate();
+
+# define NGAUSS 2048
+double gaussint[NGAUSS];
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+
+  Header mass_h, age_h;
+  Matrix mass_i, age_i;
+  double UV0, V0, DV, DUV, ra, dec;
+  double U, V, dUV, dU, dV, mass, age, d;
+  double M, dM, Ms, M2, m, ldM, lMo, lAo, ldA, dlogM;
+  double v, uv, Av, eta, deta, Ngood;
+  double ***Masses, *maxmass, *minmass;
+  float *Mbuffer, *Abuffer;
+  int x, y, i, j, I, J, Ntry, dump, NMASS, N, NAGE, k, try;
+  int NX, NY;
+  char line[1024];
+  int col1, col2;
+  
+  dump = FALSE;
+  if (N = get_argument (argc, argv, "-dump")) {
+    remove_argument (N, &argc, argv);
+    dump = TRUE;
+  }
+
+  col1 = 8;
+  if (N = get_argument (argc, argv, "-col1")) {
+    remove_argument (N, &argc, argv);
+    col1 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  col2 = 12;
+  if (N = get_argument (argc, argv, "-col2")) {
+    remove_argument (N, &argc, argv);
+    col2 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  fprintf (stderr, "using mags in columns %d & %d\n", col1, col2);
+
+  gauss_init ();
+
+  lAo = 0.1;
+  ldA =  0.3;
+  NAGE = 10;
+  lMo = 0.0;
+  ldM =  0.05;
+  if (NEWWAY)
+    NMASS = 87;
+  else 
+    NMASS = 50;
+  if (N = get_argument (argc, argv, "-mass")) {
+    if (dump) {
+      fprintf (stderr, "-mass and -dump incompatible\n");
+      exit (0);
+    }
+    remove_argument (N, &argc, argv);
+    lMo = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    ldM = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    NMASS = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 6) {
+    fprintf (stderr, "USAGE: magtomass massfile agefile d Av Ntry\n");
+    exit (0);
+  }
+  d = atof (argv[3]);
+  Av = atof (argv[4]);
+  Ntry = atof (argv[5]);
+
+  fits_read_header (argv[1], &mass_h);
+  fits_read_matrix (argv[1], &mass_i);
+  fits_read_header (argv[2], &age_h);
+  fits_read_matrix (argv[2], &age_i); 
+
+  fits_scan (&mass_h, "RA_O",  "%lf", 1, &UV0);
+  fits_scan (&mass_h, "RA_X",  "%lf", 1, &DUV);
+  fits_scan (&mass_h, "DEC_O", "%lf", 1, &V0);
+  fits_scan (&mass_h, "DEC_Y", "%lf", 1, &DV);
+  Mbuffer = (float *)mass_i.buffer;
+  Abuffer = (float *)age_i.buffer;
+  NX = mass_h.Naxis[0];
+  NY = mass_h.Naxis[1];
+  
+  ALLOCATE (Masses, double **, NAGE);
+  for (i = 0; i < NAGE; i++) {
+    ALLOCATE (Masses[i], double *, NMASS);
+    for (j = 0; j < NMASS; j++) {
+      ALLOCATE (Masses[i][j], double, 3);
+      Masses[i][j][0] = 0.0;
+	Masses[i][j][1] = 0.0;
+    }
+  }
+
+  fprintf (stderr, "beginning main loop\n");
+  while (scan_line (stdin, line) != EOF) {
+    if (!stripwhite (line)) continue;
+    if (line[0] == '#') continue;
+    /* appropriate columns hardwired */
+    dparse (&ra, 1, line);
+    dparse (&dec, 2, line);
+    dparse (&V, col1, line);
+    dparse (&dV, (col1+1), line);
+    dparse (&U, col2, line);
+    dparse (&dU, (col2+1), line);
+    dUV = sqrt (dU*dU + dV*dV);
+    x = (U-V - UV0 - 0.7*Av) / DUV;
+    y = (V - d - V0 - Av) / DV;
+    if ((x > 0) && (x < mass_h.Naxis[0]) && (y > 0) && (y < mass_h.Naxis[1])) {
+      mass = Mbuffer[x + NX*y];
+      /*      mass = fits_get_matrix_value (&mass_i, x, y); */
+      if (mass > 0.0) {
+	age = Abuffer[x + NX*y];
+	fprintf (stdout, "%f %f %f %f %f %f\n", ra, dec, V, U-V, mass, age);
+      }
+    }
+  }
+}
+
+
+
+/*
+
+	**	age = fits_get_matrix_value (&age_i, x, y);  **
+	I = MAX (MIN ((log10(age) - lAo) / ldA, NAGE - 1), 0); 
+	if (NEWWAY) {
+	  J = MAX (MIN ((4.5 - sqrt(10.0/mass)) / ldM, NMASS - 1), 0);
+	} else {
+	  J = MAX (MIN ((log10(mass) - lMo) / ldM, NMASS - 1), 0); 
+	}
+	Ngood = 1.0;
+	for (k = 0; k < Ntry; k++) {
+	  v = rnd_gauss (V, dV);
+	  uv = rnd_gauss ((U-V), dUV);
+	  x = (uv - UV0 - 0.7*Av) / DUV;
+	  y = (v - d - V0 - Av) / DV;
+	  if ((x > 0) && (x < mass_h.Naxis[0]) && (y > 0) && (y < mass_h.Naxis[1])) {
+	    mass = Mbuffer[x + NX*y];
+	    **	    mass = fits_get_matrix_value (&mass_i, x, y); **
+	    if (mass > 0.0) {
+	      age = Abuffer[x + NX*y];
+	      ** age = fits_get_matrix_value (&age_i, x, y);  **
+	      i = MAX (MIN ((log10(age) - lAo) / ldA, NAGE - 1), 0);
+	      if (NEWWAY) {
+		j = MAX (MIN ((4.5 - sqrt(10.0/mass)) / ldM, NMASS - 1), 0);
+	      } else {
+		j = MAX (MIN ((log10(mass) - lMo) / ldM, NMASS - 1), 0); 
+	      }
+	      if ((i == I) && (j == J)) {
+		Ngood += 1.0;
+	      }
+	    }
+	  }
+	}
+	Masses[I][J][0] += (Ntry / Ngood);
+	Masses[I][J][1] += 1.0;
+      }
+    }
+  }
+
+  fprintf (stderr, "finding scatter per bin\n");
+  fprintf (stdout, "# measured IMF \n");
+  fprintf (stdout, "# distance modulus = %5.2, extinction (A_V) = %5.2f\n", d, Av);
+  fprintf (stdout, "# reference mass and age filess: %s, %s\n", argv[1], argv[2]);
+  fprintf (stdout, "# eta = N(logM, logM+dlogM) / dlogM \\sim ln(10.0) * M dN/dM)\n");
+  fprintf (stdout, "# i  Mass   N(mass)  eta   d_eta\n");
+  for (i = 0; i < NAGE; i++) {
+    for (j = 0; j < NMASS; j++) {
+      if (NEWWAY) {
+	mass = 10.0 / SQ(4.5 - ldM*(j+0.5));
+	dlogM = 2.0 * (log10(4.5 - ldM*j) - log10(4.5 - ldM*(j+1)));
+      } else {
+	mass = pow (10.0, (lMo + ldM*(j+0.5)));
+	dlogM = ldM;
+      }
+      eta  = Masses[i][j][0] / dlogM;
+      deta = (Masses[i][j][1] > 0) ? eta / sqrt(Masses[i][j][1]) : 0.0;
+      age  = pow (10.0, (ldA*i + lAo));
+      M = (Masses[i][j][1] > 0) ? Masses[i][j][0]/Masses[i][j][1] : 0;  ** average correction factor **
+      dM = (Masses[i][j][1] > 0) ? Masses[i][j][0]/sqrt(Masses[i][j][1]) : 0;  ** average correction factor **
+      fprintf (stdout, "%4d %4d %5.1f %5.1f %7.1f %7.1f %6.2f %4.0f\n", i, j, mass, age, eta, deta, M, Masses[i][j][1]);
+    }
+  }
+}
+
+*/
+
+double
+rnd_gauss (mean, sigma)
+double mean, sigma; 
+{
+
+  int i;
+  double y;
+
+  y = drand48();
+  i = NGAUSS*y;
+  y = gaussint[i]*sigma + mean;
+
+  return (y);
+
+}
+
+
+gauss_init ()
+{
+
+  int i;
+  long A, B;
+  double val, x, dx, dx1, dx2, dx3, df;
+  double mean, sigma;
+
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+
+  val = 0;
+  dx = 0.001;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+  mean = 0.0;
+  sigma = 1.0;
+
+  for (i = 0, x = -7.0; (i < NGAUSS) && (x < 7.0); x += dx)  {
+    df = (3.0*gaussian(x    , mean, sigma) + 
+	  9.0*gaussian(x+dx1, mean, sigma) +
+	  9.0*gaussian(x+dx2, mean, sigma) + 
+	  3.0*gaussian(x+dx3, mean, sigma)) * (dx1/8.0);
+    val += df;
+    if (val > (i / (double) NGAUSS)) {
+      gaussint[i] = x + dx / 2.0;
+      i++;
+    }
+  }
+  return (x + dx / 2.0);
+}
+
+double 
+rnd_integrate (function, range, mean, sigma) 
+double (*function) ();
+double range, mean, sigma;
+{
+
+  double val, x, dx, dx1, dx2, dx3, df;
+
+  range += 0.0001;
+  val = 0;
+  dx = sigma / 100.0;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+
+  for (x = mean - 7*sigma; (val < range) && (x < mean + 7*sigma); x += dx)  {
+    df = (3.0*function(x    , mean, sigma) + 
+	  9.0*function(x+dx1, mean, sigma) +
+	  9.0*function(x+dx2, mean, sigma) + 
+	  3.0*function(x+dx3, mean, sigma)) * (dx1/8.0);
+    val += df;
+  }
+  return (x + dx / 2.0);
+}
+
+double 
+gaussian (x, mean, sigma) 
+double x, mean, sigma; 
+{
+
+  double f, X;
+
+  f = exp (-0.5 * SQ(x - mean) / SQ(sigma)) / sqrt(2 * M_PI * SQ(sigma));
+
+  return (f);
+
+}
+
Index: /tags/start/Ohana/src/misc/src/medianfilter.c
===================================================================
--- /tags/start/Ohana/src/misc/src/medianfilter.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/medianfilter.c	(revision 12606)
@@ -0,0 +1,146 @@
+# include <ohana.h>
+# define D_NFILES 100
+
+void fsort (float *value, int N);
+
+int main (int argc, char **argv) {
+
+  int i, j, k, n, Npixels, Npixin, Npixrd, Npixlast, N;
+  int Npass, NFILES, Nfiles;
+
+  char **filename;
+  Header head, *tmphead;
+  Matrix out,  *tmpmatr;
+  float *list, *v, *O;
+  float fmin, fmax, Nval, sum;
+
+  FT_UNSIGN_MODE = FALSE;
+  if ((N = get_argument (argc, argv, "-unsign"))) {
+    remove_argument (N, &argc, argv);
+    FT_UNSIGN_MODE = TRUE;
+  }
+
+  if (argc < 4) {
+    fprintf (stderr, "USAGE: minmaxfilter outfile fmin fmax\n");
+    exit (0);
+  }
+  fmin = atof (argv[2]); 
+  fmax = atof (argv[3]); 
+
+  /* read in the filenames */
+  NFILES = D_NFILES;
+  ALLOCATE (filename, char *, NFILES);
+  ALLOCATE (filename[0], char, 1024);
+  for (i = 0; fscanf (stdin, "%s", filename[i]) != EOF; i++) {
+    if (i == NFILES - 1) {
+      NFILES += D_NFILES;
+      REALLOCATE (filename, char *, NFILES);
+    }
+    ALLOCATE (filename[i+1], char, 1024);
+  }
+  Nfiles = i;
+  REALLOCATE (filename, char *, Nfiles);
+
+  /* load a header, setup output header, matrix */
+  fits_read_header (filename[0], &head);
+  fits_create_matrix (&head, &out);
+  fits_convert_format (&head, &out, -32, 1.0, 0.0, FALSE);
+
+  /* find size of temporary images */
+  Npixels = head.Naxis[0]*head.Naxis[1];
+  Npixin = Npixels / Nfiles;
+  Npixlast = Npixels - Npixin*Nfiles;
+  if (Npixlast == 0) {
+    Npass = Nfiles;
+    Npixlast = Npixin;
+    fprintf (stderr, "operating on %d pixels per pass\n", Npixin);
+  } else {
+    Npass = Nfiles + 1;
+    fprintf (stderr, "operating on %d pixels per pass, %d in last\n", Npixin, Npixlast);
+  }
+  
+  ALLOCATE (tmphead, Header, Nfiles);
+  ALLOCATE (tmpmatr, Matrix, Nfiles);
+  ALLOCATE (list, float, Nfiles);
+  Nval = 0;
+  for (k = fmin*Nfiles; k < fmax*Nfiles; k++) {
+    Nval += 1.0;
+  }
+
+  O = (float *) out.buffer;
+  for (n = 0; n < Npass; n++) {
+    fprintf (stderr, "pass %d\n", n);
+    Npixrd = (n == Npass - 1) ? Npixlast : Npixin;
+    for (i = 0; i < Nfiles; i++) {
+      fprintf (stderr, ".");
+      if (!fits_read_header  (filename[i], &tmphead[i])) {
+	fprintf (stderr, "trouble reading file %s\n", filename[i]);
+	exit (1);
+      }
+      fits_read_portion (filename[i], &tmpmatr[i], n*Npixin, Npixrd);
+      tmphead[i].Naxis[0] = 1;
+      tmphead[i].Naxis[1] = Npixrd;
+      fits_convert_format (&tmphead[i], &tmpmatr[i], -32, 1.0, 0.0, FALSE);
+    }
+    
+    fprintf (stderr, "starting sorts\n");
+    for (j = 0; j < Npixrd; j++, O++) {
+      for (k = 0; k < Nfiles; k++) {
+	v = (float *)tmpmatr[k].buffer;
+	list[k] = v[j];
+      }
+      fsort (list, Nfiles);
+      sum = 0;
+      for (k = fmin*Nfiles; k < fmax*Nfiles; k++) {
+	sum += list[k];
+      }
+      *O = (sum / Nval);
+    }
+
+    for (i = 0; i < Nfiles; i++) {
+      fprintf (stderr, ",");
+      fits_free_header (&tmphead[i]);
+      fits_free_matrix (&tmpmatr[i]);
+    }
+    
+  }
+
+  fits_write_header (argv[1], &head);
+  fits_write_matrix (argv[1], &out);
+
+  return (0);
+
+}
+
+void fsort (float *value, int N) {
+
+  int l,j,ir,i;
+  float temp;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      temp = value[--l];
+    }
+    else {
+      temp = value[ir];
+      value[ir] = value[0];
+      if (--ir == 0) {
+	value[0] = temp;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && value[j] < value[j+1]) ++j;
+      if (temp < value[j]) {
+	value[i]=value[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    value[i] = temp;
+  }
+}
Index: /tags/start/Ohana/src/misc/src/mefhead.c
===================================================================
--- /tags/start/Ohana/src/misc/src/mefhead.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/mefhead.c	(revision 12606)
@@ -0,0 +1,97 @@
+# include <ohana.h>
+
+int main (int argc, char **argv) {
+
+  struct stat filestat;
+  int NEXTEND, Nextend, Nmatrix, status;
+  Header header;
+  FILE *f, *g;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: mefhead (input) (output)\n");
+    exit (2);
+  }
+
+  /* exit if file exists */
+  status = stat (argv[2], &filestat);
+  if (status != -1) {
+    fprintf (stderr, "error: output file exists\n");
+    exit (1);
+  } 
+  
+  /* open stream for input */
+  g = fopen (argv[1], "r");
+  if (g == (FILE *) NULL) {
+    fprintf (stderr, "error: can't open input file\n");
+    exit (1);
+  } 
+
+  /* open stream for output */
+  f = fopen (argv[2], "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "error: can't create output file\n");
+    exit (1);
+  } 
+
+  /* read PHU */
+  status = fits_fread_header (g, &header);
+  if (!status) {
+    fprintf (stderr, "error: can't read primary header unit\n");
+    exit (1);
+  }
+  /* skip matrix */
+  Nmatrix = fits_matrix_size (&header);
+  fseek (g, Nmatrix, SEEK_CUR);
+
+  /* write PHU */
+  fits_modify (&header, "NAXIS", "%d", 1, 0);
+  status = fits_fwrite_header (f, &header);
+  if (!status) {
+    fprintf (stderr, "error: can't write primary header unit\n");
+    exit (1);
+  }
+
+  /* check if NEXTEND is accurate */
+  fits_scan (&header, "NEXTEND", "%d", 1, &NEXTEND);
+
+  Nextend = 0;
+  while (1) {
+    
+    /* read header */
+    status = fits_fread_header (g, &header);
+    if (!status) break;
+
+    /* skip matrix */
+    Nmatrix = fits_matrix_size (&header);
+    fseek (g, Nmatrix, SEEK_CUR);
+    
+    /* write header */
+    fits_modify (&header, "NAXIS", "%d", 1, 0);
+    status = fits_fwrite_header (f, &header);
+    if (!status) {
+      fprintf (stderr, "error: can't write header unit %d\n", Nextend);
+      exit (1);
+    }
+    Nextend ++;
+    fits_free_header (&header);
+  }
+
+  if (Nextend != NEXTEND) { 
+    fprintf (stderr, "warning: mismatch in NEXTEND\n");
+  }
+
+  fclose (f);
+  fclose (g);
+  exit (0);
+
+}
+
+
+
+/* mefhead (input) (output) 
+   convert (input) MEF image file to (output) MEF header file:
+   read all headers
+   convert all lines NAXIS=2 to NAXIS=0 
+   write only headers
+
+*/
Index: /tags/start/Ohana/src/misc/src/misc.c
===================================================================
--- /tags/start/Ohana/src/misc/src/misc.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/misc.c	(revision 12606)
@@ -0,0 +1,471 @@
+# include <ohana.h>
+
+static double tz = 0.0;
+void set_timezone (double dt) {
+  tz = dt;
+}
+
+/***** convert [-]00:00:00 to 0.0000 ****/
+int dms_to_ddd (double *Value, char *string) {
+  
+  int valid, neg, status;
+  double tmp, value;
+  char *p1, *p2, *px;
+
+  valid = FALSE; 
+  neg = FALSE;
+  stripwhite (string);
+  p1 = string;
+  px = string + strlen(string);
+
+  if (string[0] == '-') { 
+    valid = TRUE; 
+    neg = TRUE;
+    p1 = &string[1];
+  }
+  if (string[0] == '+') { 
+    valid = TRUE; 
+    neg = FALSE;
+    p1 = &string[1];
+  }
+  if (isdigit(string[0])) { 
+    valid = TRUE;
+    p1 = &string[0];
+  }
+  if (!valid) { return (FALSE); }
+
+  status = 1;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) return (FALSE); /* entry not a number: +fred */
+  value = tmp;
+  if (p2 == px) goto escape;    /* entry only number: +1.0 */ 
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:fred */
+  status = 2;
+  value += tmp / 60.0;
+  if (p2 == px) goto escape;    /* entry only number: +1:1 */
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:1:fred */
+  value += tmp / 3600.0;
+
+ escape:
+  if (neg) {
+    value *= -1;
+  }
+  *Value = value;
+
+  return (status);
+}
+
+/**********/
+int str_to_radec (double *ra, double *dec, char *str1, char *str2) {
+
+  double Ra, Dec;
+
+  *ra = *dec = 0;
+  switch (dms_to_ddd (&Ra, str1)) {
+  case 0:
+    fprintf (stderr, "syntax error in RA\n");
+    return (FALSE);
+  case 1:
+    break;
+  case 2:
+    Ra = Ra * 15;
+    break;
+  }
+  switch (dms_to_ddd (&Dec, str2)) {
+  case 0:
+    fprintf (stderr, "syntax error in DEC\n");
+    return (FALSE);
+  case 1:
+  case 2:
+    break;
+  }
+  *ra = Ra;
+  *dec = Dec;
+  return (TRUE);
+}
+
+# define FORMAT_DAYS    1
+# define FORMAT_HOURS   2
+# define FORMAT_MINUTES 3
+# define FORMAT_SECONDS 4
+# define FORMAT_JD      5
+# define FORMAT_DATE    6
+
+/**********/
+int chk_time (char *line) {
+
+  char *p1, *p2;
+  double tmp;
+  int mode;
+
+  p1 = line;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1 + strlen (p1) - 1) {
+    if (*p2 == 'd') {
+      mode = FORMAT_DAYS;
+    }
+    if (*p2 == 'h') {
+      mode = FORMAT_HOURS;
+    }
+    if (*p2 == 'm') {
+      mode = FORMAT_MINUTES;
+    }
+    if (*p2 == 's') {
+      mode = FORMAT_SECONDS;
+    }
+    if (*p2 == 'j') {
+      mode = FORMAT_JD;
+    }
+  } else { 
+    mode = FORMAT_DATE;
+  }
+  return (mode);
+}
+
+/**********/
+int str_to_time (char *line, unsigned long *second) {
+  
+  struct timeval now;
+  double jd;
+
+  if (!strcasecmp (line, "NOW")) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    *second = now.tv_sec;
+    return (TRUE);
+  }
+    
+  if (!strcasecmp (line, "TODAY")) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    *second = 86400 * ((int)(now.tv_sec / 86400));
+    return (TRUE);
+  }
+    
+  switch (chk_time (line)) {
+  case 0:
+    return (FALSE);
+  case FORMAT_DAYS:
+    *second = strtod (line, 0) * 86400.0;
+    return (TRUE);
+  case FORMAT_HOURS:
+    *second = strtod (line, 0) * 3600.0;
+    return (TRUE);
+  case FORMAT_MINUTES:
+    *second = strtod (line, 0) * 60.0;
+    return (TRUE);
+  case FORMAT_SECONDS:
+    *second = strtod (line, 0);
+    return (TRUE);
+  case FORMAT_JD:
+    jd = strtod (line, 0);
+    *second = jd_to_sec (jd);
+    return (TRUE);
+  case FORMAT_DATE:
+    *second = date_to_sec (line);
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+/**********/
+int str_to_dtime (char *line, double *second) {
+  
+  switch (chk_time (line)) {
+  case 0:
+  case FORMAT_JD:
+  case FORMAT_DATE:
+    return (FALSE);
+  case FORMAT_DAYS:
+    *second = strtod (line, 0) * 86400.0;
+    return (TRUE);
+  case FORMAT_HOURS:
+    *second = strtod (line, 0) * 3600.0;
+    return (TRUE);
+  case FORMAT_MINUTES:
+    *second = strtod (line, 0) * 60.0;
+    return (TRUE);
+  case FORMAT_SECONDS:
+    *second = strtod (line, 0);
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+/**********/
+double sec_to_jd (unsigned long second) {
+
+  double jd;
+  
+  jd = second/86400.0 + 2440587.5;
+  return (jd);
+}
+
+/**********/
+unsigned long int jd_to_sec (double jd) {
+
+  unsigned long int second;
+
+  second = (jd - 2440587.5)*86400;
+  return (second);
+}
+
+/**********/
+char *sec_to_date (unsigned long second) {
+  
+  struct tm *gmt;
+  char *line;
+  
+  ALLOCATE (line, char, 64);
+  second -= 3600*tz;
+  gmt   = gmtime (&second);
+  sprintf (line, "%4d/%02d/%02d,%02d:%02d:%02d", 1900+gmt[0].tm_year, gmt[0].tm_mon+1, gmt[0].tm_mday, gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+  return (line);
+
+}
+
+/***** date in format yyyy/mm/dd,hh:mm:ss *****/
+unsigned long date_to_sec (char *date) {
+  
+  unsigned long second;
+  double tmp, jd;
+  struct tm now;
+  char *p1, *p2, *px;
+  
+  p1 = date;
+  px = date + strlen(date);
+  bzero (&now, sizeof(now));
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_year = tmp;
+  if (now.tm_year > 1000) now.tm_year -= 1900;
+  if (now.tm_year <   50) now.tm_year += 100;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mon = tmp - 1; /* mon runs from 0 - 11 */
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mday = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  p1 = p2 + 1;
+  now.tm_hour = tmp;
+  if (p2 == px) goto escape;  
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_min = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_sec = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+ escape:
+  jd = now.tm_mday - 32075 + (int)(1461*(1900 + now.tm_year + 4800 + (int)(((now.tm_mon+1)-14)/12))/4)
+    + (int)(367*((now.tm_mon+1) - 2 - (int)(((now.tm_mon+1) - 14)/12)*12)/12)
+    - (int)(3*(int)((1900 + now.tm_year + 4900 + (int)(((now.tm_mon+1) - 14)/12))/100)/4) - 0.5;
+  
+  second = (jd - 2440587.5)*86400 + 3600.0*now.tm_hour + now.tm_min*60.0 + now.tm_sec;
+
+  second += 3600*tz;
+
+  return (second);
+}
+
+
+/* times may be in forms as:
+   20040200450s (N seconds since 1970.0)
+   2440900.232j (julian date)
+   99/02/23,03:22:18 (date string)
+   (separators may be anything except space, +, -)
+   99:02:15:12:23:30
+   99:02:15:12h23m30s
+   */
+
+
+/* fseek with timeout - 0.5 sec */
+int Fseek (FILE *f, long offset, int whence) {
+
+  int status, k;
+
+  status = fseek (f, offset, whence);
+  if (status == -1) {
+    for (k = 0; (k < 10) && ((status = fseek (f, 0, SEEK_SET)) == -1); k++) usleep (50000);
+    if (status == -1) {
+      return (0);
+    }
+  }
+  return (1);
+}
+
+/* return values:
+   0 - no trange arguments
+   1 - arguments ok
+   2 - arguments bad
+*/
+int get_trange_arguments (int *argc, char **argv, unsigned long **Tstart, unsigned long **Tstop, int *ntimes) {
+
+  int Na, N, Ntimes;
+  double trange;
+  unsigned long tmp, *tstart, *tstop;
+
+  /* allocate space for returned lists */
+  Ntimes = 10;
+  ALLOCATE (tstart, unsigned long, Ntimes);
+  ALLOCATE (tstop,  unsigned long, Ntimes);
+
+  for (N = 0; ; N++) {
+
+    /* find next -trange arg */
+    Na = get_argument (*argc, argv, "-trange");
+    if (Na == 0) {
+      *ntimes = N;
+      *Tstart = tstart;
+      *Tstop  = tstop;
+      return (TRUE);
+    }
+    remove_argument (Na, argc, argv);
+    
+    /* tstart */
+    if (!str_to_time (argv[Na], &tstart[N])) { 
+      return (FALSE);
+    }
+
+    /* interpret second value */
+    remove_argument (Na, argc, argv);
+    if (str_to_dtime (argv[Na], &trange)) { 
+      if (trange < 0) {
+	tstop[N]  = tstart[N];
+	tstart[N] = tstop[N] + trange;
+      } else {
+	tstop[N]  = tstart[N] + trange;
+      }
+      remove_argument (Na, argc, argv);
+      goto goodvalue;
+    }
+    if (str_to_time (argv[Na], &tstop[N])) { 
+      if (tstart[N] > tstop[N]) {
+	tmp     = tstart[N];
+	tstart[N] = tstop[N];
+	tstop[N]  = tmp;
+      }
+      remove_argument (Na, argc, argv);
+      goto goodvalue;
+    }
+    return (FALSE); /* syntax error in 2nd value */
+
+  goodvalue:
+    if (N == Ntimes - 1) {
+      Ntimes += 10;
+      REALLOCATE (tstart, unsigned long, Ntimes);
+      REALLOCATE (tstop,  unsigned long, Ntimes);
+    }
+  }
+}
+  
+void make_backup (char *filename) {
+
+  int status, cmode;
+  struct stat filestat;
+  char line [256];
+
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, make backup copy */
+    sprintf (line, "cp %s %s~", filename, filename);
+    status = system (line);
+    if (status) {
+      fprintf (stderr, "ERROR: unable to create %s~, exiting\n", filename);
+      exit (0);
+    }
+    cmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    sprintf (line, "%s~", filename);
+    chmod (line, cmode);
+  }
+}
+
+
+int get_filter_arguments (int *argc, char **argv, int **Filt, int *Nfilt) {
+
+  int i, N, Na, NF;
+  int *filt;
+
+  /* allocate space for returned lists */
+  NF = 10;
+  ALLOCATE (filt, int, NF);
+
+  for (N = 0; ; N++) {
+
+    /* find next -trange arg */
+    Na = get_argument (*argc, argv, "-filter");
+    if (Na == 0) {
+      *Nfilt = N;
+      *Filt = filt;
+      return (TRUE);
+    }
+    if (Na > *argc - 2) return (FALSE); /* -filter F */
+    remove_argument (Na, argc, argv);
+    
+    for (i = 0; i < strlen (argv[Na]); i++) { if (isspace (argv[Na][i])) argv[Na][i] = '.'; }
+    for (i = 0; i < NFILTER; i++) {
+      if (!strcasecmp (argv[Na], filtername[i])) {
+	filt[N] = filternum[i];
+      }
+    }
+    if (filt[N] == FILTER_NONE) return (FALSE);
+    remove_argument (Na, argc, argv);
+
+    if (N == NF - 1) {
+      NF += 10;
+      REALLOCATE (filt, int, NF);
+    }
+  }
+}
+  
+   
+int get_version (int argc, char **argv, char *version) {
+
+  int N;
+  char *p, *q, *line;
+
+  if (get_argument (argc, argv, "-version")) {
+
+    N = strlen (version) + 2;
+    line = (char *) malloc (N);
+    bzero (line, N);
+
+    p = strstr (version, "$Revision: ");
+    if (p != (char *) NULL) 
+      p += strlen ("$Revision: ");
+    else
+      p = version;
+
+    q = strstr (p, "$");
+    if (q != (char *) NULL) 
+      N = q - p; 
+    else
+      N = strlen (p);
+
+    strncpy (line, p, N);
+
+    fprintf (stderr, "%s\n", line);
+    exit (2);
+  }
+}  
Index: /tags/start/Ohana/src/misc/src/mkgauss.c
===================================================================
--- /tags/start/Ohana/src/misc/src/mkgauss.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/mkgauss.c	(revision 12606)
@@ -0,0 +1,88 @@
+# include <ohana.h>
+
+void   gauss_init ();
+double gaussian (double x, double mean, double sigma);
+double rnd_gauss (double mean, double sigma);
+
+/* NGAUSS defines the resolution of the distribution */
+# define NGAUSS 2048
+static double gaussint[NGAUSS];
+
+int main (int argc, char **argv) {
+
+  int i, Npts;
+  double mean, sigma, f;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: mkgauss (mean) (sigma) (npts)\n");
+    exit (2);
+  }
+
+  mean = atof (argv[1]);
+  sigma = atof (argv[2]);
+  Npts = atoi (argv[3]);
+
+  gauss_init ();
+
+  for (i = 0; i < Npts; i++) {
+    f = rnd_gauss (mean, sigma);
+    fprintf (stdout, "%f\n", f);
+  }
+
+  exit (0);
+}
+
+void gauss_init () {
+
+  int i;
+  long A, B;
+  double val, x, dx, dx1, dx2, dx3, df;
+  double mean, sigma;
+
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+
+  val = 0;
+  dx = 0.001;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+  mean = 0.0;
+  sigma = 1.0;
+
+  for (i = 0, x = -7.0; (i < NGAUSS) && (x < 7.0); x += dx)  {
+    df = (3.0*gaussian(x    , 0.0, 1.0) + 
+	  9.0*gaussian(x+dx1, 0.0, 1.0) +
+	  9.0*gaussian(x+dx2, 0.0, 1.0) + 
+	  3.0*gaussian(x+dx3, 0.0, 1.0)) * (dx1/8.0);
+    val += df;
+    if (val > (i / (double) NGAUSS)) {
+      gaussint[i] = x + dx / 2.0;
+      i++;
+    }
+  }
+  return;
+}
+
+double gaussian (double x, double mean, double sigma) {
+  double f;
+
+  f = exp (-0.5 * SQ(x - mean) / SQ(sigma)) / sqrt(2 * M_PI * SQ(sigma));
+  return (f);
+}
+
+double rnd_gauss (double mean, double sigma) {
+
+  int i;
+  double y;
+
+  i = 0;
+  while ((i == 0) || (i == NGAUSS - 1)) {
+    y = drand48();
+    i = MIN (NGAUSS - 1, MAX (0, NGAUSS*y));
+  }
+  y = gaussint[i]*sigma + mean;
+
+  return (y);
+}
Index: /tags/start/Ohana/src/misc/src/mknames.c
===================================================================
--- /tags/start/Ohana/src/misc/src/mknames.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/mknames.c	(revision 12606)
@@ -0,0 +1,66 @@
+# include "ohana.h"
+extern double drand48();
+
+# define NFILTER 5
+static char filtlist[NFILTER][2] = {"B", "V", "R", "I", "Z"};
+
+int main (int argc, char **argv) {
+ 
+  FILE *f;
+  int j, rnd;
+  int ccd, state;
+  char type[64], filter[64], name[64];
+  struct timeval now;
+  struct tm *gmt;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: mknames (fifo)\n");
+    exit (1);
+  }
+
+  /* lock fifo */
+  f = fsetlockfile (argv[1], 60.0, LCK_XCLD, &state);
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open fifo file\n");
+    fclearlockfile (argv[1], f, LCK_XCLD, &state);
+    exit (1);
+  }
+
+  gettimeofday (&now, (void *) NULL);
+  gmt = gmtime (&now.tv_sec);
+  srand48(now.tv_usec);
+  rnd = 1000*drand48();
+  sprintf (name, "%04d.%02d.%02d.%03d", gmt[0].tm_year + 1900, gmt[0].tm_mon + 1, gmt[0].tm_mday, rnd);
+
+  for (ccd = 0; ccd < 12; ccd++) {
+    strcpy (filter, "X");
+    strcpy (type, "bias");
+    fprintf (f, "%02d %s %s %s\n", ccd, type, filter, name);
+    strcpy (type, "dark");
+    fprintf (f, "%02d %s %s %s\n", ccd, type, filter, name);
+    strcpy (type, "flat");
+    for (j = 0; j < NFILTER; j++) {
+      strcpy (filter, filtlist[j]);
+      fprintf (f, "%02d %s %s %s\n", ccd, type, filter, name);
+    }
+  }
+  fclearlockfile (argv[1], f, LCK_XCLD, &state);
+  exit (0);
+}
+
+  /* 
+     
+     we need to generate a list of entries for 'elixir flips'
+     the entries look like:
+
+     (ccd) (type) (filter) (tend) (nameref)
+
+     (ccd)  - ranges from 00 to 11 
+     (type) - values are bias, dark, flat, ?
+     (filter) - for bias & dark = X
+                for flat = B,V,R,I,Z (Hon?, Hoff?)
+     (tend) = 'NOW' (probably don't need to generate this!)
+     (nameref) = SSSSSS (some string, needs to be unique... based on date?)
+
+  */
+		
Index: /tags/start/Ohana/src/misc/src/mktemp.c
===================================================================
--- /tags/start/Ohana/src/misc/src/mktemp.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/mktemp.c	(revision 12606)
@@ -0,0 +1,17 @@
+# include <stdio.h>
+# include <stdlib.h>
+
+int main (int argc, char **argv) {
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: %s (template)\n", argv[0]);
+    exit (1);
+  }
+
+  if (mkstemp (argv[1]) == -1) exit (1);
+
+  fprintf (stdout, "%s\n", argv[1]);
+
+  exit (0);
+}
+ 
Index: /tags/start/Ohana/src/misc/src/mosastro.c
===================================================================
--- /tags/start/Ohana/src/misc/src/mosastro.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/mosastro.c	(revision 12606)
@@ -0,0 +1,505 @@
+# include <ohana.h>
+# include <loneos.h>
+# define NCCD 12
+
+static double **alpha, **talpha;
+static double **beta, **tbeta;
+static double *partry, *dyda;
+static double ochisq, lambda;
+
+double *x, *y, *p, *q;
+double Px, Py, PS;
+int PSfixed;
+
+double chipfunc (int idx, double *P, double *Q, double *par, int Npar);
+double chipfit (int idx, double *par, int Npar, double *dyda);
+double mrqcof (int *index, int Npts, double *par, int Npar, double **ta, double **tb, double (funcs)(int, double *, int, double *));
+double mrqmin (int *index, int Npts, double *par, int Npar,                           double (funcs)(int, double *, int, double *));
+int mrqinit (int *index, int Npts, double *par, int Npar,                             double (funcs)(int, double *, int, double *));
+int mrqfree (int Npar);
+int gaussj (double **a, int n, double **b, int m);
+int fit (double *X, double *Y, int N, double *A, double *B);
+
+main (int argc, char **argv) {
+
+  int i, j, n;
+  int Npar, Npts, NPTS, done;
+  int *CCD, *idx;
+  double Ro, Do, chisq, nchisq, gchisq, xf, yf;
+  double Sx, Sy, Lo, Mo, Lp, Mp, dr, DSx, DSy;
+  double *R, *D, *X, *Y, *L, *M, *tmp;
+  double *par;
+  FILE *f;
+  Coords coords;
+  double *Xo, *Yo, *To;
+
+  /* load in RA, DEC, X, Y, CCD vectors */
+  if ((argc != 2) && (argc != 7)) {
+    fprintf (stderr, "USAGE: mosastro (file.mos) [Ro Do ps DSx DSy]\n");
+    exit (2);
+  }
+  PS = DSx = DSy = 0.0;
+  PSfixed = FALSE;
+  if (argc == 7) {
+    PSfixed = TRUE;
+    Ro = atof (argv[2]);
+    Do = atof (argv[3]);
+    PS = atof (argv[4]);
+    DSx = atof (argv[5]) / 1000000.0;
+    DSy = atof (argv[6]) / 1e6;
+  }
+  
+  ALLOCATE (Xo, double, NCCD);
+  ALLOCATE (Yo, double, NCCD);
+  ALLOCATE (To, double, NCCD);
+
+  Npar = 4;
+  if (PSfixed) Npar = 3;
+  ALLOCATE (par, double, Npar);
+
+  NPTS = 100;
+  ALLOCATE (R, double, NPTS);
+  ALLOCATE (D, double, NPTS);
+  ALLOCATE (X, double, NPTS);
+  ALLOCATE (Y, double, NPTS);
+  ALLOCATE (CCD, int, NPTS);
+
+  f = fopen (argv[1], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open file %s\n", argv[1]);
+    exit (1);
+  }
+
+  for (i = 0; fscanf (f, "%lf %lf %lf %lf %d", &R[i], &D[i], &X[i], &Y[i], &CCD[i]) != EOF; i++) {
+    if (i == NPTS - 1) {
+      NPTS += 100;
+      REALLOCATE (R, double, NPTS);
+      REALLOCATE (D, double, NPTS);
+      REALLOCATE (X, double, NPTS);
+      REALLOCATE (Y, double, NPTS);
+      REALLOCATE (CCD, int, NPTS);
+    }
+  }
+  NPTS = i;
+
+  /* find median of RA and DEC for field center */
+  if (!PSfixed) {
+    ALLOCATE (tmp, double, NPTS);
+    memcpy (tmp, R, NPTS*sizeof(double));
+    sort (tmp, NPTS);
+    Ro = tmp[(int)(0.5*NPTS)];
+    memcpy (tmp, D, NPTS*sizeof(double));
+    sort (tmp, NPTS);
+    Do = tmp[(int)(0.5*NPTS)];
+  }
+
+  /* basic coords */
+  strcpy (coords.ctype, "RA---TAN");
+  coords.cdelt1 = coords.cdelt2 = 1.0 / 3600.0;
+  coords.pc1_1  = 1.0;
+  coords.pc2_2  = -1.0;
+  coords.pc1_2  = coords.pc2_1 = 0.0;
+  coords.crval1 = Ro;
+  coords.crval2 = Do;
+  coords.crpix1 = coords.crpix2 = 0;
+  
+  /* RA, DEC -> L, M: */
+  /* only free parameters are Ro, Do */
+  ALLOCATE (L, double, NPTS);
+  ALLOCATE (M, double, NPTS);
+
+  for (i = 0; i < NPTS; i++) {
+    RD_to_XY (&Lp, &Mp, R[i], D[i], &coords);
+    dr = hypot (Lp, Mp);
+    L[i] = Lp * (1 + DSx*dr);
+    M[i] = Mp * (1 + DSy*dr);
+  }
+
+  ALLOCATE (x, double, NPTS);
+  ALLOCATE (y, double, NPTS);
+  ALLOCATE (p, double, NPTS);
+  ALLOCATE (q, double, NPTS);
+  ALLOCATE (idx, int, NPTS);
+
+  gchisq = 0;
+  for (i = 0; i < NCCD; i++) {
+    n = 0;
+    for (j = 0; j < NPTS; j++) {
+      if (CCD[j] == i) {
+	x[n] = X[j];
+	y[n] = Y[j];
+	p[n] = L[j];
+	q[n] = M[j];
+	idx[n] = n;
+	n ++;
+      }
+    }
+    Npts = n;
+
+    /* fit p = ax + b, q = ay + b */
+    fit (x, p, Npts, &Sx, &Lo);
+    fit (y, q, Npts, &Sy, &Mo);
+
+    /* initial guesses for par[0], par[1], par[2], par[3] */
+    par[0] = Lo;
+    par[1] = Mo;
+    par[2] = 0.0;
+    if (!PSfixed) 
+      par[3] = 0.5*fabs (Sx) + 0.5*fabs(Sy);
+
+    Px = SIGN (Sx);
+    Py = SIGN (Sy);
+    /* fprintf (stderr, "%2d: %7.1f  %7.1f  %5.3f  %6.2f\n", i, par[0], par[1], par[2], par[3]); */
+
+    chisq = mrqinit (idx, Npts, par, Npar, chipfit);
+    
+    done = FALSE;
+    for (j = 0; (j < 20) && !done; j++) {
+      nchisq = mrqmin (idx, Npts, par, Npar, chipfit);
+      /* fprintf (stderr, "%7.1f: %7.1f  %7.1f  %5.3f  %6.2f\n", nchisq, par[0], par[1], par[2], par[3]); */
+      /* if (chisq - nchisq < 0.1) done = TRUE; */
+      if (nchisq > 0) chisq = nchisq;
+    }  
+    Xo[i] = par[0];
+    Yo[i] = par[1];
+    To[i] = par[2];
+    gchisq += chisq;
+    if (!PSfixed) PS += par[3];
+
+    /*
+    if (!PSfixed) 
+      fprintf (stderr, "%2d: %7.1f  %7.1f  %6.2f  %7.5f\n", i, par[0], par[1], par[2], par[3]); 
+    else 
+      fprintf (stderr, "%2d: %7.1f  %7.1f  %6.2f  %7.5f\n", i, par[0], par[1], par[2], PS); 
+    */
+
+    for (j = 0; j < Npts; j++) {
+      chipfunc (j, &xf, &yf, par, Npar);
+      n = idx[j];
+      fprintf (stdout, "%f %f  %f %f  %f %f\n", x[n], y[n], p[n], q[n], xf, yf);
+    }
+
+  }
+  if (PSfixed) {
+    fprintf (stderr, "%f   %f  %f  %f  %f %f\n", gchisq, Ro, Do, PS, 1e6*DSx, 1e6*DSy);
+  } else {
+    fprintf (stderr, "%f   %f  %f  %f  %f %f\n", gchisq, Ro, Do, PS / NCCD, 1e6*DSx, 1e6*DSy);
+  }
+  exit (0);
+}
+
+double mrqcof (int *index, int Npts, double *par, int Npar, double **ta, double **tb, 
+	      double (funcs)(int, double *, int, double *)) {
+
+  int k, j, i;
+  double dchi, wt, chisq;
+
+  for (j = 0; j < Npar; j++) {
+    for (k = 0; k <= j; k++) ta[j][k] = 0.0;
+    tb[j][0] = 0.0;
+  }
+
+  chisq = 0.0;
+  for (i = 0; i < Npts; i++) {
+
+    dchi = funcs (index[i], par, Npar, dyda);
+    chisq += dchi;
+
+    for (j = 0; j < Npar; j++) {
+      wt = dyda[j];
+      for (k = 0; k <= j; k++) ta[j][k] += wt * dyda[k];
+      tb[j][0] += wt * dchi;
+    }
+  }
+
+  for (j = 1; j < Npar; j++)
+    for (k = 0; k < j; k++) 
+      ta[k][j] = ta[j][k];
+
+  return (chisq);
+
+}
+
+double mrqmin (int *index, int Npts, 
+	      double *par, int Npar, 
+	      double (funcs)(int, double *, int, double *)) {
+
+  int i, j, k;
+  double chisq;
+
+  /* set up test matrixes for this run */
+  for (j = 0; j < Npar; j++) {
+    for (k = 0; k < Npar; k++) talpha[j][k] = alpha[j][k];
+    talpha[j][j] = alpha[j][j] * (1.0 + lambda);
+    tbeta[j][0] = beta[j][0];
+  }
+
+  gaussj (talpha, Npar, tbeta, 1);
+
+  /* if we keep some fixed, set partry to just them 
+     for (j = 0; j < Npar; j++) partry[j] = par[j]; */
+
+  for (j = 0; j < Npar; j++) partry[j] = par[j] - tbeta[j][0];
+
+  chisq = mrqcof (index, Npts, partry, Npar, talpha, tbeta, funcs);
+
+  /* if good, save temp values */
+  if (chisq < ochisq) {
+    lambda *= 0.1;
+    ochisq = chisq;
+    for (j = 0; j < Npar; j++) {
+      for (k = 0; k < Npar; k++) alpha[j][k] = talpha[j][k];
+      beta[j][0] = tbeta[j][0];
+      par[j] = partry[j];
+    }
+  } else {
+    lambda *= 10.0;
+    chisq = ochisq;
+  }
+
+  return (chisq);
+
+}
+
+int mrqinit (int *index, int Npts, double *par, int Npar, double (funcs)(int, double *, int, double *)) {
+
+  int i;
+
+  ALLOCATE (dyda, double, Npar);
+  ALLOCATE (partry, double, Npar);
+  ALLOCATE (alpha, double *, Npar);
+  ALLOCATE (beta, double *, Npar);
+  ALLOCATE (talpha, double *, Npar);
+  ALLOCATE (tbeta, double *, Npar);
+  for (i = 0; i < Npar; i++) {
+    ALLOCATE (alpha[i], double, Npar);
+    ALLOCATE (beta[i], double, Npar);
+    ALLOCATE (talpha[i], double, Npar);
+    ALLOCATE (tbeta[i], double, Npar);
+  }
+  lambda = 0.1;
+  ochisq = mrqcof (index, Npts, par, Npar, alpha, beta, funcs);
+}
+
+int mrqfree (int Npar) {
+
+  int i;
+
+  for (i = 0; i < Npar; i++) {
+    free (alpha[i]);
+    free (talpha[i]);
+    free (beta[i]);
+    free (tbeta[i]);
+  }
+  free (alpha);
+  free (talpha);
+  free (beta);
+  free (tbeta);
+  free (partry);
+  free (dyda);
+
+}
+
+int gaussj (double **a, int n, double **b, int m) {
+
+  int *indxc,*indxr,*ipiv;
+  int i, icol, irow, j, k, l, ll, status;
+  double big,dum,pivinv;
+  
+  ALLOCATE (indxc, int, n);
+  ALLOCATE (indxr, int, n);
+  ALLOCATE (ipiv, int, n);
+  for (j = 0; j < n; j++) 
+    ipiv[j] = 0;
+
+  for (i = 0; i < n; i++) {
+    big = 0.0;
+    for (j = 0; j < n; j++) {
+      if (ipiv[j] != 1) {
+	for (k = 0; k < n; k++) {
+	  if (ipiv[k] == 0) {
+	    if (fabs (a[j][k]) >= big) {
+	      big  = fabs (a[j][k]);
+	      irow = j;
+	      icol = k;
+	    }
+	  } 
+	  else 
+	    if (ipiv[k] > 1) {
+	      fprintf (stderr, "GAUSSJ: Singular Matrix! (1)\n");
+	      return (0);
+	    }
+	}
+      }
+    }
+    ipiv[icol]++;
+    if (irow != icol) {
+      for (l = 0; l < n; l++) 
+	SWAP (a[irow][l], a[icol][l]);
+      for (l = 0; l < m; l++) 
+	SWAP (b[irow][l], b[icol][l]);
+    }
+    indxr[i] = irow;
+    indxc[i] = icol;
+    if (a[icol][icol] == 0.0) {
+      fprintf (stderr, "GAUSSJ: Singular Matrix! (2)\n");
+      return (0);
+    }
+    pivinv = 1.0 / a[icol][icol];
+    a[icol][icol] = 1.0;
+    for (l = 0; l < n; l++) 
+      a[icol][l] *= pivinv;
+    for (l = 0; l < m; l++) 
+      b[icol][l] *= pivinv;
+    for (ll = 0; ll < n; ll++) {
+      if (ll != icol) {
+	dum = a[ll][icol];
+	a[ll][icol] = 0.0;
+	for (l = 0; l < n; l++) 
+	  a[ll][l] -= a[icol][l]*dum;
+	for (l = 0; l < m; l++) 
+	  b[ll][l] -= b[icol][l]*dum;
+      }
+    }
+  }
+
+  for (l = n - 1; l >= 0; l--) {
+    if (indxr[l] != indxc[l])
+      for (k = 0; k < n; k++)
+	SWAP (a[k][indxr[l]], a[k][indxc[l]]);
+  }
+  free (ipiv);
+  free (indxr);
+  free (indxc);
+  return (1);
+}
+
+  /* par:
+     par[0] = Lo
+     par[1] = Mo
+     par[2] = ps
+     par[3] = theta
+  */
+
+double chipfunc (int idx, double *P, double *Q, double *par, int Npar) {
+  double Lo, Mo, ps, cs, sn;
+  double X, Y;
+
+  Lo = par[0];
+  Mo = par[1];
+  cs = cos (par[2]*RAD_DEG);
+  sn = sin (par[2]*RAD_DEG);
+  if (PSfixed) 
+    ps = PS;
+  else
+    ps = par[3];
+
+  X = x[idx];
+  Y = y[idx];
+
+  *P = Lo + Px * ps * (X*cs + Y*sn);
+  *Q = Mo + Py * ps * (Y*cs - X*sn);
+}
+
+double chipfit (int idx, double *par, int Npar, double *dyda) {
+
+  double Lo, Mo, ps, cs, sn;
+  double X, Y, L, M, P, Q;
+  double chisq, dp, dq;
+
+  Lo = par[0];
+  Mo = par[1];
+  cs = cos (par[2]*RAD_DEG);
+  sn = sin (par[2]*RAD_DEG);
+  if (PSfixed) 
+    ps = PS;
+  else
+    ps = par[3];
+
+  X = x[idx];
+  Y = y[idx];
+  L = p[idx];
+  M = q[idx];
+
+  P = Lo + Px * ps * (X*cs + Y*sn);
+  Q = Mo + Py * ps * (Y*cs - X*sn);
+
+  chisq = SQ(L-P) + SQ(M-Q);
+
+  dp = P - L;
+  dq = Q - M;
+
+  dyda[0] = 2*dp;
+  dyda[1] = 2*dq;
+  
+  dyda[2] =  2*RAD_DEG*ps*(dp*Px*(Y*cs - X*sn) - dq*Py*(X*cs + Y*sn));
+  if (!PSfixed)
+    dyda[3] =  2   *(dp*Px*(X*cs + Y*sn) + dq*Py*(Y*cs - X*sn));
+  
+  return (chisq);
+}
+
+sort (double *value, int N) {
+
+  int l,j,ir,i;
+  double temp;
+  
+  if (N < 2) return;
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      temp = value[--l];
+    }
+    else {
+      temp = value[ir];
+      value[ir] = value[0];
+      if (--ir == 0) {
+	value[0] = temp;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && value[j] < value[j+1]) ++j;
+      if (temp < value[j]) {
+	value[i]=value[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    value[i] = temp;
+  }
+}
+
+
+fit (double *X, double *Y, int N, double *A, double *B) {
+
+  int i;
+  double **a, **b;
+
+  ALLOCATE (a, double *, 2);
+  ALLOCATE (b, double *, 2);
+  ALLOCATE (a[0], double, 2);
+  ALLOCATE (a[1], double, 2);
+  ALLOCATE (b[0], double, 1);
+  ALLOCATE (b[1], double, 1);
+  a[0][0] = a[0][1] = a[1][0] = a[1][1] = 0;
+  b[0][0] = b[1][0] = 0;
+
+  for (i = 0; i < N; i++) {
+    a[0][0] += X[i]*X[i];
+    a[0][1] += X[i];
+    a[1][1] += 1;
+    b[0][0] += X[i]*Y[i];
+    b[1][0] += Y[i];
+  }
+
+  a[1][0] = a[0][1];
+  
+  gaussj (a, 2, b, 1);
+
+  *A = b[0][0];
+  *B = b[1][0];
+}
Index: /tags/start/Ohana/src/misc/src/posscontour.c
===================================================================
--- /tags/start/Ohana/src/misc/src/posscontour.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/posscontour.c	(revision 12606)
@@ -0,0 +1,126 @@
+# include <stdio.h>
+# include <fitsio.h>
+# include <math.h>
+# include <malloc.h>
+# include <string.h>
+# include <sys/time.h>
+# include <stdarg.h>
+# include <stdlib.h>
+
+# define TRUE (1)
+# define FALSE (0)
+# define DEG_RAD (57.29578)
+# define RAD_DEG (0.017453293)
+
+char PLTDECSN[5];
+
+double NX, NY, PLTRAH, PLTRAM, PLTRAS, PLTDECD, PLTDECM, PLTDECS, Do, Ro;
+double CNPIX1, CNPIX2, XPIXELSZ, YPIXELSZ, PPO1, PPO2, PPO3, PPO4, PPO5, PPO6;
+double AMDX1, AMDX2, AMDX3, AMDX4, AMDX5, AMDX6, AMDX7, AMDX8, AMDX9, AMDX10, AMDX11, AMDX12, AMDX13;
+double AMDY1, AMDY2, AMDY3, AMDY4, AMDY5, AMDY6, AMDY7, AMDY8, AMDY9, AMDY10, AMDY11, AMDY12, AMDY13;
+
+convert (ra, dec, X, Y) 
+     double *ra, *dec;
+     double X, Y;
+{
+
+  double x, y, Azeta, Aeta, eta, zeta;
+
+  x = (PPO3 - XPIXELSZ*(X+CNPIX1)) / 1000.0;
+  y = (YPIXELSZ*(Y+CNPIX2) - PPO6) / 1000.0;
+  Azeta = AMDX3 + x*(AMDX1 + x*(AMDX4 + AMDX7 + x*AMDX8)) + y*(AMDX2 + y*(AMDX6 + AMDX7 + y*AMDX11)) + x*y*(AMDX9*x + AMDX10*y + AMDX5) + x*(x*x+y*y)*(AMDX12 + AMDX13*(x*x+y*y));
+  Aeta  = AMDY3 + y*(AMDY1 + y*(AMDY4 + AMDY7 + y*AMDY8)) + x*(AMDY2 + x*(AMDY6 + AMDY7 + x*AMDY11)) + x*y*(AMDY9*y + AMDY10*x + AMDY5) + y*(x*x+y*y)*(AMDY12 + AMDY13*(x*x+y*y));
+  
+  eta = Aeta*RAD_DEG/3600.0;
+  zeta = Azeta*RAD_DEG/3600.0;
+  
+  *ra  = DEG_RAD*atan((zeta/cos(RAD_DEG*Do)) / (1.0 - eta*tan(RAD_DEG*Do))) + Ro;
+  *dec = DEG_RAD*atan(((eta + tan(RAD_DEG*Do)) * (cos (RAD_DEG*(*ra - Ro)))) / (1 - eta * tan(RAD_DEG*Do)));
+  
+}
+
+
+main (int argc, char **argv) 
+{
+
+  int i, status;
+  Header header;
+  double RA, DEC, ra, dec, dRA, dDEC;
+  double X, Y, dX, dY;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: posscontour filename < contour.reg\n");
+    exit (0);
+  }
+
+  status = fits_read_header (argv[1], &header);
+  if (!status) {
+    fprintf (stderr, "error opening file %s\n", argv[1]);
+    exit (0);
+  }
+
+  fits_scan (&header, "NAXIS1", "%lf", 1, &NX);
+  fits_scan (&header, "NAXIS2", "%lf", 1, &NY);
+  fits_scan (&header, "PLTRAH", "%lf", 1, &PLTRAH);
+  fits_scan (&header, "PLTRAM", "%lf", 1, &PLTRAM);
+  fits_scan (&header, "PLTRAS", "%lf", 1, &PLTRAS);
+  fits_scan (&header, "PLTDECD", "%lf", 1, &PLTDECD);
+  fits_scan (&header, "PLTDECM", "%lf", 1, &PLTDECM);
+  fits_scan (&header, "PLTDECS", "%lf", 1, &PLTDECS);
+  fits_scan (&header, "PLTDECSN", "%s", 1, &PLTDECSN);
+  fits_scan (&header, "CNPIX1", "%lf", 1, &CNPIX1);
+  fits_scan (&header, "CNPIX2", "%lf", 1, &CNPIX2);
+  fits_scan (&header, "XPIXELSZ", "%lf", 1, &XPIXELSZ);
+  fits_scan (&header, "YPIXELSZ", "%lf", 1, &YPIXELSZ);
+  fits_scan (&header, "PPO1", "%lf", 1, &PPO1);
+  fits_scan (&header, "PPO2", "%lf", 1, &PPO2);
+  fits_scan (&header, "PPO3", "%lf", 1, &PPO3);
+  fits_scan (&header, "PPO4", "%lf", 1, &PPO4);
+  fits_scan (&header, "PPO5", "%lf", 1, &PPO5);
+  fits_scan (&header, "PPO6", "%lf", 1, &PPO6);
+  fits_scan (&header, "AMDX1", "%lf", 1, &AMDX1);
+  fits_scan (&header, "AMDX2", "%lf", 1, &AMDX2);
+  fits_scan (&header, "AMDX3", "%lf", 1, &AMDX3);
+  fits_scan (&header, "AMDX4", "%lf", 1, &AMDX4);
+  fits_scan (&header, "AMDX5", "%lf", 1, &AMDX5);
+  fits_scan (&header, "AMDX6", "%lf", 1, &AMDX6);
+  fits_scan (&header, "AMDX7", "%lf", 1, &AMDX7);
+  fits_scan (&header, "AMDX8", "%lf", 1, &AMDX8);
+  fits_scan (&header, "AMDX9", "%lf", 1, &AMDX9);
+  fits_scan (&header, "AMDX10", "%lf", 1, &AMDX10);
+  fits_scan (&header, "AMDX11", "%lf", 1, &AMDX11);
+  fits_scan (&header, "AMDX12", "%lf", 1, &AMDX12);
+  fits_scan (&header, "AMDX13", "%lf", 1, &AMDX13);
+  fits_scan (&header, "AMDY1", "%lf", 1, &AMDY1);
+  fits_scan (&header, "AMDY2", "%lf", 1, &AMDY2);
+  fits_scan (&header, "AMDY3", "%lf", 1, &AMDY3);
+  fits_scan (&header, "AMDY4", "%lf", 1, &AMDY4);
+  fits_scan (&header, "AMDY5", "%lf", 1, &AMDY5);
+  fits_scan (&header, "AMDY6", "%lf", 1, &AMDY6);
+  fits_scan (&header, "AMDY7", "%lf", 1, &AMDY7);
+  fits_scan (&header, "AMDY8", "%lf", 1, &AMDY8);
+  fits_scan (&header, "AMDY9", "%lf", 1, &AMDY9);
+  fits_scan (&header, "AMDY10", "%lf", 1, &AMDY10);
+  fits_scan (&header, "AMDY11", "%lf", 1, &AMDY11);
+  fits_scan (&header, "AMDY12", "%lf", 1, &AMDY12);
+  fits_scan (&header, "AMDY13", "%lf", 1, &AMDY13);
+  Ro = 15.0*(PLTRAH + PLTRAM/60.0 + PLTRAS/3600.0);
+  Do = (PLTDECD + PLTDECM/60.0 + PLTDECS/3600.0);
+  if (PLTDECSN[0] == '-') {
+    Do *= -1;
+  }
+
+  while (fscanf (stdin, "%*s %lf %lf %lf %lf", &X, &Y, &dX, &dY) != EOF) {
+    convert (&RA, &DEC, X, Y);
+    convert (&ra, &dec, (X+dX), (Y+dY));
+    dRA = ra - RA;
+    dDEC = dec - DEC;
+    fprintf (stdout, "LINE %f %f %f %f\n", RA, DEC, dRA, dDEC);
+  }
+  
+  fits_free_header (&header);
+  
+}
+
+
+/* USAGE: posscontour filename < contour.reg > contour2.reg */
Index: /tags/start/Ohana/src/misc/src/precess.c
===================================================================
--- /tags/start/Ohana/src/misc/src/precess.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/precess.c	(revision 12606)
@@ -0,0 +1,150 @@
+# include <ohana.h>
+
+double BtoJ (double in_epoch);
+double get_epoch (char *in_epoch, char mode);
+
+int main (int argc, char **argv) {
+
+  double T, in_epoch, out_epoch;
+  double A, D, RA, DEC, zeta, z, theta;
+  double SA, CA, SD, CD;
+  int Julian, Besselian;
+
+  Besselian = Julian = 0;
+  Besselian = get_argument (argc, argv, "B");
+  Julian    = get_argument (argc, argv, "J");
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE:  precess in_epoch out_epoch\n");
+    fprintf (stderr, "   you may use B for B1950.0 or J for J2000.0\n");
+    fprintf (stderr, "   Enter values in degrees\n");
+    exit (2);
+  }
+
+  if (!Julian && !Besselian) { /* assume Julian! */
+    in_epoch  = get_epoch (argv[1], 'J');
+    out_epoch = get_epoch (argv[2], 'J');
+  }
+
+  if ((Julian == 1) && !Besselian) {
+    in_epoch  = 2000.0;
+    out_epoch = get_epoch(argv[2], 'J');
+  }
+
+  if ((Julian == 2) && !Besselian) {
+    in_epoch  = get_epoch(argv[1], 'J');
+    out_epoch = 2000.0;
+  }
+
+  if ((Besselian == 1) && !Julian) {
+    in_epoch  = BtoJ(1950.0); 
+    out_epoch = get_epoch(argv[2], 'B'); 
+  }
+
+  if ((Besselian == 2) && !Julian) {
+    in_epoch  = get_epoch(argv[1], 'B'); 
+    out_epoch = BtoJ(1950.0); 
+  }
+  
+  if (Julian && Besselian) {
+    if (Julian > Besselian) {
+      in_epoch  = BtoJ(1950.0); 
+      out_epoch = 2000.0;
+    }
+    else {
+      in_epoch  = 2000.0;
+      out_epoch = BtoJ(1950.0); 
+    }
+  }
+
+  fprintf (stderr, "converting from J%f to J%f\n", in_epoch, out_epoch);
+
+  T = (out_epoch - in_epoch) / 100.0;
+  
+  zeta  = RAD_DEG*(0.6406161*T + 0.0000839*T*T + 0.0000050*T*T*T);
+  theta = RAD_DEG*(0.5567530*T - 0.0001185*T*T - 0.0000116*T*T*T);
+  z     =          0.6406161*T + 0.0003041*T*T + 0.0000051*T*T*T;
+
+  while (fscanf (stdin, "%lf %lf", &A, &D) != EOF) {
+    SD =  cos(RAD_DEG*A + zeta)*sin(theta)*cos(RAD_DEG*D) + cos(theta)*sin(RAD_DEG*D);
+    CD = sqrt (1 - SD*SD);
+    SA =  sin(RAD_DEG*A + zeta)*cos(RAD_DEG*D)/CD;
+    CA = (cos(RAD_DEG*A + zeta)*cos(theta)*cos(RAD_DEG*D) - sin(theta)*sin(RAD_DEG*D))/CD;
+
+    DEC = DEG_RAD*asin(SD);
+    RA  = DEG_RAD*atan2(SA, CA) + z;
+
+    if (RA < 0)
+      RA += 360;
+    fprintf (stdout, "%f %f\n", RA, DEC);
+  }
+  exit (0);
+}  
+    
+
+double get_epoch (char *in_epoch, char mode) {
+
+  int done;
+  double epoch;
+
+  done = FALSE;
+  if (in_epoch[0] == 'B') {
+    epoch = BtoJ(atof(&in_epoch[1]));
+    done = TRUE;
+  }
+
+  if (in_epoch[0] == 'J') {
+    epoch = atof(&in_epoch[1]);
+    done = TRUE;
+  }
+
+  if (!done && (mode == 'B')) {
+    epoch = BtoJ(atof(in_epoch));
+    done = TRUE;
+  }
+    
+  if (!done && (mode == 'J')) {
+    epoch = atof(in_epoch);
+    done = TRUE;
+  }
+
+  if (!done) {
+    fprintf (stderr, "error finding epoch %s\n", in_epoch);
+    exit (1);
+  }
+  
+  return (epoch);
+}
+
+double BtoJ (double in_epoch) {
+
+  double JD, out_epoch;
+
+  JD = (in_epoch - 1900.0)*365.242198781 + 2415020.31352;
+  out_epoch = 2000.0 + (JD - 2451545.0)/365.25;
+
+  return (out_epoch);
+}
+
+/*
+  time =  (in_epoch - out_epoch) / 100.0;
+
+  fprintf (stderr, "precessing from %f to %f\n", in_epoch, out_epoch);
+  sinE = sin (epsilon*deg_to_rad);
+  cosE = cos (epsilon*deg_to_rad);
+  M = 1.281232*time + 0.0003879*(time*time);
+  N = 0.5567*time - 0.0001185*(time*time);
+
+  while (fscanf (stdin, "%lf %lf", &RA, &Dec) != EOF) {
+    RA = RA - M - N*sin(RA*deg_to_rad)*tan(Dec*deg_to_rad);
+    Dec = Dec - N*cos (RA*deg_to_rad);
+
+    Dec = Dec + time*thetaD*sinE*cos(RA*deg_to_rad);
+    RA = RA + time*thetaD*(cosE + sinE*sin(RA*deg_to_rad)*tan(Dec*deg_to_rad));
+
+    fprintf (stdout, "%f %f\n", RA, Dec);
+  }
+
+*/
+
+
Index: /tags/start/Ohana/src/misc/src/radec.c
===================================================================
--- /tags/start/Ohana/src/misc/src/radec.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/radec.c	(revision 12606)
@@ -0,0 +1,102 @@
+# include <ohana.h>
+
+int help ();
+int hms_to_deg (double *h, double *d, char *string, char sep, int Nin);
+
+int main (int argc, char **argv) {
+
+  char line[1000];
+  char sep;
+  double ra, dec;
+  int status, h, m, flag;
+  double s, hh;
+
+  sep = ' ';
+  if (get_argument (argc, argv, "-hms")) {
+    while (scan_line (stdin, line) != EOF) {
+      status = hms_to_deg (&ra, &dec, line, sep, 3);
+      if (status)
+	fprintf (stdout, "%10.6f %10.6f\n", ra, dec);
+    }
+    exit (0);
+  }
+    
+  if (get_argument (argc, argv, "-hh")) {
+    while (scan_line (stdin, line) != EOF) {
+      dparse (&hh, 1, line);
+      hh /= 15.0;  /* convert from degrees to hours */
+      flag = SIGN(hh);
+      hh *= flag;
+      h = hh;
+      m = 60.000001*(hh - h);
+      s = 3600*(hh - h - m / 60.0);
+      if (flag > 0)
+	fprintf (stdout, " %02d%c%02d%c%06.3f  ", h, sep, m, sep, s);
+      else
+	fprintf (stdout, "-%02d%c%02d%c%06.3f  ", h, sep, m, sep, s);
+      dparse (&hh, 2, line);
+      flag = SIGN(hh);
+      hh *= flag;
+      h = hh;
+      m = 60.000001*(hh - h);
+      s = 3600*(hh - h - m / 60.0);
+      if (flag > 0)
+	fprintf (stdout, " %02d%c%02d%c%06.3f\n", h, sep, m, sep, s);
+      else
+	fprintf (stdout, "-%02d%c%02d%c%06.3f\n", h, sep, m, sep, s);
+    }
+    exit (0);
+  }
+
+  fprintf (stderr, "USAGE: %s [-hh/-hms] \n", argv[0]);
+  fprintf (stderr, "  -hh:  convert from decimal ra,dec to hours, min sec\n");
+  fprintf (stderr, "  -hms: convert from hours, min sec to decimal ra,dec\n");
+  exit (2);
+}
+
+/**********/
+int hms_to_deg (double *h, double *d, char *string, char sep, int Nin) {
+  
+  char *c;
+  int i, flag_d, flag_h, Nfields;
+  double tmp;
+  
+  *d = *h = 0;
+  stripwhite (string);
+  for (Nfields = 2, i = 0; i < 2*(Nin - 1); i++) {
+    if ((c = strchr (string, sep)) != NULL) {
+      Nfields ++;
+      *c = ' ';
+    }
+  }
+  if (Nfields != 2*Nin) {
+    fprintf (stderr, "warning -- line with too few entries, skipping:  %d != %d\n", Nfields, Nin);
+    return (FALSE);
+  }
+
+  Nfields /= 2;
+
+  flag_h = dparse (h, 1, string);
+  flag_d = dparse (d, Nfields + 1, string);
+  *h *= flag_h;
+  *d *= flag_d;
+
+  if (Nfields > 1) {
+    dparse (&tmp, 2, string);
+    *h += tmp/60.0;
+    dparse (&tmp, Nfields + 2, string);
+    *d += tmp/60.0;
+  }
+
+  if (Nfields > 2) {
+    dparse (&tmp, 3, string);
+    *h += tmp/3600.0;
+    dparse (&tmp, Nfields + 3, string);
+    *d += tmp/3600.0;
+  }
+  
+  *h *= 15*flag_h;
+  *d *= flag_d;
+
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/misc/src/random.c
===================================================================
--- /tags/start/Ohana/src/misc/src/random.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/random.c	(revision 12606)
@@ -0,0 +1,64 @@
+# include <ohana.h>
+
+void   gauss_init ();
+double gaussian (double x, double mean, double sigma);
+double rnd_gauss (double mean, double sigma);
+
+/* NGAUSS defines the resolution of the distribution */
+# define NGAUSS 2048
+static double gaussint[NGAUSS];
+
+void gauss_init () {
+
+  int i;
+  long A, B;
+  double val, x, dx, dx1, dx2, dx3, df;
+  double mean, sigma;
+
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+
+  val = 0;
+  dx = 0.001;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+  mean = 0.0;
+  sigma = 1.0;
+
+  for (i = 0, x = -7.0; (i < NGAUSS) && (x < 7.0); x += dx)  {
+    df = (3.0*gaussian(x    , 0.0, 1.0) + 
+	  9.0*gaussian(x+dx1, 0.0, 1.0) +
+	  9.0*gaussian(x+dx2, 0.0, 1.0) + 
+	  3.0*gaussian(x+dx3, 0.0, 1.0)) * (dx1/8.0);
+    val += df;
+    if (val > (i / (double) NGAUSS)) {
+      gaussint[i] = x + dx / 2.0;
+      i++;
+    }
+  }
+  return;
+}
+
+double gaussian (double x, double mean, double sigma) {
+  double f, X;
+
+  f = exp (-0.5 * SQ(x - mean) / SQ(sigma)) / sqrt(2 * M_PI * SQ(sigma));
+  return (f);
+}
+
+double rnd_gauss (double mean, double sigma) {
+
+  int i;
+  double y;
+
+  i = 0;
+  while ((i == 0) || (i == NGAUSS - 1)) {
+    y = drand48();
+    i = MIN (NGAUSS - 1, MAX (0, NGAUSS*y));
+  }
+  y = gaussint[i]*sigma + mean;
+
+  return (y);
+}
Index: /tags/start/Ohana/src/misc/src/regions.c
===================================================================
--- /tags/start/Ohana/src/misc/src/regions.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/regions.c	(revision 12606)
@@ -0,0 +1,205 @@
+# include <ohana.h>
+# define DEBUG 0
+double BigDecBounds[] = {0.0, 7.5, 15.0, 22.5, 30.0, 37.5, 45.0, 
+			   52.5, 60.0, 67.5, 75.0, 82.5, 90.0,
+			   0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, 
+			   -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+char *DecSections[] = {"N0000", "N0730", "N1500", "N2230", "N3000", "N3730", "N4500", 
+			 "N5230", "N6000", "N6730", "N7500", "N8230", "weirdness", 
+			 "S0000", "S0730", "S1500", "S2230", "S3000", "S3730", "S4500", 
+			 "S5230", "S6000", "S6730", "S7500", "S8230", "weirdness"};
+
+char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			 "n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			 "s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			 "s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+char *disk[] = {"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", 
+		  "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "weirdness", 
+		  "disk 1", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", 
+		  "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "weirdness"};
+
+int NBigRASections [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3, 48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3};
+
+int NDecLines[] = {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 48, 
+                   0, 597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48};
+
+void  main 
+  (int argc,
+   char **argv) 
+{
+
+  /* USAGE: regions ra dec -- returns filenumber of appropriate GSC region */
+
+  char buffer[2880], temp[50], file[50], line[50];
+  char *p, prefix[1024];
+  FILE *f;
+  double ra, dec, dBigRA, RA, DEC, tmp;
+  double BigRABounds[2], RA0, RA1, DEC0, DEC1;
+  int i, NBigDec, NBigRA, NBig, VMS, N;
+  int NRA, NDEC, NLINES, done, NBLOCKS;
+
+  VMS = FALSE;
+  if (N = get_argument (argc, argv, "-vms")) {
+    remove_argument (N, &argc, argv);
+    VMS = TRUE;
+  }
+
+  strcpy (prefix, "/cdrom/");
+  if (N = get_argument (argc, argv, "-pre")) {
+    remove_argument (N, &argc, argv);
+    strcpy (prefix, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: %s (regions.tbl) [-pre (prefix)] [-vms]\n", argv[0]);
+    exit (0);
+  }
+
+  while (fscanf (stdin, "%lf %lf", &ra, &dec) != EOF) {
+    f = fopen (argv[1], "r");
+    if (f == NULL) {
+      fprintf (stderr, "could not open GSC regions file %s\n", argv[1]);
+      exit (0);
+    }
+    fread (buffer, 2880, 1, f);
+    fread (buffer, 2880, 1, f);
+    fread (buffer, 2880, 1, f);
+    fread (buffer, 2880, 1, f);
+    fread (buffer, 2880, 1, f);
+    
+    while (ra < 0) { ra += 360.0; }
+    while (ra >= 360.0) { ra -= 360.0; }
+    
+    NBigDec = -1;
+    for (i = 0; i < 12; i++) {
+      (DEBUG) && fprintf (stderr, "%d %f %f %f\n", i, dec, BigDecBounds[i], BigDecBounds[i+1]);
+      if ((dec >= BigDecBounds[i]) && (dec <= BigDecBounds[i+1])) {
+	NBigDec = i;
+	break;
+      }
+    }
+    if (NBigDec < 0) {
+      for (i = 13; i < 24; i++) {
+	(DEBUG) && fprintf (stderr, "%d %f %f %f\n", i, dec, BigDecBounds[i], BigDecBounds[i+1]);
+	if ((dec <= BigDecBounds[i]) && (dec >= BigDecBounds[i+1])) {
+	  NBigDec = i;
+	  break;
+	}
+      }
+    }
+    if (NBigDec < 0) {
+      fprintf (stderr, "dec out of range: %f\n", dec);
+    }
+    
+    NLINES = 0;
+    for (i = 0; i < NBigDec; i++) {
+      NLINES += NDecLines[i];
+    }
+    NBLOCKS = (int) (48*NLINES / 2880);
+    for (i = 0; i < NBLOCKS; i++) {
+      fread (buffer, 2880, 1, f);
+    }
+    
+    done = FALSE;
+    while (!done) {
+      fread (buffer, 2880, 1, f);
+      for (i = 0; !done && (i < 60); i++) {
+	strncpy (temp, &buffer[i*48], 48);
+	temp[49] = 0;
+	hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+	(DEBUG) && fprintf (stderr, "%f %f %f    %f %f %f  %s\n", dec, DEC0, DEC1, ra, RA0, RA1, temp);
+	if ((dec >= 0) && (dec >= DEC0) && (dec < DEC1) && (ra >= RA0) && (ra < RA1)) {
+	  done = TRUE;
+	}
+	if ((dec < 0) && (dec <= DEC0) && (dec > DEC1) && (ra >= RA0) && (ra < RA1)) {
+	  done = TRUE;
+	}
+      }
+    }
+  
+    if (VMS) 
+      sprintf (file, "%s %sGSC/%s/%c%c%c%c.GSC\\;1\0", prefix, disk[NBigDec], DecSections[NBigDec],
+	       temp[1], temp[2], temp[3], temp[4]);
+    else 
+      sprintf (file, "%s %sgsc/%s/%c%c%c%c.gsc\0", disk[NBigDec], prefix, Dec2Sections[NBigDec],
+	       temp[1], temp[2], temp[3], temp[4]);
+
+    fprintf (stdout, "%s\n", file);
+
+    fclose (f);
+    
+  }
+
+}
+
+
+
+/**********/
+int hms_to_deg (h0, h1, d0, d1, string) 
+char *string;
+double *h0, *h1, *d0, *d1;
+{
+  
+  char *c;
+  int i, flag_d0, flag_d1, flag_h0, flag_h1;
+  double tmp;
+  
+  *d0 = *h0 = *d1 = *h1 = 0;
+
+  flag_h0 = dparse (h0, 1, string);
+  flag_h1 = dparse (h1, 4, string);
+  flag_d0 = dparse (d0, 7, string);
+  flag_d1 = dparse (d1, 9, string);
+  *h0 *= flag_h0;
+  *h1 *= flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  dparse (&tmp, 2, string);
+  *h0 += tmp/60.0;
+  dparse (&tmp, 3, string);
+  *h0 += tmp/3600.0;
+  
+  dparse (&tmp, 5, string);
+  *h1 += tmp/60.0;
+  dparse (&tmp, 6, string);
+  *h1 += tmp/3600.0;
+  
+  dparse (&tmp, 8, string);
+  *d0 += tmp/60.0;
+
+  dparse (&tmp, 10, string);
+  *d1 += tmp/60.0;
+
+  *h0 *= 15*flag_h0;
+  *h1 *= 15*flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  return (TRUE);
+}
+
+
+/*
+      if (buffer[i*48 + 19] == ' ') continue;
+      strncpy (temp, &buffer[i*48 + 19], 20);       temp[20] = 0;
+      hms_to_deg (&RA,  &DEC, temp, ' ', 3);
+
+
+  dBigRA = 360.0 / (int)(0.5 + 48*cos(3.1415927*0.5*(BigDecBounds[NBigDec] + BigDecBounds[NBigDec + 1])/180.0));
+
+  NBigRA = ra / dBigRA;
+
+  NBig = NBigRA;
+  for (i = 0; (i < 12) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+  for (i = 13; (i < 24) && (i < NBigDec); i++) {
+    NBig += NBigRASections[i];
+  }
+
+
+  fprintf (stderr, "%d %d %d %d %f %f -> %f %f %f\n", NBigDec, NBigRA, NBigRASections[NBigDec], NBig, ra, dec, BigDecBounds[NBigDec], BigDecBounds[NBigDec + 1], dBigRA);
+*/
Index: /tags/start/Ohana/src/misc/src/remove_argument.c
===================================================================
--- /tags/start/Ohana/src/misc/src/remove_argument.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/remove_argument.c	(revision 12606)
@@ -0,0 +1,21 @@
+# include <stdio.h>
+
+int remove_argument (N, argc, argv)
+int N;
+int *argc;
+char *argv[];
+{
+
+  int i;
+
+  if ((N != (int)NULL) && (N != 0)) {
+    (*argc)--;
+    for (i = N; i < *argc; i++) {
+      argv[i] = argv[i+1];
+    }
+  }
+
+  return (N);
+    
+}
+
Index: /tags/start/Ohana/src/misc/src/smaeder.c
===================================================================
--- /tags/start/Ohana/src/misc/src/smaeder.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/smaeder.c	(revision 12606)
@@ -0,0 +1,512 @@
+# include <ohana.h>
+
+typedef struct {
+  double age;
+  double UV;
+  double V;
+} Model;
+
+typedef struct {
+  double mass;
+  int   Nmodel;
+  Model *model;
+} Track;
+
+int metal;
+double UV0, UV1, dUV;
+double V0, V1, dV;
+int dump, sdump;
+int col1, col2;
+char massfile[1024], agefile[1024];
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+
+  int Ntrack;
+  Track *track, *newtrack;
+
+  args (argc, argv);
+
+  fprintf (stderr, "reading in tracks...\n");
+  readmaeder (argv[1], &track, &Ntrack);
+
+  fprintf (stderr, "smoothing tracks...\n");
+  smoothtracks (&newtrack, track, Ntrack); 
+
+  fprintf (stderr, "interpolating tracks...\n");
+  interpolate_tracks (newtrack, Ntrack);
+
+}
+
+args (argc, argv) 
+int argc;
+char **argv;
+{
+
+  int N;
+
+  metal = 4; /* solar metal */
+  if (N = get_argument (argc, argv, "-metal")) {
+    remove_argument (N, &argc, argv);
+    metal = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  else {
+    fprintf (stderr, "using solar metallicity\n");
+  }
+  
+  dump = -1;
+  if (N = get_argument (argc, argv, "-dump")) {
+    remove_argument (N, &argc, argv);
+    dump = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  
+  sdump = -1;
+  if (N = get_argument (argc, argv, "-sdump")) {
+    remove_argument (N, &argc, argv);
+    sdump = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  
+  col1 = 3;
+  if (N = get_argument (argc, argv, "-col1")) {
+    remove_argument (N, &argc, argv);
+    col1 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  
+  col2 = 5;
+  if (N = get_argument (argc, argv, "-col2")) {
+    remove_argument (N, &argc, argv);
+    col2 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  fprintf (stderr, "using mags in columns %d & %d\n", col1, col2);
+  
+  UV0 = -2.0;
+  UV1 =  2.0;
+  dUV =  0.01; 
+  if (N = get_argument (argc, argv, "-color")) {
+    remove_argument (N, &argc, argv);
+    UV0 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    UV1 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    dUV = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  V0 =   5.0;
+  V1 = -15.0;
+  dV =  -0.02; 
+  if (N = get_argument (argc, argv, "-mag")) {
+    remove_argument (N, &argc, argv);
+    V0 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    V1 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    dV = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  strcpy (massfile, "mass.fits");
+  if (N = get_argument (argc, argv, "-mass")) {
+    remove_argument (N, &argc, argv);
+    strcpy (massfile, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  strcpy (agefile, "age.fits");
+  if (N = get_argument (argc, argv, "-age")) {
+    remove_argument (N, &argc, argv);
+    strcpy (agefile, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  
+  if (argc < 2) {
+    fprintf (stderr, "USAGE: smaeder (filename) [options]\n");
+    fprintf (stderr, "  options:\n");
+    fprintf (stderr, "  [-metal N] (N = 0,1,2,3,4)\n");
+    fprintf (stderr, "  [-color min max delta] \n");
+    fprintf (stderr, "  [-mag min max delta] \n");
+    fprintf (stderr, "  [-mass file] \n");
+    fprintf (stderr, "  [-age file]\n");
+    exit (0);
+  }
+}
+
+/* read in the tracks for the requested metalicity */
+/* fairly dependent on the format of the files that Andy produces */
+readmaeder (maederfile, track, Ntrack)
+char  *maederfile;
+Track **track;
+int   *Ntrack;
+{
+
+  int i, j, m;
+  FILE *f;
+  char line[1024];
+  double U, V, ntrack, nmodel;
+
+  f = fopen (maederfile, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "couldn't find maeder tracks (%s)\n", maederfile);
+    exit (0);
+  }
+
+  for (m = 0; m < 5; m ++) {
+    scan_line (f, line);
+    dparse (&ntrack, 1, line);
+    *Ntrack = ntrack;
+    if (m == metal) {
+      ALLOCATE (track[0], Track, *Ntrack);
+    }
+    for (i = 0; i < ntrack; i++) {
+      scan_line (f, line);
+      dparse (&nmodel, 2, line);
+      if (m == metal) {
+	track[0][i].Nmodel = nmodel;
+	dparse (&track[0][i].mass, 1, line);
+	ALLOCATE (track[0][i].model, Model, track[0][i].Nmodel);
+      }
+      for (j = 0; j < nmodel; j++) {
+	scan_line (f, line);
+	if (m == metal) {
+	  dparse (&track[0][i].model[j].age, 1, line);
+	  track[0][i].model[j].age /= 1000000.0;   /* convert to Myrs */
+	  dparse (&U, col1, line);
+	  dparse (&V, col2, line);
+	  track[0][i].model[j].V = V;
+	  track[0][i].model[j].UV = U-V;
+	}
+      }
+    }
+  }
+  fclose (f);
+
+  if (dump > -1) {
+    if (dump >= *Ntrack) {
+      fprintf (stderr, "track %d not found\n", dump);
+      exit (0);
+    } 
+    for (i = 0; i < track[0][dump].Nmodel; i++) {
+      fprintf (stderr, "%d %d %f %e %f %f\n", 
+	       i, track[0][dump].Nmodel, track[0][dump].mass, track[0][dump].model[i].age,
+	       track[0][dump].model[i].V, track[0][dump].model[i].UV);
+    }
+    exit (0);
+  }
+
+}
+
+
+/* convert the tracks to smooth, monotonically increasing color tracks */
+smoothtracks (newtrack, track, Ntrack)
+Track **newtrack, *track;
+int Ntrack;
+{
+
+  int i, j, J1, J2, npts, done;
+  double minC, maxC, dadc, dmdc, age1, mag1, dcolor;
+  double resolution, c1, c2;
+  
+  fprintf (stderr, "smoothing..\n");
+  resolution = dUV;
+  ALLOCATE (newtrack[0], Track, Ntrack);
+  for (i = 0; i < Ntrack ; i++) {
+    /* find min & max colors */
+    minC = track[i].model[0].UV;
+    maxC = -1000;
+    for (j = 0; j < track[i].Nmodel; j++) {
+      maxC = MAX (track[i].model[j].UV, maxC);
+    }
+    npts = (int) ((maxC - minC) / resolution) + 1;
+    ALLOCATE (newtrack[0][i].model, Model, npts);
+    newtrack[0][i].mass = track[i].mass;
+    newtrack[0][i].Nmodel = npts;
+    for (j = 0; j < npts; j++) {
+      newtrack[0][i].model[j].UV = minC + resolution*j;
+    }
+    if (npts == 1) {
+      newtrack[0][i].model[0].age = track[i].model[0].age;
+      newtrack[0][i].model[0].V = track[i].model[0].V;
+      continue;
+    }
+    J1 = 0;
+    for (J2 = J1+1; (J2 < track[i].Nmodel) 
+	   && (track[i].model[J2].UV < track[i].model[J1].UV); J2++);
+    if (J2 == track[i].Nmodel) {
+      fprintf (stderr, "logical error 1\n");
+      exit (0);
+    }
+    dadc = (track[i].model[J2].age   - track[i].model[J1].age) /
+      (track[i].model[J2].UV - track[i].model[J1].UV);
+    dmdc = (track[i].model[J2].V   - track[i].model[J1].V) /
+      (track[i].model[J2].UV - track[i].model[J1].UV);
+    age1 = track[i].model[J1].age;
+    mag1 = track[i].model[J1].V;
+    for (j = 0; j < npts; j++) {
+      if (track[i].model[J2].UV < newtrack[0][i].model[j].UV) {
+	J1 = J2;
+	for (J2 = J1+1; (J2 < track[i].Nmodel) && ((track[i].model[J2].UV < track[i].model[J1].UV) || (track[i].model[J2].UV < newtrack[0][i].model[j].UV)); J2++) {
+	}
+	if (J2 == track[i].Nmodel) {
+	  fprintf (stderr, "logical error 2\n");
+	  exit (0);
+	}
+	dadc = (track[i].model[J2].age   - track[i].model[J1].age) /
+	       (track[i].model[J2].UV - track[i].model[J1].UV);
+	dmdc = (track[i].model[J2].V   - track[i].model[J1].V) /
+	       (track[i].model[J2].UV - track[i].model[J1].UV);
+	age1 = track[i].model[J1].age;
+	mag1 = track[i].model[J1].V;
+      }	
+      dcolor = newtrack[0][i].model[j].UV - track[i].model[J1].UV;
+      newtrack[0][i].model[j].age = dadc * dcolor + age1; 
+      newtrack[0][i].model[j].V = dmdc * dcolor + mag1; 
+    }
+  }
+  fprintf (stderr, "\n");
+
+  if (sdump > -1) {
+    if (sdump >= Ntrack) {
+      fprintf (stderr, "track %d not found\n", sdump);
+      exit (0);
+    }
+    for (i = 0; i < newtrack[0][sdump].Nmodel; i++) {
+      fprintf (stderr, "%d %f %e %f %f\n", 
+	       i, newtrack[0][sdump].mass, newtrack[0][sdump].model[i].age,
+	       newtrack[0][sdump].model[i].V, newtrack[0][sdump].model[i].UV);
+    }
+    exit (0);
+  }
+  
+}
+
+interpolate_tracks (newtrack, Ntrack)
+Track *newtrack;
+int Ntrack;
+{
+ 
+  Header mass_h, age_h;
+  Matrix mass_i, age_i;
+  double Ms, As, Vs, dM, dA, DV, m, a, a1, a2, m1, m2, v, dummy, tmp;
+  double d, minD, uv;
+  int i, j, k, J1, Sx, Sy, Ey;
+  int ii, I0, I1;
+
+  mass_h.bitpix = -32;
+  mass_h.Naxes = 2;
+  mass_h.Naxis[0] = (UV1 - UV0) / dUV;
+  mass_h.Naxis[1] = fabs((V1 - V0) / dV);
+  mass_h.bzero = 0.0;
+  mass_h.bscale = 1.0;
+  mass_h.unsign = FALSE;
+  mass_h.extend = FALSE;
+
+  age_h.bitpix = -32;
+  age_h.Naxes = 2;
+  age_h.Naxis[0] = (UV1 - UV0) / dUV;
+  age_h.Naxis[1] = fabs((V1 - V0) / dV);
+  age_h.bzero = 0.0;
+  age_h.bscale = 1.0;
+  age_h.unsign = FALSE;
+  age_h.extend = FALSE;
+
+  fits_create_header (&mass_h);
+  fits_create_matrix (&mass_h, &mass_i);
+  fits_create_header (&age_h);
+  fits_create_matrix (&age_h, &age_i);
+  fprintf (stderr, "created FITS buffers\n");
+
+  for (i = 1; i < Ntrack; i++) {
+    fprintf (stderr, "%d  %d\n", i, newtrack[i].Nmodel);
+    J1 = 0;
+    for (j = 0; j < newtrack[i].Nmodel; j++) {
+      if ((newtrack[i].model[j].V < V0) &&
+	  (newtrack[i].model[j].V > V1) &&
+	  (newtrack[i].model[j].UV > UV0) &&
+	  (newtrack[i].model[j].UV < UV1)) {
+	while ((J1 < newtrack[i-1].Nmodel - 1) && ((int)((newtrack[i].model[j].UV  - UV0) / dUV) > (int)((newtrack[i-1].model[J1].UV  - UV0) / dUV))) {
+	  J1++;
+	}
+	uv = newtrack[i].model[j].UV;
+	Sx = (newtrack[i].model[j].UV  - UV0) / dUV;
+	Sy = (newtrack[i].model[j].V   -  V0) / dV;
+	if (newtrack[i].model[j].UV < newtrack[i-1].model[0].UV) {
+	  tmp = (uv - newtrack[i-1].model[0].UV) / (newtrack[i].model[0].UV -  newtrack[i-1].model[0].UV);
+	  Vs = newtrack[i-1].model[0].V +  tmp * (newtrack[i].model[0].V -  newtrack[i-1].model[0].V);
+	}
+	else {
+	  Vs = newtrack[i-1].model[J1].V;
+	}
+	Ey = (Vs - V0) / dV;
+	if ((j > 20) && (J1 > 20)) {
+	  Vs = newtrack[i-1].model[J1].V;
+	  Ms = newtrack[i-1].mass;
+	  As = newtrack[i-1].model[J1].age;
+	  Ey = (newtrack[i-1].model[J1].V - V0) / dV;
+	  DV = newtrack[i].model[j].V - Vs;
+	  dM = newtrack[i].mass - Ms;
+	  dA = newtrack[i].model[j].age - As;
+	  for (k = Sy; (k >= Ey) && (k >= 0); k--) {
+	    v = k*dV + V0;
+	    m = (v - Vs) * dM / DV + Ms;
+	    a = (v - Vs) * dA / DV + As;
+	    fits_set_matrix_value (&mass_i, Sx, k, m);
+	    fits_set_matrix_value (&age_i, Sx, k, a);
+	  }
+	}
+	else {
+	  for (k = Sy; (k >= Ey) && (k >= 0); k--) {
+	    v = k*dV + V0;
+	    minD = 1000;
+	    for (ii = 0; (ii < newtrack[i].Nmodel); ii++) {
+	      I0 = MIN (ii, 20);
+	      tmp = 1.0 / hypot(newtrack[i].model[ii].V - newtrack[i-1].model[I0].V, newtrack[i].model[ii].UV - newtrack[i-1].model[I0].UV);
+	      d = -tmp * ((newtrack[i].model[ii].UV - newtrack[i-1].model[I0].UV)*(v - newtrack[i-1].model[I0].V) - 
+			  (newtrack[i].model[ii].V - newtrack[i-1].model[I0].V)*(uv - newtrack[i-1].model[I0].UV));
+	      if ((d > 0) && (d < minD)) {
+		I1 = ii;
+		minD = d;
+	      }
+	      if (d > minD) {
+		break;
+	      }
+	    }
+	    I0 = MIN (I1, 20);
+	    tmp = ((newtrack[i].model[I1].UV - newtrack[i-1].model[I0].UV)*(uv - newtrack[i-1].model[I0].UV) + 
+		   (newtrack[i].model[I1].V - newtrack[i-1].model[I0].V)*(v - newtrack[i-1].model[I0].V)) / 
+	      hypot(newtrack[i].model[I1].V - newtrack[i-1].model[I0].V, newtrack[i].model[I1].UV - newtrack[i-1].model[I0].UV);
+	    d = tmp / hypot (newtrack[i].model[I1].V - newtrack[i-1].model[I0].V, newtrack[i].model[I1].UV - newtrack[i-1].model[I0].UV);
+	    dM = newtrack[i].mass - newtrack[i-1].mass;
+	    dA = newtrack[i].model[I1].age - newtrack[i-1].model[I0].age;
+	    m1 = d * dM + newtrack[i-1].mass;
+	    a1 = d * dA + newtrack[i-1].model[I0].age;
+	    /*	    fprintf (stderr, "%d  %f  %f  %f  %f  %f\n", I1, minD, d, tmp, dM, m1); */
+	    
+	    tmp = ((newtrack[i].model[I1+1].UV - newtrack[i-1].model[I0+1].UV)*(uv - newtrack[i-1].model[I0+1].UV) + 
+		   (newtrack[i].model[I1+1].V - newtrack[i-1].model[I0+1].V)*(v - newtrack[i-1].model[I0+1].V)) / 
+	      hypot(newtrack[i].model[I1+1].V - newtrack[i-1].model[I0+1].V, newtrack[i].model[I1+1].UV - newtrack[i-1].model[I0+1].UV);
+	    d = tmp / hypot (newtrack[i].model[I1+1].V - newtrack[i-1].model[I0+1].V, newtrack[i].model[I1+1].UV - newtrack[i-1].model[I0+1].UV);
+	    dM = newtrack[i].mass - newtrack[i-1].mass;
+	    dA = newtrack[i].model[I1+1].age - newtrack[i-1].model[I0+1].age;
+	    m2 = d * dM + newtrack[i-1].mass;
+	    a2 = d * dA + newtrack[i-1].model[I0+1].age;
+
+	    d = -((newtrack[i].model[I1].UV - newtrack[i-1].model[I0].UV)*(v - newtrack[i-1].model[I0].V) - 
+		 (newtrack[i].model[I1].V - newtrack[i-1].model[I0].V)*(uv - newtrack[i-1].model[I0].UV))
+	      / hypot(newtrack[i].model[I1].V - newtrack[i-1].model[I0].V, newtrack[i].model[I1].UV - newtrack[i-1].model[I0].UV);
+	    tmp = ((newtrack[i].model[I1+1].UV - newtrack[i-1].model[I0+1].UV)*(v - newtrack[i-1].model[I0+1].V) - 
+		 (newtrack[i].model[I1+1].V - newtrack[i-1].model[I0+1].V)*(uv - newtrack[i-1].model[I0+1].UV))
+	      / hypot(newtrack[i].model[I1+1].V - newtrack[i-1].model[I0+1].V, newtrack[i].model[I1+1].UV - newtrack[i-1].model[I0+1].UV);
+
+	    a = d * (a2 - a1) / (d + tmp) + a1;
+	    m = d * (m2 - m1) / (d + tmp) + m1;
+	    fits_set_matrix_value (&mass_i, Sx, k, m);
+	    fits_set_matrix_value (&age_i, Sx, k, a);
+	  }
+	}
+      }
+    }
+  }
+  /*   
+  for (i = 1; i < Ntrack; i++) {
+    fprintf (stderr, "%d  %d\n", i, newtrack[i].Nmodel);
+    for (j = 0; j < newtrack[i].Nmodel; j++) {
+      if ((newtrack[i].model[j].V < V0) &&
+	  (newtrack[i].model[j].V > V1) &&
+	  (newtrack[i].model[j].UV > UV0) &&
+	  (newtrack[i].model[j].UV < UV1)) {
+	Sx = (newtrack[i].model[j].UV  - UV0) / dUV;
+	Sy = (newtrack[i].model[j].V   -  V0) / dV;
+	fits_set_matrix_value (&age_i, Sx, Sy, 1000.0);
+	fits_set_matrix_value (&mass_i, Sx, Sy, 1000.0);
+      }
+    }
+  }
+  */
+
+  fits_modify (&mass_h, "RA_O", "%lf", 1, UV0);
+  fits_modify (&mass_h, "RA_X", "%lf", 1, dUV);
+  fits_modify (&mass_h, "RA_Y", "%lf", 1, 0.0);
+  fits_modify (&mass_h, "DEC_O", "%lf", 1, V0);
+  fits_modify (&mass_h, "DEC_Y", "%lf", 1, dV);
+  fits_modify (&mass_h, "DEC_X", "%lf", 1, 0.0);
+
+  fits_write_header (massfile, &mass_h);
+  fits_write_matrix (massfile, &mass_i);
+
+  fits_modify (&age_h, "RA_O",  "%lf", 1, UV0);
+  fits_modify (&age_h, "RA_X",  "%lf", 1, dUV);
+  fits_modify (&age_h, "RA_Y",  "%lf", 1, 0.0);
+  fits_modify (&age_h, "DEC_O", "%lf", 1, V0);
+  fits_modify (&age_h, "DEC_Y", "%lf", 1, dV);
+  fits_modify (&age_h, "DEC_X", "%lf", 1, 0.0);
+
+  fits_write_header (agefile, &age_h);
+  fits_write_matrix (agefile, &age_i);
+
+}
+
+/*
+ 	  minD = 1000;
+	  for (ii = 0; ii < newtrack[i-1].Nmodel; ii++) {
+	    d = hypot(newtrack[i-1].model[ii].V - v, newtrack[i-1].model[ii].UV - uv);
+	    if (d < minD) {
+	      I0 = ii;
+	      minD = d;
+	    }
+	  }
+	  minD = 1000;
+	  for (ii = 0; ii < newtrack[i].Nmodel; ii++) {
+	    d = hypot(newtrack[i].model[ii].V - v, newtrack[i].model[ii].UV - uv);
+	    if (d < minD) {
+	      I1 = ii;
+	      minD = d;
+	    }
+	  }
+ for (i = 1; i < Ntrack; i++) {
+    fprintf (stderr, "%d  %d\n", i, newtrack[i].Nmodel);
+    J1 = 0;
+    for (j = 0; j < newtrack[i].Nmodel; j++) {
+      if ((newtrack[i].model[j].V < V0) &&
+	  (newtrack[i].model[j].V > V1) &&
+	  (newtrack[i].model[j].UV > UV0) &&
+	  (newtrack[i].model[j].UV < UV1)) {
+	while ((J1 < newtrack[i-1].Nmodel - 1) && ((int)((newtrack[i].model[j].UV  - UV0) / dUV) > (int)((newtrack[i-1].model[J1].UV  - UV0) / dUV))) {
+	  J1++;
+	}
+	Sx = (newtrack[i].model[j].UV  - UV0) / dUV;
+	Sy = (newtrack[i].model[j].V   -  V0) / dV;
+	if (newtrack[i].model[j].UV < newtrack[i-1].model[0].UV) {
+	  tmp = (newtrack[i].model[j].UV - newtrack[i-1].model[0].UV) / (newtrack[i].model[0].UV -  newtrack[i-1].model[0].UV);
+	  Vs = newtrack[i-1].model[0].V +  tmp * (newtrack[i].model[0].V -  newtrack[i-1].model[0].V);
+	  As = newtrack[i-1].model[0].age + tmp * (newtrack[i].model[0].age -  newtrack[i-1].model[0].age);
+	  Ms = newtrack[i-1].mass + tmp * (newtrack[i].mass - newtrack[i-1].mass);
+	  Ey = (Vs  - V0) / dV;
+	}
+	else {
+	  Vs = newtrack[i-1].model[J1].V;
+	  Ms = newtrack[i-1].mass;
+	  As = newtrack[i-1].model[J1].age;
+	  Ey = (newtrack[i-1].model[J1].V - V0) / dV;
+	}
+	DV = newtrack[i].model[j].V - Vs;
+	dM = newtrack[i].mass - Ms;
+	dA = newtrack[i].model[j].age - As;
+	for (k = Sy; (k >= Ey) && (k >= 0); k--) {
+	  v = k*dV + V0;
+	  m = (v - Vs) * dM / DV + Ms;
+	  fits_set_matrix_value (&mass_i, Sx, k, m);
+	  a = (v - Vs) * dA / DV + As;
+	  fits_set_matrix_value (&age_i, Sx, k, a);
+	}
+      }
+    }
+  }
+*/
Index: /tags/start/Ohana/src/misc/src/string.c
===================================================================
--- /tags/start/Ohana/src/misc/src/string.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/string.c	(revision 12606)
@@ -0,0 +1,113 @@
+# include <ohana.h>
+
+/* Strip whitespace from the start and end of STRING. */
+int stripwhite (string)
+char *string;
+{
+  int i;
+
+  if (string == (char *) NULL)
+    return (FALSE);
+
+  for (i = 0; whitespace (string[i]); i++);
+  if (i) memmove (string, string + i, strlen(string+i)+1);
+  for (i = strlen (string) - 1; (i > 0) && whitespace (string[i]); i--);
+  string[++i] = 0;
+  return (i);
+
+}
+
+/* create a new string from this string */
+char *strcreate (string)
+char *string;
+{
+
+  char *line;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+  
+  ALLOCATE (line, char, MAX (1, strlen(string)) + 1);
+  line = strcpy (line, string);
+
+  return (line);
+
+}
+
+/* create a new string of length n from this string */
+char *strncreate (string, n)
+char *string;
+int   n;
+{
+
+  char *line;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+  
+  ALLOCATE (line, char, n + 1);
+  memmove (line, string, n);
+  line[n] = 0;
+  return (line);
+
+}
+
+int scan_line (f, line) 
+FILE *f;
+char line[];
+{
+
+  int i, status;
+  char c;
+  
+  status = EOF + 1;
+  
+  for (i = 0, c = 0; (c != '\n') && (status != EOF); i++) {
+    status = fscanf (f, "%c", &c);
+    line[i] = c;
+  }
+  line[i - 1] = 0;  /* this could make things crash! */
+
+  if (i > 1) {
+    status = EOF + 1;
+  }
+
+  return (status);
+
+}
+
+char *_parse_nextword(string)
+char *string;
+{
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (; isspace (*string); string++);
+  for (; (*string != 0) && !isspace (*string); string++);
+  for (; isspace (*string); string++);
+  return (string);
+}
+
+int dparse (X, NX, line)
+double *X;
+int NX;
+char *line;
+{
+
+  int i;
+  char *word;
+  char *ptr;
+
+  word = line;
+  for (i = 0; i < NX - 1; i++)
+    word = _parse_nextword (word);
+
+  *X = strtod (word, &ptr);
+  if (ptr == word)
+    return (FALSE);
+  else {
+    if (word[0] == '-') 
+      return (-1);
+    else
+      return (1);
+  }
+}
+
+
Index: /tags/start/Ohana/src/misc/src/striphead.c
===================================================================
--- /tags/start/Ohana/src/misc/src/striphead.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/striphead.c	(revision 12606)
@@ -0,0 +1,64 @@
+# include <ohana.h>
+
+main (argc, argv) 
+int argc;
+char *argv[];
+{
+
+  int i, j, status, N, FORCE;
+  char head[1000];
+  Header header;
+  char *p;
+  FILE *f;
+
+  if (get_argument (argc, argv, "-help") || get_argument (argc, argv, "-h")) {
+    fprintf (stderr, "USAGE: %s [-f] (filenames)\n", argv[0]);
+    exit (0);
+  }
+
+  if (N = get_argument (argc, argv, "-f")) {
+    remove_argument (N, &argc, argv);
+    FORCE = TRUE;
+  }
+  else 
+    FORCE = FALSE;
+  
+  if (argc == 1) {
+    fprintf (stderr, "USAGE: %s [-f] (filenames)\n", argv[0]);
+    exit (0);
+  }
+
+  for (i = 1; i < argc; i++) {
+    
+    strcpy (head, argv[i]);
+    if (strrchr(head, '.') !=NULL)
+      strcpy(strrchr(head, '.'), ".head");
+    else 
+      strcat(head, ".head");
+    
+    if (!FORCE) {
+      f = fopen (head, "r");
+      if (f != NULL) {
+	fprintf (stderr, "header file exists for %s, skipping\n", argv[i]);
+	fclose (f);
+	continue;
+      }
+    }
+    
+    if (!fits_read_header (argv[i], &header)) {
+      fprintf (stderr, "failed to open file %s\n", argv[i]);
+      continue;
+    }
+    
+    for (j = 79; j < header.size; j+= 80) {
+      header.buffer[j] = 10;
+    }
+
+    if (!fits_write_header (head, &header)) {
+      fprintf (stderr, "failed to write file %s\n", head);
+      continue;
+    }
+    
+    fits_free_header (&header);
+  }
+}
Index: /tags/start/Ohana/src/misc/src/test.c
===================================================================
--- /tags/start/Ohana/src/misc/src/test.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/test.c	(revision 12606)
@@ -0,0 +1,74 @@
+# include <stdio.h>
+# include <fitsio.h>
+# include <math.h>
+# include <malloc.h>
+# include <string.h>
+# include <sys/time.h>
+# include <stdarg.h>
+# include <stdlib.h>
+# include <readline/readline.h>
+# include <readline/history.h>
+
+# define TRUE (1)
+# define FALSE (0)
+# define SIGN(X)  (((X) == 0) ? 0 : ((fabs((double)(X))) / (X)))
+# define ROUND(X) ((int) ((X) + 0.5*SIGN(X)))
+# define SQR(X)   (double) (((double)(X))*((double)(X)))
+# define SQ(X)    (double) (((double)(X))*((double)(X)))
+# define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+# define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+# define SWAP(X,Y) {double tmp=(X); (X) = (Y); (Y) = tmp;}
+# define ISVAR(a) (isalnum (a) || (a == '.') || (a == '_'))
+# define ISWORD(a,q) ((q) ? (a != '"') : (isalnum(a) || (a == '.') || (a == '_') || (a == '-')))
+# define ISNUM(c) (isdigit(c) || (c == '-') || (c == '.'))
+
+/* Strip whitespace from the start and end of STRING. */
+int stripwhite (string)
+char *string;
+{
+  int i;
+
+  if (string == (char *) NULL)
+    return (0);
+
+  for (i = 0; whitespace (string[i]); i++);
+
+  if (i)
+    strcpy (string, string + i);
+
+  i = strlen (string) - 1;
+
+  for (; (i > 0) && whitespace (string[i]); i--);
+
+  string[++i] = 0;
+
+  return (i);
+
+}
+
+void main (int argc, char **argv) {
+
+  int i, j, nbytes;
+  Header header;
+  char filename[1000], buffer[1000];
+  char *p;
+
+  /* fprintf (stderr, "starting\n"); */
+  while (fscanf (stdin, "%s", filename) != EOF) {
+    if (!fits_read_header (filename, &header)) continue;
+    fprintf (stdout, "%s  ", filename);
+    for (i = 1; i < argc; i++) {
+      bzero (buffer, 1000);
+      fits_scan (&header, argv[i], "%s", 1, buffer);
+      stripwhite (buffer);
+      fprintf (stdout, "%s  ", buffer);
+    }
+    fprintf (stdout, "\n");
+
+    fits_free_header (&header);
+
+  }
+
+}
+
+
Index: /tags/start/Ohana/src/misc/src/testcat.c
===================================================================
--- /tags/start/Ohana/src/misc/src/testcat.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/testcat.c	(revision 12606)
@@ -0,0 +1,96 @@
+# include "addstar.h"
+# include "ohana.h"
+
+main (int argc, char **argv) {
+  
+  Catalog catalog;
+  char filename[64], line[64];
+  int Nitems, nitems;
+  int i, Nmeas, Nmiss;
+  FILE *f;
+  struct tm *local;
+  struct timeval now;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: testcat (catname)\n");
+    exit (1);
+  }
+
+  /* read catalog header */
+  if (!fits_read_header (argv[1], &catalog.header)) {
+    fprintf (stderr, "can't find file %s\n", argv[1]);
+    exit (1);
+  } else {
+    strcpy (filename, argv[1]);
+  }
+
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't open catalog file: %s\n", filename);
+    exit (1);
+  }
+  fseek (f, catalog.header.size, SEEK_SET); 
+
+  /** find number of stars, measurements **/
+  catalog.Nmissing = catalog.Naverage = catalog.Nmeasure = 0;
+  fits_scan (&catalog.header, "NSTARS", "%d", 1, &catalog.Naverage);
+  fits_scan (&catalog.header, "NMEAS", "%d", 1, &catalog.Nmeasure);
+  fits_scan (&catalog.header, "NMISS", "%d", 1, &catalog.Nmissing);
+  fprintf (stderr, "loading data for %d %d %d\n", catalog.Naverage, catalog.Nmeasure, catalog.Nmissing);
+  ALLOCATE (catalog.average, Average, MAX (catalog.Naverage, 1));
+  ALLOCATE (catalog.measure, Measure, MAX (catalog.Nmeasure, 1));
+  ALLOCATE (catalog.missing, Missing, MAX (catalog.Nmissing, 1));
+  if (catalog.Naverage == 0) {
+    fprintf (stderr, "no stars yet in catalog %s\n", argv[1]);
+    fclose (f);
+    exit (0);
+  }
+
+  /* read average values */
+  Nitems = catalog.Naverage;
+  nitems = Fread (catalog.average, sizeof(Average), Nitems, f, "average");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to read averages from catalog file: %d read != %d want\n", nitems, Nitems);
+    fclose (f);
+    exit (1);
+  }
+  
+  /* read measurements */
+  Nitems = catalog.Nmeasure;
+  nitems = Fread (catalog.measure, sizeof(Measure), Nitems, f, "measure");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to read measures from catalog file: %d read != %d want\n", nitems, Nitems);
+    fclose (f);
+    exit (1);
+  }
+  
+  /* read missing */
+  Nitems = catalog.Nmissing;
+  nitems = Fread (catalog.missing, sizeof(Missing), Nitems, f, "missing");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to read missings from catalog file: %d read != %d want\n", nitems, Nitems);
+    fclose (f);
+    exit (1);
+  }
+  
+  if (VERBOSE) fprintf (stderr, "read %d stars from catalog file %s (%d measurements, %d missing)\n", 
+	   catalog.Naverage, argv[1], catalog.Nmeasure, catalog.Nmissing);
+
+  for (i = Nmeas = Nmiss = 0; i < catalog.Naverage; i++) {
+    Nmeas += catalog.average[i].Nm; 
+    Nmiss += catalog.average[i].Nn; 
+  }
+  if ((Nmeas != catalog.Nmeasure) || (Nmiss != catalog.Nmissing)) {
+    fprintf (stderr, "ERROR: data in catalog %s is corrupt, sums don't check\n");
+    fprintf (stderr, "ERROR: Nmeas: %d, %d\n", Nmeas, catalog.Nmeasure);
+    fprintf (stderr, "ERROR: Nmiss: %d, %d\n", Nmiss, catalog.Nmissing);
+    exit (1);
+  }
+
+  fclose (f);
+
+  fprintf (stderr, "catalog %s looks ok\n", argv[1]);
+  exit (0);
+
+}
+
Index: /tags/start/Ohana/src/misc/src/usmaeder.c
===================================================================
--- /tags/start/Ohana/src/misc/src/usmaeder.c	(revision 12606)
+++ /tags/start/Ohana/src/misc/src/usmaeder.c	(revision 12606)
@@ -0,0 +1,191 @@
+# include <ohana.h>
+
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+
+  Header mass_h, age_h, UV_h, V_h;
+  Matrix mass_i, age_i, UV_i, V_i;
+  int x, y, X, Y, X0, X1, Y0, Y1, NAGE, NMASS, N;
+  double ldA, lAo, ldM, lMo, age, mass;
+  double v, uv, UV0, DUV, V0, DV, slope_x, slope_y, tmp;
+  
+  lAo =   0.0;
+  ldA =   0.01;
+  NAGE =  320;
+  if (N = get_argument (argc, argv, "-age")) {
+    remove_argument (N, &argc, argv);
+    lAo = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    ldA = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    NAGE = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  lMo = -0.1;
+  ldM =  0.05;
+  NMASS = 50;
+  if (N = get_argument (argc, argv, "-mass")) {
+    remove_argument (N, &argc, argv);
+    lMo = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    ldM = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    NMASS = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE %s massfile agefile colorfile magfile\n", argv[0]);
+    fprintf (stderr, "  options:\n");
+    fprintf (stderr, "  [-mass lMo ldM NMASS]\n");
+    fprintf (stderr, "  [-age  lAo ldA NAGE]\n");
+    exit (0);
+  }
+
+  fits_read_header (argv[1], &mass_h);
+  fits_read_matrix (argv[1], &mass_i);
+  fits_read_header (argv[2], &age_h);
+  fits_read_matrix (argv[2], &age_i); 
+
+  fits_scan (&mass_h, "RA_O",  "%lf", 1, &UV0);
+  fits_scan (&mass_h, "RA_X",  "%lf", 1, &DUV);
+  fits_scan (&mass_h, "DEC_O", "%lf", 1, &V0);
+  fits_scan (&mass_h, "DEC_Y", "%lf", 1, &DV);
+
+  V_h.bitpix = -32;
+  V_h.Naxes = 2;
+  V_h.Naxis[0] = NAGE;
+  V_h.Naxis[1] = NMASS;
+  V_h.bzero = 0.0;
+  V_h.bscale = 1.0;
+  V_h.unsign = FALSE;
+  V_h.extend = FALSE;
+
+  UV_h.bitpix = -32;
+  UV_h.Naxes = 2;
+  UV_h.Naxis[0] = NAGE;
+  UV_h.Naxis[1] = NMASS;
+  UV_h.bzero = 0.0;
+  UV_h.bscale = 1.0;
+  UV_h.unsign = FALSE;
+  UV_h.extend = FALSE;
+
+  fits_create_header (&V_h);
+  fits_create_matrix (&V_h, &V_i);
+  fits_create_header (&UV_h);
+  fits_create_matrix (&UV_h, &UV_i);
+  fprintf (stderr, "created FITS buffers\n");
+
+  fits_modify (&V_h, "RA_O", "%lf", 1, lAo);
+  fits_modify (&V_h, "RA_X", "%lf", 1, ldA);
+  fits_modify (&V_h, "RA_Y", "%lf", 1, 0.0);
+  fits_modify (&V_h, "DEC_O", "%lf", 1, lMo);
+  fits_modify (&V_h, "DEC_Y", "%lf", 1, ldM);
+  fits_modify (&V_h, "DEC_X", "%lf", 1, 0.0);
+
+  fits_modify (&UV_h, "RA_O",  "%lf", 1, lAo);
+  fits_modify (&UV_h, "RA_X",  "%lf", 1, ldA);
+  fits_modify (&UV_h, "RA_Y",  "%lf", 1, 0.0);
+  fits_modify (&UV_h, "DEC_O", "%lf", 1, lMo);
+  fits_modify (&UV_h, "DEC_Y", "%lf", 1, ldM);
+  fits_modify (&UV_h, "DEC_X", "%lf", 1, 0.0);
+
+  /* the value of 100 is hard wired in this and the others as a bad color */
+
+  for (x = 0; x < NAGE; x++) {
+    for (y = 0; y < NMASS; y++) {
+      fits_set_matrix_value (&UV_i, x, y, 100.0); 
+      fits_set_matrix_value (&V_i, x, y, 100.0); 
+    }
+  }
+
+  for (x = 0; x < mass_h.Naxis[0]; x++) {
+    fprintf (stderr, ".");
+    for (y = 0; y < mass_h.Naxis[1]; y++) {
+      mass = fits_get_matrix_value (&mass_i, x, y);
+      age = fits_get_matrix_value (&age_i, x, y); 
+      if (mass > 0) {
+	X = (log10(age) - lAo) / ldA;
+	Y = (log10(mass) - lMo) / ldM;
+	if ((X >= 0) && (X < NAGE) &&
+	    (Y >= 0) && (Y < NMASS)) {
+	  uv = x*DUV + UV0;
+	  v  = y*DV + V0;
+	  fits_set_matrix_value (&UV_i, X, Y, uv); 
+	  fits_set_matrix_value (&V_i, X, Y, v); 
+	}
+      }
+    }
+  }
+  fprintf (stderr, "\n");
+
+  /* fix the holes */
+  for (x = 0; x < NAGE; x++) {
+    for (y = 0; y < NMASS; y++) {
+      uv = fits_get_matrix_value (&UV_i, x, y);
+      if (uv == 100.0) {
+	/* find neighbors up and down */
+	X1 = NAGE; Y1 = NMASS;
+	X0 = Y0 = -1;
+	for (X = x + 1; X < NAGE; X++) {
+	  if ((fits_get_matrix_value (&UV_i, X, y)) != 100.0) {
+	    X1 = X;
+	    break;
+	  }
+	}
+	for (X = x - 1; X >= 0; X--) {
+	  if ((fits_get_matrix_value (&UV_i, X, y)) != 100.0) {
+	    X0 = X;
+	    break;
+	  }
+	}
+	for (Y = y + 1; Y < NMASS; Y++) {
+	  if ((fits_get_matrix_value (&UV_i, x, Y)) != 100.0) {
+	    Y1 = Y;
+	    break;
+	  }
+	}
+	for (Y = y - 1; Y >= 0; Y--) {
+	  if ((fits_get_matrix_value (&UV_i, x, Y)) != 100.0) {
+	    Y0 = Y;
+	    break;
+	  }
+	}
+	slope_x = slope_y = 100000.0;
+	if ((X1 < NAGE) && (X0 > -1)) {
+	  slope_x = (fits_get_matrix_value (&UV_i, X1, y) - fits_get_matrix_value (&UV_i, X0, y)) / (X1 - X0);
+	}
+	if ((Y1 < NMASS) && (Y0 > -1)) {
+	  slope_y = (fits_get_matrix_value (&UV_i, x, Y1) - fits_get_matrix_value (&UV_i, x, Y0)) / (Y1 - Y0);
+	}
+	if ((fabs(slope_x) < fabs(slope_y)) && (slope_x != 100000.0)) {
+	  uv = (x - X0) * slope_x + fits_get_matrix_value (&UV_i, X0, y);
+	  tmp = (fits_get_matrix_value (&V_i, X1, y) - fits_get_matrix_value (&V_i, X0, y)) / (X1 - X0);
+	  v  = (x - X0) * tmp + fits_get_matrix_value (&V_i, X0, y);
+	  fits_set_matrix_value (&UV_i, x, y, uv); 
+	  fits_set_matrix_value (&V_i, x, y, v); 
+	}	  
+	if ((fabs(slope_x) >= fabs(slope_y)) && (slope_y != 100000.0)) {
+	  uv = (y - Y0) * slope_y + fits_get_matrix_value (&UV_i, x, Y0);
+	  tmp = (fits_get_matrix_value (&V_i, x, Y1) - fits_get_matrix_value (&V_i, x, Y0)) / (Y1 - Y0);
+	  v  = (y - Y0) * tmp + fits_get_matrix_value (&V_i, x, Y0);
+	  fits_set_matrix_value (&UV_i, x, y, uv); 
+	  fits_set_matrix_value (&V_i, x, y, v); 
+	}	  
+      }
+    }
+  }
+	
+
+
+  fits_write_header (argv[3], &V_h);
+  fits_write_matrix (argv[3], &V_i);
+  fits_write_header (argv[4], &UV_h);
+  fits_write_matrix (argv[4], &UV_i);
+
+}
+
Index: /tags/start/Ohana/src/nightd/Makefile
===================================================================
--- /tags/start/Ohana/src/nightd/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/nightd/Makefile	(revision 12606)
@@ -0,0 +1,62 @@
+include ../../Configure
+HOME 	=	$(ROOT)/src/nightd
+PROGRAM =       nightd
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#  
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lFITS -lohana -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS)
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+NIGHTD = \
+$(SRC)/nightd.$(ARCH).o 	$(SRC)/ConfigInit.$(ARCH).o 	\
+$(SRC)/DoCommand.$(ARCH).o 	$(SRC)/GetStatus.$(ARCH).o 	\
+$(SRC)/SetSignals.$(ARCH).o 	$(SRC)/StartUp.$(ARCH).o 	\
+$(SRC)/misc.$(ARCH).o
+
+OBJ = $(NIGHTD)
+
+default: $(PROGRAM)
+
+$(DESTBIN)/srt: $(DESTBIN)/$(PROGRAM)
+	cp $(DESTBIN)/$(PROGRAM) $(DESTBIN)/srt
+
+$(DESTBIN)/ert: $(DESTBIN)/$(PROGRAM)
+	cp $(DESTBIN)/$(PROGRAM) $(DESTBIN)/ert
+
+$(NIGHTD): $(INC)/nightd.h
+
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM) $(DESTBIN)/srt $(DESTBIN)/ert
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:	
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
+
+
Index: /tags/start/Ohana/src/nightd/include/nightd.h
===================================================================
--- /tags/start/Ohana/src/nightd/include/nightd.h	(revision 12606)
+++ /tags/start/Ohana/src/nightd/include/nightd.h	(revision 12606)
@@ -0,0 +1,44 @@
+# include <ohana.h>
+# include <loneos.h>
+# include <signal.h>
+# include <errno.h>
+
+FILE *LogFile;
+char *Program;
+
+char logfile[256];
+char **MainCommand;
+char **InitCommand;
+char **DoneCommand;
+
+char TestCommand[256];
+
+char DateStr[256];
+char TimeStr[256];
+
+char PIDFile[256];
+
+float NightStart;
+float NightStop;
+
+int SuspendAction;
+
+int ConfigInit (int *argc, char **argv);
+void LoadConfig (int sig);
+int dms_to_ddd (double *Value, char *string);
+int SetPID (pid_t *Xpid, char *Xuser, char *Xmachine);
+int GetDateTime (char *datestr, char *timestr, float *time);
+int WaitForMinute ();
+int GetStatus ();
+int ResetConfig ();
+int SendShutdown ();
+int StartUp ();
+int SetSignals ();
+void ToggleSuspend (int sig);
+void Shutdown (int sig);
+int Expose (char *filename);
+int vsystem (char *line);
+char *ExpandWords (char *line);
+
+int PERIOD;
+int TIMEOUT;
Index: /tags/start/Ohana/src/nightd/scripts/ertrc
===================================================================
--- /tags/start/Ohana/src/nightd/scripts/ertrc	(revision 12606)
+++ /tags/start/Ohana/src/nightd/scripts/ertrc	(revision 12606)
@@ -0,0 +1,29 @@
+
+# multiple entries are allowed for each 
+# command line, MAIN, INIT, DONE. they 
+# are performed in sequence
+
+# there are run at the start of the night
+INIT_COMMAND el_plots init
+INIT_COMMAND elixir.reload sextract
+INIT_COMMAND elixir.reload imstats
+
+MAIN_COMMAND gettemps
+MAIN_COMMAND el_plots plot
+MAIN_COMMAND elixir.link
+
+# these are run at the end of the night
+DONE_COMMAND el_plots done
+DONE_COMMAND elixir.launch mkdetrend 
+
+# PID_FILE /h/eugene/skyprobe/ert.pid
+# LOG_FILE /h/eugene/skyprobe/ert.log
+
+PID_FILE /data/milo/elixir/log/ert.pid
+LOG_FILE /data/milo/elixir/log/ert.log
+
+NIGHT_START 18:00
+NIGHT_STOP  06:00
+
+PERIOD 180
+TIMEOUT 360
Index: /tags/start/Ohana/src/nightd/scripts/skyproberc
===================================================================
--- /tags/start/Ohana/src/nightd/scripts/skyproberc	(revision 12606)
+++ /tags/start/Ohana/src/nightd/scripts/skyproberc	(revision 12606)
@@ -0,0 +1,20 @@
+
+HOME      /h/skyprobe
+
+DATA_PATH $HOME/data
+PID_FILE  $HOME/.skyprobe.pid
+LOG_FILE  $HOME/sp_daemon.log
+
+CCD_TEMP -20
+EXPTIME   30
+
+INIT_COMMAND sp_command cool $CCD_TEMP
+INIT_COMMAND sp_command init $DATA_PATH/&DATE
+MAIN_COMMAND sp_command expose $EXPTIME $DATA_PATH/&DATE/sp_&DATE_&TIME.fits
+DONE_COMMAND sp_command warm
+
+NIGHT_START 18:00
+NIGHT_STOP  06:00
+
+PERIOD 60
+TIMEOUT 300
Index: /tags/start/Ohana/src/nightd/scripts/srtrc
===================================================================
--- /tags/start/Ohana/src/nightd/scripts/srtrc	(revision 12606)
+++ /tags/start/Ohana/src/nightd/scripts/srtrc	(revision 12606)
@@ -0,0 +1,21 @@
+
+# wrap the commands (init, main, done) in a single script
+# this will let the config info come from the config system
+
+INIT_COMMAND sp_plots init
+
+MAIN_COMMAND sp_plots plot 
+
+DONE_COMMAND sp_plots done &DATE
+
+PID_FILE /data/milo/elixir/log/srt.pid
+LOG_FILE /data/milo/elixir/log/srt.log
+
+# PID_FILE /h/eugene/skyprobe/skyprobe.pid
+# LOG_FILE /h/eugene/skyprobe/skyprobe.log
+
+NIGHT_START 18:00
+NIGHT_STOP  06:00
+
+PERIOD 60
+TIMEOUT 300
Index: /tags/start/Ohana/src/nightd/src/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/nightd/src/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/nightd/src/ConfigInit.c	(revision 12606)
@@ -0,0 +1,115 @@
+# include "nightd.h"
+
+static char *file;
+
+int ConfigInit (int *argc, char **argv) {
+
+  char *home;
+
+  /*** load configuration info ***/
+  home = getenv ("HOME");
+  if (home == (char *) NULL) {
+    fprintf (stderr, "can't determine HOME, please set\n");
+    exit (2);
+  }
+  ALLOCATE (file, char, strlen (home) + strlen (Program) + 10);
+
+  sprintf (file, "%s/.%src", home, Program);
+  LoadConfig (SIGKILL);
+
+}
+
+void LoadConfig (int sig) {
+
+  int i, Ncmd, found;
+  char *config;
+  char line[256];
+  double tmp;
+
+  if (sig == SIGUSR1) {
+    fprintf (LogFile, "re-loading config file %s\n", file);
+    fflush (LogFile);
+  }
+
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (LogFile, "can't find configuration file %s\n", file);
+    exit (2);
+  }
+
+  /* need to check for error status */
+  ScanConfig (config, "PERIOD",                 "%d", 0, &PERIOD);
+  ScanConfig (config, "TIMEOUT",                "%d", 0, &TIMEOUT);
+
+  /* load list of InitCommands */
+  found = TRUE;
+  Ncmd = 10;
+  ALLOCATE (InitCommand, char *, Ncmd);
+  for (i = 0; found; i++) {
+    ALLOCATE (InitCommand[i], char, 256);
+    bzero (InitCommand[i], 256);
+    found = ScanConfig (config, "INIT_COMMAND", "%s", i + 1, InitCommand[i]);
+    if (i == Ncmd - 1) {
+      Ncmd += 10;
+      REALLOCATE (InitCommand, char *, Ncmd);
+    }      
+  }
+  
+  /* load list of MainCommands */
+  found = TRUE;
+  Ncmd = 10;
+  ALLOCATE (MainCommand, char *, Ncmd);
+  for (i = 0; found; i++) {
+    ALLOCATE (MainCommand[i], char, 256);
+    bzero (MainCommand[i], 256);
+    found = ScanConfig (config, "MAIN_COMMAND", "%s", i + 1, MainCommand[i]);
+    if (i == Ncmd - 1) {
+      Ncmd += 10;
+      REALLOCATE (MainCommand, char *, Ncmd);
+    }      
+  }
+
+  /* load list of DoneCommands */
+  found = TRUE;
+  Ncmd = 10;
+  ALLOCATE (DoneCommand, char *, Ncmd);
+  for (i = 0; found; i++) {
+    ALLOCATE (DoneCommand[i], char, 256);
+    bzero (DoneCommand[i], 256);
+    found = ScanConfig (config, "DONE_COMMAND", "%s", i + 1, DoneCommand[i]);
+    if (i == Ncmd - 1) {
+      Ncmd += 10;
+      REALLOCATE (DoneCommand, char *, Ncmd);
+    }      
+  }
+
+  ScanConfig (config, "PID_FILE",               "%s", 0, PIDFile);
+  ScanConfig (config, "LOG_FILE",               "%s", 0, logfile);
+    
+  ScanConfig (config, "NIGHT_START",            "%s", 0, line);
+  if (!dms_to_ddd (&tmp, line)) { 
+    fprintf (LogFile, "format error in NIGHT_START\n");
+    exit (2);
+  } 
+  NightStart = tmp;
+  if (NightStart < 12.0) {
+    fprintf (LogFile, "warning: night starts before noon!\n");
+    fprintf (LogFile, "if you live in the Arctic Circle (or Antarctic), you might need to adjust the program\n");
+    exit (2);
+  }
+  ScanConfig (config, "NIGHT_STOP",             "%s", 0, line);
+  if (!dms_to_ddd (&tmp, line)) { 
+    fprintf (LogFile, "format error in NIGHT_STOP\n");
+    exit (2);
+  } 
+  NightStop = tmp;
+  if (NightStop > 12.0) {
+    fprintf (LogFile, "warning: night ends after noon!\n");
+    fflush (LogFile);
+  }
+  if (NightStop < 12.0) NightStop += 24.0;
+
+  /* check format of command calls: must have a certain set of %d, %s, etc */
+  free (config);
+
+}
Index: /tags/start/Ohana/src/nightd/src/DoCommand.c
===================================================================
--- /tags/start/Ohana/src/nightd/src/DoCommand.c	(revision 12606)
+++ /tags/start/Ohana/src/nightd/src/DoCommand.c	(revision 12606)
@@ -0,0 +1,21 @@
+# include "nightd.h"
+
+/* special words:
+   word    variable
+   DATE    DateStr
+   TIME    TimeStr
+*/
+
+int DoCommand (char *command, char *name) {
+  
+  int status;
+  char *line;
+
+  line = strcreate (command);
+  line = ExpandWords (line);
+  if (pcommand (line, TIMEOUT)) {
+    fprintf (LogFile, "error running %s command\n", name);
+    fflush (LogFile);
+  }
+  free (line);
+}
Index: /tags/start/Ohana/src/nightd/src/GetStatus.c
===================================================================
--- /tags/start/Ohana/src/nightd/src/GetStatus.c	(revision 12606)
+++ /tags/start/Ohana/src/nightd/src/GetStatus.c	(revision 12606)
@@ -0,0 +1,56 @@
+# include "nightd.h"
+
+int GetStatus () {
+
+  char user[256], machine[256];
+  pid_t pid;
+
+  if (SetPID (&pid, user, machine)) {
+    fprintf (stderr, "%s is not running\n", Program);
+    unlink (PIDFile);
+    exit (1);
+  }
+
+  fprintf (stderr, "%s apparently running:\n\n", Program);
+  fprintf (stderr, "  machine: %s\n", machine);
+  fprintf (stderr, "  user: %s\n", user);
+  fprintf (stderr, "  PID: %d\n", pid);
+  fprintf (stderr, "  remove %s if %s has died unexpectedly\n", PIDFile, Program);
+  exit (0);
+
+}
+  
+int ResetConfig () {
+
+  char user[256], machine[256], line[256];
+  pid_t pid;
+
+  if (SetPID (&pid, user, machine)) {
+    fprintf (stderr, "%s is not running\n", Program);
+    unlink (PIDFile);
+    exit (1);
+  }
+
+  sprintf (line, "rsh %s kill -USR1 %d", machine, pid);
+  system (line);
+  exit (0);
+
+}
+  
+int SendShutdown () {
+
+  char user[256], machine[256], line[256];
+  pid_t pid;
+
+  if (SetPID (&pid, user, machine)) {
+    fprintf (stderr, "%s is not running\n", Program);
+    unlink (PIDFile);
+    exit (1);
+  }
+
+  sprintf (line, "rsh %s kill -TERM %d", machine, pid);
+  system (line);
+  exit (0);
+
+}
+  
Index: /tags/start/Ohana/src/nightd/src/SetSignals.c
===================================================================
--- /tags/start/Ohana/src/nightd/src/SetSignals.c	(revision 12606)
+++ /tags/start/Ohana/src/nightd/src/SetSignals.c	(revision 12606)
@@ -0,0 +1,28 @@
+# include "nightd.h"
+
+int SetSignals () {
+
+  signal (SIGTERM, Shutdown);
+  signal (SIGUSR1, LoadConfig);
+  signal (SIGUSR2, ToggleSuspend);
+
+}
+
+void ToggleSuspend (int sig) {
+
+  SuspendAction = SuspendAction ^ TRUE;
+
+}
+
+void Shutdown (int sig) {
+
+  fprintf (LogFile, "shutting down skyprobed\n");
+  fflush (LogFile);
+
+  if (unlink (PIDFile)) {
+    fprintf (LogFile, "error deleting PID File %s\n", PIDFile);
+    exit (1);
+  }   
+
+  exit (0);
+}
Index: /tags/start/Ohana/src/nightd/src/StartUp.c
===================================================================
--- /tags/start/Ohana/src/nightd/src/StartUp.c	(revision 12606)
+++ /tags/start/Ohana/src/nightd/src/StartUp.c	(revision 12606)
@@ -0,0 +1,76 @@
+# include "nightd.h"
+
+int StartUp () {
+
+  int i;
+  int night, NightTime, status;
+  char user[256], machine[256], filename[256];
+  float time;
+  pid_t pid;
+  struct stat filestat;
+
+  if (!SetPID (&pid, user, machine)) {
+    fprintf (stderr, "%s apparently running:\n\n", Program);
+    fprintf (stderr, "  machine: %s\n", machine);
+    fprintf (stderr, "  user: %s\n", user);
+    fprintf (stderr, "  PID: %d\n", pid);
+    fprintf (stderr, "  remove %s if %s has died unexpectedly\n", PIDFile, Program);
+    exit (1);
+  }
+
+  SetSignals ();
+
+  SuspendAction = FALSE;
+  NightTime = FALSE;
+
+  /* Event Loop */
+  while (1) {
+
+    if (SuspendAction) {
+      usleep (100000);
+      continue;
+    }
+
+    /* events happen at time % PERIOD */
+    WaitForPeriod ();
+
+    /* time should be UTCmidnight - UTCmidnight + 24 */
+    GetDateTime (DateStr, TimeStr, &time);
+    night = (time > NightStart) && (time < NightStop);
+
+    /* start of night */
+    if (night && !NightTime) {
+      NightTime = TRUE;
+      fprintf (LogFile, "beginning of night %s, running INIT commands\n", DateStr);
+      fflush (LogFile);
+      for (i = 0; InitCommand[i][0]; i++) {
+	DoCommand (InitCommand[i], "INIT");
+      }
+    }
+
+    /* end of night */
+    if (!night && NightTime) {
+      NightTime = FALSE;
+      fprintf (LogFile, "end of night %s, running DONE commands\n", DateStr);
+      fflush (LogFile);
+      for (i = 0; DoneCommand[i][0]; i++) {
+	DoCommand (DoneCommand[i], "DONE");
+      }
+    }
+
+    /* main event */
+    if (NightTime) {
+      for (i = 0; MainCommand[i][0]; i++) {
+	DoCommand (MainCommand[i], "MAIN");
+      }
+    }
+
+  }
+}
+
+/* 
+   SuspendAction - loop without operations, used for testing
+   NightStart    - time in hours of beginning of night
+   NightStop     - time in hours of end of night
+   NightTime     - current night / day state
+*/
Index: /tags/start/Ohana/src/nightd/src/misc.c
===================================================================
--- /tags/start/Ohana/src/nightd/src/misc.c	(revision 12606)
+++ /tags/start/Ohana/src/nightd/src/misc.c	(revision 12606)
@@ -0,0 +1,335 @@
+# include "nightd.h"
+# include <time.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <unistd.h>
+# include <fcntl.h>
+
+char **getargs (char *);
+
+/***** convert [-]00:00:00 to 0.0000 ****/
+int dms_to_ddd (double *Value, char *string) {
+  
+  int valid, neg, status;
+  double tmp, value;
+  char *p1, *p2, *px;
+
+  valid = FALSE; 
+  neg = FALSE;
+  stripwhite (string);
+  p1 = string;
+  px = string + strlen(string);
+
+  if (string[0] == '-') { 
+    valid = TRUE; 
+    neg = TRUE;
+    p1 = &string[1];
+  }
+  if (string[0] == '+') { 
+    valid = TRUE; 
+    neg = FALSE;
+    p1 = &string[1];
+  }
+  if (isdigit(string[0])) { 
+    valid = TRUE;
+    p1 = &string[0];
+  }
+  if (!valid) { return (FALSE); }
+
+  status = 1;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) return (FALSE); /* entry not a number: +fred */
+  value = tmp;
+  if (p2 == px) goto escape;    /* entry only number: +1.0 */ 
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:fred */
+  status = 2;
+  value += tmp / 60.0;
+  if (p2 == px) goto escape;    /* entry only number: +1:1 */
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:1:fred */
+  value += tmp / 3600.0;
+
+ escape:
+  if (neg) {
+    value *= -1;
+  }
+  *Value = value;
+
+  return (status);
+}
+
+/* SetPID is always called outside of daemon loop, send errors to stderr */
+int SetPID (pid_t *Xpid, char *Xuser, char *Xmachine) {
+  
+  pid_t pid;
+  char *username, machine[256];
+  FILE *f;
+
+  f = fopen (PIDFile, "r");
+  if (f == (FILE *) NULL) { 
+
+    pid = getpid ();
+    username = getenv ("USER");
+    if (username == (char *) NULL) {
+      fprintf (stderr, "error getting username\n");
+      exit (2);
+    }
+    bzero (machine, 256);
+    if (gethostname (machine, 256)) {
+      fprintf (stderr, "error getting hostname\n");
+      exit (2);
+    }
+
+    f = fopen (PIDFile, "w");
+    if (f == (FILE *) NULL) { 
+      fprintf (stderr, "can't write to PID file %s\n", PIDFile);
+      exit (2);
+    }
+
+    fprintf (f, "PID:     %d\n", pid);
+    fprintf (f, "USER:    %-s\n", username);
+    fprintf (f, "MACHINE: %-s\n", machine);
+    fclose (f);
+    return (TRUE); 
+  }
+
+  fscanf (f, "%*s %d", Xpid);
+  fscanf (f, "%*s %s", Xuser);
+  fscanf (f, "%*s %s", Xmachine);
+  fclose (f);
+  return (FALSE);
+}
+
+/* date is the UT date at 09:00 local time for day starting at 12:00 */
+int GetDateTime (char *datestr, char *timestr, float *time) {
+
+  struct tm *local, *gmt;
+  struct timeval now;
+  unsigned long tsec, tref;
+  int dsec;
+  float hour;
+
+  gettimeofday (&now, (struct timezone *) NULL);
+  tsec = now.tv_sec;
+  local = localtime (&tsec);
+
+  sprintf (timestr, "%02dh%02dm", local[0].tm_hour, local[0].tm_min);
+  hour = local[0].tm_hour + local[0].tm_min / 60.0 + local[0].tm_sec / 3600.0;
+  if (hour < 12) hour += 24.0;
+
+  dsec = 3600.0*(33.0 - hour);
+  tref = tsec + dsec;
+
+  gmt = gmtime (&tref);
+
+  sprintf (datestr, "%04d%02d%02d", 1900 + gmt[0].tm_year, gmt[0].tm_mon + 1, gmt[0].tm_mday);
+  *time = hour;
+  
+  return (TRUE);
+}
+
+int WaitForPeriod () {
+
+  int Nsec, tsec;
+  struct timeval now;
+  struct tm *local;
+  
+  gettimeofday (&now, (struct timezone *) NULL);
+  Nsec = PERIOD - (now.tv_sec % PERIOD);
+  sleep (Nsec);
+}
+
+int pcommand (char *line, int timeout) {
+
+  int i, status, eof, done, pidstat, Nread, exit_good, exit_stat;
+  int rfd[2], wfd[2];
+  pid_t pid;
+  char buffer[0x4000];
+  char *file, **arglist;
+
+  /* create pipes for communications */
+  status = pipe (rfd);
+  if (status < 0) {
+    perror ("pipe");
+    return (1);
+  }
+  status = pipe (wfd);
+  if (status < 0) {
+    perror ("pipe");
+    return (1);
+  }
+
+  arglist = getargs (line);
+  pid = fork ();
+  if (!pid) { /* must be child process */
+    dup2 (wfd[0], STDIN_FILENO);
+    dup2 (rfd[1], STDOUT_FILENO);
+    dup2 (rfd[1], STDERR_FILENO);
+    setvbuf (stdin,  (char *) NULL, _IONBF, BUFSIZ); 
+    setvbuf (stdout, (char *) NULL, _IONBF, BUFSIZ);
+    setvbuf (stderr, (char *) NULL, _IONBF, BUFSIZ);
+
+    status = execvp (arglist[0], arglist);
+    fprintf (stderr, "error starting command %s\n", arglist[0]);
+    exit (1);
+  }
+
+  eof = 0x04;
+  write (wfd[1], &eof, 1);
+  close (wfd[1]);
+ 
+  /* ok to close these here? */
+  close (rfd[1]);
+  close (wfd[0]);
+
+  fcntl (rfd[0], F_SETFL, O_NONBLOCK);
+
+  done = FALSE;
+  exit_good = FALSE;
+  for (i = 0; !done && (i < 10*timeout); i++) {
+    Nread = read (rfd[0], buffer, 0x4000);
+    if (Nread > 0) {
+      fwrite (buffer, 1, Nread, LogFile);
+    }
+    fflush (LogFile);
+    pidstat = waitpid (pid, &status, WNOHANG);
+    if (pidstat == pid) { 
+      done = TRUE;
+      exit_good = WIFEXITED (status);
+      exit_stat = WEXITSTATUS (status);
+    } else {
+      usleep (100000);
+    }
+  }
+  
+  if (i == 10*timeout) {
+    exit_good = FALSE;
+    fprintf (LogFile, "timeout on %s\n", arglist[0]);
+    fflush (LogFile);
+    fprintf (stderr, "timeout on %s\n", arglist[0]);
+    kill (pid, SIGKILL);
+
+    done = FALSE;
+    for (i = 0; !done && (i < 2*timeout); i++) {
+      pidstat = waitpid (pid, &status, WNOHANG);
+      if (pidstat == pid) { 
+	done = TRUE;
+      } else {
+	usleep (100000);
+      }
+    }
+  }
+  
+  close (rfd[0]);
+  freeargs (arglist);
+  if (exit_good) return (exit_stat);
+  return (1);
+}
+    
+/* split line into words by spaces, end with NULL */
+char **getargs (char *input) {
+
+  int i;
+  char **args, *line, *p, *e;
+  int Nargs, N, Nchar;
+
+  line = strcreate (input);
+  stripwhite (line);
+  p = line;
+
+  /* count words in line */
+  Nargs = 0;
+  while (*p != 0) {
+    for (; (*p != 0) && !isspace (*p); p++);
+    for (; isspace (*p); p++);
+    Nargs ++;
+  }
+  Nargs ++;
+  ALLOCATE (args, char *, Nargs);
+
+  /* extract words from line */
+  N = 0;
+  e = line;
+  p = line;
+  while (*p != 0) {
+    for (; (*e != 0) && !isspace (*e); e++);
+    Nchar = e - p;
+    ALLOCATE (args[N], char, Nchar + 1);
+    strncpy (args[N], p, Nchar);
+    args[N][Nchar] = 0;
+    p = e;
+    for (; isspace (*p); p++);
+    e = p;
+    N ++;
+  }
+  args[N] = (char *) NULL;
+  free (line);
+  return (args);
+}
+
+int freeargs (char **arglist) {
+
+  int i;
+
+  for (i = 0; arglist[i] != (char *) NULL; i++) {
+    free (arglist[i]);
+  }
+  free (arglist);
+
+}
+
+char *ExpandWords (char *line) {
+
+  int Nin, Nout, Ncpy, NBYTES;
+  char *p1, *p2, word[256], value[256];
+  char *outline;
+  
+  NBYTES = 256;
+  ALLOCATE (outline, char, NBYTES);
+  Nout = 0;
+  Nin  = 0;
+  while ((p1 = strchr (&line[Nin], '&')) != (char *) NULL) {
+    Ncpy = p1 - line - Nin;
+    if (Nout + Ncpy >= NBYTES) {
+      NBYTES = Nout + Ncpy + 256;
+      REALLOCATE (outline, char, NBYTES - 2);
+    }
+    memcpy (&outline[Nout], &line[Nin], Ncpy);
+    Nout += Ncpy;
+    
+    p1 ++;
+    for (p2 = p1; isalnum (*p2); p2++);
+    memcpy (word, p1, p2 - p1);
+    word[p2-p1] = 0;
+    Nin += Ncpy + 1 + p2 - p1;
+    
+    /* substitute value for word */
+    bzero (value, 256);
+    if (!strcasecmp (word, "DATE")) strcpy (value, DateStr);
+    if (!strcasecmp (word, "TIME")) strcpy (value, TimeStr);
+
+    Ncpy = strlen(value);
+    if (Nout + Ncpy >= NBYTES - 2) {
+      NBYTES = Nout + Ncpy + 256;
+      REALLOCATE (outline, char, NBYTES);
+    }    
+    memcpy (&outline[Nout], value, Ncpy);
+    Nout += Ncpy;
+  }
+  Ncpy = strlen(&line[Nin]);
+  if (Nout + Ncpy >= NBYTES - 2) {
+    NBYTES = Nout + Ncpy + 256;
+    REALLOCATE (outline, char, NBYTES);
+  }  
+  memcpy (&outline[Nout], &line[Nin], Ncpy);
+  Nout += Ncpy;
+  outline[Nout] = 0;
+  free (line);
+  return (outline);
+
+}
Index: /tags/start/Ohana/src/nightd/src/nightd.c
===================================================================
--- /tags/start/Ohana/src/nightd/src/nightd.c	(revision 12606)
+++ /tags/start/Ohana/src/nightd/src/nightd.c	(revision 12606)
@@ -0,0 +1,33 @@
+# include "nightd.h"
+
+main (int argc, char **argv) {
+
+  Program = filebasename (argv[0]);
+
+  LogFile = stderr;
+  ConfigInit (&argc, argv);  
+  
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: %s [mode]\n", Program);
+    fprintf (stderr, " mode = start, stop, status, config\n");
+    exit (2);
+  }
+
+  if (!strcasecmp(argv[1], "status")) GetStatus ();
+  if (!strcasecmp(argv[1], "config")) ResetConfig ();
+  if (!strcasecmp(argv[1], "stop"))   SendShutdown ();
+
+  /* execute in background, send output to logfile */
+  LogFile = fopen (logfile, "w");
+  if (LogFile == (FILE *) NULL) {
+    LogFile = stderr;
+    fprintf (LogFile, "can't open Log File %s, writing to stderr\n", logfile);
+  }
+  if (!strcasecmp(argv[1], "start"))  StartUp ();
+  /* if (!strcasecmp(argv[1], "test"))   TestMode (); */
+
+  fprintf (stderr, "invalid %s command %s\n", Program, argv[1]);
+  exit (2);
+
+}
+
Index: /tags/start/Ohana/src/opihi/Makefile
===================================================================
--- /tags/start/Ohana/src/opihi/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/opihi/Makefile	(revision 12606)
@@ -0,0 +1,39 @@
+
+### this is the top-level makefile for the opihi.v2 collection of programs
+
+default: all
+
+### the include file dependencies need to be cleaned up still
+
+mana:  lib.data lib.shell cmd.basic cmd.data cmd.astro
+dimm:  lib.data lib.shell cmd.basic cmd.data cmd.astro
+dvo2:  lib.data lib.shell cmd.basic cmd.data cmd.astro
+dvo:   lib.data lib.shell cmd.basic cmd.data cmd.astro
+sched: lib.data lib.shell cmd.basic cmd.data cmd.astro
+
+LIBS = cmd.basic cmd.data cmd.astro lib.data lib.shell
+
+PROGRAM = mana dvo dvo2 sched dimm 
+
+all:
+	for i in $(PROGRAM); do make $$i || exit; done
+
+install:
+	for i in $(PROGRAM); do make $$i.install || exit; done
+
+clean:
+	for i in $(PROGRAM) $(LIBS); do make $$i.clean || exit; done
+
+#############################################################
+
+$(PROGRAM) $(LIBS):
+	if [ -e "$@" ]; then (cd $@ && make); fi
+
+%.install:
+	if [ -e "$*" ]; then (cd $* && make install); fi
+
+%.clean:
+	if [ -e "$*" ]; then (cd $* && make clean); fi
+
+.PHONY: $(PROGRAM) $(LIBS)
+
Index: /tags/start/Ohana/src/opihi/bin/.cvsignore
===================================================================
--- /tags/start/Ohana/src/opihi/bin/.cvsignore	(revision 12606)
+++ /tags/start/Ohana/src/opihi/bin/.cvsignore	(revision 12606)
@@ -0,0 +1,1 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
Index: /tags/start/Ohana/src/opihi/cmd.astro/Makefile
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/Makefile	(revision 12606)
@@ -0,0 +1,109 @@
+include ../../../Configure
+
+HOME    =       $(ROOT)/src/opihi.v2
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+SDIR    =       $(HOME)/cmd.astro
+#
+DESTBIN =       $(LBIN)
+DESTLIB =       $(LLIB)
+DESTINC =       $(LINC)
+DESTMAN =       $(LMAN)
+HELP    =       $(HOME)/help
+#  
+INCS    =       -I$(INC) -I$(LINC) -I$(XINC)
+LFLAGS  =       -L$(LLIB) -L$(LIB)
+LIBS    =       -lFITS -lsocket -lnsl -lreadline -ltermcap -lohana -lm
+CFLAGS  =       $(INCS)
+CCFLAGS =       $(LIBS) 
+
+# astro user commands ########################
+
+astrocmd = \
+$(SDIR)/init.$(ARCH).o             \
+$(SDIR)/biassub.$(ARCH).o	   \
+$(SDIR)/cgrid.$(ARCH).o		   \
+$(SDIR)/coords.$(ARCH).o	   \
+$(SDIR)/cplot.$(ARCH).o		   \
+$(SDIR)/csystem.$(ARCH).o	   \
+$(SDIR)/ctimes.$(ARCH).o	   \
+$(SDIR)/cval.$(ARCH).o		   \
+$(SDIR)/czplot.$(ARCH).o	   \
+$(SDIR)/drizzle.$(ARCH).o	   \
+$(SDIR)/flux.$(ARCH).o		   \
+$(SDIR)/gauss.$(ARCH).o		   \
+$(SDIR)/getvel.$(ARCH).o	   \
+$(SDIR)/imfit.$(ARCH).o		   \
+$(SDIR)/medianmap.$(ARCH).o	   \
+$(SDIR)/mkgauss.$(ARCH).o	   \
+$(SDIR)/multifit.$(ARCH).o	   \
+$(SDIR)/objload.$(ARCH).o	   \
+$(SDIR)/outline2.$(ARCH).o	   \
+$(SDIR)/outline.$(ARCH).o	   \
+$(SDIR)/polar.$(ARCH).o		   \
+$(SDIR)/precess.$(ARCH).o	   \
+$(SDIR)/profile.$(ARCH).o	   \
+$(SDIR)/region.$(ARCH).o	   \
+$(SDIR)/rotcurve.$(ARCH).o	   \
+$(SDIR)/scale.$(ARCH).o		   \
+$(SDIR)/sexigesimal.$(ARCH).o	   \
+$(SDIR)/spec.$(ARCH).o		   \
+$(SDIR)/star.$(ARCH).o		   \
+$(SDIR)/testfit.$(ARCH).o	   \
+$(SDIR)/transform.$(ARCH).o
+
+libastrocmd:    $(DESTLIB)/libastrocmd.a 
+
+$(LIB)/libastrocmd.$(ARCH).a:   	$(astrocmd)
+
+# utilities #################################################
+$(BIN)/%.$(ARCH):
+	@if [ ! -d $(BIN) ]; then mkdir -p $(BIN); fi
+	$(CC) $^ -o $@ $(LFLAGS) $(LIBS)
+	@echo "compiled $*"
+	@echo ""
+
+$(DESTBIN)/%: $(BIN)/%.$(ARCH) 
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	rm -f $(DESTBIN)/$*
+	cp $(BIN)/$*.$(ARCH) $(DESTBIN)/$*
+	@echo "installed $*"
+	@echo ""
+
+$(LIB)/%.$(ARCH).a:
+	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
+	rm -f $@
+	ar rcv $@ $^ 
+	ranlib $@
+	@echo "compiled library $*"
+	@echo ""
+
+$(DESTLIB)/%.a: $(LIB)/%.$(ARCH).a
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	@echo ""
+	rm -f $@
+	cp $^ $@
+
+lib%.clean:
+	rm -f $(LIB)/lib$*.$(ARCH).a
+	rm -f $($*)
+	@echo ""
+
+%.clean:
+	rm -f $(BIN)/$*.$(ARCH)
+	@echo ""
+
+%.$(ARCH).o : %.c
+	$(CC) $(CFLAGS) -c $*.c -o $@
+
+clean:
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f $(LIB)/*.$(ARCH).a
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+dist: clean
+	rm -f $(BIN)/*
+	rm -f $(LIB)/*
Index: /tags/start/Ohana/src/opihi/cmd.astro/biassub.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/biassub.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/biassub.c	(revision 12606)
@@ -0,0 +1,125 @@
+# include "astro.h"
+
+int biassub (int argc, char **argv) {
+  
+  int i, j, k, N, dir, nlong, nwide, start;
+  int sx, sy, nx, ny, NX, NY, NoVector, Nval;
+  float *V, *DV, dV, *vect, *segment, val;
+  Vector *xvec, *yvec;
+  Buffer *buf;
+
+  NoVector = TRUE;
+  if (N = get_argument (argc, argv, "-v")) {
+    NoVector = FALSE;
+    remove_argument (N, &argc, argv);
+    if ((xvec = SelectVector (argv[N], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    remove_argument (N, &argc, argv);
+    if ((yvec = SelectVector (argv[N], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 7) {
+    fprintf (stderr, "USAGE: biassub <buffer> sx sy nx ny dir [-v N V]\n");
+    fprintf (stderr, "  optional storage of vector and sequence in N and V\n");
+    return (FALSE);
+  }
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  sx = atof (argv[2]);
+  sy = atof (argv[3]);
+  nx = atof (argv[4]);
+  ny = atof (argv[5]);
+  dir = atof (argv[6]);
+  if ((dir != 0) && (dir != 1)) {
+    fprintf (stderr, " dir must be either 0 (x) or 1 (y)\n");
+    return (FALSE);
+  }
+  if (dir) {
+    start = sy;
+    nwide = nx;
+    nlong = ny;
+  } else {
+    start = sx;
+    nwide = ny;
+    nlong = nx;
+  }    
+  fprintf (GetOutfile(), "start: %d %d  size: %d %d\n", sx, sy, nx, ny);
+
+    if ((sx < 0) || (sy < 0) || 
+      (sx+nx > buf[0].matrix.Naxis[0]) || 
+      (sy+ny > buf[0].matrix.Naxis[1])) {
+    fprintf (stderr, "region out of range\n");
+    return (FALSE);
+  }
+
+  ALLOCATE (vect, float, nlong);
+  ALLOCATE (segment, float, nwide);
+
+  NX = buf[0].matrix.Naxis[0];
+  NY = buf[0].matrix.Naxis[1];
+  if (dir) {
+    for (j = sy; j < sy + ny; j++) {
+      V = (float *)(buf[0].matrix.buffer) + j*NX + sx; 
+      for (i = 0; i < nx; i++, V++) {
+	segment[i] = *V;
+      }
+      fsort (segment, nwide);
+      val = Nval = 0;
+      for (k = 0.25*nwide; k <=0.75*nwide; k++) {
+	val += segment[k];
+	Nval ++;
+      }
+      vect[j-sy] = val / Nval;
+    }
+  } else {
+    for (i = 0; i < nx; i++) {
+      V = (float *)(buf[0].matrix.buffer) + sy*NX + sx + i; 
+      for (j = 0; j < ny; j++, V+=NX) {
+	segment[j] = *V;
+      }
+      fsort (segment, nwide);
+      val = Nval = 0;
+      for (k = 0.25*nwide; k <=0.75*nwide; k++) {
+	val += segment[k];
+	Nval ++;
+      }
+      vect[i] = val / Nval;
+    }
+  }
+
+  if (!NoVector) {
+    xvec[0].Nelements = yvec[0].Nelements = nlong;
+    REALLOCATE (xvec[0].elements, float, nlong);
+    REALLOCATE (yvec[0].elements, float, nlong);
+    for (i = 0; i < nlong; i++) {
+      xvec[0].elements[i] = i + start;
+      yvec[0].elements[i] = vect[i];
+    }
+  }
+
+  if (dir) {
+    /* here we run all the way across in X for the defined Y range */
+    for (j = sy; j < sy + ny; j++) {
+      V = (float *)(buf[0].matrix.buffer) + j*NX; 
+      dV = vect[j];
+      for (i = 0; i < NX; i++, V++) {
+	*V -= dV;
+      }
+    }
+  } else {
+    /* here we run all the way across in Y for the defined X range */
+    for (j = 0; j < NY; j++) {
+      V = (float *)(buf[0].matrix.buffer) + j*NX + sx; 
+      DV = vect;
+      for (i = 0; i < nx; i++, V++, DV++) {
+	*V -= *DV;
+      }
+    }
+  }
+
+  free (segment);
+  free (vect);
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.astro/cgrid.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/cgrid.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/cgrid.c	(revision 12606)
@@ -0,0 +1,403 @@
+# include "astro.h"
+# define CHECKELEMENTS \
+  if (N == NELEMENTS) { \
+    NELEMENTS +=200; \
+    REALLOCATE (Xvec.elements, float, NELEMENTS); \
+    REALLOCATE (Yvec.elements, float, NELEMENTS); \
+  }
+
+int cgrid (int argc, char **argv) {
+  
+  double range, lrange, factor, mantis, power, fmantis;
+  double firstRA, firstDEC, minorRA, minorDEC;
+  double r, d, dR, dD, D;
+  double x, y;
+  Vector Xvec, Yvec;
+  int NorthPole, SouthPole, N, OnPic, LOnPic, status, NELEMENTS, First;
+  Graphdata graphmode;
+  int Ngraph;
+
+  Ngraph = 0;
+  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: cgrid\n");
+    return (FALSE);
+  }
+
+  /* are we plotting one of the poles? */
+  NorthPole = SouthPole = FALSE;
+  status = RD_to_XY (&x, &y, 0.0, 90.0, &graphmode.coords);
+  if ((x >= graphmode.xmin) && (x <= graphmode.xmax) && 
+      (y >= graphmode.ymin) && (y <= graphmode.ymax) && status)
+    NorthPole = TRUE;
+  status = RD_to_XY (&x, &y, 0.0, -90.0, &graphmode.coords);
+  if ((x >= graphmode.xmin) && (x <= graphmode.xmax) && 
+      (y >= graphmode.ymin) && (y <= graphmode.ymax) && status)
+    SouthPole = TRUE;
+
+  /* set spacings for RA */
+  minorRA = minorDEC = 0.1;
+  range = MIN (fabs(graphmode.xmax-graphmode.xmin), fabs(graphmode.ymax-graphmode.ymin));
+  if (NorthPole || SouthPole) range = 360;
+  lrange = log10(MAX(fabs(range), 1e-30));
+  factor = (int) (lrange);
+  if (lrange < 0) { factor -= 1; }
+  mantis = lrange - factor;
+  power = pow(10.0, factor);
+  fmantis = pow(10.0, mantis);
+  if ((fmantis >= 1.0) && (fmantis <=  2.0)) {
+    minorRA = 0.1 * power;
+  }
+  if ((fmantis > 2.0) && (fmantis <=  4.0)) {
+    minorRA = 0.2 * power;
+  }
+  if ((fmantis > 4.0) && (fmantis <=  6.0)) {
+    minorRA = 0.5 * power;
+  }
+  if ((fmantis > 6.0) && (fmantis <=  10.0)) {
+    minorRA = 0.5 * power;
+  }
+  dR = range / 100.0;
+  /* set spacings for DEC */
+  range = MIN (fabs(graphmode.xmax-graphmode.xmin), fabs(graphmode.ymax-graphmode.ymin));
+  lrange = log10(MAX(fabs(range), 1e-30));
+  factor = (int) (lrange);
+  if (lrange < 0) { factor -= 1; }
+  mantis = lrange - factor;
+  power = pow(10.0, factor);
+  fmantis = pow(10.0, mantis);
+  if ((fmantis >= 1.0) && (fmantis <=  2.0)) {
+    minorDEC = 0.1 * power;
+  }
+  if ((fmantis > 2.0) && (fmantis <=  4.0)) {
+    minorDEC = 0.2 * power;
+  }
+  if ((fmantis > 4.0) && (fmantis <=  6.0)) {
+    minorDEC = 0.5 * power;
+  }
+  if ((fmantis > 6.0) && (fmantis <=  10.0)) {
+    minorDEC = 0.5 * power;
+  }
+  dD = range / 100.0;
+
+  /* choose a starting point */
+  if ((int)(graphmode.coords.crval1/minorRA) == (graphmode.coords.crval1/minorRA)) {
+    firstRA = graphmode.coords.crval1;
+  } else {
+    firstRA = minorRA + minorRA*((int)(graphmode.coords.crval1/minorRA));
+  }
+  if ((int)(graphmode.coords.crval2/minorDEC) == (graphmode.coords.crval2/minorDEC)) {
+    firstDEC = graphmode.coords.crval2;
+  } else {
+    firstDEC = minorDEC + minorDEC*((int)(graphmode.coords.crval2/minorDEC));
+  }
+  if (SouthPole) firstDEC = -90;
+  if (NorthPole) firstDEC = 90;
+  
+  /* prepare vectors to hold data */
+  NELEMENTS = 200;
+  ALLOCATE (Xvec.elements, float, NELEMENTS);
+  ALLOCATE (Yvec.elements, float, NELEMENTS);
+  N = 0;
+  
+  /***  do consecutive RA lines, first increasing **/
+  OnPic = TRUE;
+  for (r = firstRA; (r <= firstRA + 180) && (OnPic); r += minorRA) {
+    /* first, DEC increasing */
+    LOnPic = TRUE;
+    OnPic = FALSE;
+    First = TRUE;
+    for (d = firstDEC; (d < 90 + dD) && (LOnPic || NorthPole || SouthPole); d += dD) {
+      D = MAX (-90, MIN(90, d));
+      status = fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], r, D, &graphmode.coords);
+      /*
+      if ((fabs(Xvec.elements[N] - Xvec.elements[N-1]) > 10) && (fabs(Yvec.elements[N] - Yvec.elements[N-1]) > 10))
+	First = TRUE;
+	*/
+      if ((Xvec.elements[N] >= graphmode.xmin) && (Xvec.elements[N] <= graphmode.xmax) && 
+	  (Yvec.elements[N] >= graphmode.ymin) && (Yvec.elements[N] <= graphmode.ymax) && status) {
+	N++;
+	CHECKELEMENTS;
+	OnPic = TRUE;
+	if (!First) {
+	  Xvec.elements[N] = Xvec.elements[N-1];
+	  Yvec.elements[N] = Yvec.elements[N-1];
+	  N++;
+	  CHECKELEMENTS;
+	} else {
+	  if (N > 1) {
+	    Xvec.elements[N-2] = Xvec.elements[N-1];
+	    Yvec.elements[N-2] = Yvec.elements[N-1];
+	    N--;
+	  }
+	  First = FALSE;
+	}
+      } else {
+	LOnPic = FALSE;
+	First = TRUE;
+      }
+    }
+    /* next, DEC decreasing */
+    First = TRUE;
+    LOnPic = TRUE;
+    for (d = firstDEC; (d > -90 - dD) && (LOnPic || NorthPole || SouthPole); d -= dD) {
+      D = MAX (-90, MIN(90, d));
+      status = fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], r, D, &graphmode.coords);
+      /*
+      if ((fabs(Xvec.elements[N] - Xvec.elements[N-1]) > 10) && (fabs(Yvec.elements[N] - Yvec.elements[N-1]) > 10))
+	First = TRUE;
+	*/
+      if ((Xvec.elements[N] >= graphmode.xmin) && (Xvec.elements[N] <= graphmode.xmax) && 
+	  (Yvec.elements[N] >= graphmode.ymin) && (Yvec.elements[N] <= graphmode.ymax) && status) {
+	N++;
+	CHECKELEMENTS;
+	OnPic = TRUE;
+	if (!First) {
+	  Xvec.elements[N] = Xvec.elements[N-1];
+	  Yvec.elements[N] = Yvec.elements[N-1];
+	  N++;
+	  CHECKELEMENTS;
+	} else {
+	  if (N > 1) {
+	    Xvec.elements[N-2] = Xvec.elements[N-1];
+	    Yvec.elements[N-2] = Yvec.elements[N-1];
+	    N--;
+	  }
+	  First = FALSE;
+	}
+      } else {
+	LOnPic = FALSE;
+	First = TRUE;
+      } 
+    }
+  }
+
+  /***  do consecutive RA lines, decreasing **/
+  OnPic = TRUE;
+  for (r = firstRA; (r >=  firstRA - 180) && (OnPic); r -= minorRA) {
+    /* first, DEC increasing */
+    First = TRUE;
+    LOnPic = TRUE;
+    OnPic = FALSE;
+    for (d = firstDEC; (d < 90 + dD) && (LOnPic || NorthPole || SouthPole); d += dD) {
+      D = MAX (-90, MIN(90, d));
+      status = fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], r, D, &graphmode.coords);
+      /*
+      if ((fabs(Xvec.elements[N] - Xvec.elements[N-1]) > 10) && (fabs(Yvec.elements[N] - Yvec.elements[N-1]) > 10))
+	First = TRUE;
+	*/
+      if ((Xvec.elements[N] >= graphmode.xmin) && (Xvec.elements[N] <= graphmode.xmax) && 
+	  (Yvec.elements[N] >= graphmode.ymin) && (Yvec.elements[N] <= graphmode.ymax) && status) {
+	N++;
+	CHECKELEMENTS;
+	OnPic = TRUE;
+	if (!First) {
+	  Xvec.elements[N] = Xvec.elements[N-1];
+	  Yvec.elements[N] = Yvec.elements[N-1];
+	  N++;
+	  CHECKELEMENTS;
+	} else {
+	  if (N > 1) {
+	    Xvec.elements[N-2] = Xvec.elements[N-1];
+	    Yvec.elements[N-2] = Yvec.elements[N-1];
+	    N--;
+	  }
+	  First = FALSE;
+	}
+      } else {
+	LOnPic = FALSE;
+	First = TRUE;
+      }
+    }
+    /* next, DEC decreasing */
+    First = TRUE;
+    LOnPic = TRUE;
+    for (d = firstDEC; (d > -90 - dD) && (LOnPic || NorthPole || SouthPole); d -= dD) {
+      D = MAX (-90, MIN(90, d));
+      status = fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], r, D, &graphmode.coords);
+      /*
+      if ((fabs(Xvec.elements[N] - Xvec.elements[N-1]) > 10) && (fabs(Yvec.elements[N] - Yvec.elements[N-1]) > 10))
+	First = TRUE;
+	*/
+      if ((Xvec.elements[N] >= graphmode.xmin) && (Xvec.elements[N] <= graphmode.xmax) && 
+	  (Yvec.elements[N] >= graphmode.ymin) && (Yvec.elements[N] <= graphmode.ymax) && status) {
+	N++;
+	CHECKELEMENTS;
+	OnPic = TRUE;
+	if (!First) {
+	  Xvec.elements[N] = Xvec.elements[N-1];
+	  Yvec.elements[N] = Yvec.elements[N-1];
+	  N++;
+	  CHECKELEMENTS;
+	} else {
+	  if (N > 1) {
+	    Xvec.elements[N-2] = Xvec.elements[N-1];
+	    Yvec.elements[N-2] = Yvec.elements[N-1];
+	    N--;
+	  }
+	  First = FALSE;
+	}
+      } else {
+	LOnPic = FALSE;
+	First = TRUE;
+      }
+    }
+  }
+
+  /***  do consecutive DEC lines, first increasing **/
+  OnPic = TRUE;
+  for (d = firstDEC; (d < 90 + dD) && (OnPic); d += minorDEC) {
+    D = MAX (-90, MIN(90, d));
+    /* first, RA increasing */
+    LOnPic = TRUE;
+    OnPic = FALSE;
+    First = TRUE;
+    for (r = firstRA; (r < firstRA + 180) && (LOnPic || NorthPole || SouthPole); r += dR) {
+      status = fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], r, D, &graphmode.coords);
+      /*
+      if ((fabs(Xvec.elements[N] - Xvec.elements[N-1]) > 10) && (fabs(Yvec.elements[N] - Yvec.elements[N-1]) > 10))
+	First = TRUE;
+	*/
+      if ((Xvec.elements[N] >= graphmode.xmin) && (Xvec.elements[N] <= graphmode.xmax) && 
+	  (Yvec.elements[N] >= graphmode.ymin) && (Yvec.elements[N] <= graphmode.ymax) && status) {
+	N++;
+	CHECKELEMENTS;
+	OnPic = TRUE;
+	if (!First) {
+	  Xvec.elements[N] = Xvec.elements[N-1];
+	  Yvec.elements[N] = Yvec.elements[N-1];
+	  N++;
+	  CHECKELEMENTS;
+	} else {
+	  if (N > 1) {
+	    Xvec.elements[N-2] = Xvec.elements[N-1];
+	    Yvec.elements[N-2] = Yvec.elements[N-1];
+	    N--;
+	  }
+	  First = FALSE;
+	}
+      } else {
+	LOnPic = FALSE;
+	First = TRUE;
+      }
+    }
+    /* next, RA decreasing */
+    First = TRUE;
+    LOnPic = TRUE;
+    for (r = firstRA; (r > firstRA - 180) && (LOnPic || NorthPole || SouthPole); r -= dR) {
+      status = fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], r, D, &graphmode.coords);
+      /*
+      if ((fabs(Xvec.elements[N] - Xvec.elements[N-1]) > 10) && (fabs(Yvec.elements[N] - Yvec.elements[N-1]) > 10))
+	First = TRUE;
+	*/
+      if ((Xvec.elements[N] >= graphmode.xmin) && (Xvec.elements[N] <= graphmode.xmax) && 
+	  (Yvec.elements[N] >= graphmode.ymin) && (Yvec.elements[N] <= graphmode.ymax) && status) {
+	N++;
+	CHECKELEMENTS;
+	OnPic = TRUE;
+	if (!First) {
+	  Xvec.elements[N] = Xvec.elements[N-1];
+	  Yvec.elements[N] = Yvec.elements[N-1];
+	  N++;
+	  CHECKELEMENTS;
+	} else {
+	  if (N > 1) {
+	    Xvec.elements[N-2] = Xvec.elements[N-1];
+	    Yvec.elements[N-2] = Yvec.elements[N-1];
+	    N--;
+	  }
+	  First = FALSE;
+	}
+      } else {
+	LOnPic = FALSE;
+	First = TRUE;
+      }
+    }
+  }
+
+  /***  do consecutive DEC lines, decreasing **/
+  OnPic = TRUE;
+  for (d = firstDEC; (d > -90 - dD) && (OnPic); d -= minorDEC) {
+    D = MAX (-90, MIN(90, d));
+    /* first, RA increasing */
+    LOnPic = TRUE;
+    OnPic = FALSE;
+    First = TRUE;
+    for (r = firstRA; (r < firstRA + 180) && (LOnPic || NorthPole || SouthPole); r += dR) {
+      status = fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], r, D, &graphmode.coords);
+      /*
+      if ((fabs(Xvec.elements[N] - Xvec.elements[N-1]) > 10) && (fabs(Yvec.elements[N] - Yvec.elements[N-1]) > 10))
+	First = TRUE;
+	*/
+      if ((Xvec.elements[N] >= graphmode.xmin) && (Xvec.elements[N] <= graphmode.xmax) && 
+	  (Yvec.elements[N] >= graphmode.ymin) && (Yvec.elements[N] <= graphmode.ymax) && status) {
+	N++;
+	CHECKELEMENTS;
+	OnPic = TRUE;
+	if (!First) {
+	  Xvec.elements[N] = Xvec.elements[N-1];
+	  Yvec.elements[N] = Yvec.elements[N-1];
+	  N++;
+	  CHECKELEMENTS;
+	} else {
+	  if (N > 1) {
+	    Xvec.elements[N-2] = Xvec.elements[N-1];
+	    Yvec.elements[N-2] = Yvec.elements[N-1];
+	    N--;
+	  }
+	  First = FALSE;
+	}
+      } else {
+	LOnPic = FALSE;
+	First = TRUE;
+      }
+    }
+    /* next, RA decreasing */
+    First = TRUE;
+    LOnPic = TRUE;
+    for (r = firstRA; (r > firstRA - 180) && (LOnPic || NorthPole || SouthPole); r -= dR) {
+      status = fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], r, D, &graphmode.coords);
+      /*
+      if ((fabs(Xvec.elements[N] - Xvec.elements[N-1]) > 10) && (fabs(Yvec.elements[N] - Yvec.elements[N-1]) > 10))
+	First = TRUE;
+	*/
+      if ((Xvec.elements[N] >= graphmode.xmin) && (Xvec.elements[N] <= graphmode.xmax) && 
+	  (Yvec.elements[N] >= graphmode.ymin) && (Yvec.elements[N] <= graphmode.ymax) && status) {
+	N++;
+	CHECKELEMENTS;
+	OnPic = TRUE;
+	if (!First) {
+	  Xvec.elements[N] = Xvec.elements[N-1];
+	  Yvec.elements[N] = Yvec.elements[N-1];
+	  N++;
+	  CHECKELEMENTS;
+	} else {
+	  if (N > 1) {
+	    Xvec.elements[N-2] = Xvec.elements[N-1];
+	    Yvec.elements[N-2] = Yvec.elements[N-1];
+	    N--;
+	  }
+	  First = FALSE;
+	}
+      } else {
+	LOnPic = FALSE;
+	First = TRUE;
+      }
+    }
+  }
+  
+  /* send the line segments as connect-points */
+  Xvec.Nelements = Yvec.Nelements = N;
+  graphmode.style = 2; /* points */
+  graphmode.ptype = 100; /* connect a pair */
+  graphmode.etype = 0;
+  PrepPlotting (N, &graphmode);
+  PlotVector (N, Xvec.elements);
+  PlotVector (N, Yvec.elements);
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.astro/coords.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/coords.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/coords.c	(revision 12606)
@@ -0,0 +1,55 @@
+# include "astro.h"
+
+int coords (int argc, char **argv) {
+
+  int mode, N;
+  double X, Y, R, D;
+  Coords coords;
+  Buffer *buf;
+
+  mode = 0;
+  if (N = get_argument (argc, argv, "-p")) {
+    remove_argument (N, &argc, argv);
+    X = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    Y = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    mode = 1;
+  }
+  if (N = get_argument (argc, argv, "-c")) {
+    if (mode == 1) {
+      fprintf (stderr, "only one of -p or -c can be used\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    R = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    D = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    mode = 2;
+  }
+  if ((mode == 0) || (argc != 2)) {
+    fprintf (stderr, "USAGE: coords [buffer] (-c R D) / (-p X Y)\n");
+    return (FALSE);
+  }    
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  GetCoords (&coords, &buf[0].header);
+  
+  if (mode == 1) {
+    XY_to_RD (&R, &D, X, Y, &coords);
+    fprintf (stderr, "%10.6f %10.6f\n", R, D);
+    set_variable ("RA", R);
+    set_variable ("DEC", D);
+  }
+    
+  if (mode == 2) {
+    RD_to_XY (&X, &Y, R, D, &coords);
+    fprintf (stderr, "%7.2f %7.2f\n", X, Y);
+    set_variable ("Xc", X);
+    set_variable ("Yc", Y);
+  }
+
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.astro/cplot.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/cplot.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/cplot.c	(revision 12606)
@@ -0,0 +1,60 @@
+# include "astro.h"
+
+int cplot (int argc, char **argv) {
+  
+  int i, Npts, Ngraph;
+  float *x, *y, *r, *d, Rmin, Rmax;
+  Vector Xvec, Yvec, *xvec, *yvec;
+  Graphdata graphmode;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: cplot <ra> <dec>\n");
+    return (FALSE);
+  }
+  
+  Ngraph = 0;
+  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);
+
+  Rmin = graphmode.coords.crval1 - 182.0;
+  Rmax = graphmode.coords.crval1 + 182.0;
+
+  /* find vectors */
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (xvec[0].Nelements != yvec[0].Nelements) {
+    fprintf (stderr, "vectors are not the same length\n");
+    return (FALSE);
+  }
+
+  ALLOCATE (Xvec.elements, float, xvec[0].Nelements);
+  ALLOCATE (Yvec.elements, float, xvec[0].Nelements);
+    
+  Xvec.Nelements = xvec[0].Nelements;
+  Yvec.Nelements = xvec[0].Nelements;
+  
+  r = xvec[0].elements;
+  d = yvec[0].elements;
+  x = Xvec.elements;
+  y = Yvec.elements;
+  
+  for (i = 0; i < Xvec.Nelements; i++, r++, d++, x++, y++) {
+    while (*r < Rmin) *r += 360.0;
+    while (*r > Rmax) *r -= 360.0;
+    fRD_to_XY (x, y, *r, *d, &graphmode.coords);
+  }
+  
+  
+  Npts = Xvec.Nelements;
+  graphmode.etype = 0;
+  PrepPlotting (Npts, &graphmode);
+  PlotVector (Npts, Xvec.elements);
+  PlotVector (Npts, Yvec.elements);
+  
+  free (Xvec.elements);
+  free (Yvec.elements);
+    
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.astro/csystem.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/csystem.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/csystem.c	(revision 12606)
@@ -0,0 +1,120 @@
+# include "astro.h"
+
+int csystem (int argc, char **argv) {
+
+  /* USAGE: csystem [C/G/E/H] [C/G/E/H] [epoch] */
+  int i;
+  double X, Y, Xo, xo, phi, T;
+  double sin_x, sin_y, cos_x, cos_y;
+  float *x, *y;
+  struct timeval now;
+  struct tm *local;
+  Vector *xvec, *yvec;
+   
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: csystems [C/G/E/H] [C/G/E/H] X Y\n");
+    return (FALSE);
+  }
+
+  Xo = xo = phi = 0;
+  switch (argv[1][0]) {
+  case 'C':
+    switch (argv[2][0]) {
+    case 'C': 
+      fprintf (stderr, "same coordinate system\n");
+      return (TRUE);
+      break;
+    case 'G':
+      phi = -62.6*RAD_DEG;
+      Xo = 282.25;
+      xo = 33;
+      break;
+    case 'E':
+      gettimeofday (&now, (struct timezone *) NULL);
+      local = localtime (&now.tv_sec);
+      T = local[0].tm_year / 100.0;
+      phi = -1*(23.452294 - 0.013013*T - 0.000001639*T*T + 0.000000503*T*T*T);
+      phi *= RAD_DEG;
+      Xo = xo = 0.0;
+      break;
+    }
+    break;
+  case 'E':
+    switch (argv[2][0]) {
+    case 'C': 
+      gettimeofday (&now, (struct timezone *) NULL);
+      local = localtime (&now.tv_sec);
+      T = local[0].tm_year / 100.0;
+      phi = 23.452294 - 0.013013*T - 0.000001639*T*T + 0.000000503*T*T*T;
+      phi *= RAD_DEG;
+      Xo = xo = 0.0;
+      break;
+    case 'G':
+      fprintf (stderr, "error: conversions between galactic and ecliptic not implemented\n");
+      return (FALSE);
+      phi = -62.6*RAD_DEG;
+      Xo = 282.25;
+      xo = 33;
+      break;
+    case 'E':
+      phi = Xo = xo = 0.0;
+      break;
+    }
+    break;
+  case 'G':
+    switch (argv[2][0]) {
+    case 'C': 
+      phi = 62.6*RAD_DEG;
+      Xo = 33;
+      xo = 282.25;
+      break;
+    case 'G':
+      phi = Xo = xo = 0.0;
+      break;
+    case 'E':
+      fprintf (stderr, "error: conversions between galactic and ecliptic not implemented\n");
+      return (FALSE);
+      gettimeofday (&now, (struct timezone *) NULL);
+      local = localtime (&now.tv_sec);
+      T = local[0].tm_year / 100.0;
+      phi = -1*(23.452294 - 0.013013*T - 0.000001639*T*T + 0.000000503*T*T*T);
+      Xo = xo = 0.0;
+      break;
+    }
+  }
+ 
+  Xo *= RAD_DEG;
+
+  /* find vectors */
+  if ((xvec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[4], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (xvec[0].Nelements != yvec[0].Nelements) {
+    fprintf (stderr, "vectors %s and %s not the same length\n", argv[3], argv[4]);
+    return (FALSE);
+  }
+  
+  x = xvec[0].elements;
+  y = yvec[0].elements;
+
+  for (i = 0; i < xvec[0].Nelements; i++, x++, y++) {
+    X = *x*RAD_DEG;
+    Y = *y*RAD_DEG;
+
+    sin_y = cos(Y)*sin(X - Xo)*sin(phi) + sin(Y)*cos(phi);
+    cos_y = sqrt (1 - sin_y*sin_y);
+    sin_x = (cos(Y)*sin(X - Xo)*cos(phi) - sin(Y)*sin(phi)) /  cos_y;
+    cos_x = cos(Y)*cos(X - Xo) / cos_y;
+    
+    X = (DEG_RAD * atan2 (sin_x, cos_x) + xo + 360);
+    
+    while (X >= 360.0)
+      X -= 360;
+    Y = DEG_RAD * atan2 (sin_y, cos_y);
+    *x = X;
+    *y = Y;
+  }
+
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.astro/ctimes.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/ctimes.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/ctimes.c	(revision 12606)
@@ -0,0 +1,66 @@
+# include "astro.h"
+
+int ctimes (int argc, char **argv) {
+
+  int Reference, TimeFormat, N;
+  double value;
+  time_t time, TimeReference;
+  char *date, *Variable;
+
+  Variable = (char *) NULL;
+  if (N = get_argument (argc, argv, "-var")) {
+    remove_argument (N, &argc, argv);
+    Variable = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: ctimes [-ref (value) / -abs (date)] [-var name]\n");
+    return (FALSE);
+  }
+
+  GetTimeFormat (&TimeReference, &TimeFormat);
+
+  Reference = FALSE;
+  if (!strcmp (argv[1], "-ref")) Reference = TRUE;
+
+  if (Reference) {
+
+    value = atof (argv[2]);
+    time = TimeRef (value, TimeReference, TimeFormat);
+    date = sec_to_date (time);
+    
+    if (Variable != (char *) NULL) {
+      set_str_variable (Variable, date);
+      free (Variable);
+    } else {
+      fprintf (stderr, "time: %s\n", date);
+    }
+
+    free (date);
+    return (TRUE);
+
+  } else {
+
+    if (strcmp (argv[1], "-abs")) {
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+
+    if (!str_to_time (argv[2], &time)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    
+    value = TimeValue (time, TimeReference, TimeFormat);
+    
+    if (Variable != (char *) NULL) {
+      set_variable (Variable, value);
+      free (Variable);
+      return (TRUE);
+    }
+    fprintf (stderr, "time: %f\n", value);
+    return (TRUE);
+  }
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.astro/cval.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/cval.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/cval.c	(revision 12606)
@@ -0,0 +1,51 @@
+# include "astro.h"
+
+int cval (int argc, char **argv) {
+  
+  int i, j, Nx;
+  int sx, sy, nx, ny, xo, yo, dx, dy;
+  float *V, cval, val, sn, sky;
+  Buffer *buf;
+
+  if (argc != 7) {
+    fprintf (stderr, "USAGE: cval <buffer> x y dx dy sky\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  xo = atof (argv[2]);
+  yo = atof (argv[3]);
+  dx = atof (argv[4]);
+  dy = atof (argv[5]);
+  sky = atof (argv[6]);
+
+  sx = xo - dx;
+  sy = yo - dy;
+  nx = 2*dx + 1;
+  ny = 2*dy + 1;
+  if ((sx < 0) || (sy < 0) || 
+      (sx+nx > buf[0].matrix.Naxis[0]) || 
+      (sy+ny > buf[0].matrix.Naxis[1])) {
+    fprintf (stderr, "region out of range\n");
+    return (FALSE);
+  }
+
+  V = (float *)buf[0].matrix.buffer;
+  Nx = buf[0].matrix.Naxis[0];
+  val = V[xo + yo*Nx];
+
+  sn = 0;
+  cval = 0;
+  for (j = sy; j < sy + ny; j++) {
+    for (i = sx; i < sx + nx; i++) {
+      cval += (val - V[i + j*Nx]) / sqrt(V[i + j*Nx]);
+      sn += SQ (V[i + j*Nx] - sky) / V[i + j*Nx];
+    }
+  }
+
+  fprintf (stderr, "cval: %f  sn: %f\n", cval, sqrt(sn));
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.astro/czplot.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/czplot.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/czplot.c	(revision 12606)
@@ -0,0 +1,78 @@
+# include "astro.h"
+
+int czplot (int argc, char **argv) {
+  
+  int i, N, Npts, Ngraph;
+  double min, range, Rmin, Rmax;
+  float *in, *out, *r, *d, *x, *y;
+  Vector Xvec, Yvec, Zvec, *xvec, *yvec, *zvec;
+  Graphdata graphmode;
+
+  Ngraph = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Ngraph = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);
+
+  if (argc != 6) {
+    fprintf (stderr, "USAGE: czplot <x> <y> <z> min max\n");
+    return (FALSE);
+  }
+
+  min = atof(argv[4]);
+  range = atof(argv[5]) - min;
+  Rmin = graphmode.coords.crval1 - 180.0;
+  Rmax = graphmode.coords.crval1 + 180.0;
+
+  /* find vectors */
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((zvec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (xvec[0].Nelements != yvec[0].Nelements) {
+    fprintf (stderr, "vectors %s and %s not the same length\n", argv[1], argv[2]);
+    return (FALSE);
+  }
+  if (xvec[0].Nelements != zvec[0].Nelements) {
+    fprintf (stderr, "vectors %s and %s not the same length\n", argv[1], argv[3]);
+    return (FALSE);
+  }
+  Xvec.Nelements = xvec[0].Nelements;
+  Yvec.Nelements = xvec[0].Nelements;
+  Zvec.Nelements = zvec[0].Nelements;
+  ALLOCATE (Xvec.elements, float, Xvec.Nelements);
+  ALLOCATE (Yvec.elements, float, Yvec.Nelements);
+  ALLOCATE (Zvec.elements, float, Zvec.Nelements);
+  
+  r   = xvec[0].elements;
+  d   = yvec[0].elements;
+  in  = zvec[0].elements;
+  x   = Xvec.elements;
+  y   = Yvec.elements;
+  out = Zvec.elements;
+  for (i = 0; i < Zvec.Nelements; i++, in++, out++, r++, d++, x++, y++) {
+    *out = MIN (1.0, MAX (0.01, (*in - min) / range));
+    while (*r < Rmin) *r += 360.0;
+    while (*r > Rmax) *r -= 360.0;
+    fRD_to_XY (x, y, *r, *d, &graphmode.coords);
+  }
+
+  graphmode.style = 2;
+  graphmode.size = -1; /* point size determined by Zvec */
+  graphmode.etype = 0;
+  Npts = Xvec.Nelements;
+  PrepPlotting (Npts, &graphmode);
+
+  PlotVector (Npts, Xvec.elements);
+  PlotVector (Npts, Yvec.elements);
+  PlotVector (Npts, Zvec.elements);
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+  free (Zvec.elements);
+
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.astro/drizzle.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/drizzle.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/drizzle.c	(revision 12606)
@@ -0,0 +1,228 @@
+# include "astro.h"
+
+static double XO, XX, XY;
+static double YO, YX, YY;
+int ZERO;
+
+int map_output_to_input (int Npix, double df);
+int map_input_to_output (int Npix, double df);
+void set_linear_terms (Coords *in, Coords *out, int i, int j, int Npix);
+void apply_terms (double *Xout, double *Yout, double Xin, double Yin);
+
+Coords coords_in, coords_out;
+Buffer *in, *out, *wt;
+
+int drizzle (int argc, char **argv) {
+
+  int Nlinear, Np, N;
+  double scale_in, scale_out, df;
+
+  ZERO = FALSE;
+  if (N = get_argument (argc, argv, "-zero")) {
+    ZERO = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: transform <from> <to> <weight> (Nlinear)\n");
+    fprintf (stderr, "  output buffer must exist with target astrometry header\n");
+    fprintf (stderr, "  Nlinear is the pixel scale for linear astrometric transformation\n");
+    return (FALSE);
+  }
+
+  if ((in  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((wt  = SelectBuffer (argv[3], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  Nlinear = atoi (argv[4]);
+
+  GetCoords (&coords_in, &in[0].header);
+  GetCoords (&coords_out, &out[0].header);
+  
+  scale_in = sqrt(fabs(coords_in.cdelt1*coords_in.cdelt2*(coords_in.pc1_1*coords_in.pc2_2 - coords_in.pc1_2*coords_in.pc2_1)));
+  scale_out = sqrt(fabs(coords_out.cdelt1*coords_out.cdelt2*(coords_out.pc1_1*coords_out.pc2_2 - coords_out.pc1_2*coords_out.pc2_1)));
+  
+  fprintf (stderr, "%f - %f\n", scale_in, scale_out);
+
+  if (scale_in > scale_out) {
+    Np = MAX (1, 3*scale_out / scale_in);
+    df = 1.0 / Np;
+    map_output_to_input (Nlinear, df);
+  } else {
+    Np = MAX (1, 3*scale_in / scale_out);
+    df = 1.0 / Np;
+    map_input_to_output (Nlinear, df);
+  }
+  return (TRUE);
+}
+
+/* mode 1: input pixels >> output pixels: loop over output pixels */
+/* mode 2: input pixels << output pixels: loop over input pixels */
+/* mode 3: input pixels ~= output pixels: drizzle input to output */
+
+/* loop over the input pixels, map input output image */
+int map_output_to_input (int Npix, double df) {
+
+  int i, j, Ni, No, Nx, Ny, nx, ny;
+  float *Vin, *Vout, *Vwt;
+  double x, y, X, Y;
+
+  /* loop over output pixels */
+  /* set up pointers for buffers */
+  Vin  = (float *) in[0].matrix.buffer;
+  Vout = (float *) out[0].matrix.buffer;
+  Vwt  = (float *) wt[0].matrix.buffer;
+
+  nx = in[0].header.Naxis[0];
+  ny = in[0].header.Naxis[1];
+  Nx = out[0].header.Naxis[0];
+  Ny = out[0].header.Naxis[1];
+
+  if (ZERO) {
+    bzero (Vout, Nx*Ny*sizeof(float));
+    bzero (Vwt,  Nx*Ny*sizeof(float));
+  }
+
+  for (j = 0; j < Ny; j+=Npix) {
+    for (i = 0; i < Nx; i+=Npix) {
+      
+      /* define linear transformation in region */
+      set_linear_terms (&coords_out, &coords_in, i, j, Npix);
+
+      for (X = i; (X < i + Npix) && (X < Nx); X += df) {
+	for (Y = j; (Y < j + Npix) && (Y < Ny); Y += df) {
+	  
+	  No = (int)X + ((int)Y)*Nx;
+	  apply_terms (&x, &y, X, Y);
+	  if (x < 0) continue;
+	  if (x >= nx) continue;
+	  if (y < 0) continue;
+	  if (y >= ny) continue;
+	  Ni = (int)x + ((int)y)*nx;
+
+	  Vout[No] += Vin[Ni];
+	  Vwt[No] ++;
+	}
+      }
+    }
+  }
+  return (TRUE);
+}
+
+/* loop over the input pixels, map input output image */
+int map_input_to_output (int Npix, double df) {
+
+  int i, j, Ni, No, Nx, Ny, nx, ny;
+  float *Vin, *Vout, *Vwt;
+  double x, y, X, Y;
+
+  /* loop over output pixels */
+  /* set up pointers for buffers */
+  Vin  = (float *) in[0].matrix.buffer;
+  Vout = (float *) out[0].matrix.buffer;
+  Vwt  = (float *) wt[0].matrix.buffer;
+
+  Nx = in[0].header.Naxis[0];
+  Ny = in[0].header.Naxis[1];
+  nx = out[0].header.Naxis[0];
+  ny = out[0].header.Naxis[1];
+
+  if (ZERO) {
+    bzero (Vout, nx*ny*sizeof(float));
+    bzero (Vwt,  nx*ny*sizeof(float));
+  }
+
+  for (j = 0; j < Ny; j+=Npix) {
+    for (i = 0; i < Nx; i+=Npix) {
+      
+      /* define linear transformation in region */
+      set_linear_terms (&coords_in, &coords_out, i, j, Npix);
+
+      for (X = i; (X < i + Npix) && (X < Nx); X += df) {
+	for (Y = j; (Y < j + Npix) && (Y < Ny); Y += df) {
+	  
+	  Ni = (int)X + ((int)Y)*Nx;
+	  apply_terms (&x, &y, X, Y);
+	  if (x < 0) continue;
+	  if (x >= nx) continue;
+	  if (y < 0) continue;
+	  if (y >= ny) continue;
+	  No = (int)x + ((int)y)*nx;
+
+	  Vout[No] += Vin[Ni];
+	  Vwt[No] ++;
+	}
+      }
+    }
+  }
+  return (TRUE);
+}
+
+/* find the linear astrometric fix between images at this location */
+void set_linear_terms (Coords *in, Coords *out, int i, int j, int Npix) {
+
+  int n;
+  double x, y, x2, y2, xy, X, Y, Xx, Xy, Yx, Yy;
+  double Xin, Yin, Xout, Yout;
+  double Sx2, Sy2, Sxy, SXx, SXy, SYx, SYy;
+  double N, r, d;
+
+  N = x = y = x2 = y2 = xy = X = Y = Xx = Xy = Yx = Yy = 0;
+
+  /* define several test points, fit a line to the input,output pairs */
+  for (n = 0; n < 3; n++) {
+
+    switch (n) {
+    case 0:
+      Xin = i;
+      Yin = j;
+      break;
+    case 1:
+      Xin = i + Npix;
+      Yin = j;
+      break;
+    case 2:
+      Xin = i;
+      Yin = j + Npix;
+      break;
+    }
+
+    XY_to_RD (&r, &d, Xin, Yin, in);
+    RD_to_XY (&Xout, &Yout, r, d, out);
+
+    x  += Xin;
+    y  += Yin;
+    x2 += Xin*Xin;
+    y2 += Yin*Yin;
+    xy += Xin*Yin;
+    X  += Xout;
+    Y  += Yout;
+    Xx += Xout*Xin;
+    Xy += Xout*Yin;
+    Yx += Yout*Xin;
+    Yy += Yout*Yin;
+    N  += 1.0;
+  }
+
+  Sx2 = x2 - x*x/N;
+  Sy2 = y2 - y*y/N;
+  Sxy = xy - x*y/N;
+  SXx = Xx - X*x/N;
+  SXy = Xy - X*y/N;
+  SYx = Yx - Y*x/N;
+  SYy = Yy - Y*y/N;
+  
+  XX = (SXx*Sy2 - SXy*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  XY = (SXy*Sx2 - SXx*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  XO = X/N - XX*x/N - XY*y/N;
+
+  YX = (SYx*Sy2 - SYy*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  YY = (SYy*Sx2 - SYx*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  YO = Y/N - YX*x/N - YY*y/N;
+
+}
+
+
+void apply_terms (double *Xout, double *Yout, double Xin, double Yin) {
+  *Xout = XO + XX*Xin + XY*Yin;
+  *Yout = YO + YX*Xin + YY*Yin;
+}
Index: /tags/start/Ohana/src/opihi/cmd.astro/flux.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/flux.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/flux.c	(revision 12606)
@@ -0,0 +1,76 @@
+# include "astro.h"
+
+int flux (int argc, char **argv) {
+  
+  int i, j, k, xmin, ymin, xmax, ymax;
+  int oldsignal;
+  double ax, ay, s, S, flux;
+  double bx[5], by[5], x[5], y[5], bb[5];
+  float *V;
+  FILE *f;
+  Buffer *buf;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: flux <buffer> (region)\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  f = fopen (argv[2], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "file %s not found\n", argv[2]);
+    return (FALSE);
+  }
+
+  xmin = buf[0].matrix.Naxis[0];
+  xmax = 0;
+  ymin = buf[0].matrix.Naxis[1];
+  ymax = 0;
+  for (i = 0; i < 4; i++) {
+    fscanf (f, "%lf %lf", &x[i], &y[i]);
+    xmin = MAX (0, MIN (xmin, x[i] - 1));
+    ymin = MAX (0, MIN (ymin, y[i] - 1));
+    xmax = MIN (MAX (xmax, x[i] + 1), buf[0].matrix.Naxis[0]);
+    ymax = MIN (MAX (ymax, y[i] + 1), buf[0].matrix.Naxis[1]);
+  }
+  fclose (f);
+
+  x[4] = x[0]; y[4] = y[0];
+  for (i = 0; i < 4; i++) {
+    bx[i] = x[i+1] - x[i];
+    by[i] = y[i+1] - y[i];
+  }
+  bx[4] = bx[0]; by[4] = by[0];
+  for (i = 0; i < 4; i++) {
+    bb[i] = hypot (bx[i], by[i]) * SIGN (bx[i]*by[i+1] - bx[i+1]*by[i]);
+  }
+  fprintf (stderr, "%f %f %f %f\n", bb[0], bb[1], bb[2], bb[3]);
+
+  /* this only works for convex contours --
+   we have to add up the angles for concave contours */
+  flux = 0;
+  oldsignal = (int) signal (SIGINT, handle_interrupt);
+  interrupt = FALSE;
+  for (j = ymin; (j < ymax) && !interrupt; j++) {
+    V = (float *)(buf[0].matrix.buffer) + j*buf[0].matrix.Naxis[0] + xmin; 
+    for (i = xmin; (i < xmax) && !interrupt; i++, V++) {
+      S = 1.0;
+      for (k = 0; k < 4; k++) {
+	ax = i - x[k];
+	ay = j - y[k];
+	s = (ay*bx[k] - ax*by[k]) / bb[k] + 0.5;
+	/* s = b x a / |b|, with the correct sign (above) so inside is positive */
+	s = MAX (0.0, MIN (1.0, s));  /* s is between 0.0 and 1.0 */
+	S *= s;
+      }
+      flux += S * (*V);
+    }
+  }
+  signal (SIGINT, (void *) oldsignal);
+
+  fprintf (GetOutfile(), "flux: %f\n", flux);
+  set_variable ("FLUX", flux);
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.astro/gauss.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/gauss.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/gauss.c	(revision 12606)
@@ -0,0 +1,69 @@
+# include "astro.h"
+
+int gauss (int argc, char **argv) {
+
+  char buffer[20], key;
+  int i, N, Npix, Nborder, Nspot;
+  double X, Y, Z, max;
+  int Ximage, Nimage;
+  Buffer *buf;
+
+  Nimage = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Nimage = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (&Ximage, &Nimage)) return (FALSE);
+
+  Nborder = 3;
+  if (N = get_argument (argc, argv, "-border")) {
+    remove_argument (N, &argc, argv);
+    Nborder  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  Nborder = MAX (Nborder, 1);
+  
+  max = 60000;
+  if (N = get_argument (argc, argv, "-sat")) {
+    remove_argument (N, &argc, argv);
+    max  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  
+  if ((argc != 2) && (argc != 3)) {
+    fprintf (stderr, "USAGE: gauss Npix [Nspots] [-border N] [-sat cnts]\n");
+    return (FALSE);
+  }
+  
+  if (Ximage < 1) {
+    fprintf (stderr, "no active TV\n");
+    return (FALSE);
+  }
+
+  Nspot = 0;
+  Npix = atof (argv[1]);
+  if (argc == 3) {
+    Nspot = atof (argv[2]);
+  }
+
+  if ((buf = SelectBuffer (GetImageName(), OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  fcntl (Ximage, F_SETFL, !O_NONBLOCK);  
+  write (Ximage, "CURS", 4); /* ask Ximage to look for the keystrokes */
+  
+  for (i = 0; (i < Nspot) || (Nspot == 0); i++) {
+    bzero (buffer, 20);
+    read (Ximage, buffer, 16);
+    buffer[16] = 0;
+    sscanf (buffer, "%c %lf %lf", &key, &X, &Y);
+    if ((key == 'q') || (key == 'Q')) {
+      break;
+    }
+    Z = get_aperture_stats (&buf[0].matrix, (int)(X+0.5), (int)(Y+0.5), Npix, Nborder, max);
+    
+  }
+  write (Ximage, "NCUR", 4); /* tell Ximage "end of keystrokes" */
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.astro/getvel.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/getvel.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/getvel.c	(revision 12606)
@@ -0,0 +1,81 @@
+# include "astro.h"
+
+int getvel (int argc, char **argv) {
+  
+  int i, X, n, Ncurve;
+  int nx, ny;
+  double L, V, Vo, dV, Bo, dB;
+  double xo, yo;
+  double sl, cl, wo, Ro, Rs, wr, r, fr, d, x;
+  double R[100], T[100], W[100];
+  FILE *f;
+  Buffer *buf;
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: rotcurve buf X Y curve.txt\n");
+    return (FALSE);
+  }
+
+  f = fopen (argv[4], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't find rotation curve data file %s\n", argv[4]);
+    return (FALSE);
+  }
+  for (i = 0; fscanf (f, "%lf %lf", &R[i], &T[i]) != EOF; i++) {
+    W[i] = T[i] / R[i];
+  }  
+  fclose (f);
+  Ncurve = i;
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  nx = buf[0].matrix.Naxis[0];
+  ny = buf[0].matrix.Naxis[1];
+
+  /* we expect the input image to have units of velocity, lattitude, and longitude */
+  fits_scan (&buf[0].header, "CRVAL1", "%lf", 1, &Vo);
+  fits_scan (&buf[0].header, "CDELT1", "%lf", 1, &dV);
+  fits_scan (&buf[0].header, "CRPIX1", "%lf", 1, &xo);
+  fits_scan (&buf[0].header, "CRVAL2", "%lf", 1, &Bo);
+  fits_scan (&buf[0].header, "CDELT2", "%lf", 1, &dB);
+  fits_scan (&buf[0].header, "CRPIX2", "%lf", 1, &yo);
+  fits_scan (&buf[0].header, "CRVAL3", "%lf", 1, &L);
+  Vo *= 0.001;
+  dV *= 0.001;
+
+  while (L >= 360) {L -= 360.0;}
+  while (L < 0.0)  {L += 360.0;}
+  fprintf (stderr, "L: %f (%d)\n", L, X);
+
+  cl = cos (L*RAD_DEG);
+  sl = sin (L*RAD_DEG);
+  wo = 25.0;
+  Ro = 10.0;
+  Rs = Ro*sl;
+  x = atof (argv[2]);
+  /* this method depends on wr monotonically decreasing */
+
+  V = (x - xo) * dV + Vo;
+  wr = V/Rs + wo;
+  for (n = 0; (n < Ncurve) && (wr < W[n]); n++);
+  if ((n == 0) || (n == Ncurve)) {
+    fprintf (stderr, "velocity out of reasonable range\n");
+    fprintf (stderr, "%f %f %f %f\n", V, wr, W[0], W[Ncurve-1]);
+    return (TRUE);
+  }
+  r = (wr - W[n]) *  (R[n-1] - R[n]) / (W[n-1] - W[n]) + R[n];
+  fr = (Ro/r);
+  if (r < fabs(Rs)) { /* can't be on rotation curve */
+    fprintf (stderr, "velocity out of reasonable range\n");
+    fprintf (stderr, "%f %f %f %f %f %f %f\n", V, wr, W[0], W[Ncurve-1], r, fr, Rs);
+    return (TRUE);
+  }
+  if (r < Ro)
+    d = Ro*cl - sqrt(r*r - Rs*Rs);
+  else 
+    d = Ro*cl + sqrt(r*r - Rs*Rs);
+  
+  fprintf (stderr, "dist: %f, vel: %f\n", d, V);
+
+  return (TRUE);
+
+} 
Index: /tags/start/Ohana/src/opihi/cmd.astro/imfit.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/imfit.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/imfit.c	(revision 12606)
@@ -0,0 +1,333 @@
+# include "astro.h"
+
+# define SUBTRACT 0
+
+static float (*fitfunc)(float, float, float *, int, float *);
+
+float fgaussTD (float, float, float *, int, float *);
+float fgalaxyTD (float, float, float *, int, float *);
+float fbarTD (float, float, float *, int, float *);
+void fix_ellipsegauss_pars (float *par, int Npar);
+
+/*** for some reason, fgaussTD fails occasionally if we use these two vars... */ 
+static float f1, f2;
+
+int imfit (int argc, char **argv) {
+
+  int i, j, N, done, Npts, Subtract;
+  double Npar, DZ, DZ2;
+  float dx, dy, chisq, nchisq;
+  float **covar;
+  float *V, *x, *y, *z, *dz, *par, tmpsky, DFact;
+  int sx, sy, nx, ny;
+  char *c, line[64];
+  Buffer *buf;
+
+  Subtract = FALSE;
+  if (N = get_argument (argc, argv, "-sub")) {
+    remove_argument (N, &argc, argv);
+    Subtract  = TRUE;
+  }
+
+  DFact = 1;
+  if (N = get_argument (argc, argv, "-D")) {
+    remove_argument (N, &argc, argv);
+    DFact  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  fitfunc = fgaussTD;
+  if (N = get_argument (argc, argv, "-gal")) {
+    remove_argument (N, &argc, argv);
+    fitfunc = fgalaxyTD; 
+  }
+  if (N = get_argument (argc, argv, "-bar")) {
+    remove_argument (N, &argc, argv);
+    fitfunc = fbarTD; 
+  }
+
+  if (argc != 6) {
+    fprintf (stderr, "USAGE: imfit <buffer> sx sy nx ny\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  f1 = 1;
+  if ((c = get_variable ("BETA1")) != (char *) NULL) f1 = atof (c);
+
+  f2 = 1;
+  if ((c = get_variable ("BETA2")) != (char *) NULL) f2 = atof (c);
+
+  sx = atof (argv[2]);
+  sy = atof (argv[3]);
+  nx = atof (argv[4]);
+  ny = atof (argv[5]);
+
+  if ((sx < 0) || (sy < 0) || 
+      (sx+nx > buf[0].matrix.Naxis[0]) || 
+      (sy+ny > buf[0].matrix.Naxis[1])) {
+    fprintf (stderr, "region out of range\n");
+    return (FALSE);
+  }
+
+  Npar = 7;
+  ALLOCATE (par, float, 2*Npar);
+  bzero (par, Npar*sizeof(float));
+
+  /* convert array z[x,y] to x[i], y[i], z[i] */
+  Npts = nx*ny;
+  ALLOCATE (x, float, 2*Npts);
+  ALLOCATE (y, float, 2*Npts);
+  ALLOCATE (z, float, 2*Npts);
+  ALLOCATE (dz, float, 2*Npts);
+
+  for (N = j = 0; j < ny; j++) {
+    V = (float *)(buf[0].matrix.buffer) + (j+sy)*buf[0].matrix.Naxis[0] + sx; 
+    for (i = 0; i < nx; i++, V++, N++) {
+      dx = i + sx;
+      dy = j + sy;
+      z[N] = *V;
+      dz[N] = 1.0 / *V;  /* temporarily no gain (or, gain = 1) */
+      x[N] = dx;
+      y[N] = dy;
+    }
+  }
+
+  /* make initial guesses on parameters */
+  /* fitting X^2 / (2*Sx), Y^2 / (2*Sy) */
+  get_aperture_stats (&buf[0].matrix, (int)(sx + 0.5*nx), (int)(sy + 0.5*ny), 15, 2, 65000);
+  par[0] = atof (get_variable ("Xg"));
+  par[1] = atof (get_variable ("Yg"));
+  par[2] = SQ (atof (get_variable ("SXg")) / 2.355);
+  par[3] = SQ (atof (get_variable ("SYg")) / 2.355);
+  par[4] = 0;
+  par[5] = atof (get_variable ("Zcg")) / 15.0;
+  /* par[5] is peak intensity, Zcg is total flux, scale down some */
+  par[6] = atof (get_variable ("Sg"));
+
+  /* soften the errors */
+  for (i = 0; i < Npts; i++) {
+    double tmp1;
+    tmp1 = fitfunc (x[i], y[i], par, Npar, (float *) NULL);
+    if (!finite (tmp1)) { 
+      fprintf (stderr, "nan for tmp @ %d (%f %f %f)\n", i, x[i], y[i], z[i]); 
+    } else {
+      DZ = DFact * fabs (z[i] - tmp1);
+      DZ2 = DFact * fabs (z[i] - tmp1);
+      dz[i] *= 1 / (dz[i]*DZ + 1);  /* dz[i] = 1 / (DZ + 1/dz[i]) */
+    }
+  }
+  /* run fit routine */
+  chisq = mrq2dinit (x, y, z, dz, Npts, par, Npar, fitfunc);
+  done = FALSE;
+  for (i = 0; (i < 30) && !done; i++) {
+    nchisq = mrq2dmin (x, y, z, dz, Npts, par, Npar, fitfunc);
+    if (chisq - nchisq < 0.1) done = TRUE;
+    if (nchisq > 0) chisq = nchisq;
+  }  
+  covar = mrq2dcovar (Npar);
+  mrq2dfree (Npar);
+
+  if (Subtract) {
+    tmpsky = par[6];
+    par[6] = 0;
+    for (N = j = 0; j < ny; j++) {
+      V = (float *)(buf[0].matrix.buffer) + (j+sy)*buf[0].matrix.Naxis[0] + sx; 
+      for (i = 0; i < nx; i++, V++, N++) {
+	dx = i + sx;
+	dy = j + sy;
+	*V -= fitfunc (dx, dy, par, Npar, (float *) NULL);
+      }
+    }
+    par[6] = tmpsky;
+  }
+
+  fix_ellipsegauss_pars (par, Npar); 
+
+  for (i = 0; i < Npar; i++) {
+    sprintf (line, "PAR%d", i);
+    set_variable (line, (double) par[i]);
+    fprintf (stderr, "%f ", par[i]);
+  }
+  fprintf (stderr, "  %f\n", nchisq/(1.0*Npts));
+
+  free (par);
+  free (x);
+  free (y);
+  free (z);
+  free (dz);
+
+  return (TRUE);
+
+}
+
+/* pars: x, y, sx, sy, sxy, I, sky */
+float fgaussTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, Z, E, F, q, R, f, p2, p3;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  p2 = X / par[2];
+  p3 = Y / par[3];
+
+  Z = 0.5*p2*X + X*Y*par[4] + 0.5*p3*Y;                 /* R^2 */
+  /* E = 1.0 / (1 + f1*Z + f2*(0.5*Z*Z + 0.1666666*Z*Z*Z)); */  /* ~ exp (-Z) */
+  E = 1.0 / (1 + Z + (0.5*Z*Z + 0.1666666*Z*Z*Z));   /* ~ exp (-Z) */
+  F = (f1 + f2*(Z + 0.5*Z*Z));
+
+  q = par[5] * E;
+  R = q*E*F;
+  
+  f = q + par[6];
+
+  if (dpar != (float *) NULL) {
+    dpar[0] = R*(p2 + par[4]*Y);
+    dpar[1] = R*(p3 + par[4]*X);
+    dpar[2] = 0.5*R*p2*p2;
+    dpar[3] = 0.5*R*p3*p3;
+    dpar[4] = -R*X*Y;
+    
+    dpar[5] = E;
+    dpar[6] = 1;
+  }
+
+  /*
+  if ((fabs(X) < 2) && (fabs(Y) < 2)) {
+    int i;
+
+    for (i = 0; i < Npar; i++) {
+      fprintf (stderr, "%d  %f  %f\n", i, par[i], dpar[i]);
+    }
+    fprintf (stderr, "func: (%f, %f)  %f\n", X, Y, f);
+  }
+  */
+
+  if (!finite (f)) {
+    fprintf (stderr, "nan for fgaussTD\n");
+  }
+
+  return (f);
+
+}
+
+/* pars: x, y, sx, sy, sxy, I, sky */
+float fgalaxyTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, Z, E, F, q, R, f, p2, p3;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  p2 = X / par[2];
+  p3 = Y / par[3];
+
+  Z = sqrt (0.5*p2*X + X*Y*par[4] + 0.5*p3*Y);                 /* R */
+  E = 1.0 / (1 + Z);   
+
+  q = par[5] * E;
+  R = q*E;
+  F = 0.5 / Z;
+  
+  f = q + par[6];
+
+  if (dpar != (float *) NULL) {
+    dpar[0] = F*R*(p2 + par[4]*Y);
+    dpar[1] = F*R*(p3 + par[4]*X);
+    dpar[2] = F*0.5*R*p2*p2;
+    dpar[3] = F*0.5*R*p3*p3;
+    dpar[4] = -R*X*Y*F;
+    
+    dpar[5] = E;
+    dpar[6] = 1;
+  }
+
+  /*
+  if ((fabs(X) < 2) && (fabs(Y) < 2)) {
+    int i;
+
+    for (i = 0; i < Npar; i++) {
+      fprintf (stderr, "%d  %f  %f\n", i, par[i], dpar[i]);
+    }
+    fprintf (stderr, "func: (%f, %f)  %f\n", X, Y, f);
+  }
+  */
+  return (f);
+
+}
+
+
+/* pars: x, y, sx, sy, sxy, I, sky */
+float fbarTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, Z, E, F, q, R, f, p2, p3;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  p2 = X / par[2];
+  p3 = Y / par[3];
+
+  Z = 0.5*p2*X + X*Y*par[4] + 0.5*p3*Y;                 /* R */
+  E = 1.0 / (1 + Z*Z*Z);   
+
+  q = par[5] * E;
+  F = 3*Z*Z;
+  R = q*E*F;
+  
+  f = q + par[6];
+
+  if (dpar != (float *) NULL) {
+    dpar[0] = R*(p2 + par[4]*Y);
+    dpar[1] = R*(p3 + par[4]*X);
+    dpar[2] = 0.5*R*p2*p2;
+    dpar[3] = 0.5*R*p3*p3;
+    dpar[4] = -R*X*Y;
+    
+    dpar[5] = E;
+    dpar[6] = 1;
+  }
+
+  /*
+  if ((fabs(X) < 2) && (fabs(Y) < 2)) {
+    int i;
+
+    for (i = 0; i < Npar; i++) {
+      fprintf (stderr, "%d  %f  %f\n", i, par[i], dpar[i]);
+    }
+    fprintf (stderr, "func: (%f, %f)  %f\n", X, Y, f);
+  }
+  */
+  return (f);
+
+}
+
+
+void fix_ellipsegauss_pars (float *par, int Npar) {
+
+  float p2, p4, angle, t1, t2, tmp, area;
+
+  /* par[0], par[1] = Xo, Yo - stay the same */
+
+  p2 = 1/par[2];
+  p4 = 1/par[3];
+
+  angle = 0.5 * atan2 (-2*par[4], p4 - p2); 
+
+  tmp = sqrt (SQ(p2 - p4) + 4*SQ(par[4]));
+  t1 = (p2 + p4 + tmp) / 2;
+  t2 = t1 - tmp;
+
+  par[2] = 2.35482*sqrt(1/t2);
+  par[3] = 2.35482*sqrt(1/t1);
+  par[4] = DEG_RAD * angle;
+
+  area = 2*M_PI/sqrt(t1*t2);
+
+  par[5] *= area;
+
+}
+
+
Index: /tags/start/Ohana/src/opihi/cmd.astro/init.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/init.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/init.c	(revision 12606)
@@ -0,0 +1,80 @@
+# include "astro.h"
+
+int biassub		    PROTO((int, char **));
+int cgrid		    PROTO((int, char **));
+int coords		    PROTO((int, char **));
+int cplot		    PROTO((int, char **));
+int csystem		    PROTO((int, char **));
+int ctimes		    PROTO((int, char **));
+int cval		    PROTO((int, char **));
+int czplot		    PROTO((int, char **));
+int drizzle		    PROTO((int, char **));
+int flux		    PROTO((int, char **));
+int gauss		    PROTO((int, char **));
+int gaussfit		    PROTO((int, char **));
+int getvel		    PROTO((int, char **));
+int imfit		    PROTO((int, char **));
+int medianmap		    PROTO((int, char **));
+int mkgauss		    PROTO((int, char **));
+int multifit		    PROTO((int, char **));
+int objload		    PROTO((int, char **));
+int outline		    PROTO((int, char **));
+int polar		    PROTO((int, char **));
+int precess		    PROTO((int, char **));
+int profile		    PROTO((int, char **));
+int region		    PROTO((int, char **));
+int rotcurve		    PROTO((int, char **));
+int scale		    PROTO((int, char **));
+int sexigesimal		    PROTO((int, char **));
+int spec		    PROTO((int, char **));
+int star		    PROTO((int, char **));
+int testfit		    PROTO((int, char **));
+int times		    PROTO((int, char **));
+int transform		    PROTO((int, char **));
+
+static Command cmds[] = {  
+  {"biassub", 	  biassub,      "subtract medianed overscan row or column"},
+  {"cgrid",       cgrid,        "plot sky coordinate grid"},
+  {"coords",  	  coords,       "load coordinates for buffer from file"},
+  {"cplot",       cplot,        "plot vectors in sky coordinates"},
+  {"csystem", 	  csystem,      "convert between coordinate systems"},
+  {"ctimes",  	  ctimes,       "convert between time formats"},
+  {"cval",        cval,         "cosmic ray flux?"},
+  {"czplot",  	  czplot,       "plot scaled vectors in sky coordinates"},
+  {"drizzle", 	  drizzle,      "transform image to image"},
+  {"flux",    	  flux,         "flux in a convex contour"},
+  {"gauss",   	  gauss,        "get statistics on a star, assuming gaussian profile"},
+  {"getvel",      getvel,       "rotcurve to velocities"},
+  {"imfit",   	  imfit,        "fit function"},
+  {"medianmap",   medianmap,    "small median image"},
+  {"mkgauss",     mkgauss,      "generate a 2-D gaussian centered in image"},
+  {"multifit",    multifit,     "fit multi-order spectrum"},
+  {"objload",     objload,      "plot obj data on Ximage "},
+  {"outline",     outline,      "fit outline region"},
+  {"polar",       polar,        "convert polar image to cartesian"},
+  {"precess",     precess,      "precess coordinates"},
+  {"profile",     profile,      "radial profile at X, Y"},
+  {"region",      region,       "define sky region for plot"},
+  {"rotcurve",    rotcurve,     "convert CO images to polar coords"},
+  {"scale",       scale,        "get / set real bzero / bscale values"},
+  {"sexigesimal", sexigesimal,  "convert to/from sexigesimal/decimal"},
+  {"spec",    	  spec,         "extract a spectrum"},
+  {"star",    	  star,         "star stats at rough coords"},
+  {"transform",   transform,    "geometric transformation of image"},
+}; 
+
+/* not currently implemented 
+  {"gaussfit",    gaussfit,     "fit a gaussian to pixels in a region"},
+  {"testfit",     testfit, ""},
+  {"times", , ""},
+*/
+
+void InitAstro () {
+  
+  int i;
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.astro/medianmap.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/medianmap.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/medianmap.c	(revision 12606)
@@ -0,0 +1,111 @@
+# include "astro.h"
+
+int medianmap (int argc, char **argv) {
+  
+  float *temp, *tp;
+  int i, j, k, I0, I1, J0, J1, I, J, n, N;
+  int nx, ny, Nx, Ny, NX, NY, Ignore;
+  float Mv, Nv, Mv2, value, min, max, IgnoreValue;
+  float *In, *Out, *ip;
+  float fx, fy;
+  Buffer *in, *out;
+
+  Ignore = FALSE;
+  if (N = get_argument (argc, argv, "-ignore")) {
+    Ignore = TRUE;
+    remove_argument (N, &argc, argv);
+    IgnoreValue = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  min = 0.45;
+  max = 0.55;
+  if (N = get_argument (argc, argv, "-range")) {
+    remove_argument (N, &argc, argv);
+    min  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    max  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: medianmap (in) (out) Nx Ny [-range min max]\n");
+    fprintf (stderr, "       Nx, Ny specify dimensions of output image\n");
+    fprintf (stderr, "       min, max specify fractional range for sorted average\n");
+    return (FALSE);
+  }
+
+  if ((in  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out = SelectBuffer (argv[2], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  Nx = atof (argv[3]);
+  Ny = atof (argv[4]);
+  NX = in[0].header.Naxis[0];
+  NY = in[0].header.Naxis[1];
+
+  /* duplicate the (in) buffer to the (out), with different size */
+  /* this should probably be a function in misc */
+  fits_free_matrix (&out[0].matrix);
+  fits_free_header (&out[0].header);
+  out[0].bitpix = in[0].bitpix;
+  out[0].unsign = in[0].unsign;
+  out[0].bscale = in[0].bscale;
+  out[0].bzero  = in[0].bzero;
+  fits_copy_header (&in[0].header, &out[0].header);
+  fits_modify (&out[0].header, "NAXIS1", "%d", 1, Nx);
+  fits_modify (&out[0].header, "NAXIS2", "%d", 1, Ny);
+  out[0].header.Naxis[0] = Nx;
+  out[0].header.Naxis[1] = Ny;
+  fits_create_matrix (&out[0].header, &out[0].matrix);
+
+  In = (float *) in[0].matrix.buffer;
+  Out = (float *) out[0].matrix.buffer;
+
+  fx = (float) Nx / NX;
+  fy = (float) Ny / NY;
+
+  nx = 1 + 1/fx;
+  ny = 1 + 1/fy;
+
+  ALLOCATE (temp, float, 2*nx*ny);
+
+  Nv = Mv = Mv2 = 0.0;
+
+  for (j = 0; j < Ny; j++) {
+    J0 = j / fy;
+    J1 = (j + 1) / fy;
+    for (i = 0; i < Nx; i++) {
+      
+      I0 = i / fx;
+      I1 = (i + 1) / fx;
+
+      n = 0;
+      tp = temp;
+      for (J = J0; J < J1; J++) {
+	ip = &In[J*NX + I0];
+	for (I = I0; I < I1; I++, tp++, ip++) {
+	  if (Ignore && (fabs (*ip - IgnoreValue) < 0.01)) continue;
+	  *tp = *ip;
+	  n++;
+	}
+      }
+
+      fsort (temp, n);
+
+      value = 0;
+      N = 0;
+      for (k = min*n; k < max*n; k++) {
+	value += temp[k];
+	N ++;
+      }
+      if (N == 0)
+	Out[j*Nx + i] = 0;
+      else 
+	Out[j*Nx + i] = value / N;
+    }
+  }
+
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.astro/mkgauss.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/mkgauss.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/mkgauss.c	(revision 12606)
@@ -0,0 +1,71 @@
+# include "astro.h"
+
+int mkgauss (int argc, char **argv) {
+  
+  int i, j, Nx, Ny, N;
+  float *in;
+  double Sig_x, Sig_y, Theta;
+  double root1, root2, R, A1, A2, A3;
+  double Sx, Sy, Sxy;
+  double x, y, r, f, Xo, Yo;
+  Buffer *buf;
+
+  Xo = Yo = 0;
+  if (N = get_argument (argc, argv, "-c")) {
+    remove_argument (N, &argc, argv);
+    Xo = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    Yo = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((argc < 3) || (argc > 5)) {
+    fprintf (stderr, "USAGE: mkgauss (buffer) (sigma) [[sy/sx] angle]\n");
+    return (FALSE);
+  }
+
+  /* select input / output buffers */
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  Nx = buf[0].header.Naxis[0];
+  Ny = buf[0].header.Naxis[1];
+  
+  /* gaussian parameters */
+  Sig_x = atof (argv[2]);
+  Sig_y = Sig_x;
+  Theta = 0.0;
+  if (argc > 3) {
+    Sig_y = Sig_x*atof (argv[3]);
+    if (argc == 5) {
+      Theta = atof (argv[4]);
+    }
+  }
+
+  /* given Sig_x, Sig_y, Theta, find Sx, Sy, Sxy */
+  root1 = SQ(1.0 / Sig_y);
+  root2 = SQ(1.0 / Sig_x);
+
+  R = 0.5 * (root1 - root2);
+  A1 = 0.25*(root1 + root2) - 0.5*R*cos(2*RAD_DEG*Theta);
+  A2 = 0.25*(root1 + root2) + 0.5*R*cos(2*RAD_DEG*Theta);
+  A3 = -R*sin(2*RAD_DEG*Theta);
+
+  Sx = 0.5/A1;
+  Sy = 0.5/A2;
+  Sxy = A3;
+
+  /* f = exp (-r), r = (x^2 / 2Sx) + (y^2 / 2Sy) + Sxy*x*y */
+
+  in = (float *) buf[0].matrix.buffer;
+  for (j = 0; j < Ny; j++) {
+    for (i = 0; i < Nx; i++, in++) {
+
+      x = i - Xo;
+      y = j - Yo;
+      r = 0.5*x*x/Sx + 0.5*y*y/Sy + x*y*Sxy;
+      f = exp (-r);
+      *in += f;
+    }
+  }
+
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.astro/multifit.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/multifit.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/multifit.c	(revision 12606)
@@ -0,0 +1,179 @@
+# include "astro.h"
+
+int multifit (int argc, char **argv) {
+  
+  char *p, name[64];
+  double **a, **b, v;
+  int i, j, I, J, n, valid;
+  Vector **Nc, **Nmb, **NMb, **Nwb, **Nmh, **Nml, **Nwo;
+  int *nterm;
+  int Ndim, Norder, Nx, Ny;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: multifit (Norder)\n");
+    return (FALSE);
+  }
+
+  Ndim = 0;
+  Norder = atoi (argv[1]);
+  ALLOCATE (nterm, int, Norder);
+  for (i = 0; i < Norder; i++) {
+    sprintf (name, "nterm:%d", i);
+    p = get_variable (name);
+    nterm[i] = atoi (p); 
+    Ndim += nterm[i];
+    free (p);
+  }
+
+  ALLOCATE (a, double *, Ndim);
+  ALLOCATE (b, double *, Ndim);
+  for (i = 0; i < Ndim; i++) {
+    ALLOCATE (a[i], double, Ndim);
+    ALLOCATE (b[i], double, 1);
+    bzero (a[i], Ndim*sizeof(double));
+    bzero (b[i], sizeof(double));
+  }
+ 
+  ALLOCATE (Nc,  Vector *, Norder);
+  ALLOCATE (NMb, Vector *, Norder);
+  ALLOCATE (Nmb, Vector *, Norder);
+  ALLOCATE (Nwb, Vector *, Norder);
+  ALLOCATE (Nmh, Vector *, Norder - 1);
+  ALLOCATE (Nml, Vector *, Norder - 1);
+  ALLOCATE (Nwo, Vector *, Norder - 1);
+  
+  for (i = 0; i < Norder; i++) {
+    sprintf (name, "c%d", i);
+    if ((Nc[i]  = SelectVector (name, ANYVECTOR, TRUE)) == NULL) goto escape;
+    sprintf (name, "Mb%d", i);
+    if ((NMb[i] = SelectVector (name, OLDVECTOR, TRUE)) == NULL) goto escape;
+    sprintf (name, "mb%d", i);
+    if ((Nmb[i] = SelectVector (name, OLDVECTOR, TRUE)) == NULL) goto escape;
+    sprintf (name, "wb%d", i);
+    if ((Nwb[i] = SelectVector (name, OLDVECTOR, TRUE)) == NULL) goto escape;
+  }
+  for (i = 0; i < Norder - 1; i++) {
+    sprintf (name, "ml%d", i);
+    if ((Nml[i] = SelectVector (name, OLDVECTOR, TRUE)) == NULL) goto escape;
+    sprintf (name, "mh%d", i);
+    if ((Nmh[i] = SelectVector (name, OLDVECTOR, TRUE)) == NULL) goto escape;
+    sprintf (name, "wo%d", i);
+    if ((Nwo[i] = SelectVector (name, OLDVECTOR, TRUE)) == NULL) goto escape;
+  }
+
+  Ny = 0;
+  for (i = 0; i < Norder; i++) {
+    for (j = 0; j < nterm[i]; j++, Ny++) {
+      Nx = 0;
+      valid = FALSE;
+      for (I = 0; I < Norder; I++) {
+	if (I == i - 1) { 
+	  for (J = 0; J < nterm[I]; J++) {
+	    v = 0;
+	    for (n = 0; n < Nwo[i-1][0].Nelements; n++) {
+	      v += -pow (Nwo[i-1][0].elements[n], (double)(j+J));
+	    }
+	    a[Ny][Nx] = v;
+	    Nx ++;
+	  }
+	  valid = TRUE;
+	}
+	if (I == i + 1) { 
+	  for (J = 0; J < nterm[I]; J++) {
+	    v = 0;
+	    for (n = 0; n < Nwo[i][0].Nelements; n++) {
+	      v += -pow (Nwo[i][0].elements[n], (double)(j+J));
+	    }
+	    a[Ny][Nx] = v;
+	    Nx ++;
+	  }
+	  valid = TRUE;
+	}
+	if (I == i) { 
+	  for (J = 0; J < nterm[I]; J++) {
+	    v = 0;
+	    for (n = 0; n < Nwb[i][0].Nelements; n++) {
+	      v += pow (Nwb[i][0].elements[n], (double)(j+J));
+	    }
+	    if (i > 0) {
+	      for (n = 0; n < Nwo[i-1][0].Nelements; n++) {
+		v += pow (Nwo[i-1][0].elements[n], (double)(j+J));
+	      }
+	    }
+	    if (i < Norder - 1) {
+	      for (n = 0; n < Nwo[i][0].Nelements; n++) {
+		v += pow (Nwo[i][0].elements[n], (double)(j+J));
+	      }
+	    }
+	    a[Ny][Nx] = v;
+	    Nx ++;
+	  }
+	  valid = TRUE;
+	}
+	if (!valid) {
+	  Nx += nterm[I];
+	}
+      }
+    }
+  }
+
+  Ny = 0;
+  for (i = 0; i < Norder; i++) {
+    for (j = 0; j < nterm[i]; j++, Ny++) {
+      v = 0;
+      for (n = 0; n < Nwb[i][0].Nelements; n++) {
+	v += NMb[i][0].elements[n]*pow (Nwb[i][0].elements[n], (double)j);
+	v -= Nmb[i][0].elements[n]*pow (Nwb[i][0].elements[n], (double)j);
+      }
+      if (i > 0) {
+	for (n = 0; n < Nwo[i-1][0].Nelements; n++) {
+	  v += Nmh[i-1][0].elements[n] * pow (Nwo[i-1][0].elements[n], (double)j);
+	  v -= Nml[i-1][0].elements[n] * pow (Nwo[i-1][0].elements[n], (double)j);
+	}
+      }
+      if (i < Norder - 1) {
+	for (n = 0; n < Nwo[i][0].Nelements; n++) {
+	  v += Nml[i][0].elements[n] * pow (Nwo[i][0].elements[n], (double)j);
+	  v -= Nmh[i][0].elements[n] * pow (Nwo[i][0].elements[n], (double)j);
+	}
+      }
+      b[Ny][0] = v;
+    }
+  }
+  gaussj (a, Ndim, b, 1);
+
+  Ny = 0;
+  for (i = 0; i < Norder; i++) {
+    Nc[i][0].Nelements = nterm[i];
+    REALLOCATE (Nc[i][0].elements, float, nterm[i]);
+    for (j = 0; j < nterm[i]; j++, Ny++) {
+      Nc[i][0].elements[j] = b[Ny][0];
+    }
+  }
+
+  for (i = 0; i < Ndim; i++) {
+    free (a[i]);
+    free (b[i]);
+  }
+  free (a);
+  free (b);
+  free (nterm);
+  free (Nc);
+  free (NMb);
+  free (Nmb);
+  free (Nwb);
+  free (Nmh);
+  free (Nml);
+  free (Nwo);
+  
+  return (TRUE);
+  
+ escape: 
+  fprintf (stderr, "syntax error\n");
+  return (FALSE);
+  
+}
+
+
+
+
Index: /tags/start/Ohana/src/opihi/cmd.astro/objload.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/objload.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/objload.c	(revision 12606)
@@ -0,0 +1,102 @@
+# include "dvo.h"
+# define CHAR_LINE 104
+# define NBLOCK 100
+
+int objload (int argc, char **argv) {
+  
+  int i, nstar, N, Nout, n, Type, type, NSTAR, Nline, status;
+  double *X, *Y;
+  FILE *f;
+  char *buffer, *line;
+  int Ximage, Nimage;
+  
+  Nimage = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Nimage = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (&Ximage, &Nimage)) return (FALSE);
+
+  Type = 0;
+  if (N = get_argument (argc, argv, "-t")) {
+    remove_argument (N, &argc, argv);
+    Type = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: load (overlay) <filename>\n");
+    return (FALSE);
+  }
+
+  if (!SelectOverlay (argv[1], &n)) return (FALSE);
+
+  f = fopen (argv[2], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't find object file %s\n", argv[2]);
+    return (FALSE);
+  }
+
+  /* read average values from first line */
+  ALLOCATE (line, char, 129);
+  scan_line (f, line);
+
+  nstar = 0;
+  NSTAR = 1000;
+  ALLOCATE (X, double, NSTAR);
+  ALLOCATE (Y, double, NSTAR);
+  ALLOCATE (buffer, char, CHAR_LINE*NBLOCK);
+
+  /* read in data from obj file */
+  while ((Nline = fread (buffer, CHAR_LINE, NBLOCK, f)) > 0) {
+    for (i = 0; i < Nline; i++) {
+      /* we are now using all entries on the *.obj line */
+      status = sscanf (&buffer[i*CHAR_LINE], "%d %lf %lf",  &type, &X[nstar], &Y[nstar]);
+      if (Type && (Type != type)) continue;
+      nstar ++;
+      if (nstar == NSTAR) {
+	NSTAR += 1000;
+	REALLOCATE (X, double, NSTAR);
+	REALLOCATE (Y, double, NSTAR);
+      }
+    }
+  }
+  fclose (f);
+  free (buffer);
+
+  write (Ximage, "LOAD", 4); /* force Ximage to look for the incoming image */
+  sprintf (line, "OVER %9d ", n);
+  write (Ximage, line, 16);
+  
+  ALLOCATE (buffer, char, 66000);
+  bzero (buffer, 65536);
+  for (Nout = i = 0; i < nstar; i++, Nout++) {
+    snprintf (&buffer[Nout*128], 129, "%15s %20.10f %20.10f %20.10f %20.10f ", "BOX", X[i], Y[i], 5.0, 5.0);
+    if (Nout == 512) {
+      sprintf (line, "NLINES  %7d ", Nout);
+      write (Ximage, line, 16);
+      write (Ximage, buffer, Nout*128);
+      bzero (buffer, 65536);
+      Nout = -1;
+    }
+  }
+
+  if (Nout) {
+    sprintf (line, "NLINES  %7d ", Nout);
+    write (Ximage, line, 16);
+    write (Ximage, buffer, Nout*128);
+  }
+  sprintf (line, "DONE ");
+  write (Ximage, line, 16);
+
+  free (X);
+  free (Y);
+
+  free (buffer);
+  free (line);
+
+  fprintf (stderr, "loaded %d objects\n", nstar);
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.astro/outline.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/outline.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/outline.c	(revision 12606)
@@ -0,0 +1,303 @@
+# include "astro.h"
+
+float par[5];
+float dpar[5];
+float Dpar[5];
+float outline_chi (float, float *, int, int, float *);
+
+int outline (int argc, char **argv) {
+  
+  int i, j, k, Npar, BigChange, ABigChange;
+  float Io, *in, ochisq, dchi, chisq, chisq_p, chisq_m, dp, tmp_par;
+  float curve, frac;
+  Buffer *buf;
+
+  if (argc != 9) {
+    fprintf (stderr, "USAGE: outline x y dx dy dxy Io (buffer) Npar\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[7], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  par[0] = atof(argv[1]);
+  par[1] = atof(argv[2]);
+  par[2] = atof(argv[3]);
+  par[3] = atof(argv[4]);
+  par[4] = atof(argv[5]);
+  Io = atof(argv[6]);
+  Npar = atof (argv[8]);
+
+  dpar[0] = 10;
+  dpar[1] = 10;
+  dpar[2] = 10;
+  dpar[3] = 10;
+  dpar[4] = 10;
+
+  Dpar[0] = 10;
+  Dpar[1] = 10;
+  Dpar[2] = 10;
+  Dpar[3] = 10;
+  Dpar[4] = 10;
+
+  in = (float *) buf[0].matrix.buffer;
+
+  chisq = outline_chi (Io, in, buf[0].matrix.Naxis[0], buf[0].matrix.Naxis[1], &frac);
+  fprintf (stderr, "chisq (1): %f\n", chisq);
+  
+  for (j = 0; j < 15; j++) {
+
+    /*
+    if (!(j % 3)) {
+      chisq = outline_chi (Io, in, buf[0].matrix.Naxis[0], buf[0].matrix.Naxis[1], &frac);
+      for (k = 0; (k < 3) && (fabs (frac) > 0.3); k++) {
+	tmp1 = par[2];
+	tmp2 = par[3];
+	par[2] *= 1 + 0.1*frac;
+	par[3] *= 1 + 0.1*frac;
+	nchisq = outline_chi (Io, in, buf[0].matrix.Naxis[0], buf[0].matrix.Naxis[1], &frac);
+	if (nchisq > chisq) {
+	  par[2] = tmp1;
+	  par[3] = tmp2;
+	  k = 3;
+	} else {
+	  chisq = nchisq;
+	}
+	fprintf (stderr, "frac: %f  %f %f   %f\n", frac, par[2], par[3], chisq);
+      }
+    }
+    */
+    
+    ABigChange = FALSE;
+    ochisq = chisq;
+    for (i = 4; i >= 0; i--) {
+      /* find +chisq, -chisq for this par & adjust par as needed */
+
+      for (k = 0, BigChange = TRUE; (k < 3) && BigChange; k++) {
+	tmp_par = par[i];
+	par[i] = tmp_par + dpar[i];
+	chisq_p = outline_chi (Io, in, buf[0].matrix.Naxis[0], buf[0].matrix.Naxis[1], &frac);
+	par[i] = tmp_par - dpar[i];
+	chisq_m = outline_chi (Io, in, buf[0].matrix.Naxis[0], buf[0].matrix.Naxis[1], &frac);
+	
+	/* have we braketted a minimum? (curve < 0) */
+	curve = (chisq_p - chisq) * (chisq - chisq_m);
+	if (curve > 0) {
+	  dp = 2*dpar[i];
+	} else {
+	  dp = 0.5 * dpar[i] * (chisq_m - chisq_p) / (chisq_m + chisq_p - 2*chisq);
+	}      
+	if (chisq_m + chisq_p - 2*chisq == 0) dp = 0;
+	/* don't let extrapolation go too far */
+	if (fabs (dp) > 2*fabs(dpar[i])) { dp = SIGN(dp) * fabs (2*dpar[i]); }
+	
+	par[i] = tmp_par + dp;
+	chisq = outline_chi (Io, in, buf[0].matrix.Naxis[0], buf[0].matrix.Naxis[1], &frac);
+	
+	BigChange = FALSE;
+	if (chisq <= 1.001*ochisq) {
+	  /* got better */
+	  dchi = (ochisq - chisq) / ochisq; 
+	  if ((dchi > 0.03) || (curve > 0)) BigChange = TRUE;
+	} else {
+	  par[i] = tmp_par;
+	  chisq = ochisq;
+	  if (chisq_m < chisq) {
+	    chisq = chisq_m;
+	    par[i] = tmp_par - dpar[i];
+	  }	
+	  if (chisq_p < chisq) {
+	    chisq = chisq_p;
+	    par[i] = tmp_par + dpar[i];
+	  }	
+	}	
+	/*
+	fprintf (stderr, "try: %d  %f   ", i, chisq);
+	for (k = 0; k < 5; k++) {
+	  fprintf (stderr, "%f ", par[k]);
+	}
+	fprintf (stderr, "\n");
+	*/
+	ochisq = chisq;
+	ABigChange |= BigChange;
+      }
+      if (!BigChange) dpar[i] *= 0.8;
+    }
+
+    if (ABigChange) {
+      for (i = 0; i < 5; i++) {
+	dpar[i] = Dpar[i];
+      }
+    }
+
+    fprintf (stderr, "try: %d  %f   ", j, chisq);
+    for (i = 0; i < 5; i++) {
+      fprintf (stderr, "%f ", par[i]);
+    }
+    fprintf (stderr, "\n          ");
+    for (i = 0; i < 5; i++) {
+      fprintf (stderr, "%f ", dpar[i]);
+    }
+    fprintf (stderr, "\n");
+    dchi -= chisq;
+
+  }
+
+    /* code to draw dots on Ximage */
+    {
+      char *buffer, *line;
+      int Nline, Nimage, Ximage;
+      float xp, yp, x, y;
+      float dx, dy, theta, t, dt;
+      
+      Nimage = -1;
+      if (!GetImage (&Ximage, &Nimage)) return (FALSE);
+      
+      ALLOCATE (buffer, char, 65536);  /* space for 512 lines of 128 bytes */
+      bzero (buffer, 65536);
+      ALLOCATE (line, char, 1024);     /* space to read the file */
+      Nline = 0;
+      
+      write (Ximage, "LOAD", 4); /* force Ximage to look for the incoming image */
+      sprintf (line, "OVER %9d ", 0);
+      write (Ximage, line, 16);
+      
+      dx = par[2];
+      dy = par[3];
+      dt = 1 / MAX (dx, dy);
+      theta = par[4];
+      
+      for (t = 0; t < 6.3; t += dt) {
+	xp = dx * cos (t);
+	yp = dy * sin (t);
+	
+	x = xp * cos (theta * RAD_DEG) - yp * sin (theta * RAD_DEG) + par[0];
+	y = xp * sin (theta * RAD_DEG) + yp * cos (theta * RAD_DEG) + par[1];
+	
+	sprintf (&buffer[Nline*128], "%15s %20.10f %20.10f %20.10f %20.10f ", "BOX", x, y, 1.0, 1.0);
+	Nline ++;
+	
+	if (Nline >= 510) {
+	  sprintf (line, "NLINES  %7d ", Nline);
+	  write (Ximage, line, 16);
+	  write (Ximage, buffer, Nline*128);
+	  bzero (buffer, 65536);
+	  Nline = 0;
+	}
+      }
+      
+      sprintf (line, "NLINES  %7d ", Nline);
+      write (Ximage, line, 16);
+      write (Ximage, buffer, Nline*128);
+      sprintf (line, "DONE ");
+      write (Ximage, line, 16);
+      free (buffer);
+      free (line);
+      
+    }
+
+  return (TRUE);
+
+}
+
+/* par[0] = x
+   par[1] = y
+   par[2] = dx
+   par[3] = dy
+   par[4] = dxy
+   
+   ellipse is:  
+
+   ((X-x)/dx)^2 + ((Y-y)/dy)^2 + (X-x)(Y-y)dxy = 1
+  
+   (yp/dy)^2 + xp yp dxy + (xp/dx)^2 - 1 = 0
+
+   yp^2 + yp xp dxy dy^2 + xp^2 (dy/dx)^2 - dy^2 = 0
+
+*/
+
+float outline_chi (float Io, float *in, int Nx, int Ny, float *frac) {
+
+  int npts, xo, yo, x, y;
+  float xp, yp, dx, dy, theta;
+  float t, dt, dv, Dv;
+  float chisq, v, Frac;
+
+  /* 
+  if (!SelectVector (&Nvec, "diffs", ANYVECTOR)) return (FALSE);
+  if (!SelectVector (&Nvec2, "angle", ANYVECTOR)) return (FALSE);
+  if (!SelectVector (&Nvecx, "xdif", ANYVECTOR)) return (FALSE);
+  if (!SelectVector (&Nvecy, "ydif", ANYVECTOR)) return (FALSE);
+  */
+
+  dx = par[2];
+  dy = par[3];
+  theta = par[4];
+  dt = 1 / MAX (dx, dy);
+
+  Frac = 0;
+  chisq = 0;
+  npts = 0;
+  xo = -1; yo = -1;  /* an impossible coordinate */
+
+  /*
+  Npts = 1000;
+  REALLOCATE (vectors[Nvec].elements, float, Npts);
+  REALLOCATE (vectors[Nvec2].elements, float, Npts);
+  REALLOCATE (vectors[Nvecx].elements, float, Npts);
+  REALLOCATE (vectors[Nvecy].elements, float, Npts);
+  */
+
+  for (t = 0; t < 6.3; t += dt) {
+    xp = dx * cos (t);
+    yp = dy * sin (t);
+    
+    x = xp * cos (theta * RAD_DEG) - yp * sin (theta * RAD_DEG) + par[0];
+    y = xp * sin (theta * RAD_DEG) + yp * cos (theta * RAD_DEG) + par[1];
+    
+    if ((x == xo) && (y == yo)) continue;
+    xo = x; yo = y;
+
+    if ((x >= 0) && (x < Nx) && (y >= 0) && (y < Ny)) {
+      v = in[y*Nx + x];
+      if (v > 0) {
+	Dv = v - Io;
+	dv = v + 0.2 * fabs (Dv);
+	chisq += Dv * Dv / dv;
+	if (Dv > sqrt(dv)) Frac += 1.0;
+	if (Dv < sqrt(dv)) Frac -= 1.0;
+	/*
+	vectors[Nvec].elements[npts] = Dv;
+	vectors[Nvec2].elements[npts] = t*DEG_RAD;
+	vectors[Nvecx].elements[npts] = x;
+	vectors[Nvecy].elements[npts] = y;
+	*/
+	npts ++;
+	/* 
+	if (npts == Npts - 1) {
+	  Npts += 1000;
+	  REALLOCATE (vectors[Nvec].elements, float, Npts);
+	  REALLOCATE (vectors[Nvec2].elements, float, Npts);
+	  REALLOCATE (vectors[Nvecx].elements, float, Npts);
+	  REALLOCATE (vectors[Nvecy].elements, float, Npts);
+	}
+	*/
+      }
+    }
+  }
+  /* 
+  vectors[Nvec].Nelements = npts;
+  vectors[Nvec2].Nelements = npts;
+  vectors[Nvecx].Nelements = npts;
+  vectors[Nvecy].Nelements = npts;
+  */
+
+  chisq = chisq / npts;
+  *frac = Frac / npts;
+  if (npts == 0) {
+    chisq = 1e8;
+    *frac = -1.0;
+  }
+
+  return (chisq);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.astro/outline2.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/outline2.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/outline2.c	(revision 12606)
@@ -0,0 +1,354 @@
+# include "astro.h"
+
+int Npts;
+float *xs, *ys, *zs;
+float par[5];
+float dpar[5];
+float Dpar[5];
+float outline_chi (float, float *);
+int plot_outline ();
+
+int outline (int argc, char **argv) {
+  
+  int i, j, k, Nx, Ny, NPTS, BigChange;
+  float dIo, Io, ochisq, dchi, chisq, chisq_p, chisq_m, dp;
+  float tmp_par, curve, value;
+  float *in;
+  Buffer *buf;
+
+  if (argc != 9) {
+    fprintf (stderr, "USAGE: outline x y dx dy dxy Io dIo (buffer)\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[8], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  par[0] = atof(argv[1]);
+  par[1] = atof(argv[2]);
+  par[2] = atof(argv[3]);
+  par[3] = atof(argv[4]);
+  par[4] = atof(argv[5]);
+  Io = atof(argv[6]);
+  dIo = atof(argv[7]);
+
+  dpar[0] = 10;
+  dpar[1] = 10;
+  dpar[2] = 10;
+  dpar[3] = 10;
+  dpar[4] = 10;
+
+  Dpar[0] = 10;
+  Dpar[1] = 10;
+  Dpar[2] = 10;
+  Dpar[3] = 10;
+  Dpar[4] = 10;
+
+  in = (float *) buf[0].matrix.buffer;
+
+  /* find all pixels within range Io-dIo : Io+dIo, in region about center guess */
+
+  Nx = buf[0].matrix.Naxis[0];  
+  Ny = buf[0].matrix.Naxis[1];
+  Npts = 0;
+  NPTS = 1000;
+  ALLOCATE (xs, float, NPTS);
+  ALLOCATE (ys, float, NPTS);
+  ALLOCATE (zs, float, NPTS);
+  for (j = par[1]-2*par[3]; j < par[1]+2*par[3]; j++) {
+    if (j < 0) continue;
+    if (j >= buf[0].matrix.Naxis[1]) continue;
+    for (i = par[0]-2*par[2]; i < par[0]+2*par[2]; i++) {
+      if (i < 0) continue;
+      if (i >= buf[0].matrix.Naxis[0]) continue;
+      value = in[i + Nx*j];
+      if (fabs (value - Io) < dIo) {
+	xs[Npts] = i;
+	ys[Npts] = j;
+	zs[Npts] = value;
+	Npts ++;
+	if (Npts == NPTS) {
+	  NPTS += 1000;
+	  REALLOCATE (xs, float, NPTS);
+	  REALLOCATE (ys, float, NPTS);
+	  REALLOCATE (zs, float, NPTS);
+	}
+      }
+    }
+  }
+
+  if (Npts == 0) {
+    fprintf (stderr, "no valid points in box, try again\n");
+    free (xs);
+    free (ys);
+    free (zs);
+    return (FALSE);
+  }
+
+  plot_outline ();
+  chisq = outline_chi (Io, in);
+  fprintf (stderr, "starting chisq: %f for %d pts\n", chisq, Npts);
+
+# if (1)
+  for (j = 0; j < 15; j++) {
+    
+    ochisq = chisq;
+    for (i = 0; i < 5; i++) {
+      /* find +chisq, -chisq for this par & adjust par as needed */
+
+      for (k = 0, BigChange = TRUE; (k < 3) && BigChange; k++) {
+	tmp_par = par[i];
+	par[i] = tmp_par + dpar[i];
+	chisq_p = outline_chi (Io, in);
+	par[i] = tmp_par - dpar[i];
+	chisq_m = outline_chi (Io, in);
+	
+	/* have we braketted a minimum? (curve < 0) */
+	curve = (chisq_p - chisq) * (chisq - chisq_m);
+	if (curve > 0) {
+	  dp = 2*dpar[i];
+	} else {
+	  dp = 0.5 * dpar[i] * (chisq_m - chisq_p) / (chisq_m + chisq_p - 2*chisq);
+	}      
+	if (chisq_m + chisq_p - 2*chisq == 0) dp = 0;
+	/* don't let extrapolation go too far */
+	if (fabs (dp) > 2*fabs(dpar[i])) { dp = SIGN(dp) * fabs (2*dpar[i]); }
+	
+	par[i] = tmp_par + dp;
+	chisq = outline_chi (Io, in);
+	
+	BigChange = FALSE;
+	if (chisq <= 1.001*ochisq) {
+	  /* got better */
+	  dchi = (ochisq - chisq) / ochisq; 
+	  if ((dchi > 0.03) || (curve > 0)) BigChange = TRUE;
+	} else {
+	  par[i] = tmp_par;
+	  chisq = ochisq;
+	  if (chisq_m < chisq) {
+	    chisq = chisq_m;
+	    par[i] = tmp_par - dpar[i];
+	  }	
+	  if (chisq_p < chisq) {
+	    chisq = chisq_p;
+	    par[i] = tmp_par + dpar[i];
+	  }	
+	}	
+	ochisq = chisq;
+      }
+      if (!BigChange) dpar[i] *= 0.8;
+    }
+
+    fprintf (stderr, "try: %d  %f   ", j, chisq);
+    for (i = 0; i < 5; i++) {
+      fprintf (stderr, "%f ", par[i]);
+    }
+    fprintf (stderr, "\n          ");
+    for (i = 0; i < 5; i++) {
+      fprintf (stderr, "%f ", dpar[i]);
+    }
+    fprintf (stderr, "\n");
+    dchi -= chisq;
+
+  }
+# endif
+
+  free (xs);
+  free (ys);
+  free (zs);
+  
+  plot_outline ();
+  return (TRUE);
+
+}
+
+/* par[0] = x
+   par[1] = y
+   par[2] = dx
+   par[3] = dy
+   par[4] = dxy
+   
+    xp = par[2] * cos (t);
+    yp = par[3] * sin (t);
+    
+    x = xp * cos (par[4] * RAD_DEG) - yp * sin (par[4] * RAD_DEG) + par[0];
+    y = xp * sin (par[4] * RAD_DEG) + yp * cos (par[4] * RAD_DEG) + par[1];
+
+*/
+
+# if (1)
+
+float outline_chi (float Io, float *in) {
+
+  int i;
+  float theta, phi;
+  float xp, yp, x, y;
+  float chisq, R2;
+
+  chisq = 0;
+
+  for (i = 0; i < Npts; i++) {
+    
+    phi = atan2 (ys[i] - par[1], xs[i] - par[0]) - RAD_DEG * par[4];
+    /* find a point:
+
+       xp, yp such that atan (r2 sin(phi), r1 cos(phi)) == theta 
+
+       tan (theta) = r2 sin(phi) / r1 cos (phi)
+
+       (r1/r2) tan(theta) = sin(phi) / cos (phi);
+       (r1/r2) tan(theta) = tan (phi)
+
+       phi = atan2 (r1 sin(theta), r2 cos(theta))
+    */
+
+    theta = atan2 (par[2]*sin(phi), par[3]*cos(phi));
+
+    /* this is the point on the ellipse at the same angle as ref point */
+    /* this is wrong, but close -- tends to make ellipses too fat */
+    xp = par[2] * cos (theta);
+    yp = par[3] * sin (theta);
+    
+    x = xp * cos (par[4] * RAD_DEG) - yp * sin (par[4] * RAD_DEG) + par[0];
+    y = xp * sin (par[4] * RAD_DEG) + yp * cos (par[4] * RAD_DEG) + par[1];
+
+    R2 = sqrt (SQ (x - xs[i]) + SQ (y - ys[i]));
+
+    /*
+    Dv = zs[i] - Io;
+    dv = fabs(zs[i]);
+    F2 = Dv * Dv / dv;
+    */
+
+    chisq += R2;
+
+  }
+
+  chisq = chisq / Npts;
+  return (chisq);
+
+}
+
+# else 
+
+float outline_chi (float Io, float *in) {
+
+  int i;
+  float theta, theta1, theta2;
+  float xp, yp, x, y;
+  float chisq, dv, Dv, R2, F2, R, dR;
+
+  int Nvec, Nvec2, Nvecx, Nvecy, Nv, nv;
+
+  chisq = 0;
+
+  nv = 0;
+  Nv = 1000;
+  if (!SelectVector (&Nvec, "dR", ANYVECTOR)) return (FALSE);
+  if (!SelectVector (&Nvec2, "dF", ANYVECTOR)) return (FALSE);
+  if (!SelectVector (&Nvecx, "x", ANYVECTOR)) return (FALSE);
+  if (!SelectVector (&Nvecy, "y", ANYVECTOR)) return (FALSE);
+  REALLOCATE (vectors[Nvec].elements, float, Nv);
+  REALLOCATE (vectors[Nvec2].elements, float, Nv);
+  REALLOCATE (vectors[Nvecx].elements, float, Nv);
+  REALLOCATE (vectors[Nvecy].elements, float, Nv);
+
+  for (i = 0; i < Npts; i++) {
+    
+    theta1 = atan2 (ys[i] - par[1], xs[i] - par[0]) - RAD_DEG * par[4];
+    theta = atan2 (par[2]*sin(theta1), par[3]*cos(theta1));
+
+    xp = par[2] * cos (theta);
+    yp = par[3] * sin (theta);
+    
+    x = xp * cos (par[4] * RAD_DEG) - yp * sin (par[4] * RAD_DEG) + par[0];
+    y = xp * sin (par[4] * RAD_DEG) + yp * cos (par[4] * RAD_DEG) + par[1];
+
+    R2 = SQ (x - xs[i]) + SQ (y - ys[i]);
+
+    /* 
+    Dv = fabs (zs[i] - Io) + 1;
+    dv = zs[i] + 0.2 * fabs (Dv);
+    F2 = Dv * Dv / dv;
+    */
+
+    vectors[Nvec].elements[nv] = x;
+    vectors[Nvec2].elements[nv] = y;
+    vectors[Nvecx].elements[nv] = xs[i];
+    vectors[Nvecy].elements[nv] = ys[i];
+    nv ++;
+    if (nv == Nv - 1) {
+      Nv += 1000;
+      REALLOCATE (vectors[Nvec].elements, float, Nv);
+      REALLOCATE (vectors[Nvec2].elements, float, Nv);
+      REALLOCATE (vectors[Nvecx].elements, float, Nv);
+      REALLOCATE (vectors[Nvecy].elements, float, Nv);
+    }
+
+    /* typical distance might be 1 - 10 pix,
+       typical z error might be 100 cts */
+    chisq += R2; 
+
+  }
+  vectors[Nvec].Nelements = nv;
+  vectors[Nvec2].Nelements = nv;
+  vectors[Nvecx].Nelements = nv;
+  vectors[Nvecy].Nelements = nv;
+
+  chisq = chisq / Npts;
+  return (chisq);
+
+}
+# endif
+
+int plot_outline () {
+  
+  char *buffer, *line;
+  int Nline, Nimage, Ximage;
+  float xp, yp, x, y;
+  float dx, dy, theta, t, dt;
+  
+  Nimage = -1;
+  if (!GetImage (&Ximage, &Nimage)) return (FALSE);
+  
+  ALLOCATE (buffer, char, 65536);  /* space for 512 lines of 128 bytes */
+  bzero (buffer, 65536);
+  ALLOCATE (line, char, 1024);     /* space to read the file */
+  Nline = 0;
+  
+  write (Ximage, "LOAD", 4); /* force Ximage to look for the incoming image */
+  sprintf (line, "OVER %9d ", 0);
+  write (Ximage, line, 16);
+  
+  dx = par[2];
+  dy = par[3];
+  dt = 1 / MAX (dx, dy);
+  theta = par[4];
+  
+  for (t = 0; t < 6.3; t += dt) {
+    xp = dx * cos (t);
+    yp = dy * sin (t);
+    
+    x = xp * cos (theta * RAD_DEG) - yp * sin (theta * RAD_DEG) + par[0];
+    y = xp * sin (theta * RAD_DEG) + yp * cos (theta * RAD_DEG) + par[1];
+    
+    sprintf (&buffer[Nline*128], "%15s %20.10f %20.10f %20.10f %20.10f ", "BOX", x, y, 1.0, 1.0);
+    Nline ++;
+    
+    if (Nline >= 510) {
+      sprintf (line, "NLINES  %7d ", Nline);
+      write (Ximage, line, 16);
+      write (Ximage, buffer, Nline*128);
+      bzero (buffer, 65536);
+      Nline = 0;
+    }
+  }
+  
+  sprintf (line, "NLINES  %7d ", Nline);
+  write (Ximage, line, 16);
+  write (Ximage, buffer, Nline*128);
+  sprintf (line, "DONE ");
+  write (Ximage, line, 16);
+  free (buffer);
+  free (line);
+  
+}
Index: /tags/start/Ohana/src/opihi/cmd.astro/polar.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/polar.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/polar.c	(revision 12606)
@@ -0,0 +1,71 @@
+# include "astro.h"
+
+int polar (int argc, char **argv) {
+  
+  double Lo, dL, Do, dD, Mo, dM, No, dN;
+  double xo, yo, Xo, Yo;
+  double x, y, r, t;
+  float *Vin, *Vout, *Vmask;
+  int i, j, nx, ny, Nx, Ny;
+  int X, Y;
+  Buffer *in, *out, *mask;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: polar in out\n");
+    return (FALSE);
+  }
+
+  if ((in   = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out  = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((mask = SelectBuffer (argv[3], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  Nx = out[0].matrix.Naxis[0];
+  Ny = out[0].matrix.Naxis[1];
+  nx = mask[0].matrix.Naxis[0];
+  ny = mask[0].matrix.Naxis[1];
+  if ((Nx != nx) && (Ny != ny)) {
+    fprintf (stderr, "output and mask must have same dimensions\n");
+    return (FALSE);
+  }
+  nx = in[0].matrix.Naxis[0];
+  ny = in[0].matrix.Naxis[1];
+
+  /* we expect the output image to have units of longitude and distance */
+  fits_scan (&in[0].header, "CRVAL1", "%lf", 1, &Lo);
+  fits_scan (&in[0].header, "CDELT1", "%lf", 1, &dL);
+  fits_scan (&in[0].header, "CRPIX1", "%lf", 1, &xo);
+  fits_scan (&in[0].header, "CRVAL2", "%lf", 1, &Do);
+  fits_scan (&in[0].header, "CDELT2", "%lf", 1, &dD);
+  fits_scan (&in[0].header, "CRPIX2", "%lf", 1, &yo);
+
+  /* we expect the input image to have units of distance X and Y */
+  fits_scan (&out[0].header, "CRVAL1", "%lf", 1, &Mo);
+  fits_scan (&out[0].header, "CDELT1", "%lf", 1, &dM);
+  fits_scan (&out[0].header, "CRPIX1", "%lf", 1, &Xo);
+  fits_scan (&out[0].header, "CRVAL2", "%lf", 1, &No);
+  fits_scan (&out[0].header, "CDELT2", "%lf", 1, &dN);
+  fits_scan (&out[0].header, "CRPIX2", "%lf", 1, &Yo);
+
+  Vin  = (float *)in[0].matrix.buffer;
+  Vout = (float *)out[0].matrix.buffer;
+  Vmask = (float *)mask[0].matrix.buffer;
+  for (j = 0; j < Ny; j++) {
+    for (i = 0; i < Nx; i++, Vout++, Vmask++) {
+      x = (i - Xo) * dM + Mo;
+      y = (j - Yo) * dN + No;
+      r = hypot(x, y);
+      t = DEG_RAD*atan2 (y, x);
+      while (t < 360.0) {t += 360.0;}
+      while (t > 360.0) {t -= 360.0;}
+      X = (t - Lo) / dL + xo;
+      Y = (r - Do) / dD + yo;
+      if ((X >= 0) && (X < nx) && (Y >= 0) && (Y < ny)) {
+	*Vout += Vin[Y*nx + X];
+	*Vmask += 1;
+      }
+    }
+  }
+
+ return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.astro/precess.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/precess.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/precess.c	(revision 12606)
@@ -0,0 +1,112 @@
+# include "astro.h"
+
+int precess (int argc, char **argv) {
+
+  int i, Julian, Besselian;
+  double T, in_epoch, out_epoch;
+  double A, D, RA, DEC, zeta, z, theta;
+  double SA, CA, SD, CD;
+  Vector *xvec, *yvec;
+
+  Besselian = Julian = 0;
+  Besselian = get_argument (argc, argv, "B");
+  Julian    = get_argument (argc, argv, "J");
+
+  in_epoch = out_epoch = 2000.0;
+  if (argc != 5) {
+    fprintf (stderr, "USAGE:  precess (from) (to) RA DEC \n");
+    fprintf (stderr, "   you may use B for B1950.0 or J for J2000.0\n");
+    return (FALSE);
+  }
+
+  if (!Julian && !Besselian) { /* assume Julian! */
+    in_epoch  = get_epoch (argv[1], 'J');
+    out_epoch = get_epoch (argv[2], 'J');
+  }
+
+  if ((Julian == 1) && !Besselian) {
+    in_epoch  = 2000.0;
+    out_epoch = get_epoch(argv[2], 'J');
+  }
+
+  if ((Julian == 2) && !Besselian) {
+    in_epoch  = get_epoch(argv[1], 'J');
+    out_epoch = 2000.0;
+  }
+
+  if ((Besselian == 1) && !Julian) {
+    in_epoch  = BtoJ(1950.0); 
+    out_epoch = get_epoch(argv[2], 'B'); 
+  }
+
+  if ((Besselian == 2) && !Julian) {
+    in_epoch  = get_epoch(argv[1], 'B'); 
+    out_epoch = BtoJ(1950.0); 
+  }
+  
+  if (Julian && Besselian) {
+    if (Julian > Besselian) {
+      in_epoch  = BtoJ(1950.0); 
+      out_epoch = 2000.0;
+    }
+    else {
+      in_epoch  = 2000.0;
+      out_epoch = BtoJ(1950.0); 
+    }
+  }
+
+  fprintf (stderr, "converting from J%f to J%f\n", in_epoch, out_epoch);
+
+  T = (out_epoch - in_epoch) / 100.0;
+  
+  zeta  = RAD_DEG*(0.6406161*T + 0.0000839*T*T + 0.0000050*T*T*T);
+  theta = RAD_DEG*(0.5567530*T - 0.0001185*T*T - 0.0000116*T*T*T);
+  z     =          0.6406161*T + 0.0003041*T*T + 0.0000051*T*T*T;
+
+  if (ISNUM(argv[3][0]) && ISNUM(argv[4][0])) {
+    A = atof (argv[3]);
+    D = atof (argv[4]);
+    SD =  cos(RAD_DEG*A + zeta)*sin(theta)*cos(RAD_DEG*D) + cos(theta)*sin(RAD_DEG*D);
+    CD = sqrt (1 - SD*SD);
+    SA =  sin(RAD_DEG*A + zeta)*cos(RAD_DEG*D)/CD;
+    CA = (cos(RAD_DEG*A + zeta)*cos(theta)*cos(RAD_DEG*D) - sin(theta)*sin(RAD_DEG*D))/CD;
+
+    DEC = DEG_RAD*asin(SD);
+    RA  = DEG_RAD*atan2(SA, CA) + z;
+
+    if (RA < 0)
+      RA += 360;
+    fprintf (GetOutfile(), "%f %f -> %f %f\n", A, D, RA, DEC);
+    return (TRUE);
+  }    
+
+  /* find vectors */
+  if ((xvec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[4], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (xvec[0].Nelements != yvec[0].Nelements) {
+    fprintf (stderr, "vectors %s and %s not the same length\n", argv[3], argv[4]);
+    return (FALSE);
+  }
+  
+  for (i = 0; i < xvec[0].Nelements; i++) {
+    A = xvec[0].elements[i];
+    D = yvec[0].elements[i];
+    SD =  cos(RAD_DEG*A + zeta)*sin(theta)*cos(RAD_DEG*D) + cos(theta)*sin(RAD_DEG*D);
+    CD = sqrt (1 - SD*SD);
+    SA =  sin(RAD_DEG*A + zeta)*cos(RAD_DEG*D)/CD;
+    CA = (cos(RAD_DEG*A + zeta)*cos(theta)*cos(RAD_DEG*D) - sin(theta)*sin(RAD_DEG*D))/CD;
+
+    DEC = DEG_RAD*asin(SD);
+    RA  = DEG_RAD*atan2(SA, CA) + z;
+
+    if (RA < 0)
+      RA += 360;
+    
+    xvec[0].elements[i] = RA;
+    yvec[0].elements[i] = DEC; 
+  }
+
+  return (TRUE);
+
+}  
Index: /tags/start/Ohana/src/opihi/cmd.astro/profile.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/profile.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/profile.c	(revision 12606)
@@ -0,0 +1,52 @@
+# include "astro.h"
+
+int profile (int argc, char **argv) {
+  
+  int i, j, N, Nx, Npt;
+  float *V;
+  double sx, sy;
+  Vector *xvec, *yvec;
+  Buffer *buf;
+
+  if (argc != 7) {
+    fprintf (stderr, "USAGE: profile <buffer> <X vector> <Y vector> x y N\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  
+  sx = atof (argv[4]);
+  sy = atof (argv[5]);
+  N  = atof (argv[6]);
+
+  if (sx - N < 0) goto range_error;
+  if (sy - N < 0) goto range_error;
+  if (sx + N > buf[0].matrix.Naxis[0]) goto range_error;
+  if (sy + N > buf[0].matrix.Naxis[1]) goto range_error;
+
+  if ((xvec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[3], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  xvec[0].Nelements = yvec[0].Nelements = (int)SQ(2*N+1);
+  REALLOCATE (xvec[0].elements, float, 5*(int)SQ(2*N+1));
+  REALLOCATE (yvec[0].elements, float, 5*(int)SQ(2*N+1));
+  bzero (yvec[0].elements, (int)SQ(2*N+1)*sizeof(float)+1);
+  V = (float *)(buf[0].matrix.buffer); 
+  Npt = 0;
+  Nx = buf[0].matrix.Naxis[0];
+  for (i = sx - N; i < sx + N; i++) {
+    for (j = sy - N; j < sy + N; j++, Npt++) {
+      yvec[0].elements[Npt] = V[i + j*Nx];
+      xvec[0].elements[Npt] = hypot (i - sx, j - sy);
+    }
+  }
+
+  fsortpair (xvec[0].elements, yvec[0].elements, xvec[0].Nelements);
+
+  return (TRUE);
+
+range_error:
+  fprintf (stderr, "region out of range\n");
+  return (FALSE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.astro/region.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/region.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/region.c	(revision 12606)
@@ -0,0 +1,119 @@
+# include "astro.h"
+
+int region (int argc, char **argv) {
+  
+  char buffer[65], buffer2[35], string[256];
+  double Ra, Dec, Radius;
+  double dx, dy;
+  int status, N;
+  Graphdata graphmode;
+  int Ngraph, Xgraph;
+
+  Ngraph = 0;
+  if (!GetGraph (&graphmode, &Xgraph, &Ngraph)) return (FALSE);
+
+  if (N = get_argument (argc, argv, "-ew")) {
+    remove_argument (N, &argc, argv);
+    graphmode.flipeast = TRUE;
+  }
+
+  if (N = get_argument (argc, argv, "+ew")) {
+    remove_argument (N, &argc, argv);
+    graphmode.flipeast = FALSE;
+  }
+
+  if (N = get_argument (argc, argv, "-ns")) {
+    remove_argument (N, &argc, argv);
+    graphmode.flipnorth = TRUE;
+  }
+
+  if (N = get_argument (argc, argv, "+ns")) {
+    remove_argument (N, &argc, argv);
+    graphmode.flipnorth = FALSE;
+  }
+
+  if ((argc != 4) && (argc != 5)) {
+    fprintf (stderr, "USAGE: region Ra Dec Radius [projection] [orientation]\n");
+    fprintf (stderr, " current: %f %f (%f x %f) (%s)\n", 
+	     graphmode.coords.crval1, graphmode.coords.crval2, 
+	     fabs(graphmode.xmax - graphmode.xmin), 
+	     fabs(graphmode.ymax - graphmode.ymin), 
+	     &graphmode.coords.ctype[5]);
+    return (FALSE);
+  }
+  
+  if (!str_to_radec (&Ra, &Dec, argv[1], argv[2])) return (FALSE);
+  Radius = atof (argv[3]);
+  strcpy (graphmode.coords.ctype, "RA---TAN");
+  if (argc == 5) {
+    if (!strcasecmp (argv[4], "SIN")) 
+      strcpy (graphmode.coords.ctype, "RA---SIN");
+    if (!strcasecmp (argv[4], "ZEA"))
+      strcpy (graphmode.coords.ctype, "RA---ZEA");
+    if (!strcasecmp (argv[4], "AIT")) 
+      strcpy (graphmode.coords.ctype, "RA---AIT");
+    if (!strcasecmp (argv[4], "GLS")) 
+      strcpy (graphmode.coords.ctype, "RA---GLS");
+    if (!strcasecmp (argv[4], "PAR")) 
+      strcpy (graphmode.coords.ctype, "RA---PAR");
+  }
+
+  
+  /* ask kapa for coordinate limits, so get the right aspect ratio */
+  status = write (Xgraph, "LIMS", 4); 
+  read (Xgraph, buffer, 30); 
+  sscanf (buffer, "%*s %lf %lf", &dx, &dy); 
+  dx = fabs (dx);
+  dy = fabs (dy); 
+
+  /* define limits for Ra, Dec at center, grid in degrees */
+  if (dy < dx) {
+    graphmode.xmin = -(dx/dy)*Radius;
+    graphmode.ymin = -Radius;
+    graphmode.xmax = (dx/dy)*Radius;
+    graphmode.ymax = Radius;
+  } else {
+    graphmode.xmin = -Radius;
+    graphmode.ymin = -(dy/dx)*Radius;
+    graphmode.xmax = Radius;
+    graphmode.ymax = (dy/dx)*Radius;
+  } 
+
+  set_variable ("XMIN", graphmode.xmin);
+  set_variable ("XMAX", graphmode.xmax);
+  set_variable ("YMIN", graphmode.ymin);
+  set_variable ("YMAX", graphmode.ymax);
+
+  set_variable ("RMIN", Ra  + graphmode.xmin);
+  set_variable ("RMAX", Ra  + graphmode.xmax);
+  set_variable ("DMIN", Dec + graphmode.ymin);
+  set_variable ("DMAX", Dec + graphmode.ymax);
+
+  graphmode.coords.pc1_1 = (graphmode.flipeast) ? -1 : 1;
+  graphmode.coords.pc2_2 = (graphmode.flipnorth) ? -1 : 1;
+
+  graphmode.coords.pc1_2 = graphmode.coords.pc2_1 = 0.0;
+  graphmode.coords.crval1 = Ra;
+  graphmode.coords.crval2 = Dec;
+  graphmode.coords.crpix1 = 0.0;
+  graphmode.coords.crpix2 = 0.0;
+  graphmode.coords.cdelt1 = graphmode.coords.cdelt2 = 1.0;
+
+  write (Xgraph, "ERAS", 4);
+    
+  write (Xgraph, "SLIM", 4);
+  sprintf (buffer, "%f %f %f %f ", graphmode.xmin, graphmode.xmax, graphmode.ymin, graphmode.ymax);
+  sprintf (buffer2, "NBYTES: %6d ", strlen (buffer));
+  write (Xgraph, buffer2, 16);
+  write (Xgraph, buffer, strlen (buffer));
+
+  sprintf (string, "%8.4f %8.4f (%f)", Ra, Dec, Radius);
+  SendLabel (string, Xgraph, 2);
+
+  SetGraph (graphmode);
+
+  return (TRUE);
+
+}
+
+
Index: /tags/start/Ohana/src/opihi/cmd.astro/rotcurve.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/rotcurve.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/rotcurve.c	(revision 12606)
@@ -0,0 +1,120 @@
+# include "astro.h"
+
+int rotcurve (int argc, char **argv) {
+  
+  int i, j, X, Y, n, Ncurve;
+  float *Vin, *Vout, *Vmask;
+  int nx, ny, Nx, Ny, N;
+  double L, dL, Lo, V, Vo, dV, Bo, dB, Do, dD;
+  double xo, yo, Xo, Yo;
+  double sl, cl, wo, Ro, Rs, wr, r, fr, d, min;
+  double R[100], T[100], W[100];
+  FILE *f;
+  Buffer *in, *out, *mask;
+
+  min = -1000;
+  if (N = get_argument (argc, argv, "-min")) {
+    remove_argument (N, &argc, argv);
+    min = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: rotcurve in out mask curve.txt\n");
+    return (FALSE);
+  }
+
+  f = fopen (argv[4], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't find rotation curve data file %s\n", argv[4]);
+    return (FALSE);
+  }
+  for (i = 0; fscanf (f, "%lf %lf", &R[i], &T[i]) != EOF; i++) {
+    W[i] = T[i] / R[i];
+  }  
+  fclose (f);
+  Ncurve = i;
+
+  if ((in   = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out  = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((mask = SelectBuffer (argv[3], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  Nx = out[0].matrix.Naxis[0];
+  Ny = out[0].matrix.Naxis[1];
+  nx = mask[0].matrix.Naxis[0];
+  ny = mask[0].matrix.Naxis[1];
+  if ((Nx != nx) && (Ny != ny)) {
+    fprintf (stderr, "output and mask must have same dimensions\n");
+    return (FALSE);
+  }
+  nx = in[0].matrix.Naxis[0];
+  ny = in[0].matrix.Naxis[1];
+
+  /* we expect the input image to have units of velocity, lattitude, and longitude */
+  fits_scan (&in[0].header, "CRVAL1", "%lf", 1, &Vo);
+  fits_scan (&in[0].header, "CDELT1", "%lf", 1, &dV);
+  fits_scan (&in[0].header, "CRPIX1", "%lf", 1, &xo);
+  fits_scan (&in[0].header, "CRVAL2", "%lf", 1, &Bo);
+  fits_scan (&in[0].header, "CDELT2", "%lf", 1, &dB);
+  fits_scan (&in[0].header, "CRPIX2", "%lf", 1, &yo);
+  fits_scan (&in[0].header, "CRVAL3", "%lf", 1, &L);
+  Vo *= 0.001;
+  dV *= 0.001;
+
+  /* we expect the output image to have units of longitude and distance */
+  fits_scan (&out[0].header, "CRVAL1", "%lf", 1, &Lo);
+  fits_scan (&out[0].header, "CDELT1", "%lf", 1, &dL);
+  fits_scan (&out[0].header, "CRPIX1", "%lf", 1, &Xo);
+  fits_scan (&out[0].header, "CRVAL2", "%lf", 1, &Do);
+  fits_scan (&out[0].header, "CDELT2", "%lf", 1, &dD);
+  fits_scan (&out[0].header, "CRPIX2", "%lf", 1, &Yo);
+
+  while (L >= 360) {L -= 360.0;}
+  while (L < 0.0)  {L += 360.0;}
+  X = (L - Lo) / dL + Xo;
+  if ((X >= Nx) || (X < 0)) {
+    fprintf (stderr, "X out of range\n");
+    return (FALSE);
+  }
+  fprintf (stderr, "L: %f (%d)\n", L, X);
+
+  cl = cos (L*RAD_DEG);
+  sl = sin (L*RAD_DEG);
+  wo = 25.0;
+  Ro = 10.0;
+  Rs = Ro*sl;
+  /* this method depends on wr monotonically decreasing */
+
+  Vin  = (float *)in[0].matrix.buffer;
+  Vout = (float *)out[0].matrix.buffer;
+  Vmask = (float *)mask[0].matrix.buffer;
+  for (j = 0; j < ny; j++) {
+    for (i = 0; i < nx; i++, Vin++) {
+      if (*Vin <= min) continue;
+      V = (i - xo) * dV + Vo;
+      wr = V/Rs + wo;
+      for (n = 0; (n < Ncurve) && (wr < W[n]); n++);
+      if ((n == 0) || (n == Ncurve)) {
+	continue;
+      }
+      r = (wr - W[n]) *  (R[n-1] - R[n]) / (W[n-1] - W[n]) + R[n];
+      fr = (Ro/r);
+      if (r < fabs(Rs)) { /* can't be on rotation curve */
+	continue;
+      }
+      if (r < Ro)
+	d = Ro*cl - sqrt(r*r - Rs*Rs);
+      else 
+	d = Ro*cl + sqrt(r*r - Rs*Rs);
+      Y = (d - Do) / dD + Yo;
+      if ((Y < Ny) && (Y >= 0)) {
+	Vout[Y*Nx + X] += *Vin;
+	Vmask[Y*Nx + X] += 1.0;
+      }
+    }
+  }
+
+
+  return (TRUE);
+
+} 
Index: /tags/start/Ohana/src/opihi/cmd.astro/scale.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/scale.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/scale.c	(revision 12606)
@@ -0,0 +1,43 @@
+# include "astro.h"
+
+int scale (int argc, char **argv) {
+
+  Buffer *buf;
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: scale (buffer) (key) [-r/-w] (value)\n");
+    return (FALSE);
+  }  
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  if (strcasecmp (argv[2], "bzero") && strcasecmp (argv[2], "bscale")) {
+    fprintf (stderr, "use bzero or bscale only\n");
+    return (FALSE);
+  }
+    
+  if (strcmp (argv[3], "-r") && strcmp (argv[3], "-w")) {
+    fprintf (stderr, "use -r or -w only\n");
+    return (FALSE);
+  }
+    
+  if (!strcmp (argv[3], "-r")) {
+    if (!strcasecmp (argv[2], "bzero")) {
+      set_variable (argv[4], (double) buf[0].bzero);
+    } else {
+      set_variable (argv[4], (double) buf[0].bscale);
+    }      
+  } else {
+    if (!strcasecmp (argv[2], "bzero")) {
+      buf[0].bzero = atof (argv[4]);
+    } else {
+      buf[0].bscale = atof (argv[4]);
+    }      
+  }
+
+  return (TRUE);
+}
+
+/* get or set external bzero / bscale values 
+   (these keywords are set to 0,1 internally, 
+   so we can't just manipulate them like other keywords */
Index: /tags/start/Ohana/src/opihi/cmd.astro/sexigesimal.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/sexigesimal.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/sexigesimal.c	(revision 12606)
@@ -0,0 +1,49 @@
+# include "astro.h"
+
+int sexigesimal (int argc, char **argv) {
+  
+  int HMS, N;
+  double value;
+  char string[80];
+
+  HMS = TRUE;
+  if (N = get_argument (argc, argv, "-hms")) {
+    HMS = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-hh")) {
+    HMS = FALSE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((argc != 3) && (argc != 2)) {
+    fprintf (stderr, "USAGE: sexigesimal (from) [to]\n");
+    return (FALSE);
+  }
+
+  if (HMS) {
+    if (!dms_to_ddd (&value, argv[1])) {
+      fprintf (stderr, "syntax error in input\n");
+      return (FALSE);
+    }
+    if (argc == 3) {
+      set_variable (argv[2], value);
+    } else {
+      fprintf (GetOutfile(), "%10.6f\n", value);
+    }
+    return (TRUE);
+  } else {
+    value = atof (argv[1]);
+    hms_format (string, value);
+    if (argc == 3) {
+      set_str_variable (argv[2], string);
+    } else {
+      fprintf (GetOutfile(), "%s\n", string);
+    }
+    return (TRUE);
+  }      
+
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.astro/spec.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/spec.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/spec.c	(revision 12606)
@@ -0,0 +1,112 @@
+# include "astro.h"
+
+int spec (int argc, char **argv) {
+
+  int i, j, Xo, X1, y1, y2, Nx, Ny;
+  int Nlong, Ngap, Nrow, N, Nring;
+  float *buffer, *V;
+  double sky, sky2, S, SX, F, R, Npts;
+  Vector *xvec, *yvec;
+  Buffer *buf;
+
+  Nlong = 31;
+  if (N = get_argument (argc, argv, "-Nlong")) {
+    remove_argument (N, &argc, argv);
+    Nlong  = 0.5*atof(argv[N]);
+    Nlong = 2*Nlong + 1;  /* force an odd number */
+    remove_argument (N, &argc, argv);
+  }
+  
+  Ngap = 15;
+  if (N = get_argument (argc, argv, "-Ngap")) {
+    remove_argument (N, &argc, argv);
+    Ngap  = 0.5*atof(argv[N]);
+    Ngap = 2*Ngap + 1;  /* force an odd number */
+    remove_argument (N, &argc, argv);
+  }
+  
+  Nrow = 1;
+  if (N = get_argument (argc, argv, "-Nrow")) {
+    remove_argument (N, &argc, argv);
+    Nrow  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  
+  if (argc != 7) {
+    fprintf (stderr, "USAGE: spec buffer x y1 y2 X Y [-Nlong N] [-Ngap N] [-Nrow N]\n");
+    return (FALSE);
+  }
+  
+  if ((Nrow < 1) || (Nlong < 2) || (Ngap < 1) || (Nlong - Ngap < 2)) {
+    fprintf (stderr, "bad values for options\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+
+  Xo = atof (argv[2]);
+  y1 = atof (argv[3]);
+  y2 = atof (argv[4]);
+
+  if ((xvec = SelectVector (argv[5], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[6], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  N = y2 - y1;
+  REALLOCATE (xvec[0].elements, float, N);
+  REALLOCATE (yvec[0].elements, float, N);
+  xvec[0].Nelements = N;
+  yvec[0].Nelements = N;
+  
+  ALLOCATE (buffer, float, Nlong);
+
+  for (j = 0; j < y2 - y1; j++) {
+    V = (float *) (buf[0].matrix.buffer) + Nx*(y1 + j) + Xo - (int)(0.5*Nlong);
+    /* find sky on edge */
+    for (i = 0, Nring = 0; i < 0.5*(Nlong - Ngap); i++, V++, Nring++) {
+      buffer[i] = *V;
+    }
+    fsort (buffer, Nring);
+    for (Npts = sky = 0, i = 0.25*Nring; i < 0.75*Nring; i++, Npts += 1.0) {
+      sky += buffer[i];
+    }
+    sky = sky / Npts;
+    /* find center column for this row */
+    for (S = SX = i = 0, Nring = 0; i < Ngap; i++, V++, Nring++) {
+      S += (*V - sky);
+      SX += (*V - sky)*(i + Xo - 0.5*Ngap);
+    }
+    X1 = SX / S;
+    fprintf (stderr, "%4d %4d %5.1f ", j+y1, X1, sky);
+    /*    X1 = MAX (MIN (X1, Xo + 0.5+Ngap), Xo - 0.5+Ngap); */
+    V = (float *) (buf[0].matrix.buffer) + Nx*(y1 + j) + X1 - (int)(0.5*Nlong);
+    /* find sky on edges */
+    for (i = 0, Nring = 0; i < 0.5*(Nlong - Ngap); i++, V++, Nring++) {
+      buffer[Nring] = *V;
+    }
+    V = (float *) (buf[0].matrix.buffer) + Nx*(y1 + j) + X1 + (int)(0.5*Ngap);
+    for (i = 0; i < 0.5*(Nlong - Ngap); i++, V++, Nring++) {
+      buffer[Nring] = *V;
+    }
+    fsort (buffer, Nring);
+    for (Npts = sky = 0, i = 0.25*Nring; i < 0.75*Nring; i++, Npts += 1.0) {
+      sky += buffer[i];
+      sky2 += buffer[i]*buffer[i];
+    }
+    sky = sky / Npts;
+    sky2 = (sky2 / Npts - sky*sky);
+    /* find weighted flux */
+    V = (float *) (buf[0].matrix.buffer) + Nx*(y1 + j) + X1 - (int)(0.5*Ngap);
+    for (F = R = i = 0; i < Ngap; i++, V++) {
+      F += (*V - sky) / sky2;
+      R += 1.0 / sky2;
+    }
+    xvec[0].elements[j] = j + y1; 
+    yvec[0].elements[j] = F / R; 
+    fprintf (stderr, " %5.1f %7.1f  %6.2f\n", sky, sky2, (F/R));
+  }    
+
+  free (buffer);
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.astro/star.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/star.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/star.c	(revision 12606)
@@ -0,0 +1,41 @@
+# include "astro.h"
+
+int star (int argc, char **argv) {
+
+  int x, y, N, dx, Nborder;
+  double Z, max;
+  Buffer *buf;
+
+  Nborder = 3;
+  if (N = get_argument (argc, argv, "-border")) {
+    remove_argument (N, &argc, argv);
+    Nborder  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  Nborder = MAX (Nborder, 1);
+  
+  max = 60000;
+  if (N = get_argument (argc, argv, "-sat")) {
+    remove_argument (N, &argc, argv);
+    max  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  
+  if ((argc != 4) && (argc != 5)) {
+    fprintf (stderr, "USAGE: star (buffer) x y [dx] [-border N] [-sat cnts]\n");
+    return (FALSE);
+  }
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  dx = 11;
+  x = atof (argv[2]);
+  y = atof (argv[3]);
+  if (argc == 5) {
+    dx = atof (argv[4]);
+  }
+
+  Z = get_aperture_stats (&buf[0].matrix, x, y, dx, Nborder, max);
+  
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.astro/testfit.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/testfit.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/testfit.c	(revision 12606)
@@ -0,0 +1,161 @@
+# include "astro.h"
+
+/* local private functions */
+float fgaussOD (float, float *, int, float *);
+
+int imfit (int argc, char **argv) {
+
+  float par[4], *v1, *v2, *dy, chisq, **covar;
+  int i, Npts, Npar;
+  Vector *xvec, *yvec, *svec;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: imfit <x> <y> <dy>\n");
+    return (FALSE);
+  }
+  
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((svec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  Npts = xvec[0].Nelements;
+  ALLOCATE (dy, float, Npts);
+  v1 = svec[0].elements;
+  v2 = dy;
+  
+  for (i = 0; i < Npts; i++, v1++, v2++) *v2 = 1.0 / (*v1 * *v1);
+  
+  par[0] = 7;
+  par[1] = 2;
+  par[2] = 6;
+  par[3] = 1;
+  Npar = 4;
+
+  mrqinit (xvec[0].elements, yvec[0].elements, dy, Npts, par, Npar, fgaussOD);
+
+  for (i = 0; i < 10; i++) {
+
+    chisq = mrqmin (xvec[0].elements, yvec[0].elements, dy, Npts, par, Npar, fgaussOD);
+    fprintf (stderr, "chisq: %f, %f %f %f %f\n", chisq, par[0], par[1], par[2], par[3]);
+
+  }  
+
+  covar = mrqcovar (Npar);
+
+  for (i = 0; i < Npar; i++) {
+    fprintf (stderr, "%d  %f  %f\n", i, par[i], covar[i][i]);
+  }
+
+  mrqfree (Npar);
+  return (TRUE);
+}
+
+
+/* pars: x, y, sx, sy, sxy, sky I, */
+float fgaussOD (float x, float *par, int Npar, float *dpar) {
+
+  float X, S, Z, R, f;
+
+  X = x - par[0];
+  S = 1.0 / (par[1]*par[1]);
+  Z = -0.5*X*X*S;
+  R = exp (Z);
+  f = par[2]*R + par[3];
+
+  dpar[0] = par[2]*R*X*S;
+  dpar[1] = dpar[0]*X/par[1];
+  dpar[2] = R;
+  dpar[3] = 1;
+  
+  return (f);
+
+}
+
+# if (0)
+
+/* pars: x, y, sx, sy, sxy, sky I, */
+float testF (float x, float *par, int Npar, float *dpar) {
+
+  float f;
+
+  f = par[0]*x + par[1];
+
+  dpar[0] = x;
+  dpar[1] = 1;
+  
+  return (f);
+
+}
+
+
+/* pars: x, y, sx, sy, sxy, sky I, */
+float fgaussTD (float x, float y, float *par, int Npar) {
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  t1 = X / par[2];
+  t2 = Y * Y / par[3];
+  t3 = Y * par[4] * 2.0;
+
+  r = 0.5 * ((t1 + t3)*X + t2);
+  f = par[5] + par[6] / (1.0 + r*(1.0 + 0.5*r*(1.0 + 0.33333333*r)));
+  
+  return (f);
+
+}
+
+float chisq (float *buf, float *sig, int Nx, int Ny, float (func)(), float *par, int Npar) {
+
+  float *ptr;
+
+  X = 0;
+  ptr = buf;
+  for (i = 0; i < Nx; i++) {
+    for (j = 0; j < Ny; j++, ptr++, sig++) {
+      f = *ptr - func ((float) i, (float) j, par, Npar);
+      X += (f * f) / *sig;
+    }
+  }    
+  return (X);
+}
+
+  int i, j, Nbuf, status;
+  char *string;
+  double Npix, N1, N2, max, min, range, median;
+  float *V;
+  int sx, sy, nx, ny, *hist, Nhist, bin;
+
+  if (argc != 6) {
+    fprintf (stderr, "USAGE: imfit <buffer> sx sy nx ny\n");
+    return (FALSE);
+  }
+
+  if (!SelectBuffer (&Nbuf, argv[1], OLDBUFFER)) return (FALSE);
+
+  sx = atof (argv[2]);
+  sy = atof (argv[3]);
+  nx = atof (argv[4]);
+  ny = atof (argv[5]);
+
+  Npix = N1 = N2 = 0;
+  if ((sx < 0) || (sy < 0) || 
+      (sx+nx > buffers[Nbuf].matrix.Naxis[0]) || 
+      (sy+ny > buffers[Nbuf].matrix.Naxis[1])) {
+    fprintf (stderr, "region out of range\n");
+    return (FALSE);
+  }
+
+  Npix = nx*ny;
+
+  ALLOCATE (tempbuf, float, Npix);
+
+  buf = tempbuf;
+  for (j = 0; j < ny; j++) {
+    V = (float *)(buffers[Nbuf].matrix.buffer) + (j+sy)*buffers[Nbuf].matrix.Naxis[0] + sx; 
+    for (i = 0; i < nx; i++, V++) {
+      *buf = *V;
+    }
+  }
+
+# endif
Index: /tags/start/Ohana/src/opihi/cmd.astro/transform.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.astro/transform.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.astro/transform.c	(revision 12606)
@@ -0,0 +1,68 @@
+# include "astro.h"
+
+int transform (int argc, char **argv) {
+
+  int i, j, Nx, Ny;
+  Coords coords_in, coords_out;
+  double scale_in, scale_out;
+  int X, Y;
+  double x, y, r, d, dx, dy;
+  double frac;
+  char *Sout, *S;
+  float *Vin, *Vout;
+  Buffer *in, *out;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: transform <from> <to>\n");
+    return (FALSE);
+  }
+
+  if ((in  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  GetCoords (&coords_in, &in[0].header);
+  GetCoords (&coords_out, &out[0].header);
+  
+  scale_in = sqrt(fabs(coords_in.cdelt1*coords_in.cdelt2*(coords_in.pc1_1*coords_in.pc2_2 - coords_in.pc1_2*coords_in.pc2_1)));
+  scale_out = sqrt(fabs(coords_out.cdelt1*coords_out.cdelt2*(coords_out.pc1_1*coords_out.pc2_2 - coords_out.pc1_2*coords_out.pc2_1)));
+
+  Vin  = (float *) in[0].matrix.buffer;
+  Vout = (float *) out[0].matrix.buffer;
+  Nx = out[0].header.Naxis[0];
+  Ny = out[0].header.Naxis[1];
+  bzero (Vout, Nx*Ny*sizeof(float));
+  ALLOCATE (S, char, Nx*Ny);
+  Sout = S;
+  bzero (Sout, Nx*Ny*sizeof(char));
+  frac = 0.333;
+
+  /* if (scale_in < scale_out) { */
+
+  for (j = 0; j < in[0].header.Naxis[1]; j++) {
+    fprintf (stderr, ".");
+    for (i = 0; i < in[0].header.Naxis[0]; i++, Vin++) {
+      for (dx = 0.0 + 0.5*frac; dx < 1.0 - 0.5*frac; dx += frac) {
+	for (dy = 0.0 + 0.5*frac; dy < 1.0 - 0.5*frac; dy += frac) {
+	  XY_to_RD (&r, &d, i + dx, j + dy, &coords_in);
+	  RD_to_XY (&x, &y, r, d, &coords_out);
+	  X = x; Y = y;
+	  if ((X > -1) && (X < Nx) && (Y > -1) && (Y < Ny)) {
+	    Vout[X + Y*Nx] += *Vin;
+	    Sout[X + Y*Nx] ++;
+	  }
+	}
+      }
+    }
+  }
+
+  Sout = S;
+  Vout = (float *) out[0].matrix.buffer;
+  for (i = 0; i < Nx*Ny; i++, Vout++, Sout++) {
+    *Vout = *Vout / *Sout;
+  }
+
+  free (S);
+    
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.basic/Makefile
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/Makefile	(revision 12606)
@@ -0,0 +1,109 @@
+include ../../../Configure
+
+HOME    =       $(ROOT)/src/opihi.v2
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+SDIR    =       $(HOME)/cmd.basic
+#
+DESTBIN =       $(LBIN)
+DESTLIB =       $(LLIB)
+DESTINC =       $(LINC)
+DESTMAN =       $(LMAN)
+HELP    =       $(HOME)/help
+#  
+INCS    =       -I$(INC) -I$(LINC) -I$(XINC)
+LFLAGS  =       -L$(LLIB) -L$(LIB)
+LIBS    =       -lFITS -lsocket -lnsl -lreadline -ltermcap -lohana -lm
+CFLAGS  =       $(INCS)
+CCFLAGS =       $(LIBS) 
+
+# basic user commands ########################
+
+basiccmd = \
+$(SDIR)/init.$(ARCH).o       \
+$(SDIR)/break.$(ARCH).o	     \
+$(SDIR)/cd.$(ARCH).o	     \
+$(SDIR)/config.$(ARCH).o     \
+$(SDIR)/continue.$(ARCH).o   \
+$(SDIR)/date.$(ARCH).o	     \
+$(SDIR)/echo.$(ARCH).o	     \
+$(SDIR)/file.$(ARCH).o	     \
+$(SDIR)/getchr.$(ARCH).o     \
+$(SDIR)/help.$(ARCH).o	     \
+$(SDIR)/input.$(ARCH).o	     \
+$(SDIR)/list.$(ARCH).o	     \
+$(SDIR)/list_help.$(ARCH).o  \
+$(SDIR)/list_vars.$(ARCH).o  \
+$(SDIR)/local.$(ARCH).o	     \
+$(SDIR)/macro.$(ARCH).o	     \
+$(SDIR)/memory.$(ARCH).o     \
+$(SDIR)/output.$(ARCH).o     \
+$(SDIR)/quit.$(ARCH).o	     \
+$(SDIR)/run_for.$(ARCH).o    \
+$(SDIR)/run_if.$(ARCH).o     \
+$(SDIR)/run_while.$(ARCH).o  \
+$(SDIR)/scan.$(ARCH).o	     \
+$(SDIR)/shell.$(ARCH).o	     \
+$(SDIR)/sprintf.$(ARCH).o    \
+$(SDIR)/strlen.$(ARCH).o     \
+$(SDIR)/substr.$(ARCH).o     \
+$(SDIR)/usleep.$(ARCH).o     \
+$(SDIR)/sleep.$(ARCH).o	     \
+$(SDIR)/wait.$(ARCH).o	     \
+$(SDIR)/which.$(ARCH).o
+
+libbasiccmd:    $(DESTLIB)/libbasiccmd.a 
+
+$(LIB)/libbasiccmd.$(ARCH).a:   	$(basiccmd)
+
+# utilities #################################################
+$(BIN)/%.$(ARCH):
+	@if [ ! -d $(BIN) ]; then mkdir -p $(BIN); fi
+	$(CC) $^ -o $@ $(LFLAGS) $(LIBS)
+	@echo "compiled $*"
+	@echo ""
+
+$(DESTBIN)/%: $(BIN)/%.$(ARCH) 
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	rm -f $(DESTBIN)/$*
+	cp $(BIN)/$*.$(ARCH) $(DESTBIN)/$*
+	@echo "installed $*"
+	@echo ""
+
+$(LIB)/%.$(ARCH).a:
+	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
+	rm -f $@
+	ar rcv $@ $^ 
+	ranlib $@
+	@echo "compiled library $*"
+	@echo ""
+
+$(DESTLIB)/%.a: $(LIB)/%.$(ARCH).a
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	@echo ""
+	rm -f $@
+	cp $^ $@
+
+lib%.clean:
+	rm -f $(LIB)/lib$*.$(ARCH).a
+	rm -f $($*)
+	@echo ""
+
+%.clean:
+	rm -f $(BIN)/$*.$(ARCH)
+	@echo ""
+
+%.$(ARCH).o : %.c
+	$(CC) $(CFLAGS) -c $*.c -o $@
+
+clean:
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f $(LIB)/*.$(ARCH).a
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+dist: clean
+	rm -f $(BIN)/*
+	rm -f $(LIB)/*
Index: /tags/start/Ohana/src/opihi/cmd.basic/break.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/break.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/break.c	(revision 12606)
@@ -0,0 +1,27 @@
+# include "basic.h"
+
+int exec_break (int argc, char **argv) {
+
+  int N, value;
+
+  if (N = get_argument (argc, argv, "-auto")) {
+    remove_argument (N, &argc, argv);
+    value = -1;
+    if (!strcasecmp (argv[N], "on")) value = TRUE;
+    if (!strcasecmp (argv[N], "off")) value = FALSE;
+    if (value == -1) {
+      fprintf (stderr, "USAGE: break -auto [on / off]\n");
+      if (auto_break) 
+	fprintf (stderr, "auto break on\n");
+      else 
+	fprintf (stderr, "auto break off\n");
+      return (FALSE);
+    }
+    auto_break = value;
+    return (TRUE);
+  }
+
+  loop_break = TRUE;
+  return (FALSE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/cd.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/cd.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/cd.c	(revision 12606)
@@ -0,0 +1,46 @@
+# include "basic.h"
+
+int cd (int argc, char **argv) {
+
+  int status;
+  char *cwd;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: cd <path>\n");
+    return (FALSE);
+  }
+
+  status = chdir (argv[1]);
+  if (!status) {
+    if ((cwd = getcwd (NULL, 64)) == NULL) {
+      fprintf (stderr, "error getting cwd\n");
+      return (FALSE);
+    }
+    fprintf(stderr, "cwd: %s\n", cwd);
+    free (cwd);
+    return (TRUE);
+  }
+
+  fprintf (stderr, "error changing to %s\n", argv[1]);
+  return (FALSE);
+
+}
+
+int pwd (int argc, char **argv) {
+
+  char *cwd;
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: pwd\n");
+    return (FALSE);
+  }
+  
+  if ((cwd = getcwd(NULL, 64)) == NULL) {
+    fprintf (stderr, "error getting cwd\n");
+    return (FALSE);
+  }
+  fprintf(stderr, "cwd: %s\n", cwd);
+  free (cwd);
+  return (TRUE);
+  
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/config.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/config.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/config.c	(revision 12606)
@@ -0,0 +1,9 @@
+# include "basic.h"
+
+int config (int argc, char **argv) {
+
+  if (!ConfigInit (&argc, argv)) return (FALSE);
+
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/continue.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/continue.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/continue.c	(revision 12606)
@@ -0,0 +1,7 @@
+# include "basic.h"
+
+int exec_continue (int argc, char **argv) {
+  loop_continue = TRUE;
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.basic/date.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/date.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/date.c	(revision 12606)
@@ -0,0 +1,26 @@
+# include "basic.h"
+
+int date (int argc, char **argv) {
+  
+  int N;
+  struct timeval now;
+  char *tstring;
+
+  if ((argc != 1) && (argc != 2)) {
+    fprintf (stderr, "USAGE: date [variable]\n");
+    return (FALSE);
+  }
+
+  gettimeofday (&now, NULL);
+  tstring = ctime (&now.tv_sec);
+  N = strlen (tstring) - 1;
+  tstring[N] = 0;
+
+  if (argc == 1) {
+    fprintf (stderr, "%s\n", tstring);
+  } else {
+    set_str_variable (argv[1], tstring);
+  }
+
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/echo.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/echo.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/echo.c	(revision 12606)
@@ -0,0 +1,12 @@
+# include "basic.h"
+
+int echo (int argc, char **argv) {
+  
+  int i;
+
+  for (i = 1; i < argc; i++) {
+    fprintf (GetOutfile(), "%s ", argv[i]);
+  }
+  fprintf (GetOutfile(), "\n");
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/file.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/file.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/file.c	(revision 12606)
@@ -0,0 +1,32 @@
+# include "basic.h"
+
+int file (int argc, char **argv) {
+  
+  /* usage: file (filename) [var] */
+
+  int status, vstat;
+  struct stat fstats;
+
+  if (argc < 2) {
+    fprintf (stderr, "USAGE: file (filename) [var]\n");
+    return (FALSE);
+  }
+
+  status = stat (argv[1], &fstats);
+
+  vstat = !status;
+
+  if (argc == 3) {
+      
+    set_int_variable (argv[2], vstat);
+
+  } else {
+
+    fprintf (stderr, "file %s is ", argv[1]);
+    if (!vstat) fprintf (stderr, "not ");
+    fprintf (stderr, "found\n");
+    
+  }
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.basic/getchr.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/getchr.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/getchr.c	(revision 12606)
@@ -0,0 +1,29 @@
+# include "basic.h"
+
+int getchr_func (int argc, char **argv) {
+
+  /* returns position of the first given character */ 
+  char *c;
+  int pos;
+
+  if ((argc != 3) && (argc != 4)) {
+    fprintf (stderr, "USAGE: strchr (string) (char) [var]\n");
+    return (FALSE);
+  }
+
+  c = strchr (argv[1], argv[2][0]);
+
+  if (c == (char *) NULL) {
+    pos = -1;
+  } else {
+    pos = c - argv[1];
+  }
+
+  if (argc == 4) {
+    set_int_variable (argv[3], pos);
+  } else {
+    fprintf (stderr, "%d\n", pos);
+  }
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/help.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/help.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/help.c	(revision 12606)
@@ -0,0 +1,34 @@
+# include "basic.h"
+
+int help (int argc, char **argv) {
+
+  FILE *f;
+  char *helpdir, file[1024], buff[512];
+
+  helpdir = get_variable ("HELPDIR");
+  if (helpdir == (char *) NULL) {
+    fprintf (stderr, "variable HELPDIR not found\n");
+    return (FALSE);
+  }
+
+  if (argc == 1) {
+    sprintf (buff, "ls %s", helpdir);
+    system (buff);
+    return (TRUE);
+  }
+
+  sprintf (file, "%s/%s", helpdir, argv[1]);
+
+  f = fopen (file, "r");
+  if (f == NULL) {
+    fprintf (stderr, "No help for: %s\n", argv[1]);
+    return (FALSE);
+  }
+
+  while (scan_line (f, buff) != EOF)
+    fprintf (stdout, "%s\n", buff);
+
+  fclose (f);
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.basic/init.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/init.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/init.c	(revision 12606)
@@ -0,0 +1,80 @@
+# include "basic.h"
+
+int config          PROTO((int, char **));
+int exec_sleep      PROTO((int, char **));
+int exec_usleep     PROTO((int, char **));
+int cd              PROTO((int, char **));
+int date            PROTO((int, char **));
+int echo            PROTO((int, char **));
+int exec_break      PROTO((int, char **));
+int exec_continue   PROTO((int, char **));
+int file            PROTO((int, char **));
+int getchr_func     PROTO((int, char **));
+int help       	    PROTO((int, char **));
+int input      	    PROTO((int, char **));
+int list       	    PROTO((int, char **));
+int list_help  	    PROTO((int, char **));
+int list_vars  	    PROTO((int, char **));
+int local           PROTO((int, char **)); /* data? */
+int macro      	    PROTO((int, char **));
+int memory          PROTO((int, char **));
+int output     	    PROTO((int, char **));
+int pwd        	    PROTO((int, char **));
+int quit       	    PROTO((int, char **));
+int run_for    	    PROTO((int, char **));
+int run_if     	    PROTO((int, char **));
+int run_while  	    PROTO((int, char **));
+int scan       	    PROTO((int, char **));
+int shell      	    PROTO((int, char **));
+int sprintf_opihi   PROTO((int, char **));
+int strlen_func     PROTO((int, char **));
+int substr_func     PROTO((int, char **));
+int wait       	    PROTO((int, char **));
+int which      	    PROTO((int, char **));
+
+/** mapping of the command names to command functions **/
+static Command cmds[] = {  
+  {"config",        config,             "(re)load config file?"},
+  {"sleep",         exec_sleep,         "sleep for N seconds"},
+  {"usleep",        exec_usleep,        "sleep for N microseconds"},
+  {"cd",      	    cd,                 "change directory"},
+  {"date",    	    date,               "get current date"},
+  {"echo",    	    echo,               "type this line *"},
+  {"break",   	    exec_break,         "escape from function *"},
+  {"continue",	    exec_continue,      "next loop iteration"},
+  {"file",          file,               "test file existence"},
+  {"getchr",        getchr_func,        "find character in string"},
+  {"help",    	    help,               "get help on a function *"},
+  {"input",   	    input,              "read command lines from a file *"},
+  {"list",    	    list,               "get variable list"},
+  {"?",       	    list_help,          "list commands *"},
+  {"??",      	    list_vars,          "list variables *"},
+  {"local",  	    local,              "define local variables"},
+  {"macro",   	    macro,              "deal with the macros *"}, 
+  {"memory",        memory,             "long listing of the allocated memory"},
+  {"output",  	    output,             "redirect output to file"},
+  {"pwd",     	    pwd,                "print current working directory"},
+  {"exit",    	    quit,               "exit program *"}, 
+  {"quit",    	    quit,               "exit program *"},
+  {"for",     	    run_for,            "for loop"}, 
+  {"if",      	    run_if,             "logical cases *"}, 
+  {"while",   	    run_while,          "while loop"}, 
+  {"scan",    	    scan,               "scan line from keyboard or file to variable *"},
+  {"!",       	    shell,              "system call"},
+  {"exec",    	    shell,              "system call"},
+  {"sprintf",       sprintf_opihi,      "formatted print to a variable"},
+  {"strlen",        strlen_func,        "string length"},
+  {"substr",        substr_func,        "substring"},
+  {"wait",    	    wait,               "wait until return is typed"},
+  {"which",   	    which,              "show command *"}
+};
+
+void InitBasic () {
+  
+  int i;
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/input.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/input.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/input.c	(revision 12606)
@@ -0,0 +1,52 @@
+# include "basic.h"
+# define D_NLINES 100
+
+int input (int argc, char **argv) {
+  
+  int i, NLINES, status;
+  FILE *infile;
+  Macro inlist;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: input <filename>\n");
+    return (FALSE);
+  }
+
+  infile = fopen (argv[1], "r");
+  if (infile == NULL) {
+    fprintf (stderr, "no file %s\n", argv[1]); 
+    return (FALSE);
+  }
+
+  /* read file into the current list */
+  NLINES = D_NLINES;
+  ALLOCATE (inlist.line, char *, NLINES);
+  ALLOCATE (inlist.line[0], char, 1024);
+  for (i = 0; (scan_line (infile, inlist.line[i]) != EOF);) {
+    stripwhite (inlist.line[i]);
+    if (inlist.line[i][0] == 0) continue;
+    if (inlist.line[i][0] == '#') continue;
+    if (inlist.line[i][0] == '!') continue;
+
+    REALLOCATE (inlist.line[i], char, strlen(inlist.line[i]) + 1);
+    if (i == NLINES - 1) {
+      NLINES += D_NLINES;
+      REALLOCATE (inlist.line, char *, NLINES)
+    }
+    i++;
+    ALLOCATE (inlist.line[i], char, 1024);
+  }
+  inlist.Nlines = i;
+  fclose (infile);
+
+  /* process this list */
+  status = exec_loop (&inlist);
+
+  /* cleanup list */
+  for (i = 0; i < inlist.Nlines; i++) {
+    free (inlist.line[i]);
+  }
+  free (inlist.line);
+  return (status);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/list.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/list.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/list.c	(revision 12606)
@@ -0,0 +1,136 @@
+# include "basic.h"
+# define D_NLINES 100
+static char prompt[] = ">> ";
+
+int list (int argc, char **argv) {
+
+  int ThisList, depth, i, done;
+  char *input, line[1024];
+  int N, Nbytes, NBYTES, Nread, status;
+  int RunCommand;
+  char *A, *B, *val, *Cmd;
+  FILE *f;
+
+  RunCommand = FALSE;
+  if (N = get_argument (argc, argv, "-x")) {
+    remove_argument (N, &argc, argv);
+    Cmd = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    RunCommand = TRUE;
+  }
+
+  if ((argc > 2) && (!strcmp (argv[2], "-split"))) {
+    if (argc == 3) {
+      fprintf (stderr, "USAGE: list (root) -split (word) (word) ...\n");
+      return (FALSE);
+    }
+    
+    for (i = 0; i < argc - 3; i++) {
+      sprintf (line, "%s:%d", argv[1], i);
+      set_str_variable (line, argv[i+3]);
+    }
+    sprintf (line, "%s:n", argv[1]);
+    set_int_variable (line, i);
+
+    return (TRUE);
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: list (root) -- terminate with 'END'\n");
+    return (FALSE);
+  }
+
+  if (RunCommand) {
+    
+    /* val will hold the result */
+    NBYTES = 1024;
+    ALLOCATE (val, char, NBYTES);
+    
+    /* need to loop until command produces no more output, 
+       REALLOCATING as needed. */
+    f = popen (Cmd, "r");
+    done = FALSE;
+    Nbytes = 0;
+    while (!done) {
+      Nread = fread (&val[Nbytes], 1, 1023, f);
+      if (Nread < 0) { 
+	fprintf (stderr, "error reading from command\n");
+	done = TRUE;
+      }
+      if (Nread > 0) {
+	Nbytes += Nread;
+	NBYTES = 1024 + Nbytes;
+	REALLOCATE (val, char, NBYTES);
+      }
+      if (Nread == 0) {
+	done = TRUE;
+      }
+      
+    }
+    val[Nbytes] = 0;
+    status = pclose (f);
+    free (Cmd);
+    
+    if (status) {
+      fprintf (stderr, "warning: exit status of command %d\n", status);
+    }
+      
+    A = B = val;
+    for (i = 0; B != (char *) NULL;) {
+      while (isspace (*A) && (*A != 0)) A++;
+      B = strchr (A, '\n');
+      if (B != (char *) NULL) { *B = 0; }
+      if (*A != 0) {
+	sprintf (line, "%s:%d", argv[1], i);
+	set_str_variable (line, A);
+	A = B + 1;
+	i++;
+      }
+    }      
+    free (val);
+    
+    sprintf (line, "%s:n", argv[1]);
+    set_int_variable (line, i);
+    return (TRUE);
+  }
+
+  /* read in loop */
+  depth = 0;
+  ThisList = Nlists;
+  for (i = 0, done = FALSE; !done; ) {
+
+    /* get the next line (from correct place) */
+    if (ThisList == 0) 
+      input = readline (prompt);
+    else 
+      input = get_next_listentry (ThisList);
+
+    if (input == (char *) NULL) {
+      if (ThisList == 0)  {
+	fprintf (stderr, "end list with 'END'\n");
+	continue;
+      } else {
+	return (FALSE);
+      }	
+    }
+    stripwhite (input);
+
+    /* test for end of nested list -- if not nested, END refers to this macro */
+    if (!strncasecmp (input, "END", 3)) {
+      depth --;
+      if (depth < 0) { /* we hit the last "END", loop is done */
+	sprintf (line, "%s:n", argv[1]);
+	set_int_variable (line, i);
+	free (input);
+	return (TRUE);
+      }
+    }
+
+    if (*input) { 
+      sprintf (line, "%s:%d", argv[1], i);
+      set_str_variable (line, input);
+      i++;
+    }
+  }
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/list_help.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/list_help.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/list_help.c	(revision 12606)
@@ -0,0 +1,24 @@
+# include "basic.h"
+
+int list_help (int argc, char **argv) {
+
+  FILE *f;
+  int fd;
+  char filename[128], line[256];
+
+  sprintf (filename, "/tmp/status.XXXXXX");
+  if ((fd = mkstemp (filename)) == -1) {
+    fprintf (stderr, "error opening output\n");
+    return (FALSE);
+  }
+  f = fdopen (fd, "w");
+  if (f == (FILE *) NULL) f = stdout;
+  print_commands (f);
+  if (f != stdout) {
+    fclose (f);
+    sprintf (line, "more %s", filename);
+    system (line);
+  }
+  unlink (filename);
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/list_vars.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/list_vars.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/list_vars.c	(revision 12606)
@@ -0,0 +1,8 @@
+# include "basic.h"
+
+int list_vars (int argc, char **argv) {
+
+  ListVariables ();
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.basic/local.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/local.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/local.c	(revision 12606)
@@ -0,0 +1,33 @@
+# include "basic.h"
+
+int local (int argc, char **argv) {
+
+  int i, N, STATIC;
+  char *p;
+
+  /* create a variable named MacroDepth.argv[1] */
+
+  STATIC = FALSE;
+  if (N = get_argument (argc, argv, "-static")) {
+    remove_argument (N, &argc, argv);
+    STATIC = TRUE;
+  }
+
+  if (argc < 2) {
+    fprintf (stderr, "USAGE: local (variable)\n");
+    return (FALSE);
+  }
+  
+  for (i = 1; i < argc; i++) {
+    if (STATIC) {
+      p = get_local_variable_ptr (argv[i]);
+      if (p == NULL) {
+	set_local_variable (argv[i], "NULL");
+      }
+    } else {
+      set_local_variable (argv[i], "NULL");
+    }      
+  }
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/macro.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/macro.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/macro.c	(revision 12606)
@@ -0,0 +1,52 @@
+# include "basic.h"
+# include "macro.h"
+
+int macro (int argc, char **argv) {
+
+  int i, N, status;
+
+  if ((argc != 2) && (argc != 3) && (argc != 4)) {
+    fprintf (stderr, "USAGE: macro (cmd)\n");
+    fprintf (stderr, "  (cmd) can be one of:\n");
+    fprintf (stderr, "    (name)         -- create macro (name)\n");
+    fprintf (stderr, "    create (name)  -- create macro (name)\n");
+    fprintf (stderr, "    delete (name)  -- delete macro (name)\n");
+    fprintf (stderr, "    list   (name)  -- list macro (name)\n");
+    fprintf (stderr, "    edit   (name)  -- edit macro (name) <not working yet!> *\n");
+    fprintf (stderr, "    read   (name)  -- read macro(s) from file (name) <not working yet!> *\n");
+    fprintf (stderr, "    write  (name)  -- write macro (name) to a file <not working yet!> *\n");
+    return (FALSE);
+  }
+
+  N = sizeof (in_macro) / sizeof (Command);
+
+  /* find the macro sub-command which matches from the list. */
+  /* if sub-command is not found, assume this is creating a new macro */
+  for (i = 0; i < N; i++) {
+    if (!strcmp (in_macro[i].name, argv[1])) {
+      (*in_macro[i].func) (argc - 1, argv + 1);
+      return (status);
+    }
+  }
+
+  /* sub-command was not found, pass argv[1..N] to macro create,
+     make argv[0] say "create" to be consistent (probably not needed) */
+  REALLOCATE (argv[0], char, 8);
+  strcpy (argv[0], "create");
+  status = macro_create (argc, argv);
+  return (status);
+}
+
+
+/* macro is called with the command "macro".  
+   the command line word "macro" is meant to be followed the one of several 
+   possible options:
+   
+   macro create
+   macro delete
+   macro list
+   macro edit
+   macro read
+   macro write
+
+*/
Index: /tags/start/Ohana/src/opihi/cmd.basic/memory.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/memory.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/memory.c	(revision 12606)
@@ -0,0 +1,23 @@
+# include "basic.h"
+
+int memory (int argc, char **argv) {
+  
+# ifdef MEMMAP
+  struct mallinfo minfo;
+
+  minfo = mallinfo ();
+
+  fprintf (stderr, " arena: %d\n", minfo.arena);      /* total space in arena */
+  fprintf (stderr, " ordblks: %d\n", minfo.ordblks);    /* number of ordinary blocks */
+  fprintf (stderr, " smblks: %d\n", minfo.smblks);     /* number of small blocks */
+  fprintf (stderr, " hblkhd: %d\n", minfo.hblkhd);     /* space in holding block headers */
+  fprintf (stderr, " hblks: %d\n", minfo.hblks);      /* number of holding blocks */
+  fprintf (stderr, " usmblks: %d\n", minfo.usmblks);    /* space in small blocks in use */
+  fprintf (stderr, " fsmblks: %d\n", minfo.fsmblks);    /* space in free small blocks */
+  fprintf (stderr, " uordblks: %d\n", minfo.uordblks);   /* space in ordinary blocks in use */
+  fprintf (stderr, " fordblks: %d\n", minfo.fordblks);   /* space in free ordinary blocks */
+  fprintf (stderr, " keepcost: %d\n", minfo.keepcost);   /* space penalty if keep option is used */
+# endif
+
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/output.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/output.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/output.c	(revision 12606)
@@ -0,0 +1,34 @@
+# include "basic.h"
+
+static FILE *outfile;
+
+int output (int argc, char **argv) {
+  
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: output <filename>\n");
+    return (FALSE);
+  }
+
+  fflush (outfile);
+  if (outfile != stdout) fclose (outfile);
+  
+  /* we only use stdout, but let stderr be a synonym */
+  outfile = stdout;
+  if (strcmp (argv[1], "stdout") && strcmp (argv[1], "stderr")) {
+    outfile = fopen (argv[1], "a");
+  }
+
+  if (outfile == NULL) {
+    fprintf (stderr, "cannot open file %s\n", argv[1]);
+    outfile = stdout;
+  }
+  return (TRUE);
+}
+
+FILE *GetOutfile () {
+  return (outfile);
+}
+
+void InitOutfile () {
+  outfile = stdout;
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/quit.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/quit.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/quit.c	(revision 12606)
@@ -0,0 +1,17 @@
+# include "basic.h"
+
+int quit (int argc, char **argv) {
+
+  int state;
+
+  fprintf (stderr, "Goodbye!\n");
+  cleanup ();
+
+  state = 0;
+  if (argc > 1) {
+    state = atof (argv[1]);
+  } 
+
+  exit (state);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/run_for.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/run_for.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/run_for.c	(revision 12606)
@@ -0,0 +1,107 @@
+# include "basic.h"
+# define D_NLINES 100
+static char prompt[] = ">> ";
+
+int run_for (int argc, char **argv) {
+
+  int ThisList, depth, i, done, status, NLINES, j;
+  double start, end, delta;
+  char *input;
+  double value, sign;
+  Macro loop;
+
+  if ((argc != 4) && (argc != 5)) {
+    fprintf (stderr, "USAGE: for (var) (start) (stop) [delta] -- terminate with 'END'\n");
+    return (FALSE);
+  }
+
+  start = atof (argv[2]);
+  end   = atof (argv[3]);
+  delta = 1.0;
+  if (argc == 5) delta = atof (argv[4]);
+  sign = SIGN(delta);
+
+  NLINES = D_NLINES;
+  ALLOCATE (loop.line, char *, NLINES);
+
+  /* read in loop */
+  depth = 0;
+  ThisList = Nlists;
+  for (i = 0, done = FALSE; !done; ) {
+
+    /* get the next line (from correct place) */
+    if (ThisList == 0) 
+      input = readline (prompt);
+    else 
+      input = get_next_listentry (ThisList);
+    stripwhite (input);
+
+    /* check for end-of-data syntax error */
+    if (input == (char *) NULL) {
+      if (ThisList == 0)  {
+	fprintf (stderr, "end loop with 'END'\n");
+	continue;
+      } else {
+	fprintf (stderr, "misbalanced loop\n");
+	for (j = 0; j < loop.Nlines; j++) {
+	  free (loop.line[j]);
+	}
+	free (loop.line);
+	return (FALSE);
+      }	
+    }
+
+    /* test for new macro (or other list, in the future?) */
+    if (is_list (input)) depth ++;
+
+    /* test for end of nested list -- if not nested, END refers to this macro */
+    if (!strncasecmp (input, "END", 3)) {
+      depth --;
+      if (depth < 0) break;
+    }
+
+    /* if line has data, add to loop list */
+    if (*input) { 
+      loop.line[i] = input;
+      i++;
+      if (i == NLINES - 1) {
+	NLINES += D_NLINES;
+	REALLOCATE (loop.line, char *, NLINES);
+      }
+    }
+  }
+
+  /* cleanup loop data */
+  free (input);
+  loop.Nlines = i;
+  REALLOCATE (loop.line, char *, MAX (loop.Nlines, 1));
+
+  for (value = start; (sign*value < sign*end) && !interrupt; value += delta) {
+    loop_continue = loop_break = FALSE;
+    if ((int)value == value) 
+      set_int_variable (argv[1], (int) value);
+    else 
+      set_variable (argv[1], value);
+    status = exec_loop (&loop);
+    value = get_double_variable (argv[1]);
+    if (loop_break) break;
+    if (loop_continue) continue;
+  }
+  loop_continue = loop_break = FALSE;
+  if (auto_break && !status) loop_break = TRUE;
+
+  /* cleanup list */
+  for (j = 0; j < loop.Nlines; j++) {
+    free (loop.line[j]);
+  }
+  free (loop.line);
+  if (loop_break) return (FALSE);
+  return (TRUE);
+}
+
+/*
+  If we are entering at the keyboard (Nlists == 0), use readline.
+  Otherwise, read from the current list, remove list lines.
+  execute when we hit the final "END" (the true END -- we count macro defines!!) 
+*/
+     
Index: /tags/start/Ohana/src/opihi/cmd.basic/run_if.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/run_if.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/run_if.c	(revision 12606)
@@ -0,0 +1,129 @@
+# include "basic.h"
+# define prompt    "if: "
+
+int run_if (int argc, char **argv) {
+
+  int ThisList, depth, done, status, BreakOnTrue;
+  int logic, equals;
+  char *input, *outline, *val;
+  int nloop, size;
+
+  BreakOnTrue = FALSE;
+
+  if ((argc != 2) && (argc != 3)) {
+    fprintf (stderr, "USAGE: if (conditional) [break], end with the word 'END'\n");
+    return (FALSE);
+  }
+  if ((argc == 3) && strcmp (argv[2], "break")) {
+    fprintf (stderr, "USAGE: if (conditional) [break], end with the word 'END'\n");
+    return (FALSE);
+  }
+  if ((argc == 3) && !strcmp (argv[2], "break")) {
+    BreakOnTrue = TRUE;
+  }
+
+  /* read in if-list */
+  nloop = 0;
+  depth = 0;
+  ThisList = Nlists;
+
+  /* determine value of conditional expression */
+  val = dvomath (1, &argv[1], &size, 0);
+  if (val == NULL) { /* try expression as string op string */
+    char **stack;
+    int Nstack;
+
+    stack = isolate_elements (1, &argv[1], &Nstack); 
+    if (Nstack != 5) goto syntax;
+    if (strcmp (stack[0], "(")) goto syntax;
+    if (strcmp (stack[4], ")")) goto syntax;
+    equals = -1;
+    if (!strcmp (stack[2], "==")) equals = TRUE;
+    if (!strcmp (stack[2], "!=")) equals = TRUE;
+    if (equals == -1) goto syntax;
+    logic = FALSE;
+    if (equals && !strcmp (stack[1], stack[3])) logic = TRUE;
+    if (!equals && strcmp (stack[1], stack[3])) logic = TRUE;
+  } else {
+    logic = atof (val); /* warning: round-off error is a danger */ 
+  }
+  if (BreakOnTrue) {
+    if (logic) {
+      loop_break = TRUE;
+      return (FALSE);
+    } else {
+      return (TRUE);
+    }
+  }    
+
+  done = FALSE;
+  while (!done) {
+
+    nloop ++;
+    /* get the next line (from correct place) */
+    if (ThisList == 0) {
+      input = readline (prompt);
+    } else {
+      input = get_next_listentry (ThisList);
+    }
+
+    if ((ThisList == 0) && (input == (char *) NULL)) {
+      fprintf (stderr, "end if-block with 'END'\n");
+      continue;
+    }
+    if ((ThisList >  0) && (input == (char *) NULL)) {
+      fprintf (stderr, "missing 'END' in if-block\n");
+      input = strcreate ("end");
+    }
+
+    stripwhite (input);
+
+    /* test for new macro, search for "end" statement */
+    if (!logic && is_list (input)) {
+      depth ++;
+      free (input);
+      continue;
+    }
+    
+    /* check for an "else", invert logic */
+    if ((depth == 0) && !strncasecmp (input, "ELSE", 4)) {
+      logic ^= TRUE;
+      free (input);
+      continue;
+    }
+
+    /* test for end of nested block -- if not nested, END refers to this if */
+    if (!strncasecmp (input, "END", 3)) {
+      depth --;
+      if (depth < 0) { 
+	/* we hit the last "END", if-block is done */
+	free (input);
+	return (TRUE);	
+      }
+      free (input);  /* a do-nothing line */
+      continue;
+    }
+
+    if (logic) {
+      if (*input) { 
+	if (ThisList == 0) add_history (input);
+	status = command (input, &outline);
+	if (outline != (char *) NULL) free (outline);
+	if (!status) return (FALSE);
+      }
+    } else {
+      free (input);
+    }
+  }
+  return (TRUE);
+
+ syntax:
+  fprintf (stderr, "syntax error in if-statement\n");
+  return (FALSE);
+}
+
+/*
+     If we are entering at the keyboard (Nlists == 0), use readline.
+     Otherwise, read from the current list, remove list lines.
+     End when we hit the final "END" (the true END -- we count macro defines!!) 
+     */
Index: /tags/start/Ohana/src/opihi/cmd.basic/run_while.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/run_while.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/run_while.c	(revision 12606)
@@ -0,0 +1,97 @@
+# include "basic.h"
+# define D_NLINES 100
+static char prompt[] = ">> ";
+
+int run_while (int argc, char **argv) {
+
+  int ThisList, depth, i, done, status, NLINES, j;
+  char *input, *val;
+  int logic, size;
+  Macro loop;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: while (condition)\n");
+    return (FALSE);
+  }
+
+  val = dvomath (1, &argv[1], &size, 0);
+  if (val == NULL) return (FALSE);
+  logic = atof (val); /* warning: round-off error is a danger */
+  
+  NLINES = D_NLINES;
+  ALLOCATE (loop.line, char *, NLINES);
+
+  /* read in loop */
+  depth = 0;
+  ThisList = Nlists;
+  for (i = 0, done = FALSE; !done; ) {
+
+    /* get the next line (from correct place) */
+    if (ThisList == 0) 
+      input = readline (prompt);
+    else 
+      input = get_next_listentry (ThisList);
+    stripwhite (input);
+
+    /* check for end-of-data syntax error */
+    if (input == (char *) NULL) {
+      if (ThisList == 0)  {
+	fprintf (stderr, "end 'while' loop with 'END'\n");
+	continue;
+      } else {
+	fprintf (stderr, "misbalanced 'while' loop\n");
+	for (j = 0; j < loop.Nlines; j++) {
+	  free (loop.line[j]);
+	}
+	free (loop.line);
+	return (FALSE);
+      }	
+    }
+
+    /* test for new macro (or other list, in the future?) */
+    if (is_list (input)) depth ++;
+
+    /* test for end of nested list -- if not nested, END refers to this macro */
+    if (!strncasecmp (input, "END", 3)) {
+      depth --;
+      if (depth < 0) break;
+    }
+
+    /* if line has data, add to loop list */
+    if (*input) { 
+      loop.line[i] = input;
+      i++;
+      if (i == NLINES - 1) {
+	NLINES += D_NLINES;
+	REALLOCATE (loop.line, char *, NLINES);
+      }
+    }
+  }
+
+  /* cleanup loop data */
+  free (input);
+  loop.Nlines = i;
+  REALLOCATE (loop.line, char *, MAX (loop.Nlines, 1));
+
+  /* execute for loop */
+  do { 
+    loop_continue = loop_break = FALSE;
+    status = exec_loop (&loop);
+    if (loop_break) break;
+    if (loop_continue) continue;
+
+    val = dvomath (1, &argv[1], &size, 0);
+    if (val == NULL) return (FALSE);
+    logic = atof (val); /* warning: round-off error is a danger */
+  } while (logic && !interrupt);
+  loop_continue = loop_break = FALSE;
+  if (auto_break && !status) loop_break = TRUE;
+
+  /* cleanup list */
+  for (j = 0; j < loop.Nlines; j++) {
+    free (loop.line[j]);
+  }
+  free (loop.line);
+  if (loop_break) return (FALSE);
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/scan.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/scan.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/scan.c	(revision 12606)
@@ -0,0 +1,42 @@
+# include "basic.h"
+
+int scan (int argc, char **argv) {
+
+  int i, N, status;
+  char *line;
+  FILE *f;
+
+  if ((argc != 3) && (argc != 4)) {
+    fprintf (stderr, "USAGE: scan <filename> <var> [N]\n");
+    return (FALSE);
+  }
+
+  f = stdin;
+  if (strcmp (argv[1], "stdin")) {
+    f = fopen (argv[1], "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "file %s not found\n", argv[1]);
+      return (FALSE);
+    }
+  }
+  
+  ALLOCATE (line, char, 1024);
+  N = 1;
+  if (argc == 4) 
+    N = atof(argv[3]);
+
+  for (i = 0; (i < N) && ((status = scan_line (f, line)) != EOF); i++);
+  if (i < N) {
+    set_str_variable (argv[2], "EOF");
+  } else {
+    set_str_variable (argv[2], line);
+  }
+  free (line);
+
+  if (f != stdin) {
+    fclose (f);
+  }
+  return (TRUE);
+ 
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/shell.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/shell.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/shell.c	(revision 12606)
@@ -0,0 +1,25 @@
+# include "basic.h"
+
+int shell (int argc, char **argv) {
+  
+  int i, status;
+  char line[2048], tmp[1024];
+
+  bzero (tmp, 1024);
+  bzero (line, 2048);
+
+  for (i = 1; i < argc; i++) {
+    sprintf (tmp, "%s ", argv[i]);
+    strcat (line, tmp);
+  }
+
+  strcat (line, "\n");
+  status = system (line);
+
+  if (status) {
+    return (FALSE);
+  } else {
+    return (TRUE);
+  }
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.basic/sleep.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/sleep.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/sleep.c	(revision 12606)
@@ -0,0 +1,15 @@
+# include "basic.h"
+
+int exec_sleep (int argc, char **argv) {
+
+  int i;
+
+  if (argc < 2) {
+    fprintf (stderr, "usage: sleep N\n");
+    return (FALSE);
+  }
+
+  i = atof (argv[1]);
+  sleep (i);
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/sprintf.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/sprintf.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/sprintf.c	(revision 12606)
@@ -0,0 +1,82 @@
+# include "basic.h"
+# define NCHAR 1024
+
+/* convert line, tmp, fmt to dynamic strings? */
+
+int sprintf_opihi (int argc, char **argv) {
+
+  int i, Nchar;
+  char line[NCHAR], tmp[NCHAR], fmt[NCHAR];
+  char *p1, *p2, *q;
+
+  if (argc < 3) {
+    fprintf (stderr, "USAGE: sprintf var format value value ...\n");
+    return (FALSE);
+  }
+
+  q  = line;
+  bzero (line, NCHAR);
+
+  p1 = argv[2];
+  for (i = 3; i < argc; i++) {
+    bzero (tmp, NCHAR);
+    bzero (fmt, NCHAR);
+
+    /* find next format character */
+    p2 = strchr (p1, '%');
+    if (p2 == (char *) NULL) {
+      fprintf (stderr, "mismatch between format and values\n");
+      return (FALSE);
+    }
+    if (strlen(q) + p2 - p1 > NCHAR) {
+      fprintf (stderr, "line too long");
+      return (FALSE);
+    }
+    memcpy (q, p1, p2-p1);
+    q = line + strlen(line);
+    
+    /* identify type (%NNNs %NNNNd %NNNNf) */
+    for (p1 = p2 + 1; (*p1 == '.') || (*p1 == '-') || (*p1 == '+') || (*p1 == ' ') || isdigit(*p1); p1++);
+    memcpy (fmt, p2, p1 - p2 + 1);
+    switch (*p1) {
+      case 'e':
+      case 'f':
+	sprintf (tmp, fmt, atof(argv[i]));
+	break;
+      case 's':
+	sprintf (tmp, fmt, argv[i]);
+	break;
+      case 'd':
+      case 'c':
+      case 'x':
+	sprintf (tmp, fmt, atoi(argv[i]));
+	break;
+      default:
+	fprintf (stderr, "syntax error in format (only e,f,s,d,c,x allowed)\n");
+	return (FALSE);
+    }
+    if (strlen(q) + strlen(tmp) > NCHAR) {
+      fprintf (stderr, "line too long");
+      return (FALSE);
+    }
+    memcpy (q, tmp, strlen(tmp));
+    q = line + strlen(line);
+    p1++;
+  }
+  p2 = strchr (p1, '%');
+  if (p2 != (char *) NULL) {
+    fprintf (stderr, "mismatch between format and values\n");
+    return (FALSE);
+  }
+  
+  p2 = p1 + strlen (p1);
+  if (strlen(q) + p2 - p1 > NCHAR) {
+    fprintf (stderr, "line too long");
+    return (FALSE);
+  }
+  memcpy (q, p1, p2-p1);
+  set_str_variable (argv[1], line);
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.basic/strchr.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/strchr.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/strchr.c	(revision 12606)
@@ -0,0 +1,29 @@
+# include "basic.h"
+
+int getchr_func (int argc, char **argv) {
+
+  /* returns position of the first given character */ 
+  char *c;
+  int pos;
+
+  if ((argc != 3) && (argc != 4)) {
+    fprintf (stderr, "USAGE: strchr (string) (char) [var]\n");
+    return (FALSE);
+  }
+
+  c = strchr (argv[1], argv[2][0]);
+
+  if (c == (char *) NULL) {
+    pos = -1;
+  } else {
+    pos = c - argv[1];
+  }
+
+  if (argc == 5) {
+    set_variable (argv[3], pos);
+  } else {
+    fprintf (stderr, "%d\n", pos);
+  }
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/strlen.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/strlen.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/strlen.c	(revision 12606)
@@ -0,0 +1,22 @@
+# include "basic.h"
+
+int strlen_func (int argc, char **argv) {
+
+  /* returns length of the given string */ 
+  int len;
+
+  if ((argc != 2) && (argc != 3)) {
+    fprintf (stderr, "USAGE: strchr (string) [var]\n");
+    return (FALSE);
+  }
+
+  len = strlen (argv[1]);
+
+  if (argc == 3) {
+    set_int_variable (argv[2], len);
+  } else {
+    fprintf (stderr, "%d\n", len);
+  }
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/substr.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/substr.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/substr.c	(revision 12606)
@@ -0,0 +1,37 @@
+# include "basic.h"
+
+int substr_func (int argc, char **argv) {
+
+  int N1, N2, len;
+  char *c, *string;
+
+  if ((argc != 4) && (argc != 5)) {
+    fprintf (stderr, "USAGE: substr (string) N1 N2 [var]\n");
+    return (FALSE);
+  }
+
+  N1 = atof (argv[2]);
+  N2 = atof (argv[3]);
+
+  len = strlen (argv[1]);
+  if ((N1 >= len) || (N1 + N2 > len)) {
+    c = (char *) NULL;
+  } else {
+    c = strncreate (&argv[1][N1], N2);
+  }
+
+  if (c == (char *) NULL) {
+    string = strcreate ("");
+  } else {
+    string = strcreate (c);
+  }
+
+  if (argc == 5) {
+    set_str_variable (argv[4], string);
+  } else {
+    fprintf (stderr, "%s\n", string);
+  }
+  free (string);
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/usleep.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/usleep.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/usleep.c	(revision 12606)
@@ -0,0 +1,15 @@
+# include "basic.h"
+
+int exec_usleep (int argc, char **argv) {
+
+  int i;
+
+  if (argc < 2) {
+    fprintf (stderr, "usage: usleep N\n");
+    return (FALSE);
+  }
+
+  i = atof (argv[1]);
+  usleep (i);
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/wait.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/wait.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/wait.c	(revision 12606)
@@ -0,0 +1,14 @@
+# include "basic.h"
+
+int wait (int argc, char **argv) {
+
+  char buff[1024];
+  int i;
+
+  for (i = 1; i < argc; i++) {
+    fprintf (stderr, "%s ", argv[i]);
+  }
+  fprintf (stderr, "\n");
+  scan_line (stdin, buff);
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.basic/which.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.basic/which.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.basic/which.c	(revision 12606)
@@ -0,0 +1,18 @@
+# include "basic.h"
+
+int which (int argc, char **argv) {
+
+  Command *cmd;
+ 
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: which <filename>\n");
+    return (FALSE);
+  }
+
+  cmd = MatchCommand (argv[1], TRUE, TRUE);
+  if (cmd == NULL) return (FALSE);
+
+  fprintf (stderr, "%-25s -- %s\n", cmd[0].name, cmd[0].help);
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/Makefile
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/Makefile	(revision 12606)
@@ -0,0 +1,169 @@
+include ../../../Configure
+
+HOME    =       $(ROOT)/src/opihi.v2
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+SDIR    =       $(HOME)/cmd.data
+#
+DESTBIN =       $(LBIN)
+DESTLIB =       $(LLIB)
+DESTINC =       $(LINC)
+DESTMAN =       $(LMAN)
+HELP    =       $(HOME)/help
+#  
+INCS    =       -I$(INC) -I$(LINC) -I$(XINC)
+LFLAGS  =       -L$(LLIB) -L$(LIB)
+LIBS    =       -lFITS -lsocket -lnsl -lreadline -ltermcap -lohana -lm
+CFLAGS  =       $(INCS)
+CCFLAGS =       $(LIBS) 
+
+# data user commands ########################
+datacmd = \
+$(SDIR)/init.$(ARCH).o          \
+$(SDIR)/accum.$(ARCH).o		\
+$(SDIR)/applyfit2d.$(ARCH).o	\
+$(SDIR)/applyfit.$(ARCH).o	\
+$(SDIR)/box.$(ARCH).o		\
+$(SDIR)/center.$(ARCH).o	\
+$(SDIR)/clear.$(ARCH).o		\
+$(SDIR)/clip.$(ARCH).o		\
+$(SDIR)/concat.$(ARCH).o	\
+$(SDIR)/contour.$(ARCH).o	\
+$(SDIR)/create.$(ARCH).o	\
+$(SDIR)/cursor.$(ARCH).o	\
+$(SDIR)/cut.$(ARCH).o		\
+$(SDIR)/delete.$(ARCH).o	\
+$(SDIR)/device.$(ARCH).o	\
+$(SDIR)/dimendown.$(ARCH).o	\
+$(SDIR)/dimenup.$(ARCH).o	\
+$(SDIR)/erase.$(ARCH).o		\
+$(SDIR)/extract.$(ARCH).o	\
+$(SDIR)/fft1d.$(ARCH).o		\
+$(SDIR)/fft2d.$(ARCH).o		\
+$(SDIR)/fit2d.$(ARCH).o		\
+$(SDIR)/fit.$(ARCH).o		\
+$(SDIR)/gaussj.$(ARCH).o	\
+$(SDIR)/gaussdeviate.$(ARCH).o	\
+$(SDIR)/grid.$(ARCH).o		\
+$(SDIR)/gridify.$(ARCH).o       \
+$(SDIR)/histogram.$(ARCH).o	\
+$(SDIR)/imhist.$(ARCH).o	\
+$(SDIR)/imcut.$(ARCH).o	\
+$(SDIR)/integrate.$(ARCH).o	\
+$(SDIR)/interpolate.$(ARCH).o	\
+$(SDIR)/jpeg.$(ARCH).o		\
+$(SDIR)/kern.$(ARCH).o		\
+$(SDIR)/keyword.$(ARCH).o	\
+$(SDIR)/labels.$(ARCH).o	\
+$(SDIR)/limits.$(ARCH).o	\
+$(SDIR)/line.$(ARCH).o		\
+$(SDIR)/list_buffers.$(ARCH).o	\
+$(SDIR)/list_header.$(ARCH).o	\
+$(SDIR)/list_vectors.$(ARCH).o	\
+$(SDIR)/load.$(ARCH).o		\
+$(SDIR)/mcreate.$(ARCH).o	\
+$(SDIR)/medacc.$(ARCH).o	\
+$(SDIR)/mget.$(ARCH).o		\
+$(SDIR)/minterpolate.$(ARCH).o	\
+$(SDIR)/mset.$(ARCH).o		\
+$(SDIR)/peak.$(ARCH).o		\
+$(SDIR)/plot.$(ARCH).o		\
+$(SDIR)/point.$(ARCH).o		\
+$(SDIR)/ps.$(ARCH).o		\
+$(SDIR)/pop.$(ARCH).o		\
+$(SDIR)/push.$(ARCH).o		\
+$(SDIR)/queues.$(ARCH).o	\
+$(SDIR)/radial.$(ARCH).o	\
+$(SDIR)/rd.$(ARCH).o		\
+$(SDIR)/rdseg.$(ARCH).o		\
+$(SDIR)/read_vectors.$(ARCH).o	\
+$(SDIR)/rebin.$(ARCH).o		\
+$(SDIR)/resize.$(ARCH).o	\
+$(SDIR)/roll.$(ARCH).o		\
+$(SDIR)/rotate.$(ARCH).o	\
+$(SDIR)/save.$(ARCH).o		\
+$(SDIR)/section.$(ARCH).o	\
+$(SDIR)/select.$(ARCH).o	\
+$(SDIR)/set.$(ARCH).o		\
+$(SDIR)/shift.$(ARCH).o		\
+$(SDIR)/sort.$(ARCH).o		\
+$(SDIR)/spline_apply.$(ARCH).o	\
+$(SDIR)/spline_construct.$(ARCH).o \
+$(SDIR)/stats.$(ARCH).o		   \
+$(SDIR)/style.$(ARCH).o		   \
+$(SDIR)/subraster.$(ARCH).o	   \
+$(SDIR)/subset.$(ARCH).o	   \
+$(SDIR)/svd.$(ARCH).o		   \
+$(SDIR)/swapbytes.$(ARCH).o	   \
+$(SDIR)/textline.$(ARCH).o	   \
+$(SDIR)/tv.$(ARCH).o		   \
+$(SDIR)/tvcontour.$(ARCH).o	   \
+$(SDIR)/tvgrid.$(ARCH).o	   \
+$(SDIR)/uniq.$(ARCH).o		   \
+$(SDIR)/unsign.$(ARCH).o	   \
+$(SDIR)/vbin.$(ARCH).o		   \
+$(SDIR)/vclip.$(ARCH).o		   \
+$(SDIR)/vgrid.$(ARCH).o		   \
+$(SDIR)/vstat.$(ARCH).o		   \
+$(SDIR)/vroll.$(ARCH).o		   \
+$(SDIR)/vpop.$(ARCH).o		   \
+$(SDIR)/wd.$(ARCH).o		   \
+$(SDIR)/write_vectors.$(ARCH).o	   \
+$(SDIR)/zap.$(ARCH).o		   \
+$(SDIR)/zplot.$(ARCH).o
+
+libdatacmd:    $(DESTLIB)/libdatacmd.a 
+
+$(LIB)/libdatacmd.$(ARCH).a:   	$(datacmd)
+
+# utilities #################################################
+$(BIN)/%.$(ARCH):
+	@if [ ! -d $(BIN) ]; then mkdir -p $(BIN); fi
+	$(CC) $^ -o $@ $(LFLAGS) $(LIBS)
+	@echo "compiled $*"
+	@echo ""
+
+$(DESTBIN)/%: $(BIN)/%.$(ARCH) 
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	rm -f $(DESTBIN)/$*
+	cp $(BIN)/$*.$(ARCH) $(DESTBIN)/$*
+	@echo "installed $*"
+	@echo ""
+
+$(LIB)/%.$(ARCH).a:
+	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
+	rm -f $@
+	ar rcv $@ $^ 
+	ranlib $@
+	@echo "compiled library $*"
+	@echo ""
+
+$(DESTLIB)/%.a: $(LIB)/%.$(ARCH).a
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	@echo ""
+	rm -f $@
+	cp $^ $@
+
+lib%.clean:
+	rm -f $(LIB)/lib$*.$(ARCH).a
+	rm -f $($*)
+	@echo ""
+
+%.clean:
+	rm -f $(BIN)/$*.$(ARCH)
+	@echo ""
+
+%.$(ARCH).o : %.c
+	$(CC) $(CFLAGS) -c $*.c -o $@
+
+clean:
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f $(LIB)/*.$(ARCH).a
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+dist: clean
+	rm -f $(BIN)/*
+	rm -f $(LIB)/*
Index: /tags/start/Ohana/src/opihi/cmd.data/accum.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/accum.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/accum.c	(revision 12606)
@@ -0,0 +1,72 @@
+# include "data.h"
+
+int accum (int argc, char **argv) {
+  
+  int i, Nbins, bin, N, Normalize;
+  float start, end, delta;
+  float *V, *K, *O, *NV;
+  Vector *val, *key, *out;
+
+  Normalize = FALSE;
+  if (N = get_argument (argc, argv, "-norm")) {
+    remove_argument (N, &argc, argv);
+    Normalize = TRUE;
+  }
+
+  if ((argc != 6) && (argc != 7)) {
+    fprintf (stderr, "USAGE: accum <value> <vector> <key> start end [delta]\n");
+    return (FALSE);
+  }
+
+  if ((val = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((key = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if (val[0].Nelements != key[0].Nelements) {
+    fprintf (stderr, "key and value don't match\n");
+    return (FALSE);
+  }
+  if ((out = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  start = atof (argv[4]);
+  end   = atof (argv[5]);
+  if (argc == 7) 
+    delta = atof (argv[6]);
+  else 
+    delta = 1;
+  if ((start == end) || (delta == 0)) {
+    fprintf (stderr, "error in value: %f to %f, %f\n", start, end, delta);
+    return (FALSE);
+  }
+  delta = fabs (delta);
+  if (end - start < 0) {
+    delta = -1.0 * delta;
+  }
+  Nbins = (end - start) / delta;
+
+  out[0].Nelements = Nbins;
+  REALLOCATE (out[0].elements, float, out[0].Nelements);
+  bzero (out[0].elements, sizeof(float)*out[0].Nelements);
+  if (Normalize) {
+    ALLOCATE (NV, float, Nbins);
+    bzero (NV, sizeof(float)*Nbins);
+  }
+
+  V = val[0].elements;
+  K = key[0].elements;
+  O = out[0].elements;
+
+  for (i = 0; i < val[0].Nelements; i++, V++, K++) {
+    bin = MIN (MAX (0, (*K - start) / delta), Nbins - 1);
+    O[bin] += *V;
+    if (Normalize) NV[bin] ++;
+  }      
+
+  if (Normalize) {
+    for (i = 0; i < Nbins; i++) {
+      O[i] /= (float) NV[i];
+    }
+    free (NV);
+  }
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/applyfit.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/applyfit.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/applyfit.c	(revision 12606)
@@ -0,0 +1,58 @@
+# include "data.h"
+
+char *get_variable (char *);
+
+int applyfit (int argc, char **argv) {
+  
+  int i, j, order;
+  char *c, name[64];
+  double *C, X;
+  float *x, *y;
+  Vector *xvec, *yvec;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: applyfit x y\n");
+    return (FALSE);
+  }
+
+  c = get_variable ("Cn");
+  if (c == (char *) NULL) {
+    fprintf (stderr, "no fit available\n");
+    return (FALSE);
+  }
+  order = atof (c);
+
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+  if ((yvec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);    
+
+  ALLOCATE (C, double, order+1);
+  for (i = 0; i < order + 1; i++) {
+    sprintf (name, "C%d", i);
+    c = get_variable (name);
+    if (c == (char *) NULL) {
+      fprintf (stderr, "missing fit term %d\n", i);
+      return (FALSE);
+    }
+    C[i] = atof (c);
+  }
+  yvec[0].Nelements = xvec[0].Nelements;
+  REALLOCATE (yvec[0].elements, float, yvec[0].Nelements);
+  bzero (yvec[0].elements, sizeof(float)*yvec[0].Nelements);
+  x = xvec[0].elements;
+  y = yvec[0].elements;
+
+  for (j = 0; j < xvec[0].Nelements; j++, x++, y++) {
+    X = 1;
+    for (i = 0; i < order + 1; i++) {
+      *y += C[i]*X;
+      X = X * (*x);
+    }
+  }
+
+  return (TRUE);
+
+}
+
+
+
+
Index: /tags/start/Ohana/src/opihi/cmd.data/applyfit2d.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/applyfit2d.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/applyfit2d.c	(revision 12606)
@@ -0,0 +1,68 @@
+# include "data.h"
+
+char *get_variable (char *);
+
+int applyfit2d (int argc, char **argv) {
+  
+  int i, j, n, order;
+  char *c, name[64];
+  double **C, X, Y;
+  float *x, *y, *z;
+  Vector *xvec, *yvec, *zvec;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: applyfit x y z\n");
+    return (FALSE);
+  }
+
+  c = get_variable ("Cnn");
+  if (c == (char *) NULL) {
+    fprintf (stderr, "no fit available\n");
+    return (FALSE);
+  }
+  order = atof (c);
+
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+  if ((zvec = SelectVector (argv[3], ANYVECTOR, TRUE)) == NULL) return (FALSE);    
+
+  ALLOCATE (C, double *, order+1);
+  for (i = 0; i < order + 1; i++) {
+    ALLOCATE (C[i], double, order+1);
+    for (j = 0; j < order + 1 - i; j++) {
+      sprintf (name, "CX%dY%d", i, j);
+      c = get_variable (name);
+      if (c == (char *) NULL) {
+	fprintf (stderr, "missing fit term %d,%d\n", i, j);
+	return (FALSE);
+      }
+      C[i][j] = atof (c);
+    }
+  }
+
+  zvec[0].Nelements = xvec[0].Nelements;
+  REALLOCATE (zvec[0].elements, float, zvec[0].Nelements);
+  bzero (zvec[0].elements, sizeof(float)*zvec[0].Nelements);
+  x = xvec[0].elements;
+  y = yvec[0].elements;
+  z = zvec[0].elements;
+
+  for (n = 0; n < xvec[0].Nelements; n++, x++, y++, z++) {
+    Y = X = 1;
+    for (j = 0; j < order + 1; j++) {
+      X = Y;
+      for (i = 0; i < order + 1 - j; i++) {
+	*z += C[i][j]*X;
+	X = X * (*x);
+      }
+      Y = Y * (*y);
+    }
+  }
+
+  return (TRUE);
+
+}
+
+
+
+
Index: /tags/start/Ohana/src/opihi/cmd.data/box.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/box.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/box.c	(revision 12606)
@@ -0,0 +1,105 @@
+# include "data.h"
+
+int box (int argc, char **argv) {
+  
+  int i, N, Ngraph, Xgraph;
+  char buffer[65], buffer2[65];
+  Graphdata graphmode;
+  char Ticks[16], Axis[16], Labels[16];
+  
+  strcpy (Ticks, "2222");
+  if (N = get_argument (argc, argv, "-ticks")) {
+    remove_argument (N, &argc, argv);
+    strcpy (Ticks, argv[N]);
+    remove_argument (N, &argc, argv);
+    if (strlen (Ticks) != 4) { goto usage; }
+    for (i = 0; i < strlen (Ticks); i++) {
+      if ((Ticks[i] != '0') && (Ticks[i] != '1') && (Ticks[i] != '2')) { goto usage; }
+    }
+  }
+  
+  strcpy (Labels, "2222");
+  if (N = get_argument (argc, argv, "-labels")) {
+    remove_argument (N, &argc, argv);
+    strcpy (Labels, argv[N]);
+    remove_argument (N, &argc, argv);
+    if (strlen (Labels) != 4) { goto usage; }
+    for (i = 0; i < strlen (Labels); i++) {
+      if ((Labels[i] != '0') && (Labels[i] != '1') && (Labels[i] != '2')) { goto usage; }
+    }
+  }
+
+  strcpy (Axis, "2222");
+  if (N = get_argument (argc, argv, "-axis")) {
+    remove_argument (N, &argc, argv);
+    strcpy (Axis, argv[N]);
+    remove_argument (N, &argc, argv);
+    if (strlen (Axis) != 4) { goto usage; }
+    for (i = 0; i < strlen (Axis); i++) {
+      if ((Axis[i] != '0') && (Axis[i] != '1') && (Axis[i] != '2')) { goto usage; }
+    }
+  }
+
+  Ngraph = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Ngraph = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraph (&graphmode, &Xgraph, &Ngraph)) return (FALSE);
+
+  if (argc != 1) goto usage;
+
+  write (Xgraph, "DBOX", 4);
+
+  snprintf (buffer, 64, "%12.6g %12.6g %12.6g %12.6g", graphmode.xmin, graphmode.xmax, graphmode.ymin, graphmode.ymax);
+  snprintf (buffer2, 64, "NBYTES: %6d", strlen (buffer));
+  write (Xgraph, buffer2, 16);
+  write (Xgraph, buffer, strlen (buffer));
+  
+  snprintf (buffer, 64, "%s %s %s", Axis, Labels, Ticks);
+  snprintf (buffer2, 64, "NBYTES: %6d", strlen (buffer));
+  write (Xgraph, buffer2, 16);
+  write (Xgraph, buffer, strlen (buffer));
+  
+  return (TRUE);
+      
+ usage:
+  fprintf (stderr, "USAGE: box [-ticks NNNN] [-axis NNNN] [-labels NNNN]\n");
+  return (FALSE);
+
+}
+
+
+/* box has:
+   axis
+   labels
+   ticks
+
+   assign like this:   
+   -axis 0000
+   -labels 0000
+   -ticks 0000
+
+   default:
+   -axis 1111
+   -labels 1100
+   -ticks 1111
+   
+
+
+   messages to kapa:
+
+   DBOX
+   (xmin) (xmax) (ymin) (ymax)
+   AAAA LLLL TTTT
+
+   A = axis
+   L = label
+   T = ticks
+   
+   0 = off
+   1 = on
+   2 = default / maintain
+
+*/
Index: /tags/start/Ohana/src/opihi/cmd.data/center.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/center.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/center.c	(revision 12606)
@@ -0,0 +1,39 @@
+# include "data.h"
+
+int center (int argc, char **argv) {
+  
+  double x, y;
+  int zoom;
+  char buffer[512], buffer2[20];
+  int Ximage, Nimage, N;
+  
+  Nimage = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Nimage = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (&Ximage, &Nimage)) return (FALSE);
+
+  if ((argc != 3) && (argc != 4)) {
+    fprintf (stderr, "USAGE: center x y [zoom]\n");
+    return (FALSE);
+  }
+
+  x = atof (argv[1]);
+  y = atof (argv[2]);
+  zoom = 0;
+  if (argc == 4) {
+    zoom = atof (argv[3]);
+  }
+
+  write (Ximage, "CENT", 4); /* tell Ximage to look for the incoming image */
+
+  sprintf (buffer, "%8.3f %8.3f %8d ", x, y, zoom);
+  sprintf (buffer2, "NBYTES %8d ", strlen (buffer));
+  write (Ximage, buffer2, 16);
+  write (Ximage, buffer, strlen (buffer));
+  
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/clear.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/clear.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/clear.c	(revision 12606)
@@ -0,0 +1,36 @@
+# include "data.h"
+
+int clear (int argc, char **argv) {
+  
+  int N, ClearSection;
+  int Ngraph, Xgraph;
+
+  Ngraph = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Ngraph = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraph (NULL, &Xgraph, &Ngraph)) return (FALSE);
+
+  ClearSection = FALSE;
+  if (N = get_argument (argc, argv, "-s")) {
+    remove_argument (N, &argc, argv);
+    ClearSection = TRUE;
+  }
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: clear [-n Xgraph]\n");
+    return (FALSE);
+  }
+
+  if (ClearSection) {
+    write (Xgraph, "ERAS", 4);
+  } else {
+    write (Xgraph, "ERSS", 4);
+  }
+  
+  return (TRUE);
+  
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/clip.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/clip.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/clip.c	(revision 12606)
@@ -0,0 +1,71 @@
+# include "data.h"
+
+int clip (int argc, char **argv) {
+
+  int i, Npix, DO_NAN, DO_INF, N;
+  double min, Vmin, max, Vmax, nan_val, inf_val;
+  float *in;
+  Buffer *buf;
+
+  DO_NAN = FALSE;
+  if (N = get_argument (argc, argv, "-nan")) {
+    remove_argument (N, &argc, argv);
+    nan_val  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    DO_NAN = TRUE;
+  }
+
+  DO_INF = FALSE;
+  if (N = get_argument (argc, argv, "-inf")) {
+    remove_argument (N, &argc, argv);
+    inf_val  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    DO_INF = TRUE;
+  }
+
+  if ((argc != 6) && (!(DO_INF || DO_NAN))) {
+    fprintf (stderr, "USAGE: clip (buffer) [min Vmin max Vmax] [-inf val] [-nan val]\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  if (argc == 6) {
+    min = atof (argv[2]);
+    Vmin = atof (argv[3]);
+    max = atof (argv[4]);
+    Vmax = atof (argv[5]);
+  }
+
+  Npix = buf[0].matrix.Naxis[0]*buf[0].matrix.Naxis[1];
+  in = (float *) buf[0].matrix.buffer;
+
+  if (argc == 6) {
+    for (i = 0; i < Npix; i++, in++) {
+      if (*in < min) 
+	*in = Vmin;
+      if (*in > max)
+	*in = Vmax;
+    }
+  }
+  in = (float *) buf[0].matrix.buffer;
+  if (DO_NAN) {
+    for (i = 0; i < Npix; i++, in++) {
+      if (isnan (*in)) {
+	*in = nan_val;
+      }
+    }
+  }
+  in = (float *) buf[0].matrix.buffer;
+  if (DO_INF) {
+    for (i = 0; i < Npix; i++, in++) {
+      if (!finite (*in)) {
+	*in = inf_val;
+      }
+    }
+  }
+  return (TRUE);
+
+}
+
+
Index: /tags/start/Ohana/src/opihi/cmd.data/concat.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/concat.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/concat.c	(revision 12606)
@@ -0,0 +1,39 @@
+# include "data.h"
+
+int concat (int argc, char **argv) {
+
+  int  i, j, Nin;
+  char *end;
+  double value;
+  Vector *ivec, *ovec;
+
+  /** check basic syntax **/
+  if (argc != 3) {
+    fprintf (stderr, "SYNTAX: concat (vector/value) vector\n");
+    fprintf (stderr, "  concatanate (vector/value) to vector\n");
+    return (FALSE);
+  }
+
+  if ((ovec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  /* if argv[1] is a number, use just that */
+  value = strtod (argv[1], &end);
+  if (end == argv[1] + strlen(argv[1])) {
+    Nin = ovec[0].Nelements;
+    ovec[0].Nelements++;
+    REALLOCATE (ovec[0].elements, float, ovec[0].Nelements);
+    ovec[0].elements[Nin] = atof (argv[1]);
+    return (TRUE);
+  } 
+  
+  if ((ivec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  
+  REALLOCATE (ovec[0].elements, float, ovec[0].Nelements + ivec[0].Nelements);
+  for (j = ovec[0].Nelements, i = 0; i < ivec[0].Nelements; i++, j++) {
+    ovec[0].elements[j] = ivec[0].elements[i];
+  }
+  ovec[0].Nelements += ivec[0].Nelements;
+  
+  return (TRUE);
+    
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/contour.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/contour.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/contour.c	(revision 12606)
@@ -0,0 +1,262 @@
+# include "data.h"
+# define LL { \
+ dx =  d00 / (*v01 - *v00); \
+ dy = -d00 / (*v10 - *v00); \
+ x = i - 0.5; \
+ y = j - dy - 0.5; }
+
+# define UL { \
+ tmp = d00 / (*v10 - *v00); \
+ dy = 1 - tmp; \
+ dx =  d10 / (*v11 - *v10); \
+ x = i - 0.5; \
+ y = j + tmp - 0.5; }
+      
+# define LR { \
+ tmp = d00 / (*v01 - *v00); \
+ dx = 1 - tmp; \
+ dy = d01 / (*v11 - *v01); \
+ x = i + tmp - 0.5; \
+ y = j - 0.5; }
+
+# define UR { \
+ tmp = d10 / (*v11 - *v10); \
+ dx = 1 - tmp; \
+ dy = -d11 / (*v01 - *v11); \
+ x = i + tmp - 0.5; \
+ y = j + 1 - 0.5; }
+      
+# define HZ { \
+ tmp = d00 / (*v10 - *v00); \
+ dy = d01 / (*v11 - *v01) - tmp; \
+ dx = 1; \
+ x = i - 0.5; \
+ y = j + tmp - 0.5; }
+
+# define VT { \
+ tmp = d00 / (*v01 - *v00); \
+ dx = d10 / (*v11 - *v10) - tmp; \
+ x = i + tmp - 0.5; \
+ dy = 1; \
+ y = j - 0.5; }
+
+Vector *xv, *yv;
+int N, NVEC;
+
+void DUMP (float x, float y, float dx, float dy) {
+  
+  xv[0].elements[N]   = x;
+  xv[0].elements[N+1] = x+dx;
+  
+  yv[0].elements[N]   = y;
+  yv[0].elements[N+1] = y+dy;
+  
+  N+=2;
+
+  if (N >= NVEC - 2) {
+    NVEC += 100;
+    REALLOCATE (xv[0].elements, float, NVEC);
+    REALLOCATE (yv[0].elements, float, NVEC);
+  }
+}
+
+int contour (int argc, char **argv) {
+
+  int i, j, Nx, Ny;
+  float level, d00, d01, d10, d11, tmp;
+  float x, y, dx, dy;
+  float *v00, *v01, *v10, *v11;
+  float *matrix;
+  Buffer *buf;
+  
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: contour <buffer> X Y level\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((xv = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yv = SelectVector (argv[3], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  level = atof (argv[4]);
+  matrix = (float *)(buf[0].matrix.buffer);
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+
+  v00 = matrix;
+  v01 = matrix + 1;
+  v10 = matrix + Nx;
+  v11 = matrix + Nx + 1;
+  d01 = (level - *v00);
+  d11 = (level - *v10);
+
+  N = 0;
+  NVEC = 100;
+  REALLOCATE (xv[0].elements, float, NVEC);
+  REALLOCATE (yv[0].elements, float, NVEC);
+
+  for (j = 1; j < Ny; j++) {
+    if (!(j%10)) fprintf (stderr, ".");
+    for (i = 1; i < Nx; i++, v00++, v01++, v10++, v11++) {
+
+      d00 = d01;
+      d10 = d11;
+      d01 = (level - *v01);
+      d11 = (level - *v11);
+
+      if (((d00 > 0) && (d01 > 0) && (d10 > 0) && (d11 > 0)) ||
+	  ((d00 < 0) && (d01 < 0) && (d10 < 0) && (d11 < 0)))
+	continue;
+
+      if ((d00 > 0) && (d10 <= 0)) { 
+	if ((d01 <= 0) && (d11 <= 0)) { /* \  */
+	  LL;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 > 0) && (d11 <= 0)) { /* -  */
+	  HZ;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 > 0) && (d11 > 0)) { /* /  */
+	  UL;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 > 0)) { /* \\  */
+	  LL;
+	  DUMP (x,y,dx,dy);
+	  UR;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+      }
+
+      if ((d00 <= 0) && (d10 > 0)) {
+	if ((d01 > 0) && (d11 > 0)) { /* \  */
+	  LL;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 > 0)) { /* -  */
+	  HZ;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 <= 0)) { /* /  */
+	  UL;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 > 0) && (d11 <= 0)) { /* //  */
+	  UL;
+	  DUMP (x,y,dx,dy);
+	  LR;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+      }
+      
+
+      if ((d00 <= 0) && (d10 <= 0)) { 
+	if ((d01 > 0) && (d11 <= 0)) {
+	  LR;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 > 0)) {
+	  UR;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 > 0) && (d11 > 0)) {
+	  VT;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+      }
+
+      if ((d00 > 0) && (d10 > 0)) { 
+	if ((d01 <= 0) && (d11 > 0)) {
+	  LR;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 > 0) && (d11 <= 0)) {
+	  UR;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 <= 0)) {
+	  VT;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+      }
+
+    }
+    /* skip left-hand edge */
+    v00++; v01++; v10++; v11++;
+    d01 = (level - *v00);
+    d11 = (level - *v10);
+  }
+
+  /****** bottom line *******/
+  v00 = matrix;  
+  v01 = matrix + 1;  
+  y = 0;
+  dx = 0;
+  dy = -0.5;
+  for (i = 1; i < Nx; i++, v00++, v01++) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      x = i + (level - *v01)/(*v01 - *v00);
+      DUMP (x,y,dx,dy);
+    }
+  }
+
+  /********** top line *******/
+  v00 = matrix + Nx*(Ny - 1);  
+  v01 = v00 + 1;
+  y = Ny - 1;
+  dx = 0;
+  dy = 0.5;
+  for (i = 1; i < Nx; i++, v00++, v01++) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      x = i + (level - *v01)/(*v01 - *v00);
+      DUMP (x,y,dx,dy);
+    }
+  }
+
+  /******** left line *********/
+  v00 = matrix; 
+  v01 = matrix + Nx;
+  x = 0;
+  dx = -0.5;
+  dy = 0;
+  for (j = 1; j < Ny; j++, v00+=Nx, v01+=Nx) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      y = j + (level - *v01)/(*v01 - *v00);
+      DUMP (x,y,dx,dy);
+    }
+  }
+
+  /******** right line *********/
+  v00 = matrix + Nx - 1; 
+  v01 = v00 + Nx;
+  x = Nx - 1;
+  dx = 0.5;
+  dy = 0;
+  for (j = 1; j < Ny; j++, v00+=Nx, v01+=Nx) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      y = j + (level - *v01)/(*v01 - *v00);
+      DUMP (x,y,dx,dy);
+    }
+  }
+  
+/* free anything? */
+
+  xv[0].Nelements = N;
+  yv[0].Nelements = N;
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/create.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/create.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/create.c	(revision 12606)
@@ -0,0 +1,79 @@
+# include "data.h"
+
+int imcreate (int argc, char **argv);
+
+int create (int argc, char **argv) {
+  
+  int i, N;
+  float start, end, delta;
+  Vector *vec;
+  
+  if (N = get_argument (argc, argv, "-image")) {
+    remove_argument (N, &argc, argv);
+    return (imcreate (argc, argv));
+  }
+  
+  if ((argc != 5) && (argc != 4)) {
+    fprintf (stderr, "USAGE: create vector start end [delta]\n");
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  start = atof (argv[2]);
+  end   = atof (argv[3]);
+  delta = 1;
+  if (argc == 5) delta = atof (argv[4]);
+  if ((start == end) || (delta == 0)) {
+    fprintf (stderr, "error in value: %f to %f, %f\n", start, end, delta);
+    return (FALSE);
+  }
+  delta = fabs (delta);
+  if (end - start < 0) {
+    delta = -1.0 * delta;
+  }
+
+  vec[0].Nelements = (end - start) / delta;
+  REALLOCATE (vec[0].elements, float, vec[0].Nelements);
+
+  for (i = 0; i < vec[0].Nelements; i++) {
+    vec[0].elements[i] = start + i*delta;
+  }
+
+  return (TRUE);
+}
+
+
+int imcreate (int argc, char **argv) {
+  
+  Buffer *buf;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: create -image buffer Nx Ny\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  fits_free_matrix (&buf[0].matrix);
+  fits_free_header (&buf[0].header);
+
+  buf[0].bitpix = 16;
+  buf[0].unsign = FALSE;
+  buf[0].bscale = 1.0;
+  buf[0].bzero  = 0x8000;
+
+  buf[0].header.bitpix = -32;
+  buf[0].header.unsign = FALSE;
+  buf[0].header.bscale = 1.0;
+  buf[0].header.bzero  = 0.0;
+
+  buf[0].header.Naxes = 2;
+  buf[0].header.Naxis[0] = atoi (argv[2]);
+  buf[0].header.Naxis[1] = atoi (argv[3]);
+
+  fits_create_header (&buf[0].header);
+  fits_create_matrix (&buf[0].header, &buf[0].matrix);
+
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/cursor.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/cursor.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/cursor.c	(revision 12606)
@@ -0,0 +1,92 @@
+# include "data.h"
+
+int cursor (int argc, char **argv) {
+
+  char buffer[40], string[20], key;
+  int i, N, Nsource, Source, IsImage, oldsignal;
+  double X, Y, R, D, Z;
+  Graphdata graphmode;
+  Buffer *buf;
+
+  Nsource = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Nsource = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-g")) {
+    remove_argument (N, &argc, argv);
+    SetImageDevice (FALSE);
+  }  
+  if (N = get_argument (argc, argv, "-i")) {
+    remove_argument (N, &argc, argv);
+    SetImageDevice (TRUE);
+  }  
+  IsImage = GetCurrentDevice ();
+  if (IsImage) {
+    if (!GetImage (&Source, &Nsource)) return (FALSE);
+  } else {
+    if (!GetGraph (&graphmode, &Source, &Nsource)) return (FALSE);
+  }
+
+  N = 0;
+  if (argc == 2) N = atof (argv[1]);
+
+  if ((argc != 1) && (argc != 2)) {
+    fprintf (stderr, "USAGE: cursor [Npts] [-n window] [-g | -i]\n");
+    return (FALSE);
+  }
+  
+  buf = NULL;
+  if (IsImage) buf = SelectBuffer (GetImageName(), OLDBUFFER, FALSE);
+  
+  sprintf (string, "CURS");
+  write (Source, string, 4); /* ask Source to look for the keystrokes */
+  
+  oldsignal = (int) signal (SIGINT, handle_interrupt);
+  interrupt = FALSE;
+  Z = -1.0;
+  for (i = 0; ((i < N) || (N == 0)) && !interrupt; i++) {
+    bzero (buffer, 20);
+    read (Source, buffer, 32);
+    buffer[32] = 0;
+    sscanf (buffer, "%c %lf %lf", &key, &X, &Y);
+
+    sprintf (string, "X%1c", key);
+    set_variable (string, X);
+    sprintf (string, "Y%1c", key);
+    set_variable (string, Y);
+    sprintf (string, "%c", key);
+    set_str_variable ("KEY", string);
+    
+    if (IsImage && (buf != NULL)) 
+      Z = fits_get_matrix_value (&buf[0].matrix, (int)X, (int)Y);
+
+    if (!IsImage) {
+      XY_to_RD (&R, &D, X, Y, &graphmode.coords);
+      sprintf (string, "R%1c", key);
+      set_variable (string, R);
+      sprintf (string, "D%1c", key);
+      set_variable (string, D);
+    }
+
+    /* I still don't like this, but I have to decide which to print... */
+    if (IsImage) {
+      fprintf (GetOutfile(), "%c %f %f  %f\n", key, X, Y, Z);
+    } else {
+      fprintf (GetOutfile(), "%c %f %f\n", key, X, Y);
+    }
+
+    if ((key == 'q') || (key == 'Q')) {
+      signal (SIGINT, (void *) oldsignal);
+      write (Source, "NCUR", 4); /* ask Source to stop looking for the keystrokes */
+      return (TRUE);
+    }
+
+  }
+
+  signal (SIGINT, (void *) oldsignal);
+  write (Source, "NCUR", 4); /* ask Source to look for the keystrokes */
+  return (TRUE);
+      
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/cut.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/cut.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/cut.c	(revision 12606)
@@ -0,0 +1,120 @@
+# include "data.h"
+
+enum {SUM, MEAN, MEDIAN};
+
+int cut (int argc, char **argv) {
+  
+  int i, j, N, Nx, Ny, Mode;
+  float *Vin, *Vbuf, value;
+  int sx, sy, nx, ny;
+  Vector *xvec, *yvec;
+  Buffer *buf;
+
+  Mode = SUM;
+  if (N = get_argument (argc, argv, "-median")) {
+    remove_argument (N, &argc, argv);
+    Mode = MEDIAN;
+  }
+  if (N = get_argument (argc, argv, "-mean")) {
+    remove_argument (N, &argc, argv);
+    Mode = MEAN;
+  }
+
+  if (argc != 9) {
+    fprintf (stderr, "USAGE: cut <buffer> <X vector> <Y vector> <X|Y> sx sy nx ny\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+ 
+  sx = atof (argv[5]);
+  sy = atof (argv[6]);
+  nx = atof (argv[7]);
+  ny = atof (argv[8]);
+
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+
+  if ((sx < 0) || (sy < 0) || (sx+nx > Nx) || (sy+ny > Ny)) {
+    fprintf (stderr, "region out of range\n");
+    return (FALSE);
+  }
+
+  if ((xvec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[3], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  switch (argv[4][0]) {
+  case 'x':
+  case 'X':
+    /* create output vectors */
+    xvec[0].Nelements = yvec[0].Nelements = nx;
+    REALLOCATE (xvec[0].elements, float, MAX (nx, 1));
+    REALLOCATE (yvec[0].elements, float, MAX (nx, 1));
+    bzero (yvec[0].elements, nx*sizeof(float));
+    for (i = 0; i < nx; i++) {
+      xvec[0].elements[i] = i + sx; 
+    }
+    ALLOCATE (Vbuf, float, MAX (ny, 1));
+
+    for (i = 0; i < nx; i++) {
+      /* accumulate values */
+      Vin = (float *)(buf[0].matrix.buffer) + sy*Nx + sx + i; 
+      for (j = 0; j < ny; j++, Vin += Nx) {
+	Vbuf[j] = *Vin;
+      }
+      /* apply stat of choice */
+      if (Mode == MEDIAN) {
+	fsort (Vbuf, ny);
+	value = Vbuf[(int)(0.5*ny)];
+      } else {
+	value = 0;
+	for (j = 0; j < ny; j++) {
+	  value += Vbuf[j];
+	}
+	if (Mode == MEAN) { value /= ny; }
+      }
+      yvec[0].elements[i] = value;
+    }
+    break;
+    
+  case 'y':
+  case 'Y':
+    xvec[0].Nelements = yvec[0].Nelements = ny;
+    REALLOCATE (xvec[0].elements, float, ny);
+    REALLOCATE (yvec[0].elements, float, ny);
+    bzero (yvec[0].elements, ny*sizeof(float));
+    for (i = 0; i < ny; i++) {
+      xvec[0].elements[i] = i + sy; 
+    }
+    ALLOCATE (Vbuf, float, MAX (nx, 1));
+
+    for (i = 0; i < ny; i++) {
+      /* accumulate values */
+      Vin = (float *)(buf[0].matrix.buffer) + (sy + i)*Nx + sx; 
+      for (j = 0; j < nx; j++, Vin ++) {
+	Vbuf[j] = *Vin;
+      }
+      /* apply stat of choice */
+      if (Mode == MEDIAN) {
+	fsort (Vbuf, nx);
+	value = Vbuf[(int)(0.5*nx)];
+      } else {
+	value = 0;
+	for (j = 0; j < nx; j++) {
+	  value += Vbuf[j];
+	}
+	if (Mode == MEAN) { value /= nx; }
+      }
+      yvec[0].elements[i] = value;
+    }
+    break;
+
+  default:
+    fprintf (stderr, "<dir> can be X or Y\n");
+    return (FALSE);
+    break;
+  }
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/delete.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/delete.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/delete.c	(revision 12606)
@@ -0,0 +1,31 @@
+# include "data.h"
+
+int delete (int argc, char **argv) {
+  
+  int i, N, Quiet;
+
+  Quiet = FALSE;
+  if (N = get_argument (argc, argv, "-q")) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-quiet")) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc < 2) {
+    fprintf (stderr, "USAGE: delete <obiect> [<object> ..]\n");
+    return (FALSE);
+  }
+
+  for (i = 1; i < argc; i++) {
+    if (DeleteNamedBuffer (argv[i])) continue;
+    if (DeleteNamedVector (argv[i])) continue;
+    if (DeleteNamedScalar (argv[i])) continue;
+    if (!Quiet) fprintf (stderr, "can't find object %s\n", argv[i]);
+  }
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/device.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/device.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/device.c	(revision 12606)
@@ -0,0 +1,33 @@
+# include "data.h"
+
+int device (int argc, char **argv) {
+
+  int N, Source, Nsource, IsImage;
+  /* set / get current graphics device */
+
+  Nsource = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Nsource = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-g")) {
+    remove_argument (N, &argc, argv);
+    SetImageDevice (FALSE);
+  }  
+  if (N = get_argument (argc, argv, "-i")) {
+    remove_argument (N, &argc, argv);
+    SetImageDevice (TRUE);
+  }  
+
+  IsImage = GetCurrentDevice ();
+  if (IsImage) {
+    if (!GetImage (&Source, &Nsource)) return (FALSE);
+    fprintf (stderr, "kii %d\n", Nsource); 
+  } else {
+    if (!GetGraph (NULL, &Source, &Nsource)) return (FALSE);
+    fprintf (stderr, "kapa %d\n", Nsource); 
+  }
+
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/dimendown.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/dimendown.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/dimendown.c	(revision 12606)
@@ -0,0 +1,34 @@
+# include "data.h"
+
+int dimendown (int argc, char **argv) {
+  
+  int i, Nx, Ny, Npix;
+  float *in, *out;
+  Vector *vec;
+  Buffer *buf;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: dimendown <buffer> <vector>\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((vec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+  Npix = Nx * Ny;
+
+  vec[0].Nelements = Npix;
+  REALLOCATE (vec[0].elements, float, Npix);
+
+  in = (float *) buf[0].matrix.buffer;
+  out = vec[0].elements;
+
+  for (i = 0; i < Npix; i++, in++, out++) {
+    *out = *in;
+  }
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/dimenup.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/dimenup.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/dimenup.c	(revision 12606)
@@ -0,0 +1,51 @@
+# include "data.h"
+
+int dimenup (int argc, char **argv) {
+  
+  int i, Nx, Ny, Npix;
+  float *in, *out;
+  Vector *vec;
+  Buffer *buf;
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: dimenup <vector> <buffer> Nx Ny\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((vec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  Npix = vec[0].Nelements;
+  Nx = atof (argv[3]);
+  Ny = atof (argv[4]);
+  if (Npix != Nx * Ny) {
+    fprintf (stderr, "dimensions don't match\n");
+    return (FALSE);
+  }
+
+  buf[0].matrix.Naxis[0] = Nx;
+  buf[0].matrix.Naxis[1] = Ny;
+
+  /* I should encapsulate this in a create_default_buffer */
+  fits_free_matrix (&buf[0].matrix);
+  fits_free_header (&buf[0].header);
+  buf[0].header.bitpix = buf[0].bitpix = -32;
+  buf[0].header.unsign = buf[0].unsign = FALSE;
+  buf[0].header.bscale = buf[0].bscale = 1.0;
+  buf[0].header.bzero  = buf[0].bzero  = 0.0;
+  buf[0].header.Naxes = 2;
+  buf[0].header.Naxis[0] = Nx;
+  buf[0].header.Naxis[1] = Ny;
+  fits_create_header (&buf[0].header);
+  fits_create_matrix (&buf[0].header, &buf[0].matrix);
+
+  out = (float *) buf[0].matrix.buffer;
+  in = vec[0].elements;
+
+  for (i = 0; i < Npix; i++, in++, out++) {
+    *out = *in;
+  }
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/erase.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/erase.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/erase.c	(revision 12606)
@@ -0,0 +1,53 @@
+# include "data.h"
+
+int erase (int argc, char **argv) {
+  
+  int i, n, N;
+  char buffer[128];
+  int Ximage, Nimage;
+  
+  Nimage = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Nimage = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (&Ximage, &Nimage)) return (FALSE);
+
+  if (argc < 2) {
+    fprintf (stderr, "USAGE: erase (overlay) [overlay, overlay, ..] \n");
+    fprintf (stderr, " (overlay) may be: red (0), green (1), blue (2), yellow (3) or all\n");
+    return (FALSE);
+  }
+
+  for (i = 1; i < argc; i++) {
+    if (strcmp (argv[i], "0")   && strcmp (argv[i], "1")     && strcmp (argv[i], "2")   && strcmp (argv[i], "3") &&
+	strcmp (argv[i], "red") && strcmp (argv[i], "green") && strcmp (argv[i], "blue") && strcmp (argv[i], "yellow") &&
+	strcmp (argv[i], "all") && strcmp (argv[i], "tick") ) {
+      fprintf (stderr, "%s is not a valid overlay\n", argv[i]);
+      return (FALSE);
+    }
+    n = atof (argv[i]);
+    if (!(strcmp (argv[i], "all"))) {
+      for (n = 0; n < 4; n++) {
+	write (Ximage, "ERAS", 4); /* force Ximage to look for the incoming image */
+	sprintf (buffer, "OVERLAY %7d ", n);
+	write (Ximage, buffer, 16);
+      }
+      return (TRUE);
+    }
+    
+    if (!(strcmp (argv[i], "red"))) n = 0;
+    if (!(strcmp (argv[i], "green"))) n = 1;
+    if (!(strcmp (argv[i], "blue"))) n = 2;
+    if (!(strcmp (argv[i], "yellow"))) n = 3;
+    if (!(strcmp (argv[i], "tick"))) n = 4;
+    
+    write (Ximage, "ERAS", 4); /* force Ximage to look for the incoming image */
+    sprintf (buffer, "OVERLAY %7d ", n);
+    write (Ximage, buffer, 16);
+  }
+
+  return (TRUE);
+  
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/extract.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/extract.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/extract.c	(revision 12606)
@@ -0,0 +1,92 @@
+# include "data.h"
+
+int extract (int argc, char **argv) {
+  
+  int i, j;
+  float *Vin, *Vout;
+  int sx, sy, nx, ny, NX, NY;
+  int Sx, Sy, Nx, Ny;
+  Buffer *in, *out;
+
+  if (argc != 11) {
+    fprintf (stderr, "USAGE: extract <from> <to> sx sy nx ny Sx Sy Nx Ny\n");
+    return (FALSE);
+  }
+
+  if ((in = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  NX = in[0].matrix.Naxis[0];
+  NY = in[0].matrix.Naxis[1];
+
+  sx = atof (argv[3]);
+  sy = atof (argv[4]);
+  nx = atof (argv[5]);
+  ny = atof (argv[6]);
+
+  Sx = atof (argv[7]);
+  Sy = atof (argv[8]);
+  Nx = atof (argv[9]);
+  Ny = atof (argv[10]);
+
+  if ((Sy + ny > Ny) || (Sx + nx > Nx)) {
+    fprintf (stderr, "mismatch between source and dest regions\n");
+    fprintf (stderr, "%d + %d > %d or %d + %d > %d\n", Sy, ny, Ny, Sx, nx, Nx);
+    return (FALSE);
+  }
+
+  /* region is not on first image */
+  if ((sx + nx < 0) || (sy + ny < 0) || 
+      (sx > in[0].matrix.Naxis[0]) || 
+      (sy > in[0].matrix.Naxis[1])) {
+    fprintf (stderr, "region outside of source image\n");
+    return (FALSE);
+  }
+
+  if ((Sx + nx > Nx) || (Sy + ny > Ny)) {
+    fprintf (stderr, "source region larger than dest region\n");
+    return (FALSE);
+  }
+  if ((Sx < 0) || (Sy < 0)) {
+    fprintf (stderr, "dest region out of range\n");
+    return (FALSE);
+  }
+
+  if ((out = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) {
+    if ((out = SelectBuffer (argv[2], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+    fits_free_matrix (&out[0].matrix);
+    fits_free_header (&out[0].header);
+
+    out[0].bitpix = in[0].bitpix;
+    out[0].unsign = in[0].unsign;
+    out[0].bscale = in[0].bscale;
+    out[0].bzero  = in[0].bzero;
+    fits_copy_header (&in[0].header, &out[0].header);
+    fits_modify (&out[0].header, "NAXIS1", "%d", 1, Nx);
+    fits_modify (&out[0].header, "NAXIS2", "%d", 1, Ny);
+    out[0].header.Naxis[0] = Nx;
+    out[0].header.Naxis[1] = Ny;
+    fits_create_matrix (&out[0].header, &out[0].matrix);
+  } else {
+    if ((out[0].header.Naxis[1] != Ny) || (out[0].header.Naxis[0] != Nx)) {
+      fprintf (stderr, "matrix sizes mis-matched\n");
+      fprintf (stderr, "%d x %d  vs  %d x %d\n", Nx, Ny, 
+	       out[0].header.Naxis[0], out[0].header.Naxis[1]);
+      return (FALSE);
+    }
+  }
+
+  for (j = 0; j < ny; j++) {
+    if (j + sy < 0) continue;
+    if (j + sy >= NY) continue;
+    Vin = (float *)(in[0].matrix.buffer) + (j + sy)*in[0].matrix.Naxis[0] + sx;  
+    Vout = (float *)(out[0].matrix.buffer) + (j + Sy)*out[0].matrix.Naxis[0] + Sx;   
+    for (i = 0; i < nx; i++, Vin++, Vout++) {
+      if (i + sx < 0) continue;
+      if (i + sx >= NX) continue;
+      *Vout = *Vin;
+    }
+  }
+
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/fft1d.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/fft1d.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/fft1d.c	(revision 12606)
@@ -0,0 +1,69 @@
+# include "data.h"
+
+int fft1d (int argc, char **argv) {
+  
+  int i, Npix, ZeroImaginary;
+  float *t1, *t2, *temp;
+  Vector *Ire, *Iim, *Ore, *Oim;
+
+  if ((argc != 6) || (strcmp (argv[3], "to"))) {
+    fprintf (stderr, "USAGE: fft1d (real) (imag) to (real) (imag)\n");
+    return (FALSE);
+  }
+
+  ZeroImaginary = TRUE;
+  if ((Ire = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if (strcmp (argv[2], "0")) {
+    ZeroImaginary = FALSE;
+    if ((Iim = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  }    
+  if ((Ore = SelectVector (argv[4], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((Oim = SelectVector (argv[5], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  Npix = Ire[0].Nelements;
+  if (!ZeroImaginary && (Npix != Iim[0].Nelements)) {
+    fprintf (stderr, "vector mismatch in size\n");
+    return (FALSE);
+  }
+
+  if (!IsBinary (Npix)) {
+    fprintf (stderr, "Npix is not a binary number!\n");
+    return (FALSE);
+  }
+  
+  ALLOCATE (temp, float, 2*Npix);
+  if (ZeroImaginary) {
+    t1 = Ire[0].elements;
+    for (i = 0; i < Npix; i++, t1++) {
+      temp[2*i  ] = *t1;
+      temp[2*i+1] = 0;
+    }
+  } else {
+    t1 = Ire[0].elements;
+    t2 = Iim[0].elements;
+    for (i = 0; i < Npix; i++, t1++, t2++) {
+      temp[2*i  ] = *t1;
+      temp[2*i+1] = *t2;
+    }
+  }    
+    
+  fft (temp, Npix, 1); 
+
+  Ore[0].Nelements = Npix;
+  Oim[0].Nelements = Npix;
+  REALLOCATE (Ore[0].elements, float, Npix);
+  REALLOCATE (Oim[0].elements, float, Npix);
+ 
+  t1 = Ore[0].elements;
+  t2 = Oim[0].elements;
+  for (i = 0; i < Npix; i++, t1++, t2++) {
+    *t1 = temp[2*i  ] / Npix;
+    *t2 = temp[2*i+1] / Npix;
+  }    
+  
+  free (temp);
+  
+  return (TRUE);
+}
+
+  
Index: /tags/start/Ohana/src/opihi/cmd.data/fft2d.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/fft2d.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/fft2d.c	(revision 12606)
@@ -0,0 +1,112 @@
+# include "data.h"
+
+int fft2d (int argc, char **argv) {
+  
+  int i, N, Nx, Ny, Naxis[2];
+  int Npix, ZeroImaginary, isign;
+  float *t1, *t2, *out, *temp;
+  Buffer *Ire, *Iim, *Ore, *Oim;;
+
+  isign = 1;
+  if (N = get_argument (argc, argv, "-inverse")) {
+    remove_argument (N, &argc, argv);
+    isign = -1;
+  }
+
+  if ((argc != 6) || (strcmp (argv[3], "to"))) {
+    fprintf (stderr, "USAGE: fft2d (real) (imag) to (real) (imag)\n");
+    return (FALSE);
+  }
+
+  /* select input / output buffers */
+  if ((Ire = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  ZeroImaginary = TRUE; /* Input(imaginary) may be 0, in which case we create a 0 filled image */
+  if (!strcmp (argv[2], "0")) { 
+  } else {
+    ZeroImaginary = FALSE;
+    if ((Iim = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  }    
+  if ((Ore = SelectBuffer (argv[4], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((Oim = SelectBuffer (argv[5], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  /* free up output space */
+  fits_free_matrix (&Ore[0].matrix);
+  fits_free_header (&Ore[0].header);
+  fits_free_matrix (&Oim[0].matrix);
+  fits_free_header (&Oim[0].header);
+
+  /* get image dimensions, check value */
+  Npix = Ire[0].header.Naxis[0]*Ire[0].header.Naxis[1];
+  Nx = Ire[0].header.Naxis[0];
+  Ny = Ire[0].header.Naxis[1];
+  Naxis[0] = Ny; Naxis[1] = Nx;
+  if (!IsBinary (Npix)) {
+    fprintf (stderr, "dimensions are not binary!\n");
+    return (FALSE);
+  }
+  
+  /* create working space */
+  t1 = (float *) Ire[0].matrix.buffer;
+  ALLOCATE (temp, float, 2*Npix);
+  out = temp;
+
+  /* copy input to working space */
+  if (ZeroImaginary) {
+    for (i = 0; i < Npix; i++, t1++) {
+      *out = *t1;
+      out++;
+      *out = 0;
+      out++;
+    }
+  } else {
+    t2 = (float *) Iim[0].matrix.buffer;
+    for (i = 0; i < Npix; i++, t1++, t2++) {
+      *out = *t1;
+      out++;
+      *out = *t2;
+      out++;
+    }
+  } 
+    
+  /* run the fft */
+  fftN (temp, Naxis, 2, isign);
+
+  /* fix up output headers (real) */
+  fits_copy_header (&Ire[0].header, &Ore[0].header);
+  fits_modify (&Ore[0].header, "NAXIS1", "%d", 1, Nx);
+  fits_modify (&Ore[0].header, "NAXIS2", "%d", 1, Ny);
+  Ore[0].header.Naxis[0] = Nx;
+  Ore[0].header.Naxis[1] = Ny;
+  Ore[0].bitpix = Ire[0].bitpix;
+  Ore[0].unsign = Ire[0].unsign;
+  Ore[0].bscale = Ire[0].bscale;
+  Ore[0].bzero  = Ire[0].bzero;
+  fits_create_matrix (&Ore[0].header, &Ore[0].matrix);
+
+  /* fix up output headers (imaginary) */
+  fits_copy_header (&Ire[0].header, &Oim[0].header);
+  fits_modify (&Oim[0].header, "NAXIS1", "%d", 1, Nx);
+  fits_modify (&Oim[0].header, "NAXIS2", "%d", 1, Ny);
+  Oim[0].header.Naxis[0] = Nx;
+  Oim[0].header.Naxis[1] = Ny;
+  Oim[0].bitpix = Ire[0].bitpix;
+  Oim[0].unsign = Ire[0].unsign;
+  Oim[0].bscale = Ire[0].bscale;
+  Oim[0].bzero  = Ire[0].bzero;
+  fits_create_matrix (&Oim[0].header, &Oim[0].matrix);
+
+  /* move data from working space to output buffers */
+  out = temp;
+  t1 = (float *) Ore[0].matrix.buffer;
+  t2 = (float *) Oim[0].matrix.buffer;
+  for (i = 0; i < Npix; i++, t1++, t2++) {
+    *t1 = *out / Npix;
+    out ++;
+    *t2 = *out / Npix;
+    out ++;
+  }    
+
+  free (temp);
+
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/fit.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/fit.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/fit.c	(revision 12606)
@@ -0,0 +1,120 @@
+# include "data.h"
+
+int fit (int argc, char **argv) {
+  
+  double **c, **b, *s, X, Y, dY;
+  int i, j, nterm, mterm, order;
+  int N, Weight, Quiet;
+  Vector *xvec, *yvec, *dyvec;
+  float *x, *y, *dy;
+  char name[64];
+
+  Quiet = FALSE;
+  if (N = get_argument (argc, argv, "-q")) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-quiet")) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  Weight = FALSE;
+  if (N = get_argument (argc, argv, "-dy")) {
+    remove_argument (N, &argc, argv);
+    if ((dyvec = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+    remove_argument (N, &argc, argv);
+    Weight = TRUE;
+  }
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: fit x y order [-dy wt]\n");
+    return (FALSE);
+  }
+
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+
+  order = atof (argv[3]);
+  nterm = order + 1;
+  mterm = 2*order + 1;
+
+  if (xvec[0].Nelements != yvec[0].Nelements) {
+    fprintf (stderr, "vectors must have same length\n");
+    return (FALSE);
+  }
+  if (Weight && xvec[0].Nelements != dyvec[0].Nelements) {
+    fprintf (stderr, "vectors must have same length\n");
+    return (FALSE);
+  }
+  
+  x = xvec[0].elements;
+  y = yvec[0].elements;
+  if (Weight) dy = dyvec[0].elements;
+
+  ALLOCATE (s, double, 2*mterm);
+  bzero (s, 2*mterm*sizeof(double));
+  ALLOCATE (b, double *, nterm);
+  ALLOCATE (c, double *, nterm);
+  for (i = 0; i < nterm; i++) {
+    ALLOCATE (c[i], double, nterm);
+    bzero (c[i], nterm*sizeof(double));
+    ALLOCATE (b[i], double, 1);
+    bzero (b[i], sizeof(double));
+  }
+
+  for (i = 0; i < xvec[0].Nelements; i++, x++, y++) {
+    if (!(finite(*x) && finite(*y))) continue;
+    dY = 1.0;
+    if (Weight) { 
+      dY = 1.0 / SQ(*dy);
+      dy ++;
+    }
+    X = 1*dY;
+    Y = *y*dY;
+    for (j = 0; j < nterm; j++) {
+      s[j] += X;
+      b[j][0] += Y;
+      X = X * (*x);
+      Y = Y * (*x);
+    }
+    for (j = nterm; j < mterm; j++) {
+      s[j] += X;
+      X = X * (*x);
+    }
+  }
+
+  for (i = 0; i < nterm; i++) {
+    for (j = 0; j < nterm; j++) {
+      c[i][j] = s[i + j];
+    }
+  }
+  gaussj (c, nterm, b, 1);
+
+  /* print & save basic fit parameters */
+  if (!Quiet) fprintf (stderr, "y = ");
+  for (i = 0; i < nterm; i++) {
+    sprintf (name, "C%d", i);
+    set_variable (name, b[i][0]);
+    if (!Quiet) fprintf (stderr, "%f x^%d ", b[i][0], i);
+  }
+  sprintf (name, "Cn");
+  set_variable (name, (double) order);
+  
+  /* print & save basic fit parameters */
+  if (!Quiet) fprintf (stderr, "\n");
+  if (!Quiet) fprintf (stderr, "    ");
+  for (i = 0; i < nterm; i++) {
+    sprintf (name, "dC%d", i);
+    set_variable (name, sqrt(c[i][i]));
+    if (!Quiet) fprintf (stderr, "%f     ", sqrt(c[i][i]));
+  }
+  if (!Quiet) fprintf (stderr, "\n");
+
+  return (TRUE);
+
+}
+
+
+
+
Index: /tags/start/Ohana/src/opihi/cmd.data/fit2d.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/fit2d.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/fit2d.c	(revision 12606)
@@ -0,0 +1,128 @@
+# include "data.h"
+
+int fit2d (int argc, char **argv) {
+  
+  double **c, **b, **s, X, Y;
+  int k, K, i, j, nx, ny, nterm, mterm, wterm, order;
+  int N, Weight;
+  float *x, *y, *z; 
+  char name[64];
+  Vector *xvec, *yvec, *zvec, *dyvec;
+
+  Weight = FALSE;
+  if (N = get_argument (argc, argv, "-dy")) {
+    remove_argument (N, &argc, argv);
+    if ((dyvec = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+    remove_argument (N, &argc, argv);
+    Weight = TRUE;
+    fprintf (stderr, "warning: weighting currently ignored!\n");
+  }
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: fit x y z order [-dy`z wt]\n");
+    return (FALSE);
+  }
+
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+  if ((zvec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+
+  order = atof (argv[4]);
+  nterm = order + 1;
+  wterm = nterm*(nterm + 1)/2;
+  mterm = 2*order + 1;
+
+  if (xvec[0].Nelements != yvec[0].Nelements) {
+    fprintf (stderr, "vectors must have same length\n");
+    return (FALSE);
+  }
+  if (xvec[0].Nelements != zvec[0].Nelements) {
+    fprintf (stderr, "vectors must have same length\n");
+    return (FALSE);
+  }
+  if (Weight && xvec[0].Nelements != dyvec[0].Nelements) {
+    fprintf (stderr, "vectors must have same length\n");
+    return (FALSE);
+  }
+  
+  x = xvec[0].elements;
+  y = yvec[0].elements;
+  z = zvec[0].elements;
+  /* dy = dyvec[0].elements; */
+
+  /* allocate the summation matrices */
+  ALLOCATE (b, double *, wterm);
+  ALLOCATE (c, double *, wterm);
+  for (i = 0; i < wterm; i++) {
+    ALLOCATE (c[i], double, wterm);
+    bzero (c[i], wterm*sizeof(double));
+    ALLOCATE (b[i], double, 1);
+    bzero (b[i], sizeof(double));
+  }
+  ALLOCATE (s, double *, mterm);
+  for (i = 0; i < mterm; i++) {
+    ALLOCATE (s[i], double, mterm);
+    bzero (s[i], mterm*sizeof(double));
+  }
+
+  /* add up the x,y values */
+  for (i = 0; i < xvec[0].Nelements; i++, x++, y++) {
+    Y = X = 1;
+    for (ny = 0; ny < mterm; ny++) {
+      X = Y;
+      for (nx = 0; nx < mterm - ny; nx++) {
+	s[nx][ny] += X;
+	X = X * (*x);
+      }
+      Y = Y * (*y);
+    }
+  }
+
+  /* add up the z values */
+  x = xvec[0].elements;
+  y = yvec[0].elements;
+  z = zvec[0].elements;
+  for (i = 0; i < xvec[0].Nelements; i++, x++, y++, z++) {
+    Y = X = *z;
+    for (N = 0, ny = 0; ny < nterm; ny++) {
+      X = Y;
+      for (nx = 0; nx < nterm - ny; nx++, N++) {
+	b[N][0] += X;
+	X = X * (*x);
+      }
+      Y = Y * (*y);
+    }
+  }
+
+  /* re-sort mterm x mterm matrix to wterm matrix */
+  for (k = j = 0; j < nterm; j++) {
+    for (i = 0; i < nterm - j; i++, k++) {
+      for (K = ny = 0; ny < nterm; ny++) {
+	for (nx = 0; nx < nterm - ny; nx++, K++) {
+	  c[K][k] = s[nx+i][ny+j];
+	}
+      }
+    }
+  }
+
+  gaussj (c, wterm, b, 1);
+
+  fprintf (stderr, "z = ");
+  for (N = ny = 0; ny < nterm; ny++) {
+    for (nx = 0; nx < nterm - ny; nx++, N++) {
+      sprintf (name, "CX%dY%d", nx, ny);
+      set_variable (name, b[N][0]);
+      fprintf (stderr, "%f x^%d y^%d  ", b[N][0], nx, ny);
+    }
+  }
+  sprintf (name, "Cnn");
+  set_variable (name, (double) order);
+  
+  fprintf (stderr, "\n");
+  return (TRUE);
+
+}
+
+
+
+
Index: /tags/start/Ohana/src/opihi/cmd.data/gaussdeviate.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/gaussdeviate.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/gaussdeviate.c	(revision 12606)
@@ -0,0 +1,30 @@
+# include "data.h"
+
+int gaussdeviate (int argc, char **argv) {
+  
+  int i, Npts;
+  double mean, sigma;
+  Vector *vec;
+
+  if (argc != 5) goto usage;
+
+  if ((vec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) return (FALSE);    
+
+  Npts = atoi (argv[2]);
+  mean = atof (argv[3]);
+  sigma = atof (argv[4]);
+
+  vec[0].Nelements = Npts;
+  REALLOCATE (vec[0].elements, float, Npts);
+
+  gauss_init (2048);
+  for (i = 0; i < Npts; i++) {
+    vec[0].elements[i] = rnd_gauss (mean, sigma);
+  }
+  return (TRUE);
+
+ usage:
+  fprintf (stderr, "USAGE: gaussdeviate (vector) Npts mean sigma\n");
+  return (FALSE);
+    
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/gaussj.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/gaussj.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/gaussj.c	(revision 12606)
@@ -0,0 +1,58 @@
+# include "data.h"
+
+int gaussjordan (int argc, char **argv) {
+  
+  float *m, *v;
+  double **a, **b;
+  int i, j, N;
+  Vector *B;
+  Buffer *A;
+
+  if (argc != 3) goto usage;
+
+  if ((A = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);    
+  if ((B = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+
+  N = B[0].Nelements;
+  if (A[0].matrix.Naxis[0] != N) goto usage;
+  if (A[0].matrix.Naxis[1] != N) goto usage;
+  
+  ALLOCATE (a, double *, N);
+  ALLOCATE (b, double *, N);
+  for (i = 0; i < N; i++) {
+    ALLOCATE (a[i], double, N);
+    ALLOCATE (b[i], double, 1);
+  }
+
+  m = (float *) A[0].matrix.buffer;
+  v = B[0].elements;
+  for (i = 0; i < N; i++) {
+    for (j = 0; j < N; j++) {
+      a[i][j] = m[i+j*N];
+    }
+    b[i][0] = v[i]; 
+  }
+  gaussj (a, N, b, 1);
+
+  for (i = 0; i < N; i++) {
+    for (j = 0; j < N; j++) {
+       m[i+j*N] = a[i][j];
+    }
+    v[i] = b[i][0]; 
+  }
+
+  for (i = 0; i < N; i++) {
+    free (a[i]);
+    free (b[i]);
+  }
+  free (a);
+  free (b);
+  return (TRUE);
+
+ usage:
+  fprintf (stderr, "USAGE: gaussj A B\n");
+  fprintf (stderr, "  solves Ax = B, returns 1/A in A and x in B\n");
+  fprintf (stderr, "  A must be square, B same dimensions\n");
+  return (FALSE);
+    
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/grid.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/grid.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/grid.c	(revision 12606)
@@ -0,0 +1,212 @@
+# include "data.h"
+
+int grid (int argc, char **argv) {
+  
+  int j, N, MinorTick, MajorTick;
+  Vector Xvec, Yvec;
+  double range, lrange, factor, mantis, fmantis, power, major, minor, first, next;
+  Graphdata graphmode;
+  int Ngraph;
+
+  Ngraph = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Ngraph = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);
+
+  MajorTick = TRUE;
+  MinorTick = FALSE;
+  if (N = get_argument (argc, argv, "-all")) {
+    remove_argument (N, &argc, argv);
+    MinorTick = TRUE;
+  }
+
+  if (argc > 1) {
+    fprintf (stderr, "USAGE: grid [-n graph]\n");
+    return (FALSE);
+  }
+
+  N = 0;
+  Xvec.Nelements = 200;
+  Yvec.Nelements = 200;
+  ALLOCATE (Xvec.elements, float, Xvec.Nelements);
+  ALLOCATE (Yvec.elements, float, Yvec.Nelements);
+
+  major = minor = 1;
+  range = graphmode.xmax - graphmode.xmin;
+  lrange = log10(MAX(fabs(range), 1e-30));
+  factor = (int) (lrange);
+  if (lrange < 0) { factor -= 1; }
+  mantis = lrange - factor;
+  power = pow(10.0, factor);
+  fmantis = pow(10.0, mantis);
+  if ((fmantis >= 1.0) && (fmantis <=  2.0)) {
+    major = 0.5 * power;
+    minor = 0.1 * power;
+  }
+  if ((fmantis > 2.0) && (fmantis <=  4.0)) {
+    major = 1.0 * power;
+    minor = 0.2 * power;
+  }
+  if ((fmantis > 4.0) && (fmantis <=  6.0)) {
+    major = 1.0 * power;
+    minor = 0.5 * power;
+  }
+  if ((fmantis > 6.0) && (fmantis <=  10.0)) {
+    major = 2.0 * power;
+    minor = 0.5 * power;
+  }
+  if (graphmode.xmin > 0)
+    first = minor + minor*((int)(graphmode.xmin/minor));
+  else 
+    first = -minor + minor*((int)(graphmode.xmin/minor));
+  if (minor*((int)(graphmode.xmin/minor)) == graphmode.xmin) {
+    first = graphmode.xmin;
+  }
+  
+  for (j = 0, next = first; next <= graphmode.xmax; j++) {
+    if ((fabs((int)(next/major) - (next/major)) < 0.5*(minor/major)) || (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major))) {
+      if (MajorTick) {
+	/* major tick */
+	Xvec.elements[N] = next;
+	Yvec.elements[N] = graphmode.ymin;
+	N++;
+	if (N == Xvec.Nelements) {
+	  Xvec.Nelements += 200;
+	  Yvec.Nelements += 200;
+	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
+	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
+	}
+	Xvec.elements[N] = next;
+	Yvec.elements[N] = graphmode.ymax;
+	N++;
+	if (N == Xvec.Nelements) {
+	  Xvec.Nelements += 200;
+	  Yvec.Nelements += 200;
+	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
+	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
+	}
+      }
+    } else {
+      if (MinorTick) {
+	/* minor tick */
+	Xvec.elements[N] = next;
+	Yvec.elements[N] = graphmode.ymin;
+	N++;
+	if (N == Xvec.Nelements) {
+	  Xvec.Nelements += 200;
+	  Yvec.Nelements += 200;
+	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
+	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
+	}
+	Xvec.elements[N] = next;
+	Yvec.elements[N] = graphmode.ymax;
+	N++;
+	if (N == Xvec.Nelements) {
+	  Xvec.Nelements += 200;
+	  Yvec.Nelements += 200;
+	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
+	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
+	}
+      }
+    }
+    next += minor;
+  }
+
+  range = graphmode.ymax - graphmode.ymin;
+  lrange = log10(MAX(fabs(range), 1e-30));
+  factor = (int) (lrange);
+  if (lrange < 0) { factor -= 1; }
+  mantis = lrange - factor;
+  power = pow(10.0, factor);
+  fmantis = pow(10.0, mantis);
+  if ((fmantis >= 1.0) && (fmantis <=  2.0)) {
+    major = 0.5 * power;
+    minor = 0.1 * power;
+  }
+  if ((fmantis > 2.0) && (fmantis <=  4.0)) {
+    major = 1.0 * power;
+    minor = 0.2 * power;
+  }
+  if ((fmantis > 4.0) && (fmantis <=  6.0)) {
+    major = 1.0 * power;
+    minor = 0.5 * power;
+  }
+  if ((fmantis > 6.0) && (fmantis <=  10.0)) {
+    major = 2.0 * power;
+    minor = 0.5 * power;
+  }
+  if (graphmode.ymin > 0)
+    first = minor + minor*((int)(graphmode.ymin/minor));
+  else 
+    first = -minor + minor*((int)(graphmode.ymin/minor));
+  if (minor*((int)(graphmode.ymin/minor)) == graphmode.ymin) {
+    first = graphmode.ymin;
+  }
+  
+  for (j = 0, next = first; next <= graphmode.ymax; j++) {
+    if ((fabs((int)(next/major) - (next/major)) < 0.5*(minor/major)) || (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major))) {
+      if (MajorTick) {
+	/* major tick */
+	Xvec.elements[N] = graphmode.xmin;
+	Yvec.elements[N] = next;
+	N++;
+	if (N == Xvec.Nelements) {
+	  Xvec.Nelements += 200;
+	  Yvec.Nelements += 200;
+	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
+	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
+	}
+	Xvec.elements[N] = graphmode.xmax;
+	Yvec.elements[N] = next;
+	N++;
+	if (N == Xvec.Nelements) {
+	  Xvec.Nelements += 200;
+	  Yvec.Nelements += 200;
+	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
+	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
+	}
+      }
+    } else {
+      if (MinorTick) {
+	/* minor tick */
+	Xvec.elements[N] = graphmode.xmin;
+	Yvec.elements[N] = next;
+	N++;
+	if (N == Xvec.Nelements) {
+	  Xvec.Nelements += 200;
+	  Yvec.Nelements += 200;
+	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
+	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
+	}
+	Xvec.elements[N] = graphmode.xmax;
+	Yvec.elements[N] = next;
+	N++;
+	if (N == Xvec.Nelements) {
+	  Xvec.Nelements += 200;
+	  Yvec.Nelements += 200;
+	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
+	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
+	}
+      }
+    }
+    next += minor;
+  }
+
+  Xvec.Nelements = Yvec.Nelements = N;
+  graphmode.style = 2; /* points */
+  graphmode.ptype = 100; /* connect a pair */
+  graphmode.etype = 0;
+  PrepPlotting (N, &graphmode);
+  PlotVector (N, Xvec.elements);
+  PlotVector (N, Yvec.elements);
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/gridify.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/gridify.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/gridify.c	(revision 12606)
@@ -0,0 +1,86 @@
+# include "data.h"
+
+int gridify (int argc, char **argv) {
+
+  int i, Nx, Ny, Xb, Yb;
+  float Xmin, Xmax, dX, Ymin, Ymax, dY;
+  float *buf, *val, *x, *y, *z;
+  int *Nval;
+  Buffer *bf;
+  Vector *vx, *vy, *vz;
+
+  if (argc != 11) {
+    fprintf (stderr, "USAGE: vectobuf x y z buffer Xmin Xmax dX Ymin Ymax dY\n");
+    return (FALSE);
+  }
+  
+  if ((vx = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vy = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vz = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((bf = SelectBuffer (argv[4], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  if (vx[0].Nelements != vy[0].Nelements) return (FALSE);
+  if (vx[0].Nelements != vz[0].Nelements) return (FALSE);
+
+  Xmin = atof (argv[5]);
+  Xmax = atof (argv[6]);
+  dX   = atof (argv[7]);
+
+  Ymin = atof (argv[8]);
+  Ymax = atof (argv[9]);
+  dY   = atof (argv[10]);
+
+  Nx = (Xmax - Xmin) / dX + 1;
+  Ny = (Ymax - Ymin) / dY + 1;
+  
+  /* these steps are a standard 'createbuffer', define? */
+  bf[0].bitpix = -32;
+  bf[0].unsign = FALSE;
+  bf[0].bscale = 1.0;
+  bf[0].bzero  = 0.0;
+  strcpy (bf[0].file, "(empty)");
+
+  bf[0].header.bitpix = bf[0].bitpix;
+  bf[0].header.bscale = bf[0].bscale;
+  bf[0].header.bzero  = bf[0].bzero; 
+  bf[0].header.unsign = bf[0].unsign;
+  bf[0].header.Naxes = 2;
+  bf[0].header.Naxis[0] = Nx;
+  bf[0].header.Naxis[1] = Ny;
+  free (bf[0].header.buffer);  /* ALLOCATEd in SelectBuffer */
+  free (bf[0].matrix.buffer);  /* ALLOCATEd in SelectBuffer */
+  fits_create_header (&bf[0].header);
+  fits_create_matrix (&bf[0].header, &bf[0].matrix);
+
+  ALLOCATE (val, float, Nx*Ny);
+  bzero (val, Nx*Ny*sizeof(float));
+  ALLOCATE (Nval, int, Nx*Ny);
+  bzero (Nval, Nx*Ny*sizeof(int));
+
+  x = vx[0].elements;
+  y = vy[0].elements;
+  z = vz[0].elements;
+  for (i = 0; i < vx[0].Nelements; i++, x++, y++, z++) {
+    Xb = (*x - Xmin) / dX;
+    Yb = (*y - Ymin) / dY;
+    if (Xb >= Nx) continue;
+    if (Yb >= Ny) continue;
+    val[Xb + Yb*Nx] = *z;
+    Nval[Xb + Yb*Nx]++;
+  }
+
+  buf = (float *) bf[0].matrix.buffer;
+  for (i = 0; i < Nx*Ny; i++) {
+    if (Nval[i] == 0) {
+      buf[i] = 0;
+      continue;
+    }
+    buf[i] = val[i] / Nval[i];
+  }
+
+  free (val);
+  free (Nval);
+
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/histogram.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/histogram.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/histogram.c	(revision 12606)
@@ -0,0 +1,45 @@
+# include "data.h"
+
+int histogram (int argc, char **argv) {
+  
+  int i, bin, Nbins;
+  float *V, start, end, delta;
+  Vector *xvec, *yvec;
+
+  if ((argc != 6) && (argc != 5)) {
+    fprintf (stderr, "USAGE: hist invec outvec start end [delta]\n");
+    return (FALSE);
+  }
+
+  delta = 1;
+  start = atof (argv[3]);
+  end   = atof (argv[4]);
+  if (argc == 6) delta = atof (argv[5]);
+ 
+  if ((start == end) || (delta == 0)) {
+    fprintf (stderr, "error in value: %f to %f, %f\n", start, end, delta);
+    return (FALSE);
+  }
+  delta = fabs (delta);
+  if (end - start < 0) {
+    delta = -1.0 * delta;
+  }
+  Nbins = (end - start) / delta;
+  /* number here should match number in create.c */
+
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  yvec[0].Nelements = Nbins;
+    
+  REALLOCATE (yvec[0].elements, float, yvec[0].Nelements);
+  bzero (yvec[0].elements, sizeof(float)*yvec[0].Nelements);
+
+  V = xvec[0].elements;
+  for (i = 0; i < xvec[0].Nelements; i++, V++) {
+    bin = MIN (MAX (0, (*V - start) / delta), Nbins - 1);
+    yvec[0].elements[bin] += 1.0;
+  }      
+
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/imcut.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/imcut.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/imcut.c	(revision 12606)
@@ -0,0 +1,66 @@
+# include "data.h"
+
+int imcut (int argc, char **argv) {
+  
+  int i, Nx, Ny, xi, yi, L;
+  double xs, ys, xe, ye, dX, dY;
+  Vector *xvec, *yvec;
+  Buffer *buf;
+  float *V;
+
+  if (argc != 8) {
+    fprintf (stderr, "USAGE: cut <buffer> <X vector> <Y vector> xs ys xe ye\n");
+    return (FALSE);
+  }
+
+  if ((buf  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) goto usage;
+  if ((xvec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) goto usage;
+  if ((yvec = SelectVector (argv[3], ANYVECTOR, TRUE)) == NULL) goto usage;
+ 
+  xs = atof (argv[4]);
+  ys = atof (argv[5]);
+  xe = atof (argv[6]);
+  ye = atof (argv[7]);
+
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+
+  if ((xs < 0) || (xs > Nx)) goto range;
+  if ((ys < 0) || (ys > Ny)) goto range;
+  if ((xe < 0) || (xe > Nx)) goto range;
+  if ((ye < 0) || (ye > Ny)) goto range;
+
+  dX = xe - xs;
+  dY = ye - ys;
+  L = hypot (dX, dY);
+  dX = dX / L;
+  dY = dY / L;
+
+  REALLOCATE (xvec[0].elements, float, MAX (L, 1));
+  REALLOCATE (yvec[0].elements, float, MAX (L, 1));
+  xvec[0].Nelements = L;
+  yvec[0].Nelements = L;
+
+  V = (float *)buf[0].matrix.buffer;
+  for (i = 0; i < L; i++) {
+    xi = xs + i*dX - 0.5;
+    yi = ys + i*dY - 0.5;
+    xvec[0].elements[i] = i;
+    yvec[0].elements[i] = V[xi + Nx*yi];
+  }
+
+  return (TRUE);
+
+ usage: 
+  fprintf (stderr, "USAGE: circstats <buffer> x y radius\n");
+  return (FALSE);
+
+ range:
+  fprintf (stderr, "ERROR: coordinates out of range\n");
+  return (FALSE);
+
+ missed:
+  fprintf (stderr, "ERROR: buffer not found\n");
+  return (FALSE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/imhist.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/imhist.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/imhist.c	(revision 12606)
@@ -0,0 +1,97 @@
+# include "data.h"
+
+int imhist (int argc, char **argv) {
+  
+  int i, j, N;
+  int sx, sy, nx, ny, bin;
+  float *V;
+  double max, min, dx;
+  Vector *vec1, *vec2;
+  Buffer *buf;
+
+  min = max = 0.0;
+  if (N = get_argument (argc, argv, "-range")) {
+    remove_argument (N, &argc, argv);
+    min = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    max = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  sx = sy = 0.0;
+  nx = ny = 0.0;
+  if (N = get_argument (argc, argv, "-region")) {
+    remove_argument (N, &argc, argv);
+    sx = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    sy = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    nx = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    ny = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: histogram <buffer> <x> <y> [-region sx sy nx ny] [-range min max]\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  
+  /* if either range is set to zero, use the rest of the chip */
+  if (nx == 0)
+    nx = buf[0].matrix.Naxis[0] - sx;
+  if (ny == 0)
+    ny = buf[0].matrix.Naxis[1] - sy;
+
+  if ((sx < 0) || (sy < 0) || 
+      (sx+nx > buf[0].matrix.Naxis[0]) || 
+      (sy+ny > buf[0].matrix.Naxis[1])) {
+    fprintf (stderr, "region out of range\n");
+    return (FALSE);
+  }
+
+  if ((vec1 = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vec2 = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  /* unfortunately, we must do this in two passes:
+     first pass finds the max and min and defines the bin size
+     second pass counts the pixes in each bin 
+     */
+
+  if ((max == 0) && (min == 0)) {
+    max = min = *((float *)(buf[0].matrix.buffer) + sy*buf[0].matrix.Naxis[0] + sx);
+    fprintf (stderr, "sx: %d, sy: %d, first: %f\n", sx, sy, max);
+    for (j = sy; j < sy + ny; j++) {
+      V = (float *)(buf[0].matrix.buffer) + j*buf[0].matrix.Naxis[0] + sx; 
+      for (i = 0; i < nx; i++, V++) {
+	max = MAX (max, *V);
+	min = MIN (min, *V);
+      }
+    }
+  }
+  dx = (max - min) / 1024.0;
+  fprintf (stderr, "max %f, min %f, dx %f\n", max, min, dx);
+  
+  vec1[0].Nelements = 1025;
+  vec2[0].Nelements = 1025;
+  REALLOCATE (vec1[0].elements, float, vec1[0].Nelements);
+  bzero (vec1[0].elements, vec1[0].Nelements*sizeof(float));
+  REALLOCATE (vec2[0].elements, float, vec2[0].Nelements);
+  bzero (vec2[0].elements, vec2[0].Nelements*sizeof(float));
+  
+  for (j = sy; j < sy + ny; j++) {
+    V = (float *)(buf[0].matrix.buffer) + j*buf[0].matrix.Naxis[0] + sx; 
+    for (i = 0; i < nx; i++, V++) {
+      bin = MAX (MIN (1024, (*V - min) / dx), 0);
+      vec2[0].elements[bin] += 1.0;
+    }
+  }
+  for (i = 0; i < 1025; i++, V++) {
+    vec1[0].elements[i] = i*dx + min;
+  }
+  
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/init.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/init.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/init.c	(revision 12606)
@@ -0,0 +1,201 @@
+# include "data.h"
+
+int accum            PROTO((int, char **));
+int applyfit         PROTO((int, char **));
+int applyfit2d       PROTO((int, char **));
+int box              PROTO((int, char **));
+int center           PROTO((int, char **));
+int circstats        PROTO((int, char **));
+int clear            PROTO((int, char **));
+int clip             PROTO((int, char **));
+int concat           PROTO((int, char **));
+int contour          PROTO((int, char **));
+int create           PROTO((int, char **));
+int cursor           PROTO((int, char **));
+int cut              PROTO((int, char **));
+int datafile         PROTO((int, char **));
+int delete           PROTO((int, char **));
+int device           PROTO((int, char **));
+int dimendown        PROTO((int, char **));
+int dimenup          PROTO((int, char **));
+int erase            PROTO((int, char **));
+int extract          PROTO((int, char **));
+int fft1d            PROTO((int, char **));
+int fft2d            PROTO((int, char **));
+int fit2d            PROTO((int, char **));
+int fit              PROTO((int, char **));
+int gaussjordan      PROTO((int, char **));
+int gaussdeviate     PROTO((int, char **));
+int grid             PROTO((int, char **));
+int gridify          PROTO((int, char **));
+int histogram        PROTO((int, char **));
+int imhist           PROTO((int, char **));
+int imcut            PROTO((int, char **));
+int integrate        PROTO((int, char **));
+int interpolate      PROTO((int, char **));
+int jpeg             PROTO((int, char **));
+int kern             PROTO((int, char **));
+int keyword          PROTO((int, char **));
+int labels           PROTO((int, char **));
+int limits           PROTO((int, char **));
+int line             PROTO((int, char **));
+int list_buffers     PROTO((int, char **));
+int header           PROTO((int, char **));
+int list_vectors     PROTO((int, char **));
+int load             PROTO((int, char **));
+int mcreate          PROTO((int, char **));
+int medacc           PROTO((int, char **));
+int mget             PROTO((int, char **));
+int minterp          PROTO((int, char **));
+int mset             PROTO((int, char **));
+int peak             PROTO((int, char **));
+int plot             PROTO((int, char **));
+int point            PROTO((int, char **));
+int pop              PROTO((int, char **));
+int ps               PROTO((int, char **));
+int push             PROTO((int, char **));
+int queuelist        PROTO((int, char **));
+int queuesize        PROTO((int, char **));
+int rd               PROTO((int, char **));
+int rdseg            PROTO((int, char **));
+int read_vectors     PROTO((int, char **));
+int rebin            PROTO((int, char **));
+int resize           PROTO((int, char **));
+int roll             PROTO((int, char **));
+int rotate           PROTO((int, char **));
+int save             PROTO((int, char **));
+int section          PROTO((int, char **));
+int set              PROTO((int, char **));
+int shift            PROTO((int, char **));
+int sort_vectors     PROTO((int, char **));
+int spline_apply     PROTO((int, char **));
+int spline_construct PROTO((int, char **));
+int stats            PROTO((int, char **));
+int style            PROTO((int, char **));
+int subraster        PROTO((int, char **));
+int subset           PROTO((int, char **));
+int svd              PROTO((int, char **));
+int swapbytes        PROTO((int, char **));
+int textline         PROTO((int, char **));
+int tv               PROTO((int, char **));
+int tvcontour        PROTO((int, char **));
+int tvgrid           PROTO((int, char **));
+int uniq             PROTO((int, char **));
+int unsign           PROTO((int, char **));
+int vbin             PROTO((int, char **));
+int vclip            PROTO((int, char **));
+int vect_select      PROTO((int, char **));
+int vgrid            PROTO((int, char **));
+int vstat            PROTO((int, char **));
+int vroll            PROTO((int, char **));
+int vpop             PROTO((int, char **));
+int wd               PROTO((int, char **));
+int write_vectors    PROTO((int, char **));
+int zap              PROTO((int, char **));
+int zplot            PROTO((int, char **));
+
+static Command cmds[] = {  
+  {"accum",        accum,	     "accumulate vector values in another vector"},
+  {"applyfit",     applyfit,	     "apply fit to new vector"},
+  {"applyfit2d",   applyfit2d,	     "apply 2-d fit to new vector"},
+  {"box",     	   box,		     "draw a box on the plot"},
+  {"center",       center,	     "center image on coords"},
+  {"circstats",    circstats,	     "circular statistics"},
+  {"clear",   	   clear,	     "erase plot"},
+  {"clip",         clip,	     "clip values in a buffer to be within a range"},
+  {"concat",  	   concat,	     "reduce vector dimension"},
+  {"contour", 	   contour,	     "create contour from image"},
+  {"create",  	   create,	     "create a new vector"},
+  {"cursor",  	   cursor,	     "get coords from cursor"},
+  {"cut",	   cut,		     "extract a cut across an image"},
+  {"datafile",     datafile,	     "define file to read vectors"},
+  {"delete",  	   delete,	     "delete vectors or matrices"},
+  {"device",  	   device,	     "set / get current graphics device"},
+  {"dimendown",	   dimendown,	     "convert matrix to vector"},
+  {"dimenup",	   dimenup,	     "convert vector to matrix"},
+  {"erase",        erase,	     "erase objects on an overlay"},
+  {"extract",      extract,	     "extract a portion of a buffer into another buffer"},
+  {"fft1d",        fft1d,	     "fft on the pixel-stream in an image"},
+  {"fft2d",        fft2d,	     "fft on an image"},
+  {"fit",     	   fit,		     "fit polynomial to vector pair"},
+  {"fit2d",        fit2d,	     "fit 2-d polynomial to vector triplet"},
+  {"gaussj",  	   gaussjordan,	     "solve Ax = B (N-D)"},
+  {"gaussdev",	   gaussdeviate,     "generate a gaussian deviate vector"},
+  {"grid",    	   grid,	     "plot cartesian grid"},
+  {"gridify",      gridify,	     "convert vector triplet to buffer"},
+  {"header",       header,	     "print buffer header"},
+  {"histogram",    histogram,	     "generate histogram from vector"},
+  {"imhist",       imhist,	     "histogram of an image region"},
+  {"integrate",    integrate,	     "integrate a vector"},
+  {"interpolate",  interpolate,	     "interpolate between vector pairs"},
+  {"imcut",        imcut,	     "linear image cut between arbitrary coords"},
+  {"jpeg",         jpeg,	     "write text line on graph"},
+  {"kern",         kern,	     "convolve with 3x3 kernel"},
+  {"keyword",      keyword,	     "extract a FITS keyword from buffer header"},
+  {"labels",  	   labels,	     "define labels for plot"},
+  {"limits",  	   limits,	     "define plot limits"},
+  {"line",         line,	     "plot line"},
+  {"buffers",      list_buffers,     "list the currently allocated buffers"},
+  {"vectors", 	   list_vectors,     "list vectors"},
+  {"load",         load,	     "load an SAOimage style overlay"},
+  {"mcreate", 	   mcreate,	     "create a matrix"},
+  {"medacc",       medacc,	     "accumulate vector values in another vector"},
+  {"mget",    	   mget,	     "extract a vector from a matrix"},
+  {"minterp",      minterp,	     "interpolate image pixels"},
+  {"mset",    	   mset,	     "insert a vector in a matrix"},
+  {"peak",	   peak,	     "find vector peak in range"},
+  {"plot",    	   plot,	     "plot a pair of vectors"},
+  {"point",	   point,	     "load overlay with single point"},
+  {"ps",      	   ps,		     "define labels for plot"},
+  {"pop",      	   pop,		     "pop value from queue to variable"},
+  {"push",     	   push,	     "push value onto queue"},
+  {"queuelist",	   queuelist,	     "list defined queues"},
+  {"queuesize",    queuesize,	     "show queue size"},
+  {"rd",           rd,		     "load fits image"},
+  {"rdseg",	   rdseg,	     "read a segment of an image from a file"},
+  {"read",         read_vectors,     "read vectors from datafile"},
+  {"rebin",	   rebin,	     "rebin data by factor of N"},
+  {"resize",  	   resize,	     "set graphics/image window size"},
+  {"roll",	   roll,	     "roll image to new start point"},
+  {"rotate",	   rotate,	     "rotate image"},
+  {"save",	   save,	     "save an SAOimage style overlay"},
+  {"section", 	   section,	     "define section of graph"},
+  {"set",     	   set,		     "vector math"},
+  {"shift",	   shift,	     "shift data in an image"},
+  {"sort",    	   sort_vectors,     "sort list of vectors"},
+  {"spline.apply", spline_apply,     "apply spline fit to generate an image"},
+  {"spline.const", spline_construct, "create spline 2nd deriv. terms"},
+  {"stats",   	   stats,	     "give statistics on a portion of a buffer"},
+  {"style",   	   style,	     "set the style for graph plots"},
+  {"subraster",    subraster,	     "subraster of fits image"},
+  {"subset",  	   subset,	     "expand vector dimension"},
+  {"svd",	   svd,		     "singular value decomposition of a matrix"},
+  {"swapbytes",	   swapbytes,        "byte swap thing"},
+  {"textline",     textline,	     "write text line on graph"},
+  {"tv",      	   tv,		     "display an image on the Kii window"},
+  {"tvcontour",	   tvcontour,	     "send contour to overlay"},
+  {"tvgrid",	   tvgrid,	     "wait until return is typed"},
+  {"uniq",    	   uniq,	     "create a uniq vector subset from a vector"},
+  {"unsign",	   unsign,	     "toggle the UNSIGN status"},
+  {"vbin",	   vbin,	     "bin values in a vector to be within a range"},
+  {"vclip",	   vclip,	     "clip values in a vector to be within a range"},
+  {"select",	   vect_select,	     "selective vector assignment"},
+  {"vgrid",        vgrid,	     "get info from imreg database"},
+  {"vstat",        vstat,	     "get info from imreg database"},
+  {"vroll",        vroll,	     "roll vector elements"},
+  {"vpop",         vpop, 	     "remove first element"},
+  {"wd",      	   wd,		     "write an image to a file"},
+  {"write",   	   write_vectors,    "write vectors to datafile"},
+  {"zap",     	   zap,		     "delete pixels"},
+  {"zplot",   	   zplot,	     "plot x y with size scaled by z"},
+}; 
+
+void InitData () {
+  
+  int i;
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/integrate.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/integrate.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/integrate.c	(revision 12606)
@@ -0,0 +1,44 @@
+# include "data.h"
+
+int integrate (int argc, char **argv) {
+  
+  int i, N, VERBOSE;
+  float *X, *Y;
+  double start, end, value, range;
+  Vector *vecx, *vecy;
+
+  VERBOSE = FALSE;
+  if (N = get_argument (argc, argv, "-v")) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: integrate <x> <y> start end\n");
+    return (FALSE);
+  }
+
+  if ((vecx = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vecy = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  start = atof (argv[3]);
+  end   = atof (argv[4]);
+
+  X = vecx[0].elements;
+  Y = vecy[0].elements;
+
+  value = 0;
+  range = 0;
+  for (i = 0; i < vecx[0].Nelements-1; i++, X++, Y++) {
+    if ((*X >= start) && (*X <= end)) {
+      value += *Y * (X[1] - X[0]);
+      range += (X[1] - X[0]);
+    }
+  }      
+
+  set_variable ("sum", value); 
+  set_variable ("range", range);
+  if (VERBOSE) fprintf (GetOutfile(), "sum: %f\n", value);
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/interpolate.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/interpolate.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/interpolate.c	(revision 12606)
@@ -0,0 +1,53 @@
+# include "data.h"
+
+int interpolate (int argc, char **argv) {
+
+  int  i, j;
+  double x0, x1, dx, dy, y0;
+  Vector *xout, *yout, *xin, *yin;
+
+  /** check basic syntax **/
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: interpolate Xi Yi Xo Yo\n");
+    fprintf (stderr, "  Xi Yi - sorted reference vectors\n");
+    fprintf (stderr, "  Xo    - output positions\n");
+    fprintf (stderr, "  Yo    - output values\n");
+    return (FALSE);
+  }
+
+  if ((xin  = SelectVector (argv[1],  OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yin  = SelectVector (argv[2],  OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((xout = SelectVector (argv[3],  OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yout = SelectVector (argv[4],  ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  yout[0].Nelements = xout[0].Nelements;
+  REALLOCATE (yout[0].elements, float, yout[0].Nelements);
+
+  dx = xin[0].elements[1] - xin[0].elements[0];
+  dy = yin[0].elements[1] - yin[0].elements[0];
+  x0 = xin[0].elements[0];
+  y0 = yin[0].elements[0];
+  
+  /* in vectors are sorted, out vectors are not */
+  for (j = 0; j < xin[0].Nelements - 1; j++) {
+    dx = xin[0].elements[j+1] - xin[0].elements[j];
+    dy = yin[0].elements[j+1] - yin[0].elements[j];
+    x0 = xin[0].elements[j];
+    y0 = yin[0].elements[j];
+    x1 = xin[0].elements[j+1];
+    for (i = 0; i < xout[0].Nelements; i++) {
+      if ((xout[0].elements[i] >= x0) && (xout[0].elements[i] < x1)) {
+	yout[0].elements[i] = (dy/dx)*(xout[0].elements[i] - x0) + y0;
+      }
+      if ((j == 0) && (xout[0].elements[i] < x0)) {
+	yout[0].elements[i] = (dy/dx)*(xout[0].elements[i] - x0) + y0;
+      }
+      if ((j == xin[0].Nelements - 2) && (xout[0].elements[i] > x1)) {
+	yout[0].elements[i] = (dy/dx)*(xout[0].elements[i] - x0) + y0;
+      }
+    }    
+  }
+
+  return (TRUE);
+    
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/jpeg.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/jpeg.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/jpeg.c	(revision 12606)
@@ -0,0 +1,64 @@
+# include "data.h"
+
+int jpeg (int argc, char **argv) {
+
+  char filename[1024], buffer[20], type[16];
+  int N, Source, Nsource, IsImage;
+  
+  if (N = get_argument (argc, argv, "--help")) {
+    fprintf (stderr, "USAGE: jpeg [-name file] [-g | -i] [-n device] [-ppm]\n");
+    return (FALSE);
+  }
+
+  /* image type */
+  strcpy (type, "PNGF");
+  if (N = get_argument (argc, argv, "-ppm")) {
+    remove_argument (N, &argc, argv);
+    strcpy (type, "PPMF");
+  }
+
+  /* file name */
+  filename[0] = 0;
+  if (N = get_argument (argc, argv, "-name")) {
+    remove_argument (N, &argc, argv);
+    strcpy (filename, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* display source */
+  Nsource = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Nsource = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-g")) {
+    remove_argument (N, &argc, argv);
+    SetImageDevice (FALSE);
+  }  
+  if (N = get_argument (argc, argv, "-i")) {
+    remove_argument (N, &argc, argv);
+    SetImageDevice (TRUE);
+  }  
+  IsImage = GetCurrentDevice ();
+  if (IsImage) {
+    if (!GetImage (&Source, &Nsource)) return (FALSE);
+    if (!filename[0]) strcpy (filename, "Ximage.jpg");
+    strcpy (type, "JPEG");
+  } else {
+    if (!GetGraph (NULL, &Source, &Nsource)) return (FALSE);
+    if (!filename[0]) strcpy (filename, "Xgraph.png");
+  }
+
+  strcpy (buffer, type);
+  write (Source, buffer, 4);
+  sprintf (buffer, "LEN: %11d", strlen(filename));
+  write (Source, buffer, 16);
+  write (Source, filename, strlen(filename));
+  read (Source, buffer, 4);
+
+  return (TRUE);
+}
+
+/* jpeg -g converts graph to png
+   jpeg converts image to jpeg */
Index: /tags/start/Ohana/src/opihi/cmd.data/kern.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/kern.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/kern.c	(revision 12606)
@@ -0,0 +1,101 @@
+# include "data.h"
+
+int kern (int argc, char **argv) {
+
+  int i, n, m;
+  int NX, NY, status;
+  FILE *f;
+  float *in_buff, *out_buff, *ib, *ob;
+  char line[256], *list;
+  double kernel[3][3], val;
+  Buffer *buf;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: kern buffer (file)\n");
+    fprintf (stderr, "USAGE: kern buffer (list)\n");
+    fprintf (stderr, "USAGE: kern buffer -\n");
+    fprintf (stderr, "kernel file contains a 3x3 matrix for convolution\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  /* open file to read in kernel */
+  if (!strcmp (argv[2], "-")) {
+    for (i = 0; i < 3; i++) {
+      status = scan_line (stdin, line);
+      if (status == EOF) {
+	fprintf (stderr, "kernel should be a 3x3 matrix...\n");
+	return (FALSE);
+      }
+      dparse (&kernel[0][i], 1, line);
+      dparse (&kernel[1][i], 2, line);
+      dparse (&kernel[2][i], 3, line);
+    }
+    goto have_kernel;
+  }
+  /* test list */
+  sprintf (line, "%s:n", argv[2]);
+  if ((list = get_variable (line)) == (char *) NULL) {
+    /* file */
+    f = fopen (argv[2], "r");
+    for (i = 0; i < 3; i++) {
+      status = scan_line (f, line);
+      if (status == EOF) {
+	fprintf (stderr, "kernel should be a 3x3 matrix...\n");
+	fclose (f);
+      }
+      return (FALSE);
+      dparse (&kernel[0][i], 1, line);
+      dparse (&kernel[1][i], 2, line);
+      dparse (&kernel[2][i], 3, line);
+    }
+    fclose (f);
+    goto have_kernel;
+  }
+  if (atoi (list) != 9) {
+    fprintf (stderr, "kernel should be a 3x3 matrix...\n");
+    return (FALSE);
+  }
+  free (list);
+  for (i = 0; i < 9; i++) {
+    sprintf (line, "%s:%d", argv[2], i);
+    list = get_variable (line);
+    if (list == (char *) NULL) {
+      fprintf (stderr, "kernel should be a 3x3 matrix...\n");
+      return (FALSE);
+    }
+    kernel[(int)(i/3)][i%3] = atof (list);
+    free (list);
+  }
+  goto have_kernel;
+
+ have_kernel:
+  fprintf (stderr, "working...");
+  
+  /* create output buffer */
+  NX = buf[0].header.Naxis[0];
+  NY = buf[0].header.Naxis[1];
+  in_buff = (float *)buf[0].matrix.buffer;
+  ALLOCATE (buf[0].matrix.buffer, char, sizeof(float)*NX*NY);
+  out_buff = (float *)buf[0].matrix.buffer;
+  
+  /* do the convolution (on all but outer rows) */
+  
+  for (n = 0; n < 3; n++) {
+    for (m = 0; m < 3; m++) {
+      fprintf (stderr, "%d", n*3 + m + 1);
+      val = kernel[n][m];
+      ob = out_buff + NX + 1;
+      ib = in_buff + m*NX + n;
+      for (i = 0; i < (NX-2)*(NY-2); i++, ob++, ib++) {
+	*ob += *ib*val;
+      }
+    }
+  }
+  fprintf (stderr, "(done)\n");
+
+  free (in_buff);
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/keyword.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/keyword.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/keyword.c	(revision 12606)
@@ -0,0 +1,158 @@
+# include "data.h"
+
+enum {NONE, STRING, FLOAT, INT, BOOLEAN, KEYCOMMENT, COMMENT};
+
+/** WARNING: no error checking on variable validity **/
+int keyword (int argc, char **argv) {
+
+  int ivalue, status, N, ascomment, asfloat, delete, soft, Wmode;
+  char line[80];
+  double value;
+  Buffer *buf;
+
+  asfloat = FALSE;
+  if (N = get_argument (argc, argv, "-f")) {
+    remove_argument (N, &argc, argv);
+    asfloat = TRUE;
+  }
+  
+  ascomment = FALSE;
+  if (N = get_argument (argc, argv, "-c")) {
+    remove_argument (N, &argc, argv);
+    ascomment = TRUE;
+  }
+  
+  delete = FALSE;
+  if (N = get_argument (argc, argv, "-d")) {
+    remove_argument (N, &argc, argv);
+    delete = TRUE;
+  }
+  
+  /* return TRUE for missing keyword if soft */
+  soft = FALSE;
+  if (N = get_argument (argc, argv, "-soft")) {
+    remove_argument (N, &argc, argv);
+    soft = TRUE;
+  }
+  
+  /* identify write modes */
+  Wmode = NONE;
+  if (N = get_argument (argc, argv, "-w")) {
+    remove_argument (N, &argc, argv);
+    strcpy (line, argv[N]);
+    remove_argument (N, &argc, argv);
+    Wmode = STRING;
+  }
+  if (N = get_argument (argc, argv, "-wf")) {
+    remove_argument (N, &argc, argv);
+    strcpy (line, argv[N]);
+    remove_argument (N, &argc, argv);
+    Wmode = FLOAT;
+  }
+  if (N = get_argument (argc, argv, "-wd")) {
+    remove_argument (N, &argc, argv);
+    strcpy (line, argv[N]);
+    remove_argument (N, &argc, argv);
+    Wmode = INT;
+  }
+  if (N = get_argument (argc, argv, "-wc")) {
+    remove_argument (N, &argc, argv);
+    strcpy (line, argv[N]);
+    remove_argument (N, &argc, argv);
+    Wmode = KEYCOMMENT;
+  }
+  if (N = get_argument (argc, argv, "-ws")) {
+    remove_argument (N, &argc, argv);
+    strcpy (line, argv[N]);
+    remove_argument (N, &argc, argv);
+    Wmode = COMMENT;
+  }
+  if (N = get_argument (argc, argv, "-wb")) {
+    remove_argument (N, &argc, argv);
+    strcpy (line, argv[N]);
+    remove_argument (N, &argc, argv);
+    Wmode = BOOLEAN;
+  }
+
+  if (!((argc == 3) || (!N && argc == 4))) {
+    fprintf (stderr, "USAGE: keyword <buffer> (KEYWORD) [variable] [-d] [-w(mode) value]\n");
+    fprintf (stderr, " -w modes: \n");
+    fprintf (stderr, "  -w  - string\n");
+    fprintf (stderr, "  -wf - float\n");
+    fprintf (stderr, "  -wd - int\n");
+    fprintf (stderr, "  -wb - boolean\n");
+    fprintf (stderr, "  -wc - comment\n");
+    fprintf (stderr, "  -ws - full string comment\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  if (Wmode != NONE) {
+    switch (Wmode) {
+    case STRING:
+      fits_modify (&buf[0].header, argv[2], "%s", 1, line);
+      return (TRUE);
+    case FLOAT:
+      value = atof(line);
+      fits_modify (&buf[0].header, argv[2], "%lf", 1, value);
+      return (TRUE);
+    case INT:
+      fits_modify (&buf[0].header, argv[2], "%d", 1, atoi(line));
+      return (TRUE);
+    case BOOLEAN:
+      if (strcasecmp (line, "T") && strcasecmp (line, "TRUE") && strcasecmp (line, "F") && strcasecmp (line, "FALSE")) {
+	fprintf (stderr, "syntax error in boolean value\n");
+	return (FALSE);
+      }
+      ivalue = !strcasecmp (line, "T");
+      fits_modify (&buf[0].header, argv[2], "%t", 1, ivalue);
+      return (TRUE);
+    case KEYCOMMENT:
+      fits_modify (&buf[0].header, argv[2], "%C", 1, line);
+      return (TRUE);
+    case COMMENT:
+      fits_modify (&buf[0].header, argv[2], "%S", 0, line);
+      return (TRUE);
+    }
+  }
+  
+  if (delete) {
+    fits_delete (&buf[0].header, argv[2], -1);
+    return (TRUE);
+  }
+  
+  /* grab the value in the given format, either a string or a digit */
+  if (asfloat) {
+    status = fits_scan (&buf[0].header, argv[2], "%lf", 1, &value);
+    if (!status) goto failure;
+    if (argc == 4) 
+      set_variable (argv[3], value);
+    else 
+      fprintf (GetOutfile(), "%s: %f\n", argv[2], value);
+    return (TRUE);
+  } 
+
+  if (ascomment) {
+    status = fits_scan (&buf[0].header, argv[2], "%C", 1, line);
+    if (!status) goto failure;
+    if (argc == 4) 
+      set_str_variable (argv[3], line);
+    else 
+      fprintf (GetOutfile(), "%s: %s\n", argv[2], line);
+    return (TRUE);
+  }    
+
+  /* not-specified */
+  status = fits_scan (&buf[0].header, argv[2], "%s", 1, line);
+  if (!status) goto failure;
+  if (argc == 4) 
+    set_str_variable (argv[3], line);
+  else 
+    fprintf (GetOutfile(), "%s: %s\n", argv[2], line);
+  return (TRUE);
+
+ failure: 
+  if (!soft) fprintf (stderr, "keyword %s not found\n", argv[2]);
+  return (soft);
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/labels.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/labels.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/labels.c	(revision 12606)
@@ -0,0 +1,99 @@
+# include "data.h"
+
+int labels (int argc, char **argv) {
+  
+  char name[64], buffer[32];
+  int N, size, Xgraph;
+
+  if (!GetGraph (NULL, &Xgraph, NULL)) return (FALSE);
+
+  if (get_argument (argc, argv, "-h")) {
+    fprintf (stderr, "label options: \n");
+    fprintf (stderr, " -x : bottom-center\n");
+    fprintf (stderr, " +x : top-center\n");
+    fprintf (stderr, " -y : right-side\n");
+    fprintf (stderr, " +y : left-side\n\n");
+
+    fprintf (stderr, " -ul : upper-left corner\n");
+    fprintf (stderr, " -ll : lower-left corner\n");
+    fprintf (stderr, " -ur : upper-right corner\n");
+    fprintf (stderr, " -lr : lower-right corner\n\n");
+
+    fprintf (stderr, " -fn (font) (size) : set font and size\n");
+    fprintf (stderr, "   (font) : courier, helvetica, times, symbol\n\n");
+    fprintf (stderr, " label special characters:\n");
+    fprintf (stderr, " ^ : superscript\n");
+    fprintf (stderr, " _ : subscript\n");
+    fprintf (stderr, " | : default script \n");
+    fprintf (stderr, " &c, &h, &t, &s : set font\n\n");
+    return (FALSE);
+  }
+
+  if (N = get_argument (argc, argv, "-fn")) {
+    remove_argument (N, &argc, argv);
+    strcpy (name, argv[N]);
+    remove_argument (N, &argc, argv);
+    size = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    write (Xgraph, "FONT", 4);
+    sprintf (buffer, "%s", name);
+    write (Xgraph, buffer, 16);
+    sprintf (buffer, "%d", size);
+    write (Xgraph, buffer, 16);
+  } 
+
+  if (N = get_argument (argc, argv, "-x")) {
+    remove_argument (N, &argc, argv);
+    SendLabel (argv[N], Xgraph, 0);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (N = get_argument (argc, argv, "-y")) {
+    remove_argument (N, &argc, argv);
+    SendLabel (argv[N], Xgraph, 1);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (N = get_argument (argc, argv, "+x")) {
+    remove_argument (N, &argc, argv);
+    SendLabel (argv[N], Xgraph, 2);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (N = get_argument (argc, argv, "+y")) {
+    remove_argument (N, &argc, argv);
+    SendLabel (argv[N], Xgraph, 3);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (N = get_argument (argc, argv, "-ul")) {
+    remove_argument (N, &argc, argv);
+    SendLabel (argv[N], Xgraph, 4);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (N = get_argument (argc, argv, "-ur")) {
+    remove_argument (N, &argc, argv);
+    SendLabel (argv[N], Xgraph, 5);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (N = get_argument (argc, argv, "-ll")) {
+    remove_argument (N, &argc, argv);
+    SendLabel (argv[N], Xgraph, 6);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (N = get_argument (argc, argv, "-lr")) {
+    remove_argument (N, &argc, argv);
+    SendLabel (argv[N], Xgraph, 7);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: labels [-x] [-y] [+x] [+y] [-ul] [-ur] [-ll] [-lr]\n");
+    return (FALSE);
+  }
+
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/limits.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/limits.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/limits.c	(revision 12606)
@@ -0,0 +1,76 @@
+# include "data.h"
+
+int limits (int argc, char **argv) {
+
+  int N, APPLY;
+  int Ngraph, Xgraph;
+  Graphdata graphmode;
+  Vector *xvec, *yvec;
+
+  xvec = yvec = NULL;
+
+  APPLY = FALSE;
+  if (N = get_argument (argc, argv, "-a")) {
+    remove_argument (N, &argc, argv);
+    APPLY = TRUE;
+  }
+
+  Ngraph = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Ngraph = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraph (&graphmode, &Xgraph, &Ngraph)) return (FALSE);
+
+  if (argc == 1) {
+    fprintf (stderr, "limits: %f %f %f %f [-a] [-n Xgraph]\n",
+	     graphmode.xmin, graphmode.xmax,
+	     graphmode.ymin, graphmode.ymax);
+    goto success;
+  }
+
+  if (argc == 3) { /* expect to see: limits x y */
+    if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+    if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+    goto success;
+  }
+    
+  if (argc == 4) { /* expect to see: limits x num num or limits num num y */
+    if (ISNUM(argv[1][0]) && ISNUM(argv[2][0])) {
+      if ((yvec = SelectVector (argv[3], OLDVECTOR, FALSE)) == NULL) goto error;
+      graphmode.xmin = atof (argv[1]);
+      graphmode.xmax = atof (argv[2]);
+      goto success;
+    }
+    if (ISNUM(argv[2][0]) && ISNUM(argv[3][0])) {
+      if ((xvec = SelectVector (argv[1], OLDVECTOR, FALSE)) == NULL) goto error;
+      graphmode.ymin = atof (argv[2]);
+      graphmode.ymax = atof (argv[3]);
+      goto success;
+    }
+    goto error;
+  }
+  
+  if (argc == 5) {
+    graphmode.xmin = atof (argv[1]);
+    graphmode.xmax = atof (argv[2]);
+    graphmode.ymin = atof (argv[3]);
+    graphmode.ymax = atof (argv[4]);
+    goto success;
+  }
+
+  fprintf (stderr, "USAGE: limits [xrange] [yrange]\n");
+  fprintf (stderr, " [range] may be either [min max] or a vector\n");
+  return (FALSE);
+
+ error:
+  fprintf (stderr, "error in vectors\n");
+  return (FALSE);
+
+ success:
+  SetLimits (xvec, yvec, &graphmode);
+  ApplyLimits (Xgraph, &graphmode, APPLY);
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/line.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/line.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/line.c	(revision 12606)
@@ -0,0 +1,125 @@
+# include "data.h"
+
+int line (int argc, char **argv) {
+  
+  int N, Npts, Ngraph;
+  Graphdata graphmode;
+  Vector *vecx, *vecy, *dxm, *dxp, *dym, *dyp;
+
+  /* choose the appropriate graphing window */
+  Ngraph = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Ngraph = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);
+
+  /* evaluate various plotting options */
+  if (N = get_argument (argc, argv, "-lt")) {
+    remove_argument (N, &argc, argv);
+    graphmode.ltype = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-lw")) {
+    remove_argument (N, &argc, argv);
+    graphmode.lweight = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-pt")) {
+    remove_argument (N, &argc, argv);
+    graphmode.ptype = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "+eb")) {
+    remove_argument (N, &argc, argv);
+    graphmode.ebar = TRUE;
+  }
+  if (N = get_argument (argc, argv, "-eb")) {
+    remove_argument (N, &argc, argv);
+    graphmode.ebar = FALSE;
+  }
+  if (N = get_argument (argc, argv, "-sz")) {
+    remove_argument (N, &argc, argv);
+    graphmode.size = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-c")) {
+    remove_argument (N, &argc, argv);
+    graphmode.color = GetColor (argv[N]);
+    if (graphmode.color == -1) return (FALSE);
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-x")) {
+    remove_argument (N, &argc, argv);
+    graphmode.style = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* decide on error bars */
+  dxm = dxp = dym = dyp = NULL;
+  if (N = get_argument (argc, argv, "-dx")) {
+    remove_argument (N, &argc, argv);
+    if ((dxm = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "+dx")) {
+    remove_argument (N, &argc, argv);
+    if ((dxp = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-dy")) {
+    remove_argument (N, &argc, argv);
+    if ((dym = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "+dy")) {
+    remove_argument (N, &argc, argv);
+    if ((dyp = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: plot <x> <y>\n");
+    return (FALSE);
+  }
+
+  /* set plotting options (these are sticky) */
+  SetGraph (graphmode);
+
+  /* set errorbar mode (these are NOT sticky) */
+  graphmode.etype = 0;
+  if ((dym != NULL) && (dyp == NULL)) dyp = dym;
+  if ((dyp != NULL) && (dym == NULL)) dym = dyp;
+  if ((dyp != NULL) || (dym != NULL)) graphmode.etype |= 0x01;
+  if ((dxm != NULL) && (dxp == NULL)) dxp = dxm;
+  if ((dxp != NULL) && (dxm == NULL)) dxm = dxp;
+  if ((dxp != NULL) || (dxm != NULL)) graphmode.etype |= 0x02;
+  
+  /* find vectors */
+  if ((vecx = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vecy = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if (vecy[0].Nelements != vecy[0].Nelements) {
+    fprintf (stderr, "vectors %s and %s not the same length\n", argv[1], argv[2]);
+    return (FALSE);
+  }
+  
+  Npts = vecx[0].Nelements;
+  if (!PrepPlotting (Npts, &graphmode)) return (FALSE);
+  
+  PlotVector (Npts, vecx[0].elements);
+  PlotVector (Npts, vecy[0].elements);
+  if (graphmode.etype & 0x01) {
+    PlotVector (Npts, dym[0].elements);
+    PlotVector (Npts, dyp[0].elements);
+  }
+  if (graphmode.etype & 0x02) {
+    PlotVector (Npts, dxm[0].elements);
+    PlotVector (Npts, dxp[0].elements);
+  }
+  
+  return (TRUE);
+
+}
+
+
Index: /tags/start/Ohana/src/opihi/cmd.data/list_buffers.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/list_buffers.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/list_buffers.c	(revision 12606)
@@ -0,0 +1,10 @@
+# include "data.h"
+
+int list_buffers (int argc, char **argv) {
+
+  if (argc == 3) PrintBuffers (TRUE);
+  else PrintBuffers (FALSE);
+
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/list_header.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/list_header.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/list_header.c	(revision 12606)
@@ -0,0 +1,79 @@
+# include "data.h"
+
+int header (int argc, char **argv) {
+  
+  int j, N, nlines, nbytes, Nbytes, LOADHEAD, status, bitpix, unsign;
+  char *p, filename[128];
+  FILE *f;
+  double bscale, bzero;
+  Buffer *buf;
+
+  LOADHEAD = FALSE;
+  if (N = get_argument (argc, argv, "-w")) {
+    remove_argument (N, &argc, argv);
+    strcpy (filename, argv[N]);
+    remove_argument (N, &argc, argv);
+    LOADHEAD = TRUE;
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: header <buffer> [-w filename]\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  if (LOADHEAD) {
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "file %s not found\n", filename);
+      return (FALSE);
+    }
+    fclose (f);
+    
+    bitpix = buf[0].header.bitpix;
+    bzero  = buf[0].header.bzero;
+    bscale = buf[0].header.bscale;
+    unsign = buf[0].header.unsign;
+    fits_free_header (&buf[0].header);
+    
+    strcpy (filename, buf[0].file);
+    strcpy (buf[0].file, "*");
+    strcat (buf[0].file, filename);
+    status = fits_read_header (argv[2], &buf[0].header);
+    buf[0].header.bitpix = bitpix;     
+    buf[0].header.bzero  = bzero;      
+    buf[0].header.bscale = bscale;     
+    buf[0].header.unsign = unsign;     
+    fits_modify (&buf[0].header, "BITPIX", "%d",  1, bitpix);
+    fits_modify (&buf[0].header, "BSCALE", "%lf", 1, bscale);
+    fits_modify (&buf[0].header, "BZERO",  "%lf", 1, bzero);
+    fits_modify (&buf[0].header, "UNSIGN", "%t",  1, unsign);
+    
+  } else {
+
+    f = popen ("more", "w");
+    
+    p = fits_header_field (&buf[0].header, "END", 1);
+    nlines = (p - buf[0].header.buffer) / 80;
+    nbytes = 81*nlines;
+
+    /* duplicate the header, add in the <return> chars, send to more */
+    ALLOCATE (p, char, nbytes);
+    for (j = 0; j < nlines; j++) {
+      memcpy (&p[81*j], &buf[0].header.buffer[80*j], 80);
+      p[81*j+80] = 10;
+    }
+    Nbytes = fwrite (p, sizeof(char), nbytes, f);
+    if (Nbytes != nbytes) {
+      fprintf (stderr, "warning: not all printed...\n");
+    }
+    free (p);
+
+    pclose (f);
+
+  }
+
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/list_vectors.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/list_vectors.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/list_vectors.c	(revision 12606)
@@ -0,0 +1,8 @@
+# include "data.h"
+
+int list_vectors (int argc, char **argv) {
+
+  ListVectors ();
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/load.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/load.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/load.c	(revision 12606)
@@ -0,0 +1,147 @@
+# include "data.h"
+
+int load (int argc, char **argv) {
+  
+  int N, n, Nline, ISCEL;
+  int Ximage, Nimage;
+  char *c, type[10], string[128];
+  double x, y, dx, dy, x1, y1;
+  double dra, ddec, ra1, dec1, ra, dec;
+  FILE *f;
+  char *buffer, *line;
+  Coords coords;
+  Buffer *buf;
+  
+  Nimage = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Nimage = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (&Ximage, &Nimage)) return (FALSE);
+
+  ISCEL = FALSE;
+  if (N = get_argument (argc, argv, "-c")) {
+    remove_argument (N, &argc, argv);
+    ISCEL = TRUE;
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: load (overlay) <filename>\n [-c] [-n]");
+    fprintf (stderr, "  -c: read overlay in celestial coords\n");
+    return (FALSE);
+  }
+  
+  if (!SelectOverlay (argv[1], &n)) return (FALSE);
+
+  if (!strcmp (argv[2], "-")) {
+    f = stdin;
+  } else {
+    f = fopen (argv[2], "r");
+  }
+  if (f == NULL) {
+    fprintf (stderr, "can't find file %s\n", argv[2]);
+    return (FALSE);
+  }
+
+  if (ISCEL) {
+    if ((buf = SelectBuffer (GetImageName(), OLDBUFFER, TRUE)) == NULL) return (FALSE);
+    GetCoords (&coords, &buf[0].header);
+  }
+
+  ALLOCATE (buffer, char, 65536);  /* space for 512 lines of 128 bytes */
+  bzero (buffer, 65536);
+  ALLOCATE (line, char, 1024);     /* space to read the file */
+  Nline = 0;
+
+  write (Ximage, "LOAD", 4); /* force Ximage to look for the incoming image */
+  sprintf (line, "OVER %9d ", n);
+  write (Ximage, line, 16);
+  
+  for (n = 0; scan_line (f, line) != EOF;) {
+    c = strchr (line, '#');
+    if (c != (char *) NULL) 
+      *c = 0;  /* force end of line at comment! */
+    while ((c = strchr (line, '(')) != (char *) NULL) 
+      *c = ' ';
+    while ((c = strchr (line, ')')) != (char *) NULL) 
+      *c = ' ';
+    while ((c = strchr (line, ',')) != (char *) NULL) 
+      *c = ' ';
+    /* we could use some syntactial checks here */
+    /* have to get all three for this to be any valid object, if the line is commented out,
+     we should get none, so check that N == 3 before continuing: */
+    N = sscanf (line, "%s %lf %lf %lf %lf", type, &ra, &dec, &dra, &ddec);
+    switch (N) {
+    case 0:
+    case -1:
+      continue;
+    case 1:
+    case 2:
+    case 3:
+      if (strcmp (type, "TEXT")) {
+	fprintf (stderr, "syntactical error in line:\n   %s\n", line);
+	continue;
+      }
+      sscanf (line, "%s %lf %lf %127s", type, &ra, &dec, string);
+    case 4:
+      ddec = dra;
+    case 5:
+      if (ISCEL) {
+	if (!strcmp (type, "LINE")) {
+	  RD_to_XY (&x, &y, ra, dec, &coords);
+	  ra1 = ra + dra;
+	  dec1 = dec + ddec;
+	  RD_to_XY (&x1, &y1, ra1, dec1, &coords);
+	  dy = (y1 - y);
+	  dx = (x1 - x);
+	} else {
+	  RD_to_XY (&x, &y, ra, dec, &coords);
+	  ra1 = ra;
+	  dec1 = dec + ddec;
+	  RD_to_XY (&x1, &y1, ra1, dec1, &coords);
+	  dy = (fabs(x1 - x) + fabs(y1 - y));
+	  ra1 = ra + dra/cos(dec*RAD_DEG);;
+	  dec1 = dec;
+	  RD_to_XY (&x1, &y1, ra1, dec1, &coords);
+	  dx = (fabs(x1 - x) + fabs(y1 - y));
+	}
+      }
+      else {
+	x = ra;
+	y = dec;
+	dx = dra;
+	dy = ddec;
+      }
+    }
+    if (!strcmp (type, "TEXT")) {
+      snprintf (&buffer[Nline*128], 128, "%15s %20.10f %20.10f %s ", type, x, y, string);
+    } else {
+      snprintf (&buffer[Nline*128], 128, "%15s %20.10f %20.10f %20.10f %20.10f ", type, x, y, dx, dy);
+    }
+    n++;
+    Nline ++;
+    if (Nline == 512) {
+      sprintf (line, "NLINES  %7d ", Nline);
+      write (Ximage, line, 16);
+      write (Ximage, buffer, Nline*128);
+      bzero (buffer, 65536);
+      Nline = 0;
+    }
+  }
+
+  sprintf (line, "NLINES  %7d ", Nline);
+  write (Ximage, line, 16);
+  write (Ximage, buffer, Nline*128);
+  sprintf (line, "DONE ");
+  write (Ximage, line, 16);
+
+  free (buffer);
+  free (line);
+  fprintf (stderr, "loaded %d objects\n", n);
+  if (f != stdin) {
+    fclose (f);
+  }
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/mcreate.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/mcreate.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/mcreate.c	(revision 12606)
@@ -0,0 +1,36 @@
+# include "data.h"
+
+int mcreate (int argc, char **argv) {
+  
+  int Nx, Ny;
+  Buffer *buf;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: mcreate <buffer> Nx Ny\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  Nx = atof (argv[2]);
+  Ny = atof (argv[3]);
+
+  buf[0].matrix.Naxis[0] = Nx;
+  buf[0].matrix.Naxis[1] = Ny;
+
+  /* I should encapsulate this in a create_default_buffer */
+  fits_free_matrix (&buf[0].matrix);
+  fits_free_header (&buf[0].header);
+  buf[0].header.bitpix = buf[0].bitpix = -32;
+  buf[0].header.unsign = buf[0].unsign = FALSE;
+  buf[0].header.bscale = buf[0].bscale = 1.0;
+  buf[0].header.bzero  = buf[0].bzero  = 0.0;
+  buf[0].header.Naxes = 2;
+  buf[0].header.Naxis[0] = Nx;
+  buf[0].header.Naxis[1] = Ny;
+  fits_create_header (&buf[0].header);
+  fits_create_matrix (&buf[0].header, &buf[0].matrix);
+  return (TRUE);
+
+}
+
+
Index: /tags/start/Ohana/src/opihi/cmd.data/medacc.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/medacc.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/medacc.c	(revision 12606)
@@ -0,0 +1,83 @@
+# include "data.h"
+
+int medacc (int argc, char **argv) {
+  
+  int i, j, Nbins, Nvalues, N, N0, N1;
+  double start, end, delta, k0, k1, fn;
+  float *V, *K, *V1, *K1, *O, *tmpvec, *tmpkey;
+  Vector *val, *key, *out;
+
+  if ((argc != 6) && (argc != 7)) {
+    fprintf (stderr, "USAGE: medacc <value> <vector> <key> start end [delta]\n");
+    return (FALSE);
+  }
+
+  if ((val = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((key = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if (val[0].Nelements != key[0].Nelements) {
+    fprintf (stderr, "key and value don't match\n");
+    return (FALSE);
+  }
+  if ((out = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  start = atof (argv[4]);
+  end   = atof (argv[5]);
+  if (argc == 7) 
+    delta = atof (argv[6]);
+  else 
+    delta = 1;
+
+  delta = fabs (delta);
+  if (end - start < 0) {
+    delta = -1.0 * delta;
+  }
+  Nbins = 1 + (int)((end - start) / delta);
+
+  out[0].Nelements = Nbins;
+  REALLOCATE (out[0].elements, float, out[0].Nelements);
+  bzero (out[0].elements, sizeof(float)*out[0].Nelements);
+
+  /* copy vec and key to temp vectors */
+  ALLOCATE (tmpvec, float, val[0].Nelements);
+  ALLOCATE (tmpkey, float, val[0].Nelements);
+
+  V = val[0].elements;
+  K = key[0].elements;
+  V1 = tmpvec;
+  K1 = tmpkey;
+  Nvalues = val[0].Nelements;
+  for (i = 0; i < Nvalues; i++, V++, K++, V1++, K1++) {
+    *V1 = *V;
+    *K1 = *K;
+  }      
+
+  /* sort vec and key by key */
+  fsortpair (tmpkey, tmpvec, Nvalues);
+
+  O = out[0].elements;
+  /* find the start and end key for each range */
+  N0 = 0;
+  N1 = 0;
+  for (i = 0; i < Nbins; i++) {
+    k0 = i*delta + start;
+    k1 = (i+1)*delta + start;
+    for (j = N1; (j < Nvalues) && (tmpkey[j] < k0); j++);
+    N0 = j;
+    for (j = N0; (j < Nvalues) && (tmpkey[j] < k1); j++);
+    N1 = j;
+    N = N1 - N0;
+    fsort (&tmpvec[N0], N);
+    fn = O[i] = 0;
+    for (j = N0 + 0.25*N; j < N0 + 0.75*N; j++) {
+      O[i] += tmpvec[j];
+      fn += 1.0;
+    }
+    if (fn > 0) O[i] /= fn;
+  }      
+  
+  free (tmpvec);
+  free (tmpkey);
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/mget.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/mget.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/mget.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include "data.h"
+
+int mget (int argc, char **argv) {
+  
+  int i, Nx, Ny, Npix, xdir, Nset;
+  float *in, *out;
+  Buffer *buf;
+  Vector *vec;
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: mget <buffer> <vector> <-x/-y> <N>\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((vec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (strcasecmp (argv[3], "-x") && strcasecmp (argv[3], "-y")) {
+    fprintf (stderr, "USAGE: mget <buffer> <vector> <-x/-y> <N>\n");
+    return (FALSE);
+  }
+  xdir = TRUE;
+  if (!strcasecmp (argv[3], "-y")) xdir = FALSE;
+
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+  Nset = atof (argv[4]);
+  if (Nset < 0) {
+    fprintf (stderr, "selection out of range\n");
+    return (FALSE);
+  }
+
+  if (xdir) {
+    vec[0].Nelements = Npix = Nx;
+    REALLOCATE (vec[0].elements, float, Npix);
+    if (Nset >= Ny) {
+      fprintf (stderr, "row out of range\n");
+      return (FALSE);
+    }
+    in  = (float *) buf[0].matrix.buffer + Nx*Nset;
+    out = vec[0].elements;
+    for (i = 0; i < Npix; i++, in++, out++) {
+      *out = *in;
+    }
+    return (TRUE);
+  } else {
+    vec[0].Nelements = Npix = Ny;
+    REALLOCATE (vec[0].elements, float, Npix);
+    if (Nset >= Nx) {
+      fprintf (stderr, "column out of range\n");
+      return (FALSE);
+    }
+    in  = (float *) buf[0].matrix.buffer + Nset;
+    out = vec[0].elements;
+    for (i = 0; i < Npix; i++, in+=Nx, out++) {
+      *out = *in;
+    }
+    return (TRUE);
+  }    
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/minterpolate.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/minterpolate.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/minterpolate.c	(revision 12606)
@@ -0,0 +1,115 @@
+# include "data.h"
+
+int minterp (int argc, char **argv) {
+  
+  int i, j, status, nx, ny, Nx, Ny;
+  char temp[1024];
+  double scale, scale2, dX, dY;
+  float *V00, *V01, *V10, *V11, *Vout, dV1, dV2, dV3;
+  Buffer *in, *out;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: minterpolate <from> <to> scale \n");
+    return (FALSE);
+  }
+
+  if ((in  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out = SelectBuffer (argv[2], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  fits_free_matrix (&out[0].matrix);
+  fits_free_header (&out[0].header);
+
+  scale  = atof (argv[3]);
+  scale2 = scale*scale;
+  Nx = in[0].header.Naxis[0];
+  Ny = in[0].header.Naxis[1];
+  nx = Nx * scale;
+  ny = Ny * scale;
+
+  /* create new matrix */
+  out[0].bitpix = in[0].bitpix;
+  out[0].unsign = in[0].unsign;
+  out[0].bscale = in[0].bscale;
+  out[0].bzero  = in[0].bzero;
+  fits_copy_header (&in[0].header, &out[0].header);
+
+  fits_modify (&out[0].header, "NAXIS1", "%d", 1, nx);
+  fits_modify (&out[0].header, "NAXIS2", "%d", 1, ny);
+  out[0].header.Naxis[0] = nx;
+  out[0].header.Naxis[1] = ny;
+  fits_create_matrix (&out[0].header, &out[0].matrix);
+
+  /* fix astrometric terms */
+  status =  fits_scan (&out[0].header, "CDELT1", "%lf", 1, &dX);
+  status &= fits_scan (&out[0].header, "CDELT2", "%lf", 1, &dY);
+  dX /= scale;
+  dY /= scale;
+  if (status) {
+    fits_modify (&out[0].header, "CDELT1", "%lf", 1, dX);
+    fits_modify (&out[0].header, "CDELT2", "%lf", 1, dY);
+  }
+  status =  fits_scan (&out[0].header, "CRPIX1", "%lf", 1, &dX);
+  status &= fits_scan (&out[0].header, "CRPIX2", "%lf", 1, &dY);
+  dX *= scale;
+  dY *= scale;
+  if (status) {
+    fits_modify (&out[0].header, "CRPIX1", "%lf", 1, dX);
+    fits_modify (&out[0].header, "CRPIX2", "%lf", 1, dY);
+  }
+
+  /* adjust filename */
+  temp[0] = 0;
+  if ((in[0].file[0] != '*') && (in[0].file[0] != '(')) {
+    strcpy (temp, "*");
+  }
+  strcat (temp, in[0].file);
+  strcpy (out[0].file, temp);
+
+  dX = dY = scale;
+
+  {
+
+    int dx, dy, Npix;
+    float I, J, x, y, xs, xe, ys, ye;
+
+    Npix = 0;
+    for (j = 0; j < Ny - 1; j++) {
+      for (i = 0; i < Nx - 1; i++) {
+	V00 = (float *)(in[0].matrix.buffer) + j*Nx + i;
+	V10 = V00 + 1;
+	V01 = V00 + Nx;
+	V11 = V01 + 1;
+	dV1 = (*V11 + *V00 - *V01 - *V10) / scale2;
+	dV2 = (*V01 - *V00) / scale;
+	dV3 = (*V10 - *V00) / scale;
+
+	x = (i + 0.5) * scale;
+	y = (j + 0.5) * scale;
+
+	xs = 0;
+	if (i == 0) { xs = -0.5*scale; }
+	xe = scale;
+	if (i == Nx - 2) { xe = 1.5*scale; }
+
+	ys = 0;
+	if (j == 0) { ys = -0.5*scale; }
+	ye = scale;
+	if (j == Ny - 2) { ye = 1.5*scale; }
+
+	for (J = ys; J < ye; J += 1.0) {
+	  dx = (x + xs);
+	  dy = (y + J);
+	  Vout = (float *)(out[0].matrix.buffer) + dy*nx + dx;
+	  for (I = xs; I < xe; I += 1.0, Vout++) {
+	    *Vout = dV1 * (I*J) + dV2 * J + dV3 * I + *V00;
+	    Npix ++;
+	  }
+	}
+      }
+    }
+  }
+
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/mset.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/mset.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/mset.c	(revision 12606)
@@ -0,0 +1,66 @@
+# include "data.h"
+
+int mset (int argc, char **argv) {
+  
+  int i, Nx, Ny, Npix, xdir, Nset;
+  float *in, *out;
+  Buffer *buf;
+  Vector *vec;
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: mset <buffer> <vector> <-x/-y> <N>\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((vec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (strcasecmp (argv[3], "-x") && strcasecmp (argv[3], "-y")) {
+    fprintf (stderr, "USAGE: mset <buffer> <vector> <-x/-y> <N>\n");
+    return (FALSE);
+  }
+  xdir = TRUE;
+  if (!strcasecmp (argv[3], "-y")) xdir = FALSE;
+
+  Npix = vec[0].Nelements;
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+  Nset = atof (argv[4]);
+  if (Nset < 0) {
+    fprintf (stderr, "selection out of range\n");
+    return (FALSE);
+  }
+
+  if (xdir) {
+    if (Nx != Npix) {
+      fprintf (stderr, "dimensions don't match\n");
+      return (FALSE);
+    }
+    if (Nset >= Ny) {
+      fprintf (stderr, "row out of range\n");
+      return (FALSE);
+    }
+    out = (float *) buf[0].matrix.buffer + Nx*Nset;
+    in = vec[0].elements;
+    for (i = 0; i < Npix; i++, in++, out++) {
+      *out = *in;
+    }
+    return (TRUE);
+  } else {
+    if (Ny != Npix) {
+      fprintf (stderr, "dimensions don't match\n");
+      return (FALSE);
+    }
+    if (Nset >= Nx) {
+      fprintf (stderr, "column out of range\n");
+      return (FALSE);
+    }
+    out = (float *) buf[0].matrix.buffer + Nset;
+    in = vec[0].elements;
+    for (i = 0; i < Npix; i++, in++, out+=Nx) {
+      *out = *in;
+    }
+    return (TRUE);
+  }    
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/peak.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/peak.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/peak.c	(revision 12606)
@@ -0,0 +1,43 @@
+# include "data.h"
+
+int peak (int argc, char **argv) {
+  
+  int i, imax;
+  double start, end, xmax, ymax;
+  float *X, *Y;
+  Vector *vecx, *vecy;
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: peak <x> <y> start end\n");
+    return (FALSE);
+  }
+
+  if ((vecx = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vecy = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  start = atof (argv[3]);
+  end   = atof (argv[4]);
+
+  X = vecx[0].elements;
+  Y = vecy[0].elements;
+
+  imax = -1;
+  for (i = 0; i < vecx[0].Nelements-1; i++, X++, Y++) {
+    if ((*X >= start) && (*X <= end)) {
+      if ((imax == -1) || (*Y > ymax)) {
+	xmax = *X;
+	ymax = *Y;
+	imax = i;
+      }
+    }
+  }      
+
+  set_variable ("peakval", ymax);
+  set_variable ("peakpos", xmax);
+  set_variable ("peaknum", imax);
+
+  fprintf (stderr, "peak %f @ %f (%d)\n", ymax, xmax, imax);
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/plot.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/plot.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/plot.c	(revision 12606)
@@ -0,0 +1,126 @@
+# include "data.h"
+
+int plot (int argc, char **argv) {
+  
+  int N, Npts, Ngraph;
+  Graphdata graphmode;
+  Vector *xvec, *yvec, *dxmvec, *dxpvec, *dymvec, *dypvec;
+
+  /* choose the appropriate graphing window */
+  Ngraph = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Ngraph = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);
+
+  /* evaluate various plotting options */
+  if (N = get_argument (argc, argv, "-lt")) {
+    remove_argument (N, &argc, argv);
+    graphmode.ltype = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-lw")) {
+    remove_argument (N, &argc, argv);
+    graphmode.lweight = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-pt")) {
+    remove_argument (N, &argc, argv);
+    graphmode.ptype = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "+eb")) {
+    remove_argument (N, &argc, argv);
+    graphmode.ebar = TRUE;
+  }
+  if (N = get_argument (argc, argv, "-eb")) {
+    remove_argument (N, &argc, argv);
+    graphmode.ebar = FALSE;
+  }
+  if (N = get_argument (argc, argv, "-sz")) {
+    remove_argument (N, &argc, argv);
+    graphmode.size = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-c")) {
+    remove_argument (N, &argc, argv);
+    graphmode.color = GetColor (argv[N]);
+    if (graphmode.color == -1) return (FALSE);
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-x")) {
+    remove_argument (N, &argc, argv);
+    graphmode.style = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* decide on error bars */
+  dxmvec = dxpvec = dymvec = dypvec = NULL;
+  if (N = get_argument (argc, argv, "-dx")) {
+    remove_argument (N, &argc, argv);
+    if ((dxmvec = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "+dx")) {
+    remove_argument (N, &argc, argv);
+    if ((dxpvec = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-dy")) {
+    remove_argument (N, &argc, argv);
+    if ((dymvec = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "+dy")) {
+    remove_argument (N, &argc, argv);
+    if ((dypvec = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: plot <x> <y>\n");
+    return (FALSE);
+  }
+
+  /* set plotting options (these are sticky) */
+  SetGraph (graphmode);
+
+  /* set errorbar mode (these are NOT sticky) */
+  graphmode.etype = 0;
+  if ((dymvec != NULL) && (dypvec == NULL)) dypvec = dymvec;
+  if ((dypvec != NULL) && (dymvec == NULL)) dymvec = dypvec;
+  if (dypvec != NULL) graphmode.etype |= 0x01;
+  if ((dxmvec != NULL) && (dxpvec == NULL)) dxpvec = dxmvec;
+  if ((dxpvec != NULL) && (dxmvec == NULL)) dxmvec = dxpvec;
+  if (dxpvec != NULL) graphmode.etype |= 0x02;
+  
+  /* find vectors */
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if (xvec[0].Nelements != yvec[0].Nelements) {
+    fprintf (stderr, "vectors %s and %s not the same length\n", argv[1], argv[2]);
+    return (FALSE);
+  }
+  Npts = xvec[0].Nelements;
+  if (Npts == 0) return (TRUE);
+
+  if (!PrepPlotting (Npts, &graphmode)) return (FALSE);
+  
+  PlotVector (Npts, xvec[0].elements);
+  PlotVector (Npts, yvec[0].elements);
+  if (graphmode.etype & 0x01) {
+    PlotVector (Npts, dymvec[0].elements);
+    PlotVector (Npts, dypvec[0].elements);
+  }
+  if (graphmode.etype & 0x02) {
+    PlotVector (Npts, dxmvec[0].elements);
+    PlotVector (Npts, dxpvec[0].elements);
+  }
+  
+  return (TRUE);
+
+}
+
+
Index: /tags/start/Ohana/src/opihi/cmd.data/point.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/point.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/point.c	(revision 12606)
@@ -0,0 +1,87 @@
+# include "data.h"
+
+int point (int argc, char **argv) {
+  
+  int N, n, ISCEL, ISPIX;
+  int Ximage, Nimage;
+  double x, y, dx, dy, x1, y1;
+  double dra, ddec, ra1, dec1, ra, dec;
+  char *line;
+  Coords coords;
+  Buffer *buf;
+
+  Nimage = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Nimage = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (&Ximage, &Nimage)) return (FALSE);
+  
+  ISCEL = FALSE;
+  if (N = get_argument (argc, argv, "-c")) {
+    remove_argument (N, &argc, argv);
+    ISCEL = TRUE;
+  }
+  
+  ISPIX = FALSE;
+  if (N = get_argument (argc, argv, "-p")) {
+    remove_argument (N, &argc, argv);
+    ISPIX = TRUE;
+  }
+
+  if (argc != 7) {
+    fprintf (stderr, "USAGE: point (overlay) TYPE x y dx dy [-c]\n");
+    return (FALSE);
+  }
+  
+  if (!SelectOverlay (argv[1], &n)) 
+    return (FALSE);
+
+  if (ISCEL) {
+    if ((buf = SelectBuffer (GetImageName(), OLDBUFFER, TRUE)) == NULL) return (FALSE);
+    GetCoords (&coords, &buf[0].header);
+  }
+
+  ALLOCATE (line, char, 1024);     /* space to read the file */
+
+  ra = atof(argv[3]);
+  dec = atof(argv[4]);
+  dra = atof(argv[5]);
+  ddec = atof(argv[6]);
+  if (ISCEL) {
+    RD_to_XY (&x, &y, ra, dec, &coords);
+    if (!ISPIX) {
+      ra1 = ra + dra;
+      dec1 = dec + ddec;
+      RD_to_XY (&x1, &y1, ra1, dec1, &coords);
+      dx = x1 - x;
+      dy = y1 - y;
+    } else {
+      dx = atof(argv[5]);
+      dy = atof(argv[6]);
+    }
+  }
+  else {
+    x = ra;
+    y = dec;
+    dx = dra;
+    dy = ddec;
+  }
+
+  write (Ximage, "LOAD", 4); /* force Ximage to look for the incoming image */
+  sprintf (line, "OVERLAY %6d ", n);
+  write (Ximage, line, 16);
+  sprintf (line, "NLINES %7d ", 1);
+  write (Ximage, line, 16);
+  sprintf (line, "%15s %20.10f %20.10f %20.10f %20.10f ", argv[2], x, y, dx, dy);
+  write (Ximage, line, 128);
+  sprintf (line, "DONE ");
+  write (Ximage, line, 16);
+
+  free (line);
+
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/pop.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/pop.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/pop.c	(revision 12606)
@@ -0,0 +1,44 @@
+# include "data.h"
+
+int pop (int argc, char **argv) {
+  
+  int N;
+  char *var;
+  char *line;
+  Queue *queue;
+
+  var = (char *) NULL;
+  if (N = get_argument (argc, argv, "-var")) {
+    remove_argument (N, &argc, argv);
+    var = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: pop (queue) [-var variable]\n");
+    return (FALSE);
+  }
+
+  /* will create a queue if none exists */
+  queue = FindQueue (argv[1]);
+  if (queue == NULL) {
+    fprintf (stderr, "ERROR: queue %s not found\n", argv[1]);
+    return (FALSE);
+  }
+
+  line = PopQueue (queue);
+  if (line == NULL) {
+    fprintf (stderr, "ERROR: queue %s is empty\n", argv[1]);
+    return (FALSE);
+  }
+
+  if (var == (char *) NULL) {
+    fprintf (stderr, "%s\n", line);
+  } else {
+    set_str_variable (argv[2], line);
+  }
+
+  free (line);
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/ps.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/ps.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/ps.c	(revision 12606)
@@ -0,0 +1,68 @@
+# include "data.h"
+
+int ps (int argc, char **argv) {
+
+  char filename[1024], buffer[64];
+  int N, Source, Nsource, RawImage, NoScale, IsImage;
+  
+  if (N = get_argument (argc, argv, "--help")) {
+    fprintf (stderr, "USAGE: ps [-name file.ps] [-g | -i] [-n device] [-raw] [-scale]\n");
+    return (FALSE);
+  }
+
+  /* raw image? */
+  RawImage = FALSE;
+  if (N = get_argument (argc, argv, "-raw")) {
+    remove_argument (N, &argc, argv);
+    RawImage = TRUE;
+  }
+  /* scale image? */
+  NoScale = FALSE;
+  if (N = get_argument (argc, argv, "-noscale")) {
+    remove_argument (N, &argc, argv);
+    NoScale = TRUE;
+  }
+  /* what file? */
+  filename[0] = 0;
+  if (N = get_argument (argc, argv, "-name")) {
+    remove_argument (N, &argc, argv);
+    strcpy (filename, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  /* which tool */
+  Nsource = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Nsource = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  /* which device */
+  if (N = get_argument (argc, argv, "-g")) {
+    remove_argument (N, &argc, argv);
+    SetImageDevice (FALSE);
+  }  
+  if (N = get_argument (argc, argv, "-i")) {
+    remove_argument (N, &argc, argv);
+    SetImageDevice (TRUE);
+  }  
+  IsImage = GetCurrentDevice ();
+  if (IsImage) {
+    if (!GetImage (&Source, &Nsource)) return (FALSE);
+    if (!filename[0]) strcpy (filename, "Ximage.ps");
+  } else {
+    if (!GetGraph (NULL, &Source, &Nsource)) return (FALSE);
+    if (!filename[0]) strcpy (filename, "Xgraph.ps");
+  }
+  
+  if (RawImage) write (Source, "PSRW", 4); /* tell Ximage to ps the image */
+  if (NoScale)  write (Source, "PSNS", 4); /* tell Ximage to ps the image */
+  if (!RawImage && !NoScale) write (Source, "PSIT", 4); /* tell Ximage to ps the image */
+
+  sprintf (buffer, "LEN: %11d", strlen(filename));
+  write (Source, buffer, 16);
+  write (Source, filename, strlen(filename));
+  read (Source, buffer, 4);
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/push.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/push.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/push.c	(revision 12606)
@@ -0,0 +1,17 @@
+# include "data.h"
+
+int push (int argc, char **argv) {
+  
+  Queue *queue;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: push (queue) (value)\n");
+    return (FALSE);
+  }
+
+  /* will create a queue if none exists */
+  queue = CreateQueue (argv[1]);
+  PushQueue (queue, argv[2]);
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/queues.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/queues.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/queues.c	(revision 12606)
@@ -0,0 +1,48 @@
+# include "data.h"
+
+int queuelist (int argc, char **argv) {
+  
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: queuelist\n");
+    return (FALSE);
+  }
+
+  ListQueues ();
+  return (TRUE);
+}
+
+
+int queuesize (int argc, char **argv) {
+  
+  int N;
+  char *var;
+  Queue *queue;
+
+  var = (char *) NULL;
+  if (N = get_argument (argc, argv, "-var")) {
+    remove_argument (N, &argc, argv);
+    var = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: queuesize (name) [-var variable]\n");
+    return (FALSE);
+  }
+
+  queue = FindQueue (argv[1]);
+  if (queue == NULL) {
+    fprintf (stderr, "ERROR: queue %s not found\n", argv[1]);
+    return (FALSE);
+  }
+
+  if (var == (char *) NULL) {
+    fprintf (stderr, "Nlines: %d\n", queue[0].Nlines);
+    return (TRUE);
+  }
+
+  set_int_variable (var, queue[0].Nlines);
+  free (var);
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/radial.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/radial.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/radial.c	(revision 12606)
@@ -0,0 +1,96 @@
+# include "data.h"
+
+int circstats (int argc, char **argv) {
+  
+  int i, j, Nmode, Imode;
+  double Npix, S1, S2, max, min, Sum, Mean, Stdev, IgnoreValue; 
+  double xc, yc, radius, R2, r;
+  float *V;
+  int xs, ys, xe, ye;
+  int Ignore, Quiet, N, Nx, Ny;
+  Buffer *buf;
+
+  Ignore = FALSE;
+  if (N = get_argument (argc, argv, "-ignore")) {
+    Ignore = TRUE;
+    remove_argument (N, &argc, argv);
+    IgnoreValue = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Quiet = FALSE;
+  if (N = get_argument (argc, argv, "-q")) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-quiet")) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 5) goto usage;
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) goto missed;
+
+  xc = atof (argv[2]);
+  yc = atof (argv[3]);
+  radius = atof (argv[4]);
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+
+  if (xc < 0) goto range;
+  if (yc < 0) goto range;
+  if (xc >= Nx) goto range;
+  if (yc >= Ny) goto range;
+
+  xs = MAX (0, xc - radius);
+  ys = MAX (0, yc - radius);
+  xe = MIN (Nx, xc + radius + 1);
+  ye = MAX (Ny, yc + radius + 1);
+  R2 = radius*radius;
+
+  S1 = S2 = Npix = 0;
+  min = max = *(float *)(buf[0].matrix.buffer) + (int)(yc)*buf[0].matrix.Naxis[0] + (int)(xc); 
+  for (j = ys; j < ye; j++) {
+    V = (float *)(buf[0].matrix.buffer) + j*buf[0].matrix.Naxis[0] + xs; 
+    for (i = xs; i < xe; i++, V++) {
+      r = SQ(i - xc) + SQ(j - yc);
+      if (r > R2) continue;
+      if (Ignore && (fabs (*V - IgnoreValue) < 1e-8)) continue;
+      S1 += *V;
+      S2 += (*V)*(*V);
+      Npix += 1.0;
+      max = MAX (max, *V);
+      min = MIN (min, *V);
+    }
+  }
+  Mean = S1 / Npix;
+  Sum  = Mean * M_PI * R2;
+  Stdev = sqrt (S2/Npix - Mean*Mean);
+
+  if (!Quiet) {
+    fprintf (GetOutfile(), "     mean     stdev       min       max    Npix     Total\n");
+    fprintf (GetOutfile(), "%9.4g %9.4g %9.4g %9.4g %7.0f %9.4g\n", Mean, Stdev, min, max, Npix, Sum);
+  }
+
+  set_variable ("MIN",    min);
+  set_variable ("MAX",    max);
+  set_variable ("MEAN",   Mean);
+  set_variable ("SUM",    Sum);
+  set_variable ("NPIX",   Npix);
+  set_variable ("SIGMA",  Stdev);
+
+  return (TRUE);
+
+ usage: 
+  fprintf (stderr, "USAGE: circstats <buffer> x y radius\n");
+  return (FALSE);
+
+ range:
+  fprintf (stderr, "ERROR: coordinates out of range\n");
+  return (FALSE);
+
+ missed:
+  fprintf (stderr, "ERROR: buffer not found\n");
+  return (FALSE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/rd.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/rd.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/rd.c	(revision 12606)
@@ -0,0 +1,240 @@
+# include "data.h"
+
+/* there is some confusion in this function with the several possible options */
+int rd (int argc, char **argv) {
+  
+  int i, N, status, plane, Nplane, extend, Nextend, Nskip, JustHead;
+  int ccdsel, done;
+  char region[512], *ccdid, *filename;
+  FILE *f;
+  Buffer *buf;
+
+  JustHead = FALSE;
+  if (N = get_argument (argc, argv, "-head")) {
+    remove_argument (N, &argc, argv);
+    JustHead = TRUE;
+  }
+
+  plane = 1;
+  if (N = get_argument (argc, argv, "-plane")) {
+    remove_argument (N, &argc, argv);
+    plane  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  extend = FALSE;
+  Nextend = -1;
+  if (N = get_argument (argc, argv, "-x")) {
+    remove_argument (N, &argc, argv);
+    Nextend  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    extend = TRUE;
+  }
+
+  ccdsel = FALSE;
+  ccdid = (char *) NULL;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    ccdid  = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    ccdsel = TRUE;
+  }
+
+  if (extend && ccdsel) {
+    fprintf (stderr, "only specify one of -n and -x\n");
+    return (FALSE);
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: rd <buffer> <filename> [-head] [-plane N] [-n ccdid] [-x extnum]\n");
+    return (FALSE);
+  }
+
+  /* test if file exists */
+  f = fopen (argv[2], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "file %s not found\n", argv[2]);
+    return (FALSE);
+  }
+  fclose (f);
+
+  /* find matrix, free old data */
+  if ((buf = SelectBuffer (argv[1], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  fits_free_matrix (&buf[0].matrix);
+  fits_free_header (&buf[0].header);
+
+  /* save file name */
+  filename = filebasename (argv[2]);
+  strcpy (buf[0].file, filename);
+  free (filename);
+
+  if (extend) {
+    /* load in appropriate header */
+    Nskip = fits_read_Xheader (argv[2], &buf[0].header, Nextend);
+    if (!Nskip) {
+      fprintf (stderr, "entry in %s not found\n", argv[2]);
+      DeleteBuffer (buf);
+      return (FALSE);
+    }
+    /* fix up header */
+    {
+      static char simple[] = "SIMPLE  =                    T / Standard FITS";
+      int Ns, No;
+
+      Ns = strlen (simple);
+      No = 80 - Ns;
+      strncpy (buf[0].header.buffer, simple, Ns);
+      memset (&buf[0].header.buffer[Ns], ' ', No);
+    }
+    if (JustHead) {
+      /* should be in CreateMatrix / CreateBuffer function */
+      buf[0].header.Naxes = 0;
+      ALLOCATE (buf[0].matrix.buffer, char, 1);
+      buf[0].matrix.size = 0;
+      buf[0].bitpix = 16;
+      buf[0].bzero = 0;
+      buf[0].bscale = 1;
+      buf[0].matrix.bitpix = 16;
+      buf[0].matrix.bzero = 0;
+      buf[0].matrix.bscale = 1;
+      buf[0].header.bitpix = 16;
+      buf[0].header.bzero = 0;
+      buf[0].header.bscale = 1;
+      return (TRUE);
+    }
+    /* load matrix data */
+    f = fopen (argv[2], "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "file %s not found\n", argv[2]);
+      DeleteBuffer (buf);
+      return (FALSE);
+    }
+    fseek (f, Nskip, SEEK_SET);
+    status = fits_load_matrix (f, &buf[0].matrix, &buf[0].header);
+    fclose (f);
+  } 
+
+  if (ccdsel) {
+    char *CCDKeyword, ID[64];
+
+    CCDKeyword = get_variable ("CCDKEYWORD");
+    if (CCDKeyword == (char *) NULL) {
+      fprintf (stderr, "CCDKEYWORD variable is not set; ");
+      fprintf (stderr, "using IMAGEID as default\n");
+      CCDKeyword = strcreate ("IMAGEID");
+    }
+    done = FALSE;
+    for (i = 0; !done; i++) {
+      Nskip = fits_read_Xheader (argv[2], &buf[0].header, i);
+      if (!Nskip) {
+	fprintf (stderr, "extension %s in %s not found\n", ccdid, argv[2]);
+	DeleteBuffer (buf);
+	free (CCDKeyword);
+	return (FALSE);
+      }
+      if (!fits_scan (&buf[0].header, CCDKeyword, "%s", 1, ID)) {
+	fprintf (stderr, "%s not in header\n", CCDKeyword);
+	DeleteBuffer (buf);
+	free (CCDKeyword);
+	return (FALSE);
+      }
+
+      /* compare as numbers if both are pure numbers, else as strings */
+      done = strnumcmp (ccdid, ID);
+
+      if (!done) fits_free_header (&buf[0].header);
+    }
+    free (CCDKeyword);
+
+    /* fix up header */
+    {
+      static char simple[] = "SIMPLE  =                    T / Standard FITS";
+      int Ns, No;
+
+      Ns = strlen (simple);
+      No = 80 - Ns;
+      strncpy (buf[0].header.buffer, simple, Ns);
+      memset (&buf[0].header.buffer[Ns], ' ', No);
+    }
+    if (JustHead) {
+      buf[0].header.Naxes = 0;
+      ALLOCATE (buf[0].matrix.buffer, char, 1);
+      buf[0].matrix.size = 0;
+      buf[0].bitpix = 16;
+      buf[0].bzero = 0;
+      buf[0].bscale = 1;
+      buf[0].matrix.bitpix = 16;
+      buf[0].matrix.bzero = 0;
+      buf[0].matrix.bscale = 1;
+      buf[0].header.bitpix = 16;
+      buf[0].header.bzero = 0;
+      buf[0].header.bscale = 1;
+      return (TRUE);
+    }
+    /* load matrix data */
+    f = fopen (argv[2], "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "file %s not found\n", argv[2]);
+      DeleteBuffer (buf);
+      return (FALSE);
+    }
+    fseek (f, Nskip, SEEK_SET);
+    status = fits_load_matrix (f, &buf[0].matrix, &buf[0].header);
+    fclose (f);
+  }
+
+  if (!ccdsel && !extend) {
+    status = fits_read_header (argv[2], &buf[0].header);
+    if (JustHead) {
+      buf[0].header.Naxes = 0;
+      ALLOCATE (buf[0].matrix.buffer, char, 1);
+      buf[0].matrix.size = 0;
+      buf[0].bitpix = 16;
+      buf[0].bzero = 0;
+      buf[0].matrix.bscale = 1;
+      buf[0].matrix.bitpix = 16;
+      buf[0].matrix.bzero = 0;
+      buf[0].matrix.bscale = 1;
+      return (TRUE);
+    }
+    Nplane = buf[0].header.Naxis[2];
+    if (Nplane > 0) {
+      if (plane > Nplane) {
+	fprintf (stderr, "-plane is too large: %d total planes\n", Nplane);
+	DeleteBuffer (buf);
+	return (FALSE);
+      }
+      buf[0].header.Naxis[2] = 0;
+      buf[0].header.Naxes = 2;
+      fits_modify (&buf[0].header, "NAXIS", "%d", 1, 2);
+      fits_delete (&buf[0].header, "NAXIS3", 1);
+    }
+    sprintf (region, "-1 -1 -1 -1 %d %d", (plane - 1), plane);
+    status = fits_read_segment (argv[2], &buf[0].matrix, region);
+  }
+
+  if (!status) {
+    fprintf (stderr, "problem reading file, buffer not opened\n");
+    DeleteBuffer (buf);
+    return (FALSE);
+  }
+  if (buf[0].header.Naxes == 1) {
+    /* we need to return an array, so make Naxis[1] = 1 */
+    buf[0].header.Naxes = 2;
+    buf[0].header.Naxis[1] = 1;
+    buf[0].matrix.Naxis[1] = 1;
+  }    
+
+  buf[0].bitpix = buf[0].header.bitpix;    /* store the original values */
+  buf[0].bscale = buf[0].header.bscale;    /* store the original values */
+  buf[0].bzero  = buf[0].header.bzero;     /* store the original values */
+  buf[0].unsign = buf[0].header.unsign;
+  fprintf (GetOutfile(), "read %d bytes from %s into buffer %s\n", 
+	   buf[0].header.size + buf[0].matrix.size, argv[2], argv[1]);
+
+  /** now - convert the matrix values to floats for internal use **/
+  fits_convert_format (&buf[0].header, &buf[0].matrix, -32, 1.0, 0.0, FT_UNSIGN_MODE);
+  
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/rdseg.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/rdseg.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/rdseg.c	(revision 12606)
@@ -0,0 +1,72 @@
+# include "data.h"
+
+/* there is some confusion in this function with the several possible options */
+int rdseg (int argc, char **argv) {
+  
+  int x, y, nx, ny, status;
+  char region[512], *filename;
+  FILE *f;
+  Buffer *buf;
+
+  if (argc != 7) {
+    fprintf (stderr, "USAGE: rdseg <buffer> <filename> x y nx ny\n");
+    return (FALSE);
+  }
+  x = atoi (argv[3]);
+  y = atoi (argv[4]);
+  nx = atoi (argv[5]);
+  ny = atoi (argv[6]);
+
+  /* test if file exists */
+  f = fopen (argv[2], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "file %s not found\n", argv[2]);
+    return (FALSE);
+  }
+  fclose (f);
+
+  /* find matrix, free old data */
+  if ((buf = SelectBuffer (argv[1], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  fits_free_matrix (&buf[0].matrix);
+  fits_free_header (&buf[0].header);
+
+  /* save file name */
+  filename = filebasename (argv[2]);
+  strcpy (buf[0].file, filename);
+  free (filename);
+
+  status = fits_read_header (argv[2], &buf[0].header);
+  sprintf (region, "%d %d %d %d 0 1", x, nx + x, y, ny + y);
+  status = fits_read_segment (argv[2], &buf[0].matrix, region);
+  fits_modify (&buf[0].header, "NAXIS1", "%d", 1, nx);
+  fits_modify (&buf[0].header, "NAXIS2", "%d", 1, ny);
+  buf[0].header.Naxis[0] = nx;
+  buf[0].header.Naxis[1] = ny;
+  buf[0].matrix.Naxis[0] = nx;
+  buf[0].matrix.Naxis[1] = ny;
+
+  if (!status) {
+    fprintf (stderr, "problem reading file, buffer not opened\n");
+    DeleteBuffer (buf);
+    return (FALSE);
+  }
+  if (buf[0].header.Naxes == 1) {
+    /* we need to return an array, so make Naxis[1] = 1 */
+    buf[0].header.Naxes = 2;
+    buf[0].header.Naxis[1] = 1;
+    buf[0].matrix.Naxis[1] = 1;
+  }    
+
+  buf[0].bitpix = buf[0].header.bitpix;    /* store the original values */
+  buf[0].bscale = buf[0].header.bscale;    /* store the original values */
+  buf[0].bzero  = buf[0].header.bzero;     /* store the original values */
+  buf[0].unsign = buf[0].header.unsign;
+  fprintf (GetOutfile(), "read %d bytes from %s into buffer %s\n", 
+	   buf[0].header.size + buf[0].matrix.size, argv[2], argv[1]);
+
+  /** now - convert the matrix values to floats for internal use **/
+  fits_convert_format (&buf[0].header, &buf[0].matrix, -32, 1.0, 0.0, FT_UNSIGN_MODE);
+  
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/read_vectors.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/read_vectors.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/read_vectors.c	(revision 12606)
@@ -0,0 +1,274 @@
+ # include "data.h"
+
+FILE *f = (FILE *) NULL;
+char filename[256];
+
+int datafile (int argc, char **argv) {
+
+  if (argc < 2) {
+    fprintf (stderr, "USAGE: datafile (filename)\n");
+    return (FALSE);
+  }
+  
+  strcpy (filename, argv[1]);
+  if (f != (FILE *) NULL) { fclose (f); }
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "failed to open file %s\n", argv[1]);
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+int read_vectors (int argc, char **argv) {
+  
+  int i, j, Nskip, Nvec, *col, done, status;
+  int Nbytes, nbytes, Nstart, NELEM, N, nread;
+  char *colstr, *c0, *c1, *buffer, *extname;
+  double value;
+  Vector **vec;
+
+  /* auto-sense table type */
+  if (N = get_argument (argc, argv, "-fits")) {
+    remove_argument (N, &argc, argv);
+    extname = strcreate (argv[N]);
+    if (extname == (char *) NULL) return (FALSE);
+    remove_argument (N, &argc, argv);
+    status = read_table_vectors (argc, argv, extname);
+    free (extname);
+    return (status);
+  }
+
+  Nskip = 0;
+  if (N = get_argument (argc, argv, "-skip")) {
+    remove_argument (N, &argc, argv);
+    Nskip = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((argc < 3) || !(argc % 2)) {
+    fprintf (stderr, "USAGE: read name N name N ...\n");
+    return (FALSE);
+  }
+  /* read name N name N  */
+
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "no open file for read\n");
+    return (FALSE);
+  }
+  fseek (f, 0, SEEK_SET);
+
+  Nvec = (argc - 1) / 2;
+  ALLOCATE (vec, Vector *, Nvec);
+  ALLOCATE (col, int, Nvec);
+
+  for (i = 0; i < Nvec; i++) {
+    if ((vec[i] = SelectVector (argv[2*i + 1], ANYVECTOR, TRUE)) == NULL) {
+      fprintf (stderr, "USAGE: read name N name N ...\n");
+      free (vec);
+      free (col);
+      return (FALSE);    
+    }
+    colstr = argv[2*i+2];
+    for (j = 0; j < strlen (colstr); j++) {
+      if (!isdigit(colstr[j])) {
+	fprintf (stderr, "USAGE: read name N name N ...\n");
+	free (vec);
+	free (col);
+	return (FALSE);    
+      }
+    }
+    col[i] = atof (colstr);
+  }
+  
+  NELEM = 1000;
+  for (i = 0; i < Nvec; i++) {
+    REALLOCATE (vec[i][0].elements, float, NELEM);
+  }
+  
+  ALLOCATE (buffer, char, 0x10001);
+  bzero (buffer, 0x10001);
+  for (i = 0; i < Nskip; i++) {
+    scan_line (f, buffer);
+  }
+
+  Nstart = 0;
+  N = 0;
+  done = FALSE;
+  while (!done) {
+    Nbytes = 0x10000 - Nstart;
+    bzero (&buffer[Nstart], Nbytes);
+    nread = fread (&buffer[Nstart], 1, Nbytes, f);
+    if (ferror (f)) {
+      perror ("error reading data file");
+      break;
+    }
+    if (nread == 0) break;
+    nbytes = nread + Nstart;
+    
+    status = TRUE;
+    c0 = buffer; 
+    while (status) {
+      c1 = strchr (c0, '\n');
+      if (c1 == (char *) NULL) {
+	Nstart = strlen (c0);
+	memmove (buffer, c0, Nstart);
+	status = FALSE;
+      } else {
+	*c1 = 0;
+      }      
+      if ((*c0 != '#') && (*c0 != '!')) {
+	for (i = 0; (i < Nvec) && status; i++) {
+	  status = dparse (&value, col[i], c0);
+	  vec[i][0].elements[N] = value;
+	  if (!status) vec[i][0].elements[N] = 0.0/0.0;
+	}
+	if (status) N++;
+      }
+      c0 = c1 + 1;
+      if (N == NELEM) {
+	NELEM += 1000;
+	for (i = 0; i < Nvec; i++) {
+	  REALLOCATE (vec[i][0].elements, float, NELEM);
+	}
+      }
+	
+    }
+  }
+  for (i = 0; i < Nvec; i++) {
+    REALLOCATE (vec[i][0].elements, float, MAX (N,1));
+    vec[i][0].Nelements = N;
+  }
+  
+  free (vec);
+  free (col);
+  free (buffer);
+  return (TRUE);
+
+}
+
+int read_table_vectors (int argc, char **argv, char *extname) {
+
+  int i, j, k, Nbytes, Nread, Nextend, Ny, Binary;
+  char type[16];
+  FTable table;
+  Header header;
+  Vector **vec;
+
+  if (argc < 2) {
+    fprintf (stderr, "USAGE: read -fits extension name name ...\n");
+    fprintf (stderr, "  ('extension' may be a name or number)\n");
+    return (FALSE);
+  }
+
+  if (f == (FILE *) NULL) return (FALSE);
+  fseek (f, 0, SEEK_SET);
+  table.header = &header;
+
+  /* load appropriate extension (if extname is a number, use count) */
+  if (isdigit(extname[0])) {
+    Nextend = atoi (extname);
+
+    for (i = 0; i <= Nextend; i++) {
+      if (!fits_load_header (f, &header)) return (FALSE);
+      Nbytes = fits_matrix_size (&header);
+      /* skip the prior data buffers */
+      if (i < Nextend) { 
+	fseek (f, Nbytes, SEEK_CUR);
+	fits_free_header (&header);
+	continue;
+      }
+      /* on the desired header, load buffer */
+      ALLOCATE (table.buffer, char, Nbytes);
+      Nread = fread (table.buffer, sizeof (char), Nbytes, f);
+      if (Nread != Nbytes) {
+	fits_free_table  (&table);
+	fits_free_header (&header);
+	return (FALSE);
+      }
+      table.size = Nbytes;
+    }
+  } else {
+    if (!fits_fread_ftable (f, &table, extname)) return (FALSE);
+  }
+
+  /* identify table type (ascii / binary) */
+  Binary = FALSE;
+  fits_scan (&header, "XTENSION", "%s", 1, type);
+  if (!strcmp (type, "BINTABLE")) {
+    Binary = TRUE;
+  } 
+  Ny = header.Naxis[1];
+
+  /* find columns which match requested vectors */
+  for (i = 1; i < argc; i++) {
+    void   *data;
+    short  *Ps;
+    int    *Pi;
+    float  *Pf;
+    double *Pd;
+    int Nval;
+    char name[80];
+      
+    Nval = 0;
+    if (Binary) {
+      if (!fits_get_bintable_column_type (&header, argv[i], type, &Nval)) return (FALSE);
+      if (!strcmp (type, "char")) return (FALSE);
+      if (!fits_get_bintable_column (&header, &table, argv[i], &data)) return (FALSE);
+    } else {
+      if (!fits_get_table_column_type (&header, argv[i], type)) return (FALSE);
+      if (!strcmp (type, "char")) return (FALSE);
+      if (!fits_get_table_column (&header, &table, argv[i], &data)) return (FALSE);
+    }
+    if (Nval == 0) return (FALSE);
+
+    ALLOCATE (vec, Vector, Nval);
+    for (j = 0; j < Nval; j++) {
+      if (Nval == 1) 
+	sprintf (name, "%s", argv[i]);
+      else
+	sprintf (name, "%s:%d", argv[i], j);
+      if ((vec[j] = SelectVector (name, ANYVECTOR, TRUE)) == NULL) return (FALSE);    
+      REALLOCATE (vec[j][0].elements, float, MAX (Ny,1));
+      vec[j][0].Nelements = Ny;
+    }
+
+    if (!strcmp (type, "double")) {
+      Pd = (double *) data;
+      for (j = 0; j < Ny; j++) {
+	for (k = 0; k < Nval; k++, Pd++) {
+	  vec[k][0].elements[j] = *Pd;
+	}
+      }
+    }
+    if (!strcmp (type, "float")) {
+      Pf = (float *) data;
+      for (j = 0; j < Ny; j++) {
+	for (k = 0; k < Nval; k++, Pf++) {
+	  vec[k][0].elements[j] = *Pf;
+	}
+      }
+    }
+    if (!strcmp (type, "int")) {
+      Pi = (int *) data;
+      for (j = 0; j < Ny; j++) {
+	for (k = 0; k < Nval; k++, Pi++) {
+	  vec[k][0].elements[j] = *Pi;
+	}
+      }
+    }
+    if (!strcmp (type, "short")) {
+      Ps = (short *) data;
+      for (j = 0; j < Ny; j++) {
+	for (k = 0; k < Nval; k++, Ps++) {
+	  vec[k][0].elements[j] = *Ps;
+	}
+      }
+    }
+    free (data);
+    free (vec);
+  }
+  fits_free_table (&table);
+  fits_free_header (&header);
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/rebin.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/rebin.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/rebin.c	(revision 12606)
@@ -0,0 +1,227 @@
+# include "data.h"
+
+int rebin (int argc, char **argv) {
+  
+  int i, j, status, n, nx, ny, Nx, Ny, x, y, N, *Npix, *Vn;
+  int Ignore, IgnoreValue, VERBOSE, Normalize, ExactScale;
+  char temp[1024];
+  float *Vout, *Vin, *Out, *In;
+  double scale, scale2, fx, fy, dX, dY;
+  Buffer *in, *out;
+
+  Normalize = FALSE;
+  if (N = get_argument (argc, argv, "-norm")) {
+    remove_argument (N, &argc, argv);
+    Normalize = TRUE;
+  }
+
+  VERBOSE = FALSE;
+  if (N = get_argument (argc, argv, "-v")) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = TRUE;
+  }
+
+  Ignore = FALSE;
+  IgnoreValue = 0.0;
+  if (N = get_argument (argc, argv, "-ignore")) {
+    Ignore = TRUE;
+    remove_argument (N, &argc, argv);
+    IgnoreValue = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: rebin <from> <to> scale \n");
+    fprintf (stderr, "  negative integer scale expands image\n");
+    return (FALSE);
+  }
+
+  if ((in  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out = SelectBuffer (argv[2], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  fits_free_matrix (&out[0].matrix);
+  fits_free_header (&out[0].header);
+
+  scale  = atof (argv[3]);
+  if ((scale == (int) scale) || ((1.0/scale) == (int)(1.0/scale))) {
+    ExactScale = TRUE;
+    if (scale > 0) {
+      nx = in[0].header.Naxis[0] / scale;
+      ny = in[0].header.Naxis[1] / scale;
+    } else {
+      nx = in[0].header.Naxis[0] * fabs(scale);
+      ny = in[0].header.Naxis[1] * fabs(scale);
+    }    
+  } else {
+    ExactScale = FALSE;
+    if (scale > 0) {
+      nx = (int) (in[0].header.Naxis[0] / scale) + 1;
+      ny = (int) (in[0].header.Naxis[1] / scale) + 1;
+    } else {
+      nx = (int) (in[0].header.Naxis[0] * fabs(scale)) + 1;
+      ny = (int) (in[0].header.Naxis[1] * fabs(scale)) + 1;
+    }      
+  }
+  if (VERBOSE) fprintf (GetOutfile(), "rebin %s to %s (%d,%d to %d,%d)\n", argv[1], argv[2], in[0].header.Naxis[0], in[0].header.Naxis[1], nx, ny);
+
+  Nx = in[0].header.Naxis[0];
+  Ny = in[0].header.Naxis[1];
+  out[0].bitpix = in[0].bitpix;
+  out[0].unsign = in[0].unsign;
+  out[0].bscale = in[0].bscale;
+  out[0].bzero  = in[0].bzero;
+  fits_copy_header (&in[0].header, &out[0].header);
+  fits_modify (&out[0].header, "NAXIS1", "%d", 1, nx);
+  fits_modify (&out[0].header, "NAXIS2", "%d", 1, ny);
+
+  status =  fits_scan (&out[0].header, "CDELT1", "%lf", 1, &dX);
+  status &= fits_scan (&out[0].header, "CDELT2", "%lf", 1, &dY);
+  if (scale > 0) {
+    dX *= scale;
+    dY *= scale;
+  } else {
+    dX /= fabs(scale);
+    dY /= fabs(scale);
+  }    
+  if (status) {
+    fits_modify (&out[0].header, "CDELT1", "%lf", 1, dX);
+    fits_modify (&out[0].header, "CDELT2", "%lf", 1, dY);
+  }
+
+  status =  fits_scan (&out[0].header, "CRPIX1", "%lf", 1, &dX);
+  status &= fits_scan (&out[0].header, "CRPIX2", "%lf", 1, &dY);
+  if (scale > 0) {
+    dX /= scale;
+    dY /= scale;
+  } else {
+    dX *= fabs(scale);
+    dY *= fabs(scale);
+  }    
+  if (status) {
+    fits_modify (&out[0].header, "CRPIX1", "%lf", 1, dX);
+    fits_modify (&out[0].header, "CRPIX2", "%lf", 1, dY);
+  }
+
+  out[0].header.Naxis[0] = nx;
+  out[0].header.Naxis[1] = ny;
+  fits_create_matrix (&out[0].header, &out[0].matrix);
+  temp[0] = 0;
+  if ((in[0].file[0] != '*') && (in[0].file[0] != '(')) {
+    strcpy (temp, "*");
+  }
+  strcat (temp, in[0].file);
+  strcpy (out[0].file, temp);
+
+  if (Normalize) {
+    ALLOCATE (Npix, int, nx*ny);
+    bzero (Npix, nx*ny*sizeof(int));
+  }
+
+  if (ExactScale) {
+    n = scale;
+    if (n > 0) {
+      for (j = 0; j < ny; j++) {
+	for (y = 0; y < n; y++) {
+	  Vout = (float *)(out[0].matrix.buffer) + j*nx;
+	  Vin  = (float *)(in[0].matrix.buffer)  + (j*n + y)*in[0].header.Naxis[0];
+	  if (Normalize) { Vn = Npix + j*nx; }
+	  for (i = 0; i < nx; i++, Vout++) {
+	    for (x = 0; x < n; x++, Vin++) {
+	      if (Ignore && (*Vin == IgnoreValue)) continue;
+	      *Vout += *Vin;
+	      if (Normalize) {(*Vn) ++;}
+	    }
+	    if (Normalize) {Vn ++;}
+	  }
+	}
+      }
+    } else {
+      n = fabs (n);
+      for (j = 0; j < in[0].header.Naxis[1]; j++) {
+	for (y = 0; y < n; y++) {
+	  Vout = (float *)(out[0].matrix.buffer) + (j*n + y)*nx;
+	  Vin  = (float *)(in[0].matrix.buffer)  + j*in[0].header.Naxis[0];
+	  if (Normalize) { Vn = Npix + j*nx; }
+	  for (i = 0; i < in[0].header.Naxis[0]; i++, Vin++) {
+	    if (Ignore && (*Vin == IgnoreValue)) { 
+	      Vout += n; 
+	      if (Normalize) Vn += n; 
+	      continue; 
+	    }
+	    for (x = 0; x < n; x++, Vout++) {
+	      *Vout = *Vin;
+	      if (Normalize) {(*Vn) ++; Vn ++;}
+	    }
+	  }
+	}
+      }
+    }
+    if (Normalize) {
+      Vn = Npix;
+      Vout = (float *)out[0].matrix.buffer;
+      for (i = 0; i < nx*ny; i++, Vout++, Vn++) {
+	if (*Vn) { 
+	  *Vout /= *Vn; 
+	} else {
+	  *Vout = 0;
+	}
+      }
+    }
+  } else {
+    
+    /* normalization is broken.  repair please */
+    if (Normalize) { fprintf (stderr, "normalize not enabled for fractional scaling\n"); }
+
+    if (scale < 0) scale = 1.0 / fabs(scale);
+    In = (float *)in[0].matrix.buffer;
+    Out = (float *)out[0].matrix.buffer;
+    scale2 = scale*scale;
+    if (scale > 1) {
+      for (i = 0; i < Ny; i++) {
+	y = 0.5 + (i - 0.5) / scale;
+	fy = 0.5 + MIN (0.5, (y + 0.5) * scale - i);
+	for (j = 0; j < Nx; j++, In++) {
+	  x = 0.5 + (j - 0.5) / scale;
+	  fx = 0.5 + MIN (0.5, (x + 0.5) * scale - j);
+	  Vout = Out + y*nx + x;
+	  *Vout += fx*fy*(*In);
+	  if (fx < 1) {
+	    *(Vout+1)    += (1-fx)*fy*(*In);
+	  }
+	  if (fy < 1) {
+	    *(Vout+nx) += fx*(1-fy)*(*In);
+	  }
+	  if ((fx < 1) && (fy < 1)) {
+	    *(Vout+1+nx) += (1-fx)*(1-fy)*(*In);
+	  }
+	}
+      }
+    } else {
+      for (i = 0; i < ny; i++) {
+	y = 0.5 + (i - 0.5) * scale;
+	fy = 0.5 + MIN (0.5, (y + 0.5) / scale - i);
+	for (j = 0; j < nx; j++, Out++) {
+	  x = 0.5 + (j - 0.5) * scale;
+	  fx = 0.5 + MIN (0.5, (x + 0.5) / scale - j);
+	  Vin = In + y*Nx + x;
+	  *Out += *Vin*fx*fy;
+	  if (fx < 1) {
+	    *Out += *(Vin+1)*(1-fx)*fy;
+	  }
+	  if (fy < 1) {
+	    *Out += *(Vin+Nx)*fx*(1-fy);
+	  }
+	  if ((fx < 1) && (fy < 1)) {
+	    *Out += *(Vin+1+Nx)*(1-fx)*(1-fy);
+	  }
+	  *Out = *Out * scale2;
+	}
+      }
+    }
+  }
+
+  if (Normalize) free (Npix);
+
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/resize.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/resize.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/resize.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include "data.h"
+
+int resize (int argc, char **argv) {
+
+  char buffer[128], buffer2[128], *end;
+  double NX, NY;
+  int N, Source, Nsource, IsImage;
+  
+  /* display source */
+  Nsource = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Nsource = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-g")) {
+    remove_argument (N, &argc, argv);
+    SetImageDevice (FALSE);
+  }  
+  if (N = get_argument (argc, argv, "-i")) {
+    remove_argument (N, &argc, argv);
+    SetImageDevice (TRUE);
+  }  
+  IsImage = GetCurrentDevice ();
+  if (IsImage) {
+    if (!GetImage (&Source, &Nsource)) return (FALSE);
+  } else {
+    if (!GetGraph (NULL, &Source, &Nsource)) return (FALSE);
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: resize NX NY [-n] [-g | -i]\n");
+    return (FALSE);
+  }
+
+  /* NX & NY are pixels for the screen & points for PS 
+     convert units to points (1in = 72pt, 1cm = 28pt) */
+
+  /* have kapa convert physical units to screen units 
+     for now, fixed at 96 pix / in == 38 pix / cm
+  */
+
+  NX = strtod (argv[1], &end);
+  if (!strcmp (end, "in")) { NX *= 96; }
+  if (!strcmp (end, "cm")) { NX *= 38; }
+
+  NY = strtod (argv[2], &end);
+  if (!strcmp (end, "in")) { NY *= 96; }
+  if (!strcmp (end, "cm")) { NY *= 38; }
+
+  write (Source, "RSIZ", 4); /* tell Source to resize the image */
+
+  sprintf (buffer, "%d %d", (int) NX, (int) NY);
+  sprintf (buffer2, "NBYTES: %6d ", strlen (buffer));
+  write (Source, buffer2, 16);
+  write (Source, buffer, strlen (buffer));
+
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/roll.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/roll.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/roll.c	(revision 12606)
@@ -0,0 +1,45 @@
+# include "data.h"
+
+int roll (int argc, char **argv) {
+  
+  int Nbytes, Nextra;
+  int dX, dx, dy, nx, ny;
+  Buffer *buf;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: roll <buffer> dx dy\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  dx = atof (argv[2]);
+  dy = atof (argv[3]);
+  if (dy != 0) {
+    fprintf (stderr, "only x rolls implemented for now\n");
+  }
+
+  /* if (dx < 0), we are moving the start position back by dx pixels,
+     if (dx > 0), we are moving the start position forward by dx pixels */
+  
+  nx = buf[0].matrix.Naxis[0];
+  ny = buf[0].matrix.Naxis[1];
+
+  dX = abs(dx);
+  Nbytes = nx * ny * sizeof (float);
+  Nextra = (nx * ny + dX) * sizeof (float);
+
+  REALLOCATE (buf[0].matrix.buffer, char, Nextra);
+
+  if (dx < 0) {
+    memmove (buf[0].matrix.buffer, &buf[0].matrix.buffer[dX*sizeof(float)], Nbytes);
+  } else {
+    memmove (&buf[0].matrix.buffer[dX*sizeof(float)], buf[0].matrix.buffer, Nbytes);
+  }
+
+  REALLOCATE (buf[0].matrix.buffer, char, Nbytes);
+
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/rotate.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/rotate.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/rotate.c	(revision 12606)
@@ -0,0 +1,298 @@
+# include "data.h"
+
+int rotate (int argc, char **argv) {
+  
+  int i, j, NX, NY, X, Y, Lx, Ly, N, newCenter;
+  float *in_buff, *out_buff, *c;
+  double angle, CosAngle, SinAngle, Xo, Yo, dX, dY, fx, fy, x, y, X1, Y1;
+  double pc11, pc12, pc21, pc22, PC11, PC12, PC21, PC22;
+  Buffer *buf;
+
+  Xo = 0;
+  Yo = 0;
+  if (N = get_argument (argc, argv, "-center")) {
+    newCenter = TRUE;
+    remove_argument (N, &argc, argv);
+    Xo  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    Yo  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  else 
+    newCenter  = FALSE;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: rotate <buffer> <angle>\n");
+    return (FALSE);
+  }
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  if ((atof (argv[1]) < -180) || (atof (argv[1]) > 180)) {
+    fprintf (stderr, "valid rotate angle between -180 and +180 degrees\n");
+    return (FALSE);
+  }
+
+  /* save starting values */
+  NX = buf[0].header.Naxis[0];
+  NY = buf[0].header.Naxis[1];
+  in_buff = (float *) buf[0].matrix.buffer;  /* don't lose reference */
+
+  if (!strcasecmp (argv[2], "LEFT") || (atof (argv[2]) == -90)) {
+    buf[0].header.Naxis[0] = NY;
+    buf[0].header.Naxis[1] = NX;
+    fits_modify (&buf[0].header, "NAXIS1", "%d", 1, NY);
+    fits_modify (&buf[0].header, "NAXIS2", "%d", 1, NX);
+    fits_print  (&buf[0].header, "HISTORY", "%S", 1, "WARNING: rotated image!");
+    fits_create_matrix (&buf[0].header, &buf[0].matrix);
+    out_buff = (float *)buf[0].matrix.buffer;
+    for (i = NX - 1; i > -1; i--) {
+      for (j = 0; j < NY; j++, out_buff++) {
+	*out_buff = in_buff[i + j*NX];
+      }
+    }
+    /* fix reference pixel */
+    fits_scan (&buf[0].header, "CRPIX1", "%lf", 1, &Xo);
+    fits_scan (&buf[0].header, "CRPIX2", "%lf", 1, &Yo);
+    X1 = Yo;
+    Y1 = NX - Xo;
+    fits_modify (&buf[0].header, "CRPIX1", "%lf", 1, X1);
+    fits_modify (&buf[0].header, "CRPIX2", "%lf", 1, Y1);
+    
+    /* fix rotate matrix */
+    fits_scan (&buf[0].header, "PC001001", "%lf", 1, &pc11);
+    fits_scan (&buf[0].header, "PC001002", "%lf", 1, &pc12);
+    fits_scan (&buf[0].header, "PC002001", "%lf", 1, &pc21);
+    fits_scan (&buf[0].header, "PC002002", "%lf", 1, &pc22);
+    PC11 = pc21;
+    PC12 = pc22;
+    PC21 = -pc11;
+    PC22 = -pc12;
+    fits_modify (&buf[0].header, "PC001001", "%le", 1, PC11);
+    fits_modify (&buf[0].header, "PC001002", "%le", 1, PC12);
+    fits_modify (&buf[0].header, "PC002001", "%le", 1, PC21);
+    fits_modify (&buf[0].header, "PC002002", "%le", 1, PC22);
+
+    free (in_buff);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[2], "RIGHT") || (atof (argv[2]) == 90)) {
+    buf[0].header.Naxis[0] = NY;
+    buf[0].header.Naxis[1] = NX;
+    fits_modify (&buf[0].header, "NAXIS1", "%d", 1, NY);
+    fits_modify (&buf[0].header, "NAXIS2", "%d", 1, NX);
+    fits_print  (&buf[0].header, "HISTORY", "%S", 1, "WARNING: rotated image!");
+    fits_create_matrix (&buf[0].header, &buf[0].matrix);
+    out_buff = (float *)buf[0].matrix.buffer;
+    for (i = 0; i < NX; i++) {
+      for (j = NY - 1; j > -1; j--, out_buff++) {
+	*out_buff = in_buff[i + j*NX];
+      }
+    }
+    /* fix reference pixel */
+    fits_scan (&buf[0].header, "CRPIX1", "%lf", 1, &Xo);
+    fits_scan (&buf[0].header, "CRPIX2", "%lf", 1, &Yo);
+    X1 = NY - Yo;
+    Y1 = Xo;
+    fprintf (stderr, "%f %f -> %f %f\n", Xo, Yo, X1, Y1);
+    fits_modify (&buf[0].header, "CRPIX1", "%lf", 1, X1);
+    fits_modify (&buf[0].header, "CRPIX2", "%lf", 1, Y1);
+    
+    /* fix rotate matrix */
+    fits_scan (&buf[0].header, "PC001001", "%lf", 1, &pc11);
+    fits_scan (&buf[0].header, "PC001002", "%lf", 1, &pc12);
+    fits_scan (&buf[0].header, "PC002001", "%lf", 1, &pc21);
+    fits_scan (&buf[0].header, "PC002002", "%lf", 1, &pc22);
+    PC11 = -pc21;
+    PC12 = -pc22;
+    PC21 = pc11;
+    PC22 = pc12;
+    fprintf (stderr, "%f %f  ->  %f %f\n", pc11, pc12, PC11, PC12);
+    fprintf (stderr, "%f %f  ->  %f %f\n", pc21, pc22, PC21, PC22);
+    fits_modify (&buf[0].header, "PC001001", "%le", 1, PC11);
+    fits_modify (&buf[0].header, "PC001002", "%le", 1, PC12);
+    fits_modify (&buf[0].header, "PC002001", "%le", 1, PC21);
+    fits_modify (&buf[0].header, "PC002002", "%le", 1, PC22);
+
+    free (in_buff);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[2], "UPSIDE") || (atof (argv[2]) == -180) || (atof (argv[2]) == 180)) {
+    fits_print  (&buf[0].header, "HISTORY", "%S", 1, "WARNING: rotated image!");
+    fits_create_matrix (&buf[0].header, &buf[0].matrix);
+    out_buff = (float *)buf[0].matrix.buffer;
+    for (j = NY - 1; j > -1; j--) {
+      for (i = NX - 1; i > -1; i--, out_buff++) {
+	*out_buff = in_buff[i + j*NX];
+      }
+    }
+    /* fix reference pixel */
+    fits_scan (&buf[0].header, "CRPIX1", "%lf", 1, &Xo);
+    fits_scan (&buf[0].header, "CRPIX2", "%lf", 1, &Yo);
+    X1 = NX - Xo;
+    Y1 = NY - Yo;
+    fits_modify (&buf[0].header, "CRPIX1", "%lf", 1, X1);
+    fits_modify (&buf[0].header, "CRPIX2", "%lf", 1, Y1);
+    
+    /* fix rotate matrix */
+    fits_scan (&buf[0].header, "PC001001", "%lf", 1, &pc11);
+    fits_scan (&buf[0].header, "PC001002", "%lf", 1, &pc12);
+    fits_scan (&buf[0].header, "PC002001", "%lf", 1, &pc21);
+    fits_scan (&buf[0].header, "PC002002", "%lf", 1, &pc22);
+    PC11 = -pc11;
+    PC12 = -pc12;
+    PC21 = -pc21;
+    PC22 = -pc22;
+    fits_modify (&buf[0].header, "PC001001", "%le", 1, PC11);
+    fits_modify (&buf[0].header, "PC001002", "%le", 1, PC12);
+    fits_modify (&buf[0].header, "PC002001", "%le", 1, PC21);
+    fits_modify (&buf[0].header, "PC002002", "%le", 1, PC22);
+
+    free (in_buff);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[2], "FLIPY")) {
+    fits_print  (&buf[0].header, "HISTORY", "%S", 1, "WARNING: rotated image!");
+    fits_create_matrix (&buf[0].header, &buf[0].matrix);
+    out_buff = (float *)buf[0].matrix.buffer;
+    for (j = NY - 1; j > -1; j--) {
+      for (i = 0; i < NX; i++, out_buff++) {
+	*out_buff = in_buff[i + j*NX];
+      }
+    }
+    /* fix reference pixel */
+    fits_scan (&buf[0].header, "CRPIX1", "%lf", 1, &Xo);
+    fits_scan (&buf[0].header, "CRPIX2", "%lf", 1, &Yo);
+    X1 = Xo;
+    Y1 = NY - Yo;
+    fits_modify (&buf[0].header, "CRPIX1", "%lf", 1, X1);
+    fits_modify (&buf[0].header, "CRPIX2", "%lf", 1, Y1);
+    
+    /* fix rotate matrix */
+    fits_scan (&buf[0].header, "PC001001", "%lf", 1, &pc11);
+    fits_scan (&buf[0].header, "PC001002", "%lf", 1, &pc12);
+    fits_scan (&buf[0].header, "PC002001", "%lf", 1, &pc21);
+    fits_scan (&buf[0].header, "PC002002", "%lf", 1, &pc22);
+    PC11 = pc11;
+    PC12 = -pc12;
+    PC21 = pc21;
+    PC22 = -pc22;
+    fits_modify (&buf[0].header, "PC001001", "%le", 1, PC11);
+    fits_modify (&buf[0].header, "PC001002", "%le", 1, PC12);
+    fits_modify (&buf[0].header, "PC002001", "%le", 1, PC21);
+    fits_modify (&buf[0].header, "PC002002", "%le", 1, PC22);
+
+    free (in_buff);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[2], "FLIPX")) {
+    fits_print  (&buf[0].header, "HISTORY", "%S", 1, "WARNING: rotated image!");
+    fits_create_matrix (&buf[0].header, &buf[0].matrix);
+    out_buff = (float *)buf[0].matrix.buffer;
+    for (j = 0; j < NY; j++) {
+      for (i = NX - 1; i > -1; i--, out_buff++) {
+	*out_buff = in_buff[i + j*NX];
+      }
+    }
+    /* fix reference pixel */
+    fits_scan (&buf[0].header, "CRPIX1", "%lf", 1, &Xo);
+    fits_scan (&buf[0].header, "CRPIX2", "%lf", 1, &Yo);
+    X1 = NX - Xo;
+    Y1 = Yo;
+    fits_modify (&buf[0].header, "CRPIX1", "%lf", 1, X1);
+    fits_modify (&buf[0].header, "CRPIX2", "%lf", 1, Y1);
+    
+    /* fix rotate matrix */
+    fits_scan (&buf[0].header, "PC001001", "%lf", 1, &pc11);
+    fits_scan (&buf[0].header, "PC001002", "%lf", 1, &pc12);
+    fits_scan (&buf[0].header, "PC002001", "%lf", 1, &pc21);
+    fits_scan (&buf[0].header, "PC002002", "%lf", 1, &pc22);
+    PC11 = -pc11;
+    PC12 = pc12;
+    PC21 = -pc21;
+    PC22 = pc22;
+    fits_modify (&buf[0].header, "PC001001", "%le", 1, PC11);
+    fits_modify (&buf[0].header, "PC001002", "%le", 1, PC12);
+    fits_modify (&buf[0].header, "PC002001", "%le", 1, PC21);
+    fits_modify (&buf[0].header, "PC002002", "%le", 1, PC22);
+
+    free (in_buff);
+    return (TRUE);
+  }
+
+  angle = atof (argv[2]);
+  CosAngle = cos (angle*RAD_DEG);
+  SinAngle = sin (angle*RAD_DEG);
+  
+  fprintf (stderr, "rotating: %f %f %f\n", angle, CosAngle, SinAngle);
+
+  Lx = NX*fabs(CosAngle) + NY*fabs(SinAngle);
+  Ly = NX*fabs(SinAngle) + NY*fabs(CosAngle);
+  dX = MAX(0,NY*SinAngle);
+  dY = MAX(0,-NX*SinAngle);
+  /*
+  fprintf (stderr, "%f %f  -->  ", Xo, Yo);
+  X1 = Xo*CosAngle - Yo*SinAngle + dX;
+  Y1 =  Xo*SinAngle + Yo*CosAngle + dY;
+  fprintf (stderr, "%f %f\n", X1, Y1);
+  */
+
+  /* fix reference pixel */
+  fits_scan (&buf[0].header, "CRPIX1", "%lf", 1, &Xo);
+  fits_scan (&buf[0].header, "CRPIX2", "%lf", 1, &Yo);
+  /*
+  X1 = (Xo - dX)*CosAngle - (Yo - dY)*SinAngle;
+  Y1 = (dX - Xo)*SinAngle + (Yo - dY)*CosAngle;
+  */
+  X1 = Xo*CosAngle - Yo*SinAngle + dX;
+  Y1 =  Xo*SinAngle + Yo*CosAngle + dY;
+  fits_modify (&buf[0].header, "CRPIX1", "%lf", 1, X1);
+  fits_modify (&buf[0].header, "CRPIX2", "%lf", 1, Y1);
+
+  /* fix rotate matrix */
+  fits_scan (&buf[0].header, "PC001001", "%lf", 1, &pc11);
+  fits_scan (&buf[0].header, "PC001002", "%lf", 1, &pc12);
+  fits_scan (&buf[0].header, "PC002001", "%lf", 1, &pc21);
+  fits_scan (&buf[0].header, "PC002002", "%lf", 1, &pc22);
+  PC11 = pc11*CosAngle - pc21*SinAngle;
+  PC12 = pc12*CosAngle - pc22*SinAngle;
+  PC21 = pc21*CosAngle + pc11*SinAngle;
+  PC22 = pc22*CosAngle + pc12*SinAngle;
+  fits_modify (&buf[0].header, "PC001001", "%le", 1, PC11);
+  fits_modify (&buf[0].header, "PC001002", "%le", 1, PC12);
+  fits_modify (&buf[0].header, "PC002001", "%le", 1, PC21);
+  fits_modify (&buf[0].header, "PC002002", "%le", 1, PC22);
+
+  buf[0].header.Naxis[0] = Lx;
+  buf[0].header.Naxis[1] = Ly;
+  fits_modify (&buf[0].header, "NAXIS1", "%d", 1, Lx);
+  fits_modify (&buf[0].header, "NAXIS2", "%d", 1, Ly);
+  fits_create_matrix (&buf[0].header, &buf[0].matrix);
+  fits_print  (&buf[0].header, "HISTORY", "%S", 1, "WARNING: rotated image!");
+  out_buff = (float *)buf[0].matrix.buffer;
+  for (j = 0; j < Ly; j++) {
+    for (i = 0; i < Lx; i++, out_buff++) {
+
+      x = (i - dX)*CosAngle + (j - dY)*SinAngle;
+      y = (dX - i)*SinAngle + (j - dY)*CosAngle;
+      X = (int) x;
+      Y = (int) y;
+
+      if (X < 0) continue;
+      if (X >= NX - 1) continue;
+      if (Y < 0) continue;
+      if (Y >= NY - 1) continue;
+
+      c = &in_buff[X * NX*Y];
+      fx = x - X;
+      fy = y - Y;
+      *out_buff = (c[0]*(1-fx) + c[1]*fx)*(1-fy) + (c[NX+1]*fx + c[NX]*(1-fx))*fy;
+    }
+  }
+  free (in_buff);
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/save.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/save.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/save.c	(revision 12606)
@@ -0,0 +1,44 @@
+# include "data.h"
+
+int save (int argc, char **argv) {
+  
+  int N, n, ISCEL;
+  char buffer[512], buffer2[512];
+  int Ximage, Nimage;
+  
+  Nimage = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Nimage = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (&Ximage, &Nimage)) return (FALSE);
+
+  ISCEL = FALSE;
+  if (N = get_argument (argc, argv, "-c")) {
+    remove_argument (N, &argc, argv);
+    ISCEL = TRUE;
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: save (overlay) <filename> [-c]\n");
+    fprintf (stderr, "  -c: write contour in celestial coords\n");
+    return (FALSE);
+  }
+
+  if (!SelectOverlay (argv[1], &n)) 
+    return (FALSE);
+
+  sprintf (buffer, "FILE: %d %s", n, argv[2]);
+  sprintf (buffer2, "NBYTES: %8d", strlen(buffer));
+  
+  if (ISCEL) 
+    write (Ximage, "CSVE", 4); /* force Ximage to look for the incoming image */
+  else 
+    write (Ximage, "SAVE", 4); /* force Ximage to look for the incoming image */
+  write (Ximage, buffer2, 16);
+  write (Ximage, buffer, strlen(buffer));
+  
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/section.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/section.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/section.c	(revision 12606)
@@ -0,0 +1,67 @@
+# include "data.h"
+
+int section (int argc, char **argv) {
+  
+  int N, List;
+  char buffer[65], buffer2[65];
+  Graphdata graphmode;
+  int Ngraph, Xgraph;
+
+  List = FALSE;
+  if (N = get_argument (argc, argv, "-list")) {
+    remove_argument (N, &argc, argv);
+    List = TRUE;
+  }
+
+  Ngraph = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Ngraph = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraph (&graphmode, &Xgraph, &Ngraph)) return (FALSE);
+
+  if (argc == 1) {
+    /* list section */
+    write (Xgraph, "LSEC", 4);
+    sprintf (buffer, "* %s", argv[1]);
+    sprintf (buffer2, "NBYTES: %6d ", strlen (buffer));
+    write (Xgraph, buffer2, 16);
+    write (Xgraph, buffer, strlen (buffer));
+    fprintf (stderr, "USAGE: section name [x y dx dy]\n");
+    return (TRUE);
+  } 
+  
+  if (argc == 2) {
+    /* set section */
+    if (List) {
+      write (Xgraph, "LSEC", 4);
+    } else {
+      write (Xgraph, "SSEC", 4);
+    }
+    sprintf (buffer, "%s", argv[1]);
+    sprintf (buffer2, "NBYTES: %6d ", strlen (buffer));
+    write (Xgraph, buffer2, 16);
+    write (Xgraph, buffer, strlen (buffer));
+    return (TRUE);
+  } 
+  
+  if (argc == 6) {
+    /* define section */
+    write (Xgraph, "DSEC", 4);
+    snprintf (buffer, 65, "%s %6.3f %6.3f %6.3f %6.3f", argv[1], atof (argv[2]), atof (argv[3]), atof (argv[4]), atof (argv[5]));
+    snprintf (buffer2, 65, "NBYTES: %6d ", strlen (buffer));
+    write (Xgraph, buffer2, 16);
+    write (Xgraph, buffer, strlen (buffer));
+    return (TRUE);
+  }
+      
+  fprintf (stderr, "USAGE: section name [x y dx dy]\n");
+  return (FALSE);
+  
+}
+
+    /* should do some range checking on x y dx dy
+       should be between 0.0 and 1.0, precision of 0.001
+       is sufficient
+    */
Index: /tags/start/Ohana/src/opihi/cmd.data/select.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/select.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/select.c	(revision 12606)
@@ -0,0 +1,44 @@
+# include "data.h"
+
+int vect_select (int argc, char **argv) {
+  
+  int  i, size;
+  char *out;
+  Vector *in1, *in2, *tvec, *ovec;
+
+  out = NULL;
+  in1 = in2 = ovec = tvec = NULL;
+
+  /** check basic syntax **/
+  if ((argc != 8) || strcmp(argv[2], "=") || strcmp (argv[4], "if") || strcmp (argv[6], "else")) {
+    fprintf (stderr, "SYNTAX: select vec = vec if (logic expression) else vec\n");
+    return (FALSE);
+  }
+  if ((in1  = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((in2  = SelectVector (argv[7], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((ovec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  out = dvomath (argc - 5, &argv[5], &size, 1);
+  if (out == NULL) {
+    print_error ();
+    goto error;
+  }
+  if ((tvec = SelectVector (out, OLDVECTOR, TRUE)) == NULL) goto error;
+  /* check size of in1, in2, tvec: must match */
+
+  REALLOCATE (ovec[0].elements, float, MAX (tvec[0].Nelements, 1));
+  for (i = 0; i < tvec[0].Nelements; i++) {
+    ovec[0].elements[i] = tvec[0].elements[i] ? in1[0].elements[i] : in2[0].elements[i];
+  }
+  ovec[0].Nelements = tvec[0].Nelements;
+  REALLOCATE (ovec[0].elements, float, MAX (ovec[0].Nelements, 1));
+  
+  DeleteVector (tvec);
+  return (TRUE);
+
+ error:
+  DeleteVector (tvec);
+  DeleteVector (ovec);
+  DeleteNamedVector (out);
+  return (FALSE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/set.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/set.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/set.c	(revision 12606)
@@ -0,0 +1,42 @@
+# include "data.h"
+
+int set (int argc, char **argv) {
+  
+  int size;
+  char *out;
+
+  /** check basic form for line **/
+  if ((argc < 3) || strcmp(argv[2], "=")) {
+    fprintf (stderr, "%s = (matrix expression)\n", argv[0]);
+    return (FALSE);
+  }
+
+  out = dvomath (argc - 3, &argv[3], &size, -1);
+  if (out == NULL) {
+    print_error ();
+    return (FALSE);
+  }
+  
+  switch (size) {
+    case 0:
+      set_str_variable (argv[1], out);
+      break;
+
+    case 1:
+      if (!MoveNamedVector (argv[1], out)) {
+	DeleteNamedVector (out);
+	fprintf (stderr, "invalid output vector name\n");
+	return (FALSE);
+      }
+      break;
+  
+    case 2:
+      if (!MoveNamedBuffer (argv[1], out)) {
+	DeleteNamedBuffer (out);
+	fprintf (stderr, "invalid output matrix name\n");
+	return (FALSE);
+      }
+      break;
+  }
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/shift.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/shift.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/shift.c	(revision 12606)
@@ -0,0 +1,121 @@
+# include "data.h"
+
+int shift (int argc, char **argv) {
+ 
+  int i, j, N, ROLL;
+  int nx, ny, dx, dy, DXin, DXot, DYin, DYot;
+  float *Vin, *Vot;
+  double Dx, Dy, fdx, fdy;
+  Buffer *buf;
+
+  ROLL = FALSE;
+  if (N = get_argument (argc, argv, "-roll")) {
+    remove_argument (N, &argc, argv);
+    ROLL = TRUE;
+  }
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: shift <buffer> dx dy\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  Dx = -atof (argv[2]);
+  Dy = -atof (argv[3]);
+
+  dx = Dx;
+  dy = Dy;
+  fdx = Dx - dx;
+  fdy = Dy - dy;
+  if (fdx < -0.001) {dx -= 1; fdx += 1;}
+  if (fdy < -0.001) {dy -= 1; fdy += 1;}
+
+  nx = buf[0].matrix.Naxis[0];
+  ny = buf[0].matrix.Naxis[1];
+
+  if ((dx > buf[0].matrix.Naxis[0]) || (dy > buf[0].matrix.Naxis[1])) {
+    fprintf (stderr, "shifting data out of image\n");
+    return (FALSE);
+  }
+  
+  if (dx < 0) {
+    DXin = 0;
+    DXot = -dx;
+  } else {
+    DXin = dx;
+    DXot = 0;
+  }
+  if (dy < 0) {
+    DYin = 0;
+    DYot = -dy;
+  } else {
+    DYin = dy;
+    DYot = 0;
+  }
+  
+  if ((dy > 0) || ((dy == 0) && (dx > 0))) {
+    for (j = 0; j < ny - fabs(dy); j++) {
+      Vin = (float *)(buf[0].matrix.buffer) + (j + DYin)*nx + DXin;  
+      Vot = (float *)(buf[0].matrix.buffer) + (j + DYot)*nx + DXot; 
+      for (i = 0; i < nx - fabs(dx); i++, Vin++, Vot++) {
+	*Vot = *Vin;
+      }
+      if (dx < 0) 
+	Vot = (float *)(buf[0].matrix.buffer) + (j + DYot)*nx; 
+      for (i = 0; i < fabs(dx); i++, Vot++) {
+	*Vot = 0.0;
+      }	
+    }
+    Vot = (float *)(buf[0].matrix.buffer) + nx*(ny - abs(dy));
+    for (j = 0; j < nx * fabs(dy); j++, Vot++) {
+      *Vot = 0.0;
+    }   
+  } else {
+    for (j = ny - fabs(dy) - 1; j >= 0; j--) {
+      Vin = (float *)(buf[0].matrix.buffer) + (j + DYin)*nx + DXin + nx - abs(dx) - 1; 
+      Vot = (float *)(buf[0].matrix.buffer) + (j + DYot)*nx + DXot + nx - abs(dx) - 1; 
+      for (i = 0; i < nx - fabs(dx); i++, Vin--, Vot--) {
+	*Vot = *Vin;
+      }
+      if (dx < 0) 
+	Vot = (float *)(buf[0].matrix.buffer) + (j + DYot)*nx; 
+      for (i = 0; i < fabs(dx); i++, Vot++) {
+	*Vot = 0.0;
+      }	
+    }
+    Vot = (float *)(buf[0].matrix.buffer);
+    for (j = 0; j < nx * fabs(dy); j++, Vot++) {
+      *Vot = 0.0;
+    }
+  } 
+
+  fprintf (stderr, "%f %f\n", fdx, fdy);
+  if ((fdx > 0) || (fdy > 0)) {
+    double f00, f01, f10, f11;
+    float value;
+
+    f00 = (1-fdx)*(1-fdy);
+    f01 =    fdx *(1-fdy);
+    f10 = (1-fdx)*   fdy;
+    f11 =    fdx *   fdy;
+
+    Vin = (float *)buf[0].matrix.buffer;
+    Vot = (float *)buf[0].matrix.buffer;
+    for (j = 0; j < ny - 1; j++) {
+      for (i = 0; i < nx - 1; i++, Vin++, Vot++) {
+	value  = Vin[   0] * f00;
+	value += Vin[   1] * f01;
+	value += Vin[ny  ] * f10;
+	value += Vin[ny+1] * f11;
+	*Vot = value;
+      }
+      Vin ++;
+      Vot ++;
+    }
+  }   
+
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/sort.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/sort.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/sort.c	(revision 12606)
@@ -0,0 +1,62 @@
+# include "data.h"
+
+int sort_vectors (int argc, char **argv) {
+  
+  int i, j, Nvec, Nval;
+  float *temp, *index, *T, *V, *I;
+  Vector **vec;
+
+  if (argc < 2) {
+    fprintf (stderr, "USAGE: sort (vector) [vectors ...] \n");
+    fprintf (stderr, "  first vector is sort key for others\n");
+    return (FALSE);
+  }
+
+  Nvec = (argc - 1);
+  ALLOCATE (vec, Vector *, Nvec);
+
+  /* find vectors and check sizes */
+  for (i = 0; i < Nvec; i++) {
+    if ((vec[i] = SelectVector (argv[i + 1], OLDVECTOR, FALSE)) == NULL) {
+      fprintf (stderr, "USAGE: sort vector vector ...\n");
+      free (vec);
+      return (FALSE);    
+    }
+    if (i == 0) {
+      Nval = vec[i][0].Nelements;
+    } else {
+      if (Nval != vec[i][0].Nelements) {
+	free (vec);
+	fprintf (stderr, "vectors must all be same length\n");
+	return (FALSE);
+      }
+    }
+  }
+  
+  /* create index (use float to use sortpair) */
+  ALLOCATE (index, float, Nval);
+  for (i = 0; i < Nval; i++) index[i] = i;
+
+  /* sort key & index */
+  fsortpair (vec[0][0].elements, index, Nval);
+
+  ALLOCATE (temp, float, Nval);
+  for (i = 1; i < Nvec; i++) {
+    T = temp;
+    V = vec[i][0].elements;
+    I = index;
+    for (j = 0; j < Nval; j++, T++, I++) {
+      *T = V[(int)(*I)];
+    }
+    /* swap .elements (== V) and temp */ 
+    vec[i][0].elements = temp;
+    temp = V;
+  }
+  free (temp);
+  free (vec);
+
+  return (TRUE);
+
+}
+
+
Index: /tags/start/Ohana/src/opihi/cmd.data/spline_apply.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/spline_apply.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/spline_apply.c	(revision 12606)
@@ -0,0 +1,100 @@
+# include "data.h"
+
+void spline (float *x, float *y, int N, float *y2);
+float splint (float *x, float *y, float *y2, int N, float X);
+
+int spline_apply (int argc, char **argv) {
+  
+  int i, j, I, J;
+  int nx, ny, Nx, Ny, xdir;
+  float rx, ry, x, y;
+  float *Tx1, *Tx2, *Txc, *Ty1, *Ty2, *Tyc, *V, *V1, *V2;
+  Buffer *out, *y1, *y2;
+
+  if (argc != 7) {
+    fprintf (stderr, "USAGE: spline_apply <Y> <Y2> <out> (x/y) Nx Ny\n");
+    return (FALSE);
+  }
+
+  if ((y1  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((y2  = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out = SelectBuffer (argv[3], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  xdir = FALSE;
+  if (!strcmp (argv[4], "x")) xdir = TRUE; 
+
+  nx = atoi (argv[5]);
+  ny = atoi (argv[6]);
+
+  Nx = y1[0].matrix.Naxis[0];
+  Ny = y1[0].matrix.Naxis[1];
+
+  rx = Nx / (float) nx;
+  ry = Ny / (float) ny;
+
+  /* create an output matrix buffer with desired nx, ny */
+  fits_free_matrix (&out[0].matrix);
+  fits_free_header (&out[0].header);
+
+  out[0].bitpix = y1[0].bitpix;
+  out[0].unsign = y1[0].unsign;
+  out[0].bscale = y1[0].bscale;
+  out[0].bzero  = y1[0].bzero;
+  fits_copy_header (&y1[0].header, &out[0].header);
+  fits_modify (&out[0].header, "NAXIS1", "%d", 1, nx);
+  fits_modify (&out[0].header, "NAXIS2", "%d", 1, ny);
+
+  out[0].header.Naxis[0] = nx;
+  out[0].header.Naxis[1] = ny;
+  fits_create_matrix (&out[0].header, &out[0].matrix);
+  if ((y1[0].file[0] != '*') && (y1[0].file[0] != '(')) {
+    sprintf (out[0].file, "*%s", y1[0].file);
+  } else {
+    sprintf (out[0].file, "%s", y1[0].file);
+  }
+
+  ALLOCATE (Ty2, float, Ny);
+  ALLOCATE (Ty1, float, Ny);
+  ALLOCATE (Tyc, float, Ny);
+  for (i = 0; i < Ny; i++) { Tyc[i] = i; }
+
+  ALLOCATE (Tx1, float, Nx);
+  ALLOCATE (Tx2, float, Nx);
+  ALLOCATE (Txc, float, Nx);
+  for (i = 0; i < Nx; i++) { Txc[i] = i; }
+
+  V = (float *)(out[0].matrix.buffer);
+
+  for (J = 0; J < ny; J++) {
+    y = J * ry;
+
+    /* construct spline for each element in this row */
+    for (i = 0; i < Nx; i++) {
+      V1 = (float *)(y1[0].matrix.buffer) + i;
+      V2 = (float *)(y2[0].matrix.buffer) + i;
+      for (j = 0; j < Ny; j++, V1+=Nx, V2+=Nx) {
+	Ty1[j] = *V1;
+	Ty2[j] = *V2;
+      }
+      Tx1[i] = splint (Tyc, Ty1, Ty2, Ny, y);
+    }
+    spline (Txc, Tx1, Nx, Tx2);
+
+    /* apply x-dir spline to new image */
+    for (I = 0; I < nx; I++, V++) {
+      x = I * rx;
+      *V = splint (Txc, Tx1, Tx2, Nx, x);
+    }
+  }
+
+  free (Ty1);
+  free (Ty2);
+  free (Tyc);
+  
+  free (Tx1);
+  free (Tx2);
+  free (Txc);
+  
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/spline_construct.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/spline_construct.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/spline_construct.c	(revision 12606)
@@ -0,0 +1,71 @@
+# include "data.h"
+
+int spline_construct (int argc, char **argv) {
+  
+  int i, j, Nx, Ny, xdir;
+  float *Tx, *Ty, *Ty2, *V;
+  Buffer *in, *out;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: spline_construct <in> <out> (x/y)\n");
+    return (FALSE);
+  }
+
+  if ((in  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out = SelectBuffer (argv[2], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  free (out[0].matrix.buffer);
+  free (out[0].header.buffer);
+  if ((in[0].file[0] != '*') && (in[0].file[0] != '(')) {
+    sprintf (out[0].file, "*%s", in[0].file);
+  } else {
+    sprintf (out[0].file, "%s", in[0].file);
+  }
+  out[0].bitpix = in[0].bitpix;
+  out[0].unsign = in[0].unsign;
+  out[0].bscale = in[0].bscale;
+  out[0].bzero  = in[0].bzero;
+  fits_copy_matrix_info (&in[0].matrix, &out[0].matrix);
+  fits_copy_header (&in[0].header, &out[0].header);
+  fits_create_matrix (&out[0].header, &out[0].matrix);
+
+  xdir = FALSE;
+  if (!strcmp (argv[3], "x")) xdir = TRUE; 
+  /* ideally, the resulting image should carry this info (in header?) */
+
+  Nx = in[0].matrix.Naxis[0];
+  Ny = in[0].matrix.Naxis[1];
+
+  ALLOCATE (Ty2, float, Ny);
+  ALLOCATE (Ty, float, Ny);
+  ALLOCATE (Tx, float, Ny);
+
+  /** for now only perform the operation for the ydir splines */
+
+  /* construct coordinate vector */
+  for (j = 0; j < Ny; j++) { Tx[j] = j; }
+  
+  for (i = 0; i < Nx; i++) {
+    
+    /* construct temp vector with values to spline */
+    V = (float *)(in[0].matrix.buffer) + i;
+    for (j = 0; j < Ny; j++, V+=Nx) {
+      Ty[j] = *V;
+    }
+  
+    spline (Tx, Ty, Ny, Ty2);
+  
+    /* copy derivatives to output buffer */
+    V = (float *)(out[0].matrix.buffer) + i;
+    for (j = 0; j < Ny; j++, V+=Nx) {
+      *V = Ty2[j];
+    }
+  }
+
+  free (Tx);
+  free (Ty);
+  free (Ty2);
+  
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/stats.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/stats.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/stats.c	(revision 12606)
@@ -0,0 +1,111 @@
+# include "data.h"
+
+int stats (int argc, char **argv) {
+  
+  int i, j, Nmode, Imode;
+  double Npix, N1, N2, max, min, range, median, mode, IgnoreValue;
+  float *V;
+  int sx, sy, nx, ny, *hist, Nhist, bin;
+  int Ignore, Quiet, N;
+  Buffer *buf;
+
+  Ignore = FALSE;
+  if (N = get_argument (argc, argv, "-ignore")) {
+    Ignore = TRUE;
+    remove_argument (N, &argc, argv);
+    IgnoreValue = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Quiet = FALSE;
+  if (N = get_argument (argc, argv, "-q")) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-quiet")) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 6) {
+    fprintf (stderr, "USAGE: stats <buffer> sx sy nx ny\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  sx = strcmp (argv[2], "-") ? atof (argv[2]) : 0;
+  sy = strcmp (argv[3], "-") ? atof (argv[3]) : 0;
+  nx = strcmp (argv[4], "-") ? atof (argv[4]) : buf[0].matrix.Naxis[0];
+  ny = strcmp (argv[5], "-") ? atof (argv[5]) : buf[0].matrix.Naxis[1];
+
+  Npix = N1 = N2 = 0;
+  if ((sx < 0) || (sy < 0) || 
+      (sx+nx > buf[0].matrix.Naxis[0]) || 
+      (sy+ny > buf[0].matrix.Naxis[1])) {
+    fprintf (stderr, "region out of range\n");
+    return (FALSE);
+  }
+
+  max = min = *((float *)(buf[0].matrix.buffer) + sy*buf[0].matrix.Naxis[0] + sx);
+  for (j = sy; j < sy + ny; j++) {
+    V = (float *)(buf[0].matrix.buffer) + j*buf[0].matrix.Naxis[0] + sx; 
+    for (i = 0; i < nx; i++, V++) {
+      if (Ignore && (fabs (*V - IgnoreValue) < 1e-8)) continue;
+      N1 += *V;
+      N2 += (*V)*(*V);
+      Npix += 1.0;
+      max = MAX (max, *V);
+      min = MIN (min, *V);
+    }
+  }
+  N1 = N1 / Npix;
+
+  /* calculate mode, median */
+  median = mode = 0.5*(max + min);
+  if (range != 0) {
+    range = 0xffff / (max - min);
+    ALLOCATE (hist, int, 0x10000);
+    bzero (hist, 0x10000*sizeof(int));
+    for (j = sy; j < sy + ny; j++) {
+      V = (float *)(buf[0].matrix.buffer) + j*buf[0].matrix.Naxis[0] + sx; 
+      for (i = 0; i < nx; i++, V++) {
+	if (Ignore && (fabs (*V - IgnoreValue) < 1e-8)) continue;
+	bin = MIN (MAX (0, (*V - min) * range), 0xffff);
+	hist[bin] ++;
+      }
+    }
+    Nhist = 0;
+    for (i = 0; (i < 0xffff) && (Nhist < 0.5*Npix); i++) 
+      Nhist += hist[i];
+    median = i / range + min;
+    Nmode = hist[0];
+    Imode = 0;
+    for (i = 1; i < 0x10000; i++) {
+      if (hist[i] > Nmode) {
+	Nmode = hist[i];
+	Imode = i;
+      }
+    }
+    mode = Imode / range + min;
+    free (hist);
+  }  
+  
+  if (!Quiet) {
+    fprintf (GetOutfile(), "  mean    stdev    min     max   median   Npix   Total\n");
+    fprintf (GetOutfile(), "%7.4g %7.4g %7.4g %7.4g %7.4g %7.0f %7.4g\n", N1, sqrt (N2/Npix - N1*N1), 
+	     min, max, median, Npix, Npix*N1);
+  }
+
+  set_variable ("MIN",    min);
+  set_variable ("MAX",    max);
+  set_variable ("MEDIAN", median);
+  set_variable ("MEAN",   N1);
+  set_variable ("MODE",   mode);
+  set_variable ("TOTAL",  N1*Npix);
+  set_variable ("NPIX",   Npix);
+  set_variable ("SIGMA",  sqrt (N2/Npix - N1*N1));
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/style.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/style.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/style.c	(revision 12606)
@@ -0,0 +1,83 @@
+# include "data.h"
+# define NCOLORS 9
+static char colors[9][10] = {"black", "white", "red", "orange", "yellow", "green", "blue", "indigo", "violet"};
+
+int style (int argc, char **argv) {
+  
+  int i, N, Ngraph;
+  Graphdata graphmode;
+
+  Ngraph = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Ngraph = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);
+
+  if (argc == 1) {
+    fprintf (stderr, "current style (%d): -x %d -c %s -pt %d -lt %d -lw %f -sz %f\n", Ngraph,
+	     graphmode.style, colors[graphmode.color], graphmode.ptype, 
+	     graphmode.ltype, graphmode.lweight,
+	     graphmode.size);
+    return (TRUE);
+  }
+
+  if (N = get_argument (argc, argv, "-lt")) {
+    remove_argument (N, &argc, argv);
+    graphmode.ltype = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (N = get_argument (argc, argv, "-lw")) {
+    remove_argument (N, &argc, argv);
+    graphmode.lweight = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (N = get_argument (argc, argv, "-pt")) {
+    remove_argument (N, &argc, argv);
+    graphmode.ptype = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (N = get_argument (argc, argv, "+eb")) {
+    remove_argument (N, &argc, argv);
+    graphmode.ebar = TRUE;
+  }
+
+  if (N = get_argument (argc, argv, "-eb")) {
+    remove_argument (N, &argc, argv);
+    graphmode.ebar = FALSE;
+  }
+
+  if (N = get_argument (argc, argv, "-sz")) {
+    remove_argument (N, &argc, argv);
+    graphmode.size = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (N = get_argument (argc, argv, "-c")) {
+    remove_argument (N, &argc, argv);
+    graphmode.color = GetColor (argv[N]);
+    if (graphmode.color == -1) return (FALSE);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (N = get_argument (argc, argv, "-x")) {
+    remove_argument (N, &argc, argv);
+    graphmode.style = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  SetGraph (graphmode);
+
+  if (argc > 1) {
+    fprintf (stderr, "USAGE: style [-n Ngraph] [-x plot style] [-c color] [-pt point type] [-lt line type] [-lw line width] [-sz size]\n");
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/subraster.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/subraster.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/subraster.c	(revision 12606)
@@ -0,0 +1,86 @@
+# include "data.h"
+
+int subraster (int argc, char **argv) {
+  
+  int i, j;
+  float *Vin, *Vout;
+  int sx, sy, nx, ny;
+  int Sx, Sy, Nx, Ny;
+  int NX, NY;
+  Buffer *ibuf, *obuf;
+
+  if (argc != 11) {
+    fprintf (stderr, "USAGE: extract <from> <to> sx sy nx ny Sx Sy Nx Ny\n");
+    return (FALSE);
+  }
+
+  if ((ibuf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  NX = ibuf[0].matrix.Naxis[0];
+  NY = ibuf[0].matrix.Naxis[1];
+
+  sx = atof (argv[3]);
+  sy = atof (argv[4]);
+  nx = atof (argv[5]);
+  ny = atof (argv[6]);
+
+  Sx = atof (argv[7]);
+  Sy = atof (argv[8]);
+  Nx = atof (argv[9]);
+  Ny = atof (argv[10]);
+
+  if ((Sy + ny > Ny) || (Sx + nx > Nx)) {
+    fprintf (stderr, "mismatch between source and dest regions\n");
+    fprintf (stderr, "%d + %d > %d or %d + %d > %d\n", Sy, ny, Ny, Sx, nx, Nx);
+    return (FALSE);
+  }
+
+  /* region is not on first image */
+  if ((sx + nx < 0) || (sy + ny < 0) || 
+      (sx > ibuf[0].matrix.Naxis[0]) || 
+      (sy > ibuf[0].matrix.Naxis[1])) {
+    fprintf (stderr, "region outside of source image\n");
+    return (FALSE);
+  }
+
+  if ((Sx + nx > Nx) || (Sy + ny > Ny)) {
+    fprintf (stderr, "source region larger than dest region\n");
+    return (FALSE);
+  }
+  if ((Sx < 0) || (Sy < 0)) {
+    fprintf (stderr, "dest region out of range\n");
+    return (FALSE);
+  }
+
+  if ((obuf = SelectBuffer (argv[2], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  fits_free_matrix (&obuf[0].matrix);
+  fits_free_header (&obuf[0].header);
+
+  obuf[0].bitpix = ibuf[0].bitpix;
+  obuf[0].unsign = ibuf[0].unsign;
+  obuf[0].bscale = ibuf[0].bscale;
+  obuf[0].bzero  = ibuf[0].bzero;
+  /* strcpy (obuf[0].name, ibuf[0].name); */
+  strcpy (obuf[0].file, ibuf[0].file);
+  fits_copy_header (&ibuf[0].header, &obuf[0].header);
+  fits_modify (&obuf[0].header, "NAXIS1", "%d", 1, Nx);
+  fits_modify (&obuf[0].header, "NAXIS2", "%d", 1, Ny);
+  obuf[0].header.Naxis[0] = Nx;
+  obuf[0].header.Naxis[1] = Ny;
+  fits_create_matrix (&obuf[0].header, &obuf[0].matrix);
+
+  for (j = 0; j < ny; j++) {
+    if (j + sy < 0) continue;
+    if (j + sy >= NY) continue;
+    Vin = (float *)(ibuf[0].matrix.buffer) + (j + sy)*ibuf[0].matrix.Naxis[0] + sx;  
+    Vout = (float *)(obuf[0].matrix.buffer) + (j + Sy)*obuf[0].matrix.Naxis[0] + Sx;   
+    for (i = 0; i < nx; i++, Vin++, Vout++) {
+      if (i + sx < 0) continue;
+      if (i + sx >= NX) continue;
+      *Vout = *Vin;
+    }
+  }
+
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/subset.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/subset.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/subset.c	(revision 12606)
@@ -0,0 +1,47 @@
+# include "data.h"
+
+int subset (int argc, char **argv) {
+  
+  char *out;
+  int  i, j, size;
+  Vector *ivec, *ovec, *tvec;
+
+  out = NULL;
+  ivec = ovec = tvec = NULL;
+
+  if ((argc < 6) || strcmp(argv[2], "=") || strcmp (argv[4], "if")) {
+    fprintf (stderr, "SYNTAX: subset vec = vec if (logic expression)\n");
+    return (FALSE);
+  }
+
+  if ((ovec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) goto error;
+  if ((ivec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) goto error;
+
+  out = dvomath (argc - 5, &argv[5], &size, 1);
+  if (out == NULL) {
+    print_error ();
+    goto error;
+  }
+  if ((tvec = SelectVector (out, OLDVECTOR, TRUE)) == NULL) goto error;
+  /* check size of ivec, tvec: must match */
+
+  REALLOCATE (ovec[0].elements, float, MAX (tvec[0].Nelements, 1));
+  for (j = i = 0; i < tvec[0].Nelements; i++) {
+    if (tvec[0].elements[i]) {
+      ovec[0].elements[j] = ivec[0].elements[i];
+      j++;
+    }
+  }
+  ovec[0].Nelements = j;
+  REALLOCATE (ovec[0].elements, float, MAX (ovec[0].Nelements, 1));
+
+  DeleteVector (tvec);
+  return (TRUE);
+
+ error:
+  DeleteVector (tvec);
+  DeleteVector (ovec);
+  DeleteNamedVector (out);
+  return (FALSE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/svd.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/svd.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/svd.c	(revision 12606)
@@ -0,0 +1,71 @@
+# include "data.h"
+
+int svd (int argc, char **argv) {
+  
+  int i, Nx, Ny, status;
+  float *in, *out, *A, *U, *W, *V;
+  Vector *Vw;
+  Buffer *Ma, *Mu, *Mv;
+
+  if (argc != 6) goto usage;
+  if (strcmp (argv[2], "=")) goto usage;
+
+  if ((Ma = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((Mu = SelectBuffer (argv[3], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((Vw = SelectVector (argv[4], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((Mv = SelectBuffer (argv[5], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  Nx = Ma[0].header.Naxis[0];
+  Ny = Ma[0].header.Naxis[1];
+
+  /* U is Nx, Ny */
+  fits_free_matrix (&Mu[0].matrix);
+  fits_free_header (&Mu[0].header);
+  Mu[0].bitpix = Ma[0].bitpix;
+  Mu[0].unsign = Ma[0].unsign;
+  Mu[0].bscale = Ma[0].bscale;
+  Mu[0].bzero  = Ma[0].bzero;
+  fits_copy_header (&Ma[0].header, &Mu[0].header);
+  fits_create_matrix (&Mu[0].header, &Mu[0].matrix);
+  
+  /* V is Nx, Nx */
+  fits_free_matrix (&Mv[0].matrix);
+  fits_free_header (&Mv[0].header);
+  Mv[0].bitpix = Ma[0].bitpix;
+  Mv[0].unsign = Ma[0].unsign;
+  Mv[0].bscale = Ma[0].bscale;
+  Mv[0].bzero  = Ma[0].bzero;
+  fits_copy_header (&Ma[0].header, &Mv[0].header);
+  fits_modify (&Mv[0].header, "NAXIS2", "%d", 1, Nx);
+  Mv[0].header.Naxis[1] = Nx;
+  fits_create_matrix (&Mv[0].header, &Mv[0].matrix);
+
+  /* w is Nx */
+  Vw[0].Nelements = Nx;
+  REALLOCATE (Vw[0].elements, float, Nx);
+
+  /* pointers to the various arrays */
+  A = (float *) Ma[0].matrix.buffer;
+  U = (float *) Mu[0].matrix.buffer;
+  W = (float *) Vw[0].elements;
+  V = (float *) Mv[0].matrix.buffer;
+
+  /* copy A to U (svdcmp replaces A with U) */
+  in  = A;
+  out = U;
+  for (i = 0; i < Nx*Ny; i++, in++, out++) *out = *in;
+  /* use a bcopy instead? */
+
+  status = svdcmp (U, W, V, Nx, Ny);
+  if (!status) {
+    fprintf (stderr, "error running svdcmp\n");
+    return (FALSE);
+  }
+  return (TRUE);
+
+ usage:
+  fprintf (stderr, "USAGE: svd A = U w Vt\n");
+  return (FALSE);
+  
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/swapbytes.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/swapbytes.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/swapbytes.c	(revision 12606)
@@ -0,0 +1,29 @@
+# include "data.h"
+
+int swapbytes (int argc, char **argv) {
+  
+  int i, nx, ny;
+  char *V, tmp;
+  Buffer *buf;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: swapbytes <buffer>\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  nx = buf[0].matrix.Naxis[0];
+  ny = buf[0].matrix.Naxis[1];
+
+  fprintf (stderr, "npix: %d\n", nx*ny);
+
+  V = buf[0].matrix.buffer;
+  for (i = 0; i < nx*ny; i++, V+=4) {
+    tmp = V[0]; V[0] = V[3]; V[3] = tmp;
+    tmp = V[1]; V[1] = V[2]; V[2] = tmp;
+  }
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/teststats.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/teststats.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/teststats.c	(revision 12606)
@@ -0,0 +1,117 @@
+# include "data.h"
+
+int teststats (int argc, char **argv) {
+  
+  int i, N;
+  double max, min, sum, var, dvar, mean, stdev;
+  float *X, IgnoreValue;
+  int Ignore, Quiet;
+
+  int *Nval, bin, Nmode, Nmed;
+  double dx, mode, median;
+  Vector *vec;
+
+  Ignore = FALSE;
+  if (N = get_argument (argc, argv, "-ignore")) {
+    Ignore = TRUE;
+    remove_argument (N, &argc, argv);
+    IgnoreValue = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Quiet = FALSE;
+  if (N = get_argument (argc, argv, "-q")) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-quiet")) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: teststats (vector)\n");
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  Mean = Stdev = 0; 
+  /* first pass: measure the sample statistics */
+  for (j = 0; j < 3; j++) {
+    /* calculate mean, npix */
+    X = vec[0].elements;
+    max = min = *X;
+    sum = N = 0;
+    for (i = 0; i < vec[0].Nelements; i++, X++) {
+      if (!finite (*X)) continue;
+      if (Ignore && (*X == IgnoreValue)) continue;
+      if ((j > 0) && (fabs (*X - Mean) > 3*stdev)) continue;
+      sum += *X;
+      N++;
+    }      
+    mean = sum / N;
+    /* calculate stdev */
+    X = vec[0].elements;
+    var = 0;
+    for (i = 0; i < vec[0].Nelements; i++, X++) {
+      if (!finite (*X)) continue;
+      if (Ignore && (*X == IgnoreValue)) continue;
+      if ((j > 0) && (fabs (*X - mean) > 3*stdev)) continue;
+      dvar = (*X - mean);
+      var += dvar*dvar;
+    }      
+    stdev = sqrt (var / N);
+    Mean = mean;
+  }
+  mean = Mean;
+  set_variable ("MEAN_C",     mean);
+  set_variable ("SIGMA_C",    stdev);
+
+  /* construct histogram with resolution of 0.1*stdev and range -1000*dx : 1000*dx centered on mean */
+  dx = 0.1*stdev;
+  min = mean - 1000*dx;
+  max = mean + 1000*dx;
+  NVAL = 1 + (int)((max - min) / dx);
+  ALLOCATE (Nval, int, NVAL);
+  bzero (Nval, NVAL*sizeof(int));
+  X = vec[0].elements;
+  for (i = 0; i < vec[0].Nelements; i++, X++) {
+    if (!finite (*X)) continue;
+    if (Ignore && (*X == IgnoreValue)) continue;
+    bin = MAX (0, MIN (NVAL, (*X - min) / dx));
+    Nval[bin] ++;
+  }      
+
+  /* find mode */
+  Nmode = 0;
+  mode = Nval[Nmode];
+  for (i = 0; i < NVAL; i++) {
+    if (mode < Nval[i]) {
+      Nmode = i;
+      mode = Nval[Nmode];
+    }
+  }
+  mode = Nmode * dx + min;
+
+  
+
+  if (!Quiet) {
+    fprintf (stderr, "mean: %f, stdev: %f, min: %f, max: %f, median: %f, mode: %f, Npts: %d\n", 
+	     mean, stdev, min, max, median, mode, N);
+  }
+
+  set_variable ("MIN",      min);
+  set_variable ("MAX",      max);
+  set_variable ("MEDIAN",   median);
+  set_variable ("MODE",     mode);
+  set_variable ("TOTAL",    sum);
+  set_variable ("MEAN",     mean);
+  set_variable ("SIGMA",    stdev);
+
+  set_int_variable ("NPIX", N);
+
+  free (Nval);
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/textline.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/textline.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/textline.c	(revision 12606)
@@ -0,0 +1,78 @@
+# include "data.h"
+
+int textline (int argc, char **argv) {
+
+  int N, size, FracPositions;
+  char name[64], buffer[128];
+  double x, y, angle;
+  int Ngraph, Xgraph;
+  Graphdata graphmode;
+
+  Ngraph = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Ngraph = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraph (&graphmode, &Xgraph, &Ngraph)) return (FALSE);
+
+  if (N = get_argument (argc, argv, "-fn")) {
+    remove_argument (N, &argc, argv);
+    strcpy (name, argv[N]);
+    remove_argument (N, &argc, argv);
+    size = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    write (Xgraph, "FONT", 4);
+    sprintf (buffer, "%s", name);
+    write (Xgraph, buffer, 16);
+    sprintf (buffer, "%d", size);
+    write (Xgraph, buffer, 16);
+  } 
+
+  /* FracPositions uses coordinates of 0-1 relative to axis range */
+  FracPositions = FALSE;
+  if (N = get_argument (argc, argv, "-frac")) {
+    remove_argument (N, &argc, argv);
+    FracPositions = TRUE;
+  } 
+
+  angle = 0.0;
+  if (N = get_argument (argc, argv, "-rot")) {
+    remove_argument (N, &argc, argv);
+    angle = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  } 
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: text x y (line) [-fn (font) size] [-rot angle]\n");
+    return (FALSE);
+  }
+
+  if (strlen (argv[3]) > 127) {
+    fprintf (stderr, "labels currently limited to 127 chars\n");
+    return (FALSE);
+  }
+
+  x = atof (argv[1]);
+  y = atof (argv[2]);
+  
+  if (FracPositions) {
+    x =  x * (graphmode.xmax - graphmode.xmin) + graphmode.xmin;
+    y =  y * (graphmode.ymax - graphmode.ymin) + graphmode.ymin;
+  }    
+
+  write (Xgraph, "PTXT", 4);
+  sprintf (buffer, "%f", x);
+  write (Xgraph, buffer, 16);
+  sprintf (buffer, "%f", y);
+  write (Xgraph, buffer, 16);
+  sprintf (buffer, "%f", angle);
+  write (Xgraph, buffer, 16);
+
+  bzero (buffer, 128);
+  strcpy (buffer, argv[3]);
+  write (Xgraph, buffer, 128);
+
+  return (TRUE);
+}
+  
Index: /tags/start/Ohana/src/opihi/cmd.data/tv.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/tv.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/tv.c	(revision 12606)
@@ -0,0 +1,199 @@
+# include "data.h"
+
+int tv (int argc, char **argv) {
+  
+  int N, j, status, Npix, Ncolors, size, ISLOG, NNcol;
+  char buffer[1024], buffer2[100];
+  double a1, a2, max, min, zero, range;
+  float *in;
+  char *out, *outbuffer, *p, *tmpstring;
+  int Ximage, Nimage;
+  Coords coords;
+  Buffer *buf;
+
+  Nimage = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Nimage = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (&Ximage, &Nimage)) return (FALSE);
+
+  /* shell exits on pipe close, FIX */
+  if (N = get_argument (argc, argv, "-kill")) {
+    close (Ximage);
+    Ximage = 0;
+    return (TRUE);
+  }
+
+  min = max = 0.0;
+  ISLOG = FALSE;
+  if (N = get_argument (argc, argv, "-log")) {
+    remove_argument (N, &argc, argv);
+    ISLOG = TRUE;
+  }
+
+  if ((argc != 2) && (argc != 4)) {
+    fprintf (stderr, "USAGE: tv <buffer> [zero range] [-n Nimage] [-log] [-kill]\n");
+    return (FALSE);
+  }
+
+  GetImageScale (&zero, &range);
+  if (argc == 4) {
+    zero = atof (argv[2]);
+    range = atof (argv[3]);
+    if (range == 0.0) range = 0.001;
+    SetImageScale (zero, range);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  GetCoords (&coords, &buf[0].header);
+
+  Npix = buf[0].matrix.Naxis[0]*buf[0].matrix.Naxis[1];
+  size = Npix * sizeof (char);
+  in = (float *) (buf[0].matrix.buffer);
+  ALLOCATE (outbuffer, char, Npix);
+  out = outbuffer;
+
+  status = write (Ximage, "READ", 4); /* tell Ximage to look for the incoming image */
+
+  /* convert from (float) internal rep to 1 byte chars -- depends on how many colors Kii owns*/
+  read (Ximage, buffer, 16); 
+  sscanf (buffer, "%*s %d", &Ncolors); 
+
+  /* need to invert the logic if range < 0 */
+  /* define color table, */
+  NNcol = Ncolors - 1;
+  if (ISLOG) {
+    range = MAX (2, range);
+    a1 = Ncolors / log10 (range);
+    for (j = 0; j < Npix; j++, in++, out++) {
+      *out = (char) MIN (a1 * log10 (MAX (*in - zero, 1.0)), NNcol);
+    }
+  }
+  if (!ISLOG) {
+    a1 = Ncolors / range;
+    a2 = Ncolors * zero / range;
+    for (j = 0; j < Npix; j++, in++, out++) {
+      *out = (char) MIN (MAX (a1 * *in - a2, 0), NNcol);
+    }
+  }
+  
+  /* done with the conversion, now send Ximage the converted picture */
+  sprintf (buffer, "%8d %8d 8 1 %f %f ", buf[0].matrix.Naxis[0], buf[0].matrix.Naxis[1], 0.0, 1.0);
+  sprintf (buffer2, "NBYTES: %6d ", strlen (buffer));
+  write (Ximage, buffer2, 16);
+  write (Ximage, buffer, strlen (buffer));
+  
+  sprintf (buffer, "%f %f %f %f %d ", zero, range, min, max, size);
+  sprintf (buffer2, "NBYTES: %6d ", strlen (buffer));
+  write (Ximage, buffer2, 16);
+  write (Ximage, buffer, strlen (buffer));
+
+  sprintf (buffer, "%f %f %g %g %g ", coords.crval1, coords.crpix1, coords.cdelt1, coords.pc1_1, coords.pc1_2);
+  sprintf (buffer2, "NBYTES: %6d ", strlen (buffer));
+  write (Ximage, buffer2, 16);
+  write (Ximage, buffer, strlen (buffer));
+
+  sprintf (buffer, "%f %f %g %g %g ", coords.crval2, coords.crpix2, coords.cdelt2, coords.pc2_1, coords.pc2_2);
+  sprintf (buffer2, "NBYTES: %6d ", strlen (buffer));
+  write (Ximage, buffer2, 16);
+  write (Ximage, buffer, strlen (buffer));
+
+  p = strrchr (buf[0].file, '/');
+  if (p == (char *) NULL) p = buf[0].file;
+  else p++;
+  tmpstring = strcreate (p);
+  sprintf (buffer, "%s %s %s ", coords.ctype, tmpstring, buf[0].name);
+  free (tmpstring);
+  sprintf (buffer2, "NBYTES: %6d ", strlen (buffer));
+  write (Ximage, buffer2, 16);
+  write (Ximage, buffer, strlen (buffer));
+
+  write (Ximage, outbuffer, size);
+
+  free (outbuffer);
+
+  SetImageName (argv[1]);
+  set_str_variable ("TV", argv[1]);
+  return (TRUE);
+
+}
+
+
+/* 
+projections and coordinates:
+
+IRAS:
+CTYPE1  = 'LL      '                    /TANGENT PLANE (L)                     
+CRVAL1  =         0.100000D+02          /R.A. OF MAP CENTER  *** SEE COMMENT   
+CDELT1  =        -0.133333D-01          /SEPARATION IN L (DEG)                 
+CRPIX1  =                  128          /MAPCENTER IN L                        
+CROTA1  =         0.000000E+00          /NO ROTATION            
+                                                                               
+CTYPE2  = 'MM      '                    /TANGENT PLANE (M)                     
+CRVAL2  =         0.410000D+02          /DEC. OF MAP CENTER  *** SEE COMMENT   
+CDELT2  =         0.133333D-01          /SEPARATION IN M (DEG)                 
+CRPIX2  =                  128          /MAP CENTER IN M                       
+CROTA2  =         0.000000E+00          /NO ROTATION                           
+
+HIRAS:
+CTYPE1  = 'RA---TAN          ' / PRIMARY AXIS NAME                             
+CRVAL1  =   1.000000000000E+01 / PRIMARY REFERENCE VALUE                       
+CDELT1  =  -5.555555555556E-03 / PRIMARY PIXEL SEPARATION                      
+CRPIX1  =   2.560000000000E+02 / PRIMARY REFERENCE PIXEL                       
+CUNIT1  = 'DEGREE            ' / PRIMARY AXIS UNITS                            
+
+CDELT2  =   5.555555555556E-03 / PRIMARY PIXEL SEPARATION                      
+CRPIX2  =   2.560000000000E+02 / PRIMARY REFERENCE PIXEL                       
+CRVAL2  =   4.100000000000E+01 / PRIMARY REFERENCE VALUE                       
+CTYPE2  = 'DEC--TAN          ' / PRIMARY AXIS NAME                             
+CUNIT2  = 'DEGREE            ' / PRIMARY AXIS UNITS                            
+
+PROJTYPE= 'GNOMON    '                                                         
+COORDSYS= 'EQUATORIAL     '                                                    
+
+gene (small FOV linear):
+RA_O
+RA_X 
+RA_Y 
+DEC_O
+DEC_X
+DEC_Y
+
+
+*/
+
+# ifdef NEWTVMODE  
+  {
+    double *pixvalues, slope;
+
+    ALLOCATE (pixvalues, double, Ncolors + 1);
+    range = fabs (range);
+    for (i = 0; i < Ncolors + 1; i++) {
+      if (ISLOG) {
+	pixvalues[i] = i*range / NNcol + zero;
+      }
+      if (!ISLOG) {
+	pixvalues[i] = pow (10.0, i*log10(range - 1.0) / NNcol) + zero - 1.0;
+      }      
+    } 
+    for (j = 0; j < Npix; j++, in++, out++) {
+      if (*in < pixvalues[0]) {
+	i = 0;
+      } else {
+	if (*in > pixvalues[NNcol]) {
+	  i = NNcol;
+	} else {
+	  for (i = 0; (*in < pixvalues[i]) || (*in > pixvalues[i+1]); ) {
+	    slope = 1.0 / (pixvalues[i+1] - pixvalues[i]);
+	    i = MIN (MAX (0, i + (*in - pixvalues[i]) * slope), NNcol);
+	  }
+	}	
+      }
+      /* for (i = 0; (i < Ncolors - 1) && (pixvalues[i] < *in); i++); */
+      *out = i;
+    }
+    free (pixvalues);
+  }
+# endif
Index: /tags/start/Ohana/src/opihi/cmd.data/tvcontour.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/tvcontour.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/tvcontour.c	(revision 12606)
@@ -0,0 +1,297 @@
+# include "data.h"
+# define LL { \
+ dx =  d00 / (*v01 - *v00); \
+ dy = -d00 / (*v10 - *v00); \
+ x = i - 0.5; \
+ y = j - dy - 0.5; }
+
+# define UL { \
+ tmp = d00 / (*v10 - *v00); \
+ dy = 1 - tmp; \
+ dx =  d10 / (*v11 - *v10); \
+ x = i - 0.5; \
+ y = j + tmp - 0.5; }
+      
+# define LR { \
+ tmp = d00 / (*v01 - *v00); \
+ dx = 1 - tmp; \
+ dy = d01 / (*v11 - *v01); \
+ x = i + tmp - 0.5; \
+ y = j - 0.5; }
+
+# define UR { \
+ tmp = d10 / (*v11 - *v10); \
+ dx = 1 - tmp; \
+ dy = -d11 / (*v01 - *v11); \
+ x = i + tmp - 0.5; \
+ y = j + 1 - 0.5; }
+      
+# define HZ { \
+ tmp = d00 / (*v10 - *v00); \
+ dy = d01 / (*v11 - *v01) - tmp; \
+ dx = 1; \
+ x = i - 0.5; \
+ y = j + tmp - 0.5; }
+
+# define VT { \
+ tmp = d00 / (*v01 - *v00); \
+ dx = d10 / (*v11 - *v10) - tmp; \
+ x = i + tmp - 0.5; \
+ dy = 1; \
+ y = j - 0.5; }
+
+# define DUMP { \
+sprintf (&buffer[Nline*128], "%14s %20.10f %20.10f %20.10f %20.10f ", "LINE", Npix*x, Npix*y, Npix*dx, Npix*dy); \
+Nline ++; \
+if (Nline == 512) { \
+  sprintf (line, "NLINES  %7d ", Nline); \
+  write (Ximage, line, 16); \
+  write (Ximage, buffer, Nline*128); \
+  bzero (buffer, 65536); \
+  Nline = 0; \
+} \
+continue; }
+
+# define NUMP { \
+sprintf (&buffer[Nline*128], "%14s %20.10f %20.10f %20.10f %20.10f ", "LINE", Npix*x, Npix*y, Npix*dx, Npix*dy); \
+Nline ++; \
+if (Nline == 512) { \
+  sprintf (line, "NLINES  %7d ", Nline); \
+  write (Ximage, line, 16); \
+  write (Ximage, buffer, Nline*128); \
+  bzero (buffer, 65536); \
+  Nline = 0; \
+} }
+
+int tvcontour (int argc, char **argv) {
+
+  int i, j, ii, jj, n, Npix, Nx, Ny, Nline;
+  float level, d00, d01, d10, d11, tmp;
+  float x, y, dx, dy;
+  float *v00, *v01, *v10, *v11;
+  float *Vout, *Vin, *matrix;
+  char *buffer, line[17];
+  int Ximage, Nimage, N;
+  Buffer *buf;
+  
+  Nimage = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Nimage = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (&Ximage, &Nimage)) return (FALSE);
+
+  if ((argc != 4) && (argc != 5)) {
+    fprintf (stderr, "USAGE: contour <buffer> (overlay) level [Npix]\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if (!SelectOverlay (argv[2], &n)) return (FALSE);
+
+  level = atof (argv[3]);
+  if (argc == 5) 
+    Npix = (int) MAX (atof (argv[4]), 1); 
+  else 
+    Npix = 1;
+  level *= Npix*Npix;
+
+  /*** make rebinned image ***/
+  Nx = buf[0].header.Naxis[0]/Npix;
+  Ny = buf[0].header.Naxis[1]/Npix;
+  if (Npix != 1) {
+    fprintf (GetOutfile(), "rebin by a factor of %d (%d,%d)\n", Npix, Nx, Ny);
+    ALLOCATE (matrix, float, Nx*Ny);
+    bzero (matrix, Nx*Ny*sizeof(float));
+	
+    for (j = 0; j < Ny; j++) {
+      for (jj = 0; jj < Npix; jj++) {
+	Vout = matrix + j*Nx;
+	Vin  = (float *)(buf[0].matrix.buffer) + (j*Npix + jj)*buf[0].header.Naxis[0];
+	for (i = 0; i < Nx; i++, Vout++) {
+	  for (ii = 0; ii < Npix; ii++, Vin++) {
+	    *Vout += *Vin;
+	  }
+	}
+      }
+    }
+  }
+  else {
+    fprintf (stderr, "using scale of 1\n");
+    matrix = (float *)(buf[0].matrix.buffer);
+  }
+
+  write (Ximage, "LOAD", 4); /* force Ximage to look for the incoming image */
+  sprintf (line, "OVERLAY %7d ", n);
+  write (Ximage, line, 16);
+  ALLOCATE (buffer, char, 65536);  /* space for 512 lines of 128 bytes */
+  bzero (buffer, 65536);
+  Nline = 0;
+
+  v00 = matrix;
+  v01 = matrix + 1;
+  v10 = matrix + Nx;
+  v11 = matrix + Nx + 1;
+  d01 = (level - *v00);
+  d11 = (level - *v10);
+  for (j = 1; j < Ny; j++) {
+    if (!(j%10)) fprintf (stderr, ".");
+    for (i = 1; i < Nx; i++, v00++, v01++, v10++, v11++) {
+
+      d00 = d01;
+      d10 = d11;
+      d01 = (level - *v01);
+      d11 = (level - *v11);
+
+      if (((d00 > 0) && (d01 > 0) && (d10 > 0) && (d11 > 0)) ||
+	  ((d00 < 0) && (d01 < 0) && (d10 < 0) && (d11 < 0)))
+	continue;
+
+      if ((d00 > 0) && (d10 <= 0)) { 
+	if ((d01 <= 0) && (d11 <= 0)) { /* \  */
+	  LL;
+	  DUMP;
+	}
+	if ((d01 > 0) && (d11 <= 0)) { /* -  */
+	  HZ;
+	  DUMP;
+	}
+	if ((d01 > 0) && (d11 > 0)) { /* /  */
+	  UL;
+	  DUMP;
+	}
+	if ((d01 <= 0) && (d11 > 0)) { /* \\  */
+	  LL;
+	  NUMP;
+	  UR;
+	  DUMP;
+	}
+      }
+
+      if ((d00 <= 0) && (d10 > 0)) {
+	if ((d01 > 0) && (d11 > 0)) { /* \  */
+	  LL;
+	  DUMP;
+	}
+	if ((d01 <= 0) && (d11 > 0)) { /* -  */
+	  HZ;
+	  DUMP;
+	}
+	if ((d01 <= 0) && (d11 <= 0)) { /* /  */
+	  UL;
+	  DUMP;
+	}
+	if ((d01 > 0) && (d11 <= 0)) { /* //  */
+	  UL;
+	  NUMP;
+	  LR;
+	  DUMP;
+	}
+      }
+      
+
+      if ((d00 <= 0) && (d10 <= 0)) { 
+	if ((d01 > 0) && (d11 <= 0)) {
+	  LR;
+	  DUMP;
+	}
+	if ((d01 <= 0) && (d11 > 0)) {
+	  UR;
+	  DUMP;
+	}
+	if ((d01 > 0) && (d11 > 0)) {
+	  VT;
+	  DUMP;
+	}
+      }
+
+      if ((d00 > 0) && (d10 > 0)) { 
+	if ((d01 <= 0) && (d11 > 0)) {
+	  LR;
+	  DUMP;
+	}
+	if ((d01 > 0) && (d11 <= 0)) {
+	  UR;
+	  DUMP;
+	}
+	if ((d01 <= 0) && (d11 <= 0)) {
+	  VT;
+	  DUMP;
+	}
+      }
+
+    }
+    /* skip left-hand edge */
+    v00++; v01++; v10++; v11++;
+    d01 = (level - *v00);
+    d11 = (level - *v10);
+  }
+
+  /****** bottom line *******/
+  v00 = matrix;  
+  v01 = matrix + 1;  
+  y = 0;
+  dx = 0;
+  dy = -0.5;
+  for (i = 1; i < Nx; i++, v00++, v01++) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      x = i + (level - *v01)/(*v01 - *v00);
+      NUMP;
+    }
+  }
+
+  /********** top line *******/
+  v00 = matrix + Nx*(Ny - 1);  
+  v01 = v00 + 1;
+  y = Ny - 1;
+  dx = 0;
+  dy = 0.5;
+  for (i = 1; i < Nx; i++, v00++, v01++) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      x = i + (level - *v01)/(*v01 - *v00);
+      NUMP;
+    }
+  }
+
+  /******** left line *********/
+  v00 = matrix; 
+  v01 = matrix + Nx;
+  x = 0;
+  dx = -0.5;
+  dy = 0;
+  for (j = 1; j < Ny; j++, v00+=Nx, v01+=Nx) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      y = j + (level - *v01)/(*v01 - *v00);
+      NUMP;
+    }
+  }
+
+  /******** right line *********/
+  v00 = matrix + Nx - 1; 
+  v01 = v00 + Nx;
+  x = Nx - 1;
+  dx = 0.5;
+  dy = 0;
+  for (j = 1; j < Ny; j++, v00+=Nx, v01+=Nx) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      y = j + (level - *v01)/(*v01 - *v00);
+      NUMP;
+    }
+  }
+  
+  if (Nline > 0) {
+    sprintf (line, "NLINES  %7d ", Nline); 
+    write (Ximage, line, 16); 
+    write (Ximage, buffer, Nline*128); 
+  }
+
+  free (buffer);
+  sprintf (line, "DONE ");
+  write (Ximage, line, 16);
+  if (Npix != 1) {
+    free (matrix);
+  }
+  fprintf (stderr, "\n");
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/tvgrid.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/tvgrid.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/tvgrid.c	(revision 12606)
@@ -0,0 +1,215 @@
+# include "data.h"
+# define TEN(X) (pow(10.0, (double)(X)))
+
+int tvgrid (int argc, char **argv) {
+  
+  int ncolor, ndig1, ndig2, NX, NY, connect;
+  int tDEC, tRA;
+  double ra, dec, ra0, dec0, ra1, dec1;
+  double x0, y0, x1, y1;
+  double dDEC, fDEC, dRA, fRA;
+  char buffer[1024], format[16];
+  Coords coords;
+  int Ximage, Nimage, N;
+  Buffer *buf;
+
+  Nimage = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Nimage = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (&Ximage, &Nimage)) return (FALSE);
+  
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: load (overlay) (buffer)\n");
+    fprintf (stderr, " (overlay) may be: red, green, blue, yellow\n");
+    return (FALSE);
+  }
+  if (strcmp (argv[1], "0")   && strcmp (argv[1], "1")     && strcmp (argv[1], "2")   && strcmp (argv[1], "3") &&
+      strcmp (argv[1], "red") && strcmp (argv[1], "green") && strcmp (argv[1], "blue") && strcmp (argv[1], "yellow")) {
+    fprintf (stderr, "valid overlays may be: 0, red, 1, green, 2, blue, 3, yellow\n");
+    return (FALSE);
+  }
+
+  ncolor = atof (argv[1]);
+  if (!(strcmp (argv[1], "red"))) 
+    ncolor = 0;
+  if (!(strcmp (argv[1], "green"))) 
+    ncolor = 1;
+  if (!(strcmp (argv[1], "blue"))) 
+    ncolor = 2;
+  if (!(strcmp (argv[1], "yellow"))) 
+    ncolor = 3;
+
+  if ((buf = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  GetCoords (&coords, &buf[0].header);
+
+  XY_to_RD (&ra0, &dec0, 0.0, 0.0, &coords);
+  XY_to_RD (&ra1, &dec1, (double)buf[0].header.Naxis[0], (double)buf[0].header.Naxis[1], &coords);
+  fprintf (stderr, "%f %f  %f %f\n", ra0, dec0, ra1, dec1);
+  
+  /* tell KII to expect overlay data */
+  write (Ximage, "LOAD", 4); 
+  sprintf (buffer, "OVERLAY: %7d", ncolor);
+  write (Ximage, buffer, 16);
+  
+  dDEC = fabs(dec1 - dec0);
+  tDEC = log10(dDEC) - log10(5.0);
+  fDEC = log10(dDEC) - tDEC;
+  if ((fDEC > log10(0.5)) && (fDEC < log10(1.0))) {
+    dDEC = TEN (tDEC + log10(0.1));
+  }
+  if ((fDEC > log10(1.0)) && (fDEC < log10(2.0))) {
+    dDEC = TEN (tDEC + log10(0.2));
+  }
+  if ((fDEC > log10(2.0)) && (fDEC < log10(5.0))) {
+    dDEC = TEN (tDEC + log10(0.5));
+  }
+  if ((fDEC > log10(5.0)) && (fDEC < log10(10.0))) {
+    dDEC = TEN (tDEC + log10(1.0));
+  }
+  if ((fDEC > log10(10.0)) && (fDEC < log10(20.0))) {
+    dDEC = TEN (tDEC + log10(2.0));
+  }
+  if ((fDEC > log10(20.0)) && (fDEC < log10(50.0))) {
+    dDEC = TEN (tDEC + log10(5.0));
+  }
+  ndig2 = ((log10(dDEC) < 0) ? fabs(log10(dDEC)) : 0);
+  ndig1 = 3 + log10(MAX(dec0, dec1)) + ndig2;
+  sprintf (format, "%%%d.%df", ndig1, ndig2);
+  fprintf (stderr, "format: %s..\n", format);
+
+  NX = buf[0].header.Naxis[0];
+  NY = buf[0].header.Naxis[1];
+
+    /* find starting position
+    RD_to_XY (&x0, &y0, MIN(ra0, ra1), dec + 0.1*dDEC, &coords);
+    sprintf (label, format, dec);
+    sprintf (buffer, "%15s %20.10f %20.10f %20.10f %20.10f ", "TEXT", x0, y0, (double)(strlen(label) + 1), 0.0);
+    write (Ximage, buffer, 128);
+    write (Ximage, label, strlen(label) + 1); */
+
+  dRA = MAX (fabs(ra1 - ra0) / 100.0, 0.1);
+  connect = FALSE;
+  for (dec = dDEC * ((int)(MIN(dec0,dec1)/dDEC) + 1); dec < MAX(dec0,dec1); dec += dDEC) {
+    for (ra = 0; ra < 361; ra += dRA) {
+      RD_to_XY (&x1, &y1, ra, dec, &coords);
+      if ((x1 >= 0) && (x1 < NX) && (y1 >= 0) && (y1 < NY)) {
+	if (connect) {
+	  sprintf (buffer, "%15s %20.10f %20.10f %20.10f %20.10f ", "LINE", x0, y0, (x1 - x0), (y1 - y0));
+	  write (Ximage, buffer, 128);
+	}
+	x0 = x1;
+	y0 = y1;
+	connect = TRUE;
+      }
+      else {
+	connect = FALSE;
+      }
+    }
+  }
+
+  dRA = fabs(ra1 - ra0);
+  tRA = log10(dRA) - log10(5.0);
+  fRA = log10(dRA) - tRA;
+  if ((fRA > log10(0.5)) && (fRA < log10(1.0))) {
+    dRA = TEN (tRA + log10(0.1));
+  }
+  if ((fRA > log10(1.0)) && (fRA < log10(2.0))) {
+    dRA = TEN (tRA + log10(0.2));
+  }
+  if ((fRA > log10(2.0)) && (fRA < log10(5.0))) {
+    dRA = TEN (tRA + log10(0.5));
+  }
+  if ((fRA > log10(5.0)) && (fRA < log10(10.0))) {
+    dRA = TEN (tRA + log10(1.0));
+  }
+  if ((fRA > log10(10.0)) && (fRA < log10(20.0))) {
+    dRA = TEN (tRA + log10(2.0));
+  }
+  if ((fRA > log10(20.0)) && (fRA < log10(50.0))) {
+    dRA = TEN (tRA + log10(5.0));
+  }
+  ndig2 = ((log10(dRA) < 0) ? fabs(log10(dRA)) : 0);
+  ndig1 = 3 + log10(MAX(ra0, ra1)) + ndig2;
+  sprintf (format, "%%%d.%df", ndig1, ndig2);
+  fprintf (stderr, "format: %s..\n", format);
+
+  dDEC = MAX (fabs(dec1 - dec0) / 100.0, 0.1);
+  connect = FALSE;
+  for (ra = dRA * ((int)(MIN(ra0,ra1)/dRA) + 1); ra < MAX(ra0,ra1); ra += dRA) {
+    for (dec = -90; dec < 90; dec += dDEC) {
+      RD_to_XY (&x1, &y1, ra, dec, &coords);
+      if ((x1 >= 0) && (x1 < NX) && (y1 >= 0) && (y1 < NY)) {
+	if (connect) {
+	  sprintf (buffer, "%15s %20.10f %20.10f %20.10f %20.10f ", "LINE", x0, y0, (x1 - x0), (y1 - y0));
+	  write (Ximage, buffer, 128);
+	}
+	x0 = x1;
+	y0 = y1;
+	connect = TRUE;
+      }
+      else {
+	connect = FALSE;
+      }
+    }
+  }
+
+  /*
+  dDEC = fabs(dec1 - dec0) / 100;
+  for (ra = dRA * ((int)(MIN(ra0, ra1)/dRA) + 1); ra < MAX(ra0, ra1); ra += dRA) {
+    RD_to_XY (&x0, &y0, ra + 0.1*dRA, MIN(dec0, dec1), &coords);
+    sprintf (label, format, ra);
+    sprintf (buffer, "%15s %20.10f %20.10f %20.10f %20.10f ", "TEXT", x0, y0, (double)(strlen(label) + 1), 0.0);
+    write (Ximage, buffer, 128);
+    write (Ximage, label, strlen(label) + 1);
+    RD_to_XY (&x0, &y0, ra, MIN(dec0, dec1), &coords);
+    for (dec = MIN(dec0, dec1) + dDEC; dec < MAX(dec0,dec1); dec += dDEC) {
+      RD_to_XY (&x1, &y1, ra, dec, &coords);
+      sprintf (buffer, "%15s %20.10f %20.10f %20.10f %20.10f ", "LINE", x0, y0, (x1 - x0), (y1 - y0));
+      write (Ximage, buffer, 128);
+      x0 = x1;
+      y0 = y1;
+    }
+  }
+  */
+
+  sprintf (buffer, "DONE");
+  write (Ximage, buffer, 128);
+  return (TRUE);
+}
+
+
+  
+
+/*
+  write (Ximage, "LOAD", 4); 
+  sprintf (buffer, "OVERLAY: %7d", n);
+  write (Ximage, buffer, 16);
+  
+  for (n = 0; scan_line (f, buffer) != EOF; n++) {
+    c = strchr (buffer, '#');
+    if (c != (char *) NULL) 
+      *c = 0;  
+    while ((c = strchr (buffer, '(')) != (char *) NULL) 
+      *c = ' ';
+    while ((c = strchr (buffer, ')')) != (char *) NULL) 
+      *c = ' ';
+    while ((c = strchr (buffer, ',')) != (char *) NULL) 
+      *c = ' ';
+    N = sscanf (buffer, "%s %lf %lf %lf %lf", type, &x, &y, &dx, &dy);
+    if (N > 3) {
+      if (N == 4)
+	dy = dx;
+      sprintf (buffer, "%15s %20.10f %20.10f %20.10f %20.10f ", type, x, y, dx, dy);
+      write (Ximage, buffer, 128);
+    }
+  }
+  fprintf (stderr, "loaded %d objects\n", n);
+  sprintf (buffer, "DONE");
+  write (Ximage, buffer, 128);
+  if (f != stdin) {
+    fclose (f);
+  }
+*/
Index: /tags/start/Ohana/src/opihi/cmd.data/uniq.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/uniq.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/uniq.c	(revision 12606)
@@ -0,0 +1,39 @@
+# include "data.h"
+
+int uniq (int argc, char **argv) {
+  
+  int Nnew, i, j, found;
+  float *v1, *v2;
+  Vector *ivec, *ovec;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: uniq (in) (out)\n");
+    return (FALSE);
+  }
+
+  if ((ivec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((ovec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  /* allocate the maximum possible needed */
+  ALLOCATE (ovec[0].elements, float, ivec[0].Nelements);
+
+  Nnew = 0;
+  v1 = ivec[0].elements;
+  for (i = 0; i < ivec[0].Nelements; i++, v1++) {
+    v2 = ovec[0].elements;
+    found = FALSE;
+    for (j = 0; !found && (j < Nnew); j++, v2++) {
+      if (*v1 == *v2) found = TRUE;
+    }
+    if (!found) {
+      ovec[0].elements[Nnew] = *v1;
+      Nnew ++;
+    }
+  }
+
+  ovec[0].Nelements = Nnew;
+  REALLOCATE (ovec[0].elements, float, ovec[0].Nelements);
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/unsign.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/unsign.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/unsign.c	(revision 12606)
@@ -0,0 +1,28 @@
+# include "data.h"
+
+int unsign (int argc, char **argv) {
+  
+  if (argc == 1) {
+    if (FT_UNSIGN_MODE) 
+      fprintf (stderr, "mode is now UNSIGNED int \n");
+    else
+      fprintf (stderr, "mode is now SIGNED int \n");
+    return (TRUE);
+  }
+
+  if (argc == 2) {
+    if (!strcmp (argv[1], "1")) {
+      FT_UNSIGN_MODE = TRUE;
+      set_int_variable ("UNSIGN", 1);
+      return (TRUE);
+    }
+    if (!strcmp (argv[1], "0")) {
+      FT_UNSIGN_MODE = FALSE;
+      set_int_variable ("UNSIGN", 0);
+      return (TRUE);
+    }
+  }
+
+  fprintf (stderr, "USAGE: unsign [0/1]\n");
+  return (FALSE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/vbin.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/vbin.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/vbin.c	(revision 12606)
@@ -0,0 +1,227 @@
+# include "data.h"
+
+int vbin (int argc, char **argv) {
+  
+  int i, j, status, ExactScale;
+  int n, nx, ny, Nx, Ny, x, y, N, Normalize, *Npix, *Vn;
+  int Ignore, IgnoreValue, VERBOSE;
+  float *Vout, *Vin, *Out, *In;
+  double scale, scale2, fx, fy, dX, dY;
+  char temp[1024];
+  Buffer *in, *out;
+
+  Normalize = FALSE;
+  if (N = get_argument (argc, argv, "-norm")) {
+    remove_argument (N, &argc, argv);
+    Normalize = TRUE;
+  }
+
+  VERBOSE = FALSE;
+  if (N = get_argument (argc, argv, "-v")) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = TRUE;
+  }
+
+  Ignore = FALSE;
+  IgnoreValue = 0.0;
+  if (N = get_argument (argc, argv, "-ignore")) {
+    Ignore = TRUE;
+    remove_argument (N, &argc, argv);
+    IgnoreValue = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: vbin <input> <output> scale \n");
+    fprintf (stderr, "  (use interpolate to expand)\n");
+    return (FALSE);
+  }
+
+  if ((in  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out = SelectBuffer (argv[2], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  fits_free_matrix (&out[0].matrix);
+  fits_free_header (&out[0].header);
+
+  scale  = atof (argv[3]);
+  if ((scale == (int) scale) || ((1.0/scale) == (int)(1.0/scale))) {
+    ExactScale = TRUE;
+    if (scale > 0) {
+      nx = in[0].header.Naxis[0] / scale;
+      ny = in[0].header.Naxis[1] / scale;
+    } else {
+      nx = in[0].header.Naxis[0] * fabs(scale);
+      ny = in[0].header.Naxis[1] * fabs(scale);
+    }    
+  } else {
+    ExactScale = FALSE;
+    if (scale > 0) {
+      nx = (int) (in[0].header.Naxis[0] / scale) + 1;
+      ny = (int) (in[0].header.Naxis[1] / scale) + 1;
+    } else {
+      nx = (int) (in[0].header.Naxis[0] * fabs(scale)) + 1;
+      ny = (int) (in[0].header.Naxis[1] * fabs(scale)) + 1;
+    }      
+  }
+  if (VERBOSE) fprintf (GetOutfile(), "rebin %s to %s (%d,%d to %d,%d)\n", argv[1], argv[2], in[0].header.Naxis[0], in[0].header.Naxis[1], nx, ny);
+
+  Nx = in[0].header.Naxis[0];
+  Ny = in[0].header.Naxis[1];
+  out[0].bitpix = in[0].bitpix;
+  out[0].unsign = in[0].unsign;
+  out[0].bscale = in[0].bscale;
+  out[0].bzero  = in[0].bzero;
+  fits_copy_header (&in[0].header, &out[0].header);
+  fits_modify (&out[0].header, "NAXIS1", "%d", 1, nx);
+  fits_modify (&out[0].header, "NAXIS2", "%d", 1, ny);
+
+  status =  fits_scan (&out[0].header, "CDELT1", "%lf", 1, &dX);
+  status &= fits_scan (&out[0].header, "CDELT2", "%lf", 1, &dY);
+  if (scale > 0) {
+    dX *= scale;
+    dY *= scale;
+  } else {
+    dX /= fabs(scale);
+    dY /= fabs(scale);
+  }    
+  if (status) {
+    fits_modify (&out[0].header, "CDELT1", "%lf", 1, dX);
+    fits_modify (&out[0].header, "CDELT2", "%lf", 1, dY);
+  }
+
+  status =  fits_scan (&out[0].header, "CRPIX1", "%lf", 1, &dX);
+  status &= fits_scan (&out[0].header, "CRPIX2", "%lf", 1, &dY);
+  if (scale > 0) {
+    dX /= scale;
+    dY /= scale;
+  } else {
+    dX *= fabs(scale);
+    dY *= fabs(scale);
+  }    
+  if (status) {
+    fits_modify (&out[0].header, "CRPIX1", "%lf", 1, dX);
+    fits_modify (&out[0].header, "CRPIX2", "%lf", 1, dY);
+  }
+
+  out[0].header.Naxis[0] = nx;
+  out[0].header.Naxis[1] = ny;
+  fits_create_matrix (&out[0].header, &out[0].matrix);
+  temp[0] = 0;
+  if ((in[0].file[0] != '*') && (in[0].file[0] != '(')) {
+    strcpy (temp, "*");
+  }
+  strcat (temp, in[0].file);
+  strcpy (out[0].file, temp);
+
+  if (Normalize) {
+    ALLOCATE (Npix, int, nx*ny);
+    bzero (Npix, nx*ny*sizeof(int));
+  }
+
+  if (ExactScale) {
+    n = scale;
+    if (n > 0) {
+      for (j = 0; j < ny; j++) {
+	for (y = 0; y < n; y++) {
+	  Vout = (float *)(out[0].matrix.buffer) + j*nx;
+	  Vin  = (float *)(in[0].matrix.buffer)  + (j*n + y)*in[0].header.Naxis[0];
+	  if (Normalize) { Vn = Npix + j*nx; }
+	  for (i = 0; i < nx; i++, Vout++) {
+	    for (x = 0; x < n; x++, Vin++) {
+	      if (Ignore && (*Vin == IgnoreValue)) continue;
+	      *Vout += *Vin;
+	      if (Normalize) {(*Vn) ++;}
+	    }
+	    if (Normalize) {Vn ++;}
+	  }
+	}
+      }
+    } else {
+      n = fabs (n);
+      for (j = 0; j < in[0].header.Naxis[1]; j++) {
+	for (y = 0; y < n; y++) {
+	  Vout = (float *)(out[0].matrix.buffer) + (j*n + y)*nx;
+	  Vin  = (float *)(in[0].matrix.buffer)  + j*in[0].header.Naxis[0];
+	  if (Normalize) { Vn = Npix + j*nx; }
+	  for (i = 0; i < in[0].header.Naxis[0]; i++, Vin++) {
+	    if (Ignore && (*Vin == IgnoreValue)) { 
+	      Vout += n; 
+	      if (Normalize) Vn += n; 
+	      continue; 
+	    }
+	    for (x = 0; x < n; x++, Vout++) {
+	      *Vout = *Vin;
+	      if (Normalize) {(*Vn) ++; Vn ++;}
+	    }
+	  }
+	}
+      }
+    }
+    if (Normalize) {
+      Vn = Npix;
+      Vout = (float *)out[0].matrix.buffer;
+      for (i = 0; i < nx*ny; i++, Vout++, Vn++) {
+	if (*Vn) { 
+	  *Vout /= *Vn; 
+	} else {
+	  *Vout = 0;
+	}
+      }
+    }
+  } else {
+    
+    if (Normalize) { fprintf (stderr, "normalize not enabled for fractional scaling\n"); }
+
+    if (scale < 0) scale = 1.0 / fabs(scale);
+    In = (float *)in[0].matrix.buffer;
+    Out = (float *)out[0].matrix.buffer;
+    scale2 = scale*scale;
+    if (scale > 1) {
+      for (i = 0; i < Ny; i++) {
+	y = 0.5 + (i - 0.5) / scale;
+	fy = 0.5 + MIN (0.5, (y + 0.5) * scale - i);
+	for (j = 0; j < Nx; j++, In++) {
+	  x = 0.5 + (j - 0.5) / scale;
+	  fx = 0.5 + MIN (0.5, (x + 0.5) * scale - j);
+	  Vout = Out + y*nx + x;
+	  *Vout += fx*fy*(*In);
+	  if (fx < 1) {
+	    *(Vout+1)    += (1-fx)*fy*(*In);
+	  }
+	  if (fy < 1) {
+	    *(Vout+nx) += fx*(1-fy)*(*In);
+	  }
+	  if ((fx < 1) && (fy < 1)) {
+	    *(Vout+1+nx) += (1-fx)*(1-fy)*(*In);
+	  }
+	}
+      }
+    } else {
+      for (i = 0; i < ny; i++) {
+	y = 0.5 + (i - 0.5) * scale;
+	fy = 0.5 + MIN (0.5, (y + 0.5) / scale - i);
+	for (j = 0; j < nx; j++, Out++) {
+	  x = 0.5 + (j - 0.5) * scale;
+	  fx = 0.5 + MIN (0.5, (x + 0.5) / scale - j);
+	  Vin = In + y*Nx + x;
+	  *Out += *Vin*fx*fy;
+	  if (fx < 1) {
+	    *Out += *(Vin+1)*(1-fx)*fy;
+	  }
+	  if (fy < 1) {
+	    *Out += *(Vin+Nx)*fx*(1-fy);
+	  }
+	  if ((fx < 1) && (fy < 1)) {
+	    *Out += *(Vin+1+Nx)*(1-fx)*(1-fy);
+	  }
+	  *Out = *Out * scale2;
+	}
+      }
+    }
+  }
+
+  if (Normalize) free (Npix);
+
+  return (TRUE);
+
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/vclip.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/vclip.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/vclip.c	(revision 12606)
@@ -0,0 +1,71 @@
+# include "data.h"
+
+int vclip (int argc, char **argv) {
+
+  int i, Npix, DO_NAN, DO_INF, N;
+  double min, Vmin, max, Vmax, nan_val, inf_val;
+  float *in;
+  Vector *vec;
+
+  DO_NAN = FALSE;
+  if (N = get_argument (argc, argv, "-nan")) {
+    remove_argument (N, &argc, argv);
+    nan_val  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    DO_NAN = TRUE;
+  }
+
+  DO_INF = FALSE;
+  if (N = get_argument (argc, argv, "-inf")) {
+    remove_argument (N, &argc, argv);
+    inf_val  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    DO_INF = TRUE;
+  }
+
+  if ((argc != 6) && (!(DO_INF || DO_NAN))) {
+    fprintf (stderr, "USAGE: vclip (vector) [min Vmin max Vmax] [-inf val] [-nan val]\n");
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (argc == 6) {
+    min = atof (argv[2]);
+    Vmin = atof (argv[3]);
+    max = atof (argv[4]);
+    Vmax = atof (argv[5]);
+  }
+
+  Npix = vec[0].Nelements;
+  in =   vec[0].elements;
+
+  if (argc == 6) {
+    for (i = 0; i < Npix; i++, in++) {
+      if (*in < min) 
+	*in = Vmin;
+      if (*in > max)
+	*in = Vmax;
+    }
+  }
+  in = vec[0].elements;
+  if (DO_NAN) {
+    for (i = 0; i < Npix; i++, in++) {
+      if (isnan (*in)) {
+	*in = nan_val;
+      }
+    }
+  }
+  in = vec[0].elements;
+  if (DO_INF) {
+    for (i = 0; i < Npix; i++, in++) {
+      if (!finite (*in)) {
+	*in = inf_val;
+      }
+    }
+  }
+  return (TRUE);
+
+}
+
+
Index: /tags/start/Ohana/src/opihi/cmd.data/vcontour.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/vcontour.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/vcontour.c	(revision 12606)
@@ -0,0 +1,277 @@
+# include "data.h"
+# define LL { \
+ dx =  d00 / (*v01 - *v00); \
+ dy = -d00 / (*v10 - *v00); \
+ x = i - 0.5; \
+ y = j - dy - 0.5; }
+
+# define UL { \
+ tmp = d00 / (*v10 - *v00); \
+ dy = 1 - tmp; \
+ dx =  d10 / (*v11 - *v10); \
+ x = i - 0.5; \
+ y = j + tmp - 0.5; }
+      
+# define LR { \
+ tmp = d00 / (*v01 - *v00); \
+ dx = 1 - tmp; \
+ dy = d01 / (*v11 - *v01); \
+ x = i + tmp - 0.5; \
+ y = j - 0.5; }
+
+# define UR { \
+ tmp = d10 / (*v11 - *v10); \
+ dx = 1 - tmp; \
+ dy = -d11 / (*v01 - *v11); \
+ x = i + tmp - 0.5; \
+ y = j + 1 - 0.5; }
+      
+# define HZ { \
+ tmp = d00 / (*v10 - *v00); \
+ dy = d01 / (*v11 - *v01) - tmp; \
+ dx = 1; \
+ x = i - 0.5; \
+ y = j + tmp - 0.5; }
+
+# define VT { \
+ tmp = d00 / (*v01 - *v00); \
+ dx = d10 / (*v11 - *v10) - tmp; \
+ x = i + tmp - 0.5; \
+ dy = 1; \
+ y = j - 0.5; }
+
+# define DUMP { \
+sprintf (&buffer[Nline*128], "%14s %20.10f %20.10f %20.10f %20.10f \0", "LINE", Npix*x, Npix*y, Npix*dx, Npix*dy); \
+Nline ++; \
+if (Nline == 512) { \
+  sprintf (line, "NLINES  %7d \0", Nline); \
+  write (Ximage, line, 16); \
+  write (Ximage, buffer, Nline*128); \
+  bzero (buffer, 65536); \
+  Nline = 0; \
+} \
+continue; }
+
+# define NUMP { \
+sprintf (&buffer[Nline*128], "%14s %20.10f %20.10f %20.10f %20.10f \0", "LINE", Npix*x, Npix*y, Npix*dx, Npix*dy); \
+Nline ++; \
+if (Nline == 512) { \
+  sprintf (line, "NLINES  %7d \0", Nline); \
+  write (Ximage, line, 16); \
+  write (Ximage, buffer, Nline*128); \
+  bzero (buffer, 65536); \
+  Nline = 0; \
+} }
+
+int vcontour (int argc, char **argv) {
+
+  int i, j, ii, jj, n, Nbuf, Npix, Nx, Ny, Nline;
+  float level, d00, d01, d10, d11, tmp;
+  float x, y, dx, dy;
+  float *v00, *v01, *v10, *v11;
+  float *Vout, *Vin, *matrix;
+  char *buffer, line[17];
+  int Ximage, Nimage, N;
+  Vector *xvec, *yvec, *zvec;
+
+  fprintf (stderr, "vcontour not working yet\n");
+  return (FALSE);
+
+  if (argc != 7) {
+    fprintf (stderr, "USAGE: vcontour x y z Xc Yc (level)\n");
+    return (FALSE);
+  }
+  
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((zvec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((foo = SelectVector (argv[4], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((foo = SelectVector (argv[5], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  level = atof (argv[6]);
+
+  /* convert the x,y,z vectors to a matrix */
+  *V = xvec[0].elements;
+  max = min = *V;
+  for (i = 0; i < xvec[0].Nelements; i++, V++) {
+    if (!finite (*V)) continue;
+    max = MAX (*V, max);
+    min = MIN (*V, min);
+  }      
+  Xmax = max; Xmin = min;
+
+  *V = yvec[0].elements;
+  max = min = *V;
+  for (i = 0; i < yvec[0].Nelements; i++, V++) {
+    if (!finite (*V)) continue;
+    max = MAX (*V, max);
+    min = MIN (*V, min);
+  }      
+  Ymax = max; Ymin = min;
+
+  /* not really finished */
+
+  v01 = matrix + 1;
+  v10 = matrix + Nx;
+  v11 = matrix + Nx + 1;
+  d01 = (level - *v00);
+  d11 = (level - *v10);
+  for (j = 1; j < Ny; j++) {
+    if (!(j%10)) fprintf (stderr, ".");
+    for (i = 1; i < Nx; i++, v00++, v01++, v10++, v11++) {
+
+      d00 = d01;
+      d10 = d11;
+      d01 = (level - *v01);
+      d11 = (level - *v11);
+
+      if (((d00 > 0) && (d01 > 0) && (d10 > 0) && (d11 > 0)) ||
+	  ((d00 < 0) && (d01 < 0) && (d10 < 0) && (d11 < 0)))
+	continue;
+
+      if ((d00 > 0) && (d10 <= 0)) { 
+	if ((d01 <= 0) && (d11 <= 0)) { /* \  */
+	  LL;
+	  DUMP;
+	}
+	if ((d01 > 0) && (d11 <= 0)) { /* -  */
+	  HZ;
+	  DUMP;
+	}
+	if ((d01 > 0) && (d11 > 0)) { /* /  */
+	  UL;
+	  DUMP;
+	}
+	if ((d01 <= 0) && (d11 > 0)) { /* \\  */
+	  LL;
+	  NUMP;
+	  UR;
+	  DUMP;
+	}
+      }
+
+      if ((d00 <= 0) && (d10 > 0)) {
+	if ((d01 > 0) && (d11 > 0)) { /* \  */
+	  LL;
+	  DUMP;
+	}
+	if ((d01 <= 0) && (d11 > 0)) { /* -  */
+	  HZ;
+	  DUMP;
+	}
+	if ((d01 <= 0) && (d11 <= 0)) { /* /  */
+	  UL;
+	  DUMP;
+	}
+	if ((d01 > 0) && (d11 <= 0)) { /* //  */
+	  UL;
+	  NUMP;
+	  LR;
+	  DUMP;
+	}
+      }
+      
+
+      if ((d00 <= 0) && (d10 <= 0)) { 
+	if ((d01 > 0) && (d11 <= 0)) {
+	  LR;
+	  DUMP;
+	}
+	if ((d01 <= 0) && (d11 > 0)) {
+	  UR;
+	  DUMP;
+	}
+	if ((d01 > 0) && (d11 > 0)) {
+	  VT;
+	  DUMP;
+	}
+      }
+
+      if ((d00 > 0) && (d10 > 0)) { 
+	if ((d01 <= 0) && (d11 > 0)) {
+	  LR;
+	  DUMP;
+	}
+	if ((d01 > 0) && (d11 <= 0)) {
+	  UR;
+	  DUMP;
+	}
+	if ((d01 <= 0) && (d11 <= 0)) {
+	  VT;
+	  DUMP;
+	}
+      }
+
+    }
+    /* skip left-hand edge */
+    v00++; v01++; v10++; v11++;
+    d01 = (level - *v00);
+    d11 = (level - *v10);
+  }
+
+  /****** bottom line *******/
+  v00 = matrix;  
+  v01 = matrix + 1;  
+  y = 0;
+  dx = 0;
+  dy = -0.5;
+  for (i = 1; i < Nx; i++, v00++, v01++) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      x = i + (level - *v01)/(*v01 - *v00);
+      NUMP;
+    }
+  }
+
+  /********** top line *******/
+  v00 = matrix + Nx*(Ny - 1);  
+  v01 = v00 + 1;
+  y = Ny - 1;
+  dx = 0;
+  dy = 0.5;
+  for (i = 1; i < Nx; i++, v00++, v01++) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      x = i + (level - *v01)/(*v01 - *v00);
+      NUMP;
+    }
+  }
+
+  /******** left line *********/
+  v00 = matrix; 
+  v01 = matrix + Nx;
+  x = 0;
+  dx = -0.5;
+  dy = 0;
+  for (j = 1; j < Ny; j++, v00+=Nx, v01+=Nx) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      y = j + (level - *v01)/(*v01 - *v00);
+      NUMP;
+    }
+  }
+
+  /******** right line *********/
+  v00 = matrix + Nx - 1; 
+  v01 = v00 + Nx;
+  x = Nx - 1;
+  dx = 0.5;
+  dy = 0;
+  for (j = 1; j < Ny; j++, v00+=Nx, v01+=Nx) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      y = j + (level - *v01)/(*v01 - *v00);
+      NUMP;
+    }
+  }
+  
+  if (Nline > 0) {
+    sprintf (line, "NLINES  %7d \0", Nline); 
+    write (Ximage, line, 16); 
+    write (Ximage, buffer, Nline*128); 
+  }
+
+  free (buffer);
+  sprintf (line, "DONE \0");
+  write (Ximage, line, 16);
+  if (Npix != 1) {
+    free (matrix);
+  }
+  fprintf (stderr, "\n");
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/vgrid.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/vgrid.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/vgrid.c	(revision 12606)
@@ -0,0 +1,86 @@
+# include "data.h"
+
+int vgrid (int argc, char **argv) {
+
+  int i, Nx, Ny, Xb, Yb;
+  float Xmin, Xmax, dX, Ymin, Ymax, dY;
+  float *buf, *val, *x, *y, *z;
+  int *Nval;
+  Buffer *bf;
+  Vector *vx, *vy, *vz;
+
+  if (argc != 11) {
+    fprintf (stderr, "USAGE: vgrid x y z buffer Xmin Xmax dX Ymin Ymax dY\n");
+    return (FALSE);
+  }
+  
+  if ((vx = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vy = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vz = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((bf = SelectBuffer (argv[4], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  if (vx[0].Nelements != vy[0].Nelements) return (FALSE);
+  if (vx[0].Nelements != vz[0].Nelements) return (FALSE);
+
+  Xmin = atof (argv[5]);
+  Xmax = atof (argv[6]);
+  dX   = atof (argv[7]);
+
+  Ymin = atof (argv[8]);
+  Ymax = atof (argv[9]);
+  dY   = atof (argv[10]);
+
+  Nx = (Xmax - Xmin) / dX + 1;
+  Ny = (Ymax - Ymin) / dY + 1;
+  
+  /* these steps are a standard 'createbuffer', define? */
+  bf[0].bitpix = -32;
+  bf[0].unsign = FALSE;
+  bf[0].bscale = 1.0;
+  bf[0].bzero  = 0.0;
+  strcpy (bf[0].file, "(empty)");
+
+  bf[0].header.bitpix = bf[0].bitpix;
+  bf[0].header.bscale = bf[0].bscale;
+  bf[0].header.bzero  = bf[0].bzero; 
+  bf[0].header.unsign = bf[0].unsign;
+  bf[0].header.Naxes = 2;
+  bf[0].header.Naxis[0] = Nx;
+  bf[0].header.Naxis[1] = Ny;
+  free (bf[0].header.buffer);  /* ALLOCATEd in SelectBuffer */
+  free (bf[0].matrix.buffer);  /* ALLOCATEd in SelectBuffer */
+  fits_create_header (&bf[0].header);
+  fits_create_matrix (&bf[0].header, &bf[0].matrix);
+
+  ALLOCATE (val, float, Nx*Ny);
+  bzero (val, Nx*Ny*sizeof(float));
+  ALLOCATE (Nval, int, Nx*Ny);
+  bzero (Nval, Nx*Ny*sizeof(int));
+
+  x = vx[0].elements;
+  y = vy[0].elements;
+  z = vz[0].elements;
+  for (i = 0; i < vx[0].Nelements; i++, x++, y++, z++) {
+    Xb = (*x - Xmin) / dX;
+    Yb = (*y - Ymin) / dY;
+    if (Xb >= Nx) continue;
+    if (Yb >= Ny) continue;
+    val[Xb + Yb*Nx] = *z;
+    Nval[Xb + Yb*Nx]++;
+  }
+
+  buf = (float *) bf[0].matrix.buffer;
+  for (i = 0; i < Nx*Ny; i++) {
+    if (Nval[i] == 0) {
+      buf[i] = 0;
+      continue;
+    }
+    buf[i] = val[i] / Nval[i];
+  }
+
+  free (val);
+  free (Nval);
+
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/vpop.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/vpop.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/vpop.c	(revision 12606)
@@ -0,0 +1,23 @@
+# include "data.h"
+
+int vpop (int argc, char **argv) {
+
+  int Npix;
+  Vector *vec;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: vpop (vector)\n");
+    fprintf (stderr, "  remove first element of vector\n");
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  Npix = vec[0].Nelements;
+  if (Npix < 1) return (TRUE);
+
+  if (Npix > 1) {
+    memmove (&vec[0].elements[0], &vec[0].elements[1], Npix*sizeof(float));
+  }
+  vec[0].Nelements = Npix - 1;
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/vroll.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/vroll.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/vroll.c	(revision 12606)
@@ -0,0 +1,23 @@
+# include "data.h"
+
+int vroll (int argc, char **argv) {
+
+  int Npix;
+  float first;
+  Vector *vec;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: vroll (vector)\n");
+    fprintf (stderr, "  roll vector elements (first goes to end)\n");
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  Npix = vec[0].Nelements;
+  if (Npix < 2) return (TRUE);
+
+  first = vec[0].elements[0];
+  memmove (&vec[0].elements[0], &vec[0].elements[1], Npix*sizeof(float));
+  vec[0].elements[Npix-1] = first;
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/vstat.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/vstat.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/vstat.c	(revision 12606)
@@ -0,0 +1,113 @@
+# include "data.h"
+
+int vstat (int argc, char **argv) {
+  
+  int i, N;
+  double max, min, sum, var, dvar, mean, stdev;
+  float *X, IgnoreValue;
+  int Ignore, Quiet;
+
+  int *Nval, bin, Nmode, Nmed;
+  double dx, mode, median;
+  Vector *vec;
+
+  Ignore = FALSE;
+  if (N = get_argument (argc, argv, "-ignore")) {
+    Ignore = TRUE;
+    remove_argument (N, &argc, argv);
+    IgnoreValue = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Quiet = FALSE;
+  if (N = get_argument (argc, argv, "-q")) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-quiet")) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: vstat (vector)\n");
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  /* we need two passes, one for max, min, mean, sum, one for median, stdev, etc */
+
+  /* calculate max, min, mean, sum, npix */
+  X = vec[0].elements;
+  max = min = *X;
+  sum = N = 0;
+  for (i = 0; i < vec[0].Nelements; i++, X++) {
+    if (!finite (*X)) continue;
+    if (Ignore && (*X == IgnoreValue)) continue;
+    max = MAX (*X, max);
+    min = MIN (*X, min);
+    sum += *X;
+    N++;
+  }      
+  mean = sum / N;
+
+  /* calculate median and mode with resolution of (max - min) / 1000 */ 
+  dx = (max - min) / 1000;
+  if (dx == 0) {
+    median = mode = min;
+    stdev = 0.0;
+    goto skip;
+  }
+
+  ALLOCATE (Nval, int, 1002);
+  bzero (Nval, 1000*sizeof(int));
+  X = vec[0].elements;
+  var = 0;
+  for (i = 0; i < vec[0].Nelements; i++, X++) {
+    if (!finite (*X)) continue;
+    if (Ignore && (*X == IgnoreValue)) continue;
+    bin = MAX (0, MIN (1000, (*X - min) / dx));
+    Nval[bin] ++;
+    dvar = (*X - mean);
+    var += dvar*dvar;
+  }      
+  stdev = sqrt (var / N);
+
+  Nmode = 0;
+  mode = Nval[Nmode];
+  median = 0;
+  Nmed = -1;
+  for (i = 0; i < 1001; i++) {
+    if (Nmed == -1) {
+      median += Nval[i];
+      if (median >= N / 2.0) {
+	Nmed = i;
+	median = i * dx + min;
+      }
+    }
+    if (mode < Nval[i]) {
+      Nmode = i;
+      mode = Nval[Nmode];
+    }
+  }
+  mode = Nmode * dx + min;
+  free (Nval);
+
+skip:
+  if (!Quiet) {
+    fprintf (stderr, "mean: %f, stdev: %f, min: %f, max: %f, median: %f, mode: %f, Npts: %d\n", 
+	     mean, stdev, min, max, median, mode, N);
+  }
+
+  set_variable ("MIN",      min);
+  set_variable ("MAX",      max);
+  set_variable ("MEDIAN",   median);
+  set_variable ("MEAN",     mean);
+  set_variable ("MODE",     mode);
+  set_variable ("TOTAL",    sum);
+  set_int_variable ("NPIX", N);
+  set_variable ("SIGMA",    stdev);
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/wd.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/wd.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/wd.c	(revision 12606)
@@ -0,0 +1,179 @@
+# include "data.h"
+
+int wd (int argc, char **argv) {
+  
+  int N, Extend;
+  int newUnsign, newBitpix, newScale, newZero;
+  int outUnsign, outBitpix;
+  double outScale, outZero;
+  Header temp_header;
+  Matrix temp_matrix;
+  Buffer *buf;
+
+  Extend  = FALSE;
+  if (N = get_argument (argc, argv, "-extend")) {
+    remove_argument (N, &argc, argv);
+    Extend  = TRUE;
+  }
+
+  newZero  = FALSE;
+  if (N = get_argument (argc, argv, "-bzero")) {
+    remove_argument (N, &argc, argv);
+    outZero  = atof(argv[N]);
+    newZero  = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  newScale = FALSE;
+  if (N = get_argument (argc, argv, "-bscale")) {
+    remove_argument (N, &argc, argv);
+    outScale = atof(argv[N]);
+    newScale = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  newBitpix = FALSE;
+  if (N = get_argument (argc, argv, "-bitpix")) {
+    remove_argument (N, &argc, argv);
+    outBitpix = atof(argv[N]);
+    newBitpix = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  newUnsign = FALSE;
+  if (N = get_argument (argc, argv, "-unsign")) {
+    remove_argument (N, &argc, argv);
+    outUnsign = -1;
+    if (!strcasecmp (argv[N], "t") || !strcasecmp (argv[N], "true")) outUnsign = TRUE;
+    if (!strcasecmp (argv[N], "f") || !strcasecmp (argv[N], "false")) outUnsign = FALSE;
+    if (outUnsign == -1) {
+      fprintf (stderr, "-unsign options: t, f, true, false\n");
+      return (FALSE);
+    }
+    newUnsign = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: wd <buffer> <filename> [-bitpix N] [-bscale X] [-bzero X] [-newplane]\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  if (!newBitpix) outBitpix = buf[0].bitpix;
+  if (!newScale) outScale = buf[0].bscale;
+  if (!newZero) outZero = buf[0].bzero;
+  if (!newUnsign) outUnsign = buf[0].unsign;
+
+  /* Convert the buffer from (float) to correct format */
+  /* save the (float) version, write out a temporary buffer */
+  temp_matrix = buf[0].matrix;
+  ALLOCATE (temp_matrix.buffer, char, MAX(1, temp_matrix.size));
+  memcpy (temp_matrix.buffer, buf[0].matrix.buffer, temp_matrix.size);
+  temp_header = buf[0].header;
+  ALLOCATE (temp_header.buffer, char, MAX(1, temp_header.size));
+  memcpy (temp_header.buffer, buf[0].header.buffer, temp_header.size);
+
+  if (temp_header.Naxes) fits_convert_format (&temp_header, &temp_matrix, outBitpix, outScale, outZero, outUnsign);
+
+  if (Extend) {
+    Header Xhead;
+    FILE *f;
+    int status, Nextend;
+
+    /* assume failure means non-existent file */
+    if (!fits_read_header (argv[2], &Xhead)) {
+
+      Xhead.simple = TRUE;
+      Xhead.bitpix = 16;
+      Xhead.Naxes = 0;
+      
+      Xhead.extend = TRUE;
+      Xhead.bscale = 1.0;
+      Xhead.bzero  = 0.0;
+      Xhead.unsign = FALSE;
+      
+      fits_create_header (&Xhead);
+      fits_modify (&Xhead, "NEXTEND", "%d", 1, 0);
+      f = fopen (argv[2], "w");
+      fclose (f);
+    }
+
+    fits_modify (&Xhead, "EXTEND", "%t", 1, TRUE);
+
+    Nextend = 0;
+    fits_scan (&Xhead, "NEXTEND", "%d", 1, &Nextend);
+    Nextend ++;
+    fits_modify (&Xhead, "NEXTEND", "%d", 1, Nextend);
+
+    /* write the main header to the start of the file */
+    f = fopen (argv[2], "r+");
+    if (f == NULL) {
+      fprintf (stderr, "failed to write file\n");
+      status = FALSE;
+      goto done1;
+    }
+    
+    /* position to begining of file to write header */
+    fseek (f, 0, SEEK_SET);
+    status = fwrite (Xhead.buffer, 1, Xhead.size, f);
+    if (status != Xhead.size) {
+      fprintf (stderr, "ERROR: failed writing data to image header\n");
+      status = FALSE;
+      goto done1;
+    }
+    
+    /* fix up header */
+    {
+      static char simple[] = "XTENSION= 'IMAGE  '            / Image extension";
+      int Ns, No;
+      Ns = strlen (simple);
+      No = 80 - Ns;
+      strncpy (temp_header.buffer, simple, Ns);
+      memset (&temp_header.buffer[Ns], ' ', No);
+    }
+
+    /* position to end of file to write new extend */
+    fseek (f, 0, SEEK_END);
+    status = fwrite (temp_header.buffer, 1, temp_header.size, f);
+    fclose (f);
+    if (status != temp_header.size) {
+      fprintf (stderr, "failed to write file\n");
+      status = FALSE;
+      goto done1;
+    }
+    /* write the matrix buffer (automatically goes to end of file */
+    if (!fits_write_matrix (argv[2], &temp_matrix)) {
+      fprintf (stderr, "failed to write file\n");
+      status = FALSE;
+      goto done1;
+    }
+    status = TRUE;
+  done1:
+    fits_free_header (&Xhead);
+    fits_free_header (&temp_header);
+    fits_free_matrix (&temp_matrix);
+    return (status);
+  }
+  
+  /* the actual write-to-disk goes here */
+  if (!fits_write_header (argv[2], &temp_header)) {
+    fprintf (stderr, "failed to write header\n");
+    fits_free_header (&temp_header);
+    fits_free_matrix (&temp_matrix);
+    return (FALSE);
+  }
+  
+  if (!fits_write_matrix (argv[2], &temp_matrix)) {
+    fprintf (stderr, "failed to write matrix\n");
+    fits_free_header (&temp_header);
+    fits_free_matrix (&temp_matrix);
+    return (FALSE);
+  }
+
+  fits_free_header (&temp_header);
+  fits_free_matrix (&temp_matrix);
+  
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/cmd.data/write_vectors.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/write_vectors.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/write_vectors.c	(revision 12606)
@@ -0,0 +1,139 @@
+# include "data.h"
+
+int write_vectors (int argc, char **argv) {
+  
+  int i, j, Nvec, Ne, N;
+  FILE *f;
+  char **fmtlist, *fmttype;
+  char *p0, *p1, *p2, *format;
+  Vector **vec;
+
+  /* look for format option */
+  format = (char *) NULL;
+  if (N = get_argument (argc, argv, "-f")) {
+    remove_argument (N, &argc, argv);
+    format = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc < 3) {
+    fprintf (stderr, "USAGE: write [-f \"format\"] file vector vector ...\n");
+    return (FALSE);
+  }
+
+  /* open file for outuput */
+  f = fopen (argv[1], "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open file for write\n");
+    return (FALSE);
+  }
+
+  /* find number of output vectors */
+  Nvec = (argc - 2);
+  if (Nvec < 1) {
+      fprintf (stderr, "USAGE: write (file) vector vector ...\n");
+      fclose (f);
+      return (FALSE);
+  }
+  ALLOCATE (vec, Vector *, Nvec);
+
+  /* select/check vectors from list */
+  for (i = 0; i < Nvec; i++) {
+    if ((vec[i] = SelectVector (argv[i + 2], OLDVECTOR, FALSE)) == NULL) {
+      fprintf (stderr, "USAGE: write (file) vector vector ...\n");
+      free (vec);
+      fclose (f);
+      return (FALSE);    
+    }
+  }
+  
+  /* select vector lengths */
+  Ne = vec[0][0].Nelements;
+  for (i = 0; i < Nvec; i++) {
+    if (vec[0][0].Nelements != Ne) {
+      fprintf (stderr, "error: vectors must all be the same size\n");
+      free (vec);
+      fclose (f);
+      return (FALSE);    
+    }
+  }
+
+  /* default output format */
+  if (format == (char *) NULL) {
+    for (i = 0; i < vec[0][0].Nelements; i++) {
+      for (j = 0; j < Nvec; j++) {
+	fprintf (f, "%.10g ", vec[j][0].elements[i]);
+      }
+      fprintf (f, "\n");
+    } 
+    fclose (f);
+    free (vec);
+    return (TRUE);
+  }
+
+  /* construct an array of format strings */
+  ALLOCATE (fmttype, char, Nvec);
+  ALLOCATE (fmtlist, char *, Nvec);
+  for (i = 0; i < Nvec; i++) {
+    ALLOCATE (fmtlist[i], char, 1024);
+    bzero (fmtlist[i], 1024);
+  }
+
+  p0 = format;
+  for (j = 0; j < Nvec; j++) {
+    /* find this format character */
+    p1 = strchr (p0, '%');
+    if (p1 == (char *) NULL) {
+      fprintf (stderr, "mismatch between format and values\n");
+      free (fmttype);
+      for (i = 0; i < Nvec; i++) free (fmtlist[i]);
+      free (fmtlist);
+      free (format);
+      fclose (f);
+      return (FALSE);
+    }
+    
+    /* identify type (%NNNNd %NNNNf) */
+    for (p2 = p1 + 1; (*p2 == '.') || (*p2 == '-') || (*p2 == '+') || (*p2 == ' ') || isdigit(*p2); p2++);
+    strncpy (fmtlist[j], p0, p2 - p0 + 1);
+    switch (*p2) {
+      case 'e':
+      case 'f':
+	fmttype[j] = 'f';
+	break;
+      case 'd':
+      case 'c':
+      case 'x':
+	fmttype[j] = 'd';
+	break;
+      default:
+	fprintf (stderr, "syntax error in format (only e,f,d,c,x allowed)\n");
+	return (FALSE);
+    }
+    p0 = p2 + 1;
+  }
+  strcat (fmtlist[Nvec-1], p0);
+  
+  for (i = 0; i < vec[0][0].Nelements; i++) {
+    for (j = 0; j < Nvec; j++) {
+      if (fmttype[j] == 'd') {
+	fprintf (f, fmtlist[j], (int)(vec[j][0].elements[i]));
+      } 
+      if (fmttype[j] == 'f') {
+	fprintf (f, fmtlist[j], (float)(vec[j][0].elements[i]));
+      } 
+    }
+    fprintf (f, "\n");
+  }
+  fclose (f);
+
+  free (fmttype);
+  for (i = 0; i < Nvec; i++) free (fmtlist[i]);
+  free (fmtlist);
+  free (format);
+  
+  return (TRUE);
+
+}
+
+
Index: /tags/start/Ohana/src/opihi/cmd.data/zap.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/zap.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/zap.c	(revision 12606)
@@ -0,0 +1,43 @@
+# include "data.h"
+
+int zap (int argc, char **argv) {
+
+  int i, j, N;
+  int sx, sy, nx, ny;
+  float *V, value;
+  Buffer *buf;
+
+  value = 0;
+  if (N = get_argument (argc, argv, "-v")) {
+    remove_argument (N, &argc, argv);
+    value  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 6) {
+    fprintf (stderr, "USAGE: zap <buffer> sx sy nx ny [-v value]\n");
+    return (FALSE);
+  }
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  sx = atof (argv[2]);
+  sy = atof (argv[3]);
+  nx = atof (argv[4]);
+  ny = atof (argv[5]);
+
+  if (sx < 0) goto error;
+  if (sy < 0) goto error;
+  if (sx + nx > buf[0].matrix.Naxis[0]) goto error;
+  if (sy + ny > buf[0].matrix.Naxis[1]) goto error;
+
+  for (j = sy; j < sy + ny; j++) {
+    V = (float *)(buf[0].matrix.buffer) + j*buf[0].matrix.Naxis[0] + sx; 
+    for (i = 0; i < nx; i++, V++) *V = value;
+  }
+  return (TRUE);
+
+ error:
+  fprintf (stderr, "region out of range\n");
+  return (FALSE);
+}
+
Index: /tags/start/Ohana/src/opihi/cmd.data/zplot.c
===================================================================
--- /tags/start/Ohana/src/opihi/cmd.data/zplot.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/cmd.data/zplot.c	(revision 12606)
@@ -0,0 +1,65 @@
+# include "data.h"
+
+int zplot (int argc, char **argv) {
+  
+  int i, N, Npts, Ngraph;
+  float *in, *out;
+  double min, range;
+  Graphdata graphmode;
+  Vector *xvec, *yvec, *zvec, Zvec;
+
+  Ngraph = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Ngraph = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);
+
+  if (argc != 6) {
+    fprintf (stderr, "USAGE: zplot <x> <y> <z> min max\n");
+    return (FALSE);
+  }
+
+  min = atof(argv[4]);
+  range = atof(argv[5]) - min;
+
+  /* find vectors */
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((zvec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if (xvec[0].Nelements != yvec[0].Nelements) {
+    fprintf (stderr, "vectors %s and %s not the same length\n", argv[1], argv[2]);
+    return (FALSE);
+  }
+  if (xvec[0].Nelements != zvec[0].Nelements) {
+    fprintf (stderr, "vectors %s and %s not the same length\n", argv[1], argv[3]);
+    return (FALSE);
+  }
+  Zvec.Nelements = zvec[0].Nelements;
+  ALLOCATE (Zvec.elements, float, Zvec.Nelements);
+ 
+  in = zvec[0].elements;
+  out = Zvec.elements;
+  for (i = 0; i < Zvec.Nelements; i++, in++, out++) {
+    *out = MIN (1.0, MAX (0.01, (*in - min) / range));
+  }
+
+  /* point size determined by Zvec */
+  graphmode.style = 2; /* plot points */
+  graphmode.size = -1; /* point size determined by Zvec */
+  graphmode.etype = 0; /* no errorbars */
+  Npts = xvec[0].Nelements;
+  PrepPlotting (Npts, &graphmode);
+
+  PlotVector (Npts, xvec[0].elements);
+  PlotVector (Npts, yvec[0].elements);
+  PlotVector (Npts, Zvec.elements);
+
+  free (Zvec.elements);
+
+  return (TRUE);
+
+}
+
+
Index: /tags/start/Ohana/src/opihi/dimm/Analysis.c
===================================================================
--- /tags/start/Ohana/src/opihi/dimm/Analysis.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dimm/Analysis.c	(revision 12606)
@@ -0,0 +1,112 @@
+# include "dimm.h"
+
+/* should this all be wrapped within an opihi implementation? */
+
+int subtractImage (Image *a, Image *b) {
+
+  if (a[0].Nx != b[0].Nx) return (FALSE);
+  if (a[0].Ny != b[0].Ny) return (FALSE);
+
+  Npix = a[0].Nx*a[0].Ny;
+  ap = (float *) a[0].buffer;
+  bp = (float *) b[0].buffer;
+  for (i = 0; i < Npix; i++, ap++, bp++) {
+    *ap -= *bp;
+  }
+  return (FALSE);
+}
+
+void statsImage (Image *image, Stats *stats) {
+
+  val = (float *)image[0].buffer;
+  max = min = val[0];
+  Npix = image[0].Nx*image[0].Ny;
+  for (i = 0; i < Npix; i++, val++) {
+    N1 += *val;
+    N2 += (*val)*(*val);
+    max = MAX (max, *val);
+    min = MIN (min, *val);
+  }
+  stats[0].mean  = N1 / Npix;
+  stats[0].sigma = sqrt (N2 / Npix - SQ(stats[0].mean));
+  stats[0].min = min;
+  stats[0].max = max;
+
+  stats[0].median = stats[0].mean;
+  range = MAX (0.5, 0xffff / (max - min));
+  if (range == 0) return;
+
+  ALLOCATE (hist, int, 0x10000);
+  bzero (hist, 0x10000*sizeof(int));
+
+  val = (float *)image[0].buffer;
+  for (i = 0; i < Npix; i++) {
+    bin = MIN (MAX (0, (*val - min) * range), 0xffff);
+    hist[bin] ++;
+  }
+
+  Nhist = 0;
+  for (i = 0; (i < 0xffff) && (Nhist < 0.5*Npix); i++) 
+    Nhist += hist[i];
+  stats[0].median = i / range + min;
+  free (hist);
+
+  return;
+}
+
+# if (0)
+void findStars (Image *image, Stars **stars, int *Nstars, double threshold) {
+
+  /* binarize @ threshold */
+
+  binimage = createImage (image[0].Nx, image[0].Ny);
+
+  Npix = image[0].Nx*image[0].Ny;
+  ap = image[0].buffer;
+  bp = binimage[0].buffer;
+  bzero (bp, Npix*sizeof (short));
+
+  for (i = 0; i < Npix; i++, ap++, bp++) {
+    if (*ap > threshold) * bp = 1;
+  }
+
+  clearpix ();
+
+  for (i = 0; i < Ny; i++) {
+    for (j = 0; j < Nx; j++) {
+      pix = j + i*Ny;
+      if (binimage.buffer[pix]) {
+	addpix (pix);
+	binimage.buffer[pix] = 0;
+	/* continue in row to end */
+	for (k = j + 1; k < Nx; k++) {
+	  pix = k + i*Nx;
+	  if (!binimage.buffer[pix]) { 
+	  }
+	}
+
+# endif
+
+/* find stars: 
+   - binarize @ threshold
+   - find all contiguous blobs
+   - find geom center of each blob
+*/
+
+
+
+/*
+
+.....................
+....x................
+...xxx...............
+....x...xxx..........
+.........xx..........
+.....................
+.....................
+.....................
+.....................
+.....................
+
+
+ */
Index: /tags/start/Ohana/src/opihi/dimm/Camera.c
===================================================================
--- /tags/start/Ohana/src/opihi/dimm/Camera.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dimm/Camera.c	(revision 12606)
@@ -0,0 +1,223 @@
+# include "dimm.h"
+
+static struct sbig_init info;
+
+int InitCamera (int port) {
+  
+  int i, state;
+
+  for (i = 0; i < 10; i++) {
+    state = sbig_init (port, SBIG_IMAGING_CCD, &info);
+    if (state == -6) state = 0;
+    if (state ==  0) {
+      DumpCameraInfo ();
+      return (TRUE);
+    }
+    fprintf (stderr, "retry...\n");
+  }
+  
+  fprintf (stderr, "failed to init sbig camera on %d\n", port);
+  fprintf (stderr, "%s\n", sbig_show_error (state));
+  return (FALSE);
+}
+
+void DumpCameraInfo () {
+
+      fprintf (stderr, "opened sbig camera:\n");
+      fprintf (stderr, "linux_version: %f\n",      info.linux_version);
+      fprintf (stderr, "nmbr_bad_columns: %d\n",   info.nmbr_bad_columns);
+      fprintf (stderr, "imaging_abg_type: %d\n",   info.imaging_abg_type);
+      fprintf (stderr, "serial_number: %s\n",      info.serial_number);
+      fprintf (stderr, "firmware_version: %d\n",   info.firmware_version);
+      fprintf (stderr, "camera_name: %s\n",        info.camera_name);
+      fprintf (stderr, "nmbr_readout_modes: %d\n", info.camera_info[0].nmbr_readout_modes);
+      fprintf (stderr, "mode: %d\n",               info.camera_info[0].readout_mode[0].mode);
+      fprintf (stderr, "width: %d\n",              info.camera_info[0].readout_mode[0].width);
+      fprintf (stderr, "height: %d\n",             info.camera_info[0].readout_mode[0].height);
+      fprintf (stderr, "gain: %d\n",               info.camera_info[0].readout_mode[0].gain);
+      fprintf (stderr, "pixel_width: %d\n",        info.camera_info[0].readout_mode[0].pixel_width);
+      fprintf (stderr, "pixel_height: %d\n",       info.camera_info[0].readout_mode[0].pixel_height);
+
+      fprintf (stderr, "ST5_AD_size: %d\n", info.ST5_AD_size);
+      fprintf (stderr, "ST5_filter_type: %d\n", info.ST5_filter_type);
+}      
+
+void CameraFullSize (int *x, int *y) {
+  *x = info.camera_info[0].readout_mode[0].width;
+  *y = info.camera_info[0].readout_mode[0].height;
+}
+
+int SetTemperature (double temp) {
+
+  int state;
+  struct sbig_cool cool;
+
+  if (temp < -50) return (FALSE);
+  if (temp > +20) return (FALSE);
+
+  cool.regulation = SBIG_TEMP_REGULATION_ON;
+  cool.temperature = (int) (10.0*temp + 0.5);
+  cool.direct_drive = 0;
+
+  state = sbig_set_cooling (&cool);
+  if (state < 0) {
+    fprintf (stderr, "sbig error: %s\n", sbig_show_error (state));
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+double GetTemperature () {
+
+  int state;
+  double temp;
+  struct sbig_status status;
+
+  state = sbig_get_status (&status);
+  if (state < 0) {
+    fprintf (stderr, "sbig error: %s\n", sbig_show_error (state));
+    return (-200.0);
+  }
+  temp = (status.ccd_temperature - 0.5) / 10.0;
+  return (temp);
+}
+
+int DumpCameraStatus () {
+
+  int state;
+  double temp;
+  struct sbig_status status;
+
+  state = sbig_get_status (&status);
+  if (state < 0) {
+    fprintf (stderr, "sbig error: %s\n", sbig_show_error (state));
+    return (FALSE);
+  }
+
+  fprintf (stderr, "imaging_ccd_status: %d\n", status.imaging_ccd_status);
+  fprintf (stderr, "tracking_ccd_status: %d\n", status.tracking_ccd_status);
+  fprintf (stderr, "fan_on: %d\n", status.fan_on);
+  fprintf (stderr, "shutter_state: %d\n", status.shutter_state);
+  fprintf (stderr, "led_state: %d\n", status.led_state);
+  fprintf (stderr, "shutter_edge: %d\n", status.shutter_edge);
+  fprintf (stderr, "plus_x_relay: %d\n", status.plus_x_relay);
+  fprintf (stderr, "minus_x_relay: %d\n", status.minus_x_relay);
+  fprintf (stderr, "plus_y_relay: %d\n", status.plus_y_relay);
+  fprintf (stderr, "minus_y_relay: %d\n", status.minus_y_relay);
+  fprintf (stderr, "pulse_active: %d\n", status.pulse_active);
+  fprintf (stderr, "temperature_regulation: %d\n", status.temperature_regulation);
+  fprintf (stderr, "temperature_setpoint: %d\n", status.temperature_setpoint);
+  fprintf (stderr, "cooling_power: %d\n", status.cooling_power);
+  fprintf (stderr, "air_temperature: %d\n", status.air_temperature);
+  fprintf (stderr, "ccd_temperature: %d\n", status.ccd_temperature);
+
+  return (TRUE);
+}
+
+/* block until exposure is complete */
+int Exposure (double exptime) {
+
+  int i, state;
+  struct sbig_expose expose;
+  struct sbig_status status;
+
+  expose.ccd = SBIG_IMAGING_CCD;
+  expose.exposure_time = (int)(100.0*exptime);
+  expose.abg_state = SBIG_ABG_OFF;
+  expose.shutter = SBIG_EXPOSE_SHUTTER_NORMAL;  /* shuttermode = ? */
+
+  /* drop this ? */
+  /* usleep ((int)(exptime*1000000)); */
+  state = sbig_expose (&expose);
+  if (state < 0) {
+    fprintf (stderr, "exposure error\n");
+    fprintf (stderr, "%s\n", sbig_show_error (state));
+    return (FALSE);
+  }
+  
+  for (i = 0; i < expose.exposure_time + 10; ++i) {
+    state = sbig_get_status (&status);
+    /* fprintf (stderr, "%d\n", state); */
+    /* fprintf (stderr, "%d  %d\n", status.imaging_ccd_status, status.shutter_state); */
+    /*    if (state == 0) return (TRUE); */
+    if (status.imaging_ccd_status == -SBIG_NO_EXPOSURE_IN_PROGRESS) return (TRUE);
+    if (status.imaging_ccd_status == -SBIG_EXPOSURE_IN_PROGRESS) {
+      usleep (10000);
+      continue;
+    }
+    fprintf (stderr, "exposure error\n");
+    fprintf (stderr, "%s\n", sbig_show_error (state));
+    return (FALSE);
+  }
+  fprintf (stderr, "exposure timeout\n");
+  return (FALSE);
+}
+
+int   readout_abort;
+float readout_percent;
+static int readout_callback (float percent) {
+  /* return 1 to continue, 0 to abort */
+  if (((int)(percent) % 10) == 0) { fprintf (stderr, "."); }
+  readout_percent = percent;
+  if (readout_abort) return 0;
+  return 1;
+}
+
+int ReadOut (int x, int y, int dx, int dy, int binning, unsigned short *buffer) {
+
+  int state, Nbytes;
+  static struct sbig_readout readout;
+
+  readout.x = x;
+  readout.y = y;
+  readout.width  = dx;
+  readout.height = dy;
+
+  Nbytes = readout.width*readout.height*sizeof(short);
+
+  /* for bin 2x2 or 3x3, need to adjust dx, dy above */
+  readout.ccd = SBIG_IMAGING_CCD;
+  readout.binning = SBIG_BIN_1X1;
+  readout.data = buffer;
+  readout.data_size_in_bytes = Nbytes;
+  readout.callback = readout_callback;
+    
+  fprintf (stderr, "%d, %d : %d x %d\n", readout.x, readout.y, readout.width, readout.height);
+  sync (); 
+  readout_abort = FALSE;
+  state = sbig_readout (&readout);
+  fprintf (stderr, "\n");
+  if (state < 0) {
+    fprintf (stderr, "sbig error: %s\n", sbig_show_error (state));
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+int OpenShutter () {
+
+  int state;
+  struct sbig_control control;
+
+  control.shutter = SBIG_OPEN_SHUTTER;
+  state = sbig_control (&control);
+  if (state < 0) {
+    fprintf(stderr, "sbig error: %s\n", sbig_show_error (state));
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+int CloseShutter () {
+
+  int state;
+  struct sbig_control control;
+
+  control.shutter = SBIG_CLOSE_SHUTTER;
+  state = sbig_control (&control);
+  if (state < 0) {
+    fprintf(stderr, "sbig error: %s\n", sbig_show_error (state));
+    return (FALSE);
+  }
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/dimm/Image.c
===================================================================
--- /tags/start/Ohana/src/opihi/dimm/Image.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dimm/Image.c	(revision 12606)
@@ -0,0 +1,85 @@
+# include "dimm.h"
+
+/*** this uses an Image structure from DIMM which 
+     is different from the Image structure in DVO ***/
+
+static Image *images = (Image *) NULL;
+static int   Nimages = 0;
+
+Image *createImage (int Nx, int Ny) {
+
+  int N;
+
+  if (Nx*Ny <= 0) return ((Image *) NULL);
+
+  N = Nimages;
+  Nimages ++;
+  if (images == (Image *) NULL) {
+    ALLOCATE (images, Image, MAX (1, Nimages));
+  } else {
+    REALLOCATE (images, Image, MAX (1, Nimages));
+  }
+
+  images[N].Nx = Nx;
+  images[N].Ny = Ny;
+  images[N].Nbytes = Nx*Ny*sizeof (short);
+  ALLOCATE (images[N].buffer, char, images[N].Nbytes);
+
+  return (&images[N]);
+}
+
+int freeImage (Image *entry) {
+
+  int i, j, N;
+
+  N = -1;
+  for (i = 0; (i < Nimages) && (N == -1) ; i++) {
+    if (&images[i] == entry) N = i;
+  }
+  if (N == -1) return (FALSE);
+
+  free (images[N].buffer);
+
+  for (j = N; j < Nimages - 1; j++) {
+    images[j] = images[j+1];
+  }
+
+  Nimages --;
+  REALLOCATE (images, Image, MAX (1, Nimages));
+  return (TRUE);
+}
+
+int writeImage (char *filename, Image *image) {
+
+  Header header;
+  Matrix matrix;
+
+  header.Naxes = 2;
+  header.Naxis[0] = image[0].Nx;
+  header.Naxis[1] = image[0].Ny;
+  header.bitpix = 16;
+  header.bzero = 0;
+  header.bscale = 1;
+
+  fits_create_header (&header);
+  fits_create_matrix (&header, &matrix);
+  free (matrix.buffer);
+
+  matrix.buffer = image[0].buffer;
+  
+  /* write meta-data to header */
+  fits_print (&header, "RA", "%lf", 1, image[0].ra);
+  fits_print (&header, "DEC", "%lf", 1, image[0].dec);
+  fits_print (&header, "EQUINOX", "%lf", 1, 2000.0);
+
+  fits_print (&header, "AIRMASS", "%lf", 1, image[0].airmass);
+  fits_print (&header, "CCDTEMP", "%lf", 1, image[0].ccdtemp);
+  fits_print (&header, "AIRTEMP", "%lf", 1, image[0].airtemp);
+  fits_print (&header, "EXPTIME", "%lf", 1, image[0].exptime);
+
+  fits_write_header (filename, &header);
+  fits_write_matrix (filename, &matrix);
+  
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/dimm/Makefile
===================================================================
--- /tags/start/Ohana/src/opihi/dimm/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dimm/Makefile	(revision 12606)
@@ -0,0 +1,110 @@
+include ../../../Configure
+
+default: all
+
+HOME    =       $(ROOT)/src/opihi.v2
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+HELP    =       $(HOME)/help
+SDIR    =       $(HOME)/dimm
+#
+DESTBIN =       $(LBIN)
+DESTLIB =       $(LLIB)
+DESTINC =       $(LINC)
+DESTMAN =       $(LMAN)
+#  
+INCS    =       -I$(INC) -I$(LINC) -I$(XINC)
+LFLAGS  =       -L$(LLIB) -L$(LIB)
+LIBS1   =       -lFITS -lsocket -lnsl -lreadline -ltermcap -lohana -lm
+LIBS2   =       -lbasiccmd -ldatacmd -lastrocmd -lshell -ldata -lsbig
+LIBS    =       $(LIBS2) $(LIBS1) 
+CFLAGS  =       $(INCS)
+CCFLAGS =       $(LIBS) 
+
+# dimm user commands and support functions #####################
+
+sbig: $(DESTINC)/sbig.h $(DESTLIB)/libsbig.a
+	@echo sbig code installed
+
+$(DESTINC)/sbig.h:	$(SDIR)/sbig/sbig.h
+	cp $(SDIR)/sbig/sbig.h $(DESTINC)/sbig.h
+
+$(DESTLIB)/libsbig.a:	$(SDIR)/sbig/sbig.a
+	cp $(SDIR)/sbig/sbig.a $(DESTLIB)/libsbig.a
+
+dimm = \
+$(SDIR)/init.$(ARCH).o		  	\
+$(SDIR)/dimm.$(ARCH).o		  	\
+$(SDIR)/altaz.$(ARCH).o		  	\
+$(SDIR)/camera.$(ARCH).o	  	\
+$(SDIR)/findstars.$(ARCH).o	  	\
+$(SDIR)/telescope.$(ARCH).o       	\
+$(SDIR)/Camera.$(ARCH).o		\
+$(SDIR)/Serial.$(ARCH).o		\
+$(SDIR)/Telescope.$(ARCH).o             
+
+# are these used or replaced?
+# $(SDIR)/analysis.$(ARCH).o	  	\
+# $(SDIR)/Analysis.$(ARCH).o            \
+# $(SDIR)/Image.$(ARCH).o		\
+
+all: dimm
+
+dimm: sbig $(BIN)/dimm.$(ARCH)
+	@echo done
+
+$(BIN)/dimm.$(ARCH) : $(dimm)
+
+install: $(DESTBIN)/dimm
+
+# utilities #################################################
+$(BIN)/%.$(ARCH):
+	@if [ ! -d $(BIN) ]; then mkdir -p $(BIN); fi
+	$(CC) $^ -o $@ $(LFLAGS) $(LIBS)
+	@echo "compiled $*"
+	@echo ""
+
+$(DESTBIN)/%: $(BIN)/%.$(ARCH) 
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	rm -f $(DESTBIN)/$*
+	cp $(BIN)/$*.$(ARCH) $(DESTBIN)/$*
+	@echo "installed $*"
+	@echo ""
+
+$(LIB)/%.$(ARCH).a:
+	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
+	rm -f $@
+	ar rcv $@ $^ 
+	ranlib $@
+	@echo "compiled library $*"
+	@echo ""
+
+$(DESTLIB)/%.a: $(LIB)/%.$(ARCH).a
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	@echo ""
+	rm -f $@
+	cp $^ $@
+
+lib%.clean:
+	rm -f $(LIB)/lib$*.$(ARCH).a
+	rm -f $($*)
+	@echo ""
+
+%.clean:
+	rm -f $(BIN)/$*.$(ARCH)
+	@echo ""
+
+%.$(ARCH).o : %.c
+	$(CC) $(CFLAGS) -c $*.c -o $@
+
+clean:
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f $(LIB)/*.$(ARCH).a
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+dist: clean
+	rm -f $(BIN)/*
+	rm -f $(LIB)/*
Index: /tags/start/Ohana/src/opihi/dimm/Serial.c
===================================================================
--- /tags/start/Ohana/src/opihi/dimm/Serial.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dimm/Serial.c	(revision 12606)
@@ -0,0 +1,388 @@
+# include "dimm.h"
+# include <termios.h>
+
+# define CR   0x0D
+# define LF   0x0A
+# define BEEP 0x07
+# define OPENERR    -1   /* Port could not be opened */
+# define PORTERR    -2   /* Opened port is not a serial (tty) port */
+# define BADCMDERR  -3   /* Command sent to camera is not understood */
+# define TIMEOUTERR -4   /* No response */
+ 
+# define SER_VERBOSE 0
+# define SER_DEBUG   0
+
+# ifndef SER_VERBOSE
+# define SER_VERBOSE 1           /* Be verbose? */
+# endif
+# ifndef SER_DEBUG 
+# define SER_DEBUG 1
+# endif
+
+/* Defines for Serial Port  */
+typedef struct {
+  int f;
+  int rate;
+  int parity;
+  int bits;
+  int stpbit;
+  char port[64];
+} Serial;
+
+static Serial serial = {0, 0, 0, 0, 0};
+static int SER_ECHO = 0;
+
+int SerialOpen (char *);
+
+int SerialVerbose (int mode) {
+
+  SER_ECHO = mode;
+  return (TRUE);
+
+}
+
+int SerialInit (char *port) {
+  
+  strcpy (serial.port, port);
+  serial.rate = 2400;
+  serial.rate = 9600;
+  serial.parity = 0;
+  serial.bits = 8;
+  serial.stpbit = 1;
+  
+  serial.f = SerialOpen (serial.port);
+  if (serial.f <= 0) {
+    fprintf (stderr, "Error opening serial port %s - error %d.\n", serial.port, serial.f);
+    return (FALSE);
+  }
+  if (SerialBaudRate (serial.f, serial.rate))   return (FALSE);
+  if (SerialParity   (serial.f, serial.parity)) return (FALSE);
+  if (SerialDataBits (serial.f, serial.bits))   return (FALSE);
+  if (SerialStopBit  (serial.f, serial.stpbit)) return (FALSE);
+  return (TRUE);
+}
+
+/********************************** Open *********************************/
+int SerialOpen (char *port) {
+  
+  int err = 0;
+  struct termios term;
+  char prefix[100];
+  int fdesc = -1;
+  int locked;
+  struct flock lock;
+   
+  /* open serial line */
+   if (SER_VERBOSE) printf ("Opening the serial port %s for read/write.\n", port);
+   fdesc = open (port, O_RDWR);
+   if (fdesc == -1) {
+     if (SER_VERBOSE) fprintf(stderr, "Cannot open %s for read/write.\n", port);
+     return OPENERR;
+   }
+   /* lock serial line */
+   lock.l_type = F_WRLCK;
+   lock.l_len = 0;
+   lock.l_start = 0;
+   lock.l_whence = 0;
+   locked = fcntl (fdesc, F_SETLK, &lock);
+   if (locked == -1) {
+     fprintf (stderr, "can't lock serial line\n");
+     close (fdesc);
+     return OPENERR;
+   }
+
+   /* Get the serial port's attributes... */
+   if (tcgetattr (fdesc, &term) == -1) {
+      if (SER_VERBOSE) fprintf(stderr, "Port is not a tty\n");
+      return PORTERR;
+   }
+
+   /* cfmakeraw (&term); */
+   term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+   term.c_oflag &= ~OPOST;
+   term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+   term.c_cflag &= ~(CSIZE|PARENB);
+   term.c_cflag |= CS8;
+   term.c_cc[VMIN] = 0;     /* MIN setting...if 0, wait only for timeout */
+   term.c_cc[VTIME] = 2;    /* TIME setting...wait at most 1 sec for response 
+		              (ignored if c_cc[VMIN]>0) */
+   tcsetattr (fdesc, TCSAFLUSH, &term);
+
+# if (0)   
+   term.c_lflag &= ~ICANON; /* Turn OFF canonical input 
+ 	                      (so it does it character by character) */
+   term.c_cc[VMIN] = 0;     /* MIN setting...if 0, wait only for timeout */
+   term.c_cc[VTIME] = 10;    /* TIME setting...wait at most 1 sec for response 
+		              (ignored if c_cc[VMIN]>0) */
+   term.c_lflag &= ~ECHO;   /* Turn OFF echoing... */
+   term.c_iflag &= ~ICRNL;   /* Don't map CR to NL on input */
+
+   /* Set port (terminal) to reflect the change...(flush first) */
+   tcsetattr (fdesc, TCSAFLUSH, &term);
+# endif
+
+   return fdesc;
+}
+
+/******************************* Baud Rate *******************************/
+int SerialBaudRate (int fdesc, int rate) {
+   int err = 0;
+   struct termios term;
+
+  /* Get the serial port's attributes... */
+   if (SER_VERBOSE) printf("Setting the serial port's baud rate.\n");
+   if (tcgetattr (fdesc, &term) == -1) {
+      if (SER_VERBOSE) fprintf (stderr, "Port is not a tty\n");
+      return PORTERR;
+   }
+ 
+   /* Set the input and output baud rates to 'rate'... */
+   switch (rate) { 
+   case 1200:         /* Set speed to 1200 */ 
+      if (cfgetospeed(&term) != B1200) cfsetospeed(&term, B1200);
+      if (cfgetispeed(&term) != B1200) cfsetispeed(&term, B1200);
+      break;
+   case 2400:         /* Set speed to 2400 */ 
+      if (cfgetospeed(&term) != B2400) cfsetospeed(&term, B2400);
+      if (cfgetispeed(&term) != B2400) cfsetispeed(&term, B2400);
+      break;
+   case 9600:         /* Set speed to 9600 */
+      if (cfgetospeed(&term) != B9600) cfsetospeed(&term, B9600);
+      if (cfgetispeed(&term) != B9600) cfsetispeed(&term, B9600);
+      break;
+   case 19200:        /* Set speed to 19200 */ 
+      if (cfgetospeed(&term) != B19200) cfsetospeed(&term, B19200);
+      if (cfgetispeed(&term) != B19200) cfsetispeed(&term, B19200);
+      break;
+   default:
+      printf ("ERROR:  Unknown Baud Rate\n"); 
+      break;
+   }	
+
+   /* Set port (terminal) to reflect the change...(flush first) */
+   tcsetattr(fdesc, TCSAFLUSH, &term);
+   return (FALSE);
+}
+
+/****************************** Parity ********************************/
+int SerialParity (int fdesc, int parity) { 
+   int err=0;
+   struct termios term;
+   char *prefix = "/dev/term/";
+
+   /* Get the serial port's attributes... */
+   if (SER_VERBOSE) printf("Setting the serial port's parity.\n");
+   if (tcgetattr(fdesc, &term) == -1) {
+      if (SER_VERBOSE) fprintf(stderr, "Port is not a tty\n");
+      return PORTERR;
+   }
+
+   if (parity == 0)              /* Turn off parity generation... */
+      term.c_cflag &= ~PARENB;     
+   else if (parity == 1) {            
+      term.c_cflag |= PARENB;     /* Turn on parity generation... */
+      term.c_cflag |= PARODD;     /* Sets parity to odd */ 
+   }	 
+   else if (parity == 2)         /* Turn on parity generation... */
+      term.c_cflag |= PARENB;     /* Defaults parity to even */ 
+   else 
+      printf ("ERROR:  Unknown parity specification\n");
+ 
+   /* Set port (terminal) to reflect the change...(flush first) */
+   tcsetattr(fdesc, TCSAFLUSH, &term);
+   return (FALSE);
+}
+
+/****************************Data Bit Size ***************************/
+int SerialDataBits(int fdesc, int bits) { 
+   int err=0;
+   struct termios term;
+
+   /* Get the serial port's attributes... */
+   if (SER_VERBOSE) printf("Setting the serial port's data bit size.\n");
+   if (tcgetattr(fdesc, &term) == -1) {
+      if (SER_VERBOSE) fprintf(stderr, "Port is not a tty\n");
+      return PORTERR;
+   }
+
+   switch (bits) {
+   case 5:  			/* Sets data bits to 5 */
+      term.c_cflag &= ~CSIZE; 
+      term.c_cflag |= CS5;
+      break; 
+   case 6:   			/* Sets data bits to 6 */ 
+      term.c_cflag &= ~CSIZE; 
+      term.c_cflag |= CS6;
+      break; 
+   case 7:     		/* Sets data bits to 7 */ 
+      term.c_cflag &= ~CSIZE; 
+      term.c_cflag |= CS7;
+      break; 
+   case 8:  			/* Sets data bits to 8 */
+      term.c_cflag &= ~CSIZE; 
+      term.c_cflag |= CS8;
+      break; 
+   default:
+      printf ("ERROR:  Illegal data bit size\n");
+      break; 
+   }
+
+   /* Set port (terminal) to reflect the change...(flush first) */
+   tcsetattr(fdesc, TCSAFLUSH, &term);
+   return (FALSE);
+}
+
+/****************************** Stop Bit ****************************/
+int SerialStopBit(int fdesc, int stpbit) { 
+   int err=0;
+   struct termios term;
+
+   /* Get the serial port's attributes... */
+   if (SER_VERBOSE) printf("Setting the serial port's stop bit.\n");
+   if (tcgetattr(fdesc, &term) == -1) {
+      if (SER_VERBOSE) fprintf(stderr, "Port is not a tty\n");
+      return PORTERR;
+   }
+
+   if (stpbit == 1) {     		/* Sets stop bit to 1 */  
+      if (term.c_cflag & CSTOPB) term.c_cflag |= CSTOPB;
+   } else { 				/* Else stop bit to 2 */ 
+      term.c_cflag & CSTOPB;
+   }
+
+   /* Set port (terminal) to reflect the change...(flush first) */
+   tcsetattr(fdesc, TCSAFLUSH, &term);
+   return (FALSE);
+}
+
+/**************************** Stop ***********************************/
+void SerialStop (int fdesc) {
+   if (SER_VERBOSE) printf("Closing the serial port.\n");
+   close(fdesc); /* Close up shop... */
+}
+
+# define D_NREAD 1024
+
+/* send a string to the serial port, wait for an answer */
+/* answer is returned on the pointer provided */
+
+/**************************** Command ***********************************/
+int SerialCommand (char *in, char **out, int wait) {
+  
+  int i, j;
+  char *line;
+  int done, Nread, Nin, NREAD;
+  
+  if (SER_ECHO) fprintf (stderr, "command: %s\n", in); 
+
+  if (serial.f <= 0) {
+    fprintf (stderr, "serial line closed\n"); 
+    if (out != (char **) NULL) {
+      *out = strcreate ("SERIAL OFF");
+      /* return (char *) NULL instead? */
+    }
+    return (FALSE);
+  }
+
+  /* flush out the line */
+  tcflush (serial.f, TCIOFLUSH);
+
+# if (0)
+  for (i = 0; i < strlen(in); i++) {
+    fprintf (stderr, "%d %x\n", i, in[i]);
+  }
+# endif
+
+  /* send command to serial line */
+  Nin = write (serial.f, in, strlen(in));
+  if (Nin != strlen(in)) {
+    fprintf (stderr, "Serial Command not sent\n");
+    return (FALSE);
+   }
+  usleep (20000);
+  /* LX200 GPS requires some lead time (10msec) to check ready state */
+  
+  /* create space to store answer */
+  NREAD = D_NREAD;
+  ALLOCATE (line, char, NREAD);
+  bzero (line, NREAD);
+  Nread = Nin = 0;
+
+  /* read data back from serial line until no response (Nin == 0) 
+     or timeout (Nin == -1) && (i == wait) */
+
+  done = FALSE;
+  for (i = 0; !done && (i < wait); i++) {
+    Nin = read (serial.f, &line[Nread], 256);
+# if (SER_DEBUG)
+    fprintf (stderr, "%d ", Nin);
+# endif
+    if (Nin < 0) { /* error, check value */
+      fprintf (stderr, "error?");
+      continue;
+    }
+    if (Nin > 0) {
+      Nread += Nin;
+      line[Nread] = 0;
+      i = 0;
+    }
+    if (Nread > D_NREAD - 257) {
+      NREAD += D_NREAD;
+      REALLOCATE (line, char, NREAD);
+    }
+    if ((i > 0) && (Nin == 0)) done = TRUE;
+    usleep (2000);
+  }
+
+  if (SER_ECHO) fprintf (stderr, "answer: %s\n", line);
+
+  if (out == (char **) NULL) {
+    free (line);
+  } else {
+    *out = line;
+  }
+  return (TRUE);
+}
+
+
+/* raw:
+   cfmakeraw sets the terminal attributes as follows:
+   termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+   termios_p->c_oflag &= ~OPOST;
+   termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+   termios_p->c_cflag &= ~(CSIZE|PARENB);
+   termios_p->c_cflag |= CS8;
+
+   there conditions are turned off:
+   c_iflag:
+       IGNBRK ignore BREAK condition on input
+       BRKINT If IGNBRK is not set, generate SIGINT on BREAK condition, else read BREAK as
+              character \0.
+       PARMRK if  IGNPAR  is  not  set,  prefix a character with a parity error or framing
+              error with \377 \0.  If neither IGNPAR nor PARMRK is set, read  a  character
+              with a parity error or framing error as \0.
+       (IGNPAR ignore framing errors and parity errors.)
+
+       ISTRIP strip off eighth bit
+       INLCR  translate NL to CR on input
+       IGNCR  ignore carriage return on input
+       ICRNL  translate carriage return to newline on input (unless IGNCR is set)
+       IXON   enable XON/XOFF flow control on output
+
+   c_oflag:
+       OPOST  enable implementation-defined output processing
+
+   c_lflag:
+       ECHO   echo input characters.
+       ECHONL if ICANON is also set, echo the NL character even if ECHO is not set.
+       ICANON enable canonical mode.  This enables the special characters EOF, EOL,  EOL2,
+              ERASE, KILL, REPRINT, STATUS, and WERASE, and buffers by lines.
+       ISIG   when any of the characters INTR, QUIT, SUSP, or DSUSP are received, generate
+              the corresponding signal.
+       IEXTEN enable implementation-defined input processing.
+
+   c_cflag:
+       CSIZE  character size mask.  Values are CS5, CS6, CS7, or CS8. (CS8 set).
+       PARENB enable parity generation on output and parity checking for input.
+
+*/
Index: /tags/start/Ohana/src/opihi/dimm/Telescope.c
===================================================================
--- /tags/start/Ohana/src/opihi/dimm/Telescope.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dimm/Telescope.c	(revision 12606)
@@ -0,0 +1,361 @@
+# include "dimm.h"
+
+# define SER_TIMEOUT 10
+# define SLEW_TIMEOUT 30
+# define dCOS(A)   ((double) cos ((double)RAD_DEG*A))
+# define dSIN(A)   ((double) sin ((double)RAD_DEG*A))
+
+double distSky (double r1, double r2, double d1, double d2) {
+
+  double x1, y1, z1;
+  double x2, y2, z2;
+  double cosT, dist;
+
+  x1 = dCOS (r1) * dCOS (d1);
+  y1 = dSIN (r1) * dCOS (d1);
+  z1 = dSIN (d1);
+
+  x2 = dCOS (r2) * dCOS (d2);
+  y2 = dSIN (r2) * dCOS (d2);
+  z2 = dSIN (d2);
+
+  cosT = x1*x2 + y1*y2 + z1*z2;
+  dist = DEG_RAD * acos (cosT);
+
+  return (dist);
+}
+
+int getRD (double *r, double *d) { 
+
+  int status;
+  char *rastr, *decstr;
+
+  status = SerialCommand (":GR#", &rastr, SER_TIMEOUT);
+  if (!status) return (FALSE);
+
+  status = SerialCommand (":GD#", &decstr, SER_TIMEOUT); 
+  if (!status) return (FALSE);
+
+  status = str_to_radec (r, d, rastr, decstr);
+  if (!status) return (FALSE);
+
+  free (rastr);
+  free (decstr);
+
+  return (TRUE);
+}
+
+int gotoRD (double r, double d) {
+
+  double R, D, dist;
+  int Ntry, status;
+  char *str, *answer, cmd[64];
+
+  /* error on ra, dec means coords out of range */
+
+  /* set telescope coords, send */
+  str = meade_ra_to_str (r);
+  sprintf (cmd, ":Sr%s#", str);   free (str);
+  status = SerialCommand (cmd, &answer, SER_TIMEOUT);
+  if (!status) return (FALSE); 
+  if (answer == (char *) NULL) return (FALSE); 
+  if (strcmp (answer, "1")) return (FALSE); 
+  free (answer);
+
+  str = meade_dec_to_str (d);
+  sprintf (cmd, ":Sd%s#", str);  free (str);
+  status = SerialCommand (cmd, &answer, SER_TIMEOUT);   
+  if (!status) return (FALSE); 
+  if (answer == (char *) NULL) return (FALSE); 
+  if (strcmp (answer, "1")) return (FALSE); 
+  free (answer);
+
+  Ntry = 0;
+  status = SerialCommand (":MS#", &answer, SER_TIMEOUT);   
+  if (!status) return (FALSE); 
+  if (answer == (char *) NULL) return (FALSE); 
+  if (strcmp (answer, "0")) {
+    fprintf (stderr, "error: %s\n", answer);
+    return (FALSE); 
+  }
+  free (answer);
+
+  /* watch for response? */
+  status = FALSE;
+  while (!status) {
+    getRD (&R, &D);
+    dist = distSky (R, r, D, d);
+    if (dist < 0.1) return (TRUE);
+    usleep (100000);
+    Ntry ++;
+    if (Ntry > SLEW_TIMEOUT) return (FALSE);
+  }
+  return (status);
+}
+
+/* actual offsets are x,y, convert to arcmin */
+int offset (char *direction, double distance) {
+
+  /* Four rate choices: 
+     slew   (RS) -  8 degree / sec : rate 1
+     find   (RM) - 30 arcmin / sec : rate 2
+     center (RC) -  4 arcmin / sec : rate 3
+     guide  (RG) - 15 arcsec / sec : rate 4
+
+     communication requires ~1.0 sec:
+     offset should use rate which gives shortest time > 2.0 sec 
+  */
+
+# define NRATE 4
+  static double delay[NRATE]  = {0.1, 0.1, 0.1, 0.1};
+  static double rate[NRATE]   = {480.0, 30.0, 4.0, 0.25};
+  static char rcmd[NRATE][16] = {"RS", "RM", "RC", "RG"};
+
+  int i, status, rsel;
+  char dir, cmd[32];
+  double tsel, dt;
+
+  dir = 0;
+  if (!strcasecmp (direction, "y")) dir = (distance > 0) ? 'n' : 's';
+  if (!strcasecmp (direction, "x")) dir = (distance > 0) ? 'w' : 'e';
+  if (!dir) return (FALSE);
+
+  /* distance is in arcmin */
+  distance = fabs (distance);
+
+  /* logic is bad -- does not catch too small distances */  
+  rsel = -1;
+  tsel = SLEW_TIMEOUT;
+  for (i = 0; i < NRATE; i++) {
+    dt = distance / rate[i] - delay[i];
+    if ((dt > 0) && (dt < tsel)) {
+      rsel = i;
+      tsel = dt;
+    }
+  }
+  if (tsel < 0) {
+    fprintf (stderr, "offset %f arcmin below minimum\n", distance);
+    return (FALSE);
+  }
+  if (tsel > SLEW_TIMEOUT) {
+    fprintf (stderr, "offset %f arcmin above maximum\n", distance);
+    return (FALSE);
+  }
+  fprintf (stderr, "offsetting %c for %f seconds\n", dir, tsel);
+  
+  sprintf (cmd, ":%s#", rcmd[rsel]);
+  status = SerialCommand (cmd, (char **) NULL, SER_TIMEOUT);
+  if (!status) return (FALSE);
+
+  sprintf (cmd, ":M%c#", dir);
+  status = SerialCommand (cmd, (char **) NULL, SER_TIMEOUT);
+  if (!status) return (FALSE);
+
+  usleep ((int)(tsel*1000000));
+
+  sprintf (cmd, ":Q%c#", dir);
+  status = SerialCommand (cmd, (char **) NULL, SER_TIMEOUT);
+  if (!status) return (FALSE);
+
+  return (TRUE);
+}  
+
+/* actual offsets are x,y, convert to arcmin */
+int toffset (char *direction, char *rate, double duration) {
+
+# define NRATE 6
+  /* static char rcmd[NRATE][16] = {"RS", "RM", "RC", "RG"};*/
+  static char rcmd[NRATE][64] = {"RS", "RM", "RC", "RG", "RA0.0085", "RE0.0085"};
+
+  int i, status, rsel;
+  char dir, cmd[32];
+  double tsel, dt;
+
+  dir = 0;
+  if (!strcasecmp (direction, "x")) dir = (duration > 0) ? 'w' : 'e';
+  if (!strcasecmp (direction, "y")) dir = (duration > 0) ? 'n' : 's';
+  if (!dir) return (FALSE);
+  duration = fabs (duration);
+  
+  status = FALSE;
+  for (i = 0; i < NRATE; i++) if (!strcmp (rcmd[i], rate)) status = TRUE;
+  if (!status) {
+    fprintf (stderr, "bad rate: %s\n", rate);
+    return (FALSE);
+  }
+
+  sprintf (cmd, ":%s#", rate);
+  status = SerialCommand (cmd, (char **) NULL, SER_TIMEOUT);
+  if (!status) return (FALSE);
+
+  sprintf (cmd, ":M%c#", dir);
+  status = SerialCommand (cmd, (char **) NULL, SER_TIMEOUT);
+  if (!status) return (FALSE);
+
+  usleep ((int)(duration*1000000));
+
+  sprintf (cmd, ":Q%c#", dir);
+  status = SerialCommand (cmd, (char **) NULL, SER_TIMEOUT);
+  if (!status) return (FALSE);
+
+  return (TRUE);
+}  
+
+int getXY (double *x, double *y) {
+
+  char *answer;
+
+  SerialCommand (":GA#", &answer, SER_TIMEOUT);
+  dms_to_ddd (x, answer);
+  free (answer);
+
+  SerialCommand (":GZ#", &answer, SER_TIMEOUT);
+  dms_to_ddd (y, answer);
+  free (answer);
+
+  return (TRUE);
+}
+
+/* need error checking on these */
+int setRD (double r, double d) {
+
+  char *str, *answer, cmd[64];
+
+  /* set telescope coords, send */
+  str = meade_ra_to_str (r);
+  sprintf (cmd, ":Sr%s#", str);
+  SerialCommand (cmd, (char **) NULL, SER_TIMEOUT);
+  free (str);
+
+  str = meade_dec_to_str (d);
+  sprintf (cmd, ":Sd%s#", str);
+  SerialCommand (cmd, (char **) NULL, SER_TIMEOUT);
+  free (str);
+
+  SerialCommand (":CM#", &answer, SER_TIMEOUT);
+  fprintf (stderr, "result: %s\n", answer);
+  free (answer);
+  return (TRUE);
+}
+
+int setSite (char *sitename, double lon, double lat) {
+
+  struct tm *gmt;
+  struct timeval now;
+  char *str, line[32];
+
+  fprintf (stderr, "careful, this causes problems\n");
+  return (FALSE);
+
+  SerialCommand (":W1#", (char **) NULL, SER_TIMEOUT);
+
+  /* Set site name 1 */
+  sprintf (line, ":SM %s#", sitename); 
+  SerialCommand (line, (char **) NULL, SER_TIMEOUT);
+
+  /* Set site long */
+  str = meade_deg_to_str (lon);
+  str[6] = 0;
+  sprintf (line, ":Sg%s#", str); 
+  SerialCommand (line, (char **) NULL, SER_TIMEOUT);
+  free (str);
+
+  /* Set site lat */
+  str = meade_dec_to_str (lat);
+  sprintf (line, ":St%s#", str); 
+  SerialCommand (line, (char **) NULL, SER_TIMEOUT);
+  free (str);
+
+  /* set UTC offset to 0.0: offset + local = gmt */
+  sprintf (line, ":SG+00#");
+  SerialCommand (line, (char **) NULL, SER_TIMEOUT);
+
+  /* Set local */
+  gettimeofday (&now, (struct timezone *) NULL);
+  gmt = gmtime (&now.tv_sec);
+  sprintf (line, ":SL%02d:%02d:%02d#", gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+  SerialCommand (line, (char **) NULL, SER_TIMEOUT);
+
+  return (TRUE);
+}
+
+int setTime (char *lst) {
+
+  struct tm *gmt;
+  struct timeval now;
+  char line[32], *answer;
+
+  /* set UTC offset to 0.0: offset + local = gmt */
+  sprintf (line, ":SG+10#");
+  SerialCommand (line, (char **) NULL, SER_TIMEOUT);
+
+  /* Set local */
+  gettimeofday (&now, (struct timezone *) NULL);
+  gmt = localtime (&now.tv_sec);
+  sprintf (line, ":SL%02d:%02d:%02d#", gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+  SerialCommand (line, (char **) NULL, SER_TIMEOUT);
+
+  /*
+  sprintf (line, ":SS%s#", lst);
+  SerialCommand (line, (char **) NULL, SER_TIMEOUT);
+  */
+
+  return (TRUE);
+}
+
+int getSite (double *lon, double *lat, double *lst) {
+
+  struct tm *gmt;
+  struct timeval now;
+  char *str, *answer, line[32];
+
+  /* : get latitude */
+  SerialCommand (":Gt#", &answer, SER_TIMEOUT);
+  dms_to_ddd (lat, answer);
+  free (answer);
+
+  /* : get longitude */
+  SerialCommand (":Gg#", &answer, SER_TIMEOUT);
+  dms_to_ddd (lon, answer);
+  free (answer);
+
+  /* : get LST */
+  SerialCommand (":GS#", &answer, SER_TIMEOUT);
+  dms_to_ddd (lst, answer);
+  free (answer);
+
+  return (TRUE);
+}
+
+int ParkScope() {
+
+  char *str, *answer, line[32];
+
+  SerialCommand (":hP#", &answer, SER_TIMEOUT);
+  free (answer);
+
+  return (TRUE);
+
+}
+
+int SleepScope() {
+
+  char *str, *answer, line[32];
+  
+  SerialCommand (":hN#", &answer, SER_TIMEOUT);
+  free (answer);
+  
+  return (TRUE);
+
+}
+
+int WakeScope() {
+
+  char *str, *answer, line[32];
+
+  SerialCommand (":hW#", &answer, SER_TIMEOUT);
+  free (answer);
+
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/dimm/altaz.c
===================================================================
--- /tags/start/Ohana/src/opihi/dimm/altaz.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dimm/altaz.c	(revision 12606)
@@ -0,0 +1,88 @@
+# include "dimm.h"
+
+# define dCOS(A)   ((double) cos ((double)RAD_DEG*A))
+# define dSIN(A)   ((double) sin ((double)RAD_DEG*A))
+
+double atan2 (double y, double x);
+
+int altaz (int argc, char **argv) {
+  
+  double alt, az, lat, rot;
+  double ha, dec;
+  double sind, sinh, cosh;
+  char *latstr;
+
+  if (argc != 6) goto usage;
+
+  if (!strcmp (argv[1], "-h")) goto radec;
+  if (!strcmp (argv[1], "-c")) goto altaz;
+
+ radec:
+  /* ha/dec -> alt/az */
+  ha  = atof (argv[2]);
+  dec = atof (argv[3]);
+
+  latstr = get_variable ("LATITUDE");
+  if (latstr == (char *) NULL) {
+    fprintf (stderr, "please define $LATITUDE\n");
+    return (FALSE);
+  }
+  lat = atof (latstr);
+  free (latstr);
+ 
+  sind = dSIN (dec) * dSIN (lat) + dCOS (dec) * dCOS (ha) * dCOS (lat);
+  alt  = DEG_RAD * asin (sind);
+
+  sinh = - dCOS (dec) * dSIN (ha);
+  cosh =   dSIN (dec) * dCOS (lat) - dCOS (dec) * dCOS (ha) * dSIN (lat);
+
+  az = DEG_RAD * atan2 (sinh, cosh);
+  set_variable (argv[4], alt);
+  set_variable (argv[5], az);
+
+  sinh = -dCOS(az) * dSIN(alt) * dSIN(ha) * dSIN(lat) + dSIN(az) * dSIN(alt) * dCOS(ha) - dSIN(ha) * dCOS(alt) * dCOS(lat);
+  cosh = -dSIN(az) * dSIN(ha) * dSIN(lat) - dCOS(az) * dCOS(ha);
+  rot = -DEG_RAD * atan2 (sinh, cosh);
+  set_variable ("ROT", rot);
+
+  return (TRUE);
+  
+ altaz:
+  /* alt/az -> ha/dec */
+  alt = atof (argv[4]);
+  az  = atof (argv[5]);
+
+  latstr = get_variable ("LATITUDE");
+  if (latstr == (char *) NULL) {
+    fprintf (stderr, "please define $LATITUDE\n");
+    return (FALSE);
+  }
+  lat = atof (latstr);
+  free (latstr);
+
+  sind = dSIN (alt) * dSIN (lat) + dCOS (alt) * dCOS (az) * dCOS (lat);
+  dec  = DEG_RAD * asin (sind);
+
+  sinh = -dCOS (alt) * dSIN (az);
+  cosh =  dSIN (alt) * dCOS (lat) - dCOS (alt) * dCOS (az) * dSIN (lat);
+
+  ha = DEG_RAD * atan2 (sinh, cosh);
+  set_variable (argv[2], ha);
+  set_variable (argv[3], dec);
+
+  sinh = -dCOS(az) * dSIN(alt) * dSIN(ha) * dSIN(lat) + dSIN(az) * dSIN(alt) * dCOS(ha) - dSIN(ha) * dCOS(alt) * dCOS(lat);
+  cosh = -dSIN(az) * dSIN(ha) * dSIN(lat) - dCOS(az) * dCOS(ha);
+  rot = -DEG_RAD * atan2 (sinh, cosh);
+  set_variable ("ROT", rot);
+
+  return (TRUE);
+  
+ usage:
+  fprintf (stderr, "USAGE: altaz -h (ha) (dec) (alt) (az)\n");
+  fprintf (stderr, "USAGE: altaz -c (ha) (dec) (alt) (az)\n");
+  fprintf (stderr, "       -h alt/az to ha/dec, -c ha/dec to alt/az\n");
+  fprintf (stderr, "       returned values in variables provided\n");
+  return (FALSE);
+
+}
+
Index: /tags/start/Ohana/src/opihi/dimm/analysis.c
===================================================================
--- /tags/start/Ohana/src/opihi/dimm/analysis.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dimm/analysis.c	(revision 12606)
@@ -0,0 +1,184 @@
+
+/* should this all be wrapped within an opihi implementation? */
+
+typedef struct {
+
+  /* image data area */
+  int Nx, Ny;
+  char *buffer;
+  int Nbytes;
+
+  /* image metadata */
+  double ccdtemp;
+  double airtemp;
+  double ra, dec, airmass;
+  double exptime;
+  int binning;
+} Image;
+
+subtractImage (Image *a, Image *b) {
+
+  if (a[0].Nx != b[0].Nx) return (FALSE);
+  if (a[0].Ny != b[0].Ny) return (FALSE);
+
+  Npix = a[0].Nx*a[0].Ny;
+  ap = (float *) a[0].buffer;
+  bp = (float *) b[0].buffer;
+  for (i = 0; i < Npix; i++, ap++, bp++) {
+    *ap -= *bp;
+  }
+  return (FALSE);
+}
+
+statsImage (Image *image, Stats *stats) {
+
+  val = (float *)image[0].buffer;
+  max = min = val[0];
+  Npix = image[0].Nx*image[0].Ny;
+  for (i = 0; i < Npix; i++, val++) {
+    N1 += *val;
+    N2 += (*val)*(*val);
+    max = MAX (max, *val);
+    min = MIN (min, *val);
+  }
+  stats[0].mean  = N1 / Npix;
+  stats[0].sigma = sqrt (N2 / Npix - SQ(stats[0].mean));
+  stats[0].min = min;
+  stats[0].max = max;
+
+  stats[0].median = stats[0].mean;
+  range = MAX (0.5, 0xffff / (max - min));
+  if (range == 0) return ();
+
+  ALLOCATE (hist, int, 0x10000);
+  bzero (hist, 0x10000*sizeof(int));
+
+  val = (float *)image[0].buffer;
+  for (i = 0; i < Npix; i++) {
+    bin = MIN (MAX (0, (*val - min) * range), 0xffff);
+    hist[bin] ++;
+  }
+
+  Nhist = 0;
+  for (i = 0; (i < 0xffff) && (Nhist < 0.5*Npix); i++) 
+    Nhist += hist[i];
+  stats[0].median = i / range + min;
+  free (hist);
+
+  return ();
+}
+
+findStars (Image *image, Stars **stars, int *Nstars, double threshold) {
+
+  /* binarize @ threshold */
+
+  binimage = createImage (image[0].Nx, image[0].Ny);
+
+  Npix = image[0].Nx*image[0].Ny;
+  ap = image[0].buffer;
+  bp = binimage[0].buffer;
+  bzero (bp, Npix*sizeof (short));
+
+  for (i = 0; i < Npix; i++, ap++, bp++) {
+    if (*ap > threshold) * bp = 1;
+  }
+
+  clearpix ();
+
+  for (j = 0; j < Ny; j++) {
+    for (i = 0; i < Nx; i++) {
+      if (binimage.buffer[j*Nx + i]) {
+	status = fillrow (binimage.buffer, Nx, j*Nx, i, &xs, &xe);
+	for (J = j + 1; (J < Ny) && status; J++) {
+	  for (I = xs; !binimage.buffer[J*Nx + I] && (I < xe); I++);
+	  if (binimage.buffer[J*Nx + I]) {
+	    status = fillrow (binimage.buffer, Nx, J*Nx, I, &xs, &xe);
+	  } 
+	}  
+	/* we now have a stack of pixels, convert to a single star */
+	statpix (&x, &y, image[0].buffer, Nx);
+	addstar (x, y);
+	clearpix ();
+      }
+    }
+  }
+}
+
+/* find contiguous trigger pixels in row from starting point */
+
+int fillrow (float *buffer, int Nx, int offset, int sx, int *xs, int *xe) {
+
+  trigger = FALSE;
+  for (i = sx, pix = offset + i; buffer[pix] && (i < Nx); i++, pix++) {
+    addpix (pix);
+    buffer[pix] = 0;
+    trigger = TRUE;
+    *xe = i;
+  }
+  for (i = sx - 1, pix = offset + i; (i >= 0) && buffer[pix]; i--, pix--) {
+    addpix (pix);
+    buffer[pix] = 0;
+    trigger = TRUE;
+    *xs = i;
+  }
+  return (trigger);
+}
+
+static int Npix = 0;
+static int *Pix = (int *) NULL;
+
+addpix (int pix) {
+  Npix ++;
+  if (Pix == (int *) NULL) {
+    ALLOCATE (Pix, int, MAX (1, Npix));
+  } else {
+    REALLOCATE (Pix, int, MAX (1, Npix));
+  }    
+  Pix[Npix - 1] = pix;
+}
+
+clearpix () {
+  Npix = 0;
+  REALLOCATE (Pix, int, 1);
+}
+
+statpix (double *x, double *y, float *buffer, int Nx) {
+
+  int X, Y;
+  double Sx, Sy, So;
+
+  So = Sx = Sy = 0;
+  for (i = 0; i < Npix; i++) {
+    Y = pix / Nx;
+    X = pix % Nx;
+    So += buffer[pix];
+    Sx += X * buffer[pix];
+    Sy += Y * buffer[pix];
+  }
+  *x = Sx / So;
+  *y = Sy / So;
+}
+
+/* find stars: 
+   - binarize @ threshold
+   - find all contiguous blobs
+   - find geom center of each blob
+*/
+
+
+
+/*
+
+.....................
+....x................
+...xxx...............
+..........xxx..........
+.........xx..........
+.....................
+.....................
+.....................
+.....................
+.....................
+
+
+ */
Index: /tags/start/Ohana/src/opihi/dimm/camera.c
===================================================================
--- /tags/start/Ohana/src/opihi/dimm/camera.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dimm/camera.c	(revision 12606)
@@ -0,0 +1,137 @@
+# include "dimm.h"
+# define EXIT_STATUS(S) { seteuid (UID); return (S); }
+
+static uid_t UID, EUID;
+
+SetEUID () {
+
+  /* save the UID (ID of calling process) and EUID (should be root) */
+  UID = getuid ();
+  EUID = geteuid ();
+  seteuid (UID);
+}
+
+int camera (int argc, char **argv) {
+  
+  /* USAGE: 
+     camera init port
+     camera expose exptime
+     camera readout x y dx dy
+     camera temp set value
+     camera temp get var
+  */
+
+  if (argc < 2) goto usage;
+
+  seteuid (EUID);
+  
+  if (!strcasecmp (argv[1], "init")) {
+    int port, status;
+
+    if (argc != 3) {
+      fprintf (stderr, "USAGE: camera init (port)\n");
+      EXIT_STATUS (FALSE);
+    }
+    sscanf (argv[2], "%x", &port);
+    status = InitCamera (port);
+    EXIT_STATUS (status);
+  }
+
+  if (!strcasecmp (argv[1], "expose")) {
+
+    int status;
+    double exptime;
+
+    if (argc != 3) {
+      fprintf (stderr, "USAGE: camera expose (exptime)\n");
+      EXIT_STATUS (FALSE);
+    }
+    exptime = atof (argv[2]);
+    status = Exposure (exptime);
+    EXIT_STATUS (status);
+  }
+
+  if (!strcasecmp (argv[1], "temp")) {
+
+    int status;
+    double temp;
+
+    if (argc != 3) {
+      fprintf (stderr, "USAGE: camera temp (temperature)\n");
+      EXIT_STATUS (FALSE);
+    }
+    temp = atof (argv[2]);
+    status = SetTemperature (temp);
+    EXIT_STATUS (status);
+  }
+
+  if (!strcasecmp (argv[1], "status")) {
+
+    int status;
+    double temp;
+
+    if (argc != 2) {
+      fprintf (stderr, "USAGE: camera status\n");
+      EXIT_STATUS (FALSE);
+    }
+    DumpCameraStatus ();
+    EXIT_STATUS (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "readout")) {
+
+    int Nbuf, status;
+    double temp;
+    int x, y, dx, dy, NX, NY;
+    Buffer *buf;
+
+    if ((argc != 7) && (argc != 3)) {
+      fprintf (stderr, "USAGE: camera readout (buffer) x y dx dy\n");
+      EXIT_STATUS (FALSE);
+    }
+
+    if ((buf = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) EXIT_STATUS (FALSE);
+
+    CameraFullSize (&NX, &NY);
+    x = y = 0;
+    dx = NX;
+    dy = NY;
+    if (argc == 7) {
+      x  = atof (argv[3]);
+      y  = atof (argv[4]);
+      dx = atof (argv[5]);
+      dy = atof (argv[6]);
+    } 
+
+    /* generate a buffer to store the image */
+    fits_free_matrix (&buf[0].matrix);
+    fits_free_header (&buf[0].header);
+    buf[0].header.bitpix = buf[0].bitpix = 16;
+    buf[0].header.unsign = buf[0].unsign = FALSE;
+    buf[0].header.bscale = buf[0].bscale = 1.0;
+    buf[0].header.bzero  = buf[0].bzero  = 0.0;
+    buf[0].header.Naxes = 2;
+    buf[0].header.Naxis[0] = dx;
+    buf[0].header.Naxis[1] = dy;
+    fits_create_header (&buf[0].header);
+    fits_create_matrix (&buf[0].header, &buf[0].matrix);
+
+    ReadOut (x, y, dx, dy, 1, buf[0].matrix.buffer);
+
+    fits_convert_format (&buf[0].header, &buf[0].matrix, -32, 1.0, 0.0, FT_UNSIGN_MODE);
+
+    EXIT_STATUS (TRUE);
+  }
+
+usage:
+  fprintf (stderr, "camera init port\n");
+  fprintf (stderr, "camera expose exptime\n");
+  fprintf (stderr, "camera readout x y dx dy\n");
+  fprintf (stderr, "camera temp set value\n");
+  fprintf (stderr, "camera temp get var\n");
+  seteuid (UID);
+  return (FALSE);
+
+}
+
+
Index: /tags/start/Ohana/src/opihi/dimm/dimm.c
===================================================================
--- /tags/start/Ohana/src/opihi/dimm/dimm.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dimm/dimm.c	(revision 12606)
@@ -0,0 +1,80 @@
+# include "opihi.h"
+
+# define opihi_name "DIMM"
+# define opihi_prompt "dimm: "
+# define opihi_description "DIMM telescope controller\n"
+# define opihi_history ".dimm"
+# define opihi_rcfile ".dimmrc"
+
+void InitBasic ();
+void InitData ();
+void InitAstro ();
+void InitDIMM ();
+
+void welcome () {
+  fprintf (stderr, "\n");
+  fprintf (stderr, "Welcome to %s - %s\n\n", opihi_name, opihi_description);
+}
+
+/* program-dependent initialization */
+void initialize (int argc, char **argv) {
+  
+  FILE *f;
+
+  auto_break = TRUE;
+
+  Nlists = 0;
+  ALLOCATE (lists, List, 1); 
+
+  /* init functions required by libraries */
+  /* -libopihi */
+  InitCommands ();
+  InitMacros ();
+  InitBuffers ();
+  InitVectors ();
+  InitVariables ();
+
+  /* -libdisplay */
+  InitGraph ();
+  InitImage ();
+
+  /* load the commands used by this implementation */
+  InitBasic ();
+  InitData ();
+  InitAstro ();
+  InitDIMM ();
+  InitOutfile ();
+
+  rl_readline_name = opihi_name;
+  rl_attempted_completion_function = command_completer;
+
+  set_str_variable ("HISTORY", opihi_history);
+  set_str_variable ("PROMPT", opihi_prompt);
+  set_str_variable ("RCFILE", opihi_rcfile);
+
+  /* here we open the history file for append.  it this fails, we
+     won't be able to write to it, warn the user.  otherwise, this
+     creates the file readline will write to, if it did not exist */  
+
+  /* check history file */
+  /* rewrite with fstat or stat */
+  f = fopen (opihi_history, "a");
+  if (f == NULL) /* no current history file here */
+    fprintf (stderr, "can't save history.\n");
+  else
+    fclose (f);
+  
+  stifle_history (200);
+  read_history (opihi_history);
+
+  signal (SIGINT, SIG_IGN);
+  return;
+}
+
+/* add program-dependent exit functions here */
+void cleanup () {
+  /* -libdisplay */
+  QuitImage ();
+  QuitGraph ();
+  return;
+}
Index: /tags/start/Ohana/src/opihi/dimm/findstars.c
===================================================================
--- /tags/start/Ohana/src/opihi/dimm/findstars.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dimm/findstars.c	(revision 12606)
@@ -0,0 +1,152 @@
+# include "dimm.h"
+
+int fillrow (char *buffer, int Nx, int offset, int sx, int *xs, int *xe);
+int addpix (int pix);
+int clearpix ();
+int freepix ();
+int statpix (float *x, float *y, float *buffer, int Nx);
+int addstar (double x, double y);
+
+Vector *vecx, *vecy, *vecf, *vecn;
+
+int findstars (int argc, char **argv) {
+
+  int i, j, I, J, Npix, Nbuf, status;
+  int xs, xe, Nx, Ny;
+  char *binary, *bp;
+  float *ap, threshold, x, y;
+  Buffer *buf;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: findstars (buffer) (threshold)\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  threshold = atof (argv[2]);
+
+  if ((vecx = SelectVector ("star_x", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vecy = SelectVector ("star_y", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vecf = SelectVector ("star_f", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vecn = SelectVector ("star_n", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  vecx[0].Nelements = vecy[0].Nelements = 0;
+  vecf[0].Nelements = vecn[0].Nelements = 0;
+
+  REALLOCATE (vecx[0].elements, float, 1);
+  REALLOCATE (vecy[0].elements, float, 1);
+  REALLOCATE (vecf[0].elements, float, 1);
+  REALLOCATE (vecn[0].elements, float, 1);
+
+  /* binarize @ threshold */
+  Nx = buf[0].header.Naxis[0];
+  Ny = buf[0].header.Naxis[1];
+  Npix = Nx*Ny;
+  ALLOCATE (binary, char, Npix);
+
+  ap = (float *) buf[0].matrix.buffer;
+  bp = binary;
+  bzero (bp, Npix);
+
+  for (i = 0; i < Npix; i++, ap++, bp++) {
+    if (*ap > threshold) *bp = 1;
+  }
+
+  for (j = 0; j < Ny; j++) {
+    for (i = 0; i < Nx; i++) {
+      if (binary[j*Nx + i]) {
+	clearpix ();
+	status = fillrow (binary, Nx, j*Nx, i, &xs, &xe);
+	for (J = j + 1; (J < Ny) && status; J++) {
+	  for (I = xs; !binary[J*Nx + I] && (I <= xe); I++);
+	  status = fillrow (binary, Nx, J*Nx, I, &xs, &xe);
+	}  
+	/* we now have a stack of pixels, find geometric center */
+	statpix (&x, &y, (float *)buf[0].matrix.buffer, Nx);
+      }
+    }
+  }
+  freepix ();
+  return (TRUE);
+}
+
+/* find contiguous trigger pixels in row from starting point */
+int fillrow (char *buffer, int Nx, int offset, int sx, int *xs, int *xe) {
+
+  int i, pix, trigger;
+
+  *xe = *xs = sx;
+  trigger = FALSE;
+  for (i = sx, pix = offset + i; buffer[pix] && (i < Nx); i++, pix++) {
+    addpix (pix);
+    buffer[pix] = 0;
+    trigger = TRUE;
+    *xe = i;
+  }
+  for (i = sx - 1, pix = offset + i; (i >= 0) && buffer[pix]; i--, pix--) {
+    addpix (pix);
+    buffer[pix] = 0;
+    trigger = TRUE;
+    *xs = i;
+  }
+  return (trigger);
+}
+
+static int Npixlist = 0;
+static int *pixlist = (int *) NULL;
+
+addpix (int pix) {
+  Npixlist ++;
+  if (pixlist == (int *) NULL) {
+    ALLOCATE (pixlist, int, MAX (1, Npixlist));
+  } else {
+    REALLOCATE (pixlist, int, MAX (1, Npixlist));
+  }    
+  pixlist[Npixlist - 1] = pix;
+}
+
+clearpix () {
+  Npixlist = 0;
+  REALLOCATE (pixlist, int, 1);
+}
+
+freepix () {
+  Npixlist = 0;
+  free (pixlist);
+  pixlist = (int *) NULL;
+}
+
+statpix (float *x, float *y, float *buffer, int Nx) {
+
+  int i, X, Y, pix, Nv, No;
+  double Sx, Sy, So;
+
+  So = Sx = Sy = 0;
+  for (i = 0; i < Npixlist; i++) {
+    pix = pixlist[i];
+    Y = pix / Nx;
+    X = pix % Nx;
+    So += buffer[pix];
+    Sx += X * buffer[pix];
+    Sy += Y * buffer[pix];
+  }
+  *x = Sx / So;
+  *y = Sy / So;
+  fprintf (stderr, "%f %f  %f %d\n", *x, *y, So, Npixlist);
+
+  No = vecx[0].Nelements;
+  Nv = No + 1;
+  vecx[0].Nelements = vecy[0].Nelements = Nv;
+  vecf[0].Nelements = vecn[0].Nelements = Nv;
+
+  REALLOCATE (vecx[0].elements, float, MAX (Nv, 1));
+  REALLOCATE (vecy[0].elements, float, MAX (Nv, 1));
+  REALLOCATE (vecf[0].elements, float, MAX (Nv, 1));
+  REALLOCATE (vecn[0].elements, float, MAX (Nv, 1));
+
+  vecx[0].elements[No] = *x;
+  vecy[0].elements[No] = *y;
+  vecf[0].elements[No] = So;
+  vecn[0].elements[No] = Npixlist;
+
+}
Index: /tags/start/Ohana/src/opihi/dimm/init.c
===================================================================
--- /tags/start/Ohana/src/opihi/dimm/init.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dimm/init.c	(revision 12606)
@@ -0,0 +1,23 @@
+# include "dvo.h"
+
+int altaz           PROTO((int, char **));
+int camera          PROTO((int, char **));
+int findstars       PROTO((int, char **));
+int telescope       PROTO((int, char **));
+
+static Command cmds[] = {  
+  {"altaz",            altaz,            "altaz / celestial coord conversions"},
+  {"camera",           camera,           "camera functions"},
+  {"findstars",        findstars,        "find objects on image"},
+  {"telescope",        telescope,        "telescope communications"},
+}; 
+
+void InitDIMM () {
+  
+  int i;
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+
+}
Index: /tags/start/Ohana/src/opihi/dimm/sbig/sbig.h
===================================================================
--- /tags/start/Ohana/src/opihi/dimm/sbig/sbig.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dimm/sbig/sbig.h	(revision 12606)
@@ -0,0 +1,222 @@
+#ifndef _SBIG_H
+#define _SBIG_H
+
+#define VERSION  2.0
+
+struct sbig_init {
+    float linux_version;
+    int	 nmbr_bad_columns;	/* bad columns in imaging CCD */
+    int  bad_columns[4];
+    int  imaging_abg_type;	/* 0 no ABG, 1 ABG present */
+    char serial_number[10];
+    unsigned firmware_version;
+    char  camera_name[64];
+    struct camera_info {
+	int  nmbr_readout_modes;
+	struct readout_mode {
+	    int  mode;
+	    int  width;			/* pixels */
+	    int  height;		/* height */
+	    int  gain;			/* in 0.01 e-/ADU */
+	    unsigned pixel_width;	/* in nanometers */
+	    unsigned pixel_height;	/* in nanometers */
+	} readout_mode[12];
+    } camera_info[2];
+    int ST5_AD_size;
+    int ST5_filter_type;
+};
+extern int  sbig_init(int port, int options, struct sbig_init *);
+
+#define SBIG_IMAGING_CCD 0
+#define SBIG_TRACKING_CCD 1
+
+#define SBIG_CCD_STATUS_IDLE  0
+#define SBIG_CCD_STATUS_IN_PROGRESS  2
+#define SBIG_CCD_STATUS_COMPLETE  3
+
+#define SBIG_CCD_SHUTTER_OPENED  0
+#define SBIG_CCD_SHUTTER_CLOSED  1
+#define SBIG_CCD_SHUTTER_OPENING  2
+#define SBIG_CCD_SHUTTER_CLOSING  3
+
+struct sbig_status {
+    int  imaging_ccd_status;
+    int  tracking_ccd_status;
+    int  fan_on;
+    int  shutter_state;
+    int  led_state;
+    int  shutter_edge;
+    int  plus_x_relay;
+    int  minus_x_relay;
+    int  plus_y_relay;
+    int  minus_y_relay;
+    int  pulse_active;
+    int  temperature_regulation;
+    int  temperature_setpoint;
+    int  cooling_power;
+    int  air_temperature;
+    int  ccd_temperature;
+};
+extern int  sbig_get_status(struct sbig_status *);
+
+
+#define SBIG_LEAVE_SHUTTER  0
+#define SBIG_OPEN_SHUTTER  1
+#define SBIG_CLOSE_SHUTTER  2
+#define SBIG_INITIALIZE_SHUTTER  3
+
+#define SBIG_LED_OFF  0
+#define SBIG_LED_ON  1
+#define SBIG_LED_BLINK_SLOW 2
+#define SBIG_LED_BLINK_FAST 3
+
+struct sbig_control {
+    int  fan_on;
+    int  shutter;
+    int  led;
+};
+extern int  sbig_control(struct sbig_control *);
+
+struct sbig_pulse {
+    int nmbr_pulses;		/* 0 to 255 */
+    int pulse_width;		/* microsec, min 9 */
+    int pulse_interval;		/* microsec, min 27+pulse_width */
+};
+extern int  sbig_pulse(struct sbig_pulse *);
+
+struct sbig_relay {
+    int x_plus_time;
+    int x_minus_time;
+    int y_plus_time;
+    int y_minus_time;
+};
+extern int  sbig_activate_relay(struct sbig_relay *);
+
+
+/*
+ * Shutter control.  0 for no change in shutter (i.e. control of shutter
+ * using SBigControl class), 1 normal shutter (open during exposure,
+ * closed otherwise), 2 shutter closed (for taking dark frames).
+ */
+#define SBIG_EXPOSE_SHUTTER_UNCHANGED  0
+#define SBIG_EXPOSE_SHUTTER_NORMAL  1
+#define SBIG_EXPOSE_SHUTTER_CLOSED  2
+
+struct sbig_expose {
+    int ccd;
+    int exposure_time;
+    int abg_state;
+    int shutter;
+};
+extern int  sbig_expose(struct sbig_expose *);
+
+
+/*
+ *  Terminate the image and read it out.
+ *  Use width == 0 and height == 0 to abort an image with no readout (all
+ *   params other than ccd ignored)
+ */
+#define SBIG_BIN_1X1  0
+#define SBIG_BIN_2X2  1
+#define SBIG_BIN_3X3  2
+
+struct sbig_readout {
+    int ccd;
+    int binning;
+    int x, y;
+    int width, height;
+    unsigned short *data;
+    int data_size_in_bytes;
+    int (*callback)(float percent_complete);
+};
+extern int  sbig_readout(struct sbig_readout *);
+
+#define SBIG_NO_SHUTTER_DELAY  0x0001	/* don't wait for shutter to close */
+struct sbig_readout2 {
+    int flags;				/* see immediately above */
+    int ccd;
+    int binning;
+    int x, y;
+    int width, height;
+    unsigned short *data;
+    int data_size_in_bytes;
+    int (*callback)(float percent_complete);
+};
+extern int  sbig_readout2(struct sbig_readout2 *);
+
+
+#define SBIG_TEMP_REGULATION_OFF  0
+#define SBIG_TEMP_REGULATION_ON  1
+#define SBIG_TEMP_REGULATION_DIRECT_DRIVE  2
+
+/*
+ * Antiblooming gate control values
+ */
+#define SBIG_ABG_OFF  0
+#define SBIG_ABG_LOW  1
+#define SBIG_ABG_MEDIUM  2
+#define SBIG_ABG_HIGH  3
+
+struct sbig_cool {
+    int regulation;		/* 0 off, 1 on, 2 direct_drive */
+    int temperature;		/* in 0.1 deg C, if 'on' */
+    int direct_drive;		/* power [0..255], direct_drive */
+};
+extern int  sbig_set_cooling(struct sbig_cool *);
+
+extern int  sbig_set_ao7_deflection(int x_deflection, int y_deflection);
+
+extern int  sbig_set_ao7_focus(int type);
+
+#define SBIG_AO7_FOCUS_SOFT_CENTER 4
+#define SBIG_AO7_FOCUS_HARD_CENTER  3
+#define SBIG_AO7_FOCUS_STEP_TOWARD_SCOPE 2
+#define SBIG_AO7_FOCUS_STEP_FROM_SCOPE 1
+
+/*
+ *	Return Error Codes
+ *
+ *	These are the error codes returned by the driver
+ *	function.  They are prefixed with CE_ to designate
+ *	them as camera errors.
+ *
+ *      The return codes from the sbig_xxx() routines will
+ *      be the NEGATIVE of these on an error.
+ *
+ */
+#define SBIG_CAMERA_NOT_FOUND	-1
+#define SBIG_EXPOSURE_IN_PROGRESS -2
+#define SBIG_NO_EXPOSURE_IN_PROGRESS -3
+#define SBIG_UNKNOWN_COMMAND	-4
+#define SBIG_BAD_CAMERA_COMMAND	-5
+#define SBIG_BAD_PARAMETER	-6
+#define SBIG_TX_TIMEOUT		-7
+#define SBIG_RX_TIMEOUT		-8
+#define SBIG_NAK_RESBIGIVED	-9
+#define SBIG_CAN_RESBIGIVED	-10
+#define SBIG_UNKNOWN_RESPONSE	-11
+#define SBIG_BAD_LENGTH		-12
+#define SBIG_AD_TIMEOUT		-13
+#define SBIG_CHECKSUM_ERROR	-14
+#define SBIG_EEPROM_ERROR	-15
+#define SBIG_SHUTTER_ERROR	-16
+#define SBIG_UNKNOWN_CAMERA	-17
+#define SBIG_DRIVER_NOT_FOUND	-18
+#define SBIG_DRIVER_NOT_OPEN	-19
+#define SBIG_DRIVER_NOT_CLOSED	-20
+#define SBIG_SHARE_ERROR	-21
+#define SBIG_TSBIG_NOT_FOUND	-22
+#define SBIG_NEXT_ERROR		-23
+#define SBIG_NOT_ROOT		-24
+char *sbig_show_error(int);
+
+/*
+ * IO strategy flags
+ */
+#define SBIG_DISABLE_INTERRUPTS 0x001
+#define SBIG_LOCK_ALL	0x002
+#define SBIG_SHORT_DELAYS 0x004
+#define SBIG_DEFAULT_STRATEGY (SBIG_DISABLE_INTERRUPTS|SBIG_LOCK_ALL)
+void sbig_set_linux_strategy(int);
+
+#endif /* S_BIG_H */
Index: /tags/start/Ohana/src/opihi/dimm/sbig/sp_ccdcontrol.c
===================================================================
--- /tags/start/Ohana/src/opihi/dimm/sbig/sp_ccdcontrol.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dimm/sbig/sp_ccdcontrol.c	(revision 12606)
@@ -0,0 +1,470 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <math.h>
+#include <time.h>
+#include <fcntl.h>
+#include <values.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include "sbig.h"
+#include "fh/fh.h" /* CFHT FITS Handling library */
+
+#define N_FITS_ENTRIES 33
+
+/*
+ * The following hack is needed if you want to use sbig.a w/ libc5
+ */
+#ifndef __bzero
+void __bzero(void* s, int n)
+{
+  memset(s, 0, n);
+}
+#endif
+
+static struct sbig_init info;
+
+static int write_fits(int width, int height, double etime, int binmode, unsigned short *data);
+
+static struct sbig_readout readout;
+
+/*
+ * This is the 'progress' callback
+ * passed to sbig_readout()
+ */
+static int readout_callback(float percent)
+{
+  fprintf(stderr, "progress: Reading %d x %d pixels (%d%%)\r",
+	  readout.width, readout.height, (int)percent);
+  /* return 1 to continue, 0 to abort */
+  return 1;
+}
+
+/*
+ *  Start an exposure, wait for it, then download from the camera
+ *  in bands.  This is somewhat complex, since it handles any size
+ *  subimage of the CCD, and bands too.
+ */
+static void take_picture(double etime, int binmode, int shuttermode, int x, int y, int w, int h)
+{
+  int  ret, i, needed;
+  static unsigned short  *buffer;
+  static int  buffer_size;
+  struct sbig_expose  expose;
+  struct sbig_status  status;
+  double  f;
+  
+  expose.ccd = 0; /* Always in imaging mode, not tracking 
+		    since CFHT PF does the tracking*/
+
+  if(binmode<0 || binmode>3){
+    fprintf(stderr, "Imaging binmode options: [0=1x1, *1=2x2, 2=3x3]\n");
+    exit(EXIT_FAILURE);
+  }
+  readout.binning=binmode;
+  
+  readout.x=x;
+  readout.y=y;
+  readout.width=w;
+  readout.height=h;
+  if (readout.width == 0) {
+    readout.width =
+      info.camera_info[expose.ccd].readout_mode[readout.binning].width - x;
+  } else
+    if (readout.width + x >
+	info.camera_info[expose.ccd].readout_mode[readout.binning].width) {
+    fprintf(stderr, "Raster X or Width parameter out of range.\n");
+    exit(EXIT_FAILURE);
+  }
+
+  if (readout.height == 0) {
+    readout.height =
+      info.camera_info[expose.ccd].readout_mode[readout.binning].height - y;
+  } else
+    if (readout.height + y >
+	info.camera_info[expose.ccd].readout_mode[readout.binning].height) {
+    fprintf(stderr, "Raster Y or Height parameter out of range.\n");
+    exit(EXIT_FAILURE);
+  }
+
+  f = etime;
+  expose.exposure_time = (int)(100.0*f);
+  expose.abg_state = SBIG_ABG_OFF; /* SBIG_ABG_MEDIUM */
+
+  expose.shutter = shuttermode;  /* No shutter present */
+
+  sync();
+  ret = sbig_expose(&expose);
+  if (ret < 0)
+    fprintf(stderr, "sbig error: %s\n", sbig_show_error(ret));
+  
+  fprintf(stderr, "progress: Sleeping for %g seconds\r", 0.01*expose.exposure_time);
+
+  if (expose.exposure_time > 100) {
+    for (i = 0; i < expose.exposure_time; i += 100) {
+      sbig_get_status(&status);
+      fprintf(stderr, "progress: Exposure in progress; ccd_status=%d, shutter=%d (%d%%)\r",
+	      status.imaging_ccd_status, status.shutter_state,
+	      i * 100 / expose.exposure_time);
+      sleep(1);
+    }
+  } else
+    usleep(expose.exposure_time*10000);
+  
+  /* wait for exposure to complete */
+  fprintf(stderr, "progress: Waiting for controller                             (100%%)\r");
+
+  for (i = 0; i < 1000; ++i) {
+    ret = sbig_get_status(&status);
+    if (ret < 0) {
+      fprintf(stderr, "sbig error: %s\n", sbig_show_error(ret));
+      break;
+    }
+    if (status.imaging_ccd_status != 3)
+      fprintf(stderr, "logonly: ccd_status=%d\n", status.imaging_ccd_status);
+
+    if (readout.ccd == 0) {
+      if (status.imaging_ccd_status != 2)
+	break;
+    } else {
+      if (status.tracking_ccd_status != 2)
+	break;
+    }
+    usleep(50000);
+  }
+  if (i)
+    fprintf(stderr, "warning: Exposure took an extra %g seconds\n", 0.050*i);
+
+  if (i == 1000)
+    fprintf(stderr, "error: EXPOSURE DIDN'T FINISH!\n");
+  else
+    fprintf(stderr, "progress: Exposure complete                                  (100%%)\n");
+
+  readout.ccd = expose.ccd;
+  readout.binning = readout.binning;
+  needed = readout.height*readout.width*sizeof(short);
+  if (buffer_size < needed) {
+    if (buffer != NULL)
+      free(buffer);
+    buffer = malloc(buffer_size = needed);
+  }
+  readout.data = buffer;
+  readout.data_size_in_bytes = buffer_size;
+  readout.callback = readout_callback;
+    
+  sync();
+  if ((ret = sbig_readout(&readout)) < 0) {
+    fprintf(stderr, "sbig error: %s\n", sbig_show_error(ret));
+    return;
+  }
+
+  fprintf(stderr, "progress: Writing FITS data to stdout\n");
+
+  if(write_fits(readout.width, readout.height, etime, binmode, buffer)==-1)
+    fprintf(stderr, "error: Could not write FITS file to stdout.\n");
+  fprintf(stderr, "progress: sp_ccdcontrol done.\n");
+}
+
+static int write_fits(int w, int h, double etime, int binmode, unsigned short *data)
+{
+  HeaderUnit hu;
+  register int i;
+  double datamin = DBL_MAX, datamax = DBL_MIN;
+  unsigned short u;
+  char str[80]; /* For building string FITS headers */
+  time_t date;
+
+  int ret; /* Return value for sbig_status */
+  struct sbig_status sbstat; /* Status structure */
+  
+  /* Get status to add to FITS header */
+  sync();
+  ret = sbig_get_status(&sbstat);
+
+  if (ret < 0) {
+    fprintf(stderr, "error: sbig_get_status failed: %s\n", sbig_show_error(ret));
+    exit(EXIT_FAILURE);
+  }
+
+  /* shouldn't we scale this to fit, first? */
+  for (i = w*h; --i >= 0; )
+    {
+      u = data[i];
+      if (u > datamax) datamax = u;
+      if (u < datamin) datamin = u;
+      data[i] = ((u<<8)|(u>>8)) ^ 0x0080; /* -32768 */
+    }
+
+  time(&date);
+
+  hu = fh_create();
+  fh_reserve(hu, 50); /* Reserve space for 50 cards (TCS, Elixir?, etc.) */
+  fh_set_bool(hu, 0., "SIMPLE", 1, "Standard FITS");
+  fh_set_int(hu, 1.0, "BITPIX", 16,"16-bit data");
+  fh_set_int(hu, 2.0, "NAXIS", 2,  "Number of axes");
+  fh_set_int(hu, 2.1, "NAXIS1", w, "Number of pixel columns");
+  fh_set_int(hu, 2.2, "NAXIS2", h, "Number of pixel rows");
+  fh_set_int(hu, 5.0, "PCOUNT",	0, "No 'random' parameters");
+  fh_set_int(hu, 6.0, "GCOUNT",	1, "Only one group");
+
+  strftime(str, sizeof(str)-1, "%Y-%m-%dT%T", gmtime(&date));
+  fh_set_str(hu, 104, "DATE", str, "UTC Date of file creation");
+  strftime(str, sizeof(str)-1, "%a %b %d %H:%M:%S %Z %Y", localtime(&date));
+  fh_set_str(hu, 104.1, "HSTTIME", str, "Local time in Hawaii");
+
+  fh_set_str(hu, 105, "ORIGIN", "CFHT", "Canada-France-Hawaii Telescope");
+
+  fh_set_flt(hu, 141.,"BZERO",	32768.0, 6,	"Zero factor");
+  fh_set_flt(hu, 142.,"BSCALE",	1.0, 2, "Scale factor");
+  fh_set_flt(hu, 150, "DATAMIN", datamin, 6, "Minimum value of the data");
+  fh_set_flt(hu, 151, "DATAMAX", datamax, 6, "Maximum value of the data");
+  fh_set_flt(hu, 160, "SATURATE", 4016.0, 6, "Saturation value");
+
+  fh_set_flt(hu, 220, "EXPTIME", etime, 5, "Integration time (seconds)");
+  sprintf(str, "%d %d", binmode + 1, binmode + 1);
+  fh_set_str(hu, 230, "CCDSUM", str, "Binning factors");
+  fh_set_int(hu, 231, "CCDBIN1", binmode + 1, "Binning factor along first axis");
+  fh_set_int(hu, 232, "CCDBIN2", binmode + 1, "Binning factor along second axis");
+
+  fh_set_com(hu, 1400.0, "COMMENT", "");
+  fh_set_com(hu, 1400.1, "COMMENT", " SBIG status record:");
+  fh_set_com(hu, 1400.2, "COMMENT", "");
+  if (sbstat.imaging_ccd_status==0)
+    fh_set_str(hu, 1500, "DETSTAT", "ok", "(SBIG imaging_ccd_status is 0)");
+  else
+    fh_set_int(hu, 1500, "DETSTAT", sbstat.imaging_ccd_status, "SBIG error!");
+  fh_set_flt(hu, 1500.1, "DETTEM", sbstat.ccd_temperature/10., 3, "Detector temperature");
+  fh_set_int(hu, 1500.2, "DETTEMRG", sbstat.temperature_regulation, "1=set temp 0=set power");
+  fh_set_int(hu, 1500.3, "DETTEMSP", sbstat.temperature_setpoint, "Temperature setpoint");
+  fh_set_int(hu, 1500.4, "DETTEMCP", sbstat.cooling_power, "Cooling power");
+  fh_set_flt(hu, 1510,  "CAMTEM", sbstat.air_temperature/10., 3, "Outside air temperature");
+  fh_set_com(hu, 1600.0, "COMMENT", "");
+  fh_set_com(hu, 1600.1, "COMMENT", " SBIG info record:");
+  fh_set_com(hu, 1600.2, "COMMENT", "");
+  sprintf(str, "%u", info.firmware_version);
+  fh_set_str(hu, 1600.9, "CONSWV", str, "SBIG firmware version");
+  fh_set_str(hu, 1601,"DETECTOR", info.camera_name, info.serial_number);
+  fh_set_bool(hu, 1700, "ABGON", info.imaging_abg_type, "Antiblooming gate present");
+  fh_set_int(hu, 1701, "ABGMODE", info.imaging_abg_type, "Antiblooming gate control value");
+  fh_set_int(hu, 1800, "BADCOL", info.nmbr_bad_columns, "Number of bad columns");
+  for (i = 0; i < info.nmbr_bad_columns; ++i){
+    sprintf(str, "BADCOL%d", i);
+    fh_set_int(hu, 1800 + 0.1 + 0.1 * i, str, info.bad_columns[i], "Bad column");
+  }
+  fh_set_int(hu, 1901, "ST5ADSIZ", info.ST5_AD_size, "");
+  fh_set_int(hu, 1902, "ST5FLTYP", info.ST5_filter_type, "");
+
+  if (fh_write(hu, STDOUT_FILENO) != FH_SUCCESS)
+    exit(EXIT_FAILURE);
+
+  if (fh_write_padded_image(hu, STDOUT_FILENO, data, w*h*sizeof(unsigned short), FH_TYPESIZE_RAW) != FH_SUCCESS)
+    exit(EXIT_FAILURE);
+
+  fprintf(stderr, "logonly: Wrote %d pixels, min=%g, max=%g\n", w*h, datamin, datamax);
+  sync();
+  return 0;
+}
+
+static void show_format(void){
+  fprintf(stderr, "Format for sp_ccdcontrol, SkyProbe CCD controller:\n"
+	  "Writes FITS file to stdout, status messages to stderr.\n"
+	  "NOTE: -port {hex} is an option for all forms of sp_ccdcontrol,\n"
+	  "  to specify a hex adress for the parallel port.\n"
+	  "sp_ccdcontrol expose -etime {Exp time}\n"
+          "   [-binmode {Binning mode}]\n"
+          "   [-shuttermode {Shutter mode}]\n"
+          "   [-raster X Y W H]\n"
+	  "Exp time: Exposure time given in seconds.\n"
+	  "Binning mode: 0=1x1, 1=2x2, 2=3x3.  Note, 3x3 not allowed in -track mode.\n"
+	  "   OR \n"
+	  "sp_ccdcontrol cool {coolmode} [temp|power]\n"
+	  "coolmode: 0=OFF, 1=ON, 2=Direct Drive\n"
+	  "For coolmode=0: Do not specify temp or power\n"
+	  "For coolmode=1: Specify temp in deg C\n"
+	  "For coolmode=2: Specify power (0-255)\n");
+  exit(EXIT_FAILURE);
+}
+
+
+int main(int argc, char *argv[])
+{
+  /*    char buffer[80], last_command[80]; */
+  int  ret = -1, i, port;
+  int  is_small_camera;
+    
+  /* Simon Kras--command line variables */
+  char cmd[80];
+  double etime;
+  int binmode;
+  int shuttermode;
+  int coolmode;
+  int raster_x, raster_y, raster_h, raster_w;
+  double cooltemp, coolpwr;
+
+  if(argc>1) strcpy(cmd, argv[1]);
+  else show_format();
+
+  port = 1; /* 0x378 */
+  for (i = 1; i < argc; ++i) {
+    if (!strcmp(argv[i], "-port")) {
+      sscanf(argv[++i], "%x", &port);
+      fprintf(stderr, "port override to 0x%x\n", port);
+    }
+  }
+
+  for (i = 0; i < 4; ++i) {
+    sync();
+    /* set our verbosity to 0 (range is 0 to 5) */
+    ret = sbig_init(port, 0, &info);
+    if (ret == -6) ret = 0; /* %%% It always returns this error, but actually it worked.
+			     * Since the library is binary only, we can't fix it.
+			     */
+    if (ret == 0) break;
+    fprintf(stderr,"logonly: sbig_init() failed: %s\n", sbig_show_error(ret));
+    usleep(100000);
+  }
+  if (ret < 0) {
+    fprintf(stderr, "error: cannot open camera, giving up\n");
+    exit(EXIT_FAILURE);
+  }
+
+  is_small_camera = (strstr(info.camera_name, "237") != NULL ||
+		     index(info.camera_name, '5') != NULL);
+  for (i = 0; i < info.camera_info[0].nmbr_readout_modes; ++i) {
+    struct readout_mode  *rmp;
+    rmp = &info.camera_info[0].readout_mode[i];
+#ifdef DEBUG
+    fprintf(stderr, "debug: ImagingCCD mode %d: w=%d h=%d "
+	    "gain=%f "
+	    "pw=%g ph=%g\n", rmp->mode, rmp->width,
+	    rmp->height,  0.01*rmp->gain, 0.001*rmp->pixel_width, 
+	    0.001*rmp->pixel_height);
+#endif
+  }
+
+  for (i = 0; i < info.camera_info[1].nmbr_readout_modes; ++i) {
+    struct readout_mode  *rmp;
+
+    rmp = &info.camera_info[1].readout_mode[i];
+#ifdef DEBUG
+    fprintf(stderr, "debug: TrackingCCD mode %d: w=%d h=%d "
+	    "gain=%f "
+	    "pw=%g ph=%g\n"
+	    , rmp->mode, rmp->width, rmp->height,
+	    0.01*rmp->gain,
+	    0.001*rmp->pixel_width, 0.001*rmp->pixel_height);
+#endif
+  }
+  if(!strcmp(cmd, "expose")){
+    etime=-999.;
+    for(i=1;i<argc;++i){
+      if(!strcmp(argv[i], "-etime")){
+	if(argc>(i+1)) etime = atof(argv[++i]);
+	else
+	  fprintf(stderr, "No argument given to -etime\n");
+      }
+    }
+    if(etime==-999.){
+	fprintf(stderr, "Must specify exposure time.\n");
+	exit(EXIT_FAILURE);
+      }
+      
+      binmode=-999;
+      for(i=1;i<argc;++i){
+	if(!strcmp(argv[i], "-binmode")){
+	  if(argc>(i+1)) binmode = atoi(argv[++i]);
+	  else{
+	    fprintf(stderr, "No argument given for -binmode\n");
+	    exit(EXIT_FAILURE);
+	  }
+	}
+      }
+      if(binmode==-999) binmode=0;
+
+      shuttermode=0;
+      for (i=1; i<argc;++i){
+	if (!strcmp(argv[i], "-shuttermode")){
+	  if (argc>(i+1)) shuttermode = atoi(argv[++i]);
+	  else{
+	    fprintf(stderr, "No argument given for -shuttermode\n");
+	    exit(EXIT_FAILURE);
+	  }
+	}
+      }
+
+      raster_x=0;
+      raster_y=0;
+      raster_w=0;
+      raster_h=0;
+      for (i=1; i<argc;++i){
+	if (!strcmp(argv[i], "-raster")){
+	  if (argc>(i+4)) {
+	    raster_x = atoi(argv[++i]);
+	    raster_y = atoi(argv[++i]);
+	    raster_w = atoi(argv[++i]);
+	    raster_h = atoi(argv[++i]);
+	  }
+	  else{
+	    fprintf(stderr, "-raster requires 4 arguments: x y w h\n");
+	    exit(EXIT_FAILURE);
+	  }
+	}
+      }
+      
+      take_picture(etime, binmode, shuttermode, raster_x, raster_y, raster_w, raster_h);
+
+  } else if(!strcmp(cmd, "cool")){
+    double  f;
+    struct sbig_cool  cool;
+    
+    if(argc<3){
+      fprintf(stderr, "Too few arguments for cool mode\n");
+      exit(EXIT_FAILURE);
+    } 
+    coolmode = atoi(argv[2]);
+    
+    if(coolmode<0 || coolmode>2){
+      fprintf(stderr, "Cooling mode values allowed: [0 Off, 1 *On, 2 DirectDrive]\n");
+      exit(EXIT_FAILURE);
+    }
+    cool.regulation = coolmode;
+    cool.direct_drive = 0;
+    if (cool.regulation == 2){
+      if(argc<4){
+	fprintf(stderr, "Must specify cooling power (0-255)\n");
+	exit(EXIT_FAILURE);
+      }
+      coolpwr=atof(argv[3]);
+      if(coolpwr<0 || coolpwr>255){
+	fprintf(stderr, "Cooling power must be 0-255.\n");
+	exit(EXIT_FAILURE);
+      }
+      cool.direct_drive = coolpwr;
+    }
+    else if (cool.regulation == 1) {
+      if(argc<4){
+	fprintf(stderr, "Must specify temperature in deg C\n");
+	exit(EXIT_FAILURE);
+      }
+      cooltemp=atof(argv[3]);
+      if(cooltemp<-50 || cooltemp>20){
+	fprintf(stderr, "Cooling temperature must be -50 to 20 deg C.\n");
+	exit(EXIT_FAILURE);
+      }
+      f = cooltemp;
+      i = 10.0*f + 0.5;
+      cool.temperature = i;
+    }
+    sync();
+    ret = sbig_set_cooling(&cool);
+    if (ret < 0){
+      fprintf(stderr, "sbig error: %s\n", sbig_show_error(ret));
+    }
+  }else{
+    fprintf(stderr, "Illegal command: '%s'\n", cmd);
+    show_format();
+  }
+  exit(EXIT_SUCCESS);
+}
+ 
Index: /tags/start/Ohana/src/opihi/dimm/telescope.c
===================================================================
--- /tags/start/Ohana/src/opihi/dimm/telescope.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dimm/telescope.c	(revision 12606)
@@ -0,0 +1,236 @@
+# include "dimm.h"
+
+double distSky (double r1, double r2, double d1, double d2);
+
+int telescope (int argc, char **argv) {
+  
+  if (argc < 2) goto usage;
+
+  if (!strcasecmp (argv[1], "init")) {
+    if (argc != 3) {
+      fprintf (stderr, "USAGE: telescope init (port)\n");
+      return (FALSE);
+    }
+    if (!SerialInit (argv[2])) return (FALSE);
+    fprintf (stderr, "telescope on port %s\n", argv[2]);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "cmd")) {
+
+    int status;
+    char *answer = (char *) NULL;
+
+    if (argc != 3) {
+      fprintf (stderr, "USAGE: telescope cmd (string)\n");
+      return (FALSE);
+    }
+    status = SerialCommand (argv[2], &answer, 10);
+    fprintf (stderr, "status: %d\n", status);
+    if (answer != (char *) NULL) {
+      fprintf (stderr, "answer: ..%s..\n", answer);
+    }
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "ack")) {
+
+    int status;
+    char line[32], *answer;
+
+    if (argc != 3) {
+      fprintf (stderr, "USAGE: telescope cmd (string)\n");
+      return (FALSE);
+    }
+    line[0] = 0x06;
+    line[1] = 0;
+    status = SerialCommand (line, &answer, 10);
+    fprintf (stderr, "status: %d\n", status);
+    if (answer != (char *) NULL) {
+      fprintf (stderr, "answer: ..%s..\n", answer);
+    }
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "slew")) {
+
+    double ra, dec;
+    int status;
+
+    if (argc != 4) {
+      fprintf (stderr, "USAGE: telescope slew (ra) (dec)\n");
+      return (FALSE);
+    }
+
+    ra  = atof (argv[2]);
+    dec = atof (argv[3]);
+    while (ra  < 360.0) ra += 360.0;   
+    while (ra  > 360.0) ra -= 360.0;   
+
+    status = gotoRD (ra, dec);
+
+    if (!status) return (FALSE);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "coords")) {
+
+    int status;
+    double ra, dec;
+    char line[64];
+
+    if (argc != 2) {
+      fprintf (stderr, "USAGE: telescope coords\n");
+      return (FALSE);
+    }
+
+    if (!getRD (&ra, &dec)) return (FALSE);
+    fprintf (stderr, "%f %f\n", ra, dec);
+    set_variable ("RA", ra);
+    set_variable ("DEC", dec);
+    dms_format (line, (ra/15.0));
+    set_str_variable ("Rs", line);
+    dms_format (line, dec);
+    set_str_variable ("Ds", line);
+
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "altaz")) {
+
+    int status;
+    double x, y;
+
+    if (argc != 2) {
+      fprintf (stderr, "USAGE: telescope altaz\n");
+      return (FALSE);
+    }
+
+    if (!getXY (&x, &y)) return (FALSE);
+    fprintf (stderr, "%f %f\n", x, y);
+    set_variable ("ALT", x);
+    set_variable ("AZ", y);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "site")) {
+
+    int status;
+    double lon, lat, LST;
+
+    if (argc != 2) {
+      fprintf (stderr, "USAGE: telescope site\n");
+      return (FALSE);
+    }
+
+    if (!getSite (&lon, &lat, &LST)) return (FALSE);
+    fprintf (stderr, "%f %f  %f\n", lon, lat, LST);
+    set_variable ("LON", lon);
+    set_variable ("LAT", lat);
+    set_variable ("LST", LST);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "setsite")) {
+
+    double lon, lat;
+
+    if (argc != 5) {
+      fprintf (stderr, "USAGE: telescope setsite (name) (longitude) (latitude)\n");
+      return (FALSE);
+    }
+
+    lon = atof (argv[3]);
+    lat = atof (argv[4]);
+    if (!setSite (argv[2], lon, lat)) return (FALSE);
+    set_variable ("LON", lon);
+    set_variable ("LAT", lat);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "settime")) {
+
+    if (argc != 3) {
+      fprintf (stderr, "USAGE: telescope settime (lst)\n");
+      return (FALSE);
+    }
+
+    if (!setTime (argv[2])) return (FALSE);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "verbose")) {
+
+    int mode;
+
+    if (argc != 3) {
+      fprintf (stderr, "USAGE: telescope verbose (mode)\n");
+      return (FALSE);
+    }
+
+    mode = atoi (argv[2]);
+    SerialVerbose (mode);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "setcoords")) {
+
+    int status;
+    double ra, dec;
+
+    if (argc != 4) {
+      fprintf (stderr, "USAGE: telescope setcoords (ra) (dec)\n");
+      return (FALSE);
+    }
+
+    ra  = atof (argv[2]);
+    dec = atof (argv[3]);
+
+    if (!setRD (ra, dec)) return (FALSE);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "offset")) {
+
+    int status;
+
+    if (argc != 4) {
+      fprintf (stderr, "USAGE: telescope offset (direction) (distance)\n");
+      fprintf (stderr, "  direction : x or y\n");
+      fprintf (stderr, "  distance  : +arcmin or -arcmin\n");
+      return (FALSE);
+    }
+    status = offset (argv[2], atof (argv[3]));
+
+    if (!status) return (FALSE);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "toffset")) {
+
+    int status;
+
+    if (argc != 5) {
+      fprintf (stderr, "USAGE: telescope toffset (direction) (rate) (duration)\n");
+      fprintf (stderr, "example: telescope toffset x RC 1.5\n");
+      return (FALSE);
+    }
+    status = toffset (argv[2], argv[3], atof(argv[4]));
+
+    if (!status) return (FALSE);
+    return (TRUE);
+  }
+
+ usage:
+  fprintf (stderr, "telescope init port - set serial port (eg, /dev/ttyS0)\n");
+  fprintf (stderr, "telescope site - get site information\n");
+  fprintf (stderr, "telescope altaz - g\n");
+  fprintf (stderr, "telescope setcoords (ra) (dec)\n");
+  fprintf (stderr, "telescope setsite (name) (longitute) (latitude)\n");
+  fprintf (stderr, "telescope coords\n");
+  fprintf (stderr, "telescope slew (ra) (dec)\n");
+  fprintf (stderr, "telescope offset (direction) (duration)\n");
+  fprintf (stderr, "telescope toffset (direction) (rate) (duration)\n");
+  return (FALSE);
+}
+
Index: /tags/start/Ohana/src/opihi/doc/changes.txt
===================================================================
--- /tags/start/Ohana/src/opihi/doc/changes.txt	(revision 12606)
+++ /tags/start/Ohana/src/opihi/doc/changes.txt	(revision 12606)
@@ -0,0 +1,54 @@
+Oct 19  2003 misc/startup.c              . minor changes, DONE
+Oct 19  2003 misc/conversions.c		 . minor changes, DONE
+Oct 19  2003 misc/match_image.c		 . copied to dvo
+Apr 19 17:41 misc/ConfigInit.c		 . minor changes, kept dvo version
+May  6 16:13 misc/ImageOps.c		 . minor changes, DONE
+May 12 09:00 misc/photometry.c           . major changes : DONE
+
+Oct 15  2003 user/badimages.c            . no change
+Oct 15  2003 user/imlist.c		 . no change
+Oct 15  2003 user/precess.c		 . dvo version ok
+Oct 15  2003 user/delete.c		 . dvo version ok
+
+May  6 15:25 user/extract.c		 . mostly deprecated (transfer USNO/HST/etc versions)
+May 10 21:13 user/mextract.c		 . used status version + vectors
+May 11 12:06 user/avextract.c		 . used status version + vectors
+Oct 27  2003 user/imextract.c		 . used status version + vectors
+
+May 12 09:06 user/dmags.c		 . used status version + vectors
+May 12 09:12 user/dmagmeas.c		 . used status version + vectors
+May 12 09:13 user/dmagaves.c		 . used status version + vectors
+May 11 16:18 user/ddmags.c		 . used status version + vectors
+
+May  2 11:14 user/calextract.c		 . used status version + vectors 
+May  3 20:08 user/calmextract.c		 . used status version + vectors
+Oct 19  2003 user/cmd.c			 . fixed (photcodes vs vectors)
+Oct 19  2003 user/ccd.c			 . used status version + vectors
+
+Apr 19 19:48 user/gimages.c		 . minor changes, fixed
+Nov 14  2003 user/gstar.c		 . minor changes, fixed
+May  3 20:49 user/gtypes.c		 . dvo version ok
+May  6 09:37 user/images.c		 . copied to dvo
+May  3 20:49 user/imdata.c		 . dvo version ok
+May  3 20:50 user/imphot.c		 . dvo version ok
+May  3 20:51 user/imrough.c		 . dvo version ok
+May  3 20:51 user/imsearch.c		 . dvo version ok
+Nov  5  2003 user/photcodes.c		 . copied to dvo
+Nov  1  2003 user/pmeasure.c		 . dvo version ok
+Mar  3 11:25 user/showtile.c		 . copied to dvo
+Nov  1  2003 user/subpix.c		 . copied to dvo
+Oct 30  2003 user/dmt.c			 . minor changes & photcodes
+Nov  1  2003 user/lcurve.c		 . minor changes & photcodes
+
+May 18 09:50 user/cgrid.c		 . copied to dvo
+
+Nov  1  2003 user/abszero.c		 . deprecated
+May  3 20:51 user/zeropts.c		 . deprecated
+Nov 13  2003 user/resid.c		 . deprecated
+Nov 13  2003 user/photresid.c		 . deprecated
+
+May  2 11:20 user/cals.c		 . deprecated?
+May  3 20:37 user/ddmagextract.c	 . deprecated?
+May  3 20:11 user/dmagextract.c		 . deprecated?
+Oct 19  2003 user/ccdextract.c		 . deprecated?
+Oct 19  2003 user/cmdextract.c		 . deprecated?
Index: /tags/start/Ohana/src/opihi/doc/command.txt
===================================================================
--- /tags/start/Ohana/src/opihi/doc/command.txt	(revision 12606)
+++ /tags/start/Ohana/src/opihi/doc/command.txt	(revision 12606)
@@ -0,0 +1,24 @@
+
+readline: allocates a line and returns it; empty lines return NULL
+
+expand_vars: (recursively) expand expressions of the form $X
+	     frees the input line, allocates a new one.
+	     returns NULL on error (including NULL input)
+
+expand_vectors: expand expressions of the form $X
+	     frees the input line, allocates a new one.
+	     returns NULL on error (including NULL input)
+
+parse performs math expansion on the line, returning a new line (old one is freed)
+
+
+in newmath:
+
+isolate_elements converts argc,argv to cstack,Ncstack (argc,argv NOT freed)
+convert_to_RPN takes cstack,Nstack and converts to stack,Nstack; input cstack,Ncstack are freed
+check_stack puts pointers to data types on stack, no data allocated
+evaluate_stack 
+
+
+command parses a single input line (line) and expands
+
Index: /tags/start/Ohana/src/opihi/doc/dvo-2.txt
===================================================================
--- /tags/start/Ohana/src/opihi/doc/dvo-2.txt	(revision 12606)
+++ /tags/start/Ohana/src/opihi/doc/dvo-2.txt	(revision 12606)
@@ -0,0 +1,28 @@
+
+Region APIs
+
+Region table is a FITS table
+
+- load region data from FITS table
+- save region data to FITS table
+
+/* find region which overlaps c at given depth (-1 : max depth) */
+SkyRegion *SkyFindPoint (SkyRegion *db, SkyCoord c, int depth);
+
+/* find regions at all levels which overlap c */
+SkyRegion **SkyFindLevels (SkyRegion *db, SkyCoord c, int *Nregion);
+
+/* find regions contained within rectangular region  c1 - c2 */
+SkyRegion **SkyFindArea (SkyRegion *db, SkyCoord c1, SkyCoord c2, *nlist);
+
+- I have created table generation functions which construct a
+  collection of table entries starting with the full sky and iterating
+  down N levels.  The function also fills out the names at the
+  appropriate levels.  This is currently ok up to level 6, but runs
+  out of memory at level 7.  This should not be the case, so I suspect
+  I'm not free'ing some memory.  
+
+- I need to create a function to take the GSC table list and construct
+  a set of SkyRegions that match the layout, starting with the full
+  sky and iterating down to and past the GSC tables.  
+
Index: /tags/start/Ohana/src/opihi/doc/dvo.html
===================================================================
--- /tags/start/Ohana/src/opihi/doc/dvo.html	(revision 12606)
+++ /tags/start/Ohana/src/opihi/doc/dvo.html	(revision 12606)
@@ -0,0 +1,288 @@
+
+<h2> PA data requirements </h2>
+
+Counting the total size of the PA database for the PA survey, with
+roughly 20 pointings per location and 30 second exposures.  The depth
+for PA survey in P2 @ 20 \sigma is 21.3 (r).  Each detection uses 100
+bytes (<b>we need to flesh this out with more realistic numbers from
+our table of parameters</b>).  The access speed to a RAID disk is 100
+MB/sec.  The number density of stars in i' in the plane may be higher,
+but we reach saturation at ~1.4e6 detections per deg^2 (one object per
+100 pixels).  This is a factor of 5 higher than the raw numbers.
+
+<h3> stellar counts for PS-1 </h3>
+latitude                 90          30         0
+density (deg^{-2})      5e3         3e4       3e5
+N_det (FPA^{-1})        4e4         2e5       2e6
+Sum N_det (FPA^{-1})    8e5         4e6       4e7
+Sum Nbyte (FPA^{-1})  80 MB      400 MB      4 GB
+Nsec for 1 channel      0.8           4        40
+Nchannel for 2 sec        1           2        20
+
+The total number of bytes for the PA survey for P2 detections is ~12
+TB (30000 x 400MB).  The density of detections per FPA from P4 delta
+is roughly the same as P2 at 0 deg (2e5 vs 3e5 det deg^{-2}).  The
+total number of bytes needed to store the P4 Delta detections from all
+of PS-1 is 
+
+Fields in the plane will take longer to process
+
+<h2> addstar interactions for a distributed db </h2>
+
+addstar.client <---> addstar.daemon
+
+The sky is divided into hierarchical regions, each broken into smaller
+subregions.  Both the image and object tables are divided into
+subtables by region on the sky.  The density of image tables is
+smaller than the density of object tables.  A top-level table defines
+the distribution of the lower-level tables by defining the hierarchy
+of regions and subregions.  Each entry in this table contains:
+
+region ID  - an identifier for the subregion
+RAs, RAe   - RA range of region
+DECs, DECe - DEC range of region
+parent ID  - ID of the region which contains this region (NULL for allsky)
+Nchild     - number of children
+offset     - starting entry of first child
+images     - is this region used for images? (if FALSE, down one layer)
+objects    - is this region used for objects? (if FALSE, down one layer)
+
+use the machine name / file name as the indicator in the images and
+objects entries?
+
+The table defines the relationship between the subregions and provides
+a mechanism to find the subregions appropriate to a given sky
+location.  It also specified for a given depth if that depth is used
+for the image and/or the object table.  The image tables contain
+images whose reference coordinate is located in the given region.
+Other regions which the image overlaps contain entries in the image
+reference table which specify the primary image table in which they
+are stored.  
+
+The details of the sky region definitions do not matter for the
+structure of the region table.  The data structures can handle any
+arrangement of tables which meets the basic requirements that the
+boundaries be lines of constant RA & DEC and that each level defines
+all regions which cover the entire sky.  One implementation is as
+follows and is easy to generate:  
+
+Start with the complete sky as a single region (RAs = 0, RAe = 360;
+DECs = -90, DECe = 90).  To create a new region, always subdivide the
+region with the largest area (roughly (RAe - RAs)*(DECe -
+DECs)*cos((DECs + DECe)/2)).  To subdivide a region, define two
+possible subdivisions: RA = 0.5*(RAs + RAe) (which becomes RAs and RAe
+for the two new regions) or DEC = 0.5*(DECs + DECe).  Determine the
+length of these dividing lines (S1 = (DECe - DECs); S2 = (RAe - RAs) /
+cos (DEC)).  Choose the shorter of these two lines, and subdivide the
+region on that basis.  
+
+The number of subregions increases by a factor of 8 for
+each new level.  Approximate table size: Need at least 200,000
+lowest-level regions, leads to 2^18 regions (256k) in lowest-level.
+Total table size is roughly 300k rows.  Each row is roughly 32 bytes,
+for a table size of 10MB.
+
+There is one addstar.daemon per DVO server.  The addstar.daemons are
+responsible for serving the objects and images from the tables they
+contain.  
+
+addstar.client steps to load a new set of objects:
+- load region table (defined in config db)
+- find overlapping object regions
+- find overlapping image regions
+- identify primary image region
+- send image data to node for primary image region 
+- send image reference to nodes for secondary image regions
+- send detection data (with image ID) to corresponding object region nodes
+
+addstar.daemon responsibilities:
+- receive image data -> add to primary image table
+- receive detection data -> add to local region file
+- request objects in overlap regions from neighbor daemons
+- send detections to neighbor daemons if associated with object over
+  border
+- construct / update objects on basis of detections
+
+in DVO 1.0, addstar updates objects on every upload of the
+detections.  In fact, the construction of the objects need not be
+performed every time detections are added.  Do we need to construct
+objects for all single detections?  The current process is:
+
+- get list of new detections (from incoming image)
+- match each detection with each object
+- update object parameters
+
+another option:
+
+step 1:
+ - get list of new detections
+ - add to new.detection table
+
+step 2:
+ - match detections to object table
+ - update object parameters
+
+third option
+step 1:
+ - add new detections to new table
+
+step 2:
+ - compare detections to orphans 
+ - if found, promote to object
+ - if not, test against objects
+ - if found update object
+ - if not add to orphans
+
+<h2> DVO image organization </h2>
+
+DVO 1.0 uses a single image table to store all image data.  In this
+table, each image is a chip; that is, each entry represents a single
+astrometric system.  In principal, there is no reason this could not
+be an entire mosaic or (in the case of Pan-STARRS) an individual
+Cell. It is usually necessary to be able to define the relationship
+between the different detector / focal plane / etc coordinate
+systems.  If the data entity is a full mosaic, then it will be
+necessary to look up the chip (and cell) transformations.  If the data
+entity is the cell, the reverse conversions will be needed.  
+
+The image table should be distributed to multiple files to speed up
+the access.  One option is to do this by coordinate region.  In the
+plan for DVO 2.0, there will be a table of the region hierarchy for
+the object tables, and the image tables could be distibuted similarly,
+though with a different density.  In PS-1, for example, there will be
+around 250,000 images (FPAs).  If we store OTAs (chips) as the data
+entity in the image table, then we will have in the vicinity of 16M
+rows.  If each contains 256 bytes, the total data volume in the image
+table will be about 4 GB.  If we want to have typical access times to
+any image of 1 second, and we need to scan through the entire table to
+get to the image, then we will need to distribute the data across 40
+tables (note that they need not be distributed by machine).  If each
+table represents a region on the sky, this translates to 1000 - 500
+square degrees per table.  
+
+Some additional aspects are interesting.  First, the
+spatially-distributed tables correspond to specific regions on the
+sky, likely to be bounded by lines of constant RA and DEC, or
+something equivalent.  However, an image cannot be guaranteed to land
+in only one of these regions.  To mitigate this, each image (chip or
+FPA or whatever the data unit is) should have a single defined
+position with which the general location is identified and the choice
+of region is made.  In addition, there should be a table associated
+with each region which defines images in other tables (regions) which
+overlap the given region.  In general, these overlap tables will
+contain only a small fraction of the image entries (regions are much
+large than images) and they need only identify the image ID and the
+corresponding table.
+
+An additional accelerator table would include all images, their
+reference time and their reference coordinate, sorted by time, with an
+index for the name.
+
+The end result is three types of tables: images.db, overlaps.db,
+imagetimes.db.  images.db contains the bulk of the information (256
+byte / row).  overlaps.db contains only the image ID and the the RA
+and DEC of the reference position (not the actual table because that
+may change). imagetimes.db contains only image ID (8 byte? 16 byte?),
+time, RA, DEC, and and index.  This is a total of about 40 bytes per
+image, for a total of roughly 700 MB at the end of PS-1.
+
+<h3> Examples queries </h3>
+
+<h4> find a single, specific image by ID </h4>
+<ul>
+<li> open imagetimes.db
+<li> load block marker (ID,block; every 10000 blocks)
+<li> find appropriate block
+<li> load block
+<li> find appropriate image entry
+<li> determine appropriate image.db table (region)
+<li> open image.db 
+<li> load block marker (ra,block; every 10000 blocks)
+<li> find appropriate block
+<li> load block
+<li> find appropriate image entry
+</ul>
+
+<h4> find a single, specific image by ID </h4>
+<ul>
+<li> open imagetimes.db
+<li> load block marker (ID,block; every 10000 blocks)
+<li> find appropriate block
+<li> load block
+<li> find appropriate image entry
+<li> determine appropriate image.db table (region)
+<li> open image.db 
+<li> load block marker (ra,block; every 10000 blocks)
+<li> find appropriate block
+<li> load block
+<li> find appropriate image entry
+</ul>
+
+<h3> dvo / object catalog scaling to massive collections </h3>
+
+DVO divides the sky into tables which represent specific areas on the
+sky.  Currently, these are pre-defined to match the HST GSC regions,
+roughly 1 - 4 square degree patches with fixed RA and DEC boundaries.
+A future extension will provide a mechanism to increaese or decrease
+the table density on the fly.
+
+The likely data rate under Pan-STARRS PS-1 is in the vicinity of 5 x
+10<sup>5</sup> stars per square degree.  The density is likely to vary
+by a factor of 30 for the bulk of the sky.  The Pan-STARRS camera
+consists of 1.44 x 10<sup>8</sup> pixels.  The confusion limit will
+likely be reached when each object encompases 25 pixels, resulting in
+a saturation of 6 x 10<sup>6</sup> stars per square degree.  The
+Pan-STARRS camera covers a total of 7.45 square degrees, and the
+expected exposure rate is roughly 1 per minute on average.  This
+amounts to a total of 3000 square degrees covered per night of
+observation, or a total of 1.5 x 10<sup>9</sup>detections per night,
+or a total of 5 x 10<sup>11</sup> over the course of one year.  Given
+this total number of detections, and the total sky coverage of 30,000
+square degrees, the average number of detections per square degree
+will be in the vicinity of 1.7 x 10<sup>7</sup>
+
+There are two main limitations to the DVO object storage model.
+First, the large data volume translates to a finite time to read the
+data from the disk.  Second, the large number of objects limits the
+rate at which new detections may be associated with the existing
+objects.  The first of these has generally proven to be the more
+significant limitation in applications to date.  We can easily
+calculate the time needed to load the data relevant to a random image
+pointing, as well as the maximum time based on the range of data
+volumes.  A necessary assumption in this calculation is the number of
+bytes used per detection.  We generously assume 100 bytes per
+detection, 3 times the existing data structures used by DVO.  
+
+Based on the numbers above, the total data volume represented by a
+year of observations is 50 TB, assuming the detection component
+dominates the total.  The average camera footprint translates to
+roughly 13 GB worth of detections.  Since each footprint is performed
+once per minute, it will be necessary to perform the read and write in
+each 10 seconds.  This in turn corresponds to 1.3 GB per second for
+the read and write portions.  With typical local hard-drive access
+speeds for RAIDs of 100 MB/sec, the data will need to be distributed
+across more than the machines in order to achieve these average
+rates.  
+
+The existing DVO system expects only one object table to be open at a
+time.  In addition, access to the tables is not controlled through
+separate machines.  Rather, a single collection of tables is expected
+and all queries are performed independently.  In order to handle the
+above load with the DVO software, the following changes will be
+needed:
+
+<ul>
+<li> tables must be distributed across multiple machines.  This is
+mandatory regardless of the underlying database engine based on the
+data I/O analysis above.
+
+<li> the 'addstar' front end needs to send the data for each table to
+the database backends on each of the corresponding machines.  
+
+<li> the addstar update for a single image can be done in series as is
+currently done.
+
+<li> write locking should be done on the tables rather than on the
+database as a whole (currently using the image table). 
+</ul>
+
Index: /tags/start/Ohana/src/opihi/doc/libs.txt
===================================================================
--- /tags/start/Ohana/src/opihi/doc/libs.txt	(revision 12606)
+++ /tags/start/Ohana/src/opihi/doc/libs.txt	(revision 12606)
@@ -0,0 +1,17 @@
+
+I have divided the (non-user) functions into classes. 
+
+- conversions can be placed in a single library
+
+- graph and image (tv) functions can be placed in a library
+
+- the opihi shell functions can go into a third library
+
+- the dvo-related functions can go into a fourth
+
+- i need to clean up the mana and dimm misc functions, and put them in libraries 
+
+- the user functions also need to go into some libraries.
+
+- how do I have the library add its functions to the command list?
+
Index: /tags/start/Ohana/src/opihi/doc/mana.updates.txt
===================================================================
--- /tags/start/Ohana/src/opihi/doc/mana.updates.txt	(revision 12606)
+++ /tags/start/Ohana/src/opihi/doc/mana.updates.txt	(revision 12606)
@@ -0,0 +1,135 @@
+
+mana functions which existed in DVO from status:
+
+applyfit2d.c         : OK - vector changes only
+applyfit.c	     : OK - vector changes only
+box.c		     : OK - no diff
+center.c	     : OK - no diff
+clear.c		     : OK - no diff
+concat.c	     : OK - vector changes only
+contour.c	     : mana version writes to Ximage, dvo version writes to vectors.  mana/contour -> tvcontour.c
+create.c	     : OK - buffer changes only
+cursor.c	     : OK - buffer & minor changes only
+delete.c	     : OK - buffer & minor changes only
+device.c	     : OK - no diff
+extract.c	     : mana extract operates on buffers / status extract is db operation
+file.c		     : OK - no diff
+fit2d.c		     : OK - vector changes only
+fit.c		     : OK - added weights and parameter errors from mana version
+gaussj.c	     : OK - buffer changes only
+grid.c		     : mana version write to Ximage, dvo version writes to Xgraph. mana/grid -> tvgrid
+histogram.c	     : OK - vector changes only
+interpolate.c	     : OK - vector changes only
+jpeg.c		     : OK - no diff
+labels.c	     : OK - no diff
+limits.c	     : OK - vector & minor changes only
+list_buffers.c	     : OK - buffer changes only
+list_vectors.c	     : OK - vector & minor changes only
+mcreate.c	     : OK - buffer changes only
+mget.c		     : OK - buffer changes only
+mset.c		     : OK - buffer changes only
+ps.c		     : OK - no diff
+rd.c		     : OK - buffer changes only
+read_vectors.c	     : OK - included reading vectors from fits tables
+region.c	     : OK - no diff
+resize.c	     : OK - no diff
+section.c	     : OK - no diff
+set.c		     : OK - mana version out of date
+sprintf.c	     : OK - no diff
+stats.c		     : OK - included threshold comparison for IgnoreValue and min == max test
+style.c		     : OK - mana version out of date
+subset.c	     : OK - mana version out of date
+textline.c	     : OK - no diff
+tv.c		     : OK - buffer changes only
+uniq.c		     : OK - vector changes only
+vcontour.c	     : mana/vcontour equiv to dvo/contour
+vstat.c		     : OK - vector changes only
+wd.c		     : OK - buffer changes only
+write_vectors.c	     : OK - vector changes only
+zap.c		     : OK - buffer changes only
+zplot.c		     : OK - vector changes only
+
+mana functions not previously in DVO from status:
+
+accum.c			: fix vectors
+adc.c			: keep - specialized
+biassub.c		: fix buffers and vectors
+clip.c			: fix buffers and vectors
+cmpload.c		: keep
+coords.c		: fix buffers and vectors
+cut.c			: fix buffers and vectors
+cval.c			: ? superceeded by 'star'?
+demux.c			: keep - specialized
+dimendown.c		: fix buffers and vectors
+dimenup.c		: fix buffers and vectors
+drawline.c		: keep - unused
+drizzle.c		: fix buffers and vectors
+erase.c			: keep
+fft1d.c			: fix buffers and vectors
+fft2d.c			: fix buffers and vectors
+flux.c			: fix buffers and vectors
+gauss.c			: fix buffers and vectors
+gaussfit.c		: ? to correct?
+getchr.c		: keep
+getvel.c		: 
+imfit.c			: 
+imhist.c		: 
+integrate.c		: 
+kern.c			: 
+keyword.c		: 
+line.c			: 
+list_header.c		: 
+load.c			: 
+medacc.c		: 
+medianmap.c		: 
+memory.c		: 
+minterpolate.c		: 
+mkgauss.c		: 
+multifit.c		: 
+nextract.c		: 
+objload.c		: 
+outline2.c		: ??
+outline.c		: ??
+pause.c			: 
+peak.c			: 
+point.c			: 
+polar.c			: 
+profile.c		: 
+rdseg.c			: 
+rebin.c			: 
+roll.c			: 
+rotate.c		: 
+rotcurve.c		: 
+save.c			: 
+scale.c			: 
+select.c		: 
+sexigesimal.c		: 
+shape.c			: 
+shift.c			: 
+simsignal.c		: 
+sort_vectors.c		: 
+spec.c			: 
+spline_apply.c		: 
+spline_construct.c	: 
+star.c			: 
+strchr.c		: 
+strlen.c		: 
+substr.c		: 
+svd.c			: 
+swapbytes.c		: 
+testfit.c		: 
+transform.c		: 
+unsign.c		: 
+usleep.c		: 
+vbin.c			: 
+vclip.c			: 
+
+outdated or unneeded functions:
+
+dummy.c
+downdimen.c
+buftovec.c
+kernel.c
+updimen.c		: 
+stupidtest.c		: 
+plot2.c			: fixed GetColor in dvo/plot.c
Index: /tags/start/Ohana/src/opihi/doc/notes.dvo-data.html
===================================================================
--- /tags/start/Ohana/src/opihi/doc/notes.dvo-data.html	(revision 12606)
+++ /tags/start/Ohana/src/opihi/doc/notes.dvo-data.html	(revision 12606)
@@ -0,0 +1,166 @@
+
+<h2> data structures in DVO </h2>
+
+DVO uses several data structures, defined in <tt>loneos.h</tt> to
+represent data in the database tables.  This document attempts to
+describe the actual usage, some of which may disagree with the comment
+entries in <tt>loneos.h</tt>.
+
+<b> Image </b>
+<table> 
+<tr><th> name               </th><th> type           </th><th> value                     </th><th> units              </th>
+<tr><td> coords             </td><td> Coords         </td><td> astrometry                </td><td>                    </td>
+<tr><td> tzero              </td><td> unsigned int   </td><td> readout time row 0        </td><td> unix time          </td>
+<tr><td> nstar              </td><td> unsigned int   </td><td> number of stars on image  </td><td>                    </td>
+<tr><td> secz               </td><td> short int      </td><td> airmass                   </td><td> 1000*airmass       </td>
+<tr><td> NX                 </td><td> short int      </td><td> image size                </td><td> pixels             </td>
+<tr><td> NY                 </td><td> short int      </td><td> image size                </td><td> pixels             </td>
+<tr><td> apmifit            </td><td> short int      </td><td> aperture correction       </td><td> 1000*mag           </td>
+<tr><td> dapmifit           </td><td> short int      </td><td> error                     </td><td> 1000*mag           </td>
+<tr><td> source             </td><td> short int      </td><td> photcode                  </td><td>                    </td>
+<tr><td> Mcal               </td><td> short int      </td><td> relphot correciton        </td><td> 1000*mag           </td>
+<tr><td> dMcal              </td><td> short int      </td><td> error                     </td><td> 1000*mag           </td>
+<tr><td> Xm                 </td><td> short int      </td><td> image chi-square          </td><td> 100*log(chisq)     </td>
+<tr><td> name[32]           </td><td> char           </td><td> image name                </td><td>                    </td>
+<tr><td> detection_limit    </td><td> unsigned char  </td><td>                           </td><td> 10*mag             </td>
+<tr><td> saturation_limit   </td><td> unsigned char  </td><td>                           </td><td> 10*mag             </td>
+<tr><td> cerror             </td><td> unsigned char  </td><td> astrometric error         </td><td> 50*arcsec          </td>
+<tr><td> fwhm_x             </td><td> unsigned char  </td><td> average FWHM X            </td><td> 25*arcsec          </td>
+<tr><td> fwhm_y             </td><td> unsigned char  </td><td> average FWHM Y            </td><td> 25*arcsec          </td>
+<tr><td> trate              </td><td> unsigned char  </td><td> drift rate                </td><td> 10000*sec/pix      </td>
+<tr><td> exptime            </td><td> float          </td><td> exposure time             </td><td> seconds            </td>
+<tr><td> code               </td><td> char           </td><td> data flags                </td><td>                    </td>
+<tr><td> ccdnum             </td><td> unsigned char  </td><td> mosaic CCD ID number      </td><td>                    </td>
+<tr><td> dummy[20]          </td><td> char           </td><td> extra                     </td><td>                    </td>
+<tr><td> order              </td><td> short int      </td><td> order of Mcal function    </td><td>                    </td>
+<tr><td> Mx                 </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> My                 </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Mxx                </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Mxy                </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Myy                </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Mxxx               </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Mxxy               </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Mxyy               </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Myyy               </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Mxxxx              </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Mxxxy              </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Mxxyy              </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Mxyyy              </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Myyyy              </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+</table>
+
+<em> apmifit, dapmifit are needed for dophot data, but not sextractor data.  are these correctly handled? </em>
+<em> skyprobe used Mxxxx for Ncal and Myyyy for sky - can this be reconciled? </em>
+
+<h3> codes in Image</h3>
+<ul>
+<li> ID_IMAGE_NOCAL = 0x04 - internal to relphot 
+<li> ID_IMAGE_POOR  = 0x02 - set by relphot
+<li> ID_IMAGE_SKIP  = 0x04 - use by relphot (!!!)
+</ul>
+
+<b> Average </b>
+<table> 
+<tr><th> name       </th><th> type           </th><th> value               </th><th> units                 </th></tr>
+<tr><td> R          </td><td> float          </td><td> RA                  </td><td> decimal degrees J2000 </td></tr>
+<tr><td> D          </td><td> float          </td><td> DEC                 </td><td> decimal degrees J2000 </td></tr>
+<tr><td> M          </td><td> short int      </td><td>                     </td><td> 1000*mag		    </td></tr>
+<tr><td> Nm         </td><td> unsigned short </td><td> N measure	    </td><td> 			    </td></tr>
+<tr><td> Nn         </td><td> unsigned short </td><td> N missing	    </td><td> 			    </td></tr>
+<tr><td> Xp         </td><td> short int      </td><td> position scatter    </td><td> 100*arcsec	    </td></tr>
+<tr><td> Xm         </td><td> short int      </td><td> mag chisq           </td><td> 100*log(chisq)	    </td></tr>
+<tr><td> code       </td><td> unsigned short </td><td> data flags	    </td><td> 			    </td></tr>
+<tr><td> offset     </td><td> signed int     </td><td> measure offset	    </td><td> 			    </td></tr>
+<tr><td> missing    </td><td> signed int     </td><td> missing offset	    </td><td> 			    </td></tr>
+<tr><td> dM         </td><td> short int      </td><td> error on M          </td><td> 1000*log(value)	    </td></tr>
+<tr><td> Xg         </td><td> short int      </td><td> best chisq value    </td><td> ??		    </td></tr>
+</table>		  
+
+<h3> codes in Average</h3>
+<li> set to 0 by addstar, etc
+<li> ID_STAR_NOCAL        = 0x0001 - set by relphot
+<li> ID_PROPER            = 0x0400 - set by addusno, used by markrock
+<li> ID_BAD_DATE          = 0x0800 - deprecate (not currently set)
+<li> ID_TRANSIENT         = 0x1000 - not currently set? 
+<li> ID_VARIABLE          = 0x2000 - not currently set? 
+<li> ID_ROCK              = 0xa000 - set by markrock
+<li> ID_GHOST             = 0xc001 - set by fixcat, markstar
+<li> ID_TRAIL             = 0xc002 - set by fixcat, markstar
+<li> ID_BLEED             = 0xc003 - set by fixcat, markstar, markrock
+<li> ID_COSMIC            = 0xc004 - set by markrock
+</ul>
+
+<b> Measure </b>
+<table> 
+<tr><th> name       </th><th> type           </th><th> value               </th><th> units             </th>
+<tr><td> dR         </td><td> short int      </td><td> RA offset           </td><td> 100*arcsec        </td>
+<tr><td> dD         </td><td> short int      </td><td> DEC offset          </td><td> 100*arcsec        </td>
+<tr><td> M          </td><td> short int      </td><td> catalog mag         </td><td> 1000*mag          </td>
+<tr><td> Mcal       </td><td> short int      </td><td> image cal mag       </td><td> 1000*mag          </td>
+<tr><td> Mgal       </td><td> short int      </td><td> 'galaxy' mag,       </td><td> 1000*mag          </td>
+<tr><td> airmass    </td><td> short int      </td><td> (airmass - 1),      </td><td> 1000*airmass      </td>
+<tr><td> FWx        </td><td> short int      </td><td> fwhm major axis     </td><td> 100*arcsec        </td>
+<tr><td> dM         </td><td> unsigned char  </td><td> mag error           </td><td> 1000*mag          </td>
+<tr><td> fwy        </td><td> unsigned char  </td><td> minor/major ratio   </td><td>                   </td>
+<tr><td> theta      </td><td> unsigned char  </td><td> angle wrt ccd X dir </td><td> degree*(256/360)  </td>
+<tr><td> dophot     </td><td> char           </td><td> dophot type         </td><td>                   </td>
+<tr><td> source     </td><td> unsigned short </td><td> photcode            </td><td>                   </td>
+<tr><td> t          </td><td> unsigned int   </td><td> time                </td><td> unix time         </td>
+<tr><td> averef     </td><td> unsigned int   </td><td> average entry       </td><td>                   </td>
+<tr><td> dt         </td><td> short int      </td><td> exposure time       </td><td> 2500*log(exptime) </td>
+<tr><td> flags      </td><td> unsigned short </td><td> data flags          </td><td>                   </td>
+</table>
+
+<h3> flags in Measure</h3>
+<ul>
+<li> ID_MEAS_POOR         = 0x0001 - set by relphot, unset?
+<li> ID_MEAS_NOCAL        = 0x0002 - set by relphot, unset?
+<li> BLEND_IMAGE          = 0x0100 - set by addstar, etc
+<li> BLEND_CATALOG        = 0x0200 - set by addstar, etc
+<li> BLEND_IMAGE_NEIGHBOR = 0x1000 - set by addstar, etc
+<li> PART_OF_TRAIL        = 0x2000 - set by markstar, fixcat, used by markrock
+<li> GHOST_DATA           = 0x4000 - set by markstar, fixcat, used by markrock
+</ul>
+
+<em> relphot flag meanings: </em>
+<b> ID_IMAGE_NOCAL </b> : completely ignore image (internal only)
+<b> ID_IMAGE_SKIP  </b> : externally marked, don't include in Mrel, calculate Mcal (?)
+<b> ID_IMAGE_POOR  </b> : internally marked, don't include in Mrel, calculate Mcal (?)
+
+<b> ID_STAR_NOCAL  </b> : poor star, don't include in Mcal, calculate Mrel
+STAR_BAD == (average.Xm > STAR_CHISQ) || (average.dM > STAR_SCATTER) || (NVALID < MEAS_TOOFEW)
+
+<b> ID_MEAS_NOCAL  </b> : skip this measurement (temporary, internal)
+<b> ID_MEAS_POOR   </b> : poor star, don't include in Mcal, calculate Mrel
+MEAS_POOR == (3 sigma outlier) || (out of detector area)
+<em> currently NOT sticky!! </em>
+
+--
+
+uniphot.h:
+# define MEAS_POOR     0x0001
+# define MEAS_NOCAL    0x0002
+# define ID_IMAGE_SKIP 0x0004
+
+relphot.h:
+# define ID_VARIABLE   0x2000
+# define ID_TRANSIENT  0x1000 /* is this mutually exclusive with USNO?  */
+# define ID_BAD_DATA   0x0800 /* stationary object with some bad data points */
+# define ID_PROPER     0x0400 /* star with large proper motion */
+
+# define MEAS_POOR     0x0001
+# define MEAS_NOCAL    0x0002
+# define ID_IMAGE_SKIP 0x0004
+
+<em> things to update, cleanup </em>
+<d> finish fix of photcode in imregister-3.0, etc </d>
+<d> move flag constants from relphot/uniphot/photdbc include -> loneos.h </d>
+<d> watch for use of Xp, Xg, code in photdbc & status.extract, status.gstar</d>
+<b> status.extract.NVALID : count !(measure.flag & MEAS_POOR) </b>
+<d> fix error with ID_IMAGE_NOCAL == ID_IMAGE_SKIP </d>
+<d> make sure ID_IMAGE_POOR is saved and ID_IMAGE_SKIP is kept, including with -mosaic </d>
+<d> should STAR_BAD be saved or not?  probably not: there is not one per photcode </d>
+<d> MEAS_POOR should be saved, MEAS_NOCAL should not </d>
+<b> recompile all dvo programs, test </b>
+
+<b> photdbc </b> <em> check on the use of flags, etc; consistent with relphot, uniphot? </em>
Index: /tags/start/Ohana/src/opihi/doc/notes.photcode.html
===================================================================
--- /tags/start/Ohana/src/opihi/doc/notes.photcode.html	(revision 12606)
+++ /tags/start/Ohana/src/opihi/doc/notes.photcode.html	(revision 12606)
@@ -0,0 +1,221 @@
+
+<h2> A Primer on DVO Photcodes and Magnitude Representation </h2>
+
+<p>
+There are two types of DVO table which store magnitude data.  The
+Average table stores magnitudes which represent averages of multiple
+measurements.  The Measure table stores magnitudes which represent
+single measurements.  
+
+<p>
+Each type of entry is defined by a Photcode.  The individual Measure
+entries have their photcodes stored as part of the structure.  The
+Average entries have photcodes which are determined externally by
+their sequence.  For historical reasons, the Average photcode are
+divided into the Primary photcode (of which there may only be one) and
+Secondary (of which there may be several).  The average magnitude
+associated with the Primary photcode is stored with the Average
+structure while the Secondary photcodes are stored in a separate,
+associated table called Secfilt.  The layout of the Average and
+Secfilt tables, and the photcodes assigned to them, are defined when
+the database is created based on the layout of the photcode table.
+This table is defined with a single Primary and a number of Secondary
+photcodes.  When the database tables are created, primary photcode is
+automatically associated with the Average entry while the sequence of
+Secondary photcodes defines the sequence of the entries in the Secfilt
+table.  This is very fragile, but very fast for making the
+association.  Thus, changing the number or sequence of secondary
+photcodes would cause an existing database table to be
+mis-interpretted.  
+
+<p>
+The Measure entries are broken into two photcode types as well:
+internal and external measurements.  Internal measurements are those
+for which the data source is well understood; the instrumental
+magnitudes are available and the instrumental parameters which are
+required to determine a calibrated magnitude.  External measurements
+are provided by external sources: published catalogs, reference
+sources, etc.  For these measurements, there is no control over the
+instrumental parameters which determined the measurement, and in many
+cases the measurement represents an average of an ensemble.
+
+<p>
+The photcode table defines relationships between photcodes,
+representing different photometry systems.  Each photcode entry
+defines the target of the calibration (the equivalence), and it may
+potentially define the zero-point (Co), the airmass slope (Ko), the
+appropriate color terms (C1, C2), the reference color term (Color),
+and the polynomial coefficients of the color equation (starting with
+the 1st order term).  
+
+<p>
+I need to include operations to handle varying color terms between
+CCDs.  I have measured color terms between CCDs in the range +/- 0.1
+mag/mag.  This is an appropriate time to clean up some of the code
+that handles the photcodes, etc.  In particular, the photcode table
+should provide the relationship beween relate between filter systems.
+
+For all of the functions below, a REF photcode simply returns the
+stored magnitude without transformation.  
+
+PhotInst (measure)
+  returns the instrumental magnitude of the given Measure
+  Minst = measure[0].M - measure[0].dt - iZERO_POINT;
+
+PhotCat (measure)
+  returns the 'catalog' magnitude of the given Measure (best guess
+  given no other information like color):
+  Mcat = measure[0].M - iZERO_POINT + Klam*(measure[0].airmass - 1000) + photcodes[0].code[Np].C;
+
+PhotSys (measure, average, secfilt)
+  returns the 'system' magnitude of the given Measure (best guess
+  using existing color information, but without application of
+  relative photometry offsets):
+  Msys = Mcat + f(color)
+  color is derived from measure.photcode.c1,c2  (measure.source.c1,c2)
+
+PhotRel (measure, average, secfilt)
+  returns the 'relative' magnitude of the given Measure (best guess
+  using existing color information and current relative photometry
+  measurment for this image).  This is the same photometry system as
+  the Average (PRI/SEC) measurement equivalent to this measurement
+  photcode:
+  Mrel = Msys + measure[0].Mcal;
+  color is derived from measure.photcode.c1,c2  (measure.source.c1,c2)
+
+PhotCal (measure, average, secfilt, allmeasures, code)
+  returns the 'calibrated' magnitude of the given Measure (best guess
+  using existing color information and current relative photometry
+  measurment for this image transformed to the appropriate reference
+  photometry system):
+  Mcal = Mref + f(color)
+  color is derived from code.c1,c2
+  the provided code must be either the measure.photcode.equiv or an
+  alternate for that code.
+
+<p>
+consider two filters, B & V, and two CCDs 00 & 01.  also, reference
+data in B_L92, V_L92
+
+<pre>
+    N  photcode     type  Co      Ko       X    C1    C2    Ao     Color  Equivalent
+  100  CFH12K.B.00  dep   26.000 -0.15     -    B     V     0.1    -      B
+  101  CFH12K.B.01  dep   26.000 -0.15     -    B     V     0.0    -      B
+
+  200  CFH12K.V.00  dep   26.100 -0.15     -    B     V     0.0    -      V
+  201  CFH12K.V.01  dep   26.100 -0.15     -    B     V     0.1    -      V
+
+    1  B            pri    0.000  -        -    B_L92 V_L92 0.016  -      B_L92
+    2  V            sec    0.000  -        -    B_L92 V_L92 0.008  -      V_L92
+
+  1003 B_L92        ref    -      -        -    -     -     -      -      -
+  1004 V_L92        ref    -      -        -    -     -     -      -      -
+  
+  B = m + Co + Ko*(secz - 1) + Ao*(B - V)
+  B_L92 = B + Co + color*A0 + color^2*A1 + color^3*A2
+</pre>
+
+<b>changes I'd like to make related to photcodes</b>
+
+<li> use structure value 'photcode', not 'source' everywhere
+<li> better abstraction / conceptualization of PhotMode values (Inst, Rel, Abs, Sys)
+<li> N-order polynomial for color-fits
+
+<b> relevant programs </b>
+
+<table>
+<tr><td>* addrefs    </td><td> minor fixes, no conversions are used </td></tr> 
+<tr><td>* addspphot  </td><td> minor fixes, no conversions are used </td></tr> 
+<tr><td>* addstar    </td><td> minor fixes, no conversions are used </td></tr> 
+<tr><td>* delstar    </td><td> minor fixes, no conversions are used </td></tr> 
+<tr><td>* photcode   </td><td> probably ok, check is consistent with new (?) photcode structs </td></tr> 
+<tr><td>* photreg    </td><td> check consistency </td></tr> 
+<tr><td>* photsearch </td><td> check consistency, use photcode table to get Equivalent </td></tr> 
+<tr><td>* relphot    </td><td> signficant changes to handle new structures </td></tr>
+<tr><td>libohana     </td><td> update LoadPhotcodes funcs, check consistency, use photcode table to get Equivalent </td></tr> 
+<tr><td>photdbc      </td><td> signficant changes to handle new structures </td></tr>
+<tr><td>status       </td><td> signficant changes to handle new structures </td></tr>
+<tr><td>dvo          </td><td> repeat fixes in status </td></tr> 
+
+<tr><td>lightcurve </td><td> unused? </td></tr>
+</table>
+
+<b> basic photcode APIs </b>
+
+int LoadPhotcodes (char *filename);
+void SetZeroPoint (double ZP);
+
+PhotCode *GetPhotcodebyName (name);
+int       GetPhotcodeCodebyName (name);
+PhotCode *GetPhotEquivbyName (name);
+int       GetPhotEquivCodebyName (name);
+
+PhotCode *GetPhotcodebyCode (code);
+char     *GetPhotcodeNamebyCode (code);
+
+PhotCode *GetPhotEquivbyCode (code);
+int       GetPhotEquivCodebyCode (code);
+
+double PhotInst (Measure *measure);
+double PhotAbs (Measure *measure);
+double PhotCat (Measure *measure);
+double PhotSys (Measure *measure, Average *average, SecFilt *secfilt);
+double PhotRel (Measure *measure, Average *average, SecFilt *secfilt);
+double PhotAve (PhotCode *code, Average *average, SecFilt *secfilt);
+double PhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure);
+
+<b> examples </b>
+find measures which are of photcode equivalent to X
+if (GetPhotEquivCodebyCode (measure[0].source) == N1) { } 
+
+<b> code, entry, hashcode, hashNsec </b>
+entry = 1;
+photcode[entry].code = 100 
+photcode[entry].name = B
+hashcode[100] = 1;
+
+hashNsec is only valid for type PHOT_SEC:
+hashNsec[code] = Nsec entry in SecFilt table
+
+<b> note recursion relationships </b>
+hashcode[photcode[entry].code] = entry;
+photcode[hashcode[entry]].code = entry
+
+<b> outstanding questions / issues </b>
+
+<ul>
+<li> PhotSys needs to handle missing color values
+<li> define valid range for color?
+<li> double PhotFoo functions return what on NO_MAG?
+<li> PhotFoo functions need to check for valid input types:
+  <ul> 
+  <li> PhotInst - PHOT_DEP
+  <li> PhotAbs  - PHOT_DEP, PHOT_REF
+  <li> PhotCat  - PHOT_DEP, PHOT_REF
+  <li> PhotSys  - PHOT_DEP, PHOT_REF
+  <li> PhotRel  - PHOT_DEP, PHOT_REF
+  <li> PhotAve  - PHOT_PRI, PHOT_SEC
+  <li> PhotRef  - PHOT_PRI, PHOT_SEC
+  </ul>
+</ul>
+
+<b> phot definitions </b>
+PhotInst = Measure.M - dt - ZP 
+PhotCat  = Measure.M + K*(airmass-1) + C - ZP
+PhotSys  = Measure.M + K*(airmass-1) + C - ZP + X*color
+PhotRel  = Measure.M + K*(airmass-1) + C - ZP + X*color - Mcal  -> average.m
+PhotRef  = average.M + C + X*color 
+
+C: def ~ 26.0, pri ~ 0.0
+
+PhotAbs  = deprecate (measure.M + K*(airmass-1) + C - ZP
+
+<b> alt photcodes </b>
+
+photcodes of type ALT provide alternate calibration terms for a given
+photcode.  these codes are equivalent to primary/secondary codes, but
+no data is ever saved with this type.  There are only lookups between
+the photcode name and the photcode structure, never the photcode.code
+value, since that defines the photcode for which the given structure
+is an alternate relationship.
+
Index: /tags/start/Ohana/src/opihi/doc/notes.txt
===================================================================
--- /tags/start/Ohana/src/opihi/doc/notes.txt	(revision 12606)
+++ /tags/start/Ohana/src/opihi/doc/notes.txt	(revision 12606)
@@ -0,0 +1,103 @@
+
+opihi improvements / fixes:
+
+* single math processing system : inline shell math used one set of
+  functions (shell/math.c), while the set = () used another set, and
+  logic used part of a third set.  This has been unified into a single
+  math handling function (newmath).  The new math expression handling
+  also returns temporary in-line vectors and matrix expressions.
+
+* global user variables (Buffers, Vectors) and other global variables
+  (outfile, tv parameters, graphic and image tool parameters) have
+  been encapsulated in fuctions to avoid the global data constructs.  
+
+* improved command exit status handling : in the past, a function
+  returning FALSE would halt all script executing, returning to the
+  top level of the command stack.  we now set the variable $STATUS
+  with the exit status and allow the the user to test the exit
+  status to choose an operation.  loops, macros, and input files can
+  use the 'break' and 'continue' functions to escape from the current
+  location.  calling break returns with an exit status of FALSE,
+  calling break returns immediately with an exit status of TRUE.
+
+* more extensive use of 'outfile' 
+
+* support for opihi scripts: there is now better interpretation of
+  command-line arguments to allow for embedded opihi scripts, ie
+  scripts with the dvo or mana interpretter named on the first line
+  with the prefix #! like a shell script.  The first command-line
+  argument is interpreted as a file to input while successive ones are
+  converted to variables $argv:0 - $argv:n  WARNING: in the past,
+  multiple input files could be specified on the command-line.  this
+  now must be specified with --load file arguments.
+
+* local variables: there is now support for local (vs global) opihi
+  variables.  any macro may have a variable declared as local with the
+  command 'local (var)', which may take a list of variables.  these
+  variables are stored internally in association with the macro name.
+  the command may include the option -static, in which case the
+  variable will retain its value on successive calls to the same
+  macro.
+
+- merge of all old opihi-type programs into a single code base 
+
+- group related functions into libraries
+
+- function names, etc, should come from a single function, now a
+  global include file.
+
+- update help files
+
+- update web pages
+
+--
+
+some notes: 
+
+- new vector interpretation is now somewhat slower, due to the multiple
+  assignments.
+
+- BinaryOp does not leak memory (tested)
+
+- 55 seconds for 1000 floating-pt operations on a 4Mpix (3 GHz) -> 0.2
+  seconds per FP OP on a 4k square image
+
+- loop / list functions:
+
+  opihi.c
+  run_loop.c
+  run_if.c
+  input.c
+  for_loop.c
+  macro_exec.c
+
+  I have added continue / break functionality to all loop operations:
+
+  * the variable $STATUS is set based on the exit status of each command
+  * each loop tests for break and continue
+  * in the case of break, the loop returns a status of FALSE
+  * in the case of continue, the loop returns a status of TRUE
+  * if break -auto is set to 'on', then any exit status of FALSE escapes to  
+    the top level.
+  * interrupts are carried up to the top level.
+
+- local variables
+
+  I have added local variables.  They have names of the form
+  MacroName.VarName, where MacroName is the macro in which they are
+  local.  They are declared local with the command 'local', which
+  takes a list of variables to declare local, and the optional -static
+  flag, which requires the shell to test for the existence of the
+  variable before creating it, and only create it if it does not
+  exist.  otherwise the existing value of the variable is maintained.
+
+- math
+
+  I have removed the last instances of math interpretation being
+  performed by math, not newmath, in expand_vectors (interpreting the
+  contents of the vector square brackets: x[5]), and in the two
+  locations where logic was used in the evaluation: run_in and
+  run_while.  there are still some error in the precedence of the
+  operators: logical operators >,<,==,!=, etc need to be lower
+  priority than other binary operators.
+
Index: /tags/start/Ohana/src/opihi/doc/sample.c
===================================================================
--- /tags/start/Ohana/src/opihi/doc/sample.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/doc/sample.c	(revision 12606)
@@ -0,0 +1,18 @@
+# include <stdio.h>
+
+main (int argc, char **argv) {
+
+  int i;
+  char line[1024];
+
+  for (i = 0; i <= argc; i++) {
+    fprintf (stderr, "arg %2d: %s\n", i, argv[i]);
+  }
+  while (argv[i] != NULL) {
+    fprintf (stderr, "env %2d: %s\n", i, argv[i]);
+    i++;
+  } 
+  while (fscanf (stdin, "%s", line) != EOF) {
+    fprintf (stderr, "line: ...%s...\n", line);
+  }
+}
Index: /tags/start/Ohana/src/opihi/doc/stds.txt
===================================================================
--- /tags/start/Ohana/src/opihi/doc/stds.txt	(revision 12606)
+++ /tags/start/Ohana/src/opihi/doc/stds.txt	(revision 12606)
@@ -0,0 +1,40 @@
+
+notation:
+
+object : an astronomical source, may be observed multiple times
+measurement : a single observation of an object (one per object per exposure) 
+m_inst : instrumental magnitude measurement
+m_cat  : catalog magnitude measurement (m_inst + 25.0)
+m_sys  : nominal internal system magnitude measurement (m_inst + ZP(CCD,FILTER)
+m_rel  : transparency adjusted magnitude measurement (m_sys + offset)
+
+M_ave  : average (object) magnitude in internal system
+M_ref  : average (object) magnitude in reference system
+
+test for photometric consistency:
+
+for the output from dither.corr:
+
+M_ave - m_rel(ccd) vs x_ccd, y_ccd
+M_ave - m_rel vs x_mosaic, y_mosaic
+M_ave - m_rel vs airmass?
+
+
+
+  MEGACAM.g.00 Minst - MEGACAM.g.01 Mcal : time
+
+  MEGACAM.g.00 - g : time
+
+  MEGACAM.g.00,Mrel - MEGACAM.g.01,Mcal : MEGACAM.g.00 - MEGACAM.r.00
+
+- use relphot to flag stars in poor locations, etc
+
+- we can choose for entry if it is Minst, Mcat, Msys, Mvrel, Mcal, Mave, or Mref
+
+int GetMagnitudeType (char *name, PhotCode *code, int *MagMode);
+
+- should return photcode & value MEAS_MREL, AVE_MREF, or what ever
+- should provide an appropriate default for measures, etc
+- should check for consistency with photcode type:
+  PRI/SEC : AVE_MREF, AVE_MAVE
+  DEP     : MEAS_ETC
Index: /tags/start/Ohana/src/opihi/doc/todo.txt
===================================================================
--- /tags/start/Ohana/src/opihi/doc/todo.txt	(revision 12606)
+++ /tags/start/Ohana/src/opihi/doc/todo.txt	(revision 12606)
@@ -0,0 +1,4 @@
+
+- convert and include all mana/dimm/status derived functions
+- local scalar variables
+- break / continue in: for, macro, 
Index: /tags/start/Ohana/src/opihi/dvo/ImageOps.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/ImageOps.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/ImageOps.c	(revision 12606)
@@ -0,0 +1,81 @@
+# include "dvo.h"
+
+void image_subset (Image *image, int Nimage, int **Subset, int *Nsubset,
+	      Graphdata *graph, int RegionSelect, 
+	      unsigned long int tzero, double trange, int TimeSelect) 
+{
+
+  int i, j, flipped, status, InPic;
+  int *subset;
+  int N, n, npts;
+  double r, d, x[4], y[4], Rmin, Rmax, Rmid;
+  double X[8], Y[8];
+
+  if (RegionSelect) {
+    Rmin = graph[0].coords.crval1 - 182.0;
+    Rmax = graph[0].coords.crval1 + 182.0;
+    Rmid = 0.5*(Rmin + Rmax);
+  }
+
+  if (trange < 0) {
+    tzero = tzero + trange;
+    trange = fabs (trange);
+  }
+  status = InPic = TRUE;
+  npts = 200;
+  ALLOCATE (subset, int, npts);
+  n = N = 0;
+  for (i = 0; i < Nimage; i++) {
+    if (TimeSelect && ((image[i].tzero < tzero) || (image[i].tzero+image[i].trate*image[i].NY > tzero + trange))) continue;
+    if (RegionSelect) {
+      /* project this image to screen display coords */
+      x[0] = 0;           y[0] = 0;
+      x[1] = image[i].NX; y[1] = 0;
+      x[2] = image[i].NX; y[2] = image[i].NY;
+      x[3] = 0;           y[3] = image[i].NY;
+      status = FALSE;
+      flipped = FALSE;
+      for (j = 0; j < 4; j++) {
+	XY_to_RD (&r, &d, x[j], y[j], &image[i].coords);
+	while ((j == 0) && (r < Rmin)) { flipped = TRUE; r += 360.0; }
+	while ((j == 0) && (r > Rmax)) { flipped = TRUE; r -= 360.0; }
+	if ((j > 0) && flipped) {
+	  while (r < Rmid) r+= 360.0;
+	  while (r > Rmid) r-= 360.0;
+	}
+	status |= RD_to_XY (&X[2*j], &Y[2*j], r, d, &graph[0].coords);
+	if (j > 0) {
+	  X[2*j - 1] = X[2*j];
+	  Y[2*j - 1] = Y[2*j];
+	}
+      }
+      X[7] = X[0];
+      Y[7] = Y[0];
+      InPic = FALSE;
+      for (j = 0; status && (j < 8); j+=2) {
+	if ((X[j] >= graph[0].xmin) && 
+	    (X[j] <= graph[0].xmax) && 
+	    (Y[j] >= graph[0].ymin) && 
+	    (Y[j] <= graph[0].ymax))
+	  InPic = TRUE;
+      }
+    }
+    if (InPic && status) {
+      subset[n] = i;
+      n++;
+      if (n > npts - 1) {
+	npts += 200;
+	REALLOCATE (subset, int, npts);
+      }
+    }
+  }
+
+  REALLOCATE (subset, int, MAX (n, 1));
+  *Subset = subset;
+  *Nsubset = n;
+  return;
+}
+
+/* this routine fills the subset index with the list of selected images.
+   images may be selected on the basis of the region or on a time range 
+*/
Index: /tags/start/Ohana/src/opihi/dvo/LoadImages.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/LoadImages.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/LoadImages.c	(revision 12606)
@@ -0,0 +1,51 @@
+# include "dvo.h"
+
+Image *LoadImages (int *Nimage) {
+
+  char filename[256];
+  int nimage, NIMAGE;
+  FILE *f;
+  Header header;
+  Image *image;
+  
+  VarConfig ("IMAGE_CATALOG", "%s", filename);
+
+  /* check if image datafile exists, get header */
+  if (!fits_read_header (filename, &header)) {
+    fprintf (stderr, "No available image catalog %s (1)\n", filename);
+    *Nimage = 0;
+    return ((Image *) NULL);
+  }
+
+  /* get ready to read data on images */ 
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "No available image catalog: %s (2)\n", filename);
+    free (header.buffer);
+    *Nimage = 0;
+    return ((Image *) NULL);
+  }
+
+  NIMAGE = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &NIMAGE);
+  if (NIMAGE == 0) {
+    fprintf (stderr, "no images found\n");
+    *Nimage = NIMAGE;
+    fclose (f);
+    return ((Image *) NULL);
+  }
+
+  ALLOCATE (image, Image, NIMAGE);
+  fseek (f, header.size, SEEK_SET); 
+  nimage = Fread (image, sizeof(Image), NIMAGE, f, "image");
+  if (nimage != NIMAGE) {
+    fprintf (stderr, "failed to read in all images (%d of %d)\n", nimage, NIMAGE);
+  }
+
+  fclose (f);
+  *Nimage = nimage;
+  return (image);
+
+
+}
+  
Index: /tags/start/Ohana/src/opihi/dvo/Makefile
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/Makefile	(revision 12606)
@@ -0,0 +1,164 @@
+include ../../../Configure
+
+default: all
+
+HOME    =       $(ROOT)/src/opihi.v2
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+HELP    =       $(HOME)/help
+SDIR    =       $(HOME)/dvo
+#
+DESTBIN =       $(LBIN)
+DESTLIB =       $(LLIB)
+DESTINC =       $(LINC)
+DESTMAN =       $(LMAN)
+#  
+INCS    =       -I$(INC) -I$(LINC) -I$(XINC)
+LFLAGS  =       -L$(LLIB) -L$(LIB)
+LIBS1   =       -lFITS -lsocket -lnsl -lreadline -ltermcap -lohana -lm
+LIBS2   =       -lbasiccmd -ldatacmd -lastrocmd -lshell -ldata 
+LIBS    =       $(LIBS2) $(LIBS1) 
+CFLAGS  =       $(INCS)
+CCFLAGS =       $(LIBS) 
+
+# dvo user commands and support functions ########################
+
+dvo = \
+$(SDIR)/init.$(ARCH).o            	\
+$(SDIR)/avextract.$(ARCH).o	  	\
+$(SDIR)/badimages.$(ARCH).o	  	\
+$(SDIR)/calextract.$(ARCH).o      	\
+$(SDIR)/calmextract.$(ARCH).o     	\
+$(SDIR)/catalog.$(ARCH).o	  	\
+$(SDIR)/cmatch.$(ARCH).o	  	\
+$(SDIR)/ccd.$(ARCH).o             	\
+$(SDIR)/cmd.$(ARCH).o             	\
+$(SDIR)/cmpload.$(ARCH).o	  	\
+$(SDIR)/cmpread.$(ARCH).o	  	\
+$(SDIR)/ddmags.$(ARCH).o	  	\
+$(SDIR)/dmagaves.$(ARCH).o	  	\
+$(SDIR)/dmagmeas.$(ARCH).o	  	\
+$(SDIR)/dmags.$(ARCH).o		  	\
+$(SDIR)/dmt.$(ARCH).o		  	\
+$(SDIR)/gcat.$(ARCH).o		  	\
+$(SDIR)/gimages.$(ARCH).o	  	\
+$(SDIR)/gstar.$(ARCH).o		  	\
+$(SDIR)/images.$(ARCH).o	  	\
+$(SDIR)/imbox.$(ARCH).o		  	\
+$(SDIR)/imdata.$(ARCH).o	  	\
+$(SDIR)/imdense.$(ARCH).o	  	\
+$(SDIR)/imextract.$(ARCH).o	  	\
+$(SDIR)/imlist.$(ARCH).o	  	\
+$(SDIR)/imphot.$(ARCH).o	  	\
+$(SDIR)/imrough.$(ARCH).o	  	\
+$(SDIR)/imsearch.$(ARCH).o	  	\
+$(SDIR)/imstats.$(ARCH).o	  	\
+$(SDIR)/lcat.$(ARCH).o		  	\
+$(SDIR)/lcurve.$(ARCH).o	  	\
+$(SDIR)/mextract.$(ARCH).o	  	\
+$(SDIR)/pcat.$(ARCH).o		  	\
+$(SDIR)/photcodes.$(ARCH).o	  	\
+$(SDIR)/pmeasure.$(ARCH).o	  	\
+$(SDIR)/procks.$(ARCH).o	  	\
+$(SDIR)/showtile.$(ARCH).o	  	\
+$(SDIR)/simage.$(ARCH).o	  	\
+$(SDIR)/subpix.$(ARCH).o 		\
+$(SDIR)/find_regions.$(ARCH).o	  	\
+$(SDIR)/get_regions.$(ARCH).o           \
+$(SDIR)/aregion.$(ARCH).o               \
+$(SDIR)/region_list.$(ARCH).o		\
+$(SDIR)/match_image.$(ARCH).o		\
+$(SDIR)/LoadImages.$(ARCH).o		\
+$(SDIR)/ImageOps.$(ARCH).o		\
+$(SDIR)/dvomisc.$(ARCH).o		\
+$(SDIR)/compare.$(ARCH).o               \
+$(SDIR)/photometry.$(ARCH).o            \
+$(SDIR)/dvo.$(ARCH).o
+
+all: dvo
+
+dvo: $(BIN)/dvo.$(ARCH)
+	@echo done
+
+$(BIN)/dvo.$(ARCH) : $(dvo)
+
+install: $(DESTBIN)/dvo
+
+# utilities #################################################
+$(BIN)/%.$(ARCH):
+	@if [ ! -d $(BIN) ]; then mkdir -p $(BIN); fi
+	$(CC) $^ -o $@ $(LFLAGS) $(LIBS)
+	@echo "compiled $*"
+	@echo ""
+
+$(DESTBIN)/%: $(BIN)/%.$(ARCH) 
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	rm -f $(DESTBIN)/$*
+	cp $(BIN)/$*.$(ARCH) $(DESTBIN)/$*
+	@echo "installed $*"
+	@echo ""
+
+$(LIB)/%.$(ARCH).a:
+	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
+	rm -f $@
+	ar rcv $@ $^ 
+	ranlib $@
+	@echo "compiled library $*"
+	@echo ""
+
+$(DESTLIB)/%.a: $(LIB)/%.$(ARCH).a
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	@echo ""
+	rm -f $@
+	cp $^ $@
+
+clean:
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f $(LIB)/*.$(ARCH).a
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+dist: clean
+	rm -f $(BIN)/*
+	rm -f $(LIB)/*
+
+lib%.clean:
+	rm -f $(LIB)/lib$*.$(ARCH).a
+	rm -f $($*)
+	@echo ""
+
+%.clean:
+	rm -f $(BIN)/$*.$(ARCH)
+	@echo ""
+
+%.$(ARCH).o : %.c
+	$(CC) $(CFLAGS) -c $*.c -o $@
+
+
+
+## -*- makefile -*- 
+# deprecated functions: verify & delete
+#$(SDIR)/abszero.$(ARCH).o \
+#$(SDIR)/cals.$(ARCH).o \
+#$(SDIR)/dumpmags.$(ARCH).o \
+#$(SDIR)/extract.$(ARCH).o \
+#$(SDIR)/gtypes.$(ARCH).o \
+#$(SDIR)/photresid.$(ARCH).o \
+#$(SDIR)/resid.$(ARCH).o \
+#$(SDIR)/zeropts.$(ARCH).o
+#$(SDIR)/objload.$(ARCH).o \ - make sure we have vect to tv
+#$(SDIR)/ccdextract.$(ARCH).o \
+#$(SDIR)/cmdextract.$(ARCH).o \
+#$(SDIR)/dmagextract.$(ARCH).o \
+#$(SDIR)/ddmagextract.$(ARCH).o \
+
+# future functions, not fully implemented
+#$(SDIR)/detrend.$(ARCH).o \
+#$(SDIR)/getxtra.$(ARCH).o \
+#$(SDIR)/addxtra.$(ARCH).o \
+
+# functions that need to be updated
+#$(SDIR)/gregions.$(ARCH).o \
+
Index: /tags/start/Ohana/src/opihi/dvo/addxtra.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/addxtra.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/addxtra.c	(revision 12606)
@@ -0,0 +1,60 @@
+# include "dvo.h"
+
+typedef struct {
+  char type[64];
+  char name[64];
+  char source[256];
+  char mode[64];
+  char value[64];
+  char range[64];
+  double R, D;
+  int averef;
+} Xtras;
+
+int addxtra (int argc, char **argv) {
+  
+  Source = (char *) NULL;
+  if (N = get_argument (argc, argv, "-source")) {
+    remove_argument (N, &argc, argv);
+    Source = strcreate (atof[N]);
+    remove_argument (N, &argc, argv);
+  }
+  Name = (char *) NULL;
+  if (N = get_argument (argc, argv, "-name")) {
+    remove_argument (N, &argc, argv);
+    Name = strcreate (atof[N]);
+    remove_argument (N, &argc, argv);
+  }
+  Mode = (char *) NULL;
+  if (N = get_argument (argc, argv, "-mode")) {
+    remove_argument (N, &argc, argv);
+    Mode = strcreate (atof[N]);
+    remove_argument (N, &argc, argv);
+  }
+  Range = (char *) NULL;
+  if (N = get_argument (argc, argv, "-range")) {
+    remove_argument (N, &argc, argv);
+    Range = strcreate (atof[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 6) {
+    fprintf (stderr, "USAGE: addxtra R D radius (type) (value)\n");
+    return (FALSE);
+  }
+  
+  /*
+
+  validate the input values (type, defines the needed options)
+  find catalog (based on r,d)
+  load catalog (need to load measures?)
+  find the object
+  find the xtra entry (sorted by ra/dec? sorted by averef?)
+  add new entry
+  save catalog 
+  */
+}
+
+/* 
+  addxtra R D dR type value -name (name) -source (source) -mode (mode) -range (range) 
+*/
Index: /tags/start/Ohana/src/opihi/dvo/aregion.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/aregion.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/aregion.c	(revision 12606)
@@ -0,0 +1,81 @@
+# include "dvo.h"
+# include "hstgsc.h"
+
+/* find region file which contains ra, dec */
+void aregion (GSCRegion *region, FILE *f, double ra, double dec, char *path) {
+  
+  char buffer[28800], temp[50], file[50];
+  double RA0, RA1, DEC0, DEC1;
+  int i, NBigDec, NLINES, done;
+  
+  while (ra < 0) { ra += 360.0; }
+  while (ra >= 360.0) { ra -= 360.0; }
+
+  if (dec >= 86.25) {
+    sprintf (file, "%s/n8230/pole.cpt", path);
+    region[0].DEC[0] = 86.25;
+    region[0].DEC[1] = 93.75;
+    region[0].RA[0] =  0.0;
+    region[0].RA[1] =  360.0;
+    strcpy (region[0].filename, file);
+    return;
+  }
+    
+  NBigDec = -1;
+  for (i = 0; i < 12; i++) {
+    if ((dec >= BigDecBounds[i]) && (dec < BigDecBounds[i+1])) {
+      NBigDec = i;
+      break;
+    }
+  }
+  if (NBigDec < 0) {
+    for (i = 13; i < 24; i++) {
+      if ((dec < BigDecBounds[i]) && (dec >= BigDecBounds[i+1])) {
+	NBigDec = i;
+	break;
+      }
+    }
+  }
+  if (NBigDec < 0) {
+    fprintf (stderr, "dec out of range: %f\n", dec);
+  }
+    
+  NLINES = 0;
+  for (i = 0; i < NBigDec; i++) {
+    NLINES += NDecLines[i];
+  }
+  fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+      
+  done = FALSE;
+  Fread (buffer, 1, 48*NDecLines[NBigDec], f, "char");
+  for (i = 0; !done && (i < NDecLines[NBigDec]); i++) {
+    strncpy (temp, &buffer[i*48], 48);
+    temp[49] = 0;
+    hstgsc_hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+    if (RA1 < RA0) RA1 += 360.0;
+    if ((dec >= 0) && (dec >= DEC0) && (dec < DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+    if ((dec < 0) && (dec < DEC0) && (dec >= DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+  }
+
+  if (!done) {
+    fprintf (stderr, "error in search: %f %f\n", ra, dec);
+    exit (0);
+  }
+  temp[5] = 0;
+  sprintf (file, "%s/%s/%s.cpt", path, Dec2Sections[NBigDec],&temp[1]);
+  if (DEC0 < DEC1) {
+    region[0].DEC[0] = DEC0;
+    region[0].DEC[1] = DEC1;
+  } else {
+    region[0].DEC[0] = DEC1;
+    region[0].DEC[1] = DEC0;
+  }     
+  region[0].RA[0] = RA0;
+  region[0].RA[1] = RA1;
+  strcpy (region[0].filename, file);
+  return;
+}
Index: /tags/start/Ohana/src/opihi/dvo/avextract.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/avextract.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/avextract.c	(revision 12606)
@@ -0,0 +1,151 @@
+# include "dvo.h"
+
+int avextract (int argc, char **argv) {
+  
+  Catalog catalog;
+  Graphdata graphsky;
+  RegionFile *regions;
+  PhotCode *code;
+  Vector *vec;
+
+  char filename[256], catdir[256], *p;
+  int i, j, m, N, NPTS, param;
+  int Ngraph, Nsec, Nregions, mode;
+
+  regions = NULL;
+  catalog.average = NULL; 
+  catalog.secfilt = NULL;
+  catalog.measure = NULL;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsec = GetPhotcodeNsecfilt ();
+
+  /* load data about plot windows */
+  Ngraph = 0;
+  if (!GetGraphData (&graphsky, NULL, &Ngraph)) goto escape;
+ 
+  /* find CATDIR in config system */
+  VarConfig ("CATDIR", "%s", catdir);
+
+  /* grab value of photcode, if available */
+  code = NULL;
+  mode = MAG_AVE;
+  if (N = get_argument (argc, argv, "-photcode")) {
+    remove_argument (N, &argc, argv);
+    code = GetPhotcodebyName (argv[N]);
+    if (code == NULL) {
+      fprintf (stderr, "photcode not found in photcode table\n");
+      goto usage;
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  /* interpret command-line options */
+  if (!SetPhotSelections (&argc, argv)) goto usage;
+  if (argc != 3) { goto usage; }
+
+  /* identify selection */
+  param = GetAverageParam (argv[2]);
+  if (param == AVE_ZERO) {
+    if (!GetPhotcodeInfo (argv[2], &code, &mode)) {
+      GetAverageParam ("help");
+      fprintf (stderr, "value may also be a valid photcode\n");
+      fprintf (stderr, "photcodes or 'mag' may have optional magnitude mode: mag,[Mave, Mref]\n");
+      goto escape;
+    }
+    param = AVE_MAG;
+    for (p = argv[2]; *p != 0; p++) { 
+      if (*p == '.') *p = ':';
+    }
+  } 
+  if ((vec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) goto escape;
+
+  /* need valid code for some params: */
+  switch (param) {
+    case AVE_MAG:
+    case AVE_dMAG:
+    case AVE_Xm:
+    case AVE_TYPE:
+    case AVE_NCODE:
+    case AVE_NPHOT: 
+      if (code == NULL) goto escape;
+      if (code[0].type == PHOT_DEP) goto escape;
+      if (code[0].type == PHOT_REF) goto escape;
+      break;
+    default:
+      break;
+  }
+
+  /* determine region-file names */
+  if (!strcmp (argv[1], "all")) {
+    float Radius;
+    Radius = MAX (fabs(graphsky.xmax), fabs(graphsky.ymax));
+    regions = find_regions (graphsky.coords.crval1, graphsky.coords.crval2, Radius, &Nregions);
+    if (!SetImageSelection (param, &graphsky, TRUE)) goto escape;
+  } else {
+    Nregions = 1;
+    ALLOCATE (regions, RegionFile, 1);
+    strcpy (regions[0].name, argv[1]);
+    if (!SetImageSelection (param, NULL, FALSE)) goto escape;
+  }
+
+  /* create storage vector */
+  N = 0;
+  NPTS = 1000;
+  REALLOCATE (vec[0].elements, float, NPTS);
+
+  for (i = 0; i < Nregions; i++) {
+    /* lock, load, unlock catalog */
+    sprintf (filename, "%s/%s", catdir, regions[i].name);
+    catalog.filename = filename;
+    switch (lock_catalog (&catalog, LCK_SOFT)) {
+    case 2:
+      unlock_catalog (&catalog);
+    case 0:
+      continue;
+    }
+    if (!load_catalog (&catalog, LOAD_AVES | LOAD_MEAS | LOAD_SECF, FALSE)) {
+      unlock_catalog (&catalog);
+      continue;
+    }
+    unlock_catalog (&catalog);
+
+    for (j = 0; j < catalog.Naverage; j++) {
+      m = catalog.average[j].offset;
+      vec[0].elements[N] = ExtractAverages (code, mode, &catalog.average[j], &catalog.secfilt[j*Nsec], &catalog.measure[m], param);
+      N++;
+      if (N == NPTS - 1) {
+	NPTS += 2000;
+	REALLOCATE (vec[0].elements, float, NPTS);
+      }
+    }
+    if (catalog.average != NULL) free (catalog.average);
+    if (catalog.secfilt != NULL) free (catalog.secfilt);
+    if (catalog.measure != NULL) free (catalog.measure);
+    catalog.average = (Average *) NULL; 
+    catalog.secfilt = (SecFilt *) NULL;
+    catalog.measure = (Measure *) NULL;
+  }
+  vec[0].Nelements = N;
+  REALLOCATE (vec[0].elements, float, MAX(1,N));
+
+  if (regions != NULL) free (regions);
+  FreeImageSelection ();
+  return (TRUE);
+
+usage:
+  fprintf (stderr, "USAGE: avextract (from) (value) [options]\n");
+  fprintf (stderr, "  from: cpt name or 'all'\n");
+  fprintf (stderr, "  value: average.parameter or photcode\n");
+  return (FALSE);
+
+escape:
+  fprintf (stderr, "error in avextract\n");
+  if (regions != NULL) free (regions);
+  FreeImageSelection ();
+  if (catalog.average != NULL) free (catalog.average);
+  if (catalog.secfilt != NULL) free (catalog.secfilt);
+  if (catalog.measure != NULL) free (catalog.measure);
+  return (FALSE);
+}
Index: /tags/start/Ohana/src/opihi/dvo/badimages.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/badimages.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/badimages.c	(revision 12606)
@@ -0,0 +1,102 @@
+# include "dvo.h"
+
+static int badim_int = FALSE;
+void badim_escape () {
+  badim_int = TRUE;
+}
+
+int badimages (int argc, char **argv) {
+  
+  FILE *f;
+  int i, Nimage, nimage, entry, First, Cross;
+  float *ptr;
+  double nominal, big, small, value;
+  Header header;
+  Image *image;
+  char ImageCat[256];
+
+  VarConfig ("IMAGE_CATALOG", "%s", ImageCat);
+  
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: badimages entry value\n");
+    fprintf (stderr, "   OR: badimages -image N\n");
+    return (FALSE);
+  }
+  
+  First = FALSE;
+  if (!strcmp (argv[1], "-image")) {
+    First = TRUE;
+    entry = atof(argv[2]);
+  } else {
+    entry = atof(argv[1]);
+    nominal = atof(argv[2]);
+    Cross = FALSE;
+    if (!strcasecmp (argv[1], "x")) {
+      Cross = TRUE;
+    }
+  }
+  
+  /* check if image datafile exists, get header */
+  if (!fits_read_header (ImageCat, &header)) {
+    fprintf (stderr, "can't open image catalog %s\n", ImageCat);
+    return (FALSE);
+  }
+  
+  /* get ready to read data on images */ 
+  f = fopen (ImageCat, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open image catalog %s\n", ImageCat);
+    return (FALSE);
+  }
+  fseek (f, header.size, SEEK_SET); 
+  
+  /* read in image data */
+  Nimage = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+  ALLOCATE (image, Image, Nimage);
+  nimage = Fread (image, sizeof(Image), Nimage, f, "image");
+  fclose (f);
+  if (nimage != Nimage) {
+    fprintf (stderr, "error reading all data from image file (%d != %d)\n", nimage, Nimage);
+    free (image);
+    return (FALSE);
+  }
+  
+  if (First) {
+    ptr = &image[entry].coords.crpix1;
+    for (i = 0; i < 22; i++) {
+      fprintf (GetOutfile(), "%2d: %g\n", i, ptr[i]);
+    }
+    value = image[entry].coords.pc1_1*image[entry].coords.pc2_2 + image[entry].coords.pc1_2*image[entry].coords.pc2_1;
+    fprintf (GetOutfile(), " x: %g\n", value);
+    return (TRUE);
+  }
+  
+  big = nominal * 1.05;
+  small = nominal / 1.05;
+  if (big < small) {
+    double tmp;
+    tmp = big; big = small; small = tmp;
+  }
+  
+  badim_int = FALSE;
+  if (Cross) {
+    for (i = 0; (i < Nimage) && !badim_int; i++) {
+      value = image[i].coords.pc1_1*image[i].coords.pc2_2 + image[i].coords.pc1_2*image[i].coords.pc2_1;
+      if ((value > big) || (value < small)) {
+	fprintf (GetOutfile(), "%5d %s: %d %g\n", i, image[i].name, image[i].tzero, value);
+      }
+    }
+  } else {
+    for (i = 0; (i < Nimage) && !badim_int; i++) {
+      ptr = &image[i].coords.crpix1;
+      if ((ptr[entry] > big) || (ptr[entry] < small)) {
+	fprintf (GetOutfile(), "%5d %s: %d %g\n", i, image[i].name, image[i].tzero, ptr[entry]);
+      }
+    }
+  }
+  
+  return (TRUE);
+
+}
+  
Index: /tags/start/Ohana/src/opihi/dvo/calextract.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/calextract.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/calextract.c	(revision 12606)
@@ -0,0 +1,158 @@
+# include "dvo.h"
+
+enum {Nd, Nm, NC, NR, ND, Np, Nc, Nt, Nx, Nd1, Nd2, NVEC};
+
+int calextract (int argc, char **argv) {
+  
+  Catalog catalog;
+  Graphdata graphsky;
+  RegionFile *regions;
+  PhotCode *code[2];
+  Vector **vec;
+
+  int i, j, m, N, Nr, Nregions, mode[2];
+  int RegionList, Ngraph, Nsec, NSTAR;
+  char filename[256], catdir[256], RegionListFile[256];
+  double Radius, M1, M2, dM2, color;
+
+  /* these need to be freed in the end */
+  regions = NULL;
+  catalog.average = NULL; 
+  catalog.secfilt = NULL;
+  catalog.measure = NULL;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) return (FALSE);
+  Nsec = GetPhotcodeNsecfilt ();
+
+  /* load data about plot windows */
+  Ngraph = 0;
+  if (!GetGraphData (&graphsky, NULL, &Ngraph)) goto escape;
+
+  /* find CATDIR in config system */
+  VarConfig ("CATDIR", "%s", catdir);
+
+  /* specify catalog files */
+  RegionList = FALSE;
+  if (N = get_argument (argc, argv, "-list")) {
+    RegionList = TRUE;
+    remove_argument (N, &argc, argv);
+    strcpy (RegionListFile, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* command line arguments */
+  if (!SetPhotSelections (&argc, argv)) goto usage;
+  if (argc != 4) goto usage;
+  if (strcmp (argv[2], "-")) goto usage;
+  if (!GetPhotcodeInfo (argv[1], &code[0], &mode[0])) goto usage;
+  if (!GetPhotcodeInfo (argv[3], &code[1], &mode[1])) goto usage;
+  /* code.type must be PHOT_REF */
+
+  /* one unique value per star */
+  N = 0;
+  NSTAR = 1;
+  ALLOCATE (vec, Vector *, NVEC);
+  if ((vec[Nd] 	= SelectVector ("cal:dmag",     ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nm] 	= SelectVector ("cal:mag",      ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[NC] 	= SelectVector ("cal:color",    ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[NR] 	= SelectVector ("cal:ra",       ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[ND] 	= SelectVector ("cal:dec",      ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Np] 	= SelectVector ("cal:nphot",    ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nc] 	= SelectVector ("cal:ncode",    ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nt] 	= SelectVector ("cal:ncrit",    ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nx] 	= SelectVector ("cal:chisq",    ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nd1] = SelectVector ("cal:dm1",      ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nd2] = SelectVector ("cal:dm2",      ANYVECTOR, TRUE)) == NULL) goto escape;
+
+  /* select region files */
+  if (RegionList) {
+    regions = region_list (RegionListFile, &Nregions);
+  } else {
+    Radius = MAX (fabs(graphsky.xmax), fabs(graphsky.ymax));
+    regions = find_regions (graphsky.coords.crval1, graphsky.coords.crval2, Radius, &Nregions);
+  }
+
+  for (Nr = 0; Nr < Nregions; Nr++) {
+    if (Nr && !(Nr % 500)) { fprintf (stderr, "."); }
+
+    /* lock, load, unlock catalog */
+    sprintf (filename, "%s/%s", catdir, regions[Nr].name);
+    catalog.filename = filename;
+    switch (lock_catalog (&catalog, LCK_SOFT)) {
+    case 2:
+      unlock_catalog (&catalog);
+    case 0:
+      continue;
+    }
+    if (!load_catalog (&catalog, LOAD_AVES | LOAD_MEAS | LOAD_SECF, FALSE)) {
+      unlock_catalog (&catalog);
+      continue;
+    }
+    unlock_catalog (&catalog);
+
+    /* extract values, assign to vectors */
+    for (i = 0; i < catalog.Naverage; i++) {
+      m = catalog.average[i].offset;
+
+      if (code[0][0].c1 && code[0][0].c2 && !PhotColor (&catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], code[0][0].c1, code[0][0].c2, &color)) continue;
+
+      /* find data for filter 2 (PHOT_REF) */
+      M2 = NO_MAG;
+      for (j = 0; j < catalog.average[i].Nm; j++) {
+	if (catalog.measure[m+j].source != code[1][0].code) continue;
+	M2 = PhotCat  (&catalog.measure[m+j]);
+	dM2 = 0.001*catalog.measure[m+j].dM;
+      }	
+      if (M2 == NO_MAG) continue;
+
+      /* find data for filter 1 */
+      M1 = ExtractAverages (code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], AVE_MAG);
+      if (M1 == NO_MAG) continue;
+
+      vec[Nd ][0].elements[N] = M1 - M2;
+      vec[Nm ][0].elements[N] = M2;
+      vec[NC ][0].elements[N] = color;
+      vec[NR ][0].elements[N] = catalog.average[i].R;
+      vec[ND ][0].elements[N] = catalog.average[i].D;
+      vec[Nd1][0].elements[N] = ExtractAverages (code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], AVE_dMAG);
+      vec[Nd2][0].elements[N] = dM2;
+      vec[Nx ][0].elements[N] = ExtractAverages (code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], AVE_Xm);
+      vec[Nc ][0].elements[N] = ExtractAverages (code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], AVE_NCODE);
+      vec[Np ][0].elements[N] = ExtractAverages (code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], AVE_NPHOT);
+      vec[Nt ][0].elements[N] = ExtractAverages (code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], AVE_NCRIT);
+      N ++;
+      if (N == NSTAR) {
+	NSTAR += 100;
+	for (i = 0; i < NVEC; i++) {
+	  REALLOCATE (vec[i][0].elements, float, NSTAR);
+	}
+      }
+    }
+    if (catalog.average != (Average *) NULL) free (catalog.average);
+    if (catalog.measure != (Measure *) NULL) free (catalog.measure);
+    if (catalog.secfilt != (SecFilt *) NULL) free (catalog.secfilt);
+    catalog.average = (Average *) NULL; 
+    catalog.secfilt = (SecFilt *) NULL;
+    catalog.measure = (Measure *) NULL;
+  }
+  if (regions != NULL) free (regions);  
+  for (i = 0; i < NVEC; i++) {
+    vec[i][0].Nelements = N;
+  }
+  return (TRUE);
+  
+usage:
+  fprintf (stderr, "USAGE: calextract F - F\n");
+  return (FALSE);
+
+ escape:
+  
+  if (regions != NULL) free (regions);  
+  for (i = 0; i < NVEC; i++) {
+    DeleteVector (vec[i]);
+  }
+  free (vec);
+
+  return (FALSE);
+}
Index: /tags/start/Ohana/src/opihi/dvo/calmextract.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/calmextract.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/calmextract.c	(revision 12606)
@@ -0,0 +1,214 @@
+# include "dvo.h"
+
+enum {Nd, Nm1, Nm2, Nc, Ns, Nt, Nz, NR, ND, Nxc, Nyc, Nxm, Nym, NT, NP, Nd1, Nd2, NVEC};
+int ConcatMeasures (Vector *vec, PhotCode *code, int mode, Average *average, SecFilt *secfilt, Measure *measure, int param, int Nin);
+
+int calmextract (int argc, char **argv) {
+  
+  Catalog catalog;
+  Graphdata graphsky;
+  RegionFile *regions;
+  PhotCode *code[2];
+  Vector **vec;
+
+  int i, j, k, m, N, N1, Nr, mode[2];
+  int Ngraph, NSTAR, NStar, Nsec, Nstar, Nregions, RegionList;
+  char filename[256], catdir[256], RegionListFile[256];
+  double *M1, M2, dM2, color, Radius;
+
+  /* these need to be freed in the end */
+  regions = NULL;
+  catalog.average = NULL; 
+  catalog.secfilt = NULL;
+  catalog.measure = NULL;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) return (FALSE);
+  Nsec = GetPhotcodeNsecfilt ();
+
+  /* load data about plot windows */
+  Ngraph = 0;
+  if (!GetGraphData (&graphsky, NULL, &Ngraph)) goto escape;
+
+  /* find CATDIR in config system */
+  VarConfig ("CATDIR", "%s", catdir);
+
+  /* specify catalog files */
+  RegionList = FALSE;
+  if (N = get_argument (argc, argv, "-list")) {
+    RegionList = TRUE;
+    remove_argument (N, &argc, argv);
+    strcpy (RegionListFile, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* command line arguments */
+  if (!SetPhotSelections (&argc, argv)) goto usage;
+  if (argc != 4) goto usage;
+  if (strcmp (argv[2], "-")) goto usage;
+  if (!GetPhotcodeInfo (argv[1], &code[0], &mode[0])) goto usage;
+  if (!GetPhotcodeInfo (argv[3], &code[1], &mode[1])) goto usage;
+  /* code.type must be PHOT_REF */
+
+  /* test PhotSelections: is photcode specified if needed? */
+  if (!TestPhotSelections (&code)) {
+    fprintf (stderr, "photcode selection rules violated\n");
+    fprintf (stderr, "average and ensemble restrictions require a corresponding photcode\n");
+    goto escape;
+  }
+
+
+  /* returned vectors are dmag, mag, color, time, airmass, ra, dec, x, y, exptime */
+  N = 0;
+  Nstar = 0;
+  NSTAR = 100;
+  ALLOCATE (vec, Vector *, NVEC);
+  if ((vec[Nd ] = SelectVector ("cal:dmag",     ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nm1] = SelectVector ("cal:mag1",     ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nm2] = SelectVector ("cal:mag2",     ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nc ] = SelectVector ("cal:color",    ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Ns ] = SelectVector ("cal:star",     ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nt ] = SelectVector ("cal:time",     ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nz ] = SelectVector ("cal:airmass",  ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[NR ] = SelectVector ("cal:ra",       ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[ND ] = SelectVector ("cal:dec",      ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nxc] = SelectVector ("cal:xccd",     ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nyc] = SelectVector ("cal:yccd",     ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nxm] = SelectVector ("cal:xmosaic",  ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nym] = SelectVector ("cal:ymosaic",  ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[NT ] = SelectVector ("cal:exptime",  ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[NP ] = SelectVector ("cal:photcode", ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nd1] = SelectVector ("cal:dm1",      ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nd2] = SelectVector ("cal:dm2",      ANYVECTOR, TRUE)) == NULL) goto escape;
+  for (k = 0; k < NVEC; k++) {
+    REALLOCATE (vec[k][0].elements, float, NSTAR);
+    vec[k][0].Nelements = 0;
+  }
+
+  /* select region files */
+  if (RegionList) {
+    regions = region_list (RegionListFile, &Nregions);
+    if (!SetImageSelection (MEAS_XMOSAIC, NULL, FALSE)) goto escape;
+  } else {
+    Radius = MAX (fabs(graphsky.xmax), fabs(graphsky.ymax));
+    regions = find_regions (graphsky.coords.crval1, graphsky.coords.crval2, Radius, &Nregions);
+    if (!SetImageSelection (MEAS_XMOSAIC, &graphsky, TRUE)) goto escape;
+  }
+
+  for (Nr = 0; Nr < Nregions; Nr++) {
+    if (Nr && !(Nr % 500)) { fprintf (stderr, "."); }
+
+    /* lock, load, unlock catalog */
+    sprintf (filename, "%s/%s", catdir, regions[Nr].name);
+    catalog.filename = filename;
+    switch (lock_catalog (&catalog, LCK_SOFT)) {
+    case 2:
+      unlock_catalog (&catalog);
+    case 0:
+      continue;
+    }
+    if (!load_catalog (&catalog, LOAD_AVES | LOAD_MEAS | LOAD_SECF, FALSE)) {
+      unlock_catalog (&catalog);
+      continue;
+    }
+    unlock_catalog (&catalog);
+
+    /* extract values, assign to vectors */
+    for (i = 0; i < catalog.Naverage; i++) {
+      m = catalog.average[i].offset;
+
+      /* PRI/SEC must have data for color term */
+      if (code[0][0].c1 && code[0][0].c2 && !PhotColor (&catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], code[0][0].c1, code[0][0].c2, &color)) continue;
+
+      /* find data for filter 2 (REF) */
+      M2 = NO_MAG;
+      for (j = 0; j < catalog.average[i].Nm; j++) {
+	if (catalog.measure[m+j].source != code[1][0].code) continue;
+	M2 = PhotCat  (&catalog.measure[m+j]); 
+	dM2 = 0.001*catalog.measure[m+j].dM;
+      }	
+      if (M2 == NO_MAG) continue;
+      
+      /* find data for filter 1 */
+      M1 = ExtractMeasures (code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], &N1, MEAS_MAG);
+      if (N1 == 0) goto skip;
+
+      /* extend storage vectors to take new data, if needed */
+      if (N + N1 >= NSTAR) {
+	NSTAR += N1 + 100;
+	for (k = 0; k < NVEC; k++) {
+	  REALLOCATE (vec[k][0].elements, float, NSTAR);
+	}
+      }
+
+      ConcatMeasures (vec[Nt ], code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], N1, MEAS_TIME); 
+      ConcatMeasures (vec[Nz ], code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], N1, MEAS_AIRMASS); 
+      ConcatMeasures (vec[NT ], code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], N1, MEAS_EXPTIME); 
+      ConcatMeasures (vec[NP ], code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], N1, MEAS_PHOTCODE); 
+      ConcatMeasures (vec[Nd1], code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], N1, MEAS_dMAG); 
+      ConcatMeasures (vec[Nxc], code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], N1, MEAS_XCCD); 
+      ConcatMeasures (vec[Nyc], code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], N1, MEAS_YCCD); 
+      ConcatMeasures (vec[Nxm], code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], N1, MEAS_XMOSAIC); 
+      ConcatMeasures (vec[Nym], code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], N1, MEAS_YMOSAIC); 
+
+      for (j = 0; j < N1; j++, N++) {
+	vec[Nd ][0].elements[N] = M1[j] - M2;
+	vec[Nm1][0].elements[N] = M1[j];
+	vec[Nm2][0].elements[N] = M2;
+	vec[Nd2][0].elements[N] = dM2;
+	vec[Nc ][0].elements[N] = color;
+	vec[Ns ][0].elements[N] = NStar;
+	vec[NR ][0].elements[N] = catalog.average[i].R;
+	vec[ND ][0].elements[N] = catalog.average[i].D;
+      }
+      NStar ++; 
+    skip:
+      if (M1 != NULL) free (M1);
+    }
+    if (catalog.average != (Average *) NULL) free (catalog.average);
+    if (catalog.measure != (Measure *) NULL) free (catalog.measure);
+    if (catalog.secfilt != (SecFilt *) NULL) free (catalog.secfilt);
+    catalog.average = (Average *) NULL; 
+    catalog.secfilt = (SecFilt *) NULL;
+    catalog.measure = (Measure *) NULL;
+  }
+  if (regions != NULL) free (regions);  
+  for (i = 0; i < NVEC; i++) {
+    vec[i][0].Nelements = N;
+  }
+  return (TRUE);
+  
+usage:
+  fprintf (stderr, "USAGE: dmags F - F : measure.param\n");
+  return (FALSE);
+
+ escape:
+  
+  if (regions != NULL) free (regions);  
+  for (i = 0; i < NVEC; i++) {
+    DeleteVector (vec[i]);
+  }
+  free (vec);
+  return (FALSE);
+}
+
+int ConcatMeasures (Vector *vec, PhotCode *code, int mode, Average *average, SecFilt *secfilt, Measure *measure, int Nin, int param) {
+
+  int i, Ns, N;
+  double *value;
+
+  value = ExtractMeasures (code, mode, average, secfilt, measure, &N, param); 
+  if (N != Nin) {
+    fprintf (stderr, "error!\n");
+    return (FALSE);
+  }
+
+  Ns = vec[0].Nelements;
+  for (i = 0; i < N; i++) {
+    vec[0].elements[Ns+i] = value[i];
+  }
+  vec[0].Nelements = Ns + N;
+
+  free (value);
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/dvo/catalog.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/catalog.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/catalog.c	(revision 12606)
@@ -0,0 +1,408 @@
+# include "dvo.h"
+# define NBYTES 160000
+# define BYTES_STAR 23
+# define BLOCK 1000
+# define DNSTARS 1000
+
+# define MAGSCALE 0
+# define NUMSCALE 1
+# define MISSCALE 2
+
+int catlog (int argc, char **argv) {
+  
+  FILE *f;
+  Catalog catalog;
+  Vector Xvec, Yvec, Zvec;
+  int i, N, Nm, Nn, NN, Nbytes, nbytes, Bytes_Star;
+  int Ar, Ad, Am, InRegion, GSC, ASCII, LONEOS, FIXED;
+  char filename[128];
+  double Mz, Mr, Nz, Nr;
+  int clip, mode, IDclip, IDchoice, LimExclude;
+  RegionFile *regions;
+  int j, Nregions;
+  double Radius, Rmin, Rmax;
+  Graphdata graphmode;
+  double epoch, current_epoch;
+  char gscdir[256], catdir[256];
+  int Ngraph;
+
+  Ngraph = 0;
+  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);
+
+  VarConfig ("CATDIR", "%s", catdir);
+  VarConfig ("GSCDIR", "%s", gscdir);
+
+  Mz = 17.0;
+  Mr = -5.0;
+  mode = MAGSCALE;
+  clip = FALSE;
+  Rmin = graphmode.coords.crval1 - 182.0;
+  Rmax = graphmode.coords.crval1 + 182.0;
+
+  regions = (RegionFile *) NULL;
+  f = (FILE *) NULL;
+  Nz = Nr = Am = Ar = Ad = 0;
+  /* either MagScale or NumScale, whichever is first is scale */
+  Nm = get_argument (argc, argv, "-m");
+  Nn = get_argument (argc, argv, "+n");
+  NN = get_argument (argc, argv, "-n");
+  if (NN && Nn) {
+    fprintf (stderr, "can't mix meas and miss scaling\n");
+    return (FALSE);
+  }
+ 
+  if (Nm)
+    mode = MAGSCALE;
+  if (Nn)
+    mode = NUMSCALE;
+  if (NN)
+    mode = MISSCALE;
+    
+  if (Nm && Nn) {
+    clip = TRUE;
+    if (Nm < Nn) 
+      mode = MAGSCALE;
+    else 
+      mode = NUMSCALE;
+  }
+  if (Nm && NN) {
+    clip = TRUE;
+    if (Nm < NN) 
+      mode = MAGSCALE;
+    else 
+      mode = MISSCALE;
+  }
+   
+  current_epoch = 2000.0;
+  epoch = 2000.0;
+  if (N = get_argument (argc, argv, "-e")) {
+    remove_argument (N, &argc, argv);
+    epoch  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  IDclip = FALSE;
+  if (N = get_argument (argc, argv, "-ID")) {
+    remove_argument (N, &argc, argv);
+    IDchoice  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    IDclip = TRUE;
+  }
+
+  LimExclude = FALSE;
+  if (N = get_argument (argc, argv, "-x")) {
+    remove_argument (N, &argc, argv);
+    LimExclude = TRUE;
+  }
+
+  if (Nm = get_argument (argc, argv, "-m")) {
+    remove_argument (Nm, &argc, argv);
+    Mr  = 1000*atof(argv[Nm]);
+    remove_argument (Nm, &argc, argv);
+    Mz = 1000*atof(argv[Nm]);
+    Mr = Mr - Mz;
+    remove_argument (Nm, &argc, argv);
+  }
+
+  if (Nn = get_argument (argc, argv, "+n")) {
+    remove_argument (Nn, &argc, argv);
+    Nz  = atof(argv[Nn]);
+    remove_argument (Nn, &argc, argv);
+    Nr = atof(argv[Nn]) - Nz;
+    remove_argument (Nn, &argc, argv);
+  }
+
+  if (Nn = get_argument (argc, argv, "-n")) {
+    remove_argument (Nn, &argc, argv);
+    Nz  = atof(argv[Nn]);
+    remove_argument (Nn, &argc, argv);
+    Nr = atof(argv[Nn]) - Nz;
+    remove_argument (Nn, &argc, argv);
+  }
+
+  InRegion = FALSE;
+  if (N = get_argument (argc, argv, "-all")) {
+    remove_argument (N, &argc, argv);
+    InRegion = TRUE;
+  }
+
+  ASCII = FALSE;
+  LONEOS = TRUE;
+  GSC = FALSE;
+  FIXED = FALSE;
+  if (N = get_argument (argc, argv, "-g")) {
+    remove_argument (N, &argc, argv);
+    GSC = TRUE;
+    ASCII = FALSE;
+    LONEOS = FALSE;
+  }
+
+  if (N = get_argument (argc, argv, "-a")) {
+    remove_argument (N, &argc, argv);
+    ASCII = TRUE;
+    GSC = FALSE;
+    LONEOS = FALSE;
+    Ar = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    Ad = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    Am = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    if (N = get_argument (argc, argv, "-f")) {
+      remove_argument (N, &argc, argv);
+      FIXED = TRUE;
+      ASCII = FALSE;
+      Bytes_Star = atof(argv[N]);
+      remove_argument (N, &argc, argv);
+    }
+  }
+
+  
+  if ((InRegion || (argc != 2)) && (!InRegion || (argc != 1))) {
+    fprintf (stderr, "USAGE: catalog (filename / -all) [-m M M] [-n N N] [-g] [-a RA DEC MAG] \n");
+    return (FALSE);
+  }
+  
+  if (InRegion) {
+    Radius = MAX (fabs(graphmode.xmax), fabs(graphmode.ymax));
+    regions = find_regions (graphmode.coords.crval1, graphmode.coords.crval2, Radius, &Nregions);
+  } else {
+    Nregions = 1;
+  }
+  
+  for (j = 0; j < Nregions; j++) {
+    catalog.average = 0;
+    
+    /* Load in data from an ASCII file list of ra, dec, mag */
+    if (ASCII) {
+      char *tbuffer;
+      int nstar, NSTARS;
+      double R, D, M;
+      
+      f = fopen (argv[1], "r");
+      if (f == (FILE *) NULL) {
+	fprintf (stderr, "ERROR: can't open catalog file: %s\n", argv[1]);
+	return (FALSE);
+      }
+      
+      nstar = 0;
+      NSTARS = DNSTARS;
+      ALLOCATE (tbuffer, char, 1024);
+      ALLOCATE (catalog.average, Average, NSTARS);
+      while (scan_line (f, tbuffer) != EOF) {
+	dparse (&R, Ar, tbuffer);
+	dparse (&D, Ad, tbuffer);
+	dparse (&M, Am, tbuffer);
+	catalog.average[nstar].R = R;
+	catalog.average[nstar].D = D;
+	catalog.average[nstar].M = M * 1000.0;
+	nstar++;
+	if (nstar == NSTARS - 1) {
+	  NSTARS += DNSTARS;
+	  REALLOCATE (catalog.average, Average, NSTARS);
+	}
+      }
+      fclose (f);
+      free (tbuffer);
+      REALLOCATE (catalog.average, Average, nstar);
+      catalog.Naverage = nstar;
+
+      if (epoch != current_epoch) {
+	cprecess (catalog.average, catalog.Naverage, epoch, current_epoch);
+      }
+
+    }
+    
+    /* Load in data from an ASCII file list of ra, dec, mag */
+    if (FIXED) {
+      char *tbuffer;
+      int nstar, NSTARS;
+      double R, D, M;
+      
+      f = fopen (argv[1], "r");
+      if (f == (FILE *) NULL) {
+	fprintf (stderr, "ERROR: can't open catalog file: %s\n", argv[1]);
+	return (FALSE);
+      }
+      
+      nstar = 0;
+      NSTARS = DNSTARS;
+      ALLOCATE (tbuffer, char, (BLOCK*Bytes_Star));
+      ALLOCATE (catalog.average, Average, NSTARS);
+      Nbytes = BLOCK*Bytes_Star;
+      while ((nbytes = fread (tbuffer, 1, Nbytes, f)) > 0) {
+	for (i = 0; i < nbytes / Bytes_Star; i++) {
+	  dparse (&R, Ar, &tbuffer[i*Bytes_Star]);
+	  dparse (&D, Ad, &tbuffer[i*Bytes_Star]);
+	  dparse (&M, Am, &tbuffer[i*Bytes_Star]);
+	  catalog.average[nstar].R = R;
+	  catalog.average[nstar].D = D;
+	  catalog.average[nstar].M = M * 1000.0;
+	  nstar++;
+	  if (nstar == NSTARS - 1) {
+	    NSTARS += DNSTARS;
+	    REALLOCATE (catalog.average, Average, NSTARS);
+	  }
+	}
+      }
+      fclose (f);
+      free (tbuffer);
+      REALLOCATE (catalog.average, Average, nstar);
+      catalog.Naverage = nstar;
+
+      if (epoch != current_epoch) {
+	cprecess (catalog.average, catalog.Naverage, epoch, current_epoch);
+      }
+
+    }
+    
+    /* load data from the GSC files */
+    if (GSC) {
+      char *tbuffer;
+      int nstar, NSTARS;
+      double R, D, M;
+      
+      if (InRegion) {
+	sprintf (filename, "%s/%s", gscdir, regions[j].name);
+      } else {
+	sprintf (filename, "%s/%s", gscdir, argv[1]);
+      }
+      
+      f = fopen (filename, "r");
+      if (f == (FILE *) NULL) {
+	fprintf (stderr, "no stars in %s, skipping\n", filename);
+	continue;
+	/* return (FALSE); */
+      }
+      
+      nstar = 0;
+      NSTARS = DNSTARS;
+      ALLOCATE (tbuffer, char, (BLOCK*BYTES_STAR));
+      ALLOCATE (catalog.average, Average, NSTARS);
+      Nbytes = BLOCK*BYTES_STAR;
+      while ((nbytes = fread (tbuffer, 1, Nbytes, f)) > 0) {
+	for (i = 0; i < nbytes / BYTES_STAR; i++) {
+	  dparse (&R, 1, &tbuffer[i*BYTES_STAR]);
+	  dparse (&D, 2, &tbuffer[i*BYTES_STAR]);
+	  dparse (&M, 3, &tbuffer[i*BYTES_STAR]);
+	  catalog.average[nstar].R = R;
+	  catalog.average[nstar].D = D;
+	  catalog.average[nstar].M = M * 1000.0;
+	  nstar++;
+	  if (nstar == NSTARS - 1) {
+	    NSTARS += DNSTARS;
+	    REALLOCATE (catalog.average, Average, NSTARS);
+	  }
+	}
+      }
+      fclose (f);
+      free (tbuffer);
+      REALLOCATE (catalog.average, Average, nstar);
+      catalog.Naverage = nstar;
+    }
+  
+    /* load data from the photometry database files */
+    if (LONEOS) {
+      
+      if (InRegion) {
+	sprintf (filename, "%s/%s", catdir, regions[j].name);
+      } else {
+	sprintf (filename, "%s/%s", catdir, argv[1]);
+      }
+      
+      /* lock, load, unlock catalog */
+      catalog.filename = filename;
+      switch (lock_catalog (&catalog, LCK_SOFT)) {
+      case 2:
+	unlock_catalog (&catalog);
+      case 0:
+	continue;
+      }
+      if (!load_catalog (&catalog, LOAD_AVES, TRUE)) {
+	unlock_catalog (&catalog);
+	continue;
+      }
+      unlock_catalog (&catalog);
+    }
+    
+    /* data has been loaded, get ready to plot it */
+    Xvec.Nelements = catalog.Naverage;
+    Yvec.Nelements = catalog.Naverage;
+    Zvec.Nelements = catalog.Naverage;
+    ALLOCATE (Xvec.elements, float, Xvec.Nelements);
+    ALLOCATE (Yvec.elements, float, Yvec.Nelements);
+    ALLOCATE (Zvec.elements, float, Zvec.Nelements);
+    /* project stars to screen display coords */
+    Xvec.Nelements = 0;
+    switch (mode) {
+    case (MAGSCALE):
+      for (N = i = 0; i < catalog.Naverage; i++) {
+	if (clip && ((catalog.average[i].Nm < Nz) || (catalog.average[i].Nm > Nr+Nz))) 
+	  continue;
+	if (IDclip && (catalog.average[i].code != IDchoice))
+	  continue;
+	Zvec.elements[N] = MIN (1.0, MAX (0.01, (catalog.average[i].M - Mz) / Mr));
+	if (LimExclude && (Zvec.elements[N] > 0.99)) continue;
+	if (Zvec.elements[N] < 0.011) continue;
+	while (catalog.average[i].R < Rmin) catalog.average[i].R += 360.0;
+	while (catalog.average[i].R > Rmax) catalog.average[i].R -= 360.0;
+	if (fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], catalog.average[i].R, catalog.average[i].D, &graphmode.coords)) N ++;
+      }
+      break;
+    case (NUMSCALE):
+      for (N = i = 0; i < catalog.Naverage; i++) {
+	if (clip && ((catalog.average[i].M > Mz) || (catalog.average[i].M < Mr+Mz))) 
+	  continue;
+	if (IDclip && (catalog.average[i].code != IDchoice))
+	  continue;
+	Zvec.elements[N] = MIN (1.0, MAX (0.01, (catalog.average[i].Nm - Nz) / Nr));
+	if (LimExclude && (Zvec.elements[N] == 1.0)) continue;
+	if (Zvec.elements[N] == 0.01) 
+	  continue;
+	while (catalog.average[i].R < Rmin) catalog.average[i].R += 360.0;
+	while (catalog.average[i].R > Rmax) catalog.average[i].R -= 360.0;
+	if (fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], catalog.average[i].R, catalog.average[i].D, &graphmode.coords)) N++;
+      }
+      break;
+    case (MISSCALE):
+      for (N = i = 0; i < catalog.Naverage; i++) {
+	if (clip && ((catalog.average[i].M > Mz) || (catalog.average[i].M < Mr+Mz))) 
+	  continue;
+	if (IDclip && (catalog.average[i].code != IDchoice))
+	  continue;
+	Zvec.elements[N] = MIN (1.0, MAX (0.01, (catalog.average[i].Nn - Nz) / Nr));
+	if (LimExclude && (Zvec.elements[N] == 1.0)) continue;
+	if (Zvec.elements[N] == 0.01) 
+	  continue;
+	while (catalog.average[i].R < Rmin) catalog.average[i].R += 360.0;
+	while (catalog.average[i].R > Rmax) catalog.average[i].R -= 360.0;
+	if (fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], catalog.average[i].R, catalog.average[i].D, &graphmode.coords)) N++;
+      }
+      break;
+    }
+
+    Zvec.Nelements = Yvec.Nelements = Xvec.Nelements = N;
+    REALLOCATE (Xvec.elements, float, MAX (Xvec.Nelements, 1));
+    REALLOCATE (Yvec.elements, float, MAX (Yvec.Nelements, 1));
+    REALLOCATE (Zvec.elements, float, MAX (Zvec.Nelements, 1));
+    
+    graphmode.style = 2; /* set style to points */
+    graphmode.size = -1; /* point size determined by Zvec */
+    graphmode.etype = 0; /* no errorbars */
+    PrepPlotting (N, &graphmode);
+    
+    PlotVector (N, Xvec.elements);
+    PlotVector (N, Yvec.elements);
+    PlotVector (N, Zvec.elements);
+    
+    free (Xvec.elements);
+    free (Yvec.elements);
+    free (Zvec.elements);
+
+    if (catalog.average != 0) free (catalog.average);
+
+  }
+  return (TRUE);
+
+}
+  
Index: /tags/start/Ohana/src/opihi/dvo/ccd.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/ccd.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/ccd.c	(revision 12606)
@@ -0,0 +1,125 @@
+# include "dvo.h"
+
+int ccd (int argc, char **argv) {
+  
+  Catalog catalog;
+  Graphdata graphsky;
+  RegionFile *regions;
+  PhotCode *code[4];
+  Vector *xvec, *yvec;
+
+  char filename[256], catdir[256];
+  double Radius;
+  double *M1, *M2;
+  int i, m, k, Npts, NPTS;
+  int N1, N2, i1, i2, mode[4];
+  int Ngraph, Nsec, Nregions, UseAverages;
+
+  /* defaults */
+  regions = NULL;
+  catalog.average = NULL; 
+  catalog.secfilt = NULL;
+  catalog.measure = NULL;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsec = GetPhotcodeNsecfilt ();
+
+  /* load data about plot windows */
+  Ngraph = 0;
+  if (!GetGraphData (&graphsky, NULL, &Ngraph)) return (FALSE);
+ 
+  /* find CATDIR in config system */
+  VarConfig ("CATDIR", "%s", catdir);
+
+  /* interpret command-line options */
+  if (!SetPhotSelections (&argc, argv)) goto usage;
+  if (argc != 8) goto usage;
+  if (strcmp (argv[2], "-")) goto usage;
+  if (strcmp (argv[4], ":")) goto usage;
+  if (strcmp (argv[6], "-")) goto usage;
+
+  /* interpret command-line options */
+  if (!GetPhotcodeInfo (argv[1], &code[0], &mode[0])) return (FALSE);
+  if (!GetPhotcodeInfo (argv[3], &code[1], &mode[1])) return (FALSE);
+  if (!GetPhotcodeInfo (argv[5], &code[2], &mode[2])) return (FALSE);
+  if (!GetPhotcodeInfo (argv[7], &code[3], &mode[3])) return (FALSE);
+  if ((mode[2] == MAG_AVE) || (mode[2] == MAG_REF)) UseAverages = TRUE;
+
+  /* find catalog files which overlap this region */
+  Radius = MAX (fabs(graphsky.xmax), fabs(graphsky.ymax));
+  regions = find_regions (graphsky.coords.crval1, graphsky.coords.crval2, Radius, &Nregions);
+
+  /* init vectors to save data */
+  Npts = 0;
+  NPTS = 1;
+  if ((xvec = SelectVector ("xv", ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((yvec = SelectVector ("yv", ANYVECTOR, TRUE)) == NULL) goto escape;
+
+  /* loop over regions, extract data for each region */
+  for (k = 0; k < Nregions; k++) {
+    /* lock, load, unlock catalog */
+    sprintf (filename, "%s/%s", catdir, regions[k].name);
+    catalog.filename = filename;
+    switch (lock_catalog (&catalog, LCK_SOFT)) {
+      case 2:
+	unlock_catalog (&catalog);
+      case 0:
+	continue;
+    }
+    if (!load_catalog (&catalog, LOAD_AVES | LOAD_MEAS | LOAD_SECF, FALSE)) {
+      unlock_catalog (&catalog);
+      continue;
+    }
+    unlock_catalog (&catalog);
+
+    /* get correct mags, convert to X,Y */
+    for (i = 0; i < catalog.Naverage; i++) {
+      M1 = M2 = NULL;
+      m = catalog.average[i].offset;
+
+      M1 = ExtractDMag (&code[0], &mode[0], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], &N1);
+      if (N1 == 0) goto skip;
+
+      M2 = ExtractDMag (&code[2], &mode[2], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], &N2);
+      if (N2 == 0) goto skip;
+
+      for (i1 = 0; i1 < N1; i1++) {
+	for (i2 = 0; i2 < N2; i2++) {
+	  xvec[0].elements[Npts] = M1[i1];
+	  yvec[0].elements[Npts] = M2[i2];
+	  Npts++;
+	  if (Npts == NPTS) {
+	    NPTS += 2000;
+	    REALLOCATE (xvec[0].elements, float, NPTS);
+	    REALLOCATE (yvec[0].elements, float, NPTS);
+	  }
+	}
+      }
+    skip:
+      if (M1 != NULL) free (M1);
+      if (M2 != NULL) free (M2);
+    }
+    if (catalog.average != NULL) free (catalog.average);
+    if (catalog.secfilt != NULL) free (catalog.secfilt);
+    if (catalog.measure != NULL) free (catalog.measure);
+    catalog.average = (Average *) NULL; 
+    catalog.secfilt = (SecFilt *) NULL;
+    catalog.measure = (Measure *) NULL;
+  }
+  if (regions != NULL) free (regions);
+  xvec[0].Nelements = yvec[0].Nelements = Npts;
+  return (TRUE);
+
+usage:
+  fprintf (stderr, "USAGE: ccd F - F : measure.param\n");
+  return (FALSE);
+
+escape:
+  if (regions != NULL) free (regions);
+  if (catalog.average != NULL) free (catalog.average);
+  if (catalog.secfilt != NULL) free (catalog.secfilt);
+  if (catalog.measure != NULL) free (catalog.measure);
+  return (FALSE);
+}
+
Index: /tags/start/Ohana/src/opihi/dvo/cmatch.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/cmatch.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/cmatch.c	(revision 12606)
@@ -0,0 +1,115 @@
+# include "dvo.h"
+# define BYTES_STAR 23
+# define BLOCK 1000
+# define DNSTARS 1000
+
+int cmatch (int argc, char **argv) {
+  
+  FILE *f;
+  Catalog catalog1, catalog2;
+  int i, Nbytes, nbytes, Nitems, nitems;
+  char *tbuffer, filename[128];
+  int nstar, NSTARS;
+  double R, D, M, radius;
+  char catdir[256], gscdir[256];
+  Vector *rvec, *dvec, *mvec, *drvec, *ddvec, *dmvec;
+
+  VarConfig ("CATDIR", "%s", catdir);
+  VarConfig ("GSCDIR", "%s", gscdir);
+      
+  if (argc != 9) {
+    fprintf (stderr, "USAGE: cmatch file radius (RA) (DEC) (Mag) (dRA) (dDEC) (dMag)\n");
+    return (FALSE);
+  }
+
+  radius = atof (argv[2]);
+
+  if ((rvec  = SelectVector (argv[3], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((dvec  = SelectVector (argv[4], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((mvec  = SelectVector (argv[5], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((drvec = SelectVector (argv[6], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((ddvec = SelectVector (argv[7], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((dmvec = SelectVector (argv[8], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  /* load data from the photometry database file */
+  sprintf (filename, "%s/%s", catdir, argv[1]);
+  if (!fits_read_header (filename, &catalog1.header)) {
+    fprintf (stderr, "no stars in %s\n", filename);
+    return (FALSE);
+  }
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "no stars in %s\n", filename);
+    return (FALSE);
+  }
+  fseek (f, catalog1.header.size, SEEK_SET); 
+  
+  /** find number of stars, measurements **/
+  catalog1.Naverage = 0;
+  fits_scan (&catalog1.header, "NSTARS", "%d", 1, &catalog1.Naverage);
+  if (catalog1.Naverage == 0) {
+    fprintf (stderr, "no stars in catalog %s\n", filename);
+    fclose (f);
+    return (TRUE);
+  }
+  ALLOCATE (catalog1.average, Average, catalog1.Naverage);
+  Nitems = catalog1.Naverage;
+  nitems = Fread (catalog1.average, sizeof(Average), Nitems, f, "average");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to read data from catalog file %s (1)\n", filename);
+    fclose (f);
+    free (catalog1.average);
+    return (FALSE);
+  }
+  fclose (f);
+  fprintf (stderr, "read %d stars from phot catalog file %s\n", catalog1.Naverage, filename);
+
+  /* load data from the GSC file */
+  sprintf (filename, "%s/%s", gscdir, argv[1]);
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "no stars in %s\n", filename);
+    free (catalog1.average);
+    return (FALSE);
+    /* return (FALSE); */
+  }
+  
+  nstar = 0;
+  NSTARS = DNSTARS;
+  ALLOCATE (tbuffer, char, (BLOCK*BYTES_STAR));
+  ALLOCATE (catalog2.average, Average, NSTARS);
+  Nbytes = BLOCK*BYTES_STAR;
+  while ((nbytes = fread (tbuffer, 1, Nbytes, f)) > 0) {
+    for (i = 0; i < nbytes / BYTES_STAR; i++) {
+      dparse (&R, 1, &tbuffer[i*BYTES_STAR]);
+      dparse (&D, 2, &tbuffer[i*BYTES_STAR]);
+      dparse (&M, 3, &tbuffer[i*BYTES_STAR]);
+      catalog2.average[nstar].R = R;
+      catalog2.average[nstar].D = D;
+      catalog2.average[nstar].M = M * 1000.0;
+      nstar++;
+      if (nstar == NSTARS - 1) {
+	NSTARS += DNSTARS;
+	REALLOCATE (catalog2.average, Average, NSTARS);
+      }
+    }
+  }
+  free (tbuffer);
+  REALLOCATE (catalog2.average, Average, MAX (nstar, 1));
+  catalog2.Naverage = nstar;
+  fclose (f);
+
+  /* sort data in order of RA */
+  sortave (catalog1.average, catalog1.Naverage);
+  sortave (catalog2.average, catalog2.Naverage);
+
+  /* data has been loaded, use gcompare algorithm to match */
+  compare (&catalog1, &catalog2, rvec, dvec, mvec, drvec, ddvec, dmvec, radius);
+
+  free (catalog1.average);
+  free (catalog2.average);
+
+  return (TRUE);
+
+}
+  
Index: /tags/start/Ohana/src/opihi/dvo/cmd.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/cmd.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/cmd.c	(revision 12606)
@@ -0,0 +1,121 @@
+# include "dvo.h"
+
+int cmd (int argc, char **argv) { /* really need to think about upper limits & how to represent them */
+  
+  Catalog catalog;
+  Graphdata graphsky;
+  RegionFile *regions;
+  PhotCode *code[3];
+  Vector *xvec, *yvec;
+
+  char filename[256], catdir[256];
+  double Radius, *M1, *M3;
+  int i, j, m, i1, i3, N1, N3;
+  int Npts, NPTS, mode[3];
+  int Ngraph, Nsec, Nregions;
+
+  /* defaults */
+  regions = NULL;
+  catalog.average = NULL; 
+  catalog.secfilt = NULL;
+  catalog.measure = NULL;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsec = GetPhotcodeNsecfilt ();
+
+  /* load data about plot windows */
+  Ngraph = 0;
+  if (!GetGraphData (&graphsky, NULL, &Ngraph)) return (FALSE);
+ 
+  /* find CATDIR in config system */
+  VarConfig ("CATDIR", "%s", catdir);
+
+  /* interpret command-line options */
+  if (!SetPhotSelections (&argc, argv)) goto usage;
+  if (argc != 6) { goto usage; }
+  if (strcmp (argv[2], "-")) goto usage;
+  if (strcmp (argv[4], ":")) goto usage;
+
+  /* interpret command-line options */
+  if (!GetPhotcodeInfo (argv[1], &code[0], &mode[0])) return (FALSE);
+  if (!GetPhotcodeInfo (argv[3], &code[1], &mode[1])) return (FALSE);
+  if (!GetPhotcodeInfo (argv[5], &code[2], &mode[2])) return (FALSE);
+
+  /* find catalog files which overlap this region */
+  Radius = MAX (fabs(graphsky.xmax), fabs(graphsky.ymax));
+  regions = find_regions (graphsky.coords.crval1, graphsky.coords.crval2, Radius, &Nregions);
+
+  /* init vectors to save data */
+  Npts = 0;
+  NPTS = 1;
+  if ((xvec = SelectVector ("xv", ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((yvec = SelectVector ("yv", ANYVECTOR, TRUE)) == NULL) goto escape;
+
+  /* loop over regions, extract data for each region */
+  for (j = 0; j < Nregions; j++) {
+    /* lock, load, unlock catalog */
+    sprintf (filename, "%s/%s", catdir, regions[j].name);
+    catalog.filename = filename;
+    switch (lock_catalog (&catalog, LCK_SOFT)) {
+    case 2:
+      unlock_catalog (&catalog);
+    case 0:
+      continue;
+    }
+    if (!load_catalog (&catalog, LOAD_AVES | LOAD_MEAS | LOAD_SECF, FALSE)) {
+      unlock_catalog (&catalog);
+      continue;
+    }
+    unlock_catalog (&catalog);
+    
+    /* get correct mags, convert to X,Y */
+    for (i = 0; i < catalog.Naverage; i++) {
+      M1 = M3 = NULL;
+      m = catalog.average[i].offset;
+
+      M1 = ExtractDMag (code, mode, &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], &N1);
+      if (N1 == 0) goto skip;
+
+      M3 = ExtractMagnitudes (code[2], mode[2], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], &N3);
+      if (N3 == 0) goto skip;
+
+      for (i1 = 0; i1 < N1; i1++) {
+	for (i3 = 0; i3 < N3; i3++) {
+	  xvec[0].elements[Npts] = M1[i1];
+	  yvec[0].elements[Npts] = M3[i3];
+	  Npts++;
+	  if (Npts == NPTS) {
+	    NPTS += 2000;
+	    REALLOCATE (xvec[0].elements, float, NPTS);
+	    REALLOCATE (yvec[0].elements, float, NPTS);
+	  }
+	}
+      }
+    skip:
+      if (M1 != NULL) free (M1);
+      if (M3 != NULL) free (M3);
+    }
+    if (catalog.average != NULL) free (catalog.average);
+    if (catalog.secfilt != NULL) free (catalog.secfilt);
+    if (catalog.measure != NULL) free (catalog.measure);
+    catalog.average = (Average *) NULL; 
+    catalog.secfilt = (SecFilt *) NULL;
+    catalog.measure = (Measure *) NULL;
+  }
+  if (regions != NULL) free (regions);
+  xvec[0].Nelements = yvec[0].Nelements = Npts;
+  return (TRUE);
+
+usage:
+  fprintf (stderr, "USAGE: cmd F - F : F\n");
+  return (FALSE);
+
+escape:
+  if (regions != NULL) free (regions);
+  if (catalog.average != NULL) free (catalog.average);
+  if (catalog.secfilt != NULL) free (catalog.secfilt);
+  if (catalog.measure != NULL) free (catalog.measure);
+  return (FALSE);
+}
+    
Index: /tags/start/Ohana/src/opihi/dvo/cmpload.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/cmpload.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/cmpload.c	(revision 12606)
@@ -0,0 +1,162 @@
+# include "dvo.h"
+# define D_NSTARS 1000
+# define BYTES_STAR 66
+# define BLOCK 1000
+
+int cmpload (int argc, char **argv) {
+  
+  int i, nstar, N, Nin, Nout, Nextra, n, Type, type;
+  int doneread, done, Nskip, Nbytes, nbytes, Ninstar;
+  char *c, *c2;
+  double *X, *Y, *M;
+  double dtmp;
+  FILE *f;
+  char *buffer, *buffer2, *line;
+  Header header;
+  int Ximage, Nimage;
+  
+  Nimage = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Nimage = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (&Ximage, &Nimage)) return (FALSE);
+
+  Type = 0;
+  if (N = get_argument (argc, argv, "-t")) {
+    remove_argument (N, &argc, argv);
+    Type = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: load (overlay) <filename>\n");
+    return (FALSE);
+  }
+
+  if (!SelectOverlay (argv[1], &n)) 
+    return (FALSE);
+
+  if (!fits_read_header (argv[2], &header)) {
+    fprintf (stderr, "ERROR: can't read header for %s\n", argv[2]);
+    return (FALSE);
+  }
+
+  /* find expected number of stars */
+  fits_scan (&header, "NSTARS", "%d", 1, &nstar);
+  if (nstar == 0) {
+    fprintf (stderr, "ERROR: can't get NSTARS from header\n");
+    fits_free_header (&header);
+    return (FALSE);
+  }
+
+  f = fopen (argv[2], "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't read data from %s\n", argv[2]);
+    fits_free_header (&header);
+    return (FALSE);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  ALLOCATE (X, double, nstar);
+  ALLOCATE (Y, double, nstar);
+  ALLOCATE (M, double, nstar);
+
+  /* load in stars by blocks of 1000 */
+  Nin = 0;
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR) + 1);
+  buffer[BLOCK*BYTES_STAR] = 0;
+  Nextra = 0;
+  doneread = FALSE;
+  while (!doneread) {
+    Nbytes = BYTES_STAR * BLOCK - Nextra;
+    nbytes = fread (&buffer[Nextra], 1, Nbytes, f);
+    if (nbytes == 0) {
+      doneread = TRUE;
+      continue;
+    }
+    nbytes += Nextra;
+    /* check line-by-line integrity */
+    c = buffer;
+    done = FALSE;
+    while ((c < buffer + nbytes) && (!done)) { 
+      for (c2 = c; *c2 == '\n'; c2++);
+      if (c2 > c) { /* extra return chars */
+	memmove (c, c2, (int)(buffer + nbytes - c2));
+	Nskip = c2 - c;
+	nbytes -= Nskip;
+	bzero (buffer + nbytes, Nskip);
+      }
+      c2 = strchr (c, '\n');
+      if (c2 == (char *) NULL) {
+	done = TRUE;	
+	continue;
+      }
+      c2++;
+      if ((c2 - c) != BYTES_STAR) { /* bad line, delete it */
+	memmove (c, c2, (int)(buffer + nbytes - c2));
+	Nskip = c2 - c;
+	nbytes -= Nskip;
+	bzero (buffer + nbytes, Nskip);
+      } else {
+	c = c2;
+      }
+    }
+    Ninstar = nbytes / BYTES_STAR;
+    Nextra = nbytes % BYTES_STAR;
+    for (i = 0; i < Ninstar; i++, Nin++) {
+      dparse (&X[Nin],  1, &buffer[i*BYTES_STAR]);
+      dparse (&Y[Nin],  2, &buffer[i*BYTES_STAR]);
+      dparse (&M[Nin],  3, &buffer[i*BYTES_STAR]);
+      if (Type) {
+	dparse (&dtmp, 5, &buffer[i*BYTES_STAR]);
+	type = dtmp;
+	if (type != Type) {
+	  Nin --;
+	}
+      }
+    }
+  }
+  fclose (f);
+
+  ALLOCATE (line, char, 129);
+  write (Ximage, "LOAD", 4); /* force Ximage to look for the incoming image */
+  sprintf (line, "OVER %9d ", n);
+  write (Ximage, line, 16);
+  
+  ALLOCATE (buffer2, char, 66000);
+  bzero (buffer2, 65536);
+  for (Nout = i = 0; i < Nin; i++, Nout++) {
+    sprintf (&buffer2[Nout*128], "%15s %20.10f %20.10f %20.10f %20.10f ", "BOX", X[i], Y[i], 5.0, 5.0);
+    if (Nout == 512) {
+      sprintf (line, "NLINES  %7d ", Nout);
+      write (Ximage, line, 16);
+      write (Ximage, buffer2, Nout*128);
+      bzero (buffer2, 65536);
+      Nout = -1;
+    }
+  }
+
+  if (Nout) {
+    sprintf (line, "NLINES  %7d ", Nout);
+    write (Ximage, line, 16);
+    write (Ximage, buffer2, Nout*128);
+  }
+  sprintf (line, "DONE ");
+  write (Ximage, line, 16);
+
+  fits_free_header (&header);
+  free (X);
+  free (Y);
+  free (M);
+  free (buffer);
+  /*  */
+
+  free (buffer2);
+  free (line);
+
+  fprintf (stderr, "loaded %d objects\n", Nin);
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/dvo/cmpread.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/cmpread.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/cmpread.c	(revision 12606)
@@ -0,0 +1,148 @@
+# include "dvo.h"
+# define D_NSTARS 1000
+# define BYTES_STAR 66
+# define BLOCK 1000
+
+int cmpread (int argc, char **argv) {
+  
+  int i, nstar, Nin, Nextra;
+  int doneread, done, Nskip, Nbytes, nbytes, Ninstar, RAnDEC;
+  char *c, *c2, *name, *file;
+  float *R, *D, *V;
+  double tR, tD, tmp, X, Y;
+  FILE *f;
+  char *buffer;
+  int Nfield, Nra, Ndec;
+  Vector *rvec, *dvec, *vec;
+  Header header;
+  Coords coords;
+
+  if ((argc != 4) && (argc != 6)) {
+    fprintf (stderr, "USAGE: cmpread name Nfield <filename>\n");
+    fprintf (stderr, "USAGE: cmpread ra N dec N <filename>\n");
+    return (FALSE);
+  }
+
+  if (argc == 4) {
+    name = strcreate (argv[1]);
+    Nfield = atof (argv[2]);
+    file = strcreate (argv[3]);
+    RAnDEC = FALSE;
+  } else {
+    Nra  = atof (argv[2]);
+    Ndec = atof (argv[4]);
+    file = strcreate (argv[5]);
+    RAnDEC = TRUE;
+  }    
+
+  if (!fits_read_header (file, &header)) {
+    fprintf (stderr, "ERROR: can't read header for %s\n", file);
+    free (file);
+    if (!RAnDEC) free (name);
+    return (FALSE);
+  }
+
+  /* find expected number of stars */
+  fits_scan (&header, "NSTARS", "%d", 1, &nstar);
+  if (nstar == 0) {
+    fprintf (stderr, "ERROR: can't get NSTARS from header\n");
+    free (file);
+    if (!RAnDEC) free (name);
+    fits_free_header (&header);
+    return (FALSE);
+  }
+
+  f = fopen (file, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't read data from %s\n", file);
+    free (file);
+    if (!RAnDEC) free (name);
+    fits_free_header (&header);
+    return (FALSE);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  if (RAnDEC) {
+    if ((rvec = SelectVector ("ra",  ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    if ((dvec = SelectVector ("dec",  ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    REALLOCATE (rvec[0].elements, float, nstar);
+    REALLOCATE (dvec[0].elements, float, nstar);
+    R = rvec[0].elements;
+    D = dvec[0].elements;
+    rvec[0].Nelements = dvec[0].Nelements = nstar;
+    if (!GetCoords (&coords, &header)) {
+      fprintf (stderr, "can't get WCS info from header\n");
+      return (FALSE);
+    }
+  } else {
+    if ((vec = SelectVector (name, ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    REALLOCATE (vec[0].elements, float, nstar);
+    V = vec[0].elements;
+    vec[0].Nelements = nstar;
+  }
+
+  /* load in stars by blocks of 1000 */
+  Nin = 0;
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR) + 1);
+  buffer[BLOCK*BYTES_STAR] = 0;
+  Nextra = 0;
+  doneread = FALSE;
+  while (!doneread) {
+    Nbytes = BYTES_STAR * BLOCK - Nextra;
+    nbytes = fread (&buffer[Nextra], 1, Nbytes, f);
+    if (nbytes == 0) {
+      doneread = TRUE;
+      continue;
+    }
+    nbytes += Nextra;
+    /* check line-by-line integrity */
+    c = buffer;
+    done = FALSE;
+    while ((c < buffer + nbytes) && (!done)) { 
+      for (c2 = c; *c2 == '\n'; c2++);
+      if (c2 > c) { /* extra return chars */
+	memmove (c, c2, (int)(buffer + nbytes - c2));
+	Nskip = c2 - c;
+	nbytes -= Nskip;
+	bzero (buffer + nbytes, Nskip);
+      }
+      c2 = strchr (c, '\n');
+      if (c2 == (char *) NULL) {
+	done = TRUE;	
+	continue;
+      }
+      c2++;
+      if ((c2 - c) != BYTES_STAR) { /* bad line, delete it */
+	memmove (c, c2, (int)(buffer + nbytes - c2));
+	Nskip = c2 - c;
+	nbytes -= Nskip;
+	bzero (buffer + nbytes, Nskip);
+      } else {
+	c = c2;
+      }
+    }
+    Ninstar = nbytes / BYTES_STAR;
+    Nextra = nbytes % BYTES_STAR;
+    for (i = 0; i < Ninstar; i++, Nin++) {
+      if (RAnDEC) {
+	dparse (&X, Nra,  &buffer[i*BYTES_STAR]);
+	dparse (&Y, Ndec, &buffer[i*BYTES_STAR]);
+	XY_to_RD (&tR, &tD, X, Y, &coords);
+	R[Nin] = tR; D[Nin] = tD;
+      } else {
+	dparse (&tmp, Nfield, &buffer[i*BYTES_STAR]);
+	V[Nin] = tmp;
+      }
+    }
+  }
+  fclose (f);
+
+  fits_free_header (&header);
+  free (buffer);
+  free (file);
+  if (!RAnDEC) free (name);
+
+  fprintf (stderr, "loaded %d objects\n", Nin);
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/dvo/compare.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/compare.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/compare.c	(revision 12606)
@@ -0,0 +1,76 @@
+# include "dvo.h"
+# define D_NMATCH 500;
+
+void compare (Catalog *catlog1, Catalog *catlog2, 
+	 Vector *rvec,  Vector *dvec,  Vector *mvec, Vector *drvec, Vector *ddvec, Vector *dmvec, double radius) {
+
+  int i, j, first_j, Nmatch, NMATCH;
+  double dX, dY, dR;
+
+  Nmatch = 0;
+  NMATCH = D_NMATCH;
+  REALLOCATE (rvec[0].elements, float, NMATCH);
+  REALLOCATE (dvec[0].elements, float, NMATCH);
+  REALLOCATE (mvec[0].elements, float, NMATCH);
+  REALLOCATE (drvec[0].elements, float, NMATCH);
+  REALLOCATE (ddvec[0].elements, float, NMATCH);
+  REALLOCATE (dmvec[0].elements, float, NMATCH);
+
+  for (i = j = 0; (i < catlog1[0].Naverage) && (j < catlog2[0].Naverage);) {
+    
+    dX = catlog1[0].average[i].R - catlog2[0].average[j].R;
+
+    if (!(i % 100))
+      fprintf (stderr, ".");
+    
+    if (dX <= -radius)
+      i++;
+    if (dX >= radius)
+      j++;
+
+    if (fabs (dX) < radius) {
+      first_j = j;
+      for (j = first_j; (fabs (dX) < radius) && (j < catlog2[0].Naverage); j++) {
+	dX = catlog1[0].average[i].R - catlog2[0].average[j].R;
+	dY = catlog1[0].average[i].D - catlog2[0].average[j].D;
+	dR = hypot (dX, dY);
+	if (dR < radius) {
+	   rvec[0].elements[Nmatch] = catlog1[0].average[i].R;
+	   dvec[0].elements[Nmatch] = catlog1[0].average[i].D;
+	   mvec[0].elements[Nmatch] = catlog1[0].average[i].M;
+	  drvec[0].elements[Nmatch] = dX;
+	  ddvec[0].elements[Nmatch] = dY;
+	  dmvec[0].elements[Nmatch] = catlog1[0].average[i].M - catlog2[0].average[j].M;
+	  Nmatch ++;
+	  if (Nmatch == NMATCH - 1) {
+	    NMATCH += D_NMATCH;
+	    REALLOCATE ( rvec[0].elements, float, NMATCH);
+	    REALLOCATE ( dvec[0].elements, float, NMATCH);
+	    REALLOCATE ( mvec[0].elements, float, NMATCH);
+	    REALLOCATE (drvec[0].elements, float, NMATCH);
+	    REALLOCATE (ddvec[0].elements, float, NMATCH);
+	    REALLOCATE (dmvec[0].elements, float, NMATCH);
+	  }
+	}
+      }
+      j = first_j;
+      i++;
+    }
+  }
+
+  REALLOCATE ( rvec[0].elements, float, Nmatch);
+  REALLOCATE ( dvec[0].elements, float, Nmatch);
+  REALLOCATE ( mvec[0].elements, float, Nmatch);
+  REALLOCATE (drvec[0].elements, float, Nmatch);
+  REALLOCATE (ddvec[0].elements, float, Nmatch);
+  REALLOCATE (dmvec[0].elements, float, Nmatch);
+  
+   rvec[0].Nelements = Nmatch;
+   dvec[0].Nelements = Nmatch;
+   mvec[0].Nelements = Nmatch;
+  drvec[0].Nelements = Nmatch;
+  ddvec[0].Nelements = Nmatch;
+  dmvec[0].Nelements = Nmatch;
+
+}
+
Index: /tags/start/Ohana/src/opihi/dvo/ddmags.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/ddmags.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/ddmags.c	(revision 12606)
@@ -0,0 +1,125 @@
+# include "dvo.h"
+
+int ddmags (int argc, char **argv) {
+  
+  Catalog catalog;
+  Graphdata graphsky;
+  RegionFile *regions;
+  PhotCode *code[4];
+  Vector *xvec, *yvec;
+
+  char filename[256], catdir[256];
+  double Radius;
+  double *M1, *M2;
+  int i, m, k, Npts, NPTS;
+  int N1, N2, i1, i2, mode[4];
+  int Ngraph, Nsec, Nregions, UseAverages;
+
+  /* defaults */
+  regions = NULL;
+  catalog.average = NULL; 
+  catalog.secfilt = NULL;
+  catalog.measure = NULL;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsec = GetPhotcodeNsecfilt ();
+
+  /* load data about plot windows */
+  Ngraph = 0;
+  if (!GetGraphData (&graphsky, NULL, &Ngraph)) return (FALSE);
+ 
+  /* find CATDIR in config system */
+  VarConfig ("CATDIR", "%s", catdir);
+
+  /* interpret command-line options */
+  if (!SetPhotSelections (&argc, argv)) goto usage;
+  if (argc != 8) goto usage;
+  if (strcmp (argv[2], "-")) goto usage;
+  if (strcmp (argv[4], ":")) goto usage;
+  if (strcmp (argv[6], "-")) goto usage;
+
+  /* interpret command-line options */
+  if (!GetPhotcodeInfo (argv[1], &code[0], &mode[0])) return (FALSE);
+  if (!GetPhotcodeInfo (argv[3], &code[1], &mode[1])) return (FALSE);
+  if (!GetPhotcodeInfo (argv[5], &code[2], &mode[2])) return (FALSE);
+  if (!GetPhotcodeInfo (argv[7], &code[3], &mode[3])) return (FALSE);
+  if ((mode[2] == MAG_AVE) || (mode[2] == MAG_REF)) UseAverages = TRUE;
+
+  /* find catalog files which overlap this region */
+  Radius = MAX (fabs(graphsky.xmax), fabs(graphsky.ymax));
+  regions = find_regions (graphsky.coords.crval1, graphsky.coords.crval2, Radius, &Nregions);
+
+  /* init vectors to save data */
+  Npts = 0;
+  NPTS = 1;
+  if ((xvec = SelectVector ("xv", ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((yvec = SelectVector ("yv", ANYVECTOR, TRUE)) == NULL) goto escape;
+
+  /* loop over regions, extract data for each region */
+  for (k = 0; k < Nregions; k++) {
+    /* lock, load, unlock catalog */
+    sprintf (filename, "%s/%s", catdir, regions[k].name);
+    catalog.filename = filename;
+    switch (lock_catalog (&catalog, LCK_SOFT)) {
+      case 2:
+	unlock_catalog (&catalog);
+      case 0:
+	continue;
+    }
+    if (!load_catalog (&catalog, LOAD_AVES | LOAD_MEAS | LOAD_SECF, FALSE)) {
+      unlock_catalog (&catalog);
+      continue;
+    }
+    unlock_catalog (&catalog);
+
+    /* get correct mags, convert to X,Y */
+    for (i = 0; i < catalog.Naverage; i++) {
+      M1 = M2 = NULL;
+      m = catalog.average[i].offset;
+
+      M1 = ExtractDMag (&code[0], &mode[0], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], &N1);
+      if (N1 == 0) goto skip;
+
+      M2 = ExtractDMag (&code[2], &mode[2], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], &N2);
+      if (N2 == 0) goto skip;
+
+      for (i1 = 0; i1 < N1; i1++) {
+	for (i2 = 0; i2 < N2; i2++) {
+	  xvec[0].elements[Npts] = M1[i1];
+	  yvec[0].elements[Npts] = M2[i2];
+	  Npts++;
+	  if (Npts == NPTS) {
+	    NPTS += 2000;
+	    REALLOCATE (xvec[0].elements, float, NPTS);
+	    REALLOCATE (yvec[0].elements, float, NPTS);
+	  }
+	}
+      }
+    skip:
+      if (M1 != NULL) free (M1);
+      if (M2 != NULL) free (M2);
+    }
+    if (catalog.average != NULL) free (catalog.average);
+    if (catalog.secfilt != NULL) free (catalog.secfilt);
+    if (catalog.measure != NULL) free (catalog.measure);
+    catalog.average = (Average *) NULL; 
+    catalog.secfilt = (SecFilt *) NULL;
+    catalog.measure = (Measure *) NULL;
+  }
+  if (regions != NULL) free (regions);
+  xvec[0].Nelements = yvec[0].Nelements = Npts;
+  return (TRUE);
+
+usage:
+  fprintf (stderr, "USAGE: ddmags F - F : measure.param\n");
+  return (FALSE);
+
+escape:
+  if (regions != NULL) free (regions);
+  if (catalog.average != NULL) free (catalog.average);
+  if (catalog.secfilt != NULL) free (catalog.secfilt);
+  if (catalog.measure != NULL) free (catalog.measure);
+  return (FALSE);
+}
+
Index: /tags/start/Ohana/src/opihi/dvo/detrend.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/detrend.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/detrend.c	(revision 12606)
@@ -0,0 +1,216 @@
+# include "dvo.h"
+
+/* qualities to be extracted */
+enum {ZERO, DTIME, SKY, BIAS, FWHM, AIRM, TIME, TEMP};
+
+detrend (int argc, char **argv) {
+ 
+  FILE *f;
+  int i, Nimage, status, N, TimeSelect;
+  char DataBase[256];
+  unsigned long int tzero, tend;
+  double trange;
+  int TypeSelect, CCDSelect, FilterSelect;
+  char *Filter, *Type;
+  int type, mode, CCD;
+  int NVALUE;
+  float *value;
+  time_t TimeReference;
+  int TimeFormat;
+  Header header;
+  RegImage *pimage;
+  Vector *vec;
+
+  VarConfig ("REGISTRATION_DATABASE", "%s", DataBase);
+
+  TimeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-time")) {
+    remove_argument (N, &argc, argv);
+    if (!str_to_time (argv[N], &tzero)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!str_to_dtime (argv[N], &trange)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (trange < 0) {
+      trange = fabs (trange);
+      tzero -= trange;
+    }
+    TimeSelect = TRUE;
+  }
+  if (N = get_argument (argc, argv, "-trange")) {
+    remove_argument (N, &argc, argv);
+    if (!str_to_time (argv[N], &tzero)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!str_to_time (argv[N], &tend)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    trange = tend - tzero;
+    if (trange < 0) {
+      trange = fabs (trange);
+      tzero -= trange;
+    }
+    TimeSelect = TRUE;
+  }
+ 
+  TypeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-type")) {
+    remove_argument (N, &argc, argv);
+    Type = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    TypeSelect = TRUE;
+  }
+  type = TYPE_NONE;
+  if (TypeSelect) {
+    if (!strncasecmp (Type, "obj", 3)) {
+      type = TYPE_OBJECT;
+    }
+    if (!strncasecmp (Type, "bias", 4)) {
+      type = TYPE_BIAS;
+    }
+    if (!strncasecmp (Type, "dark", 4)) {
+      type = TYPE_DARK;
+    }
+    if (!strncasecmp (Type, "flat", 4)) {
+      type = TYPE_FLAT;
+    }
+    if (type == TYPE_NONE) {
+      fprintf (stderr, "invalid image type %s\n", Type);
+      return (FALSE);
+    }
+  }
+
+  CCDSelect = FALSE;
+  if (N = get_argument (argc, argv, "-ccd")) {
+    remove_argument (N, &argc, argv);
+    CCD = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+    CCDSelect = TRUE;
+  }
+ 
+  FilterSelect = FALSE;
+  if (N = get_argument (argc, argv, "-filter")) {
+    remove_argument (N, &argc, argv);
+    Filter = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    FilterSelect = TRUE;
+    if (!strcasecmp (Filter, "X")) {
+      FilterSelect = FALSE;
+    }
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: imrough (value)\n");
+    return (FALSE);
+  }
+  
+  /* identify selection */
+  mode = ZERO;
+  if (!strcasecmp (argv[1], "exptime")) mode = DTIME;
+  if (!strcasecmp (argv[1], "sky")) mode = SKY;
+  if (!strcasecmp (argv[1], "bias")) mode = BIAS;
+  if (!strcasecmp (argv[1], "fwhm")) mode = FWHM;
+  if (!strcasecmp (argv[1], "airmass")) mode = AIRM;
+  if (!strcasecmp (argv[1], "time")) mode = TIME;
+  if (!strcasecmp (argv[1], "temp")) mode = TEMP;
+  if (mode == ZERO) {
+    fprintf (stderr, "value may be one of the following:\n");
+    fprintf (stderr, " exptime, sky, bias, fwhm, airmass, time\n");
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  /* load in database header */
+  if (!fits_read_header (DataBase, &header)) {
+    fprintf (stderr, "ERROR: trouble reading database header\n");
+    return (FALSE);
+  }
+
+  /* open database */
+  f = fopen (DataBase, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't open Registration Database\n");
+    return (FALSE);
+  }
+  fseek (f, header.size, SEEK_SET);
+
+  /* load existing data from database */
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+  ALLOCATE (pimage, RegImage, Nimage);
+  status = Fread (pimage, sizeof(RegImage), Nimage, f, "regimage");
+  fclose (f);
+
+  if (status != Nimage) {
+    fprintf (stderr, "ERROR: header and data in dB don't match (%d vs %d)\n", Nimage, status);
+    fits_free_header (&header);
+    free (pimage);
+    return (FALSE);
+  }
+
+  N = 0;
+  NVALUE = 1000;
+  REALLOCATE (vec[0].elements, float, NVALUE);
+  value = vec[0].elements;
+
+  GetTimeFormat (&TimeReference, &TimeFormat);
+  fprintf (stderr, "%d %d\n", TimeReference, TimeFormat);
+
+  /* get data */
+  for (i = 0; i < Nimage; i++) {
+    /* skip unmatched selections */
+    if (TimeSelect && ((pimage[i].obstime < tzero) || (pimage[i].obstime > tzero + trange))) continue;
+    if (TimeSelect && ((pimage[i].obstime < tzero) || (pimage[i].obstime > tzero + trange))) continue;
+    if (FilterSelect && (strcasecmp (pimage[i].filter, Filter))) continue;
+    if (CCDSelect && (pimage[i].ccd != CCD)) continue;
+    if (TypeSelect && (pimage[i].type != type)) continue;
+
+    /* assign correct value */
+    switch (mode) {
+    case (DTIME):
+      value[N] = pimage[i].exptime;
+      break;
+    case (TIME):
+      value[N] = TimeValue (pimage[i].obstime, TimeReference, TimeFormat);
+      break;
+    case (SKY):
+      value[N] = pimage[i].sky;
+      break;
+    case (BIAS):
+      value[N] = pimage[i].bias;
+      break;
+    case (FWHM):
+      value[N] = pimage[i].fwhm;
+      break;
+    case (AIRM):
+      value[N] = pimage[i].airmass;
+      break;
+    case (TEMP):
+      value[N] = pimage[i].teltemp[0];
+      break;
+    }
+    N++;
+    if (N >= NVALUE - 1) {
+      NVALUE += 1000;
+      REALLOCATE (vec[0].elements, float, NVALUE);
+      value = vec[0].elements;
+    }
+  }
+
+  REALLOCATE (vec[0].elements, float, MAX (1,N));
+  vec[0].Nelements = N;
+
+  free (pimage);
+  fits_free_header (&header);
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/dvo/dmagaves.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/dmagaves.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/dmagaves.c	(revision 12606)
@@ -0,0 +1,129 @@
+# include "dvo.h"
+
+int dmagaves (int argc, char **argv) {
+  
+  Catalog catalog;
+  Graphdata graphsky;
+  RegionFile *regions;
+  PhotCode *code[3];
+  Vector *xvec, *yvec;
+
+  char filename[256], catdir[256];
+  double Radius, *M1, M2;
+  int i, j, k, m, N1;
+  int Npts, NPTS, param, mode[3];
+  int Ngraph, Nsec, Nregions;
+
+  /* defaults */
+  regions = NULL;
+  catalog.average = NULL; 
+  catalog.secfilt = NULL;
+  catalog.measure = NULL;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsec = GetPhotcodeNsecfilt ();
+
+  /* load data about plot windows */
+  Ngraph = 0;
+  if (!GetGraphData (&graphsky, NULL, &Ngraph)) return (FALSE);
+ 
+  /* find CATDIR in config system */
+  VarConfig ("CATDIR", "%s", catdir);
+
+  /* interpret command-line options */
+  if (!SetPhotSelections (&argc, argv)) goto usage;
+  if (argc != 6) { goto usage; }
+  if (strcmp (argv[2], "-")) goto usage;
+  if (strcmp (argv[4], ":")) goto usage;
+
+  /* interpret command-line options */
+  if (!GetPhotcodeInfo (argv[1], &code[0], &mode[0])) return (FALSE);
+  if (!GetPhotcodeInfo (argv[3], &code[1], &mode[1])) return (FALSE);
+  if ((param = GetAverageParam (argv[5])) == AVE_ZERO) return (FALSE);
+  code[2] = GetPhotcodeEquivbyCode (code[0][0].code);
+  mode[2] = mode[0];
+
+  /* test PhotSelections: is photcode specified if needed? */
+  for (i = 0; i < 3; i++) {
+    if (!TestPhotSelections (&code[i])) {
+      fprintf (stderr, "photcode selection rules violated\n");
+      fprintf (stderr, "average and ensemble restrictions require a corresponding photcode\n");
+      goto escape;
+    }
+  }
+
+  /* find catalog files which overlap this region */
+  Radius = MAX (fabs(graphsky.xmax), fabs(graphsky.ymax));
+  regions = find_regions (graphsky.coords.crval1, graphsky.coords.crval2, Radius, &Nregions);
+  if (!SetImageSelection (param, &graphsky, TRUE)) return (FALSE);
+  
+  /* init vectors to save data */
+  Npts = 0;
+  NPTS = 1;
+  if ((xvec = SelectVector ("xv", ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((yvec = SelectVector ("yv", ANYVECTOR, TRUE)) == NULL) goto escape;
+
+  for (j = 0; j < Nregions; j++) {
+    /* lock, load, unlock catalog */
+    sprintf (filename, "%s/%s", catdir, regions[j].name);
+    catalog.filename = filename;
+    switch (lock_catalog (&catalog, LCK_SOFT)) {
+    case 2:
+      unlock_catalog (&catalog);
+    case 0:
+      continue;
+    }
+    if (!load_catalog (&catalog, LOAD_AVES | LOAD_MEAS | LOAD_SECF, FALSE)) {
+      unlock_catalog (&catalog);
+      continue;
+    }
+    unlock_catalog (&catalog);
+
+    /* get correct mags, convert to X,Y */
+    for (i = 0; i < catalog.Naverage; i++) {
+      M1 = NULL;
+      m = catalog.average[i].offset;
+
+      M1 = ExtractDMag (code, mode, &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], &N1);
+      if (N1 == 0) goto skip;
+
+      M2 = ExtractAverages (code[2], mode[2], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], param);
+
+      for (k = 0; k < N1; k++) {
+	xvec[0].elements[Npts] = M1[k];
+	yvec[0].elements[Npts] = M2;
+	Npts++;
+	if (Npts == NPTS) {
+	  NPTS += 2000;
+	  REALLOCATE (xvec[0].elements, float, NPTS);
+	  REALLOCATE (yvec[0].elements, float, NPTS);
+	}
+      }
+    skip:
+      if (M1 != NULL) free (M1);
+    }
+    if (catalog.average != NULL) free (catalog.average);
+    if (catalog.secfilt != NULL) free (catalog.secfilt);
+    if (catalog.measure != NULL) free (catalog.measure);
+    catalog.average = (Average *) NULL; 
+    catalog.secfilt = (SecFilt *) NULL;
+    catalog.measure = (Measure *) NULL;
+  }
+  FreeImageSelection ();
+  if (regions != NULL) free (regions);
+  xvec[0].Nelements = yvec[0].Nelements = Npts;
+  return (TRUE);
+
+usage:
+  fprintf (stderr, "USAGE: dmagaves F - F : average.param\n");
+  return (FALSE);
+
+escape:
+  FreeImageSelection ();
+  if (regions != NULL) free (regions);
+  if (catalog.average != NULL) free (catalog.average);
+  if (catalog.secfilt != NULL) free (catalog.secfilt);
+  if (catalog.measure != NULL) free (catalog.measure);
+  return (FALSE);
+}
Index: /tags/start/Ohana/src/opihi/dvo/dmagmeas.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/dmagmeas.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/dmagmeas.c	(revision 12606)
@@ -0,0 +1,132 @@
+# include "dvo.h"
+double *ExtractByDMag (PhotCode **code, int *mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist, int param);
+
+int dmagmeas (int argc, char **argv) {
+  
+  Catalog catalog;
+  Graphdata graphsky;
+  RegionFile *regions;
+  PhotCode *code[3];
+  Vector *xvec, *yvec;
+
+  char filename[256], catdir[256];
+  double Radius, *M1, *M3;
+  int i, j, k, m, N1, N3;
+  int Npts, NPTS, param, mode[3];
+  int Ngraph, Nsec, Nregions;
+
+  /* defaults */
+  regions = NULL;
+  catalog.average = NULL; 
+  catalog.secfilt = NULL;
+  catalog.measure = NULL;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsec = GetPhotcodeNsecfilt ();
+
+  /* load data about plot windows */
+  Ngraph = 0;
+  if (!GetGraphData (&graphsky, NULL, &Ngraph)) return (FALSE);
+ 
+  /* find CATDIR in config system */
+  VarConfig ("CATDIR", "%s", catdir);
+
+  /* interpret command-line options */
+  if (!SetPhotSelections (&argc, argv)) goto usage;
+  if (argc != 6) { goto usage; }
+  if (strcmp (argv[2], "-")) goto usage;
+  if (strcmp (argv[4], ":")) goto usage;
+
+  /* interpret command-line options */
+  if (!GetPhotcodeInfo (argv[1], &code[0], &mode[0])) goto usage;
+  if (!GetPhotcodeInfo (argv[3], &code[1], &mode[1])) goto usage;
+  if ((param = GetMeasureParam (argv[5])) == MEAS_ZERO) goto usage;
+
+  /* test PhotSelections: is photcode specified if needed? */
+  for (i = 0; i < 2; i++) {
+    if (!TestPhotSelections (&code[i])) {
+      fprintf (stderr, "photcode selection rules violated\n");
+      fprintf (stderr, "average and ensemble restrictions require a corresponding photcode\n");
+      goto escape;
+    }
+  }
+
+  /* find catalog files which overlap this region */
+  Radius = MAX (fabs(graphsky.xmax), fabs(graphsky.ymax));
+  regions = find_regions (graphsky.coords.crval1, graphsky.coords.crval2, Radius, &Nregions);
+  if (!SetImageSelection (param, &graphsky, TRUE)) return (FALSE);
+
+  /* init vectors to save data */
+  Npts = 0;
+  NPTS = 1;
+  if ((xvec = SelectVector ("xv", ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((yvec = SelectVector ("yv", ANYVECTOR, TRUE)) == NULL) goto escape;
+
+  /* loop over regions, extract data for each region */
+  for (j = 0; j < Nregions; j++) {
+    /* lock, load, unlock catalog */
+    sprintf (filename, "%s/%s", catdir, regions[j].name);
+    catalog.filename = filename;
+    switch (lock_catalog (&catalog, LCK_SOFT)) {
+      case 2:
+	unlock_catalog (&catalog);
+      case 0:
+	continue;
+    }
+    if (!load_catalog (&catalog, LOAD_AVES | LOAD_MEAS | LOAD_SECF, FALSE)) {
+      unlock_catalog (&catalog);
+      continue;
+    }
+    unlock_catalog (&catalog);
+
+    /* get correct mags, convert to X,Y */
+    for (i = 0; i < catalog.Naverage; i++) {
+      M1 = M3 = NULL;
+      m = catalog.average[i].offset;
+
+      M1 = ExtractDMag (code, mode, &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], &N1);
+      if (N1 == 0) goto skip;
+
+      M3 = ExtractByDMag (code, mode, &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], &N3, param);
+      if (N3 != N1) { fprintf (stderr, "mismatch: programming error\n"); goto escape; }
+
+      for (k = 0; k < N1; k++) {
+	xvec[0].elements[Npts] = M1[k];
+	yvec[0].elements[Npts] = M3[k];
+	Npts++;
+	if (Npts == NPTS) {
+	  NPTS += 2000;
+	  REALLOCATE (xvec[0].elements, float, NPTS);
+	  REALLOCATE (yvec[0].elements, float, NPTS);
+	}
+      }
+    skip:
+      if (M1 != NULL) free (M1);
+      if (M3 != NULL) free (M3);
+    }
+    if (catalog.average != NULL) free (catalog.average);
+    if (catalog.secfilt != NULL) free (catalog.secfilt);
+    if (catalog.measure != NULL) free (catalog.measure);
+    catalog.average = (Average *) NULL; 
+    catalog.secfilt = (SecFilt *) NULL;
+    catalog.measure = (Measure *) NULL;
+  }
+  FreeImageSelection ();
+  if (regions != NULL) free (regions);
+  xvec[0].Nelements = yvec[0].Nelements = Npts;
+  return (TRUE);
+
+usage:
+  fprintf (stderr, "USAGE: dmagmeas F - F : measure.param\n");
+  return (FALSE);
+
+escape:
+  FreeImageSelection ();
+  if (regions != NULL) free (regions);
+  if (catalog.average != NULL) free (catalog.average);
+  if (catalog.secfilt != NULL) free (catalog.secfilt);
+  if (catalog.measure != NULL) free (catalog.measure);
+  return (FALSE);
+}
+
Index: /tags/start/Ohana/src/opihi/dvo/dmags.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/dmags.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/dmags.c	(revision 12606)
@@ -0,0 +1,134 @@
+# include "dvo.h"
+
+int dmags (int argc, char **argv) {
+  
+  Catalog catalog;
+  Graphdata graphsky;
+  RegionFile *regions;
+  PhotCode *code[3];
+  Vector *xvec, *yvec;
+
+  char filename[256], catdir[256];
+  double Radius, *M1, *M3;
+  int i, j, m, i1, i3, N1, N3;
+  int Npts, NPTS, mode[3];
+  int Ngraph, Nsec, Nregions;
+
+  /* defaults */
+  regions = NULL;
+  catalog.average = NULL; 
+  catalog.secfilt = NULL;
+  catalog.measure = NULL;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsec = GetPhotcodeNsecfilt ();
+
+  /* load data about plot windows */
+  Ngraph = 0;
+  if (!GetGraphData (&graphsky, NULL, &Ngraph)) return (FALSE);
+ 
+  /* find CATDIR in config system */
+  VarConfig ("CATDIR", "%s", catdir);
+
+  /* interpret command-line options */
+  if (!SetPhotSelections (&argc, argv)) goto usage;
+  if (argc != 6) { goto usage; }
+  if (strcmp (argv[2], "-")) goto usage;
+  if (strcmp (argv[4], ":")) goto usage;
+
+  /* interpret command-line options */
+  if (!GetPhotcodeInfo (argv[1], &code[0], &mode[0])) goto usage;
+  if (!GetPhotcodeInfo (argv[3], &code[1], &mode[1])) goto usage;
+  if (!GetPhotcodeInfo (argv[5], &code[2], &mode[2])) goto usage;
+
+  /* test PhotSelections: is photcode specified if needed? */
+  for (i = 0; i < 3; i++) {
+    if (!TestPhotSelections (&code[i])) {
+      fprintf (stderr, "photcode selection rules violated\n");
+      fprintf (stderr, "average and ensemble restrictions require a corresponding photcode\n");
+      goto escape;
+    }
+  }
+
+  /* find catalog files which overlap this region */
+  Radius = MAX (fabs(graphsky.xmax), fabs(graphsky.ymax));
+  regions = find_regions (graphsky.coords.crval1, graphsky.coords.crval2, Radius, &Nregions);
+
+  /* init vectors to save data */
+  Npts = 0;
+  NPTS = 1;
+  if ((xvec = SelectVector ("xv", ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((yvec = SelectVector ("yv", ANYVECTOR, TRUE)) == NULL) goto escape;
+
+  /* loop over regions, extract data for each region */
+  for (j = 0; j < Nregions; j++) {
+    /* lock, load, unlock catalog */
+    sprintf (filename, "%s/%s", catdir, regions[j].name);
+    catalog.filename = filename;
+    switch (lock_catalog (&catalog, LCK_SOFT)) {
+      case 2:
+	unlock_catalog (&catalog);
+      case 0:
+	continue;
+    }
+    if (!load_catalog (&catalog, LOAD_AVES | LOAD_MEAS | LOAD_SECF, FALSE)) {
+      unlock_catalog (&catalog);
+      continue;
+    }
+    unlock_catalog (&catalog);
+
+    /* get correct mags, convert to X,Y */
+    for (i = 0; i < catalog.Naverage; i++) {
+      M1 = M3 = NULL;
+      m = catalog.average[i].offset;
+
+      M1 = ExtractDMag (code, mode, &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], &N1);
+      if (N1 == 0) goto skip;
+
+      M3 = ExtractMagnitudes (code[2], mode[2], &catalog.average[i], &catalog.secfilt[i*Nsec], &catalog.measure[m], &N3);
+      if (N3 == 0) goto skip;
+
+      for (i1 = 0; i1 < N1; i1++) {
+	for (i3 = 0; i3 < N3; i3++) {
+	  xvec[0].elements[Npts] = M1[i1];
+	  yvec[0].elements[Npts] = M3[i3];
+	  Npts++;
+	  if (Npts == NPTS) {
+	    NPTS += 2000;
+	    REALLOCATE (xvec[0].elements, float, NPTS);
+	    REALLOCATE (yvec[0].elements, float, NPTS);
+	  }
+	}
+      }
+    skip:
+      if (M1 != NULL) free (M1);
+      if (M3 != NULL) free (M3);
+    }
+    if (catalog.average != NULL) free (catalog.average);
+    if (catalog.secfilt != NULL) free (catalog.secfilt);
+    if (catalog.measure != NULL) free (catalog.measure);
+    catalog.average = (Average *) NULL; 
+    catalog.secfilt = (SecFilt *) NULL;
+    catalog.measure = (Measure *) NULL;
+  }
+  if (regions != NULL) free (regions);
+  xvec[0].Nelements = yvec[0].Nelements = Npts;
+  return (TRUE);
+
+usage:
+  fprintf (stderr, "USAGE: dmags F - F : F\n");
+  fprintf (stderr, "  F : any photcodes with matched qualifiers:\n");
+  fprintf (stderr, "    pri: F:inst, F:cat, F:sys, F:rel, F:cal, F:ave, F:ref\n");
+  fprintf (stderr, "    sec: F:inst, F:cat, F:sys, F:rel, F:cal, F:ave, F:ref\n");
+  fprintf (stderr, "    dep: F:inst, F:cat, F:sys, F:rel, F:cal\n");
+  fprintf (stderr, "    ref: F:cat\n");
+  return (FALSE);
+
+escape:
+  if (regions != NULL) free (regions);
+  if (catalog.average != NULL) free (catalog.average);
+  if (catalog.secfilt != NULL) free (catalog.secfilt);
+  if (catalog.measure != NULL) free (catalog.measure);
+  return (FALSE);
+}
Index: /tags/start/Ohana/src/opihi/dvo/dmt.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/dmt.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/dmt.c	(revision 12606)
@@ -0,0 +1,154 @@
+# include "dvo.h"
+
+/* extract vectors giving delta mags for multiple measurements */ 
+int dmt (int argc, char **argv) {
+  
+  int i, m, k, N, Nregions, Ngraph, SaveVectors;
+  int Ns, Nsec, NPTS;
+  char catdir[256], filename[256];
+  double Radius;
+  float dt1, dt2, dmt1, dmt2;
+  float M0, M1, M2, M3;
+  PhotCode *code;
+  Catalog catalog;
+  Graphdata graphmode, graphsky;
+  RegionFile *regions;
+  Vector Xvec, Yvec, Zvec, Rvec, Dvec;
+  Vector *vec1, *vec2, *vec3, *vec4, *vec5;
+
+  VarConfig ("CATDIR", "%s", catdir);
+  if (!InitPhotcodes ()) return (FALSE);
+
+  SaveVectors = FALSE;
+  if (N = get_argument (argc, argv, "-vect")) {
+    remove_argument (N, &argc, argv);
+    if ((vec1 = SelectVector ("dmtdmt", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    if ((vec2 = SelectVector ("dmtvar", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    if ((vec3 = SelectVector ("dmtmag", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    if ((vec4 = SelectVector ("dmtra",  ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    if ((vec5 = SelectVector ("dmtdec", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    SaveVectors = TRUE;
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: dmags filter\n");
+    return (FALSE);
+  }
+
+  Ngraph = 0;
+  if (!GetGraphData (&graphsky, NULL, &Ngraph)) return (FALSE);
+  if (!GetGraph (&graphmode, NULL, NULL)) return (FALSE);
+
+  if ((code = GetPhotcodebyName (argv[1])) == NULL) {
+    fprintf (stderr, "ERROR: photcode not found in photcode table\n");
+    return (FALSE);
+  }
+  if ((code[0].type != PHOT_SEC) && (code[0].type != PHOT_PRI)) {
+    fprintf (stderr, "first filter must be a PRIMARY or SECONDARY photometry type\n");
+    return (FALSE);
+  }
+  Nsec = GetPhotcodeNsecfilt();
+  Ns = GetPhotcodeNsec (code[0].code);
+
+  Radius = MAX (fabs(graphsky.xmax), fabs(graphsky.ymax));
+  regions = find_regions (graphsky.coords.crval1, graphsky.coords.crval2, Radius, &Nregions);
+  
+  N = 0;
+  NPTS = catalog.Nmeasure;
+  ALLOCATE (Xvec.elements, float, NPTS);
+  ALLOCATE (Yvec.elements, float, NPTS);
+  if (SaveVectors) {
+    ALLOCATE (Zvec.elements, float, NPTS);
+    ALLOCATE (Rvec.elements, float, NPTS);
+    ALLOCATE (Dvec.elements, float, NPTS);
+  }
+
+  for (k = 0; k < Nregions; k++) {
+
+    sprintf (filename, "%s/%s", catdir, regions[k].name);
+    /* lock, load, unlock catalog */
+    catalog.filename = filename;
+    switch (lock_catalog (&catalog, LCK_SOFT)) {
+    case 2:
+      unlock_catalog (&catalog);
+    case 0:
+      continue;
+    }
+    if (!load_catalog (&catalog, LOAD_AVES | LOAD_MEAS | LOAD_SECF, TRUE)) {
+      unlock_catalog (&catalog);
+      continue;
+    }
+    unlock_catalog (&catalog);
+
+    for (i = 0; i < catalog.Naverage; i++) {
+      if (catalog.average[i].Nm != 3) continue;
+      m = catalog.average[i].offset;
+      M0 = (Ns == -1) ? 0.001*catalog.average[i].M : 0.001*catalog.secfilt[i*Nsec+Ns].M;
+      M1 = PhotCat (&catalog.measure[m+0]);
+      M2 = PhotCat (&catalog.measure[m+1]);
+      M3 = PhotCat (&catalog.measure[m+2]);
+
+      dt1 = (catalog.measure[m+0].t < catalog.measure[m+1].t) ? catalog.measure[m+1].t - catalog.measure[m+0].t : -1 * ((float)(catalog.measure[m+1].t - catalog.measure[m+0].t));
+      dt2 = (catalog.measure[m+1].t < catalog.measure[m+2].t) ? catalog.measure[m+2].t - catalog.measure[m+1].t : -1 * ((float)(catalog.measure[m+2].t - catalog.measure[m+1].t));
+      dmt1 = (M2 - M1) / dt1;
+      dmt2 = (M3 - M2) / dt2;
+      Xvec.elements[N] = (dmt1 - dmt2) / (dmt1 + dmt2);
+      Yvec.elements[N] = (dmt1 + dmt2) / 2.0;
+      if (SaveVectors) {
+	Rvec.elements[N] = catalog.average[i].R;
+	Dvec.elements[N] = catalog.average[i].D;
+	Zvec.elements[N] = M0;
+      }
+      N++;
+      if (N == NPTS - 1) {
+	NPTS += 2000;
+	REALLOCATE (Xvec.elements, float, NPTS);
+	REALLOCATE (Yvec.elements, float, NPTS);
+	if (SaveVectors) {
+	  REALLOCATE (Zvec.elements, float, NPTS);
+	  REALLOCATE (Rvec.elements, float, NPTS);
+	  REALLOCATE (Dvec.elements, float, NPTS);
+	}
+      }
+    }
+  }
+  Yvec.Nelements = Xvec.Nelements = N;
+  REALLOCATE (Xvec.elements, float, MAX (1, N));
+  REALLOCATE (Yvec.elements, float, MAX (1, N));
+  if (SaveVectors) {
+    Rvec.Nelements = Dvec.Nelements = Zvec.Nelements = N;
+    REALLOCATE (Zvec.elements, float, MAX (1, N));
+    REALLOCATE (Rvec.elements, float, MAX (1, N));
+    REALLOCATE (Dvec.elements, float, MAX (1, N));
+  }
+
+  if (SaveVectors) {
+    free (vec1[0].elements);
+    vec1[0].elements = Yvec.elements;
+    vec1[0].Nelements = Yvec.Nelements;
+    free (vec2[0].elements);
+    vec2[0].elements = Xvec.elements;
+    vec2[0].Nelements = Xvec.Nelements;
+    free (vec3[0].elements);
+    vec3[0].elements = Zvec.elements;
+    vec3[0].Nelements = Zvec.Nelements;
+    free (vec4[0].elements);
+    vec4[0].elements = Rvec.elements;
+    vec4[0].Nelements = Rvec.Nelements;
+    free (vec5[0].elements);
+    vec5[0].elements = Dvec.elements;
+    vec5[0].Nelements = Dvec.Nelements;
+  } else {
+    graphmode.style = 2; /* set style to points */
+    PrepPlotting (N, &graphmode);
+    
+    PlotVector (N, Xvec.elements);
+    PlotVector (N, Yvec.elements);
+
+    free (Xvec.elements);
+    free (Yvec.elements);
+    free (Zvec.elements);
+  }
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/dvo/dvo.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/dvo.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/dvo.c	(revision 12606)
@@ -0,0 +1,80 @@
+# include "opihi.h"
+
+# define opihi_name "DVO"
+# define opihi_prompt "dvo: "
+# define opihi_description "desktop virtual observatory\n"
+# define opihi_history ".dvo"
+# define opihi_rcfile ".dvorc"
+
+void InitBasic ();
+void InitData ();
+void InitAstro ();
+void InitDVO ();
+
+void welcome () {
+  fprintf (stderr, "\n");
+  fprintf (stderr, "Welcome to %s - %s\n\n", opihi_name, opihi_description);
+}
+
+/* program-dependent initialization */
+void initialize (int argc, char **argv) {
+  
+  FILE *f;
+
+  auto_break = TRUE;
+
+  Nlists = 0;
+  ALLOCATE (lists, List, 1); 
+
+  /* init functions required by libraries */
+  /* -libopihi */
+  InitCommands ();
+  InitMacros ();
+  InitBuffers ();
+  InitVectors ();
+  InitVariables ();
+
+  /* -libdisplay */
+  InitGraph ();
+  InitImage ();
+
+  /* load the commands used by this implementation */
+  InitBasic ();
+  InitData ();
+  InitAstro ();
+  InitDVO ();
+  InitOutfile ();
+
+  rl_readline_name = opihi_name;
+  rl_attempted_completion_function = command_completer;
+
+  set_str_variable ("HISTORY", opihi_history);
+  set_str_variable ("PROMPT", opihi_prompt);
+  set_str_variable ("RCFILE", opihi_rcfile);
+
+  /* here we open the history file for append.  it this fails, we
+     won't be able to write to it, warn the user.  otherwise, this
+     creates the file readline will write to, if it did not exist */  
+
+  /* check history file */
+  /* rewrite with fstat or stat */
+  f = fopen (opihi_history, "a");
+  if (f == NULL) /* no current history file here */
+    fprintf (stderr, "can't save history.\n");
+  else
+    fclose (f);
+  
+  stifle_history (200);
+  read_history (opihi_history);
+
+  signal (SIGINT, SIG_IGN);
+  return;
+}
+
+/* add program-dependent exit functions here */
+void cleanup () {
+  /* -libdisplay */
+  QuitImage ();
+  QuitGraph ();
+  return;
+}
Index: /tags/start/Ohana/src/opihi/dvo/dvomisc.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/dvomisc.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/dvomisc.c	(revision 12606)
@@ -0,0 +1,141 @@
+# include "dvo.h"
+
+void cprecess (Average *average, int Naverage, double in_epoch, double out_epoch) {
+
+  int i;
+  double T;
+  double A, D, RA, DEC, zeta, z, theta;
+  double SA, CA, SD, CD;
+  
+  T = (out_epoch - in_epoch) / 100.0;
+  
+  zeta  = RAD_DEG*(0.6406161*T + 0.0000839*T*T + 0.0000050*T*T*T);
+  theta = RAD_DEG*(0.5567530*T - 0.0001185*T*T - 0.0000116*T*T*T);
+  z     =          0.6406161*T + 0.0003041*T*T + 0.0000051*T*T*T;
+  
+  for (i = 0; i < Naverage; i++) {
+    A = average[i].R;
+    D = average[i].D;
+    SD =  cos(RAD_DEG*A + zeta)*sin(theta)*cos(RAD_DEG*D) + cos(theta)*sin(RAD_DEG*D);
+    CD = sqrt (1 - SD*SD);
+    SA =  sin(RAD_DEG*A + zeta)*cos(RAD_DEG*D)/CD;
+    CA = (cos(RAD_DEG*A + zeta)*cos(theta)*cos(RAD_DEG*D) - sin(theta)*sin(RAD_DEG*D))/CD;
+    
+    DEC = DEG_RAD*asin(SD);
+    RA  = DEG_RAD*atan2(SA, CA) + z;
+    
+    if (RA < 0)
+      RA += 360;
+    
+    average[i].R = RA;
+    average[i].D = DEC; 
+  }
+
+}
+
+/* values are ave[i].R, ave[i].D, ave[i].M */
+void sortave (Average *ave, int N) {
+
+  int l,j,ir,i;
+  Average tmp;
+
+  if (N < 2) return;
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tmp = ave[l];
+    }
+    else {
+      tmp = ave[ir];
+      ave[ir] = ave[0];
+      if (--ir == 0) {
+	ave[0] = tmp;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && ave[j].R < ave[j+1].R) j++;
+      if (tmp.R < ave[j].R) {
+	ave[i] = ave[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    ave[i] = tmp;
+  }
+}
+
+/* values are ave[i].R, ave[i].D, ave[i].M */
+void sort_images (Image *image, int N) {
+
+  int l,j,ir,i;
+  Image tmp;
+
+  if (N < 2) return;
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tmp = image[l];
+    }
+    else {
+      tmp = image[ir];
+      image[ir] = image[0];
+      if (--ir == 0) {
+	image[0] = tmp;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && image[j].tzero < image[j+1].tzero) j++;
+      if (tmp.tzero < image[j].tzero) {
+	image[i] = image[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    image[i] = tmp;
+  }
+}
+
+/* sort subset by image[subset[i]].tzero */
+void sort_image_subset (Image *image, int *subset, int N) {
+
+  int l, j, ir, i, tmp;
+
+  if (N < 2) return;
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tmp = subset[l];
+    }
+    else {
+      tmp = subset[ir];
+      subset[ir] = subset[0];
+      if (--ir == 0) {
+	subset[0] = tmp;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && image[subset[j]].tzero < image[subset[j+1]].tzero) j++;
+      if (image[tmp].tzero < image[subset[j]].tzero) {
+	subset[i] = subset[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    subset[i] = tmp;
+  }
+}
Index: /tags/start/Ohana/src/opihi/dvo/extract.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/extract.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/extract.c	(revision 12606)
@@ -0,0 +1,449 @@
+# include "dvo.h"
+
+enum {ZERO, RA, DEC, MAG, dMAG, Xm, Xp, NMEAS, NMISS, REF, TYPE, NPHOT, NCODE, FLAG};
+
+# define NBYTES 160000
+# define BYTES_STAR 23
+# define BLOCK 1000
+# define DNSTARS 1000
+
+int extract (int argc, char **argv) {
+  
+  FILE *f;
+  int i, Col, N, Nbytes, nbytes, NPTS;
+  int InRegion, GSC, ASCII, LONEOS, mode, loadmode;
+  int j, k, m, Nregions;
+  float M0, m0;
+  char filename[128];
+  float Radius;
+  char catdir[256], gscdir[256];
+  int PhotcodeSelect;
+  char PhotCodeFile[256], code[64];
+  double ZERO_POINT;
+  int Ns, N1, n1, Nsec;
+  int Ngraph;
+  int value;
+  Vector *vec;
+  PhotCodeData photcodes;
+  Graphdata graphmode;
+  Catalog catalog;
+  RegionFile *regions;
+
+  Ngraph = 0;
+  if (!GetGraphData (&graphmode, NULL, &Ngraph)) return (FALSE);
+  if (!InitPhotcodes ()) return (FALSE);
+
+  VarConfig ("CATDIR", "%s", catdir);
+  VarConfig ("GSCDIR", "%s", gscdir);
+
+  regions = (RegionFile *) NULL;
+  ASCII = FALSE;
+  LONEOS = TRUE;
+  GSC = FALSE;
+  if (N = get_argument (argc, argv, "-g")) {
+    remove_argument (N, &argc, argv);
+    GSC = TRUE;
+    ASCII = FALSE;
+    LONEOS = FALSE;
+  }
+
+  Col = 1;
+  if (N = get_argument (argc, argv, "-a")) {
+    remove_argument (N, &argc, argv);
+    ASCII = TRUE;
+    GSC = FALSE;
+    LONEOS = FALSE;
+    Col = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* check for region-based selection */
+  code = NULL;
+  PhotcodeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-photcode")) {
+    PhotcodeSelect = True;
+    remove_argument (N, &argc, argv);
+    if ((code = GetPhotcodebyName (argv[N])) == NULL) {
+      fprintf (stderr, "ERROR: photcode %s not found in photcode table\n", argv[N]);
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: extract (filename) (value) [-g / -a Ncol] \n");
+    return (FALSE);
+  }
+  
+  InRegion = FALSE;
+  if (!strcmp (argv[1], "-all")) {
+    InRegion = TRUE;
+  }
+
+  /* identify selection */
+  if (LONEOS) {
+    mode = ZERO;
+    if (!strcasecmp (argv[2], "ra")) mode = RA;
+    if (!strcasecmp (argv[2], "dec")) mode = DEC;
+    if (!strcasecmp (argv[2], "mag")) mode = MAG;
+    if (!strcasecmp (argv[2], "Nmeas")) mode = NMEAS;
+    if (!strcasecmp (argv[2], "Nmiss")) mode = NMISS;
+    if (!strcasecmp (argv[2], "Xp")) mode = Xp;
+    if (!strcasecmp (argv[2], "Xm")) mode = Xm;
+    if (!strcasecmp (argv[2], "dM")) mode = dMAG;
+    if (!strcasecmp (argv[2], "flag")) mode = FLAG;
+    if (!strcasecmp (argv[2], "ref")) mode = REF;
+    if (!strcasecmp (argv[2], "type")) mode = TYPE;
+    if (!strcasecmp (argv[2], "Nphot")) mode = NPHOT;
+    if (!strcasecmp (argv[2], "Ncode")) mode = NCODE;
+    if (mode == ZERO) {
+      fprintf (stderr, "value may be one of the following:\n");
+      fprintf (stderr, " ra dec mag Nmeas Nmiss Xp Xm ID\n");
+      return (FALSE);
+    }
+  }
+
+  if ((mode == REF) && !PhotcodeSelect) {
+    fprintf (stderr, "must specify photcode for Reference\n");
+    return (FALSE);
+  }
+  if ((mode == TYPE) && !PhotcodeSelect) {
+    fprintf (stderr, "must specify photcode for Type\n");
+    return (FALSE);
+  }
+
+  /* check photcode data / selection validity */
+  Ns = -1;
+  Nsec = GetPhotcodeNsecfilt ();
+  if (PhotcodeSelect) {
+    Ns = GetPhotcodeNsec (code[0].code);
+    if ((mode != REF) && (code[0].type != PHOT_SEC) && (code[0].type != PHOT_PRI)) {
+      fprintf (stderr, "filter must be a PRIMARY or SECONDARY photometry type\n");
+      return (FALSE);
+    }
+    if ((mode == REF) && (code[0].type != PHOT_REF)) {
+      fprintf (stderr, "filter must be a REFERENCE photometry type\n");
+      return (FALSE);
+    }
+  }
+
+  if (GSC) {
+    mode = ZERO;
+    if (!strcasecmp (argv[2], "ra")) 
+      mode = RA;
+    if (!strcasecmp (argv[2], "dec")) 
+      mode = DEC;
+    if (!strcasecmp (argv[2], "mag")) 
+      mode = MAG;
+    if (mode == ZERO) {
+      fprintf (stderr, "for GSC, value may be one of the following:\n");
+      fprintf (stderr, " ra dec mag\n");
+      return (FALSE);
+    }
+  }
+
+  if ((vec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (InRegion) {
+    Radius = MAX (fabs(graphmode.xmax), fabs(graphmode.ymax));
+    regions = find_regions (graphmode.coords.crval1, graphmode.coords.crval2, Radius, &Nregions);
+  } else {
+    Nregions = 1;
+  }
+  
+  /* create storage vector */
+  NPTS = 1000;
+  REALLOCATE (vec[0].elements, float, NPTS);
+  vec[0].Nelements = N = 0;
+
+  /* we loop over Nregions, but for ASCII Nregions = 1 */
+  for (j = 0; j < Nregions; j++) {
+    
+    /* Load in data from an ASCII file list of ra, dec, mag */
+    if (ASCII) {
+      char *tbuffer;
+      double tmp;
+      float *V;
+      
+      f = fopen (argv[1], "r");
+      if (f == (FILE *) NULL) {
+	fprintf (stderr, "ERROR: can't open data file: %s\n", argv[1]);
+	/* delete new vector! */
+	return (FALSE);
+      }
+      ALLOCATE (tbuffer, char, 1024);
+      
+      V = vec[0].elements;
+      while (scan_line (f, tbuffer) != EOF) {
+	dparse (&tmp, Col, tbuffer);
+	*V = tmp;
+	V++;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 1000;
+	  REALLOCATE (vec[0].elements, float, NPTS);
+	  V = &vec[0].elements[N];
+	}
+      }
+      free (tbuffer);
+      vec[0].Nelements = N;
+      REALLOCATE (vec[0].elements, float, MAX(1,N));
+      fclose (f);
+      return (TRUE);
+    }
+    
+    /* load data from the GSC files */
+    if (GSC) {
+      char *tbuffer;
+      double tmp;
+      float *V;
+      
+      if (InRegion) {
+	sprintf (filename, "%s/%s\0", gscdir, regions[j].name);
+      } else {
+	sprintf (filename, "%s/%s\0", gscdir, argv[1]);
+      }
+      
+      f = fopen (filename, "r");
+      if (f == (FILE *) NULL) {
+	fprintf (stderr, "no stars in %s, skipping\n", filename);
+	continue;
+      }
+      ALLOCATE (tbuffer, char, (BLOCK*BYTES_STAR));
+      
+      V = &vec[0].elements[N];
+      Nbytes = BLOCK*BYTES_STAR;
+      while ((nbytes = fread (tbuffer, 1, Nbytes, f)) > 0) {
+	for (i = 0; i < nbytes / BYTES_STAR; i++) {
+	  if (mode == RA) {
+	    dparse (&tmp, 1, &tbuffer[i*BYTES_STAR]);
+	    *V = tmp;
+	  }
+	  if (mode == DEC) {
+	    dparse (&tmp, 2, &tbuffer[i*BYTES_STAR]);
+	    *V = tmp;
+	  }
+	  if (mode == MAG) {
+	    dparse (&tmp, 3, &tbuffer[i*BYTES_STAR]);
+	    *V = tmp;
+	  }
+	  V++;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	    V = &vec[0].elements[N];
+	  }
+	}
+      }
+      free (tbuffer);
+      fclose (f);
+    }
+  
+    /* load data from the photometry database files */
+    if (LONEOS) {
+      /* find and open correct file */
+      if (InRegion) {
+	sprintf (filename, "%s/%s\0", catdir, regions[j].name);
+      } else {
+	sprintf (filename, "%s/%s\0", catdir, argv[1]);
+      }
+      catalog.average = (Average *) NULL;
+      catalog.measure = (Measure *) NULL;
+      catalog.secfilt = (SecFilt *) NULL;
+      loadmode = LOAD_AVES | LOAD_SECF;
+      if ((mode == REF) || (mode == TYPE) || (mode == NPHOT) || (mode == NCODE)) 
+	loadmode = loadmode | LOAD_MEAS;
+
+      /* lock, load, unlock catalog */
+      catalog.filename = filename;
+      switch (lock_catalog (&catalog, LCK_SOFT)) {
+      case 2:
+	unlock_catalog (&catalog);
+      case 0:
+	continue;
+      }
+      if (!load_catalog (&catalog, loadmode, TRUE)) {
+	unlock_catalog (&catalog);
+	continue;
+      }
+      unlock_catalog (&catalog);
+
+      /* assign vector values */
+      switch (mode) {
+      case (RA):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  vec[0].elements[N] = catalog.average[i].R;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (DEC):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  vec[0].elements[N] = catalog.average[i].D;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (MAG):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  M0 = (Ns == -1) ? catalog.average[i].M : catalog.secfilt[i*Nsec+Ns].M;
+	  vec[0].elements[N] = M0 / 1000.0;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (NMEAS):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  vec[0].elements[N] = catalog.average[i].Nm;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (NMISS):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  vec[0].elements[N] = catalog.average[i].Nn;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (Xp):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  /* Xp is scatter in 1/100 arcsec */
+	  vec[0].elements[N] = 0.01*catalog.average[i].Xp;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (NCODE):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  m = catalog.average[i].offset;
+	  Ncode = 0;
+	  for (k = 0; k < catalog.average[i].Nm; k++, m++) {
+	    if (code[0].code != GetPhotcodeEquivCodebyCode (catalog.measure[m].source)) continue;
+	    Ncode ++;
+	  }
+	  vec[0].elements[N] = Ncode;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (NPHOT):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  m = catalog.average[i].offset;
+	  Ncode = 0;
+	  for (k = 0; k < catalog.average[i].Nm; k++, m++) {
+	    if (code[0].code != GetPhotcodeEquivCodebyCode (catalog.measure[m].source)) continue;
+	    if (catalog.measure[m].source & (ID_MEAS_POOR | ID_MEAS_SKIP)) continue;
+	    Ncode ++;
+	  }
+	  vec[0].elements[N] = Ncode;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (Xm):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  M0 = (Ns == -1) ? catalog.average[i].Xm : catalog.secfilt[i*Nsec+Ns].Xm;
+	  vec[0].elements[N] = (M0 == NO_MAG) ? -1.0 : pow (10.0, 0.01*M0);
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (dMAG):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  /* dM is 1000.0 * error */
+	  M0 = (Ns == -1) ? catalog.average[i].dM : catalog.secfilt[i*Nsec+Ns].dM;
+	  vec[0].elements[N] = (M0 == NO_MAG) ? -1.0 : 0.001*M0;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (FLAG):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  vec[0].elements[N] = catalog.average[i].code;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (REF):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  m = catalog.average[i].offset;
+	  vec[0].elements[N] = -32;
+	  for (k = 0; k < catalog.average[i].Nm; k++) {
+	    if (catalog.measure[m+k].source == N1) {
+	      vec[0].elements[N] = PhotCat (&catalog.measure[m+k]);
+	      k = catalog.average[i].Nm;
+	    }
+	  }
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (TYPE):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  m = catalog.average[i].offset;
+	  vec[0].elements[N] = DetermineTypeCode (&catalog.average[i], &catalog.measure[m], &photcodes, N1);
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      }
+      if (catalog.average != 0) free (catalog.average);
+      if (catalog.measure != 0) free (catalog.measure);
+      if (catalog.secfilt != 0) free (catalog.secfilt);
+    }
+  }
+
+  vec[0].Nelements = N;
+  REALLOCATE (vec[0].elements, float, MAX(1,N));
+  return (TRUE);
+
+}
+  
+  /* USAGE: extract (what) (where) (from) [option] */
+  /* examples:
+     extract n0000/n0001 mag m 
+     extract -g n0000/n0020 ra r 
+     extract -all Xm xm
+     extract fred dec d -a 2 */
+  
Index: /tags/start/Ohana/src/opihi/dvo/find_regions.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/find_regions.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/find_regions.c	(revision 12606)
@@ -0,0 +1,155 @@
+# include "dvo.h"
+# include "hstgsc.h"
+
+/* returns a list of region files within the desired RA, DEC region */
+RegionFile *find_regions (double Ra, double Dec, double radius, int *Nregions) {
+  
+  char filename[256];
+  char buffer[28800], temp[50];
+  RegionFile *regions;
+  FILE *f;
+  double minRa, maxRa, minDec, maxDec, rad;
+
+  double RA0, RA1, DEC0, DEC1;
+  int i, j, NBigDec;
+  int NLINES, done, NREGIONS, nregion;
+  
+  VarConfig ("GSCFILE", "%s", filename);
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find regions file %s\n", filename);
+    *Nregions = 0;
+    return ((RegionFile *) NULL);
+  }
+  
+  NREGIONS = 50;
+  ALLOCATE (regions, RegionFile, NREGIONS);
+  nregion = 0;
+
+  while (Ra < 0) Ra += 360.0;
+  while (Ra >= 360) Ra -= 360.0;
+
+  minDec = Dec - radius;
+  maxDec = Dec + radius;
+
+  if ((minDec <= -90) || (maxDec >= 90)) {
+    minRa = 0;
+    maxRa = 360;
+  } else {
+    rad = MAX (radius / (cos(minDec*RAD_DEG)), radius / (cos(maxDec*RAD_DEG)));
+    minRa = Ra - rad;
+    maxRa = Ra + rad;
+  }
+  
+  /* use the pole regions, if near pole */
+  if (maxDec > 86.25) {
+    sprintf (regions[nregion].name, "n8230/pole.cpt");
+    regions[nregion].RA0 = 0;
+    regions[nregion].RA1 = 360;
+    regions[nregion].DEC0 = 86.25;
+    regions[nregion].DEC1 = 90.0;
+    nregion ++;
+    if (nregion == NREGIONS) {
+      NREGIONS += 50;
+      REALLOCATE (regions, RegionFile, NREGIONS);
+    }
+  }
+
+  if (minDec > 86.25) {
+    return (regions);
+  }
+    
+  if ((minDec < 0) && (maxDec > 0)) {
+    /* Search Both Sides */
+    NBigDec = 0;
+  } else {
+    /* find large DEC region (directory) */
+    NBigDec = -1;
+    for (i = 0; i < 12; i++) {
+      if ((minDec >= BigDecBounds[i]) && (minDec < BigDecBounds[i+1])) {
+	NBigDec = i;
+	break;
+      }
+    }
+    if (NBigDec < 0) {
+      for (i = 13; i < 24; i++) {
+	if ((maxDec < BigDecBounds[i]) && (maxDec >= BigDecBounds[i+1])) {
+	  NBigDec = i;
+	  break;
+	}
+      }
+    }
+  }
+  if (NBigDec < 0) {
+    fprintf (stderr, "ERROR: Dec out of range: %f\n", minDec);
+    *Nregions = 0;
+    return ((RegionFile *) NULL);
+  }
+  
+  /* count lines before section */
+  NLINES = 0;
+  for (i = 0; i < NBigDec; i++) {
+    NLINES += NDecLines[i];
+  }
+  fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+  
+  /* should be in this section.  if not, there is a problem counting... */
+  /* careful with the 0,360.0 boundary **/
+  done = FALSE;
+  for (j = 0; !done && (NBigDec + j < 25); j++) {
+    fread (buffer, 48*NDecLines[NBigDec + j], 1, f);
+    for (i = 0; (i < NDecLines[NBigDec + j]); i++) {
+      strncpy (temp, &buffer[i*48], 48);
+      temp[49] = 0;
+      hstgsc_hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+      if (RA1 < RA0) RA1 += 360.0;
+      if ((DEC1 > 0) && (minDec < DEC1) && (maxDec > DEC0) && (minRa < RA1) && (maxRa > RA0)) {
+	temp[5] = 0;
+	sprintf (regions[nregion].name, "%s/%s.cpt", Dec2Sections[NBigDec + j], &temp[1]);
+	regions[nregion].RA0 = RA0;
+	regions[nregion].RA1 = RA1;
+	regions[nregion].DEC0 = DEC0;
+	regions[nregion].DEC1 = DEC1;
+	nregion ++;
+	if (nregion == NREGIONS) {
+	  NREGIONS += 50;
+	  REALLOCATE (regions, RegionFile, NREGIONS);
+	}
+      }
+      if ((DEC1 < 0) && (minDec < DEC0) && (maxDec > DEC1) && (minRa < RA1) && (maxRa > RA0)) {
+	temp[5] = 0;
+	sprintf (regions[nregion].name, "%s/%s.cpt", Dec2Sections[NBigDec + j], &temp[1]);
+	regions[nregion].RA0 = RA0;
+	regions[nregion].RA1 = RA1;
+	regions[nregion].DEC0 = DEC0;
+	regions[nregion].DEC1 = DEC1;
+	nregion ++;
+	if (nregion == NREGIONS) {
+	  NREGIONS += 50;
+	  REALLOCATE (regions, RegionFile, NREGIONS);
+	}
+      }
+      if (((DEC1 > 0) && (maxDec <= DEC1)) || ((DEC1 < 0) && (minDec >= DEC1))) {
+	done = TRUE;
+      }
+    }
+    if (done && (minDec < 0) && (maxDec > 0) && (BigDecBounds[NBigDec + j + 1] > 0)) {
+      /* skip remaining north sections, try south sections */
+      /* count lines before section */
+      NLINES = 0;
+      for (i = 0; i < 13; i++) { 
+	NLINES += NDecLines[i];
+      }
+      fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+      done = FALSE;
+      j = 12;
+    }
+  }
+
+  REALLOCATE (regions, RegionFile, MAX(1,nregion));
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (regions);
+  
+}
Index: /tags/start/Ohana/src/opihi/dvo/gcat.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/gcat.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/gcat.c	(revision 12606)
@@ -0,0 +1,42 @@
+# include "dvo.h"
+
+int gcat (int argc, char **argv) {
+  
+  int i, Nregions;
+  RegionFile *regions;
+  char filename[128];
+  struct stat filestat;
+  double Ra, Dec, Radius;
+  char catdir[256];
+
+  VarConfig ("CATDIR", "%s", catdir);
+
+  if ((argc != 3) && (argc != 4)) {
+    fprintf (stderr, "USAGE: gcat RA DEC [Radius]\n");
+    return (FALSE);
+  }
+
+  Ra = atof (argv[1]);
+  Dec = atof (argv[2]);
+  if (argc == 4) 
+    Radius = atof(argv[3]);
+  else 
+    Radius = 0.0001;
+
+  regions = find_regions (Ra, Dec, Radius, &Nregions);
+
+  for (i = 0; i < Nregions; i++) {
+    sprintf (filename, "%s/%s", catdir, regions[i].name);
+    if (stat (filename, &filestat) != -1) {
+      fprintf (stderr, "%3d %s *\n", i, regions[i].name);
+    } else {
+      fprintf (stderr, "%3d %s\n", i, regions[i].name);
+    } 
+    set_str_variable ("CATNAME", regions[i].name);
+  }
+
+  return (TRUE);
+  free (regions);
+
+}
+
Index: /tags/start/Ohana/src/opihi/dvo/get_regions.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/get_regions.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/get_regions.c	(revision 12606)
@@ -0,0 +1,50 @@
+# include "dvo.h"
+
+/* return region files containing given image */
+GSCRegion *get_regions (Image *image, int *Nregions) {
+  
+  GSCRegion *region;
+  FILE *f;
+  double x, y;
+  double dec, ra;
+  int j, done, nregion, NREGION;
+  char filename[256], path[256];
+  
+  VarConfig ("CATDIR", "%s", path);
+  VarConfig ("GSCFILE", "%s", filename);
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find GSC region file %s\n", filename);
+    exit (0);
+  }
+  
+  /* find regions at image corners */
+  NREGION = 10;
+  ALLOCATE (region, GSCRegion, NREGION);
+  nregion = 0;
+
+  /* look for new regions on grid across image */ 
+  for (x = 0.0; x <= 1.0; x+=0.25) {
+    for (y = 0.0; y <= 1.0; y+=0.25) {
+      XY_to_RD (&ra, &dec, image[0].NX*(1.1*x - 0.05), image[0].NY*(1.1*y - 0.05), &image[0].coords);
+      aregion (&region[nregion], f, ra, dec, path);
+      done = FALSE;
+      for (j = 0; (j < nregion) && !done; j++) {
+	if (!strcmp (region[nregion].filename, region[j].filename)) {
+	  nregion --;
+	  done = TRUE;
+	}
+      }
+      nregion ++;
+      if (nregion == NREGION) {
+	NREGION += 10;
+	REALLOCATE (region, GSCRegion, NREGION);
+      }
+    }
+  }
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (region);
+  
+}
Index: /tags/start/Ohana/src/opihi/dvo/getxtra.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/getxtra.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/getxtra.c	(revision 12606)
@@ -0,0 +1,63 @@
+# include "dvo.h"
+
+int getxtra (int argc, char **argv) {
+  
+  SelectXtra = (char *) NULL;
+  if (N = get_argument (argc, argv, "-xtra")) {
+    SelectXtra = TRUE;
+    remove_argument (N, &argc, argv);
+    XtraType = strcreate (atof[N]);
+    remove_argument (N, &argc, argv);
+    XtraValue = strcreate (atof[N]);
+    remove_argument (N, &argc, argv);
+  }
+  SelectRegion = (char *) NULL;
+  if (N = get_argument (argc, argv, "-region")) {
+    SelectRegion = TRUE;
+    remove_argument (N, &argc, argv);
+    RA = atof (atof[N]);
+    remove_argument (N, &argc, argv);
+    Dec = atof (atof[N]);
+    remove_argument (N, &argc, argv);
+    Radius = atof (atof[N]);
+    remove_argument (N, &argc, argv);
+  }
+  Mode = (char *) NULL;
+  if (N = get_argument (argc, argv, "-mode")) {
+    remove_argument (N, &argc, argv);
+    Mode = strcreate (atof[N]);
+    remove_argument (N, &argc, argv);
+  }
+  Range = (char *) NULL;
+  if (N = get_argument (argc, argv, "-range")) {
+    remove_argument (N, &argc, argv);
+    Range = strcreate (atof[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 6) {
+    fprintf (stderr, "USAGE: addxtra R D radius (type) (value)\n");
+    return (FALSE);
+  }
+  
+  
+
+  /*
+
+  validate the input values (type, defines the needed options)
+  find catalog (based on r,d)
+  load catalog (need to load measures?)
+  find the object
+  find the xtra entry (sorted by ra/dec? sorted by averef?)
+  add new entry
+  save catalog 
+  */
+}
+
+/* 
+   get specified values for specified objects 
+
+   getxtra type -xtra name K01.01 
+   getxtra type -region R D radius 
+
+*/
Index: /tags/start/Ohana/src/opihi/dvo/gimages.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/gimages.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/gimages.c	(revision 12606)
@@ -0,0 +1,127 @@
+# include "dvo.h"
+
+int gimages (int argc, char **argv) {
+  
+  int i, j, N, Nimage, Nfound, *subset, Nsubset, status;
+  double ra, dec, Ra, Dec, X, Y, Mcal;
+  double trange, t;
+  int TimeSelect, PixelCoords, TimeFormat, PhotCodeSelect;
+  time_t tzero, TimeReference;
+  char name[64], *date;
+
+  PhotCode *code;
+  Image *image;
+
+  if (!InitPhotcodes ()) return (FALSE);
+
+  GetTimeFormat (&TimeReference, &TimeFormat);
+
+  TimeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-time")) {
+    remove_argument (N, &argc, argv);
+    if (!str_to_time (argv[N], &tzero)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!str_to_dtime (argv[N], &trange)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    TimeSelect = TRUE;
+  }
+  if (N = get_argument (argc, argv, "-tref")) {
+    remove_argument (N, &argc, argv);
+    TimeSelect = TRUE;
+
+    t = atof (argv[N]);
+    tzero = TimeRef (t, TimeReference, TimeFormat);
+    remove_argument (N, &argc, argv);
+
+    if (!str_to_dtime (argv[N], &trange)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  PhotCodeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-photcode")) {
+    remove_argument (N, &argc, argv);
+    if ((code = GetPhotcodebyName (argv[N])) == NULL) {
+      fprintf (stderr, "ERROR: photcode not found in photcode table\n");
+      return (FALSE);
+    }
+    PhotCodeSelect = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  PixelCoords = FALSE;
+  if (N = get_argument (argc, argv, "-pix")) {
+    remove_argument (N, &argc, argv);
+    PixelCoords = TRUE;
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: gimages RA DEC [-time t dt] [-pix]\n");
+    return (FALSE);
+  }
+
+  if (!str_to_radec (&Ra, &Dec, argv[1], argv[2])) return (FALSE);
+
+  image = LoadImages (&Nimage);
+  if (Nimage == 0) {
+    return (FALSE);
+  }
+  image_subset (image, Nimage, &subset, &Nsubset, (Graphdata *) NULL, FALSE, tzero, trange, TimeSelect);
+
+  Nfound = 0;
+  for (j = 0; j < Nsubset; j++) {
+    i = subset[j];
+    status = RD_to_XY (&X, &Y, Ra, Dec, &image[i].coords);
+    if (!status || (X < 0) || (X > image[i].NX) || (Y < 0) || (Y > image[i].NY)) continue;
+    XY_to_RD (&ra, &dec, 0.5*image[i].NX, 0.5*image[i].NY, &image[i].coords);
+    Mcal = applyMcal (&image[i], 2048.0, 2048.0);
+    /* t = TimeValue (image[i].tzero, TimeReference, TimeFormat); */
+    date = sec_to_date (image[i].tzero);
+    if (PhotCodeSelect) {
+      if ((code[0].type == PHOT_REF) || (code[0].type == PHOT_DEP)) {
+	if (code[0].code != image[i].source) continue;
+      } 
+      if ((code[0].type == PHOT_PRI) || (code[0].type == PHOT_SEC)) {
+	if (code[0].code != GetPhotcodeEquivCodebyCode (image[i].source)) continue;
+      } 
+    }      
+    if (PixelCoords) {
+      fprintf (GetOutfile(), "%3d %s %6.1f %6.1f %20s %5d %2d %4.2f %6.3f %5.3f %5.3f %4x\n", 
+	       Nfound, image[i].name, X, Y, date, image[i].nstar, image[i].source, 0.001*image[i].secz, 0.001*Mcal, 0.001*image[i].dMcal, image[i].exptime, image[i].code);
+    } else {
+      fprintf (GetOutfile(), "%3d %s %8.4f %8.4f %20s %5d %2d %4.2f %6.3f %5.3f %5.3f %4x\n", 
+	       Nfound, image[i].name, ra, dec, date, image[i].nstar, image[i].source, 0.001*image[i].secz, 0.001*Mcal, 0.001*image[i].dMcal, image[i].exptime, image[i].code);
+    }
+    sprintf (name, "IMAGEx:%d", Nfound);
+    set_variable     (name, X);
+    sprintf (name, "IMAGEy:%d", Nfound);
+    set_variable     (name, Y);
+    sprintf (name, "IMAGEt:%d", Nfound);
+    set_str_variable (name, date);
+    sprintf (name, "IMAGEccd:%d", Nfound);
+    set_int_variable (name, image[i].ccdnum);
+    sprintf (name, "IMAGEname:%d", Nfound);
+    set_str_variable (name, image[i].name);
+    Nfound ++;
+    free (date);
+  }
+  set_int_variable ("IMAGEx:n", Nfound);
+  set_int_variable ("IMAGEy:n", Nfound);
+  set_int_variable ("IMAGEt:n", Nfound);
+  set_int_variable ("IMAGEccd:n", Nfound);
+  set_int_variable ("IMAGEname:n", Nfound);
+
+  free (image);
+  free (subset);
+
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/dvo/gstar.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/gstar.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/gstar.c	(revision 12606)
@@ -0,0 +1,213 @@
+# include "dvo.h"
+
+void print_value (FILE *f, double value, short int ival);
+
+int gstar (int argc, char **argv) {
+  
+  char filename[128], catdir[256], *date;
+  double Ra, Dec, Radius, Radius2, r, dec0, dec1;
+  double t, Mcat, Mrel;
+  float *RA, *DEC;
+  int i, j, k, m, N, *N1, Nregions, Nsec, NPTS;
+  int Nstars, found, GetMeasures, Nlo, Nhi;
+  int SaveVectors;
+  Vector *vec1, *vec2, *vec3, *vec4;
+  RegionFile *regions;
+  Catalog catalog;
+  PhotCode *code;
+
+  VarConfig ("CATDIR", "%s", catdir);
+  if (!InitPhotcodes ()) return (FALSE);
+  Nsec = GetPhotcodeNsecfilt ();
+
+  SaveVectors = FALSE;
+  if (N = get_argument (argc, argv, "-save")) {
+    remove_argument (N, &argc, argv);
+    SaveVectors = TRUE;
+    if ((vec1 = SelectVector ("gs:m", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    if ((vec2 = SelectVector ("gs:t", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    if ((vec3 = SelectVector ("gs:z", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    if ((vec4 = SelectVector ("gs:f", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  }
+
+  GetMeasures = FALSE;
+  if (N = get_argument (argc, argv, "-m")) {
+    GetMeasures = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: gstar RA DEC Radius [-m]\n");
+    return (FALSE);
+  }
+  
+  Ra = atof (argv[1]);
+  Dec = atof (argv[2]);
+  Radius = atof (argv[3]);
+
+  while (Ra < 0.0) Ra += 360.0;
+  while (Ra > 360.0) Ra -= 360.0;
+  
+  regions = find_regions (Ra, Dec, Radius, &Nregions);
+
+  if (Nregions > 1) {
+    fprintf (stderr, "warning, radius overlaps region boundary, not yet implemented\n");
+  }
+
+  /* set filename, read in header */
+  sprintf (filename, "%s/%s", catdir, regions[0].name);
+  /* lock, load, unlock catalog */
+  catalog.filename = filename;
+  switch (lock_catalog (&catalog, LCK_SOFT)) {
+  case 2:
+    unlock_catalog (&catalog);
+  case 0:
+    return (FALSE);
+  }
+  if (!load_catalog (&catalog, LOAD_AVES | LOAD_MEAS | LOAD_SECF, TRUE)) {
+    unlock_catalog (&catalog);
+    return (FALSE);
+  }
+  unlock_catalog (&catalog);
+
+  Nstars = catalog.Naverage;
+  ALLOCATE (RA, float, Nstars);
+  ALLOCATE (DEC, float, Nstars);
+  ALLOCATE (N1, int, Nstars);
+
+  /* find star(s) in RA, DEC list -- use a dumb algorithm for now, improve later */
+  /* stars are not guaranteed to be sorted in RA or in DEC, so first sort the list */
+  for (i = 0; i < Nstars; i++) {
+    RA[i] = catalog.average[i].R;
+    DEC[i] = catalog.average[i].D;
+    N1[i] = i;
+  }
+  /* sort list by DEC */
+  if (Nstars > 1) sort_lists (DEC, RA, N1, Nstars);
+  /* at this point, RA, DEC, and N1 are sorted by DEC.  
+     catalog.average[N1[i]].R = RA[i] */
+
+  /* bracket the RA range of interest */
+  dec0 = Dec - Radius;
+  dec1 = Dec + Radius;
+
+  Nlo = 0; Nhi = catalog.Naverage;
+  while (Nhi - Nlo > 10) {
+    N = 0.5*(Nlo + Nhi);
+    if (DEC[N] < dec0) {
+      Nlo = N;
+    } else {
+      Nhi = N + 1;
+    }
+  }
+  /* DEC[Nlo] is guaranteed to be just lower than dec0 */
+
+  Radius2 = Radius*Radius;
+  found = FALSE;
+
+  /* data has been loaded, get ready to plot it */
+  if (SaveVectors) {
+    N = 0;
+    NPTS = 1000;
+    ALLOCATE (vec1[0].elements, float, NPTS);
+    ALLOCATE (vec2[0].elements, float, NPTS);
+    ALLOCATE (vec3[0].elements, float, NPTS);
+    ALLOCATE (vec4[0].elements, float, NPTS);
+  }
+
+  for (i = Nlo; (i < catalog.Naverage) && !found; i++) {
+
+    if (dec0 > DEC[i]) continue;
+    if (dec1 < DEC[i]) found = TRUE;
+    
+    r = SQ(Dec - DEC[i]) + SQ(Ra - RA[i]);
+    if (r < Radius2) {
+      k = N1[i];
+      fprintf (GetOutfile(), "star: %d\n", k);
+      fprintf (GetOutfile(), "%9.5f %9.5f %3d of %3d  %4.1f %5d\n", catalog.average[k].R, catalog.average[k].D, 
+	       catalog.average[k].Nm, catalog.average[k].Nn + catalog.average[k].Nm,
+	       0.01*catalog.average[k].Xp, catalog.average[k].code);
+      
+      /* filter names -- primary code is 0 in this function */
+      for (j = 0; j < Nsec + 1; j++) {
+	code = GetPhotcodebyNsec (j);
+	fprintf (GetOutfile (), "%s ", code[0].name);
+      }
+      fprintf (GetOutfile (), "\n");
+
+      /* average mags */
+      print_value (GetOutfile(), 0.001*catalog.average[k].M, catalog.average[k].M);
+      for (j = 0; j < Nsec; j++) print_value (GetOutfile(), 0.001*catalog.secfilt[j + Nsec*k].M, catalog.secfilt[j + Nsec*k].M);
+      fprintf (GetOutfile(), "\n");
+
+      /* average mag errors */
+      print_value (GetOutfile(), 0.001*catalog.average[k].dM, catalog.average[k].dM);
+      for (j = 0; j < Nsec; j++) print_value (GetOutfile(), 0.001*catalog.secfilt[j + Nsec*k].dM, catalog.secfilt[j + Nsec*k].dM);
+      fprintf (GetOutfile(), "\n");
+
+      /* average mag chisq */
+      print_value (GetOutfile(), pow (10.0, 0.01*catalog.average[k].Xm), catalog.average[k].Xm);
+      for (j = 0; j < Nsec; j++) print_value (GetOutfile(), pow (10.0, 0.01*catalog.secfilt[j + Nsec*k].Xm), catalog.secfilt[j + Nsec*k].Xm);
+      fprintf (GetOutfile(), "\n");
+
+      if (GetMeasures || SaveVectors) {
+	m = catalog.average[k].offset;
+	for (j = 0; j < catalog.average[k].Nm; j++, m++) {
+
+	  Mcat = PhotCat (&catalog.measure[m]);
+	  Mrel = PhotRel (&catalog.measure[m], &catalog.average[k], &catalog.secfilt[k*Nsec]);
+
+	  if (GetMeasures) {
+	    date = sec_to_date (catalog.measure[m].t);
+	    fprintf (GetOutfile(), "%6.3f %6.3f %5.3f  %20s  %5.2f %5.2f %2d %3x %3d %-20s\n", 
+		     Mcat, Mrel, 0.001*catalog.measure[m].dM,
+		     date, 0.01*catalog.measure[m].dR, 0.01*catalog.measure[m].dD,
+		     catalog.measure[m].dophot, catalog.measure[m].flags,
+		     catalog.measure[m].source, GetPhotcodeNamebyCode (catalog.measure[m].source));
+	    free (date);
+	  }
+	  
+	  if (SaveVectors) {
+	    vec1[0].elements[N] = Mcat;
+	    vec2[0].elements[N] = t;
+	    vec3[0].elements[N] = 0.001*catalog.measure[m].airmass;
+	    vec4[0].elements[N] = catalog.measure[m].source;
+	    N ++;
+	    if (N == NPTS - 1) {
+	      NPTS += 2000;
+	      REALLOCATE (vec1[0].elements, float, NPTS);
+	      REALLOCATE (vec2[0].elements, float, NPTS);
+	      REALLOCATE (vec3[0].elements, float, NPTS);
+	      REALLOCATE (vec4[0].elements, float, NPTS);
+	    }
+	  }
+	}
+      }
+    }
+  }
+
+  if (SaveVectors) {
+    vec1[0].Nelements = N;
+    vec2[0].Nelements = N;
+    vec3[0].Nelements = N;
+    vec4[0].Nelements = N;
+  }
+
+  free (RA);
+  free (DEC);
+  free (N1);
+  if (catalog.average != 0) free (catalog.average);
+  if (catalog.measure != 0) free (catalog.measure);
+  if (catalog.secfilt != 0) free (catalog.secfilt);
+
+  return (TRUE);
+
+}
+
+
+void print_value (FILE *f, double value, short int ival) {
+  if (ival == NO_MAG) 
+    fprintf (f, "NaN    ");
+  else 
+    fprintf (f, "%6.3f ", value);
+}
Index: /tags/start/Ohana/src/opihi/dvo/images.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/images.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/images.c	(revision 12606)
@@ -0,0 +1,156 @@
+# include "dvo.h"
+
+int images (int argc, char **argv) {
+
+  int i, j, Nimage, status, InPic, leftside, *plist, TimeSelect, ByName;
+  time_t tzero, tend;
+  int N, NPTS, n, npts;
+  Vector Xvec, Yvec;
+  double r, d, x[4], y[4], Rmin, Rmax, Rmid, trange;
+  Image *image;
+  Graphdata graphmode;
+  char name[256];
+  int Ngraph;
+
+  Ngraph = 0;
+  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);
+
+  ByName = FALSE;
+  if (N = get_argument (argc, argv, "-name")) {
+    remove_argument (N, &argc, argv);
+    strcpy (name, argv[N]);
+    remove_argument (N, &argc, argv);
+    ByName = TRUE;
+  }
+
+  TimeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-time")) {
+    remove_argument (N, &argc, argv);
+    if (!str_to_time (argv[N], &tzero)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!str_to_dtime (argv[N], &trange)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (trange < 0) {
+      trange = fabs (trange);
+      tzero -= trange;
+    }
+    TimeSelect = TRUE;
+  }
+  if (N = get_argument (argc, argv, "-trange")) {
+    remove_argument (N, &argc, argv);
+    if (!str_to_time (argv[N], &tzero)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!str_to_time (argv[N], &tend)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    trange = tend - tzero;
+    if (trange < 0) {
+      trange = fabs (trange);
+      tzero -= trange;
+    }
+    TimeSelect = TRUE;
+  }
+ 
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: image [-time start range]\n");
+    return (FALSE);
+  }
+  
+  image = LoadImages (&Nimage);
+  if (Nimage == 0) {
+    return (TRUE);
+  }
+
+  Rmin = graphmode.coords.crval1 - 180.0;
+  Rmax = graphmode.coords.crval1 + 180.0;
+  Rmid = 0.5*(Rmin + Rmax);
+  
+  npts = NPTS = 200;
+  ALLOCATE (Xvec.elements, float, NPTS);
+  ALLOCATE (Yvec.elements, float, NPTS);
+  ALLOCATE (plist, int, NPTS);
+  n = N = 0;
+  for (i = 0; i < Nimage; i++) {
+    if (ByName && strcmp (name, image[i].name)) continue;
+    if (TimeSelect && ((image[i].tzero < tzero) || (image[i].tzero+image[i].trate*image[i].NY > tzero + trange))) continue;
+    /* project this image to screen display coords */
+    x[0] = 0;           y[0] = 0;
+    x[1] = image[i].NX; y[1] = 0;
+    x[2] = image[i].NX; y[2] = image[i].NY;
+    x[3] = 0;           y[3] = image[i].NY;
+    status = FALSE;
+
+    leftside = FALSE;
+    for (j = 0; j < 4; j++) {
+      XY_to_RD (&r, &d, x[j], y[j], &image[i].coords);
+      while (r < Rmin) { r += 360.0; }
+      while (r > Rmax) { r -= 360.0; }
+      if (j == 0) {
+	leftside = (r < Rmid);
+      } 
+      if (j > 0) { 
+	if ( leftside && (r > Rmid + 90)) { r -= 360.0; }
+	if (!leftside && (r < Rmid - 90)) { r += 360.0; }
+      }
+      status |= fRD_to_XY (&Xvec.elements[N+2*j], &Yvec.elements[N+2*j], r, d, &graphmode.coords);
+      if (j > 0) {
+	Xvec.elements[N+2*j - 1] = Xvec.elements[N+2*j];
+	Yvec.elements[N+2*j - 1] = Yvec.elements[N+2*j];
+      }
+    }
+    Xvec.elements[N+7] = Xvec.elements[N];
+    Yvec.elements[N+7] = Yvec.elements[N];
+    InPic = FALSE;
+    for (j = 0; j < 8; j+=2) {
+      if ((Xvec.elements[N+j] >= graphmode.xmin) && 
+	  (Xvec.elements[N+j] <= graphmode.xmax) && 
+	  (Yvec.elements[N+j] >= graphmode.ymin) && 
+	  (Yvec.elements[N+j] <= graphmode.ymax))
+	InPic = TRUE;
+    }
+    if (InPic && status) {
+      plist[n] = i;
+      n++;
+      if (n > npts - 1) {
+	npts += 200;
+	REALLOCATE (plist, int, npts);
+      }
+      N+=8;
+      if (N > NPTS - 1) {  /* this is OK because NPTS is made always a multiple of 8 */
+	NPTS += 200;
+	REALLOCATE (Xvec.elements, float, NPTS);
+	REALLOCATE (Yvec.elements, float, NPTS);
+      }
+    }
+  }
+
+  fprintf (stderr, "plotting %d images\n", N/8);
+  Xvec.Nelements = Xvec.Nelements = N;
+  if (N > 0) {
+    graphmode.style = 2; /* points */
+    graphmode.ptype = 100; /* connect pairs of points */
+    graphmode.etype = 0;
+    PrepPlotting (N, &graphmode);
+    PlotVector (N, Xvec.elements);
+    PlotVector (N, Yvec.elements);
+  }
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+  free (image);
+  return (TRUE);
+
+}
+
+
Index: /tags/start/Ohana/src/opihi/dvo/imbox.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/imbox.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/imbox.c	(revision 12606)
@@ -0,0 +1,95 @@
+# include "dvo.h"
+
+int imbox (int argc, char **argv) {
+  
+  int i, j, status, InPic, flipped, Nextend;
+  Vector Xvec, Yvec;
+  double r, d, x[4], y[4], Rmin, Rmax, Rmid;
+  Header header;
+  Coords coords;
+  Graphdata graphmode;
+  int Ngraph;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: imbox (filename)\n");
+    return (FALSE);
+  }
+  Ngraph = 0;
+  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);
+
+  if (!fits_read_header (argv[1], &header)) {
+    fprintf (stderr, "file not found\n");
+    return (FALSE);
+  }
+  
+  Nextend = 0;
+  if (header.Naxes == 0) {
+    fits_scan (&header, "NEXTEND", "%d", 1, &Nextend);
+  }
+  
+  Rmin = graphmode.coords.crval1 - 182.0;
+  Rmax = graphmode.coords.crval1 + 182.0;
+  Rmid = 0.5*(Rmin + Rmax);
+  
+  /* project this image to screen display coords */
+  ALLOCATE (Xvec.elements, float, 8);
+  ALLOCATE (Yvec.elements, float, 8);
+
+  for (i = Nextend ? 0 : -1; i < Nextend; i++) {
+    if (Nextend) {
+      fits_read_Xheader (argv[1], &header, i);
+    }
+    if (!GetCoords (&coords, &header)) {
+      fprintf (stderr, "can't get WCS info from header\n");
+      return (TRUE);
+    }
+    x[0] = 0;               y[0] = 0;
+    x[1] = header.Naxis[0]; y[1] = 0;
+    x[2] = header.Naxis[0]; y[2] = header.Naxis[1];
+    x[3] = 0;               y[3] = header.Naxis[1];
+    status = FALSE;
+    flipped = FALSE;
+    for (j = 0; j < 4; j++) {
+      XY_to_RD (&r, &d, x[j], y[j], &coords);
+      while ((j == 0) && (r < Rmin)) { flipped = TRUE; r += 360.0; }
+      while ((j == 0) && (r > Rmax)) { flipped = TRUE; r -= 360.0; }
+      if ((j > 0) && flipped) {
+	while (r < Rmid) r+= 360.0;
+	while (r > Rmid) r-= 360.0;
+      }
+      status |= fRD_to_XY (&Xvec.elements[2*j], &Yvec.elements[2*j], r, d, &graphmode.coords);
+      if (j > 0) {
+	Xvec.elements[2*j - 1] = Xvec.elements[2*j];
+	Yvec.elements[2*j - 1] = Yvec.elements[2*j];
+      }
+    }
+    Xvec.elements[7] = Xvec.elements[0];
+    Yvec.elements[7] = Yvec.elements[0];
+    InPic = FALSE;
+    for (j = 0; j < 8; j+=2) {
+      if ((Xvec.elements[j] >= graphmode.xmin) && 
+	  (Xvec.elements[j] <= graphmode.xmax) && 
+	  (Yvec.elements[j] >= graphmode.ymin) && 
+	  (Yvec.elements[j] <= graphmode.ymax))
+	InPic = TRUE;
+    }
+
+    Xvec.Nelements = Xvec.Nelements = 8;
+    if (InPic) {
+      graphmode.style = 2; /* points */
+      graphmode.ptype = 100; /* connect pairs of points */
+      graphmode.etype = 0;
+      PrepPlotting (8, &graphmode);
+      PlotVector (8, Xvec.elements);
+      PlotVector (8, Yvec.elements);
+    }
+  }
+
+  fits_free_header (&header);
+  free (Xvec.elements);
+  free (Yvec.elements);
+  return (TRUE);
+
+}
+
+
Index: /tags/start/Ohana/src/opihi/dvo/imdata.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/imdata.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/imdata.c	(revision 12606)
@@ -0,0 +1,245 @@
+# include "dvo.h"
+void copy_region (GSCRegion *in, GSCRegion *out);
+
+int imdata (int argc, char **argv) {
+  
+  int i, j, k;
+  int Nimage, N, NPTS, skip, mode, TimeSelect;
+  int n, Nregion, Ntregion, TimeFormat;
+  int *subset, Nsubset;
+  char filename[256];
+  double trange;
+  unsigned long tzero, start, stop, TimeReference;
+  Image *image;
+  Catalog catalog;
+  GSCRegion *region, *tregion;
+  Vector *vec;
+
+  TimeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-time")) {
+    remove_argument (N, &argc, argv);
+    if (!str_to_time (argv[N], &tzero)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!str_to_dtime (argv[N], &trange)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    TimeSelect = TRUE;
+    fprintf (stderr, "searching in range %ds - %ds (%f seconds)\n", (int)tzero, (int)(tzero + trange), trange);
+    if (trange > 0) {
+      start = tzero;
+      stop  = tzero + trange;
+    } else {
+      stop = tzero;
+      start  = tzero + trange;
+    }      
+  }
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: imdata (value) [-time t dt]\n");
+    return (FALSE);
+  }
+
+  /* identify selection */
+  mode = 0;
+  if (!strcasecmp (argv[1], "ra")) 
+    mode = 1;
+  if (!strcasecmp (argv[1], "dec")) 
+    mode = 2;
+  if (!strcasecmp (argv[1], "mag")) 
+    mode = 3;
+  if (!strcasecmp (argv[1], "dmag")) 
+    mode = 4;
+  if (!strcasecmp (argv[1], "Mcal")) 
+    mode = 5;
+  if (!strcasecmp (argv[1], "Mrel")) 
+    mode = 6;
+  if (!strcasecmp (argv[1], "source")) 
+    mode = 7;
+  if (!strcasecmp (argv[1], "x")) 
+    mode = 8;
+  if (!strcasecmp (argv[1], "y")) 
+    mode = 9;
+  if (!strcasecmp (argv[1], "time")) 
+    mode = 10;
+  if (mode == 0) {
+    fprintf (stderr, "value may be one of the following:\n");
+    fprintf (stderr, " ra dR dec dD mag dmag Mrel Mcal source time\n");
+    return (FALSE);
+  }
+  if ((vec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  image = LoadImages (&Nimage);
+  if (Nimage == 0) {
+    return (FALSE);
+  }
+  image_subset (image, Nimage, &subset, &Nsubset, (Graphdata *) NULL, FALSE, tzero, trange, TimeSelect);
+  GetTimeFormat (&TimeReference, &TimeFormat);
+
+  /* for each image of interest, find the appropriate region files */
+  Nregion = 0;
+  ALLOCATE (region, GSCRegion, 1);
+  for (i = 0; i < Nsubset; i++) {
+    tregion = get_regions (&image[subset[i]], &Ntregion);
+    REALLOCATE (region, GSCRegion, MAX (1, Nregion + Ntregion));
+    for (j = 0; j < Ntregion; j++) {
+      skip = FALSE;
+      for (k = 0; (k < Nregion) && !skip; k++) {
+	if (!strcmp (region[k].filename, tregion[j].filename)) skip = TRUE;
+      }
+      if (!skip) {
+	copy_region (&tregion[j], &region[Nregion]);
+	Nregion ++;
+      }
+    }
+    free (tregion);
+  }	
+  free (subset);
+  for (i = 0; i < Nregion; i++) {
+    fprintf (stderr, "try %s\n", region[i].filename);
+  } 
+  
+  /* create output vector */
+  NPTS = 1000;
+  REALLOCATE (vec[0].elements, float, NPTS);
+  vec[0].Nelements = N = 0;
+
+  /* for each region file, extract the data of interest in the right time range */
+  for (j = 0; j < Nregion; j++) {
+
+    /* get file name and open */
+    strcpy (filename, region[j].filename);
+    catalog.filename = filename;
+    switch (lock_catalog (&catalog, LCK_SOFT)) {
+    case 2:
+      unlock_catalog (&catalog);
+    case 0:
+      continue;
+    }
+    if (!load_catalog (&catalog, LOAD_AVES, TRUE)) {
+      unlock_catalog (&catalog);
+      continue;
+    }
+    unlock_catalog (&catalog);
+
+    /* assign vector values */
+    switch (mode) {
+    case (1):  /* ra */
+      for (i = 0; i < catalog.Nmeasure; i++) {
+	if ((catalog.measure[i].t < start) || (catalog.measure[i].t > stop)) continue;
+	n = catalog.measure[i].averef;
+	vec[0].elements[N] = catalog.average[n].R - catalog.measure[i].dR / 360000.0;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 1000;
+	  REALLOCATE (vec[0].elements, float, NPTS);
+	}
+      }
+      break;
+    case (2):  /* dec */
+      for (i = 0; i < catalog.Nmeasure; i++) {
+	if ((catalog.measure[i].t < start) || (catalog.measure[i].t > stop)) continue;
+	n = catalog.measure[i].averef;
+	vec[0].elements[N] = catalog.average[n].D - catalog.measure[i].dD / 360000.0;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 1000;
+	  REALLOCATE (vec[0].elements, float, NPTS);
+	}
+      }
+      break;
+    case (3):  /* mag */
+      for (i = 0; i < catalog.Nmeasure; i++) {
+	if ((catalog.measure[i].t < start) || (catalog.measure[i].t > stop)) continue;
+	vec[0].elements[N] = catalog.measure[i].M / 1000.0;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 1000;
+	  REALLOCATE (vec[0].elements, float, NPTS);
+	}
+      }
+      break;
+    case (4):  /* dmag */
+      for (i = 0; i < catalog.Nmeasure; i++) {
+	if ((catalog.measure[i].t < start) || (catalog.measure[i].t > stop)) continue;
+	vec[0].elements[N] = catalog.measure[i].dM / 1000.0;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 1000;
+	  REALLOCATE (vec[0].elements, float, NPTS);
+	}
+      }
+      break;
+    case (5):  /* Mcal */
+      for (i = 0; i < catalog.Nmeasure; i++) {
+	if ((catalog.measure[i].t < start) || (catalog.measure[i].t > stop)) continue;
+	vec[0].elements[N] = catalog.measure[i].Mcal / 1000.0;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 1000;
+	  REALLOCATE (vec[0].elements, float, NPTS);
+	}
+      }
+      break;
+    case (6):  /* Mrel */
+      for (i = 0; i < catalog.Nmeasure; i++) {
+	if ((catalog.measure[i].t < start) || (catalog.measure[i].t > stop)) continue;
+	n = catalog.measure[i].averef;
+	vec[0].elements[N] = catalog.average[n].M / 1000.0;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 1000;
+	  REALLOCATE (vec[0].elements, float, NPTS);
+	}
+      }
+      break;
+    case (7):  /* source */
+      for (i = 0; i < catalog.Nmeasure; i++) {
+	if ((catalog.measure[i].t < start) || (catalog.measure[i].t > stop)) continue;
+	vec[0].elements[N] = catalog.measure[i].source;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 1000;
+	  REALLOCATE (vec[0].elements, float, NPTS);
+	}
+      }
+      break;
+    case (10):  /* time */
+      for (i = 0; i < catalog.Nmeasure; i++) {
+	if ((catalog.measure[i].t < start) || (catalog.measure[i].t > stop)) continue;
+	vec[0].elements[N] = TimeValue (catalog.measure[i].t, TimeReference, TimeFormat);
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 1000;
+	  REALLOCATE (vec[0].elements, float, NPTS);
+	}
+      }
+      break;
+    }
+    if (catalog.average != 0) {
+      free (catalog.average);
+    }
+    if (catalog.measure != 0) {
+      free (catalog.measure);
+    }
+  }
+  
+  vec[0].Nelements = N;
+  REALLOCATE (vec[0].elements, float, MAX(1,N));
+  return (TRUE);
+}
+
+
+void copy_region (GSCRegion *in, GSCRegion *out) {
+    
+  out[0].RA[0]  = in[0].RA[0];
+  out[0].RA[1]  = in[0].RA[1];
+  out[0].DEC[0] = in[0].DEC[0];
+  out[0].DEC[1] = in[0].DEC[1];
+  strcpy (out[0].filename, in[0].filename);
+}
+
Index: /tags/start/Ohana/src/opihi/dvo/imdense.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/imdense.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/imdense.c	(revision 12606)
@@ -0,0 +1,77 @@
+# include "dvo.h"
+extern double drand48();
+
+int imdense (int argc, char **argv) {
+  
+  long A, B;
+  int i, N, Nimage, status, NPTS, Ngraph;
+  double r, d, x, y, Rmin, Rmax;
+  Vector Xvec, Yvec;
+  Image *image;
+  Graphdata graphmode;
+
+  /* need options to list only images in region and only images in a time range */
+  /* also, option to list and not plot or plot and not list images */
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: image\n");
+    return (FALSE);
+  }
+  Ngraph = 0;
+  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);
+
+  image = LoadImages (&Nimage);
+  if (Nimage == 0) {
+    return (FALSE);
+  }
+
+  Rmin = graphmode.coords.crval1 - 182.0;
+  Rmax = graphmode.coords.crval1 + 182.0;
+  
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+
+  NPTS = 200;
+  ALLOCATE (Xvec.elements, float, NPTS);
+  ALLOCATE (Yvec.elements, float, NPTS);
+  N = 0;
+  for (i = 0; i < Nimage; i++) {
+    /* choose a position for point within image box */
+    x = (0.1 + 0.9*drand48()) * image[i].NX;
+    y = (0.1 + 0.9*drand48()) * image[i].NY;
+    /* project this image to screen display coords */
+    status = FALSE;
+    XY_to_RD (&r, &d, x, y, &image[i].coords);
+    while (r < Rmin) r += 360.0; 
+    while (r > Rmax) r -= 360.0; 
+    status |= fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], r, d, &graphmode.coords);
+    if ((Xvec.elements[N] >= graphmode.xmin) && 
+	(Xvec.elements[N] <= graphmode.xmax) && 
+	(Yvec.elements[N] >= graphmode.ymin) && 
+	(Yvec.elements[N] <= graphmode.ymax) && status) {
+      N++;
+      if (N > NPTS - 1) { 
+	NPTS += 200;
+	REALLOCATE (Xvec.elements, float, NPTS);
+	REALLOCATE (Yvec.elements, float, NPTS);
+      }
+    }
+  }
+
+  Xvec.Nelements = Xvec.Nelements = N;
+  if (N > 0) {
+    graphmode.style = 2; /* points */
+    graphmode.etype = 0;
+    PrepPlotting (N, &graphmode);
+    PlotVector (N, Xvec.elements);
+    PlotVector (N, Yvec.elements);
+  }
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+  free (image);
+  return (TRUE);
+
+}
+
+
Index: /tags/start/Ohana/src/opihi/dvo/imextract.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/imextract.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/imextract.c	(revision 12606)
@@ -0,0 +1,185 @@
+# include "dvo.h"
+
+enum {ZERO, RA, DEC, Xm, AIRMASS, MCAL, dMCAL, PHOTCODE, TIME, FWHM, EXPTIME, NSTAR, SKY, NCAL, FLAG};
+
+int imextract (int argc, char **argv) {
+  
+  int i, j, Nimage, mode, N, Ngraph, PhotcodeSelect;
+  int TimeSelect, RegionSelect, *subset, Nsubset, TimeFormat, FlagSelect, FlagValue;
+  double x, y, ra, dec, t, trange;
+  time_t tzero, TimeReference;
+
+  PhotCode *code;
+  Graphdata graphsky;
+  Image *image;
+  Vector *vec;
+
+  Ngraph = 0;
+  if (!GetGraphData (&graphsky, NULL, &Ngraph)) return (FALSE);
+  if (!InitPhotcodes ()) return (FALSE);
+
+  /* check for time-based selection */
+  TimeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-time")) {
+    remove_argument (N, &argc, argv);
+    if (!str_to_time (argv[N], &tzero)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!str_to_dtime (argv[N], &trange)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    TimeSelect = TRUE;
+  }
+
+  /* check for region-based selection */
+  RegionSelect = FALSE;
+  if (N = get_argument (argc, argv, "-region")) {
+    remove_argument (N, &argc, argv);
+    RegionSelect = TRUE;
+  }
+
+  /* check for region-based selection */
+  FlagSelect = FALSE;
+  if (N = get_argument (argc, argv, "-flag")) {
+    remove_argument (N, &argc, argv);
+    FlagValue = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+    FlagSelect = TRUE;
+  }
+
+  /* check for photcode-based selection */
+  code = NULL;
+  PhotcodeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-photcode")) {
+    PhotcodeSelect = TRUE;
+    remove_argument (N, &argc, argv);
+    if ((code = GetPhotcodebyName (argv[N])) == NULL) {
+      fprintf (stderr, "ERROR: photcode %s not found in photcode table\n", argv[N]);
+      return (FALSE);
+    }
+    if ((code[0].type != PHOT_PRI) && (code[0].type != PHOT_SEC) && (code[0].type != PHOT_DEP)) {
+      fprintf (stderr, "photcode must be primary, secondary, or dependent code\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: imextract (value) [-region] [-time start range] [-photcode photcode]\n");
+    return (FALSE);
+  }
+  
+  /* identify selection */
+  mode = ZERO;
+  if (!strcasecmp (argv[1], "ra")) mode = RA;
+  if (!strcasecmp (argv[1], "dec")) mode = DEC;
+  if (!strcasecmp (argv[1], "Xm")) mode = Xm;
+  if (!strcasecmp (argv[1], "airmass")) mode = AIRMASS;
+  if (!strcasecmp (argv[1], "Mcal")) mode = MCAL;
+  if (!strcasecmp (argv[1], "dMcal")) mode = dMCAL;
+  if (!strcasecmp (argv[1], "photcode")) mode = PHOTCODE;
+  if (!strcasecmp (argv[1], "time")) mode = TIME;
+  if (!strcasecmp (argv[1], "FWHM")) mode = FWHM;
+  if (!strcasecmp (argv[1], "exptime")) mode = EXPTIME;
+  if (!strcasecmp (argv[1], "nstar")) mode = NSTAR;
+  if (!strcasecmp (argv[1], "ncal")) mode = NCAL;
+  if (!strcasecmp (argv[1], "sky")) mode = SKY;
+  if (!strcasecmp (argv[1], "flag")) mode = FLAG;
+  if (mode == ZERO) {
+    fprintf (stderr, "value may be one of the following:\n");
+    fprintf (stderr, " ra dec airmass Mcal dMcal Xm photcode time fwhm exptime nstar ncal sky flag\n");
+    return (FALSE);
+  }
+  if ((vec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  image = LoadImages (&Nimage);
+  if (Nimage == 0) {
+    return (FALSE);
+  }
+  image_subset (image, Nimage, &subset, &Nsubset, &graphsky, RegionSelect, tzero, trange, TimeSelect);
+
+  GetTimeFormat (&TimeReference, &TimeFormat);
+
+  /* create storage vector */
+  REALLOCATE (vec[0].elements, float, Nimage);
+  vec[0].Nelements = Nimage;
+  
+  N = 0;
+  /* assign vector values */
+  for (i = 0; i < Nsubset; i++) {
+    j = subset[i];
+    if (PhotcodeSelect) {
+      if (code[0].type == PHOT_DEP) {
+	if (code[0].code != image[j].source) continue;
+      } else {
+	if (code[0].code != GetPhotcodeEquivCodebyCode (image[j].source)) continue;
+      }
+    }
+    if (FlagSelect && (FlagValue != image[j].code)) continue;
+    switch (mode) {
+    case (RA):
+      x = 0.5*image[j].NX;
+      y = 0.5*image[j].NY;
+      XY_to_RD (&ra, &dec, x, y, &image[j].coords);
+      vec[0].elements[N] = ra;
+      break;
+    case (DEC):
+      x = 0.5*image[j].NX;
+      y = 0.5*image[j].NY;
+      XY_to_RD (&ra, &dec, x, y, &image[j].coords);
+      vec[0].elements[N] = dec;
+      break;
+    case (Xm):
+      vec[0].elements[N] = pow(10.0, 0.01*image[j].Xm);
+      break;
+    case (AIRMASS):
+      vec[0].elements[N] = 0.001*image[j].secz;
+      break;
+    case (MCAL):
+      vec[0].elements[N] = 0.001*image[j].Mcal;
+      break;
+    case (dMCAL):
+      vec[0].elements[N] = 0.001*image[j].dMcal;
+      break;
+    case (PHOTCODE):
+      vec[0].elements[N] = image[j].source;
+      break;
+    case (TIME):
+      t = image[j].tzero + 0.5*image[j].NY * image[j].trate / 10000;
+      vec[0].elements[N] = TimeValue (t, TimeReference, TimeFormat);
+      break;
+    case (FWHM):
+      vec[0].elements[N] = image[j].fwhm_x / 25.0;
+      break;
+    case (EXPTIME):
+      vec[0].elements[N] = image[j].exptime;
+      break;
+    case (NSTAR):
+      vec[0].elements[N] = image[j].nstar;
+      break;
+    case (NCAL):
+      vec[0].elements[N] = image[j].Mxxxx;
+      break;
+    case (SKY):
+      vec[0].elements[N] = image[j].Myyyy + 0x8000;
+      break;
+    case (FLAG):
+      vec[0].elements[N] = image[j].code;
+      break;
+    }
+    N++;
+  }
+  
+  vec[0].Nelements = N;
+  REALLOCATE (vec[0].elements, float, N);
+
+  free (subset);
+  free (image);
+  return (TRUE);
+  
+}
+  
Index: /tags/start/Ohana/src/opihi/dvo/imlist.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/imlist.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/imlist.c	(revision 12606)
@@ -0,0 +1,93 @@
+# include "dvo.h"
+
+int imlist (int argc, char **argv) {
+  
+  int i, j, N, Nimage, *subset, Nsubset, TimeSelect, RegionSelect, TimeFormat, NameSelect;
+  int PhotcodeSelect;
+  time_t tzero, TimeReference;
+  double r, d, trange, t;
+  char *name;
+  int Ngraph;
+  Image *image;
+  Graphdata graphmode;
+  PhotCode *PhotcodeValue;
+
+  Ngraph = 0;
+  if (!GetGraphData (&graphmode, NULL, &Ngraph)) return (FALSE);
+
+  TimeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-time")) {
+    remove_argument (N, &argc, argv);
+    if (!str_to_time (argv[N], &tzero)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!str_to_dtime (argv[N], &trange)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    TimeSelect = TRUE;
+    fprintf (stderr, "plotting in range %ds - %ds (%f seconds)\n", (int)tzero, (int)(tzero + trange), trange);
+  }
+
+  RegionSelect = FALSE;
+  if (N = get_argument (argc, argv, "-region")) {
+    remove_argument (N, &argc, argv);
+    RegionSelect = TRUE;
+  }
+
+  PhotcodeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-photcode")) {
+    PhotcodeSelect = TRUE;
+    remove_argument (N, &argc, argv);
+    PhotcodeValue = GetPhotcodebyName (argv[N]);
+    if (PhotcodeValue == NULL) {
+      fprintf (stderr, "photcode not found in photcode table\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  NameSelect = FALSE;
+  if (N = get_argument (argc, argv, "-name")) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    NameSelect = TRUE;
+  }
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: image [-time start range] [-region] [-name string]\n");
+    return (FALSE);
+  }
+  
+  image = LoadImages (&Nimage);
+  if (Nimage == 0) {
+    return (FALSE);
+  }
+  image_subset (image, Nimage, &subset, &Nsubset, &graphmode, RegionSelect, tzero, trange, TimeSelect);
+
+  GetTimeFormat (&TimeReference, &TimeFormat);
+
+  for (j = 0; j < Nsubset; j++) {
+    i = subset[j];
+    if (NameSelect && (strstr (image[i].name, name) == (char *) NULL)) continue;
+    if (PhotcodeSelect) {
+      if (PhotcodeValue[0].type == PHOT_DEP) {
+	if (PhotcodeValue[0].code != image[i].source) continue;
+      } else {
+	if (PhotcodeValue[0].code != GetPhotcodeEquivCodebyCode (image[i].source)) continue;
+      }
+    }
+    t = TimeValue (image[i].tzero, TimeReference, TimeFormat);
+    XY_to_RD (&r, &d, 0.5*image[i].NX, 0.5*image[i].NY, &image[i].coords);
+    fprintf (GetOutfile(), "%3d %s %8.4f %8.4f %f %5d %2d %4.2f %5.3f %5.3f\n", 
+	     i, image[i].name, r, d, t, image[i].nstar, image[i].source, 0.001*image[i].secz, 0.001*image[i].Mcal, 0.001*image[i].dMcal);
+  }
+
+  free (subset);
+  free (image);
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/dvo/imphot.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/imphot.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/imphot.c	(revision 12606)
@@ -0,0 +1,102 @@
+# include "dvo.h"
+
+int imphot (int argc, char **argv) {
+  
+  unsigned long int tzero;
+  double trange;
+  int N, GreyScale;
+  int i, j, Nimage, Nsubset, *subset;
+  char bufname[64];
+  float *p;
+  double fx, fy, x, y, applyMcal();
+  Image *image;
+  Buffer *buf;
+
+  GreyScale = FALSE;
+  if (N = get_argument (argc, argv, "-g")) {
+    remove_argument (N, &argc, argv);
+    strcpy (bufname, argv[N]);
+    remove_argument (N, &argc, argv);
+    GreyScale = TRUE;
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: imphot tzero trange [-g buffer]\n");
+    return (FALSE);
+  }
+
+  if (GreyScale) {
+    if ((buf = SelectBuffer (bufname, ANYBUFFER, TRUE)) == NULL) return (FALSE);
+    buf[0].header.simple   = TRUE;
+    buf[0].header.unsign   = FALSE;
+    buf[0].header.extend   = FALSE;
+    buf[0].header.bitpix   = -32;
+    buf[0].header.Naxes    = 2;
+    buf[0].header.Naxis[0] = 100;
+    buf[0].header.Naxis[1] = 200;
+    buf[0].header.bzero    = 0;
+    buf[0].header.bscale   = 1;
+    CreateBuffer (&buf[0]);
+  }
+
+  /* load image(s) in time range given */
+  if (!str_to_time (argv[1], &tzero)) { 
+    fprintf (stderr, "syntax error\n");
+    return (FALSE);
+  }
+  if (!str_to_dtime (argv[2], &trange)) { 
+    fprintf (stderr, "syntax error\n");
+    return (FALSE);
+  }    
+  fprintf (stderr, "searching in range %ds - %ds (%f seconds)\n", (int)tzero, (int)(tzero + trange), trange);
+  
+  image = LoadImages (&Nimage);
+  if (Nimage == 0) {
+    return (FALSE);
+  }
+  image_subset (image, Nimage, &subset, &Nsubset, (Graphdata *) NULL, FALSE, tzero, trange, TRUE);
+
+  if ((Nsubset > 1) && GreyScale) {
+    fprintf (stderr, "more than one image selected, making GreyScale of first only\n");
+  }
+
+  if (GreyScale && Nsubset) {
+    fx = image[subset[0]].NX / 100;
+    fy = image[subset[0]].NY / 200;
+    p = (float *) buf[0].matrix.buffer;
+    for (y = 0; y < 200; y+=1.0) {
+      for (x = 0; x < 100; x+=1.0, p++) {
+	*p = applyMcal (&image[subset[0]], (fx*x), (fy*y));
+      }
+    }
+  }
+
+  for (j = 0; j < Nsubset; j++) {
+    i = subset[j];
+    switch (image[i].order) {
+    case 0:
+      fprintf (stderr, "%s: %d - %d\n", image[i].name, image[i].order, image[i].Mcal);
+      break;
+    case 1:
+      fprintf (stderr, "%s: %d - %d, %d %d\n", image[i].name, image[i].order, image[i].Mcal, image[i].Mx, image[i].My);
+      break;
+    case 2:
+      fprintf (stderr, "%s: %d - %d, %d %d, %d %d %d\n", image[i].name, image[i].order, image[i].Mcal, image[i].Mx, image[i].My, image[i].Mxx, image[i].Mxy, image[i].Myy);
+      break;
+    case 3:
+      fprintf (stderr, "%s: %d - %d, %d %d, %d %d %d, %d %d %d %d\n", image[i].name, image[i].order, image[i].Mcal, image[i].Mx, image[i].My, 
+	       image[i].Mxx, image[i].Mxy, image[i].Myy, image[i].Mxxx, image[i].Mxxy, image[i].Mxyy, image[i].Myyy);
+      break;
+    case 4:
+      fprintf (stderr, "%s: %d - %d, %d %d, %d %d %d, %d %d %d %d, %d %d %d %d %d\n", image[i].name, image[i].order, image[i].Mcal, image[i].Mx, image[i].My, 
+	       image[i].Mxx, image[i].Mxy, image[i].Myy, image[i].Mxxx, image[i].Mxxy, image[i].Mxyy, image[i].Myyy,
+	       image[i].Mxxxx, image[i].Mxxxy, image[i].Mxxyy, image[i].Mxyyy, image[i].Myyyy);
+      break;
+    }
+  }
+
+  free (image);
+  free (subset);
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/dvo/imrough.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/imrough.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/imrough.c	(revision 12606)
@@ -0,0 +1,319 @@
+# include "dvo.h"
+RegImage *load_imreg (char *DataBase, int *nimage);
+
+# define NVALUE 22
+enum {V_NONE, V_EXPTIME, V_CCDN, V_SKY, V_BIAS, V_FILTER, V_FWHM, V_AIRM, V_TIME, V_TEMP0, V_TEMP1, V_TEMP2, V_TEMP3, V_TELFOCUS, V_XPROBE, V_YPROBE, V_ZPROBE, V_RA, V_DEC, V_DETTEMP, V_ROTANGLE, V_REGTIME};
+static char valuename[NVALUE][32] = {"none", "exptime", "ccd", "sky", "bias", "filter", "fwhm", "airmass", "time", "temp0", "temp1", "temp2", "temp3", "telfocus", "xprobe", "yprobe", "zprobe", "ra", "dec", "dettemp", "rotangle", "regtime"};
+
+# define NTYPE 9
+enum {T_NONE, T_OBJECT, T_DARK, T_BIAS, T_FLAT, T_MASK, T_FRINGE, T_SCATTER, T_MODES};
+static char typename[NTYPE][32] = {"none", "object", "dark", "bias", "flat", "mask", "fringe", "scatter", "modes"};
+
+# define NMODE 6
+enum {M_NONE, M_MEG, M_SPLIT, M_SINGLE, M_CUBE, M_SLICE};
+static char modename[NMODE][32] = {"none", "MEF", "SPLIT", "SINGLE", "CUBE", "SLICE"};
+
+imrough (int argc, char **argv) {
+ 
+  int i, N, Nimage, TimeSelect;
+  int ModeSelect, TypeSelect, CCDSelect, FilterSelect, TimeFormat;
+  int type, value, mode, CCD, NVEC;
+  char DataBase[256], *Filter;
+  double trange;
+  float *Vec;
+  unsigned long tzero, tend, TimeReference;
+  RegImage *image;
+  Vector *vec;
+
+  VarConfig ("REGISTRATION_DATABASE", "%s", DataBase);
+
+  TimeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-time")) {
+    remove_argument (N, &argc, argv);
+    if (!str_to_time (argv[N], &tzero)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!str_to_dtime (argv[N], &trange)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (trange < 0) {
+      trange = fabs (trange);
+      tzero -= trange;
+    }
+    TimeSelect = TRUE;
+  }
+  if (N = get_argument (argc, argv, "-trange")) {
+    remove_argument (N, &argc, argv);
+    if (!str_to_time (argv[N], &tzero)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!str_to_time (argv[N], &tend)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    trange = tend - tzero;
+    if (trange < 0) {
+      trange = fabs (trange);
+      tzero -= trange;
+    }
+    TimeSelect = TRUE;
+  }
+ 
+  type = T_NONE;
+  TypeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-type")) {
+    TypeSelect = TRUE;
+    remove_argument (N, &argc, argv);
+    for (i = 0; (i < NTYPE) && (type == T_NONE); i++) {
+      if (!strncasecmp (argv[N], typename[i], strlen(argv[N]))) type = i;
+    }
+    if (type == T_NONE) {
+      fprintf (stderr, "ERROR: invalid image type %s\n", argv[N]);
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  mode = M_NONE;
+  ModeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-mode")) {
+    ModeSelect = TRUE;
+    remove_argument (N, &argc, argv);
+    for (i = 0; (i < NMODE) && (mode == M_NONE); i++) {
+      if (!strncasecmp (argv[N], modename[i], strlen(argv[N]))) mode = i;
+    }
+    if (mode == M_NONE) {
+      fprintf (stderr, "ERROR: invalid image mode %s\n", argv[N]);
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  CCDSelect = FALSE;
+  if (N = get_argument (argc, argv, "-ccd")) {
+    remove_argument (N, &argc, argv);
+    CCD = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+    CCDSelect = TRUE;
+  }
+ 
+  FilterSelect = FALSE;
+  if (N = get_argument (argc, argv, "-filter")) {
+    remove_argument (N, &argc, argv);
+    Filter = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    FilterSelect = TRUE;
+    if (!strcasecmp (Filter, "X")) {
+      FilterSelect = FALSE;
+    }
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: imrough (value)\n");
+    fprintf (stderr, "       value options:\n");
+    for (i = 1; i < NVALUE; i++) {
+      fprintf (stderr, "%s\n", valuename[i]);
+    }
+    return (FALSE);
+  }
+ 
+  /* identify selection */
+  value = V_NONE;
+  for (i = 0; (i < NVALUE) && (value == V_NONE); i++) {
+    if (!strncasecmp (argv[1], valuename[i], strlen(argv[1]))) value = i;
+  }
+  if (value == V_NONE) {
+    fprintf (stderr, "ERROR: invalid image value %s\n", argv[1]);
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  image = load_imreg (DataBase, &Nimage);
+  if (image == (RegImage *) NULL) return (FALSE);
+
+  N = 0;
+  NVEC = 1000;
+  REALLOCATE (vec[0].elements, float, NVEC);
+  Vec = vec[0].elements;
+
+  GetTimeFormat (&TimeReference, &TimeFormat);
+
+  /* get data */
+  for (i = 0; i < Nimage; i++) {
+    /* skip unmatched selections */
+    if (TimeSelect && ((image[i].obstime < tzero) || (image[i].obstime > tzero + trange))) continue;
+    if (TimeSelect && ((image[i].obstime < tzero) || (image[i].obstime > tzero + trange))) continue;
+    if (FilterSelect && (strcasecmp (image[i].filter, Filter))) continue;
+    if (CCDSelect && (image[i].ccd != CCD)) continue;
+    if (TypeSelect && (image[i].type != type)) continue;
+    if (ModeSelect && (image[i].mode != mode)) continue;
+
+    /* assign correct value */
+    switch (value) {
+    case (V_EXPTIME):
+      Vec[N] = image[i].exptime;
+      break;
+    case (V_CCDN):
+      Vec[N] = image[i].ccd;
+      break;
+    case (V_SKY):
+      Vec[N] = image[i].sky;
+      break;
+    case (V_BIAS):
+      Vec[N] = image[i].bias;
+      break;
+    case (V_FILTER):
+      Vec[N] = image[i].filter[0];
+      break;
+    case (V_FWHM):
+      Vec[N] = image[i].fwhm;
+      break;
+    case (V_AIRM):
+      Vec[N] = image[i].airmass;
+      break;
+    case (V_TIME):
+      Vec[N] = TimeValue (image[i].obstime, TimeReference, TimeFormat);
+      break;
+    case (V_TEMP0):
+      Vec[N] = image[i].teltemp[0];
+      break;
+    case (V_TEMP1):
+      Vec[N] = image[i].teltemp[1];
+      break;
+    case (V_TEMP2):
+      Vec[N] = image[i].teltemp[2];
+      break;
+    case (V_TEMP3):
+      Vec[N] = image[i].teltemp[3];
+      break;
+    case (V_TELFOCUS):
+      Vec[N] = image[i].telfocus;
+      break;
+    case (V_XPROBE):
+      Vec[N] = image[i].xprobe;
+      break;
+    case (V_YPROBE):
+      Vec[N] = image[i].yprobe;
+      break;
+    case (V_ZPROBE):
+      Vec[N] = image[i].zprobe;
+      break;
+    case (V_RA):
+      Vec[N] = image[i].ra;
+      break;
+    case (V_DEC):
+      Vec[N] = image[i].dec;
+      break;
+    case (V_DETTEMP):
+      Vec[N] = image[i].dettemp;
+      break;
+    case (V_ROTANGLE):
+      Vec[N] = image[i].rotangle;
+      break;
+    case (V_REGTIME):
+      Vec[N] = TimeValue (image[i].regtime, TimeReference, TimeFormat);
+      break;
+    }
+    N++;
+    if (N >= NVEC - 1) {
+      NVEC += 1000;
+      REALLOCATE (vec[0].elements, float, NVEC);
+      Vec = vec[0].elements;
+    }
+  }
+
+  REALLOCATE (vec[0].elements, float, MAX (1,N));
+  vec[0].Nelements = N;
+
+  free (image);
+  return (TRUE);
+
+}
+
+RegImage *load_imreg (char *DataBase, int *nimage) {
+
+  int Nimage, status;
+  char line[80];
+  FILE *f;
+  Header header, theader;
+  Matrix matrix;
+  FTable table;
+  RegImage *image;
+
+  *nimage = 0;
+
+  /* open database */
+  f = fopen (DataBase, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't open Registration Database\n");
+    return ((RegImage *) NULL);
+  }
+
+  /* load in database header */
+  if (!fits_fread_header (f, &header)) {
+    fclose (f);
+    fits_free_header (&header);
+    fprintf (stderr, "ERROR: trouble reading database header\n");
+    return ((RegImage *) NULL);
+  }
+
+  /* check for database v1, v2 */
+  fits_scan (&header, "ORIGIN", "%s", 1, line);
+  if (!strcmp (line, "MDM Observatory")) {
+
+    fseek (f, header.size, SEEK_SET);
+    
+    /* load existing data from database */
+    fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+    ALLOCATE (image, RegImage, Nimage);
+    status = Fread (image, sizeof(RegImage), Nimage, f, "regimage");
+    fclose (f);
+    
+    if (status != Nimage) {
+      fprintf (stderr, "ERROR: header and data in dB don't match (%d vs %d)\n", Nimage, status);
+      fits_free_header (&header);
+      free (image);
+      return ((RegImage *) NULL);
+    }
+
+    *nimage = Nimage;
+    return (image);
+  }
+
+  /* we probably have v3 */
+  if (!fits_fread_matrix (f, &matrix, &header)) {
+    fclose (f);
+    fits_free_header (&header);
+    fits_free_matrix (&matrix);
+    fprintf (stderr, "ERROR: trouble reading database matrix\n");
+    return ((RegImage *) NULL);
+  }
+
+  table.header = &theader;
+  if (!fits_fread_ftable  (f, &table, "IMAGE_DATABASE")) {
+    fclose (f);
+    fits_free_header (&header);
+    fits_free_matrix (&matrix);
+    fprintf (stderr, "ERROR: trouble reading database table\n");
+    return ((RegImage *) NULL);
+  }
+
+  /* convert to internal format */
+  image = (RegImage *) table.buffer;
+  fits_scan (table.header, "NAXIS2", "%d", 1, &Nimage);
+  ConvertStruct ((char *) image, sizeof (RegImage), Nimage, "regimage");
+
+  fits_free_header (&header);
+  fits_free_matrix (&matrix);
+
+  *nimage = Nimage;
+  return (image);
+}
Index: /tags/start/Ohana/src/opihi/dvo/imsearch.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/imsearch.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/imsearch.c	(revision 12606)
@@ -0,0 +1,187 @@
+# include "dvo.h"
+
+static char typename[5][32] = {"none", "object", "dark", "bias", "flat"};
+static char modename[3][32] = {"none", "mef", "single"};
+
+imsearch (int argc, char **argv) {
+ 
+  char DataBase[256], name[64];
+  FILE *f;
+  Header header;
+  RegImage *pimage;
+  int i, Nimage, status, N, TimeSelect, SaveNames;
+  int ModeSelect, TypeSelect, CCDSelect, FilterSelect;
+  char *Filter, *Type, *Mode, *pmode, *ptype, *obstime;
+  int type, mode, CCD;
+  unsigned long int tzero;
+  double trange;
+   
+  VarConfig ("REGISTRATION_DATABASE", "%s", DataBase);
+
+  SaveNames = FALSE;
+  if (N = get_argument (argc, argv, "-save")) {
+    remove_argument (N, &argc, argv);
+    SaveNames = TRUE;
+  }
+ 
+  TimeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-time")) {
+    remove_argument (N, &argc, argv);
+    if (!str_to_time (argv[N], &tzero)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!str_to_dtime (argv[N], &trange)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    TimeSelect = TRUE;
+  }
+ 
+  TypeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-type")) {
+    remove_argument (N, &argc, argv);
+    Type = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    TypeSelect = TRUE;
+  }
+ 
+  ModeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-mode")) {
+    remove_argument (N, &argc, argv);
+    Mode = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    ModeSelect = TRUE;
+  }
+ 
+  CCDSelect = FALSE;
+  if (N = get_argument (argc, argv, "-ccd")) {
+    remove_argument (N, &argc, argv);
+    CCD = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+    CCDSelect = TRUE;
+  }
+ 
+  FilterSelect = FALSE;
+  if (N = get_argument (argc, argv, "-filter")) {
+    remove_argument (N, &argc, argv);
+    Filter = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    FilterSelect = TRUE;
+    if (!strcasecmp (Filter, "X")) {
+      FilterSelect = FALSE;
+    }
+  }
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: imsearch [-time start range] [-type type] [-mode mode] [-ccd N] [-filter name]\n");
+    exit (1);
+  }
+
+  type = TYPE_NONE;
+  if (TypeSelect) {
+    if (!strncasecmp (Type, "obj", 3)) {
+      type = TYPE_OBJECT;
+    }
+    if (!strncasecmp (Type, "bias", 4)) {
+      type = TYPE_BIAS;
+    }
+    if (!strncasecmp (Type, "dark", 4)) {
+      type = TYPE_DARK;
+    }
+    if (!strncasecmp (Type, "flat", 4)) {
+      type = TYPE_FLAT;
+    }
+    if (type == TYPE_NONE) {
+      fprintf (stderr, "invalid image type %s\n", Type);
+      return (FALSE);
+    }
+  }
+
+  mode = MODE_NONE;
+  if (ModeSelect) {
+    if (!strncasecmp (Mode, "mef", 3)) {
+      mode = MODE_MEF;
+    }
+    if (!strncasecmp (Mode, "single", 4) || !strncasecmp (Mode, "split", 4)) {
+      mode = MODE_SINGLE;
+    }
+    if (mode == MODE_NONE) {
+      fprintf (stderr, "invalid image mode %s\n", Mode);
+      return (FALSE);
+    }
+  }
+
+  /* load in database header */
+  if (!fits_read_header (DataBase, &header)) {
+    fprintf (stderr, "ERROR: trouble reading database header\n");
+    return (FALSE);
+  }
+
+  /* open database */
+  f = fopen (DataBase, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't open Registration Database\n");
+    return (FALSE);
+  }
+  fseek (f, header.size, SEEK_SET);
+
+  /* load existing data from database */
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+  ALLOCATE (pimage, RegImage, Nimage);
+  status = Fread (pimage, sizeof(RegImage), Nimage, f, "regimage");
+  fclose (f);
+
+  if (status != Nimage) {
+    fprintf (stderr, "ERROR: header and data in dB don't match (%d vs %d)\n", Nimage, status);
+    fits_free_header (&header);
+    free (pimage);
+    return (FALSE);
+  }
+
+  /* print out all data */
+  N = 0;
+  for (i = 0; i < Nimage; i++) {
+    if (TimeSelect && ((pimage[i].obstime < tzero) || (pimage[i].obstime > tzero + trange))) continue;
+    if (FilterSelect && (strcasecmp (pimage[i].filter, Filter))) continue;
+    if (ModeSelect && (pimage[i].mode != mode)) continue;
+    if (CCDSelect && (pimage[i].ccd != CCD)) continue;
+    if (TypeSelect && (pimage[i].type != type)) continue;
+
+    if ((pimage[i].mode < 0) || (pimage[i].mode > 2)) 
+      pmode = modename[0];
+    else
+      pmode = modename[(int)pimage[i].mode];
+
+    if ((pimage[i].type < 0) || (pimage[i].type > 4)) 
+      ptype = typename[0];
+    else
+      ptype = typename[(int)pimage[i].type];
+
+    obstime = ctime (&pimage[i].obstime);
+    obstime[strlen(obstime)-1] = 0;
+    fprintf (stdout, "%5d %6s %6s %2d %2d   ", i, ptype, pmode, pimage[i].ccd, pimage[i].type);
+    fprintf (stdout, "%s %s  ", pimage[i].pathname, pimage[i].filename);
+    fprintf (stdout, "%s %s %f %s\n", pimage[i].filter, pimage[i].instrument, pimage[i].exptime, obstime);
+
+    if (SaveNames) {
+      sprintf (name, "IMAGEpath:%d", N);
+      set_str_variable (name, pimage[i].pathname);
+      sprintf (name, "IMAGEfile:%d", N);
+      set_str_variable (name, pimage[i].filename);
+      sprintf (name, "IMAGEmode:%d", N);
+      set_int_variable (name, pimage[i].mode);
+    }
+    N++;
+  }
+  if (SaveNames) {
+    set_int_variable ("IMAGEpath:n", N);
+    set_int_variable ("IMAGEfile:n", N);
+  }
+
+  free (pimage);
+  fits_free_header (&header);
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/dvo/imstats.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/imstats.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/imstats.c	(revision 12606)
@@ -0,0 +1,71 @@
+# include "dvo.h"
+
+int imstats (int argc, char **argv) {
+  
+  int i, Nimage, N;
+  int Mcal, AutoLimits, Ngraph;
+  double r, d;
+  Image *image;
+  Vector Xvec, Yvec;  
+  Graphdata graphmode;
+
+  Ngraph = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Ngraph = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);
+
+  Mcal = TRUE;
+  if (N = get_argument (argc, argv, "-dM")) {
+    remove_argument (N, &argc, argv);
+    Mcal = FALSE;
+  }
+
+  AutoLimits = FALSE;
+  if (N = get_argument (argc, argv, "-l")) {
+    remove_argument (N, &argc, argv);
+    AutoLimits = TRUE;
+  }
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: imstats [-dM] [-l]\n");
+    return (FALSE);
+  }
+
+  image = LoadImages (&Nimage);
+  if (Nimage == 0) {
+    return (FALSE);
+  }
+
+  /* assign vector values */
+  Xvec.Nelements = Nimage;
+  Yvec.Nelements = Nimage;
+  ALLOCATE (Xvec.elements, float, Xvec.Nelements);
+  ALLOCATE (Yvec.elements, float, Yvec.Nelements);
+  fprintf (stdout, "seq  ra (J2000) dec    time (s)   Nstars\n");
+  for (i = 0; i < Nimage; i++) {
+    Xvec.elements[i] = 0.001*image[i].secz;
+    if (Mcal) 
+      Yvec.elements[i] = 0.001*image[i].Mcal;
+    else 
+      Yvec.elements[i] = 0.001*image[i].dMcal;
+    XY_to_RD (&r, &d, 0.5*image[i].NX, 0.5*image[i].NY, &image[i].coords);
+    fprintf (stderr, "%d %8.4f %8.4f %10d %6d  %5.3f %6.3f %6.3f\n", 
+	     i, r, d, image[i].tzero, image[i].nstar, Xvec.elements[i], 
+	     0.001*image[i].Mcal, 0.001*image[i].dMcal);
+  } 
+  if (AutoLimits) SetLimits (&Xvec, &Yvec, &graphmode);
+
+  graphmode.style = 2;
+  graphmode.etype = 0;
+  PrepPlotting (Nimage, &graphmode);
+  PlotVector (Nimage, Xvec.elements);
+  PlotVector (Nimage, Yvec.elements);
+  
+  free (Xvec.elements);
+  free (Yvec.elements);
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/dvo/init.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/init.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/init.c	(revision 12606)
@@ -0,0 +1,103 @@
+# include "dvo.h"
+
+int addxtra	    PROTO((int, char **));
+int avextract	    PROTO((int, char **));
+int badimages	    PROTO((int, char **));
+int calextract	    PROTO((int, char **));
+int calmextract	    PROTO((int, char **));
+int catlog	    PROTO((int, char **));
+int ccd		    PROTO((int, char **));
+int cmatch	    PROTO((int, char **));
+int cmd		    PROTO((int, char **));
+int cmpload	    PROTO((int, char **));
+int cmpread	    PROTO((int, char **));
+int ddmags	    PROTO((int, char **));
+int detrend	    PROTO((int, char **));
+int dmagaves	    PROTO((int, char **));
+int dmagmeas	    PROTO((int, char **));
+int dmags	    PROTO((int, char **));
+int dmt		    PROTO((int, char **));
+int gcat	    PROTO((int, char **));
+int getxtra	    PROTO((int, char **));
+int gimages	    PROTO((int, char **));
+int gstar	    PROTO((int, char **));
+int gtypes	    PROTO((int, char **));
+int images	    PROTO((int, char **));
+int imbox	    PROTO((int, char **));
+int imdata	    PROTO((int, char **));
+int imdense	    PROTO((int, char **));
+int imextract	    PROTO((int, char **));
+int imlist	    PROTO((int, char **));
+int imphot	    PROTO((int, char **));
+int imrough	    PROTO((int, char **));
+int imsearch	    PROTO((int, char **));
+int imstats	    PROTO((int, char **));
+int lcat	    PROTO((int, char **));
+int lcurve	    PROTO((int, char **));
+int mextract	    PROTO((int, char **));
+int pcat	    PROTO((int, char **));
+int photcodes	    PROTO((int, char **));
+int pmeasure	    PROTO((int, char **));
+int procks	    PROTO((int, char **));
+int showtile	    PROTO((int, char **));
+int simage	    PROTO((int, char **));
+int subpix	    PROTO((int, char **));
+
+/* temporarily exclude
+  {"addxtra",     addxtra,      "add extra data to object"},
+  {"detrend", 	  detrend,      "extract from detrend database?"},
+  {"getxtra",     getxtra,      "get extra data from object"},
+*/
+
+static Command cmds[] = {  
+  {"avextract",   avextract,    "extract average data values"},
+  {"badimages",   badimages,    "look for images with anomalous astrometry"},
+  {"calextract",  calextract,   "extract photometry calibration"},
+  {"calmextract", calmextract,  "extract photometry calibration"},
+  {"catalog",     catlog,       "plot catalog stars"},
+  {"cmatch",      cmatch,       "match two catalogs"},
+  {"ccd",         ccd,          "plot color-color diagram"},
+  {"cmd",         cmd,          "plot cmd of stars in current region"},
+  {"cmpload",     cmpload,      "load cmp file into ?"},
+  {"cmpread",     cmpread,      "read data from cmp format files"},
+  {"ddmags",      ddmags,       "plot magnitude differences"},
+  {"dmagaves",    dmagaves,     "foo"},
+  {"dmagmeas",    dmagmeas,     "foo"},
+  {"dmags",       dmags,        "plot differential magnitudes between filters"},
+  {"dmt",         dmt,          "plot mag scatter"},
+  {"gcat",    	  gcat,         "get catalog at location"},
+  {"gimages", 	  gimages,      "get images at location"},
+  {"gstar",       gstar,        "get star statistics"},
+  {"images",  	  images,       "plot image boxes"},
+  {"imbox",   	  imbox,        "plot expected image box"},
+  {"imdata",  	  imdata,       "extract data for specific images"},
+  {"imdense", 	  imdense,      "image density plot"},
+  {"imextract",   imextract,    "extract vectors from catalogs"},
+  {"imlist",      imlist,       "list image info"},
+  {"imphot",      imphot,       "image photometry info"},
+  {"imrough",     imrough,      "get info from imruf database"},
+  {"imsearch",    imsearch,     "get info from imreg database"},
+  {"imstats", 	  imstats,      "plot image statistics"},
+  {"lcat",    	  lcat,         "list catalogs in region"},
+  {"lcurve",      lcurve,       "plot lightcurve for a star"},
+  {"mextract",    mextract,     "extract measure data values"},
+  {"pcat",    	  pcat,         "plot catalog boundaries"},
+  {"photcodes",   photcodes,    "list photometry codes"},
+  {"pmeasure",    pmeasure,     "plot individual measurements"},
+  {"procks",      procks,       "plot rocks"},
+  {"showtile",    showtile,     "plot tile pattern"},
+  {"simage",      simage,       "plot stars in an image"},
+  {"subpix",      subpix,       "get subpixel positions"},
+}; 
+
+/* move to astro */
+
+void InitDVO () {
+  
+  int i;
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+
+}
Index: /tags/start/Ohana/src/opihi/dvo/lcat.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/lcat.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/lcat.c	(revision 12606)
@@ -0,0 +1,50 @@
+# include "dvo.h"
+
+int lcat (int argc, char **argv) {
+  
+  double Radius;
+  int i, N, Nregions, ShowAll;
+  RegionFile *regions;
+  char filename[128], exists;
+  struct stat filestat;
+  char catdir[256];
+  Graphdata graphmode;
+  int Ngraph;
+
+  Ngraph = 0;
+  if (!GetGraphData (&graphmode, NULL, &Ngraph)) return (FALSE);
+
+  VarConfig ("CATDIR", "%s", catdir);
+
+  ShowAll = FALSE;
+  if (N = get_argument (argc, argv, "-all")) {
+    remove_argument (N, &argc, argv);
+    ShowAll = TRUE;
+  }
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: lcat [-all]\n");
+    return (FALSE);
+  }
+
+  Radius = MAX (fabs(graphmode.xmax), fabs(graphmode.ymax));
+  regions = find_regions (graphmode.coords.crval1, graphmode.coords.crval2, Radius, &Nregions);
+
+  for (i = 0; i < Nregions; i++) {
+    sprintf (filename, "%s/%s", catdir, regions[i].name);
+    exists = 'Y';
+    if (stat (filename, &filestat) == -1) exists = 'N';
+    if (ShowAll) {
+      fprintf (stderr, "%3d %s  %c\n", i, regions[i].name, exists);
+    } else {
+      if (exists == 'Y') {
+	fprintf (stderr, "%3d %s\n", i, regions[i].name);
+      }
+    }
+  }
+
+  return (TRUE);
+
+  free (regions);
+
+}
+
Index: /tags/start/Ohana/src/opihi/dvo/lcurve.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/lcurve.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/lcurve.c	(revision 12606)
@@ -0,0 +1,199 @@
+# include "dvo.h"
+
+int lcurve (int argc, char **argv) {
+  
+  char filename[128], string[128], catdir[256], *p;
+  double Ra, Dec, Radius, Radius2, r;
+  float *RA, *DEC;
+  int Ngraph, Xgraph, TimeFormat;
+  int Nstars, found, AutoLimits, ErrorBars, GalMag, AbsPhot, SaveVectors;
+  int i, j, m, N, NPTS, *N1, Nregions;
+  time_t TimeReference;
+  struct tm *timeptr;
+  RegionFile *regions;
+  Vector *xvec, *yvec;
+  Vector Xvec, Yvec, dYvec;
+  Catalog catalog;
+  Graphdata graphmode;
+
+  VarConfig ("CATDIR", "%s", catdir);
+  if (!InitPhotcodes ()) return (FALSE);
+
+  Ngraph = -1;
+  if (N = get_argument (argc, argv, "-n")) {
+    remove_argument (N, &argc, argv);
+    Ngraph = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraph (&graphmode, &Xgraph, &Ngraph)) return (FALSE);
+
+  AutoLimits = FALSE;
+  if (N = get_argument (argc, argv, "-l")) {
+    remove_argument (N, &argc, argv);
+    AutoLimits = TRUE;
+  }
+
+  SaveVectors = FALSE;
+  if (N = get_argument (argc, argv, "-v")) {
+    remove_argument (N, &argc, argv);
+    SaveVectors = TRUE;
+    if ((xvec = SelectVector (argv[N], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    remove_argument (N, &argc, argv);
+    if ((yvec = SelectVector (argv[N], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    remove_argument (N, &argc, argv);
+  }
+
+  AbsPhot = FALSE;
+  if (N = get_argument (argc, argv, "-abs")) {
+    remove_argument (N, &argc, argv);
+    AbsPhot = TRUE;
+  }
+
+  GalMag = FALSE;
+  if (N = get_argument (argc, argv, "-gal")) {
+    fprintf (stderr, "galaxy magnitudes currently disabled\n");
+    return (FALSE);
+  }
+
+  ErrorBars = FALSE;
+  if (N = get_argument (argc, argv, "-d")) {
+    remove_argument (N, &argc, argv);
+    ErrorBars = TRUE;
+  }
+
+  if (argc < 4) {
+    fprintf (stderr, "USAGE: lcurve RA DEC Radius\n");
+    return (FALSE);
+  }
+  
+  Ra = atof (argv[1]);
+  Dec = atof (argv[2]);
+  Radius = atof (argv[3]);
+
+  regions = find_regions (Ra, Dec, Radius, &Nregions);
+
+  if (Nregions > 1) {
+    fprintf (stderr, "warning, radius overlaps region boundary, not yet implemented\n");
+  }
+
+  /* set filename, read in header */
+  sprintf (filename, "%s/%s", catdir, regions[0].name);
+  catalog.filename = filename;
+  switch (lock_catalog (&catalog, LCK_SOFT)) {
+  case 2:
+    unlock_catalog (&catalog);
+  case 0:
+    return (FALSE);
+  }
+  if (!load_catalog (&catalog, LOAD_AVES | LOAD_MEAS, TRUE)) {
+    unlock_catalog (&catalog);
+    return (FALSE);
+  }
+  unlock_catalog (&catalog);
+
+  Nstars = catalog.Naverage;
+  ALLOCATE (RA, float, Nstars);
+  ALLOCATE (DEC, float, Nstars);
+  ALLOCATE (N1, int, Nstars);
+
+  /* find star(s) in RA, DEC list -- use a dumb algorithm for now, improve later */
+  /* stars are not guaranteed to be sorted in RA or in DEC, so first sort the list */
+  for (i = 0; i < Nstars; i++) {
+    RA[i] = catalog.average[i].R;
+    DEC[i] = catalog.average[i].D;
+    N1[i] = i;
+  }
+  /* sort list by DEC */
+  if (Nstars > 1) sort_lists (DEC, RA, N1, Nstars);
+  /* at this point, RA, DEC, and N1 are sorted by DEC.  
+     catalog.average[N1[i]].R = RA[i] */
+
+  NPTS = 100;
+  ALLOCATE (Xvec.elements, float, NPTS);
+  ALLOCATE (Yvec.elements, float, NPTS);
+  if (ErrorBars) { ALLOCATE (dYvec.elements, float, NPTS); }
+  N = 0;
+
+  GetTimeFormat (&TimeReference, &TimeFormat);
+
+  Radius2 = Radius*Radius;
+  found = FALSE;
+  for (i = 0; (i < catalog.Naverage) && !found; i++) {
+
+    /* this can be improved by using a couple of jumps to get within range */
+    if (Dec > DEC[i] + Radius)
+      continue;
+    
+    r = SQ(Dec - DEC[i]) + SQ(Ra - RA[i]);
+    if (r < Radius2) {
+      /* found star, extract measurements */
+      m = catalog.average[N1[i]].offset;
+      for (j = 0; j < catalog.average[N1[i]].Nm; j++, m++) {
+	if (ErrorBars) dYvec.elements[N] = 0.001*catalog.measure[m].dM;
+	Xvec.elements[N] = TimeValue (catalog.measure[m].t, TimeReference, TimeFormat);
+	Yvec.elements[N] = PhotCat (&catalog.measure[m]);
+	/**** need to use PhotRel optionally here ****/
+	N++; 
+	if (N == NPTS) {
+	  NPTS += 100;
+	  REALLOCATE (Xvec.elements, float, NPTS);
+	  REALLOCATE (Yvec.elements, float, NPTS);
+	  if (ErrorBars) { REALLOCATE (dYvec.elements, float, NPTS); }
+	}
+      }      
+    }
+  }
+  Xvec.Nelements = Yvec.Nelements = N;
+  if (ErrorBars) dYvec.Nelements = N;
+  
+  if (ErrorBars)
+    sortthree (Xvec.elements, Yvec.elements, dYvec.elements, N);
+  else
+    fsortpair (Xvec.elements, Yvec.elements, N);
+
+  /* autoscale the plot */
+  if (AutoLimits) SetLimits (&Xvec, &Yvec, &graphmode);
+
+  if (ErrorBars) 
+    graphmode.etype = 1;  /* y errors only in lcurves */
+  else
+    graphmode.etype = 0;  
+
+  PrepPlotting (N, &graphmode);
+  PlotVector (N, Xvec.elements);
+  PlotVector (N, Yvec.elements);
+  if (ErrorBars) {
+    PlotVector (N, dYvec.elements);
+    PlotVector (N, dYvec.elements);
+  }
+
+  timeptr = gmtime ((time_t *)&TimeReference);
+
+  if ((p = get_variable ("TIMEFORMAT")) == (char *) NULL) p = strcreate ("days");
+  sprintf (string, "%s since %02d/%02d/%02d UT", p,
+	   timeptr[0].tm_year, timeptr[0].tm_mon+1, timeptr[0].tm_mday);
+  free (p);
+  SendLabel (string, Xgraph, 0);
+
+  free (RA);
+  free (DEC);
+  free (N1);
+
+  if (SaveVectors) {
+    free (xvec[0].elements);
+    free (yvec[0].elements);
+    xvec[0].elements = Xvec.elements;
+    yvec[0].elements = Yvec.elements;
+    xvec[0].Nelements = yvec[0].Nelements = Xvec.Nelements;
+  } else {
+    free (Xvec.elements);
+    free (Yvec.elements);
+  }
+
+  if (ErrorBars) free (dYvec.elements);
+  if (catalog.average != 0) free (catalog.average);
+  if (catalog.measure != 0) free (catalog.measure);
+ 
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/dvo/match_image.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/match_image.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/match_image.c	(revision 12606)
@@ -0,0 +1,73 @@
+# include "dvo.h"
+
+int match_image (Image *image, int Nimage, unsigned int T, short int S) {
+
+  int N, Nlo, Nhi, N1, N2;
+
+  /* bracket first value of interest */
+  Nlo = 0; Nhi = Nimage;
+  while (Nhi - Nlo > 10) {
+    N = 0.5*(Nlo + Nhi);
+    if (image[N].tzero < T) {
+      Nlo = N;
+    } else {
+      Nhi = N + 1;
+    }
+  }
+  N1 = Nlo;
+
+  /* bracket last value of interest */
+  Nlo = 0; Nhi = Nimage;
+  while (Nhi - Nlo > 10) {
+    N = 0.5*(Nlo + Nhi);
+    if (image[N].tzero > T) {
+      Nhi = N;
+    } else {
+      Nlo = N - 1;
+    }
+  }
+  N2 = Nhi;
+
+  for (N = N1; N < N2; N++) {
+    if ((image[N].tzero == T) && (image[N].source == S)) {
+      return (N);
+    }
+  }
+  return (-1);
+}
+
+int match_image_subset (Image *image, int *subset, int Nsubset, unsigned int T, short int S) {
+
+  int N, Nlo, Nhi, N1, N2;
+
+  /* bracket first value of interest */
+  Nlo = 0; Nhi = Nsubset;
+  while (Nhi - Nlo > 10) {
+    N = 0.5*(Nlo + Nhi);
+    if (image[subset[N]].tzero < T) {
+      Nlo = N;
+    } else {
+      Nhi = N + 1;
+    }
+  }
+  N1 = Nlo;
+
+  /* bracket last value of interest */
+  Nlo = 0; Nhi = Nsubset;
+  while (Nhi - Nlo > 10) {
+    N = 0.5*(Nlo + Nhi);
+    if (image[subset[N]].tzero > T) {
+      Nhi = N;
+    } else {
+      Nlo = N - 1;
+    }
+  }
+  N2 = Nhi;
+
+  for (N = N1; N < N2; N++) {
+    if ((image[subset[N]].tzero == T) && (image[subset[N]].source == S)) {
+      return (subset[N]);
+    }
+  }
+  return (-1);
+}
Index: /tags/start/Ohana/src/opihi/dvo/mextract.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/mextract.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/mextract.c	(revision 12606)
@@ -0,0 +1,146 @@
+# include "dvo.h"
+
+int mextract (int argc, char **argv) {
+  
+  int i, j, k, m, N, N1, NPTS;
+  int param, mode, Nregions, Ngraph, Nsec;
+  char filename[128], catdir[256], *p;
+  double *M1;
+
+  PhotCode *code;
+  Catalog catalog;
+  RegionFile *regions;
+  Graphdata graphsky;
+  Vector *vec;
+
+  regions = NULL;
+  catalog.average = (Average *) NULL; 
+  catalog.secfilt = (SecFilt *) NULL;
+  catalog.measure = (Measure *) NULL;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsec = GetPhotcodeNsecfilt ();
+
+  /* load data about plot windows */
+  Ngraph = 0;
+  if (!GetGraphData (&graphsky, NULL, &Ngraph)) goto escape;
+ 
+  /* find CATDIR in config system */
+  VarConfig ("CATDIR", "%s", catdir);
+
+  /* specify catalog files
+  RegionList = FALSE;
+  if (N = get_argument (argc, argv, "-list")) {
+    RegionList = TRUE;
+    remove_argument (N, &argc, argv);
+    strcpy (RegionListFile, argv[N]);
+    remove_argument (N, &argc, argv);
+  } */
+
+  /* interpret command-line options */
+  if (!SetPhotSelections (&argc, argv)) goto usage;
+  if (argc != 3) goto usage;
+
+  /* identify selection */
+  code = NULL;
+  mode = MAG_REL;
+  param = GetMeasureParam (argv[2]);
+  if (param == MEAS_ZERO) {
+    if (!GetPhotcodeInfo (argv[2], &code, &mode)) {
+      GetMeasureParam ("help");
+      fprintf (stderr, "value may also be a valid photcode\n");
+      fprintf (stderr, "photcodes or 'mag' may have optional magnitude type: mag,[Minst, Mcat, Msys, Mrel, Mcal]\n");
+      goto escape;
+    }
+    param = MEAS_MAG;
+    for (p = argv[2]; *p != 0; p++) { 
+      if (*p == '.') *p = ':';
+    }
+  } 
+  /* test PhotSelections: is photcode specified if needed? */
+  if (!TestPhotSelections (&code)) {
+    fprintf (stderr, "photcode selection rules violated\n");
+    fprintf (stderr, "average and ensemble restrictions require a corresponding photcode\n");
+    goto escape;
+  }
+
+  if ((vec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) goto escape;
+
+  /* determine region-file names */
+  if (!strcmp (argv[1], "all")) {
+    float Radius;
+    Radius = MAX (fabs(graphsky.xmax), fabs(graphsky.ymax));
+    regions = find_regions (graphsky.coords.crval1, graphsky.coords.crval2, Radius, &Nregions);
+    /* I don't have a tool to select images by the overlapping region */
+    if (!SetImageSelection (param, &graphsky, TRUE)) goto escape;
+  } else {
+    Nregions = 1;
+    ALLOCATE (regions, RegionFile, 1);
+    strcpy (regions[0].name, argv[1]);
+    if (!SetImageSelection (param, NULL, FALSE)) goto escape;
+  }
+
+  /* create storage vector */
+  NPTS = 1000;
+  REALLOCATE (vec[0].elements, float, NPTS);
+  vec[0].Nelements = N = 0;
+
+  for (i = 0; i < Nregions; i++) {
+    /* lock, load, unlock catalog */
+    sprintf (filename, "%s/%s", catdir, regions[i].name);
+    catalog.filename = filename;
+    switch (lock_catalog (&catalog, LCK_SOFT)) {
+    case 2:
+      unlock_catalog (&catalog);
+    case 0:
+      continue;
+    }
+    if (!load_catalog (&catalog, LOAD_AVES | LOAD_MEAS | LOAD_SECF, FALSE)) {
+      unlock_catalog (&catalog);
+      continue;
+    }
+    unlock_catalog (&catalog);
+
+    for (j = 0; j < catalog.Naverage; j++) {
+      M1 = NULL;
+      m = catalog.average[j].offset;
+      M1 = ExtractMeasures (code, mode, &catalog.average[j], &catalog.secfilt[j*Nsec], &catalog.measure[m], &N1, param);
+      for (k = 0; k < N1; k++) {
+	vec[0].elements[N] = M1[k];
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 2000;
+	  REALLOCATE (vec[0].elements, float, NPTS);
+	}
+      }
+      if (M1 != NULL) free (M1);
+    }
+    if (catalog.average != NULL) free (catalog.average);
+    if (catalog.secfilt != NULL) free (catalog.secfilt);
+    if (catalog.measure != NULL) free (catalog.measure);
+    catalog.average = (Average *) NULL; 
+    catalog.secfilt = (SecFilt *) NULL;
+    catalog.measure = (Measure *) NULL;
+  }
+  vec[0].Nelements = N;
+  REALLOCATE (vec[0].elements, float, MAX(1,N));
+
+  if (regions != NULL) free (regions);
+  FreeImageSelection ();
+  return (TRUE);
+
+usage:
+  fprintf (stderr, "USAGE: mextract (from) (value) [options]\n");
+  fprintf (stderr, "  from: cpt name or 'all'\n");
+  fprintf (stderr, "  value: measure.parameter or photcode\n");
+  return (FALSE);
+
+escape:
+  if (regions != NULL) free (regions);
+  FreeImageSelection ();
+  if (catalog.average != NULL) free (catalog.average);
+  if (catalog.secfilt != NULL) free (catalog.secfilt);
+  if (catalog.measure != NULL) free (catalog.measure);
+  return (FALSE);
+}
Index: /tags/start/Ohana/src/opihi/dvo/pcat.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/pcat.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/pcat.c	(revision 12606)
@@ -0,0 +1,82 @@
+# include "dvo.h"
+
+int pcat (int argc, char **argv) {
+  
+  double Radius;
+  int i, j, N, Nregions, ShowAll, NPTS, Npts;
+  RegionFile *regions;
+  char filename[128];
+  struct stat filestat;
+  Vector Xvec, Yvec;
+  Graphdata graphmode;
+  double X[4], Y[4];
+  char catdir[256];
+  int Ngraph;
+
+  VarConfig ("CATDIR", "%s", catdir);
+
+  ShowAll = FALSE;
+  if (N = get_argument (argc, argv, "-all")) {
+    remove_argument (N, &argc, argv);
+    ShowAll = TRUE;
+  }
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: pcat [-all]\n");
+    return (FALSE);
+  }
+  Ngraph = 0;
+  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);
+  
+  Radius = MAX (fabs(graphmode.xmax), fabs(graphmode.ymax));
+  regions = find_regions (graphmode.coords.crval1, graphmode.coords.crval2, Radius, &Nregions);
+
+  NPTS = 200;
+  ALLOCATE (Xvec.elements, float, NPTS);
+  ALLOCATE (Yvec.elements, float, NPTS);
+  Npts = 0;
+   
+  for (i = 0; i < Nregions; i++) {
+    sprintf (filename, "%s/%s", catdir, regions[i].name);
+    if (ShowAll || (stat (filename, &filestat) != -1)) {
+      fprintf (stderr, "%3d %s\n", i, regions[i].name);
+      RD_to_XY (&X[0], &Y[0], regions[i].RA0, regions[i].DEC0, &graphmode.coords);
+      RD_to_XY (&X[1], &Y[1], regions[i].RA0, regions[i].DEC1, &graphmode.coords);
+      RD_to_XY (&X[2], &Y[2], regions[i].RA1, regions[i].DEC1, &graphmode.coords);
+      RD_to_XY (&X[3], &Y[3], regions[i].RA1, regions[i].DEC0, &graphmode.coords);
+      for (j = 0; j < 4; j++) {
+	Xvec.elements[Npts + j*2] = X[j];
+	Yvec.elements[Npts + j*2] = Y[j];
+	if (j > 0) {
+	  Xvec.elements[Npts+2*j - 1] = Xvec.elements[Npts+2*j];
+	  Yvec.elements[Npts+2*j - 1] = Yvec.elements[Npts+2*j];
+	}
+      }
+      Xvec.elements[Npts+7] = Xvec.elements[Npts];
+      Yvec.elements[Npts+7] = Yvec.elements[Npts];
+      Npts += 8;
+      if (Npts > NPTS - 1) {  /* this is OK because NPTS is made always a multiple of 8 */
+	NPTS += 200;
+	REALLOCATE (Xvec.elements, float, NPTS);
+	REALLOCATE (Yvec.elements, float, NPTS);
+      }
+    }
+  }
+
+  fprintf (stderr, "plotting %d catalogs\n", Npts/8);
+  Xvec.Nelements = Xvec.Nelements = Npts;
+  if (Npts > 0) {
+    graphmode.style = 2; /* points */
+    graphmode.ptype = 100; /* connect pairs of points */
+    graphmode.etype = 0;
+    PrepPlotting (Npts, &graphmode);
+    PlotVector (Npts, Xvec.elements);
+    PlotVector (Npts, Yvec.elements);
+  }
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+  free (regions);
+
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/dvo/photcodes.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/photcodes.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/photcodes.c	(revision 12606)
@@ -0,0 +1,63 @@
+# include "dvo.h"
+
+/* list or return all photcodes equivalent to the given filter */
+int photcodes (int argc, char **argv) {
+  
+  int i, Np;
+  int *list, Nlist;
+  char name[64];
+  PhotCode *code;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: photcodes (photcode)\n");
+    return (FALSE);
+  }
+
+  /* load photcodes, convert name to code */
+  if (!InitPhotcodes ()) return (FALSE);
+
+  if (!(Np = GetPhotcodeCodebyName (argv[1]))) {
+    fprintf (stderr, "ERROR: photcode not found in photcode table\n");
+    return (FALSE);
+  }
+
+  list = GetPhotcodeEquivList (Np, &Nlist);
+  
+  for (i = 0; i < Nlist; i++) {
+    code = GetPhotcodebyCode (list[i]);
+
+    sprintf (name, "photcode:name:%d", i);
+    set_str_variable (name, code[0].name);
+
+    sprintf (name, "photcode:C:%d", i);
+    set_variable (name, 0.001*code[0].C);
+
+    sprintf (name, "photcode:K:%d", i);
+    set_variable (name, code[0].K);
+
+    sprintf (name, "photcode:X:%d", i);
+    set_variable (name, code[0].X[0]);
+
+    sprintf (name, "photcode:dX:%d", i);
+    set_variable (name, 0.001*code[0].dX);
+
+    sprintf (name, "photcode:code:%d", i);
+    set_int_variable (name, code[0].code);
+
+    sprintf (name, "photcode:filter:%d", i);
+    set_str_variable (name, GetPhotcodeNamebyCode (code[0].equiv));
+
+    sprintf (name, "photcode:c1:%d", i);
+    set_str_variable (name, GetPhotcodeNamebyCode (code[0].c1));
+
+    sprintf (name, "photcode:c2:%d", i);
+    set_str_variable (name, GetPhotcodeNamebyCode (code[0].c2));
+
+    fprintf (stderr, "%5d %s %7.4f %7.4f %7.4f\n", 
+	     code[0].code, code[0].name, 0.001*code[0].C, code[0].K, code[0].X[0]);
+  }
+  set_int_variable ("photcode:n", Nlist);
+  free (list);
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/dvo/photometry.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/photometry.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/photometry.c	(revision 12606)
@@ -0,0 +1,1111 @@
+# include "dvo.h"
+
+/* match code to measure  */
+# define TESTCODE(C,M) \
+  switch (C[0].type) { \
+  case PHOT_DEP: \
+  case PHOT_REF: \
+    if (C[0].code != M.source) continue; \
+    break; \
+  case PHOT_PRI: \
+  case PHOT_SEC: \
+    if (C[0].code != GetPhotcodeEquivCodebyCode (M.source)) continue; \
+    break; \
+  default: \
+    break; \
+} 
+
+/* exclusions based on measure.params  */
+# define TESTMEASURE(M) \
+  if (TimeSelect && (M.t < tzero)) continue; \
+  if (TimeSelect && (M.t > tend)) continue; \
+  if (ErrSelect  && (M.dM > ErrValue)) continue; \
+  if (TypeSelect && (TypeValue != GetMeasureTypeCode (&M))) continue; \
+  if (iMagSelect && (PhotInst (&M) < iMagMin)) continue; \
+  if (FlagSelect && (M.flags != FlagValue)) continue;
+
+# define SETMAG(MOUT,MEAS,MODE) \
+  MOUT = NO_MAG; \
+  if (MODE == MAG_INST) MOUT = PhotInst (&MEAS);  \
+  if (MODE == MAG_CAT)  MOUT = PhotCat  (&MEAS); \
+  if (MODE == MAG_SYS)  MOUT = PhotSys  (&MEAS, average, secfilt); \
+  if (MODE == MAG_REL)  MOUT = PhotRel  (&MEAS, average, secfilt); \
+  if (MODE == MAG_CAL)  MOUT = PhotCal  (&MEAS, average, secfilt, measure, GetPhotcodeEquivbyCode (MEAS.source)); \
+  if (MagSelect && (MOUT > MagMax)) continue; \
+  if (MagSelect && (MOUT < MagMin)) continue;
+
+/* selection criteria */
+/* selections based on Measure quantities */
+static int TimeSelect;
+static time_t tzero, tend;
+static int MagSelect;
+static double MagMax, MagMin;
+static int TypeSelect, TypeValue;
+static int ErrSelect, ErrValue;
+static int iMagSelect;
+static double iMagMin;
+static int FlagSelect, FlagValue;
+
+/* applied to Average quantities */
+static int PhotcodeSelect;
+static PhotCode *PhotcodeValue;
+
+/* selections based on Average quantities */
+static int ChiSelect;
+static float ChiLimit;
+
+/* selections based on ensemble quantities */
+static int NphotSelect, NphotSign, NphotValue;
+static int NcodeSelect, NcodeSign, NcodeValue;
+static int FWHMSelect, FWHMsign;
+static double FWHMvalue, FWHMfrac;
+
+/* time concepts */
+static time_t TimeReference;
+static int TimeFormat;
+
+/* db image table */
+static Image *image = NULL;
+static int *subset = NULL;
+static int Nimage = 0;
+static int Nsubset = 0;
+static Coords mosaic;
+
+int GetPhotcodeInfo (char *string, PhotCode **Code, int *Mode) {
+
+  PhotCode *code;
+  int mode, status;
+  char *p, *tmpstring;
+
+  /* save local copy */
+  tmpstring = strcreate (string);
+
+  /* check for code:mode in photcode name */
+  mode = MAG_NONE;
+  p = strchr (tmpstring, ':');
+  if (p != NULL) {
+    mode = GetMagMode (p + 1);
+    if (mode == MAG_NONE) {
+      fprintf (stderr, "syntax error in magnitude mode\n");
+      free (tmpstring);
+      return (FALSE);
+    }
+    *p = 0;
+  }
+
+  /* how do we handle this elsewhere? */
+  if (!strcasecmp (tmpstring, "mag")) {
+    /* need to validate mode */
+    *Mode = mode;
+    *Code = NULL;
+    free (tmpstring);
+    return (TRUE);
+  }
+
+  code = GetPhotcodebyName (tmpstring);
+  if (code == NULL) {
+    fprintf (stderr, "photcode not found in photcode table\n");
+    free (tmpstring);
+    return (FALSE);
+  }
+
+  /* test allowable cases and/or set default values */
+  status = FALSE;
+  if (code[0].type == PHOT_DEP) {
+    if (mode == MAG_NONE) mode = MAG_REL;
+    if (mode == MAG_INST) status = TRUE;
+    if (mode == MAG_CAT)  status = TRUE;
+    if (mode == MAG_SYS)  status = TRUE;
+    if (mode == MAG_REL)  status = TRUE;
+    if (mode == MAG_CAL)  status = TRUE;
+  }  
+  if ((code[0].type == PHOT_PRI) || (code[0].type == PHOT_SEC)) {
+    if (mode == MAG_NONE) mode  = MAG_AVE;
+    if (mode == MAG_INST) status = TRUE;
+    if (mode == MAG_CAT)  status = TRUE;
+    if (mode == MAG_SYS)  status = TRUE;
+    if (mode == MAG_REL)  status = TRUE;
+    if (mode == MAG_CAL)  status = TRUE;
+    if (mode == MAG_AVE)  status = TRUE;
+    if (mode == MAG_REF)  status = TRUE;
+  }  
+  if (code[0].type == PHOT_ALT) {
+    if (mode == MAG_NONE) mode  = MAG_AVE;
+    if (mode == MAG_AVE)  status = TRUE;
+    if (mode == MAG_REF)  status = TRUE;
+  }
+
+  if (code[0].type == PHOT_REF) {
+    if (mode == MAG_NONE) mode  = MAG_CAT;
+    if (mode == MAG_CAT)  status = TRUE;
+  }
+
+  if (!status) {
+    fprintf (stderr, "mismatch in photcode and magmode\n");
+    free (tmpstring);
+    return (FALSE);
+  }
+  *Code = code;
+  *Mode = mode;
+  free (tmpstring);
+  return (TRUE);
+}
+ 
+int GetMagMode (char *string) {
+
+  int mode;
+
+  mode = MAG_NONE;
+  if (!strcasecmp (string, "inst"))   mode = MAG_INST;
+  if (!strcasecmp (string, "cat"))    mode = MAG_CAT;
+  if (!strcasecmp (string, "sys"))    mode = MAG_SYS;
+  if (!strcasecmp (string, "rel"))    mode = MAG_REL;
+  if (!strcasecmp (string, "cal"))    mode = MAG_CAL;
+  if (!strcasecmp (string, "ave"))    mode = MAG_AVE;
+  if (!strcasecmp (string, "ref"))    mode = MAG_REF;
+  return (mode);
+}
+
+int GetMeasureParam (char *parname) {
+
+  int param;
+
+  param = MEAS_ZERO;
+  if (!strcasecmp (parname, "ra"))   	 param = MEAS_RA;
+  if (!strcasecmp (parname, "dec"))  	 param = MEAS_DEC;
+  if (!strcasecmp (parname, "mag")) 	 param = MEAS_MAG;
+  if (!strcasecmp (parname, "dmag")) 	 param = MEAS_dMAG;
+  if (!strcasecmp (parname, "airmass"))  param = MEAS_AIRMASS;
+  if (!strcasecmp (parname, "exptime"))  param = MEAS_EXPTIME;
+  if (!strcasecmp (parname, "photcode")) param = MEAS_PHOTCODE;
+  if (!strcasecmp (parname, "time"))     param = MEAS_TIME;
+  if (!strcasecmp (parname, "dR")) 	 param = MEAS_dR;
+  if (!strcasecmp (parname, "dD")) 	 param = MEAS_dD;
+  if (!strcasecmp (parname, "fwhm"))   	 param = MEAS_FWHM;
+  if (!strcasecmp (parname, "dophot")) 	 param = MEAS_DOPHOT;
+  if (!strcasecmp (parname, "FLAGS"))    param = MEAS_FLAGS;
+  if (!strcasecmp (parname, "XCCD"))   	 param = MEAS_XCCD;
+  if (!strcasecmp (parname, "YCCD"))   	 param = MEAS_YCCD;
+  if (!strcasecmp (parname, "XMOSAIC"))  param = MEAS_XMOSAIC;
+  if (!strcasecmp (parname, "YMOSAIC"))  param = MEAS_YMOSAIC;
+  if (!strcasecmp (parname, "help")) {
+    fprintf (stderr, "value may be one of the following:\n");
+    fprintf (stderr, " ra dR dec dD mag dmag Mrel Mcal photcode time fwhm dophot xccd yccd xmosaic ymosaic flags\n");
+  }
+  return (param);
+}
+  
+int TestPhotSelections (PhotCode **code) {
+
+  int NeedPhotcode;
+
+  /* if i've supplied a photcode (code != NULL), i'm not allowed to restrict it */
+  if ((code[0] != NULL) && PhotcodeSelect) return (FALSE);
+
+  /* if I have an average or ensemble restriction, I must have a photcode */
+  if (ChiSelect || NphotSelect || NcodeSelect || FWHMSelect) {
+    if (code[0] != NULL) return (TRUE);
+    if (PhotcodeSelect) {
+      code[0] = PhotcodeValue;
+      return (TRUE);
+    }
+    return (FALSE);
+  }
+
+  /* if I have a photcode restriction, apply it to the code */
+  if (PhotcodeSelect) {
+    code[0] = PhotcodeValue;
+    return (TRUE);
+  }
+  return (TRUE);
+}
+
+int GetAverageParam (char *parname) {
+
+  int param;
+
+  param = AVE_ZERO;
+  if (!strcasecmp (parname, "ra"))    param = AVE_RA;
+  if (!strcasecmp (parname, "dec"))   param = AVE_DEC;
+  if (!strcasecmp (parname, "dmag"))  param = AVE_dMAG;
+  if (!strcasecmp (parname, "Nmeas")) param = AVE_NMEAS;
+  if (!strcasecmp (parname, "Nmiss")) param = AVE_NMISS;
+  if (!strcasecmp (parname, "Xp"))    param = AVE_Xp;
+  if (!strcasecmp (parname, "Xm"))    param = AVE_Xm;
+  if (!strcasecmp (parname, "flag"))  param = AVE_FLAG;
+  if (!strcasecmp (parname, "type"))  param = AVE_TYPE;
+  if (!strcasecmp (parname, "Nphot")) param = AVE_NPHOT;
+  if (!strcasecmp (parname, "Ncode")) param = AVE_NCODE;
+  if (!strcasecmp (parname, "help")) {
+    fprintf (stderr, "value may be one of the following:\n");
+    fprintf (stderr, " ra dec dmag Nmeas Nmiss Xm Xp Nphot Ncode flag type\n");
+  }
+  return (param);
+}
+
+/* load images based on parameters and region, etc */
+int SetImageSelection (int mode, Graphdata *graphsky, int RegionSelect) {
+
+  image = NULL;
+  subset = NULL;
+  
+  switch (mode) {
+  case MEAS_XCCD:
+  case MEAS_YCCD:
+    break;
+  case MEAS_XMOSAIC: 
+  case MEAS_YMOSAIC:
+    /* mosaic defines a frame with 0,0 at the mosaic center, and 1 arcsec / pixel */
+    mosaic.crpix1 = mosaic.crpix2 = 0.0;
+    mosaic.cdelt1 = mosaic.cdelt2 = 1.0 / 3600;
+    mosaic.pc1_1  = mosaic.pc2_2  = 1.0;
+    mosaic.pc1_2  = mosaic.pc2_1  = 0.0;
+    mosaic.Npolyterms = 0;
+    strcpy (mosaic.ctype, "RA---SIN");
+    break;
+  default:
+    return (TRUE);
+  }
+
+  image = LoadImages (&Nimage);
+  if (Nimage == 0) {
+    return (FALSE);
+  }
+  image_subset (image, Nimage, &subset, &Nsubset, graphsky, RegionSelect, tzero, (double) tend - tzero, TimeSelect);
+
+  sort_image_subset (image, subset, Nsubset);
+  return (TRUE);
+}
+
+/* free loaded images */
+void FreeImageSelection () {
+  if (image != NULL) free (image);
+  if (subset != NULL) free (subset);
+  return;
+}
+
+/* (re)load photcodes from photcode table */
+int InitPhotcodes () {
+
+  double ZERO_POINT;
+  char PhotCodeFile[256];
+
+  if (VarConfig ("ZERO_PT", "%lf", &ZERO_POINT) == (char *) NULL) return (FALSE);
+  SetZeroPoint (ZERO_POINT);
+
+  if (VarConfig ("PHOTCODE_FILE", "%s", PhotCodeFile) == (char *) NULL) return (FALSE);
+  if (!LoadPhotcodes (PhotCodeFile)) {
+    fprintf (stderr, "error loading photcodes\n");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+/* remove standard photometry filtering options, set selections */
+/* not all functions respect all selections... */
+int SetPhotSelections (int *argc, char **argv) {
+
+  int N;
+  double trange;
+
+  if (N = get_argument (*argc, argv, "-phothelp")) {
+    fprintf (stderr, "optional photometry selection criteria:\n");
+    fprintf (stderr, " -magrange min max\n");
+    fprintf (stderr, " -imaglim min\n");
+    fprintf (stderr, " -flag value\n");
+    fprintf (stderr, " -chisq value\n");
+    fprintf (stderr, " -photcode code\n");
+    fprintf (stderr, " -time start range\n");
+    fprintf (stderr, " -errorlim value\n");
+    fprintf (stderr, " -type type\n");
+    fprintf (stderr, " -nmeas [+/-]N\n");
+    fprintf (stderr, " -fwhm [+/-]fraction\n");
+    return (FALSE);
+  }
+
+  /* select based on measured mag (MEASURE ONLY) */
+  MagSelect = FALSE;
+  if (N = get_argument (*argc, argv, "-magrange")) {
+    MagSelect = TRUE;
+    remove_argument (N, argc, argv);
+    MagMin = atof (argv[N]);
+    remove_argument (N, argc, argv);
+    MagMax = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  /* select based on instrument mag (MEASURE ONLY) */
+  iMagSelect = FALSE;
+  if (N = get_argument (*argc, argv, "-imaglim")) {
+    iMagSelect = TRUE;
+    remove_argument (N, argc, argv);
+    iMagMin = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  /* select on value of flag (MEASURE ONLY) */
+  FlagSelect = FALSE;
+  if (N = get_argument (*argc, argv, "-flag")) {
+    FlagSelect = TRUE;
+    remove_argument (N, argc, argv);
+    FlagValue = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  /* select on value of flag (MEASURE ONLY) */
+  ChiSelect = FALSE;
+  if (N = get_argument (*argc, argv, "-chisq")) {
+    ChiSelect = TRUE;
+    remove_argument (N, argc, argv);
+    ChiLimit = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  /* select on value of photcode */
+  PhotcodeSelect = FALSE;
+  if (N = get_argument (*argc, argv, "-photcode")) {
+    PhotcodeSelect = TRUE;
+    remove_argument (N, argc, argv);
+    PhotcodeValue = GetPhotcodebyName (argv[N]);
+    if (PhotcodeValue == NULL) {
+      fprintf (stderr, "photcode not found in photcode table\n");
+      PhotcodeSelect = FALSE;
+    }
+    remove_argument (N, argc, argv);
+  }
+
+  /* selection on basis of time range (MEASURE only) */
+  TimeSelect = FALSE;
+  if (N = get_argument (*argc, argv, "-time")) {
+    remove_argument (N, argc, argv);
+    if (!str_to_time (argv[N], &tzero)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, argc, argv);
+    if (!str_to_dtime (argv[N], &trange)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, argc, argv);
+    TimeSelect = TRUE;
+    if (trange < 0) {
+      trange = fabs (trange);
+      tend = tzero;
+      tzero -= trange;
+    } else {
+      tend = tzero + trange;
+    }
+  }
+
+  /* select by error (on measure or average) */
+  ErrSelect = FALSE;
+  if (N = get_argument (*argc, argv, "-errorlim")) {
+    remove_argument (N, argc, argv);
+    ErrValue = 1000*atof (argv[N]);
+    remove_argument (N, argc, argv);
+    ErrSelect = TRUE;
+  }
+
+  /* select on measurement type: 1,2,3 (AVERAGE ONLY) */
+  TypeSelect = FALSE;
+  if (N = get_argument (*argc, argv, "-type")) {
+    remove_argument (N, argc, argv);
+    TypeValue = atoi (argv[N]);
+    remove_argument (N, argc, argv);
+    TypeSelect = TRUE;
+  }
+
+  /* select by number of measurements (AVERAGE ONLY) */
+  NphotSelect = FALSE;
+  if (N = get_argument (*argc, argv, "-nphot")) {
+    remove_argument (N, argc, argv);
+    NphotValue = abs (atoi (argv[N]));
+    NphotSign = 0;
+    if (argv[N][0] == '-') NphotSign = -1;
+    if (argv[N][0] == '+') NphotSign = +1;
+    remove_argument (N, argc, argv);
+    NphotSelect = TRUE;
+  }
+
+  /* select by number of measurements (AVERAGE ONLY) */
+  NcodeSelect = FALSE;
+  if (N = get_argument (*argc, argv, "-ncode")) {
+    remove_argument (N, argc, argv);
+    NcodeValue = abs (atoi (argv[N]));
+    NcodeSign = 0;
+    if (argv[N][0] == '-') NcodeSign = -1;
+    if (argv[N][0] == '+') NcodeSign = +1;
+    remove_argument (N, argc, argv);
+    NcodeSelect = TRUE;
+  }
+
+  /* -fwhm value frac (AVERAGE ONLY) */
+  FWHMSelect = FALSE;
+  if (N = get_argument (*argc, argv, "-fwhm")) {
+    remove_argument (N, argc, argv);
+    FWHMvalue = abs (atof (argv[N]));
+    FWHMsign = 0;
+    if (argv[N][0] == '-') FWHMsign = -1;
+    if (argv[N][0] == '+') FWHMsign = +1;
+    remove_argument (N, argc, argv);
+    FWHMSelect = TRUE;
+    remove_argument (N, argc, argv);
+    FWHMfrac = atof (argv[N]);
+  }
+
+  GetTimeFormat (&TimeReference, &TimeFormat);
+  return (TRUE);
+}
+
+/* extract a list of measure parameters from the specified average entry based on the pre-set selections */
+double *ExtractMeasures (PhotCode *code, int mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist, int param) {
+
+  int i, k, m, Nlist, NLIST, np, found, Nm;
+  time_t t;
+  double ra, dec, x, y, value, M, fwhm;
+  double *list;
+  
+  *nlist = 0; 
+  Nlist = 0;
+  NLIST = MAX (1, average[0].Nm);
+  ALLOCATE (list, double, NLIST);
+
+  /* chisq, fwhm, Nphot, Ncode */
+  if (!TestAverage (code, average, secfilt, measure)) return (list);
+
+  /* look for measures */
+  for (i = 0; i < average[0].Nm; i++) {
+    if (code != NULL) {
+      TESTCODE (code, measure[i]);
+    }
+    /* exclusions based on measure.params  */
+    TESTMEASURE (measure[i]);
+
+    /* need to have the mag value to test MagSelect */ 
+    SETMAG (M, measure[i], mode);
+
+    /* assign value */
+    switch (param) {
+    case MEAS_MAG: /* magnitudes are already determined above */
+      value = M;
+      break;
+    case MEAS_RA: /* OK */
+      value = average[0].R - measure[i].dR / 360000.0;
+      break;
+    case MEAS_DEC: /* OK */
+      value = average[0].D - measure[i].dD / 360000.0;
+      break;
+    case MEAS_dMAG: /* OK */
+      value = 0.001*measure[i].dM;
+      break;
+    case MEAS_AIRMASS: /* OK */
+      value = 0.001*measure[i].airmass;
+      break;
+    case MEAS_EXPTIME: /* OK */
+      value = pow (10.0, measure[i].dt * 0.0004);
+      break;
+    case MEAS_PHOTCODE: /* OK */
+      value = measure[i].source;
+      break;
+    case MEAS_TIME: /* OK */
+      value = TimeValue (measure[i].t, TimeReference, TimeFormat);
+      break;
+    case MEAS_dR: /* OK */
+      value = 0.01*measure[i].dR;
+      break;
+    case MEAS_dD: /* OK */
+      value = 0.01*measure[i].dD;
+      break;
+    case MEAS_FWHM: /* OK */
+      value = 0.01*measure[i].FWx;
+      break;
+    case MEAS_DOPHOT: /* OK */
+      value = measure[i].dophot;
+      break;
+    case MEAS_FLAGS: /* ? */
+      value = measure[i].flags;
+      break;
+    case MEAS_XCCD: /* OK */
+      ra  = average[0].R - measure[i].dR / 360000.0;
+      dec = average[0].D - measure[i].dD / 360000.0;
+      m = match_image_subset (image, subset, Nsubset, measure[i].t, measure[i].source);
+      if (m == -1) {
+	value = 0.0;
+	break;
+      }
+      RD_to_XY (&x, &y, ra, dec, &image[m].coords);
+      value = x;
+      break;
+    case MEAS_YCCD: /* OK */
+      ra  = average[0].R - measure[i].dR / 360000.0;
+      dec = average[0].D - measure[i].dD / 360000.0;
+      m = match_image_subset (image, subset, Nsubset, measure[i].t, measure[i].source);
+      if (m == -1) {
+	value = 0.0;
+	break;
+      }
+      RD_to_XY (&x, &y, ra, dec, &image[m].coords);
+      value = y;
+      break;
+    case MEAS_XMOSAIC: /* OK */
+      ra  = average[0].R - measure[i].dR / 360000.0;
+      dec = average[0].D - measure[i].dD / 360000.0;
+      m = match_image_subset (image, subset, Nsubset, measure[i].t, measure[i].source);
+      if (m == -1) {
+	value = 0.0;
+	break;
+      }
+      mosaic.crval1 = image[m].coords.crval1;
+      mosaic.crval2 = image[m].coords.crval2;
+      RD_to_XY (&x, &y, ra, dec, &mosaic);
+      value = x;
+      break;
+    case MEAS_YMOSAIC: /* OK */
+      ra  = average[0].R - measure[i].dR / 360000.0;
+      dec = average[0].D - measure[i].dD / 360000.0;
+      m = match_image_subset (image, subset, Nsubset, measure[i].t, measure[i].source);
+      if (m == -1) {
+	value = 0.0;
+	break;
+      }
+      mosaic.crval1 = image[m].coords.crval1;
+      mosaic.crval2 = image[m].coords.crval2;
+      RD_to_XY (&x, &y, ra, dec, &mosaic);
+      value = y;
+      break;
+    }
+    list[Nlist] = value;
+    Nlist ++;
+  }
+  *nlist = Nlist;
+  return (list);
+}
+
+/* return average.param based on the selection */
+double ExtractAverages (PhotCode *code, int mode, Average *average, SecFilt *secfilt, Measure *measure, int param) {
+
+  int i, k, Nm, Type;
+  double fwhm, value, dM;
+
+  value = NO_MAG;
+
+  /* need valid code if param is: */
+  switch (param) {
+  case AVE_MAG:
+  case AVE_dMAG:
+  case AVE_Xm:
+  case AVE_TYPE:
+  case AVE_NCODE:
+  case AVE_NPHOT: 
+    if (code == NULL) return (NO_MAG);
+    break;
+  default:
+    break;
+  }
+
+  /* chisq, fwhm, Nphot, Ncode */
+  if (!TestAverage (code, average, secfilt, measure)) return (NO_MAG);
+
+  /* for ErrSelect, check average errors */
+  if (ErrSelect) {
+    dM = iPhotdM (code, average, secfilt);
+    if (dM > ErrValue) return (NO_MAG);
+  }
+  
+  /* for TypeSelect, check on TypeCode for this object */
+  if (TypeSelect) {
+    Type = DetermineTypeCode (average, measure, code[0].code);
+    if (Type != TypeValue) return (NO_MAG);
+  }
+
+  /* assign vector values */
+  switch (param) {
+  case AVE_RA:
+    value = average[0].R;
+    break;
+  case AVE_DEC:
+    value = average[0].D;
+    break;
+  case AVE_NMEAS:
+    value = average[0].Nm;
+    break;
+  case AVE_NMISS:
+    value = average[0].Nn;
+    break;
+  case AVE_Xp:
+    value = 0.01*average[0].Xp;
+    break;
+  case AVE_FLAG:
+    value = average[0].code;
+    break;
+  case AVE_MAG:
+    switch (mode) {
+    case MAG_AVE:
+      value = PhotAve  (code, average, secfilt);
+      break;
+    case MAG_REF:
+      value = PhotRef  (code, average, secfilt, measure);
+      break;
+    }
+    break;
+  case AVE_dMAG:
+    value = PhotdM (code, average, secfilt);
+    break;
+  case AVE_Xm:
+    value = PhotXm (code, average, secfilt);
+    break;
+  case AVE_TYPE:
+    value = DetermineTypeCode (average, measure, code[0].code);
+    break;
+  case AVE_NCODE:
+    value = 0;
+    for (i = 0; i < average[0].Nm; i++) {
+      if (code[0].code != GetPhotcodeEquivCodebyCode (measure[i].source)) continue;
+      value ++;
+    }
+    break;
+  case AVE_NPHOT:
+    value = 0;
+    for (i = 0; i < average[0].Nm; i++) {
+      if (code[0].code != GetPhotcodeEquivCodebyCode (measure[i].source)) continue;
+      if (measure[i].flags & (ID_MEAS_POOR | ID_MEAS_SKIP)) continue;
+      value ++;
+    }
+    break;
+  case AVE_NCRIT:
+    value = 0;
+    for (i = 0; i < average[0].Nm; i++) {
+      if (code[0].code != GetPhotcodeEquivCodebyCode (measure[i].source)) continue;
+      if (ErrSelect && (measure[i].dM > ErrValue)) continue;
+      if (FlagSelect && (measure[i].flags != FlagValue)) continue;
+      if (TypeSelect && (TypeValue != GetMeasureTypeCode (&measure[i]))) continue;
+      if (iMagSelect && (PhotInst (&measure[i]) < iMagMin)) continue;
+      value ++;
+    }
+    break;
+  }
+  return (value);
+}  
+
+/* determine the representative dophot type for this photcode */
+int DetermineTypeCode (Average *average, Measure *measure, int code) {
+
+  int k, N, Nt[3];
+  
+  Nt[0] = Nt[1] = Nt[2] = 0;
+  for (k = 0; k < average[0].Nm; k++) {
+    if (code != GetPhotcodeEquivCodebyCode (measure[k].source)) continue;
+    N = GetMeasureTypeCode (&measure[k]);
+    Nt[N] ++;
+  }
+  if (Nt[0]) return (0);
+  if (Nt[1]) return (1);
+  if (Nt[2]) return (2);
+  return (3);
+}
+
+int GetMeasureTypeCode (Measure *measure) {
+  switch (measure[0].dophot) {
+  case 0:
+  case 1:
+  case 2:
+    return (0);
+    break;
+  case 3:
+  case 4:
+  case 5:
+  case 7:
+  case 9:
+    return (1);
+    break;
+  case 10:
+  default:
+    return (2);
+  }
+  return (2);
+}  
+
+int Quality (Measure *measure, int IsDophot) {
+
+  return (TRUE);
+  
+  if (IsDophot) {
+    
+    if (measure[0].dophot == 4) return (FALSE);
+    return (TRUE);
+  
+  } else {
+    
+    if (0.01 * measure[0].FWx < 3.0) return (FALSE);
+    if (0.01 * measure[0].FWx > 10.0) return (FALSE);
+
+    return (TRUE);
+
+  }
+}
+
+int TestAverage (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure) {
+
+  int i, Nm;
+  double value, fwhm;
+
+  /* exclusions based on average.params  */
+  if (ChiSelect) {
+    /* some average.params need a valid photcode for reference */
+    if (code == NULL) return (FALSE);
+    value = PhotXm (code, average, secfilt);
+    if (value == -1) return (FALSE);
+    if (value > ChiLimit) return (FALSE);
+  }
+  
+  /* pass objects with more than FWHMfrac points with FWHM above / below FWHMvalue */ 
+  if (FWHMSelect) {
+    Nm = 0;
+    for (i = 0; i < average[0].Nm; i++) {
+      fwhm = measure[i].FWx / 100.0;
+      switch (FWHMsign) {
+      case 0:
+	if (fwhm == FWHMvalue) break;
+	continue;
+      case +1:
+	if (fwhm >= FWHMvalue) break;
+	continue;
+      case -1:
+	if (fwhm <= FWHMvalue) break;
+	continue;
+      }
+      Nm++;
+    }
+    if (average[0].Nm * FWHMfrac > Nm) return (FALSE);
+  }
+
+  /* for NcodeSelect, count Nmeas for appropriate photcode */
+  if (NcodeSelect) {
+    Nm = 0;
+    for (i = 0; i < average[0].Nm; i++) {
+      TESTCODE (code, measure[i]);
+      Nm++;
+    }
+    switch (NcodeSign) {
+    case 0:
+      if (Nm == NcodeValue) break;
+      return (FALSE);
+    case 1:
+      if (Nm >= NcodeValue) break;
+      return (FALSE);
+    case -1:
+      if (Nm <= NcodeValue) break;
+      return (FALSE);
+    default:
+      return (FALSE);
+    }
+  }
+
+  /* for NphotSelect, count Nmeas for appropriate photcode */
+  if (NphotSelect) {
+    Nm = 0;
+    for (i = 0; i < average[0].Nm; i++) {
+      TESTCODE (code, measure[i]);
+      if (measure[i].flags && ID_MEAS_SKIP) continue;
+      Nm++;
+    }
+    switch (NphotSign) {
+    case 0:
+      if (Nm == NphotValue) break;
+      return (FALSE);
+    case 1:
+      if (Nm >= NphotValue) break;
+      return (FALSE);
+    case -1:
+      if (Nm <= NphotValue) break;
+      return (FALSE);
+    default:
+      return (FALSE);
+    }
+  }
+  return (TRUE);
+}
+
+/* for this function, we don't need to call PhotRel, etc, but we
+   do need to multiply by 0.001:
+   average[].M is stored as 1000*mag where mag is PhotAbs
+   measure[].M for PHOT_REL is the same 
+*/ 
+
+/* send in:
+   Nphot - photcode number
+   Tphot - photcode type
+   Ns    - secfilt entry (-1 for PRI)
+   &catalog.average[i], 
+   &catalog.measure[catalog.average[i].offset], 
+   &catalog.secfilt[i*Nsec] 
+*/
+
+
+double *ExtractMagnitudes (PhotCode *code, int mode, Average *average, SecFilt *secfilt, Measure *measure, int *n) {
+  
+  double *M, mag;
+  int N;
+
+  if ((mode == MAG_AVE) || (mode == MAG_REF)) {
+    ALLOCATE (M, double, 1);
+    mag = ExtractAverages (code, mode, average, secfilt, measure, AVE_MAG);
+    if (mag == NO_MAG) {
+      N = 0;
+    } else {
+      N = 1;
+      M[0] = mag;
+    }
+  } else {
+    M = ExtractMeasures (code, mode, average, secfilt, measure, &N, MEAS_MAG);
+  }
+  
+  *n = N;
+  return (M);
+}
+
+double *ExtractDMag (PhotCode **code, int *mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist) {
+
+  int i, j, A1, A2, N1, N2, Nlist, NLIST;
+  double *M1, *M2, *list;
+
+  /* check for special case of measure-measure */
+  A1 = ((mode[0] == MAG_AVE) || (mode[0] == MAG_REF));
+  A2 = ((mode[1] == MAG_AVE) || (mode[1] == MAG_REF));
+  if (!A1 && !A2) {
+    list = ExtractMeasuresDMag (code, mode, average, secfilt, measure, nlist);
+    return (list);
+  }
+
+  *nlist = 0; 
+  Nlist = 0;
+  NLIST = MAX (1, average[0].Nm*average[0].Nm);
+  ALLOCATE (list, double, NLIST);
+  M1 = M2 = NULL;
+
+  /* one of the two is an average, must do independently */
+  M1 = ExtractMagnitudes (code[0], mode[0], average, secfilt, measure, &N1);
+  if (N1 == 0) goto skip;
+  
+  M2 = ExtractMagnitudes (code[1], mode[1], average, secfilt, measure, &N2);
+  if (N2 == 0) goto skip;
+
+  /* average mags can return NO_MAG : skip them? */
+  for (i = 0; i < N1; i++) {
+    for (j = 0; j < N2; j++) {
+      list[Nlist] = M1[i] - M2[j];
+      Nlist ++;
+    }
+  }
+  *nlist = Nlist;
+  return (list);
+
+ skip: 
+  if (M1 != NULL) free (M1);
+  if (M2 != NULL) free (M2);
+  M1 = M2 = NULL;
+  return (list);
+}
+  
+/* extract a list of delta-measure-mags from the specified average entry based on the pre-set selections */
+double *ExtractMeasuresDMag (PhotCode **code, int *mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist) {
+
+  int i, j, Nlist, NLIST;
+  double *list, M1, M2, value;
+  
+  *nlist = 0; 
+  Nlist = 0;
+  NLIST = MAX (1, average[0].Nm*average[0].Nm);
+  ALLOCATE (list, double, NLIST);
+
+  /* must have two code values */
+  if (code == NULL) return (list);
+  if (code[0] == NULL) return (list);
+  if (code[1] == NULL) return (list);
+
+  /* exclude based on chisq for both codes  */
+  if (ChiSelect) {
+    value = PhotXm (code[0], average, secfilt);
+    if (value == -1) return (list);
+    if (value > ChiLimit) return (list);
+    value = PhotXm (code[1], average, secfilt);
+    if (value == -1) return (list);
+    if (value > ChiLimit) return (list);
+  }
+
+  /* loop twice over all measures */
+  for (i = 0; i < average[0].Nm; i++) {
+    TESTCODE (code[0], measure[i]);
+    TESTMEASURE (measure[i]);
+    SETMAG(M1, measure[i], mode[0]);
+    for (j = 0; j < average[0].Nm; j++) {
+      if (i == j) continue;
+      TESTCODE (code[1], measure[j]);
+      TESTMEASURE (measure[j]);
+      SETMAG(M2, measure[j], mode[1]);
+      list[Nlist] = M1 - M2;
+      Nlist ++;
+    }
+  }
+  *nlist = Nlist;
+  return (list);
+}
+
+double *ExtractByDMag (PhotCode **code, int *mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist, int param) {
+
+  int A1, A2, N1;
+  double *list;
+
+  /* check for special case of measure-measure */
+  A1 = ((mode[0] == MAG_AVE) || (mode[0] == MAG_REF));
+  A2 = ((mode[1] == MAG_AVE) || (mode[1] == MAG_REF));
+  if (!A1 && !A2) {
+    list = ExtractMeasuresByDMag (code, mode, 1, average, secfilt, measure, nlist, param);
+    return (list);
+  }
+
+  if (A1) {
+    list = ExtractMeasures (code[1], mode[1], average, secfilt, measure, &N1, param);
+  } else {
+    list = ExtractMeasures (code[0], mode[0], average, secfilt, measure, &N1, param);
+  }
+  *nlist = N1;
+  return (list);
+}
+  
+/* extract a list of delta-measure-mags from the specified average entry based on the pre-set selections */
+double *ExtractMeasuresByDMag (PhotCode **code, int *mode, int use_first, Average *average, SecFilt *secfilt, Measure *measure, int *nlist, int param) {
+
+  int i, j, k, m, n, Nlist, NLIST;
+  time_t t;
+  int np, found;
+  double *list, M1, M2, value;
+  double ra, dec, x, y;
+  
+  *nlist = 0; 
+  Nlist = 0;
+  NLIST = MAX (1, average[0].Nm*average[0].Nm);
+  ALLOCATE (list, double, NLIST);
+
+  /* must have two code values */
+  if (code == NULL) return (list);
+  if (code[0] == NULL) return (list);
+  if (code[1] == NULL) return (list);
+
+  /* chisq, fwhm, Nphot, Ncode */
+  if (!TestAverage (code[0], average, secfilt, measure)) return (list);
+  if (!TestAverage (code[1], average, secfilt, measure)) return (list);
+
+  /* loop twice over all measures */
+  for (i = 0; i < average[0].Nm; i++) {
+    TESTCODE (code[0], measure[i]);
+    TESTMEASURE (measure[i]);
+    SETMAG(M1, measure[i], mode[0]);
+    for (j = 0; j < average[0].Nm; j++) {
+      if (i == j) continue;
+      TESTCODE (code[1], measure[j]);
+      TESTMEASURE (measure[j]);
+      SETMAG(M2, measure[j], mode[1]);
+      if (use_first) 
+	n = i;
+      else 
+	n = j;
+      /* assign value */
+      switch (param) {
+      case MEAS_MAG: /* magnitudes are already determined above */
+	value = use_first ? M1 : M2;
+	break;
+      case MEAS_RA: /* OK */
+	value = average[0].R - measure[n].dR / 360000.0;
+	break;
+      case MEAS_DEC: /* OK */
+	value = average[0].D - measure[n].dD / 360000.0;
+	break;
+      case MEAS_dMAG: /* OK */
+	value = 0.001*measure[n].dM;
+	break;
+      case MEAS_AIRMASS: /* OK */
+	value = 0.001*measure[n].airmass;
+	break;
+      case MEAS_EXPTIME: /* OK */
+	value = pow (10.0, measure[n].dt * 0.0004);
+	break;
+      case MEAS_PHOTCODE: /* OK */
+	value = measure[n].source;
+	break;
+      case MEAS_TIME: /* OK */
+	value = TimeValue (measure[n].t, TimeReference, TimeFormat);
+	break;
+      case MEAS_dR: /* OK */
+	value = 0.01*measure[n].dR;
+	break;
+      case MEAS_dD: /* OK */
+	value = 0.01*measure[n].dD;
+	break;
+      case MEAS_FWHM: /* OK */
+	value = 0.01*measure[n].FWx;
+	break;
+      case MEAS_DOPHOT: /* OK */
+	value = measure[n].dophot;
+	break;
+      case MEAS_FLAGS: /* ? */
+	value = measure[n].flags;
+	break;
+    case MEAS_XCCD: /* OK */
+      ra  = average[0].R - measure[n].dR / 360000.0;
+      dec = average[0].D - measure[n].dD / 360000.0;
+      m = match_image_subset (image, subset, Nsubset, measure[n].t, measure[n].source);
+      if (m == -1) {
+	value = 0.0;
+	break;
+      }
+      RD_to_XY (&x, &y, ra, dec, &image[m].coords);
+      value = x;
+      break;
+    case MEAS_YCCD: /* OK */
+      ra  = average[0].R - measure[n].dR / 360000.0;
+      dec = average[0].D - measure[n].dD / 360000.0;
+      m = match_image_subset (image, subset, Nsubset, measure[n].t, measure[n].source);
+      if (m == -1) {
+	value = 0.0;
+	break;
+      }
+      RD_to_XY (&x, &y, ra, dec, &image[m].coords);
+      value = y;
+      break;
+    case MEAS_XMOSAIC: /* OK */
+      ra  = average[0].R - measure[n].dR / 360000.0;
+      dec = average[0].D - measure[n].dD / 360000.0;
+      m = match_image_subset (image, subset, Nsubset, measure[n].t, measure[n].source);
+      if (m == -1) {
+	value = 0.0;
+	break;
+      }
+      mosaic.crval1 = image[m].coords.crval1;
+      mosaic.crval2 = image[m].coords.crval2;
+      RD_to_XY (&x, &y, ra, dec, &mosaic);
+      value = x;
+      break;
+    case MEAS_YMOSAIC: /* OK */
+      ra  = average[0].R - measure[n].dR / 360000.0;
+      dec = average[0].D - measure[n].dD / 360000.0;
+      m = match_image_subset (image, subset, Nsubset, measure[n].t, measure[n].source);
+      if (m == -1) {
+	value = 0.0;
+	break;
+      }
+      mosaic.crval1 = image[m].coords.crval1;
+      mosaic.crval2 = image[m].coords.crval2;
+      RD_to_XY (&x, &y, ra, dec, &mosaic);
+      value = y;
+      break;
+      }
+      list[Nlist] = value;
+      Nlist ++;
+    }
+  }
+  *nlist = Nlist;
+  return (list);
+}
+
Index: /tags/start/Ohana/src/opihi/dvo/pmeasure.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/pmeasure.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/pmeasure.c	(revision 12606)
@@ -0,0 +1,151 @@
+# include "dvo.h"
+
+int pmeasure (int argc, char **argv) {
+  
+  FILE *f;
+  int i, j, k, m, N;
+  int InRegion, Nregions, Ngraph;
+  char filename[128], catdir[256];
+  double Mz, Mr, mag;
+  double Radius, Rmin, Rmax;
+  unsigned IDclip, IDchoice, LimExclude;
+  unsigned FlagChoice, FlagClip, flags;
+
+  Catalog catalog;
+  RegionFile *regions;
+  Graphdata graphmode;
+  Vector Xvec, Yvec, Zvec;
+
+  Ngraph = -1;
+  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);
+  if (VarConfig ("CATDIR", "%s", catdir) == NULL) return (FALSE);
+  if (!InitPhotcodes ()) return (FALSE);
+
+  regions = (RegionFile *) NULL;
+  f = (FILE *) NULL;
+  Mz = 17.0;
+  Mr = -5.0;
+  Rmin = graphmode.coords.crval1 - 182.0;
+  Rmax = graphmode.coords.crval1 + 182.0;
+
+  IDclip = FALSE;
+  if (N = get_argument (argc, argv, "-ID")) {
+    remove_argument (N, &argc, argv);
+    IDchoice  = atoi(argv[N]);
+    remove_argument (N, &argc, argv);
+    IDclip = TRUE;
+  }
+  FlagClip = FALSE;
+  if (N = get_argument (argc, argv, "-flag")) {
+    remove_argument (N, &argc, argv);
+    FlagChoice  = atoi(argv[N]);
+    remove_argument (N, &argc, argv);
+    FlagClip = TRUE;
+  }
+
+  LimExclude = FALSE;
+  if (N = get_argument (argc, argv, "-x")) {
+    remove_argument (N, &argc, argv);
+    LimExclude = TRUE;
+  }
+
+  if (N = get_argument (argc, argv, "-m")) {
+    remove_argument (N, &argc, argv);
+    Mr  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    Mz = atof(argv[N]);
+    Mr = Mr - Mz;
+    remove_argument (N, &argc, argv);
+  }
+
+  InRegion = FALSE;
+  if (N = get_argument (argc, argv, "-all")) {
+    remove_argument (N, &argc, argv);
+    InRegion = TRUE;
+  }
+
+  if ((InRegion || (argc != 2)) && (!InRegion || (argc != 1))) {
+    fprintf (stderr, "USAGE: catalog (filename / -all) [-m M M] [-n N N] [-g] [-a RA DEC MAG] \n");
+    return (FALSE);
+  }
+  
+  if (InRegion) {
+    Radius = MAX (fabs(graphmode.xmax), fabs(graphmode.ymax));
+    regions = find_regions (graphmode.coords.crval1, graphmode.coords.crval2, Radius, &Nregions);
+  } else {
+    Nregions = 1;
+  }
+  
+  for (j = 0; j < Nregions; j++) {
+    catalog.average = 0;
+    
+    if (InRegion) {
+      sprintf (filename, "%s/%s", catdir, regions[j].name);
+    } else {
+      sprintf (filename, "%s/%s", catdir, argv[1]);
+    }
+    
+    /* lock, load, unlock catalog */
+    catalog.filename = filename;
+    switch (lock_catalog (&catalog, LCK_SOFT)) {
+    case 2:
+      unlock_catalog (&catalog);
+    case 0:
+      continue;
+    }
+    if (!load_catalog (&catalog, LOAD_AVES | LOAD_MEAS, TRUE)) {
+      unlock_catalog (&catalog);
+      continue;
+    }
+    unlock_catalog (&catalog);
+
+    /* data has been loaded, get ready to plot it */
+    Xvec.Nelements = catalog.Nmeasure;
+    Yvec.Nelements = catalog.Nmeasure;
+    Zvec.Nelements = catalog.Nmeasure;
+    ALLOCATE (Xvec.elements, float, Xvec.Nelements);
+    ALLOCATE (Yvec.elements, float, Yvec.Nelements);
+    ALLOCATE (Zvec.elements, float, Zvec.Nelements);
+
+    /* project stars to screen display coords */
+    Xvec.Nelements = 0;
+    for (N = i = 0; i < catalog.Naverage; i++) {
+      if (IDclip && (catalog.average[i].code != IDchoice)) continue;
+      while (catalog.average[i].R < Rmin) catalog.average[i].R += 360.0;
+      while (catalog.average[i].R > Rmax) catalog.average[i].R -= 360.0;
+      m = catalog.average[i].offset;
+      for (k = 0; k < catalog.average[i].Nm; k++) {
+	if (FlagClip) {
+	  flags = catalog.measure[m+k].flags;
+	  if (!(flags & FlagChoice)) continue;
+	}
+	mag = PhotCat (&catalog.measure[m+k]);
+	Zvec.elements[N] = MIN (1.0, MAX (0.01, (mag - Mz) / Mr));
+	if (LimExclude && (Zvec.elements[N] > 0.99)) continue;
+	if (Zvec.elements[N] < 0.011) continue;
+	fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], catalog.average[i].R - 2.777e-6*catalog.measure[m+k].dR, catalog.average[i].D - 2.777e-6*catalog.measure[m+k].dD, &graphmode.coords);
+	N ++;
+      }
+    }
+    Zvec.Nelements = Yvec.Nelements = Xvec.Nelements = N;
+
+    graphmode.style = 2; /* set style to points */
+    graphmode.size = -1; /* point size determined by Zvec */
+    graphmode.etype = 0; /* no errorbars */
+    PrepPlotting (N, &graphmode);
+    
+    PlotVector (N, Xvec.elements);
+    PlotVector (N, Yvec.elements);
+    PlotVector (N, Zvec.elements);
+
+    free (Xvec.elements);
+    free (Yvec.elements);
+    free (Zvec.elements);
+
+    if (catalog.average != 0) free (catalog.average);
+    if (catalog.measure != 0) free (catalog.measure);
+  }
+  return (TRUE);
+
+}
+  
Index: /tags/start/Ohana/src/opihi/dvo/procks.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/procks.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/procks.c	(revision 12606)
@@ -0,0 +1,159 @@
+# include "dvo.h"
+
+typedef struct {
+  double ra[3];
+  double dec[3];
+  double X[3];
+  double Y[3];
+  unsigned int t[3];
+  double mag[3];
+} Rocks;
+static Rocks *rocks = (Rocks *) NULL;
+static int   Nrocks;
+
+int procks (int argc, char **argv) {
+  
+  FILE *f;
+  Vector Xvec, Yvec;
+  int i, j, N, NROCKS;
+  int N0, N1, SpeedClip, Reload;
+  unsigned int t0, t1;
+  double Mz, Mr, S0, S1;
+  double Rmin, Rmax;
+  Graphdata graphmode;
+  char rockcat[256];
+  int Ngraph;
+
+  Ngraph = 0;
+  VarConfig ("ROCK_CATALOG", "%s", rockcat);
+  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);
+
+  f = (FILE *) NULL;
+  Mz = 17.0;
+  Mr = -5.0;
+  Rmin = graphmode.coords.crval1 - 182.0;
+  Rmax = graphmode.coords.crval1 + 182.0;
+
+  if (N = get_argument (argc, argv, "-m")) {
+    remove_argument (N, &argc, argv);
+    Mr  = 1000*atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    Mz = 1000*atof(argv[N]);
+    Mr = Mr - Mz;
+    remove_argument (N, &argc, argv);
+  }
+
+  SpeedClip = FALSE;
+  if (N = get_argument (argc, argv, "-speed")) {
+    SpeedClip = TRUE;
+    remove_argument (N, &argc, argv);
+    S0 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    S1 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Reload = FALSE;
+  if (N = get_argument (argc, argv, "-reload")) {
+    Reload = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: procks [-m M M] [-speed s s] \n");
+    return (FALSE);
+  }
+  
+  f = fopen (rockcat, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open rock catalog\n");
+    return (TRUE);
+  }
+
+  if ((rocks == (Rocks *) NULL) || Reload) {
+    if (rocks != (Rocks *) NULL) free (rocks);
+    NROCKS = 100;
+    ALLOCATE (rocks, Rocks, NROCKS);
+    for (i = 0; fscanf (f, "%lf %lf %d%lf%lf%lf %d%lf%lf%lf %d%lf%lf%lf", 
+			&rocks[i].X[0], &rocks[i].Y[0], 
+			&rocks[i].t[0], &rocks[i].ra[0], &rocks[i].dec[0], &rocks[i].mag[0], 
+			&rocks[i].t[1], &rocks[i].ra[1], &rocks[i].dec[1], &rocks[i].mag[1], 
+			&rocks[i].t[2], &rocks[i].ra[2], &rocks[i].dec[2], &rocks[i].mag[2]
+			) != EOF; i++) {
+      if (i == NROCKS - 1) {
+	NROCKS += 100;
+	REALLOCATE (rocks, Rocks, NROCKS);
+      }
+    }
+    Nrocks = i;
+  }
+      
+  if (Nrocks == 0) {
+    free (rocks);
+    fprintf (stderr, "no rocks in datafile\n");
+    return (TRUE);
+  }
+
+  /* data has been loaded, get ready to plot it */
+  Yvec.Nelements = Xvec.Nelements = 3*Nrocks;
+  ALLOCATE (Xvec.elements, float, Xvec.Nelements);
+  ALLOCATE (Yvec.elements, float, Yvec.Nelements);
+  
+  /* project stars to screen display coords */
+  for (N = i = 0; i < Nrocks; i++) {
+    if (SpeedClip && ((rocks[i].Y[0] < S0) || (rocks[i].Y[0] > S1))) continue;
+    for (j = 0; j < 3; j++) {
+      while (rocks[i].ra[j] < Rmin) rocks[i].ra[j] += 360.0;
+      while (rocks[i].ra[j] > Rmax) rocks[i].ra[j] -= 360.0;
+      fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], rocks[i].ra[j], rocks[i].dec[j], &graphmode.coords);
+      N ++;
+    }
+  }
+  Yvec.Nelements = Xvec.Nelements = N;
+  
+  graphmode.style = 2; /* set style to points */
+  graphmode.etype = 0; /* no errorbars */
+  PrepPlotting (N, &graphmode);
+  
+  PlotVector (N, Xvec.elements);
+  PlotVector (N, Yvec.elements);
+
+  /* now plot vectors between two extrema */
+  Yvec.Nelements = Xvec.Nelements = 2*Nrocks;
+  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
+  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
+  
+  /* project stars to screen display coords */
+  for (N = i = 0; i < Nrocks; i++) {
+    if (SpeedClip && ((rocks[i].Y[0] < S0) || (rocks[i].Y[0] > S1))) continue;
+    N0 = N1 = 0;
+    t0 = t1 = rocks[i].t[0];
+    for (j = 1; j < 3; j++) {
+      if (rocks[i].t[j] < t0) { N0 = j; t0 = rocks[i].t[j]; }
+      if (rocks[i].t[j] > t1) { N1 = j; t1 = rocks[i].t[j]; }
+    }
+    while (rocks[i].ra[N0] < Rmin) rocks[i].ra[N0] += 360.0;
+    while (rocks[i].ra[N0] > Rmax) rocks[i].ra[N0] -= 360.0;
+    while (rocks[i].ra[N1] < Rmin) rocks[i].ra[N1] += 360.0;
+    while (rocks[i].ra[N1] > Rmax) rocks[i].ra[N1] -= 360.0;
+    fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], rocks[i].ra[N0], rocks[i].dec[N0], &graphmode.coords);
+    N ++;
+    fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], rocks[i].ra[N1], rocks[i].dec[N1], &graphmode.coords);
+    N ++;
+  }
+  Yvec.Nelements = Xvec.Nelements = N;
+  
+  graphmode.style = 2; /* set style to points */
+  graphmode.ptype = 100; /* connect pairs */
+  graphmode.etype = 0; /* no errorbars */
+  PrepPlotting (N, &graphmode);
+  
+  PlotVector (N, Xvec.elements);
+  PlotVector (N, Yvec.elements);
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+  return (TRUE);
+
+}
+  
Index: /tags/start/Ohana/src/opihi/dvo/region_list.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/region_list.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/region_list.c	(revision 12606)
@@ -0,0 +1,34 @@
+# include "dvo.h"
+
+/* returns a list of region files names from file */
+RegionFile *region_list (char *filename, int *Nregions) {
+  
+  int NREGIONS, nregion;
+  RegionFile *regions;
+  FILE *f;
+
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find region list file %s\n", filename);
+    *Nregions = 0;
+    return ((RegionFile *) NULL);
+  }
+  
+  NREGIONS = 50;
+  ALLOCATE (regions, RegionFile, NREGIONS);
+  nregion = 0;
+
+  while (fscanf (f, "%s", regions[nregion].name) != EOF) {
+    nregion ++;
+    if (nregion == NREGIONS) {
+      NREGIONS += 50;
+      REALLOCATE (regions, RegionFile, NREGIONS);
+    }
+  }
+
+  *Nregions = nregion;
+
+  return (regions);
+
+}
+
Index: /tags/start/Ohana/src/opihi/dvo/showtile.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/showtile.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/showtile.c	(revision 12606)
@@ -0,0 +1,99 @@
+# include "dvo.h"
+static float dr[] = {0.0, 1.0, 1.0, 0.0};
+static float dd[] = {0.0, 0.0, 1.0, 1.0};
+
+int showtile (int argc, char **argv) {
+
+  int Nd, N, NPTS, Ngraph, status, i, InPic;
+  Graphdata graphmode;
+  Coords coords;
+  Vector Xvec, Yvec;
+  float r, d, R, D;
+  float Ro[90], Do[90];
+
+  /* show tile pattern in viewed region */
+
+  Ngraph = 0;
+  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: showtile [option]\n");
+    return (FALSE);
+  }
+  
+  N = 0;
+  NPTS = 200;
+  ALLOCATE (Xvec.elements, float, NPTS);
+  ALLOCATE (Yvec.elements, float, NPTS);
+
+  /* starting position */
+
+  /* reference for coords is this image */
+  coords.crpix1 = coords.crpix2 = 0.0;
+  coords.crval1 = coords.crval2 = 0.0;
+  coords.cdelt1 = coords.cdelt2 = 1.0;
+  coords.pc1_1  = coords.pc2_2  = 1.0;
+  coords.pc1_2  = coords.pc2_1  = 0.0;
+  coords.Npolyterms = 0;
+  strcpy (coords.ctype, "RA---TAN");
+  
+  /* fill in top-left region */
+  for (r = 0; r < 3; r += 1.0) {
+    fprintf (stderr, "r: %f\n", r);
+    for (Nd = d = 0; d < 90; Nd ++, d += 1.0) {
+      if (r == 0) {
+	coords.crval1 = r;
+	coords.crval2 = d;
+      } else {
+	coords.crval1 = Ro[Nd];
+	coords.crval2 = Do[Nd];
+      }
+      for (i = 0; i < 4; i++) {
+	fXY_to_RD (&R, &D, dr[i], dd[i], &coords);
+	status |= fRD_to_XY (&Xvec.elements[N+2*i], &Yvec.elements[N+2*i], R, D, &graphmode.coords);
+	if (i > 0) {
+	  Xvec.elements[N+2*i - 1] = Xvec.elements[N+2*i];
+	  Yvec.elements[N+2*i - 1] = Yvec.elements[N+2*i];
+	}
+	if (i == 1) {
+	  Ro[Nd] = R;
+	  Do[Nd] = D;
+	}
+      }
+      Xvec.elements[N+7] = Xvec.elements[N];
+      Yvec.elements[N+7] = Yvec.elements[N];
+
+      /* check if any corner is in plotting region */
+      InPic = FALSE;
+      for (i = 0; i < 8; i+=2) {
+	if ((Xvec.elements[N+i] >= graphmode.xmin) && 
+	    (Xvec.elements[N+i] <= graphmode.xmax) && 
+	    (Yvec.elements[N+i] >= graphmode.ymin) && 
+	    (Yvec.elements[N+i] <= graphmode.ymax))
+	  InPic = TRUE;
+      }
+      if (!InPic) continue;
+      N+=8;
+      if (N > NPTS - 1) {  /* this is OK because NPTS is made always a multiple of 8 */
+	NPTS += 200;
+	REALLOCATE (Xvec.elements, float, NPTS);
+	REALLOCATE (Yvec.elements, float, NPTS);
+      }
+    }
+  }
+  
+  Xvec.Nelements = Xvec.Nelements = N;
+  if (N > 0) {
+    graphmode.style = 2; /* points */
+    graphmode.ptype = 100; /* connect pairs of points */
+    graphmode.etype = 0;
+    PrepPlotting (N, &graphmode);
+    PlotVector (N, Xvec.elements);
+    PlotVector (N, Yvec.elements);
+  }
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/dvo/simage.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/simage.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/simage.c	(revision 12606)
@@ -0,0 +1,173 @@
+# include "dvo.h"
+# define D_NSTARS 1000
+# define BYTES_STAR 31
+# define BLOCK 1000
+
+int simage (int argc, char **argv) {
+
+  char *buffer;
+  Vector Xvec, Yvec, Zvec;
+  double R, D, X, Y, M, zero, range;
+  FILE *f;
+  Header header;
+  Coords coords;
+  int i, j, Nstars, nstars, Nbytes, nbytes, Npts, N;
+  Graphdata graphmode;
+  int Ngraph;
+
+  Ngraph = 0;
+  if (!GetGraph (&graphmode, NULL, &Ngraph)) return (FALSE);
+
+  zero = 17.0;
+  range = -5.0;
+  if (N = get_argument (argc, argv, "-m")) {
+    remove_argument (N, &argc, argv);
+    range = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    zero  = atof(argv[N]);
+    range = range - zero;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: image (filename)\n");
+    return (FALSE);
+  }
+
+  fprintf (stderr, "not working at the moment (cmp format)\n");
+  return (FALSE);
+  
+  /* read header */
+  if (!fits_read_header (argv[1], &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s\n", argv[1]);
+    return (FALSE);
+  }
+  /* get astrometry information */
+  strcpy (coords.ctype, "NONE");
+  fits_scan (&header, "CTYPE1",   "%s",  1, coords.ctype);
+  if (strcmp (coords.ctype, "RA---PLY")) {
+    fprintf (stderr, "ERROR: wrong astrometric info in header\n");
+    return (FALSE);
+  }
+  fits_scan (&header, "CDELT1",   "%f", 1, &coords.cdelt1); 
+  fits_scan (&header, "CDELT2",   "%f", 1, &coords.cdelt2);
+  fits_scan (&header, "CRVAL1",   "%lf", 1, &coords.crval1);
+  fits_scan (&header, "CRVAL2",   "%lf", 1, &coords.crval2);  
+  fits_scan (&header, "CRPIX1",   "%f", 1, &coords.crpix1);
+  fits_scan (&header, "CRPIX2",   "%f", 1, &coords.crpix2);
+  fits_scan (&header, "PC001001", "%f", 1, &coords.pc1_1);
+  fits_scan (&header, "PC001002", "%f", 1, &coords.pc1_2);
+  fits_scan (&header, "PC002001", "%f", 1, &coords.pc2_1);
+  fits_scan (&header, "PC002002", "%f", 1, &coords.pc2_2);
+  /* RA Terms */
+  fits_scan (&header, "PCA1X2Y0", "%f", 1, &coords.polyterms[0][0]);
+  fits_scan (&header, "PCA1X1Y1", "%f", 1, &coords.polyterms[1][0]);
+  fits_scan (&header, "PCA1X0Y2", "%f", 1, &coords.polyterms[2][0]);
+  fits_scan (&header, "PCA1X3Y0", "%f", 1, &coords.polyterms[3][0]);
+  fits_scan (&header, "PCA1X2Y1", "%f", 1, &coords.polyterms[4][0]);
+  fits_scan (&header, "PCA1X1Y2", "%f", 1, &coords.polyterms[5][0]);
+  fits_scan (&header, "PCA1X0Y3", "%f", 1, &coords.polyterms[6][0]);
+  /* Dec Terms */			    
+  fits_scan (&header, "PCA2X2Y0", "%f", 1, &coords.polyterms[0][1]);
+  fits_scan (&header, "PCA2X1Y1", "%f", 1, &coords.polyterms[1][1]);
+  fits_scan (&header, "PCA2X0Y2", "%f", 1, &coords.polyterms[2][1]);
+  fits_scan (&header, "PCA2X3Y0", "%f", 1, &coords.polyterms[3][1]);
+  fits_scan (&header, "PCA2X2Y1", "%f", 1, &coords.polyterms[4][1]);
+  fits_scan (&header, "PCA2X1Y2", "%f", 1, &coords.polyterms[5][1]);
+  fits_scan (&header, "PCA2X0Y3", "%f", 1, &coords.polyterms[6][1]);
+  coords.Npolyterms = 2; /* how many do we use? */
+
+  /* find number of stars */
+  fits_scan (&header, "NSTARS", "%d", 1, &Nstars);
+  if (Nstars == 0) {
+    fprintf (stderr, "no stars in file\n");
+    return (FALSE);
+  }
+
+  /* open file data */
+  f = fopen (argv[1], "r");
+  if (f == NULL) {
+    fprintf (stderr, "can't find data in file %s\n", argv[1]);
+    return (FALSE);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* set up storage buffers */
+  Xvec.Nelements = Nstars;
+  Yvec.Nelements = Nstars;
+  Zvec.Nelements = Nstars;
+  ALLOCATE (Xvec.elements, float, Xvec.Nelements);
+  ALLOCATE (Yvec.elements, float, Yvec.Nelements);
+  ALLOCATE (Zvec.elements, float, Zvec.Nelements);
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR));
+
+  /* load in stars by blocks of 1000 */
+  nstars = 0;
+  Nbytes = Nstars*BYTES_STAR;
+  for (i = 0; i < (int)(Nbytes / (BLOCK*BYTES_STAR)); i++) {
+    nbytes = fread (buffer, 1, (BLOCK*BYTES_STAR), f);
+    if (nbytes != BLOCK*BYTES_STAR) {
+      fprintf (stderr, "failed to read in stars (1)\n");
+      free (Xvec.elements);
+      free (Yvec.elements);
+      free (Zvec.elements);
+      free (buffer);
+      return (FALSE);
+    }
+    for (j = 0; j < BLOCK; j++, nstars++) {
+      dparse (&X,  1, &buffer[j*BYTES_STAR]);
+      dparse (&Y,  2, &buffer[j*BYTES_STAR]);
+      dparse (&M,  3, &buffer[j*BYTES_STAR]);
+      XY_to_RD (&R, &D, X, Y, &coords);
+      fRD_to_XY (&Xvec.elements[nstars], &Yvec.elements[nstars], R, D, &graphmode.coords);
+      Zvec.elements[nstars] = MIN (1.0, MAX (0.01, (M - zero) / range));
+    }
+  }
+  /* left over fraction of a block */
+  nbytes = fread (buffer, 1, (Nbytes % (BLOCK*BYTES_STAR)), f);
+  if (nbytes != (Nbytes % (BLOCK*BYTES_STAR))) {
+    fprintf (stderr, "ERROR: failed to read in stars (2)\n");
+    free (Xvec.elements);
+    free (Yvec.elements);
+    free (Zvec.elements);
+    free (buffer);
+    return (FALSE);
+  }
+  for (j = 0; j < nbytes / BYTES_STAR; j++, nstars++) {
+    dparse (&X,  1, &buffer[j*BYTES_STAR]);
+    dparse (&Y,  2, &buffer[j*BYTES_STAR]);
+    dparse (&M,  3, &buffer[j*BYTES_STAR]);
+    XY_to_RD (&R, &D, X, Y, &coords);
+    fRD_to_XY (&Xvec.elements[nstars], &Yvec.elements[nstars], R, D, &graphmode.coords);
+    Zvec.elements[nstars] = MIN (1.0, MAX (0.01, (M - zero) / range));
+  }
+  
+  if (nstars != Nstars) {
+    fprintf (stderr, "ERROR: failed to read in all stars (%d of %d)\n", nstars, Nstars);
+    free (Xvec.elements);
+    free (Yvec.elements);
+    free (Zvec.elements);
+    free (buffer);
+    return (FALSE);
+  }
+
+  graphmode.style = 2;
+  graphmode.size = -1;
+  graphmode.etype = 0;
+  Npts = Xvec.Nelements;
+  PrepPlotting (Npts, &graphmode);
+
+  PlotVector (Npts, Xvec.elements);
+  PlotVector (Npts, Yvec.elements);
+  PlotVector (Npts, Zvec.elements);
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+  free (Zvec.elements);
+  free (buffer);
+
+  return (TRUE);
+
+}
+
+
Index: /tags/start/Ohana/src/opihi/dvo/subpix.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo/subpix.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo/subpix.c	(revision 12606)
@@ -0,0 +1,189 @@
+# include "dvo.h"
+
+int bracket (double *list, double value, int Nlist, int mode);
+
+int subpix (int argc, char **argv) {
+  
+  int i, j, I, Nlo, Nhi, Nentry, Nstars, Nregions, Nimage, Nmeasure;
+  int *index, *entry;
+  int Nmin, Nsub, NSUB, status;
+  int TimeFormat;
+  time_t Timage, TimeReference;
+  double X, Y, Mabs, t;
+  double Ra, Dec, Radius, Radius2, r, Rmin;
+  double *RA, *DEC;
+  char catdir[256], filename[256];
+  
+  Measure *measure;
+  Image *image;
+  RegionFile *regions;
+  Catalog catalog;
+
+  if (!InitPhotcodes ()) return (FALSE);
+
+  VarConfig ("CATDIR", "%s", catdir);
+  GetTimeFormat (&TimeReference, &TimeFormat);
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: subpix ra dec radius\n");
+    return (FALSE);
+  }
+  if (!str_to_radec (&Ra, &Dec, argv[1], argv[2])) return (FALSE);
+  if (Ra < 0) Ra += 360.0;
+  if (Ra > 360.0) Ra -= 360.0;
+  Radius = atof (argv[3]);
+
+  /* load star nearest position */
+  regions = find_regions (Ra, Dec, Radius, &Nregions);
+  if (Nregions > 1) {
+    fprintf (stderr, "warning, radius overlaps region boundary, not yet implemented\n");
+  }
+
+  /* lock, load, unlock catalog */
+  sprintf (filename, "%s/%s", catdir, regions[0].name);
+  catalog.filename = filename;
+  switch (lock_catalog (&catalog, LCK_SOFT)) {
+  case 2:
+    unlock_catalog (&catalog);
+  case 0:
+    return (FALSE);
+  }
+  if (!load_catalog (&catalog, LOAD_AVES | LOAD_MEAS, TRUE)) {
+    unlock_catalog (&catalog);
+    return (FALSE);
+  }
+  unlock_catalog (&catalog);
+
+  /* quick search of star list for Ra, Dec */
+  Nstars = catalog.Naverage;
+  ALLOCATE (RA, double, Nstars);
+  ALLOCATE (DEC, double, Nstars);
+  ALLOCATE (index, int, Nstars);
+  for (i = 0; i < Nstars; i++) {
+    RA[i] = catalog.average[i].R;
+    DEC[i] = catalog.average[i].D;
+    index[i] = i;
+  }
+  if (Nstars > 1) dsort_lists (DEC, RA, index, Nstars);
+
+  /* bracket the DEC range of interest */
+  Nlo = bracket (DEC, Dec - Radius, Nstars, FALSE);
+  Nhi = bracket (DEC, Dec + Radius, Nstars, TRUE);
+  ALLOCATE (entry, int, MAX (Nhi - Nlo, 1));
+  Nentry = 0;
+
+  /* find the list of stars */
+  Radius2 = Radius*Radius;
+  for (i = Nlo; i < Nhi; i++) {
+    r = SQ(Dec - DEC[i]) + SQ(Ra - RA[i]);
+    if (r < Radius2) {
+      entry[Nentry] = i;
+      Nentry ++;
+    }
+  }
+  if (!Nentry) {
+    fprintf (stderr, "no stars found\n");
+    free (RA);
+    free (DEC);
+    free (entry);
+    free (index);
+    if (catalog.average != 0) free (catalog.average);
+    if (catalog.measure != 0) free (catalog.measure);
+    free (regions);
+    return (TRUE);
+  }
+
+  /* find the closest star */
+  Nmin = 0;
+  Rmin = SQ(Dec - DEC[entry[0]]) + SQ(Ra - RA[entry[0]]);
+  for (i = 1; i < Nentry; i++) {
+    r = SQ(Dec - DEC[entry[i]]) + SQ(Ra - RA[entry[i]]);
+    if (r < Rmin) {
+      Rmin = r;
+      Nmin = i;
+    }
+  }
+  Nentry = index[entry[Nmin]];
+  Ra = RA[entry[Nmin]];
+  Dec = DEC[entry[Nmin]];
+  fprintf (stderr, "finding subpix values for star @ %f %f\n", Ra, Dec);
+
+  free (RA);
+  free (DEC);
+  free (entry);
+  free (index);
+
+  /* storage for the image references */
+  Nsub = 0;
+  NSUB = 100;
+  ALLOCATE (index, int, NSUB);
+
+  /* load all images, extract those touching Ra, Dec */
+  image = LoadImages (&Nimage);
+  for (i = 0; i < Nimage; i++) {
+    status = RD_to_XY (&X, &Y, Ra, Dec, &image[i].coords);
+    if (!status || (X < 0) || (X > image[i].NX) || (Y < 0) || (Y > image[i].NY)) continue;
+    index[Nsub] = i;
+    Nsub ++;
+    if (Nsub == NSUB - 1) {
+      NSUB += 100;
+      REALLOCATE (index, int, NSUB);
+    }
+  }
+
+  /* only print the entries for existing measurements of this star */ 
+  measure = &catalog.measure[catalog.average[Nentry].offset];
+  Nmeasure = catalog.average[Nentry].Nm;
+  for (i = 0; i < Nsub; i++) {
+    I = index[i];
+    Timage = image[I].tzero;
+    for (j = 0; j < Nmeasure; j++) {
+      if (measure[j].t == Timage) { 
+	Mabs = PhotCat (&measure[j]);
+	RD_to_XY (&X, &Y, Ra, Dec, &image[I].coords);
+	t = TimeValue (measure[j].t, TimeReference, TimeFormat);
+	fprintf (GetOutfile(), "%f %6.3f %7.2f %7.2f %5.3f\n", t, Mabs, X, Y, 0.001*image[I].secz);
+      } 
+    }
+  }
+
+  if (catalog.average != 0) free (catalog.average);
+  if (catalog.measure != 0) free (catalog.measure);
+  free (image);
+  free (index);
+  free (regions);
+
+  return (TRUE);
+}
+
+/* fast operation to find an entry just below (0) or above (1) value */
+int bracket (double *list, double value, int Nlist, int mode) {
+
+  int Nlo, Nhi, N;
+
+  if (mode == 0) {
+    Nlo = 0; Nhi = Nlist;
+    while (Nhi - Nlo > 10) {
+      N = 0.5*(Nlo + Nhi);
+      if (list[N] < value) {
+	Nlo = N;
+      } else {
+	Nhi = N + 1;
+      }
+    }
+    return (Nlo);
+  }
+  if (mode == 1) {
+    Nlo = 0; Nhi = Nlist;
+    while (Nhi - Nlo > 10) {
+      N = 0.5*(Nlo + Nhi);
+      if (list[N] > value) {
+	Nhi = N;
+      } else {
+	Nlo = N - 1;
+      }
+    }
+    return (Nhi);
+  }
+  return (0);
+}
Index: /tags/start/Ohana/src/opihi/dvo2/Makefile
===================================================================
--- /tags/start/Ohana/src/opihi/dvo2/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo2/Makefile	(revision 12606)
@@ -0,0 +1,118 @@
+include ../../../Configure
+
+default: all
+
+HOME    =       $(ROOT)/src/opihi.v2
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+HELP    =       $(HOME)/help
+SDIR    =       $(HOME)/dvo2
+#
+DESTBIN =       $(LBIN)
+DESTLIB =       $(LLIB)
+DESTINC =       $(LINC)
+DESTMAN =       $(LMAN)
+#  
+INCS    =       -I$(INC) -I$(LINC) -I$(XINC)
+LFLAGS  =       -L$(LLIB) -L$(LIB)
+LIBS1   =       -lFITS -lsocket -lnsl -lreadline -ltermcap -lohana -lm
+LIBS2   =       -lbasiccmd -ldatacmd -lastrocmd -lshell -ldata 
+LIBS    =       $(LIBS2) $(LIBS1) 
+CFLAGS  =       $(INCS)
+CCFLAGS =       $(LIBS) 
+
+# dvo2 user commands and support functions ########################
+
+dvo2 = \
+$(SDIR)/init.$(ARCH).o            \
+$(SDIR)/mkregions.$(ARCH).o	  \
+$(SDIR)/skydbtile.$(ARCH).o	  \
+$(SDIR)/dvo2.$(ARCH).o
+
+all: dvo2
+
+dvo2: $(BIN)/dvo2.$(ARCH)
+	@echo done
+
+$(BIN)/dvo2.$(ARCH) : $(dvo2)
+
+install: $(DESTBIN)/dvo2
+
+# utilities #################################################
+$(BIN)/%.$(ARCH):
+	@if [ ! -d $(BIN) ]; then mkdir -p $(BIN); fi
+	$(CC) $^ -o $@ $(LFLAGS) $(LIBS)
+	@echo "compiled $*"
+	@echo ""
+
+$(DESTBIN)/%: $(BIN)/%.$(ARCH) 
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	rm -f $(DESTBIN)/$*
+	cp $(BIN)/$*.$(ARCH) $(DESTBIN)/$*
+	@echo "installed $*"
+	@echo ""
+
+$(LIB)/%.$(ARCH).a:
+	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
+	rm -f $@
+	ar rcv $@ $^ 
+	ranlib $@
+	@echo "compiled library $*"
+	@echo ""
+
+$(DESTLIB)/%.a: $(LIB)/%.$(ARCH).a
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	@echo ""
+	rm -f $@
+	cp $^ $@
+
+clean:
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f $(LIB)/*.$(ARCH).a
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+dist: clean
+	rm -f $(BIN)/*
+	rm -f $(LIB)/*
+
+lib%.clean:
+	rm -f $(LIB)/lib$*.$(ARCH).a
+	rm -f $($*)
+	@echo ""
+
+%.clean:
+	rm -f $(BIN)/$*.$(ARCH)
+	@echo ""
+
+%.$(ARCH).o : %.c
+	$(CC) $(CFLAGS) -c $*.c -o $@
+
+
+
+## -*- makefile -*- 
+# deprecated functions: verify & delete
+#$(SDIR)/abszero.$(ARCH).o \
+#$(SDIR)/cals.$(ARCH).o \
+#$(SDIR)/dumpmags.$(ARCH).o \
+#$(SDIR)/extract.$(ARCH).o \
+#$(SDIR)/gtypes.$(ARCH).o \
+#$(SDIR)/photresid.$(ARCH).o \
+#$(SDIR)/resid.$(ARCH).o \
+#$(SDIR)/zeropts.$(ARCH).o
+#$(SDIR)/objload.$(ARCH).o \ - make sure we have vect to tv
+#$(SDIR)/ccdextract.$(ARCH).o \
+#$(SDIR)/cmdextract.$(ARCH).o \
+#$(SDIR)/dmagextract.$(ARCH).o \
+#$(SDIR)/ddmagextract.$(ARCH).o \
+
+# future functions, not fully implemented
+#$(SDIR)/detrend.$(ARCH).o \
+#$(SDIR)/getxtra.$(ARCH).o \
+#$(SDIR)/addxtra.$(ARCH).o \
+
+# functions that need to be updated
+#$(SDIR)/gregions.$(ARCH).o \
+
Index: /tags/start/Ohana/src/opihi/dvo2/dvo2.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo2/dvo2.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo2/dvo2.c	(revision 12606)
@@ -0,0 +1,80 @@
+# include "opihi.h"
+
+# define opihi_name "DVO2"
+# define opihi_prompt "dvo2: "
+# define opihi_description "an image manipulation tool\n"
+# define opihi_history ".dvo"
+# define opihi_rcfile ".dvorc"
+
+void InitBasic ();
+void InitData ();
+void InitAstro ();
+void InitDVO2 ();
+
+void welcome () {
+  fprintf (stderr, "\n");
+  fprintf (stderr, "Welcome to %s - %s\n\n", opihi_name, opihi_description);
+}
+
+/* program-dependent initialization */
+void initialize (int argc, char **argv) {
+  
+  FILE *f;
+
+  auto_break = TRUE;
+
+  Nlists = 0;
+  ALLOCATE (lists, List, 1); 
+
+  /* init functions required by libraries */
+  /* -libopihi */
+  InitCommands ();
+  InitMacros ();
+  InitBuffers ();
+  InitVectors ();
+  InitVariables ();
+
+  /* -libdisplay */
+  InitGraph ();
+  InitImage ();
+
+  /* load the commands used by this implementation */
+  InitBasic ();
+  InitData ();
+  InitAstro ();
+  InitDVO2 ();
+  InitOutfile ();
+
+  rl_readline_name = opihi_name;
+  rl_attempted_completion_function = command_completer;
+
+  set_str_variable ("HISTORY", opihi_history);
+  set_str_variable ("PROMPT", opihi_prompt);
+  set_str_variable ("RCFILE", opihi_rcfile);
+
+  /* here we open the history file for append.  it this fails, we
+     won't be able to write to it, warn the user.  otherwise, this
+     creates the file readline will write to, if it did not exist */  
+
+  /* check history file */
+  /* rewrite with fstat or stat */
+  f = fopen (opihi_history, "a");
+  if (f == NULL) /* no current history file here */
+    fprintf (stderr, "can't save history.\n");
+  else
+    fclose (f);
+  
+  stifle_history (200);
+  read_history (opihi_history);
+
+  signal (SIGINT, SIG_IGN);
+  return;
+}
+
+/* add program-dependent exit functions here */
+void cleanup () {
+  /* -libdisplay
+  QuitImage ();
+  QuitGraph (); */
+  return;
+}
Index: /tags/start/Ohana/src/opihi/dvo2/init.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo2/init.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo2/init.c	(revision 12606)
@@ -0,0 +1,17 @@
+# include "dvo2.h"
+
+int mkregions	    PROTO((int, char **));
+
+static Command cmds[] = {  
+  {"mkregions",     mkregions,       "make region list"},
+}; 
+
+void InitDVO2 () {
+  
+  int i;
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+
+}
Index: /tags/start/Ohana/src/opihi/dvo2/mkregions.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo2/mkregions.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo2/mkregions.c	(revision 12606)
@@ -0,0 +1,35 @@
+# include "dvo2.h"
+
+int mkregions (int argc, char **argv) {
+
+  int i, status, Nlevels, Nlist;
+  SkyRegion *list;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: mkregions (Nlevel)\n");
+    return (FALSE);
+  }
+  
+  Nlevels = atoi (argv[1]);
+
+  fprintf (stderr, "make regions\n");
+  list = SkyMakeRegions (Nlevels, &Nlist);
+
+  fprintf (stderr, "make names\n");
+  status = SkyMakeNames (list, NULL, 0);
+  if (!status) {
+    fprintf (stderr, "error making region names\n");
+    return (FALSE);
+  }
+
+  /*
+  for (i = 0; i < Nlist; i++) {
+    fprintf (stderr, "%24s : %10.6f - %10.6f : %10.6f - %10.6f : %3d  %3d  %3d - %3d\n", 
+	     list[i].name,
+	     list[i].Rmin, list[i].Rmax, list[i].Dmin, list[i].Dmax, 
+	     list[i].child, list[i].depth, list[i].childS, list[i].childE);
+  }
+  */
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/dvo2/skydb_io.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo2/skydb_io.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo2/skydb_io.c	(revision 12606)
@@ -0,0 +1,216 @@
+# include "dvo2.h"
+
+/* variables which describe the skydb table */
+char *dBFile = (char *) NULL;
+FILE *f;
+Header header;
+Header theader;
+Matrix matrix;
+FTable table;
+SkyRegions *region;
+int Nregion;
+int lockstate;
+int dbstate = LCK_UNLOCK;
+
+SkyRegions *get_regions (int *N) {
+  *N = Nregion;
+  return (region);
+}
+
+int set_regions (SkyRegions *new, int Nnew) {
+
+  int Nbytes;
+
+  /* assign pointers to new data block */
+  free (region);
+  Nregion = Nnew;
+  region = new;
+
+  /* update header, table structures */
+  fits_modify (table.header, "NAXIS2", "%d", 1, Nnew);
+  table.header[0].Naxis[1] = Nnew;
+  Nbytes = fits_matrix_size (table.header);
+
+  /* add padding space to buffer */
+  REALLOCATE ((char *) region, char, Nbytes);
+  table.buffer = (char *) region;
+  table.size = Nbytes;
+
+  return (TRUE);
+}
+
+int load_db () {
+
+  int Nx, Ny;
+
+  lockstate = (output.modify || output.delete) ? LCK_HARD : LCK_SOFT;
+  header.buffer = matrix.buffer = theader.buffer = table.buffer = (char *) NULL;
+
+  if (dBFile == (char *) NULL) {
+    fprintf (stderr, "ERROR: db file is not set\n");
+    exit (1);
+  }
+
+  /* lock database (soft) */
+  f = fsetlockfile (dBFile, 300.0, lockstate, &dbstate);
+  if (dbstate == LCK_EMPTY) return (0);
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't set lock on %s\n", dBFile);
+    exit (1);
+  }
+
+  /* init & load in table data */
+  table.header = &theader;
+  if (!fits_fread_header (f, &header))                   escape (UNLOCK, "ERROR: can't read primary header"); 
+  if (!fits_fread_matrix (f, &matrix, &header))          escape (UNLOCK, "ERROR: can't read primary matrix");
+  if (!fits_fread_ftable (f, &table, "SKY_REGIONS"))     escape (UNLOCK, "ERROR: can't read table");
+
+  /* convert to internal format */
+  region = (SkyRegions *) table.buffer;
+  fits_scan (table.header, "NAXIS1", "%d", 1, &Nx);  /* double check that Nx matches structure? */
+  fits_scan (table.header, "NAXIS2", "%d", 1, &Ny);
+  Nregion = Ny;
+
+  if (!ConvertStruct ((char *) region, sizeof (SkyRegions), Nregion, "skyregions"))
+    escape (UNLOCK, "ERROR: can't convert data"); 
+
+  return (1);
+}
+
+/* save complete db file */
+int save_db () {
+
+  if (!ConvertStruct ((char *) region, sizeof (SkyRegions), Nregion, "skyregions")) 
+    escape (UNLOCK, "ERROR: can't convert from native format");
+
+  /* write all regions to file */
+  make_backup (dBFile);
+  Fseek (f, 0, SEEK_SET);
+  if (!fits_fwrite_header  (f, &header))  escape (LOCK, "ERROR: can't update db");
+  if (!fits_fwrite_matrix  (f, &matrix))  escape (LOCK, "ERROR: can't update db");
+  if (!fits_fwrite_Theader (f, &theader)) escape (LOCK, "ERROR: can't update db");
+  if (!fits_fwrite_table   (f, &table))   escape (LOCK, "ERROR: can't update db");
+
+  fits_free_header (&header);
+  fits_free_matrix (&matrix);
+  fits_free_header (&theader);
+  fits_free_table  (&table);
+
+  fclearlockfile (dBFile, f, lockstate, &dbstate);
+  return (TRUE);
+}
+
+/* save subset in db file */
+int update_db (int *match, int Nmatch) {
+
+  int i, N, Nx, Ny;
+  VTable vtable;
+
+  fits_scan (table.header, "NAXIS1", "%d", 1, &Nx);
+  fits_scan (table.header, "NAXIS2", "%d", 1, &Ny);
+
+  /* make empty vtable from table */
+  vtable.header = table.header;
+  vtable.size = table.size;
+  vtable.Nrow = Ny;
+  vtable.pad = vtable.size - Nx*Ny;
+
+  /* insert selected rows in vtable */ 
+  ALLOCATE (vtable.row, int, Nmatch);
+  ALLOCATE (vtable.buffer, char *, Nmatch);
+  for (N = i = 0; i < Nmatch; i++) {
+    if (match[i] == -1) continue;
+    vtable.row[N] = match[i];
+    ALLOCATE (vtable.buffer[N], char, Nx);
+    memcpy (vtable.buffer[N], &region[match[i]], sizeof (SkyRegions));
+    ConvertStruct ((char *) vtable.buffer[N], sizeof (SkyRegions), 1, "skyregions");
+    N++;
+  }
+  vtable.Nrow = N;
+
+  /* write subset to file */
+  make_backup (dBFile);
+  Fseek (f, 0, SEEK_SET);
+  if (!fits_fwrite_header (f, &header))   escape (LOCK, "ERROR: can't update db");
+  if (!fits_fwrite_matrix (f, &matrix))   escape (LOCK, "ERROR: can't update db");
+  if (!fits_fwrite_Theader (f, &theader)) escape (LOCK, "ERROR: can't update db");
+  if (!fits_fwrite_vtable   (f, &vtable)) escape (LOCK, "ERROR: can't update db");
+
+  fits_free_header (&header);
+  fits_free_matrix (&matrix);
+  fits_free_header (&theader);
+  fits_free_vtable (&vtable);
+  fits_free_table  (&table);
+
+  fclearlockfile (dBFile, f, lockstate, &dbstate);
+  return (TRUE);
+}
+
+int append_db (SkyRegions *new, int Nnew) {
+
+  VTable vtable;
+
+  /* add error checks! */
+  fits_table_to_vtable (&table, &vtable, 0, 0);
+
+  ConvertStruct ((char *) new, sizeof (SkyRegions), Nnew, "skyregions");
+  fits_vadd_rows (&vtable, new, Nnew, sizeof(SkyRegions));
+
+  /* write subset to file */
+  Fseek (f, 0, SEEK_SET);
+  if (!fits_fwrite_header  (f, &header))  escape (LOCK, "ERROR: can't append to db");
+  if (!fits_fwrite_matrix  (f, &matrix))  escape (LOCK, "ERROR: can't append to db");
+  if (!fits_fwrite_Theader (f, &theader)) escape (LOCK, "ERROR: can't append to db");
+  if (!fits_fwrite_vtable  (f, &vtable))  escape (LOCK, "ERROR: can't append to db");
+
+  fits_free_header (&header);
+  fits_free_matrix (&matrix);
+  fits_free_header (&theader);
+  fits_free_vtable (&vtable);
+
+  fclearlockfile (dBFile, f, lockstate, &dbstate);
+  return (TRUE);
+}
+
+int create_db () {
+
+  /* f & dBFile set by load_db */
+
+  /* define table layout */
+  define_table (&header, &matrix, &theader, &table);
+
+  /* convert to internal format */
+  region = (SkyRegions *) table.buffer;
+  Nregion = 0;
+
+  return (TRUE);
+}
+
+int close_db () {
+
+  fits_free_header (&header);
+  fits_free_matrix (&matrix);
+  fits_free_header (&theader);
+
+  if (dbstate == LCK_UNLOCK) return (TRUE);
+  fclearlockfile (dBFile, f, lockstate, &dbstate);
+  return (TRUE);
+}  
+
+int close_lock_db () {
+
+  fits_free_header (&header);
+  fits_free_matrix (&matrix);
+  fits_free_header (&theader);
+
+  if (dbstate == LCK_UNLOCK) return (TRUE);
+  fclearlockfile (dBFile, f, LCK_XCLD, &dbstate);
+  return (TRUE);
+}  
+
+int escape (int mode, char *message) {
+  
+  if (mode == UNLOCK) close_db ();
+  fprintf (stderr, "%s\n", message);
+  exit (1);
+}
Index: /tags/start/Ohana/src/opihi/dvo2/skydbsearch.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo2/skydbsearch.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo2/skydbsearch.c	(revision 12606)
@@ -0,0 +1,379 @@
+# include "dvo2.h"
+
+/* each region is bounded on the sky by lines of constant RA & DEC.
+   the region represents a specified depth, and it may or may not have
+   children.  The start and end of the children in the array are childS and childE 
+   If the region at the given depth is populated with an object table, then 'object' is TRUE.
+   If the region at the given depth is populated with an image table, then 'image' is TRUE.
+   I have defined no accelerators other than the table hierarchy */
+
+/* find region which overlaps c at given depth (-1 : max depth) */
+SkyRegion *SkyFindPoint (SkyRegion *db, SkyCoord c, int depth) {
+  
+  Ns = 0;
+  Ne = 1;
+
+  while (1) {
+    No = -1;
+    for (i = Ns; i < Ne; i++) {
+      if (c.r < db[i].Rmin) continue;
+      if (c.r > db[i].Rmax) continue;
+      if (c.d < db[i].Dmin) continue;
+      if (c.d > db[i].Dmax) continue;
+      No = i;
+      break;
+    }
+    if (No == -1) return ((SkyRegion *) NULL);
+    if (depth == db[No].depth) return (&db[No]);
+    if ((depth > db[No].depth) && !db[No].child) return ((SkyRegion *) NULL);
+
+    /* need to check Ns, Ne, or guarantee valid range */
+    Ns = db[No].childS;
+    Ne = db[No].childE;
+
+    if ((depth > db[No].depth) && db[No].child) continue;
+    return (&db[No]);
+  }
+}
+
+/* find regions at all levels which overlap c */
+SkyRegion **SkyFindLevels (SkyRegion *db, SkyCoord c, int *Nregion) {
+
+  SkyRegion **region;
+  
+  Ns = 0;
+  Ne = 1;
+
+  N = 0;
+  NREGION = 10;
+  ALLOCATE (region, SkyRegion *, NREGION);
+
+  while (1) {
+    No = -1;
+    for (i = Ns; i < Ne; i++) {
+      if (c.r < db[i].Rmin) continue;
+      if (c.r > db[i].Rmax) continue;
+      if (c.d < db[i].Dmin) continue;
+      if (c.d > db[i].Dmax) continue;
+      No = i;
+      break;
+    }
+    if (No == -1) return ((SkyRegion *) NULL);
+
+    region[N] = &db[No];
+    N++;
+    if (N == NREGION) {
+      NREGION += 10;
+      REALLOCATE (region, SkyRegion *, NREGION);
+    }      
+
+    /* need to check Ns, Ne, or guarantee valid range */
+    if (db[No].child) {
+      Ns = db[No].childS;
+      Ne = db[No].childE;
+    } else {
+      *Nregion = N; 
+      return (region);
+    }
+  }
+}
+
+/* find regions contained within rectangular region  c1 - c2 */
+SkyRegion **SkyFindArea (SkyRegion *db, SkyCoord c1, SkyCoord c2, int *nlist) {
+
+  int Nlist;
+  SkyRegion *list, *new, *sub;
+
+  while (c1.r > 360.0) c1.r -= 360.0;
+  while (c1.r <   0.0) c1.r += 360.0;
+  while (c2.r > 360.0) c2.r -= 360.0;
+  while (c2.r <   0.0) c2.r += 360.0;
+
+  /* check on c1.r > c2.r : cross boundary */
+  if (c1.r > c2.r) {
+    c0 = c2; c0.r = 360.0;
+    list = SkyFindArea (db, c1, c0, &Nlist);
+    c0 = c1; c0.r = 0.0;
+    new  = SkyFindArea (db, c0, c2, &Nnew);
+    REALLOCATE (list, SkyRegion *, MAX (1, Nlist + Nnew));
+    memcpy (&list[Nlist], new, Nnew*sizeof(SkyRegion *));
+    free (new);
+    Nlist += Nnew;
+    *nlist = Nlist;
+    return (list);
+
+  }    
+
+  Ns = 0;
+  Ne = 1;
+  Nlist = 1;
+  ALLOCATE (list, SkyRegion *, Nlist);
+  list[0] = &db[0];
+  getchild = db[0].child;
+
+  while (getchild) {
+
+    getchild = FALSE;
+    Nnew = 0;
+    NNEW = 100;
+    ALLOCATE (new, SkyRegion *, NNEW);
+
+    for (i = Ns; i < Ne; i++) {
+      children = SkyFindChildren(db, list[i], c1, c2, &Nchildren);
+      if (children == NULL) continue;
+      if (Nnew + Nchildren >= NNEW) {
+	NNEW += 100;
+	REALLOCATE (new, SkyRegion *, NNEW);
+      }
+      for (i = 0; i < Nchildren; i++) {
+	getchild |= children[i][0].child;
+	new[Nnew] = children[i];
+	Nnew++;
+      }
+      free (children);
+    }
+
+    REALLOCATE (list, SkyRegion *, Nlist + Nnew);
+    memcpy (&list[Nlist], new, Nnew*sizeof(SkyRegion *));
+    free (new);
+    Nlist += Nnew;
+  }
+  return (list);
+  *nlist = Nlist;
+}
+
+/* find all children of the given sky region */
+SkyRegion **SkyFindChildren (SkyRegion *db, SkyRegion *parent, SkyCoord c1, SkyCoord c2, int *Nchildren) {
+
+  int i, Ns, Ne, Nregion, NREGION;
+  SkyRegion **region;
+  
+  *Nchildren = 0;
+  if (!parent[0].child) return (NULL);
+
+  Ns = parent[0].childS;
+  Ne = parent[0].childE;
+
+  Nregion = 0;
+  NREGION = 100;
+  ALLOCATE (region, SkyRegion *, NREGION);
+
+  for (i = Ns; i < Ne; i++) {
+    if (db[i].Rmax < c1.r) continue;
+    if (db[i].Rmin > c2.r) continue;
+    if (db[i].Dmax < c1.d) continue;
+    if (db[i].Dmin > c2.d) continue;
+    region[Nregion] = &db[i];
+    Nregion++;
+    if (Nregion == NREGION) {
+      NREGION += 100;
+      REALLOCATE (region, SkyRegion *, NREGION);
+    }      
+  }
+  *Nchildren = Nregion; 
+  return (region);
+}
+
+SkyRegion *SkyBuildTable (SkyRegion *seed, int Nseed, int level, int depth) {
+
+  /* given a table of Rmin, Dmin, Rmax, Dmax, name, at level 3, generate
+     all higher levels and 'depth' extra levels */
+
+  /* levels:
+     0 - fullsky.cpt
+     1 - n????.cpt, s????.cpt
+     2 - r????.cpt
+     3 - ????.cpt
+     4 - ????.??.cpt
+  */
+  
+  SkyRegion *db;
+
+  /* allocate at least 30 for levels 0 & 1 */
+  NREGION = 100;
+  ALLOCATE (db, SkyRegion, NREGION);
+
+  /* full sky */
+  strcpy (db[0].name, "fullsky.cpt");
+  db[0].Rmin =   0; db[0].Rmax = 360;
+  db[0].Dmin = -90; db[0].Dmax =  90;
+  db[0].depth = 0;
+  db[0].child = FALSE;
+  N = 1;
+
+  db[0].childS = N;
+  /* north dec bands */
+  for (dec = 0; dec < 90; dec += 7.5) {
+    sprintf (db[N].name, "n%04d.cpt", (int) 100*dec);
+    db[N].Rmin =   0; db[N].Rmax = 360;
+    db[N].Dmin = dec; db[N].Dmax = dec + 7.5;
+    db[N].depth = 1;
+    db[N].child = FALSE;
+    N++;
+  }
+  /* south dec bands */
+  for (dec = 0; dec > -90; dec -= 7.5) {
+    sprintf (db[N].name, "s%04d.cpt", (int) 100*dec);
+    db[N].Rmin =   0;       db[N].Rmax = 360;
+    db[N].Dmin = dec - 7.5; db[N].Dmax = dec;
+    db[N].depth = 1;
+    db[N].child = FALSE;
+    N++;
+  }
+  db[0].childE = N;
+
+  /* subdivide dec bands based on seed */
+  Rnumber = 0;
+  childS = db[0].childS;
+  childE = db[0].childE;
+  for (i = childS; i < childE; i++) {
+
+    Nnew = 0;
+    NNEW = 100;
+    ALLOCATE (new, SkyRegion, NNEW);
+
+    for (j = 0; j < Nseed; j++) {
+      if (seed[j].Rmin > db[i].Rmax) continue;
+      if (seed[j].Rmax < db[i].Rmin) continue;
+      if (seed[j].Dmin > db[i].Dmax) continue;
+      if (seed[j].Dmax < db[i].Dmin) continue;
+      
+      for (k = 0; k < Nnew; k++) {
+	if ((seed[j].Rmin == new[k].Rmin) && 
+	    (seed[j].Rmax == new[k].Rmax)) { 
+	  goto next_seed;
+	}
+	if ((seed[j].Rmin == new[k].Rmin) ^^ 
+	    (seed[j].Rmax != new[k].Rmax)) { 
+	  fprintf (stderr, "inconsistent blocks in seed file\n");
+	  return (NULL);
+	}
+      }	
+      new[Nnew].Rmin = seed[j].Rmin;
+      new[Nnew].Rmax = seed[j].Rmax;
+      new[Nnew].Dmin = db[i].Dmin;
+      new[Nnew].Dmax = db[i].Dmax;
+      new[Nnew].depth = 2;
+      new[Nnew].child = FALSE;
+      strncpy (root, db[i].name, 5); root[5] = 0;
+      sprintf (new[Nnew].name, "%s/r%04d.cpt", root, Rnumber);
+      Rnumber ++;      
+      Nnew ++;
+      if (Nnew == NNEW) {
+	NNEW += 100;
+	REALLOCATE (new, SkyRegion, NNEW);
+      }
+    next_seed:
+    }
+    /* update db list */
+    db[i].childS = N;
+    db[i].childE = N + Nnew;
+    NREGION = N + Nnew + 100;
+    REALLOCATE (db, SkyRegion, NREGION);
+    memcpy (&db[N], new, Nnew*sizeof(SkyRegion));
+    free (new);
+    N += Nnew;
+  }
+
+  /* subdivide ra strips based on seed */
+  childS = db[db[0].childS].childS;
+  childE = db[db[0].childE - 1].childE;
+  nextS = N;
+  for (i = childS; i < childE; i++) {
+
+    Nnew = 0;
+    NNEW = 100;
+    ALLOCATE (new, SkyRegion, NNEW);
+
+    for (j = 0; j < Nseed; j++) {
+      if (seed[j].Rmin > db[i].Rmax) continue;
+      if (seed[j].Rmax < db[i].Rmin) continue;
+      if (seed[j].Dmin > db[i].Dmax) continue;
+      if (seed[j].Dmax < db[i].Dmin) continue;
+      
+      for (k = 0; k < Nnew; k++) {
+	if ((seed[j].Dmin == new[k].Dmin) && 
+	    (seed[j].Dmax == new[k].Dmax)) { 
+	  goto next_seed;
+	}
+	if ((seed[j].Dmin == new[k].Dmin) ^^ 
+	    (seed[j].Dmax != new[k].Dmax)) { 
+	  fprintf (stderr, "inconsistent blocks in seed file\n");
+	  return (NULL);
+	}
+      }	
+      new[Nnew].Dmin = seed[j].Dmin;
+      new[Nnew].Dmax = seed[j].Dmax;
+      new[Nnew].Rmin = db[i].Rmin;
+      new[Nnew].Rmax = db[i].Rmax;
+      new[Nnew].depth = 3;
+      new[Nnew].child = FALSE;
+      strcpy (new[Nnew].name, seed[j].name);
+      Nnew ++;
+      if (Nnew == NNEW) {
+	NNEW += 100;
+	REALLOCATE (new, SkyRegion, NNEW);
+      }
+    next_seed:
+    }
+    
+    /* update db list */
+    db[i].childS = N;
+    db[i].childE = N + Nnew;
+    NREGION = N + Nnew + 100;
+    REALLOCATE (db, SkyRegion, NREGION);
+    memcpy (&db[N], new, Nnew*sizeof(SkyRegion));
+    free (new);
+    N += Nnew;
+  }
+  nextE = N;
+
+  /* subdivide entries once more */
+  childS = nextS;
+  childE = nextE;
+  for (i = childS; i < childE; i++) {
+    Rnumber = 0;
+    db[i].childS = N;
+    dDec = (db[i].Dmax - db[i].Dmin) / 5.0;
+    dRa  = (db[i].Rmax - db[i].Rmin) / 5.0;
+    for (nx = 0; nx < 5; nx++) {
+      for (ny = 0; ny < 5; ny++) {
+	db[N].Dmin = db[i].Dmin + dDec * (nx + 0);
+	db[N].Dmax = db[i].Dmax + dDec * (nx + 1);
+	db[N].Rmin = db[i].Rmin + dDec * (nx + 0);
+	db[N].Rmax = db[i].Rmax + dDec * (nx + 1);
+	db[N].depth = 3;
+	db[N].child = FALSE;
+	strncpy (root, db[i].name, 10); root[10] = 0;
+	sprintf (db[N].name, "%s.%02d.cpt", root, Rnumber);
+	Rnumber ++;
+	N ++;
+	if (N == NREGION) {
+	  NREGION += 100;
+	  REALLOCATE (new, SkyRegion, NREGION);
+	}
+      }
+    }
+  }
+
+}
+
+/* region is pointer to entry in db */
+SkyRegion *SkyExtend (SkyRegion *db, SkyRegion *region) {
+
+}
+
+/* region is pointer to entry in db */
+SkyRegion *SkyContract (SkyRegion *db, SkyRegion *region) {
+
+}
+
+SkyRegion *SkyFindGCircle (SkyRegion *db, SkyCoord c1, SkyCoord c2) {
+
+}
+
+
+/* is entire db in memory, or do we load from disk for each operation? 
+   10,000 at level 3, 100,000 @ 4 : 0.5MB, 5MB */
+
+
Index: /tags/start/Ohana/src/opihi/dvo2/skydbtile.c
===================================================================
--- /tags/start/Ohana/src/opihi/dvo2/skydbtile.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/dvo2/skydbtile.c	(revision 12606)
@@ -0,0 +1,283 @@
+# include "dvo2.h"
+SkyRegion *SkyDivideList (SkyRegion *list, int Nlist);
+
+/* region names:
+
+ depth Ntables  Name 
+ 0     1      	fullsky.cpt
+ 1     16     	n????.cpt, s????.cpt
+ 2     256    	n????/r????.cpt
+ 3     4096   	n????/t????.cpt
+ 4     65536  	n????/r????/r????.cpt
+ 5     1.0+06  	n????/t????/t????.cpt
+ 6     1.7+07  	n????/r????/r????/r????.cpt
+
+ depth Ntables  Name 
+ 0     1      	fullsky
+ 1     16     	d%02
+ 2     256    	d%02/r%03d
+ 3     4096   	d%02/t%04d
+ 4     65536  	d%02/r%03d/r%03d
+ 5     1.0+06  	d%02/t%04d/t%04d
+ 6     1.7+07  	d%02/r%03d/r%03d/r%03d
+ 7     2.7+08  	d%02/t%04d/t%04d/t%04d
+
+*/
+
+/* a valid SkyRegion set must always start with the fullsky as the first entry, 
+   with the sequence of entries ordered primarily by depth, followed by parent 
+*/
+
+int SkyMakeNames (SkyRegion *db, SkyRegion *ref, int depth) {
+
+  int i, j, N, Ns, Ne, ns, ne;
+
+  if (db == NULL) return (FALSE);
+  if (depth == 0) {
+    if (db[0].depth != 0) return (FALSE);
+    strcpy (db[0].name, "fullsky");
+    Ns = db[0].childS;
+    Ne = db[0].childE;
+    for (i = Ns; i < Ne; i++) {
+      sprintf (db[i].name, "d%02d", i - 1);
+      if (!SkyMakeNames (db, &db[i], 2)) return (FALSE);
+      if (!SkyMakeNames (db, &db[i], 3)) return (FALSE);
+    }
+    return (TRUE);
+  }
+
+  if (ref == NULL) return (FALSE);
+  
+  if (depth == 2) {
+    if (!ref[0].child) return (TRUE);
+    Ns = ref[0].childS;
+    Ne = ref[0].childE;
+    N = 0;
+    for (i = Ns; i < Ne; i++, N++) {
+      sprintf (db[i].name, "%s/r%02d", ref[0].name, N);
+      if (!SkyMakeNames (db, &db[i], depth + 2)) return (FALSE);
+    }
+  }
+  
+  if (depth > 2) {
+    Ns = ref[0].childS;
+    Ne = ref[0].childE;
+    N = 0;
+    for (i = Ns; i < Ne; i++) {
+      if (!ref[0].child) continue;
+      ns = db[i].childS;
+      ne = db[i].childE;
+      for (j = ns; j < ne; j++, N++) {
+	if (depth % 2) {
+	  sprintf (db[j].name, "%s/t%03d", ref[0].name, N);
+	} else {				      			    
+	  sprintf (db[j].name, "%s/r%02d", ref[0].name, N);
+	}
+	if (!SkyMakeNames (db, &db[j], depth + 2)) return (FALSE);
+      }
+    }  
+  }
+}
+
+SkyRegion *SkyMakeRegions (int Nlevels, int *nlist) {
+
+  int Nlist, Nnext, Ncurr, i, j;
+  SkyRegion *list, *curr, *next;
+
+  Nlist = 0;
+  Nnext = 1;
+  Ncurr = 1;
+  ALLOCATE (list, SkyRegion, Ncurr);
+  ALLOCATE (curr, SkyRegion, Ncurr);
+
+  curr[0].Rmin =   0;
+  curr[0].Rmax = 360;
+  curr[0].Dmin = -90;
+  curr[0].Dmax =  90;
+  curr[0].depth = 0;
+  curr[0].object = FALSE;
+  curr[0].image = FALSE;
+  curr[0].child = FALSE;
+  curr[0].childS = 0;
+  curr[0].childE = 0;
+
+  for (i = 1; i < Nlevels; i++) {
+    next  = SkyDivideRegions (curr, &Nnext);
+    for (j = 0; j < Nnext; j++) {
+      next[j].depth = i;
+    }   
+    REALLOCATE (list, SkyRegion, Nlist + Ncurr);
+    memcpy (&list[Nlist], curr, Ncurr*sizeof(SkyRegion));
+    for (j = Nlist; j < Nlist + Ncurr; j++) {
+      list[j].childS += Nlist + Ncurr;
+      list[j].childE += Nlist + Ncurr;
+    }
+    Nlist += Ncurr;
+    free (curr);
+    curr = next;
+    Ncurr = Nnext;
+  }
+  REALLOCATE (list, SkyRegion, Nlist + Ncurr);
+  memcpy (&list[Nlist], curr, Ncurr*sizeof(SkyRegion));
+  Nlist += Ncurr;
+  free (curr);
+
+  list[0].object = TRUE;
+  list[0].image = TRUE;
+  *nlist = Nlist;
+  return (list);
+}
+
+SkyRegion *SkyDivideRegions (SkyRegion *parents, int *N) {
+
+  int i, Nchildren, Nparents, Np;
+  SkyRegion *children, *temp;
+  float *child, *index;
+
+  Nchildren = Nparents = *N;
+
+  /* copy input list to a new list, set child to be sequence number */
+  ALLOCATE (children, SkyRegion, Nchildren);
+  memcpy (children, parents, Nchildren*sizeof(SkyRegion));
+  for (i = 0; i < Nchildren; i++) {
+    children[i].childS = i;
+    parents[i].childS = i;
+  }
+
+  /* double the number of children, dividing only the largest in half each pass */
+  for (i = 0; i < 4; i++) {
+    temp = SkyDivideList (children, Nchildren);
+    free (children);
+    children = temp;
+    Nchildren *= 2;
+  }
+
+  /* sort children by childS (currently is parent entry) */
+  ALLOCATE (child, float, Nchildren);
+  ALLOCATE (index, float, Nchildren);
+  for (i = 0; i < Nchildren; i++) {
+    index[i] = i;
+    child[i] = children[i].childS;
+  }
+  fsortpair (child, index, Nchildren);
+  ALLOCATE (temp, SkyRegion, Nchildren);
+  for (i = 0; i < Nchildren; i++) {
+    temp[i] = children[(int)index[i]];
+  }
+  free (children);
+  free (child);
+  free (index);
+  children = temp;
+  
+  /* look for all matching values of childS, setup parent values of childS, childE */
+  Np = children[0].childS;
+  parents[Np].childS = 0;
+  parents[Np].child = TRUE;
+  for (i = 0; i < Nchildren; i++) {
+    if (children[i].childS != Np) {
+      parents[Np].childE = i;
+      Np = children[i].childS;
+      parents[Np].childS = i;
+      parents[Np].child = TRUE;
+    }
+    children[i].childS = 0;
+    children[i].childE = 0;
+    children[i].child = FALSE;
+  }
+  parents[Np].childE = i;
+  *N = Nchildren;
+  return (children);
+}
+
+/* always break the region with the largest area */
+SkyRegion *SkyDivideBiggest (SkyRegion *list, int *nlist) {
+
+  int i, N, Nlist;
+  float *area, *indx, dec;
+  SkyRegion *out, save;
+
+  Nlist = *nlist;
+  ALLOCATE (area, float, Nlist);
+  ALLOCATE (indx, float, Nlist);
+  for (i = 0; i < Nlist; i++) {
+    dec = 0.5*(list[i].Dmax + list[i].Dmin);
+    area[i] = (list[i].Rmax - list[i].Rmin)*(list[i].Dmax - list[i].Dmin)*cos(RAD_DEG*dec);
+    indx[i] = i;
+  }
+  fsortpair (area, indx, Nlist);
+
+  N = indx[Nlist - 1];
+  out = SkyDivide (&list[N]);
+  
+  REALLOCATE (list, SkyRegion, Nlist + 1);
+  list[N] = out[0];
+  list[Nlist] = out[1];
+
+  *nlist = Nlist + 1;
+  free (out);
+  free (area);
+  free (indx);
+  return (list);
+}
+
+SkyRegion *SkyDivide (SkyRegion *in) {
+
+  SkyRegion *out;
+  double RA, DEC, R_div, D_div;
+
+  ALLOCATE (out, SkyRegion, 2);
+
+  out[0] = in[0];
+  out[1] = in[0];
+
+  RA  = 0.5*(in[0].Rmin + in[0].Rmax);
+  DEC = 0.5*(in[0].Dmin + in[0].Dmax);
+  if ((DEC >= 90) || (DEC <= -90)) {
+    fprintf (stderr, "error in Dmin");
+    return (NULL);
+  }
+ 
+  D_div = (in[0].Rmax - in[0].Rmin) * cos (RAD_DEG*DEC);
+  R_div = (in[0].Dmax - in[0].Dmin);
+  if (R_div < D_div) {
+    /* divide RA range */
+    out[0].Rmax = RA;
+    out[1].Rmin = RA;
+  } else {
+    out[0].Dmax = DEC;
+    out[1].Dmin = DEC;
+  }
+
+  return (out);
+}
+
+/* return a list with 2x as many entries, each split in two */
+SkyRegion *SkyDivideList (SkyRegion *in, int Nin) {
+
+  SkyRegion *out;
+  double RA, DEC, R_div, D_div;
+  int i;
+
+  ALLOCATE (out, SkyRegion, 2*Nin);
+
+  for (i = 0; i < Nin; i++) {
+    /* inherit properties from parent */
+    out[2*i + 0] = in[i];
+    out[2*i + 1] = in[i];
+
+    RA  = 0.5*(in[i].Rmin + in[i].Rmax);
+    DEC = 0.5*(in[i].Dmin + in[i].Dmax);
+    
+    /* split along longest axis */
+    D_div = (in[i].Rmax - in[i].Rmin) * cos (RAD_DEG*DEC);
+    R_div = (in[i].Dmax - in[i].Dmin);
+    if (R_div < D_div) {
+      out[2*i + 0].Rmax = RA;
+      out[2*i + 1].Rmin = RA;
+    } else {
+      out[2*i + 0].Dmax = DEC;
+      out[2*i + 1].Dmin = DEC;
+    }
+  }
+  return (out);
+}
Index: /tags/start/Ohana/src/opihi/help/!
===================================================================
--- /tags/start/Ohana/src/opihi/help/!	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/!	(revision 12606)
@@ -0,0 +1,6 @@
+
+  exec (line)
+
+  perform a system call.  this can also be invoked with "!".  
+  don't use ! in a macro or input script as it is interpreted as a
+  comment character. 
Index: /tags/start/Ohana/src/opihi/help/Graphics
===================================================================
--- /tags/start/Ohana/src/opihi/help/Graphics	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/Graphics	(revision 12606)
@@ -0,0 +1,20 @@
+
+  Kapa, the graphics window.
+
+  Kapa is the program which Status uses to display plots on an X
+terminal.  There are actually 5 graphics windows available to Status,
+though several functions write to specific windows by default.  All
+plots of sky coordinates are displayed on window 0, while 
+functions which plot other types of data use window 1.  Most functions
+have an option -n which allows the user to specify which Kapa window.
+If it is not specified, the last window used will receive the action.
+
+  Below are the available Resources.  
+
+  kii*Foreground:			white
+  kii*Background:			maroon
+  kii*geometry:				540x540+10+10
+
+  See Also: box, clear, limits, plot
+
+
Index: /tags/start/Ohana/src/opihi/help/Kii
===================================================================
--- /tags/start/Ohana/src/opihi/help/Kii	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/Kii	(revision 12606)
@@ -0,0 +1,57 @@
+
+
+  Kii (= "picture" in Hawaiian) is the program which Mana uses to
+display images on an X terminal.  The window consists of a main region
+where the image is displayed, a small "zoom box" where a magnified
+view of the region around the cursor is shown, a colorbar showing the
+current color map across the top of the window, a status box where the
+coordinates and pixel values are displayed, and several buttons.
+Clicking with the mounse in the different regions produces different
+effects.
+
+  Image Window:  Clicking with the left mouse button (mouse-1)
+recenters the image at the specified location.  Clicking with the
+right button (mouse-3) also recenters, but increases the zoom factor
+by one.  Clicking with the middle button centers and decreases the
+zoom factor.  
+
+  Colorbar: Clicking and draging with the left button (mouse-1) alters
+the color mapping.  Moving left-to-right slides the center of the
+color scale with the mouse.  Moving up-and-down squeezes or expands
+the color scale.  The middle button resets the color mapping.
+Clicking and dragging side-to-side with the right button expands or
+squeezes the color mapping.  **Note: the dynamic colormap cannot be
+used with a 24 or 32 bit visual.  The standard Linux XFree86 server
+does not support 8 bit visuals in 24 or 32 bit/pixel mode.  In this
+case, the Kii window must resort to a static colormap with the
+colorbar disabled.  In Linux, it is possible to run startx with the
+following command-line options to force the 8 bit/pixel mode:
+# startx -- -bpp 8 
+This assumes that you have an 8bpp Display mode set in the XF86Config
+file.  If not, you can just duplicate the 24 or 32 bpp Display modes
+which will enable this option.
+
+  Buttons:
+    PS: this button creates a PostScript version of the image.
+    Grey: this button makes the colormap a greyscale.
+    Rainbow: this button makes the colormap a rainbow.
+    Puns: this button make the colormap a blue and yellow mapping.
+    Recenter: this button recenters the image and resets the zoom.
+
+  Kii also recognizes several X Resource values:
+
+  Below are the available Resources (with Gene's default values).  Unlike
+most standard X programs, the geometry resource specifies the size of
+the Image Window, not the borders of the entire window.  Valid values
+for the colormap are: greyscale, grayscale (photonegative), -greyscale,
+-grayscale (photopositive), Puns, GoBears (buff 'n blue colormap),
+Rainbow (a rainbow map).  
+
+  kii*Foreground:			white
+  kii*Background:			maroon
+  kii*Colormap:				greyscale
+  kii*geometry:				540x540+10+10
+  
+
+  See Also: tv, cursor
+
Index: /tags/start/Ohana/src/opihi/help/Math
===================================================================
--- /tags/start/Ohana/src/opihi/help/Math	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/Math	(revision 12606)
@@ -0,0 +1,58 @@
+
+  Opihi shell math operations:
+
+  Mana will evaluate scalar (1D) arithmetic expresions in two
+situations.  To set a variable equal to a math operation, use the
+syntax is:
+
+  $foo = expression
+
+where "expression" is an arithmetic expression on numbers and
+variables, including a variety of functions (see below).  After
+performing the arithmetic and setting the variable to the resulting
+value, mana returns the prompts without performing any further
+command.  Mana will also evaluate any arithmetic expression enclosed
+in curly brackets before attempting to perform the given command.  For
+example, if the variables $MEAN and $SIGMA contain the mean and
+standard deviation of an image, it would be possible to display the
+image with a zero and range based on $MEAN and $SIGMA like this:
+
+  tv image {$MEAN - 1.5*$SIGMA} {5*$SIGMA}
+
+
+The two expressions in curly brackets are evaluated and the resulting
+numbers passed as arguments to the "tv" command.
+
+  See Also:  Variables, tv
+
+
+list of valid math operations:
+
+  binary operators:
+  * (times)
+  / (divided by)
+  + (plus)
+  - (minus)
+  ^ (to the power of: 2^3 = 8)
+
+  unary operators:
+  exp (e to the power of)
+  ten (10 to the power of)
+  ln  (natural logarithm)
+  log (log base 10)
+
+  angles in radians:
+  sin (sine)
+  cos (cosine)
+  tan (tangent)
+  asin (arcsin)
+  acos (arccos)
+  atan (arctan)
+
+  angles in degrees:
+  dsin (sine)
+  dcos (cosine)
+  dtan (tangent)
+  dasin (arcsin)
+  dacos (arccos)
+  datan (arctan)
Index: /tags/start/Ohana/src/opihi/help/Opihi
===================================================================
--- /tags/start/Ohana/src/opihi/help/Opihi	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/Opihi	(revision 12606)
@@ -0,0 +1,5 @@
+
+
+    Opihi
+
+  
Index: /tags/start/Ohana/src/opihi/help/Photometry
===================================================================
--- /tags/start/Ohana/src/opihi/help/Photometry	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/Photometry	(revision 12606)
@@ -0,0 +1,26 @@
+
+cals: Plot residuals for reference stars. 
+
+ This function takes the currently displayed region and looks for all
+ stars which have 'reference' photometry and plots the difference
+ between the reference magnitude (in the given filter) and the
+ observed magnitude (same filter) versus one of several options:  the
+ star color (based on the 'reference' photometry), the star magnitude,
+ the airmass, time, secqunce, etc.
+
+ These plots can use one of two options for the 'observed' magnitude.
+ Either, the magnitude for individual measurement, using the currently
+ set values for the CCD zeropoints (from the photometry database), or
+ using the relative photometry determined for the particular star.  
+
+
+dmags: plot difference between two measured magnitudes
+
+resid: 
+
+abszero
+
+zeropts
+
+cmd
+
Index: /tags/start/Ohana/src/opihi/help/Shell
===================================================================
--- /tags/start/Ohana/src/opihi/help/Shell	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/Shell	(revision 12606)
@@ -0,0 +1,5 @@
+
+
+    Opihi
+
+  
Index: /tags/start/Ohana/src/opihi/help/Variables
===================================================================
--- /tags/start/Ohana/src/opihi/help/Variables	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/Variables	(revision 12606)
@@ -0,0 +1,17 @@
+
+  Opihi shell variables (scalars):
+
+  The Opihi shell can have variables which are designated by a word
+following a dollar sign: $foo.  Certain Mana function create and set
+variables (ie, stats, cursor).  You can also set a variable to the
+result of an arithmetic expression or just a number like this:
+
+  $foo = 10.0
+  $bar = 5*$foo + 0.6
+
+Mana will replace the variables on a line before executing a command.
+See also "Math" for more description of arithmetic operations.
+
+  See Also:  Math
+
+
Index: /tags/start/Ohana/src/opihi/help/applyfit
===================================================================
--- /tags/start/Ohana/src/opihi/help/applyfit	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/applyfit	(revision 12606)
@@ -0,0 +1,10 @@
+
+  applyfit x y
+
+  apply the results of a polynomial fit (stored in variables 
+  $C0, $C1, etc, with $Cn representing the order of the fit).
+  The second vector will contain the function value at the 
+  corresponding x coordinates of the first vector.
+
+  See also: fit
+
Index: /tags/start/Ohana/src/opihi/help/biassub
===================================================================
--- /tags/start/Ohana/src/opihi/help/biassub	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/biassub	(revision 12606)
@@ -0,0 +1,9 @@
+
+  biassub buffer sx sy nx ny dir [-v N V]
+
+  Apply a bias correction.  The region defines a vector 
+  (median is taken perpendicular to the dir direction) which 
+  is subtracted from the image.
+
+
+
Index: /tags/start/Ohana/src/opihi/help/box
===================================================================
--- /tags/start/Ohana/src/opihi/help/box	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/box	(revision 12606)
@@ -0,0 +1,11 @@
+
+  box [-n Nwindow]
+
+  draw a coordinate box on the current kapa window, or on the window
+specified by -n (0 - 4).
+
+  See also: Kapa
+
+
+
+  
Index: /tags/start/Ohana/src/opihi/help/break
===================================================================
--- /tags/start/Ohana/src/opihi/help/break	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/break	(revision 12606)
@@ -0,0 +1,7 @@
+
+  break
+
+  halts macro, if, or for processes and returns to the basic prompt.
+
+  See also: macro, if, for
+
Index: /tags/start/Ohana/src/opihi/help/buffers
===================================================================
--- /tags/start/Ohana/src/opihi/help/buffers	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/buffers	(revision 12606)
@@ -0,0 +1,9 @@
+
+  buffers
+
+  buffers gives information about the currently allocated buffers.  
+A * next to the filename means the data has been altered from the
+originally read in image.
+
+  See also: memory
+
Index: /tags/start/Ohana/src/opihi/help/catalog
===================================================================
--- /tags/start/Ohana/src/opihi/help/catalog	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/catalog	(revision 12606)
@@ -0,0 +1,74 @@
+
+  catalog (filename/-all) [many options!]
+
+  plot the star positions from any of several possible catalogs.  By
+default, the photometry database (see Database) is used, but the HST
+Guide Star Catalog and a simple ASCII file may also be used.  The
+plotting is done on window 0, with the current point type.  The point
+size can be scaled by the magnitude of the star or by the number
+of observations (-n).  
+
+There are many options to this function.  Here they are all:
+
+-e epoch: given ASCII catalog has this epoch, plot in J2000
+
+-ID ID: plot only measurements with this ID number
+ ID may be one of:
+	0 - star
+	4 - variable
+	5 - transient
+      100 - ghost image
+      101 - trail (satellite)
+      102 - bright star garbage	
+      note that numbers < 50 are static objects, 
+	and numbers > 100 are bad data.
+
+-all:  plot all data for the current display region
+
+-g: use the HST GSC instead of the photometry database
+
+-a RA DEC MAG:  the given file is an ASCII file with 
+	RA, DEC, and MAG in columns given by the three numbers
+
+-v ra dec scale: save the values in vectors with the three names given
+	the ra and dec are always used, but the third is the size of 
+	the points plotted, based on whatever the scaling is.
+
+-m m1 m2: scale points by magnitude, with smallest points having
+	magnitude m2.
+
++n n1 n2: scale points by number of measurements, with smallest points
+	having number n1.
+
+-n n1 n2: scale points by number of missing values, with smallest points
+	having number n1.
+
+Note that if two of -m, -n, +n are given, the first determines the
+ scaling of the points.  the second provides an allowed range, so
+ points are only plotted if the second parameter has a value in the
+ given range.
+
+Examples: 
+
+  catalog -all -m 12 18  
+    plot all stars in current region with magnitude 12 having the
+    biggest points and magnitude 18 having the smallest.
+   
+  catalog -all -m 12 18 +n 2 4
+    plot all stars in current region with magnitude 12 having the
+    biggest points and magnitude 18 having the smallest, but only
+    if the stars have 2-4 measurements each
+   
+  catalog -all -m 12 18 +n 0 1 -ID 101
+    plot all stars in current region with magnitude 12 having the
+    biggest points and magnitude 18 having the smallest, but only
+    if the stars have 1 measurements each, and if the object is 
+    found to be a trail.
+   
+  catalog n2230/1819.cpt -n 2 8  
+    plot all stars in catalog n2230/1819.cpt with the biggest points
+    having 8 measurements and the smallest having only 2.
+
+  See Also: lcat, pcat, style, region
+
+   
Index: /tags/start/Ohana/src/opihi/help/cd
===================================================================
--- /tags/start/Ohana/src/opihi/help/cd	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/cd	(revision 12606)
@@ -0,0 +1,9 @@
+
+   cd (path)
+
+   change current working directory. 
+
+   Note that Kii or Kapa will be launched in the original 
+   directory, which means PS files created by Kii or Kapa 
+   will land in that directory (perhaps an unexpected result).
+
Index: /tags/start/Ohana/src/opihi/help/center
===================================================================
--- /tags/start/Ohana/src/opihi/help/center	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/center	(revision 12606)
@@ -0,0 +1,10 @@
+
+  center (xpix) (ypix) [magnification]
+
+  "center" centers the Kii window at the specified pixel coordinates.
+Specifying a magnification will change the image scale to the
+specified magnification.  If you do not specify a magnification
+(default), the image scale will remain the same.
+
+  See also: Kii, tv
+
Index: /tags/start/Ohana/src/opihi/help/cgrid
===================================================================
--- /tags/start/Ohana/src/opihi/help/cgrid	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/cgrid	(revision 12606)
@@ -0,0 +1,6 @@
+
+  cgrid
+
+  draws a grid in RA and DEC on window 0 approriate for the current
+  region.
+
Index: /tags/start/Ohana/src/opihi/help/clear
===================================================================
--- /tags/start/Ohana/src/opihi/help/clear	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/clear	(revision 12606)
@@ -0,0 +1,5 @@
+
+   clear
+
+   clear the Kapa window
+
Index: /tags/start/Ohana/src/opihi/help/clip
===================================================================
--- /tags/start/Ohana/src/opihi/help/clip	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/clip	(revision 12606)
@@ -0,0 +1,8 @@
+
+  clip (buffer) [min Vmin max Vmax] [-inf val] [-nan val]
+
+  clip values in an image.  A min/max clip can be applied, 
+  in which case all values above max are set to Vmax and all
+  below min are set to Vmin.  -nan and -inf flags will set all 
+  instances of NaN or any non-finite values to the given value.
+
Index: /tags/start/Ohana/src/opihi/help/concat
===================================================================
--- /tags/start/Ohana/src/opihi/help/concat	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/concat	(revision 12606)
@@ -0,0 +1,8 @@
+
+   concat v1 v2
+
+   concatenates the values of vector v2 to the end of vector
+   v1, increasing the length of v1.
+
+   See also: subset, set
+
Index: /tags/start/Ohana/src/opihi/help/contour
===================================================================
--- /tags/start/Ohana/src/opihi/help/contour	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/contour	(revision 12606)
@@ -0,0 +1,13 @@
+
+  contour <buffer> (overlay) level [Npix]
+
+  "contour" makes a contour plot from the given <buffer> at the
+specified level.  If Npix is specified, the image is rebinned by a
+factor of Npix in each direction.  The contour is drawn as a series of
+lines on the specified overlay.  The new lines are added to any
+existing shapes.  (Use "erase" first to erase all objects if desired).
+
+Valid overlays may be: 0, red, 1, green, 2, blue, 3, yellow.
+
+  See also: load, save, erase
+
Index: /tags/start/Ohana/src/opihi/help/coords
===================================================================
--- /tags/start/Ohana/src/opihi/help/coords	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/coords	(revision 12606)
@@ -0,0 +1,19 @@
+
+  coords <buffer> (filename)
+
+  "coords" loads astrometric parameters for the given buffer from the
+header of the named file.  The parameters are applied to the buffer,
+and will register in the Ki'i window if the buffer it tv'ed again.
+This is particularly convenient for intercomparing coordinate system
+or in the event the astrometry is stored in a different file (eg, a
+stripped off header).  Currently, the only format of coordinate
+information that is looked for are gene's linear transformation: RA_O,
+RA_X, RA_Y, DEC_O, DEC_X, DEC_Y such that the RA,DEC of an object is
+given by:
+
+RA  = RA_O  + x*RA_X  + y*RA_Y
+DEC = DEC_O + x*DEC_X + y*DEC_Y.
+
+
+  See also: rd, tv
+
Index: /tags/start/Ohana/src/opihi/help/create
===================================================================
--- /tags/start/Ohana/src/opihi/help/create	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/create	(revision 12606)
@@ -0,0 +1,7 @@
+
+   create vector start end [delta]
+
+   create a vector of uniformly spaced values, starting at
+   start and going to end.  By default the spacing is 1, but
+   may be chosen with the delta option.
+
Index: /tags/start/Ohana/src/opihi/help/cursor
===================================================================
--- /tags/start/Ohana/src/opihi/help/cursor	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/cursor	(revision 12606)
@@ -0,0 +1,13 @@
+
+  cursor
+
+  place cursor coordinates (and values ??) into Mana variables.  to do
+this, type cursor, then place the cursor on the desired spot in the
+Ki'i window and type a digit (0 - 9).  The coordinates of the cursor
+are then placed in the variables $Xn and $Yn (where n is the digit you
+typed).  To exit the cursor mode, type "q" (or "Q") in the Ki'i
+window.  
+
+  See Also: Kii, tv, center
+
+ 
Index: /tags/start/Ohana/src/opihi/help/cut
===================================================================
--- /tags/start/Ohana/src/opihi/help/cut	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/cut	(revision 12606)
@@ -0,0 +1,9 @@
+
+   cut buffer <X vector> <Y vector> <X|Y> sx sy nx ny
+
+   take a cut from an image and place it in a pair of vectors.
+   the <X vector> gets the pixel coordinate in the given direction,
+   the <Y vector> gets the pixel values.  <X|Y> specifies the 
+   direction of the cut.  the region sx, sy, nx, ny specifies the
+   region for the cut, with summation in the cross-direction.
+
Index: /tags/start/Ohana/src/opihi/help/datafile
===================================================================
--- /tags/start/Ohana/src/opihi/help/datafile	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/datafile	(revision 12606)
@@ -0,0 +1,6 @@
+
+   datafile (filename)
+
+   define a data file for subsequent vector reads.
+
+   See also: read
Index: /tags/start/Ohana/src/opihi/help/delete
===================================================================
--- /tags/start/Ohana/src/opihi/help/delete	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/delete	(revision 12606)
@@ -0,0 +1,5 @@
+
+  delete <buffer>
+
+  delete the named buffer.  Warning: no second chances are given!
+
Index: /tags/start/Ohana/src/opihi/help/echo
===================================================================
--- /tags/start/Ohana/src/opihi/help/echo	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/echo	(revision 12606)
@@ -0,0 +1,10 @@
+
+  echo [anything]
+
+  prints the rest of the line, after variables and math expressions
+are parsed.  
+
+
+  See Also:  Opihi, math
+
+
Index: /tags/start/Ohana/src/opihi/help/erase
===================================================================
--- /tags/start/Ohana/src/opihi/help/erase	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/erase	(revision 12606)
@@ -0,0 +1,8 @@
+
+  erase (overlay)
+
+  "erase" erases all objects on the specified overlay.  
+  Valid overlays may be: all, red, green, blue, yellow.
+
+  See also: load, save, contour
+
Index: /tags/start/Ohana/src/opihi/help/exec
===================================================================
--- /tags/start/Ohana/src/opihi/help/exec	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/exec	(revision 12606)
@@ -0,0 +1,6 @@
+
+   exec (or !) system function
+
+   perform a UNIX system call.  variables are parsed before 
+   the commands is passed to the UNIX shell.
+
Index: /tags/start/Ohana/src/opihi/help/extract
===================================================================
--- /tags/start/Ohana/src/opihi/help/extract	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/extract	(revision 12606)
@@ -0,0 +1,12 @@
+
+  extract <from> <to> sx sy nx ny sx sy nx ny
+
+  extract takes a portion of an image (buffer <from>) and creates a
+new image (buffer <to>).  The source region is defined by the first
+set of (sx sy nx ny), the resulting image and the location of the
+extracted image are defined by the second (sx sy nx ny).  This allows
+a portion of an image to be overlayed at a particular location in a
+larger image.
+
+  See also: Kii, tv
+
Index: /tags/start/Ohana/src/opihi/help/fit
===================================================================
--- /tags/start/Ohana/src/opihi/help/fit	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/fit	(revision 12606)
@@ -0,0 +1,9 @@
+
+   fit x y order [-dy wt]
+
+   perform a lease-square polynomial fit to the data defined 
+   by vectors x and y.  the coefficients are placed in the variables
+   $C0, $C1, ..., and the order is placed in $Cn.
+
+   See also: applyfit
+
Index: /tags/start/Ohana/src/opihi/help/flux
===================================================================
--- /tags/start/Ohana/src/opihi/help/flux	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/flux	(revision 12606)
@@ -0,0 +1,7 @@
+
+   flux buffer (file)
+
+   calculate the flux enclosed by the contour given in the file.  The
+   file contains the coordinates of the polygon corners.
+
+
Index: /tags/start/Ohana/src/opihi/help/for
===================================================================
--- /tags/start/Ohana/src/opihi/help/for	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/for	(revision 12606)
@@ -0,0 +1,19 @@
+
+   for var (start) (stop) [delta]
+
+    perform a loop, with $var as the loop variable. 
+    the value of $var runs from (start) to (stop) inclusive, 
+    and is incremented by [delta] (1 by default).
+
+    The loop commands are entered until the appropriate "end" is typed;
+    if there are nested loops, macro definitions, or logical blocks,
+    the correct "end" is used!
+
+    for may be used at the command line, in a macro, or in an input
+    file with no ill effects.
+
+    the variable $var may be accessed during the loop execution.  if
+    the variable $var is assigned a value beyond (stop) during the
+    loop, the loop execution will end.
+
+    See also: macro, if
Index: /tags/start/Ohana/src/opihi/help/gauss
===================================================================
--- /tags/start/Ohana/src/opihi/help/gauss	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/gauss	(revision 12606)
@@ -0,0 +1,15 @@
+
+   gauss Npix [Nspots] [-border N] [-sat cnts]
+
+   calculate statistics on stars, assuming a Gaussian profile.  The
+   user types a key on a star in the Kii window, and the resulting
+   information is printed on the screen.  This is really aperture
+   photometry.  Npix defines the aperture width (square aperture), the
+   optional -border defines the number of pixels in an annulus used to
+   find the background, -sat defines the value of a saturated pixel.
+   If the Nspots option is given, exactly Nspots stars are chosen.
+   Otherwise, the user may type on stars until the 'q' is typed.  The
+   results of the last star are stored the a set of Mana variables.
+
+   See also: star, cursor
+
Index: /tags/start/Ohana/src/opihi/help/grid
===================================================================
--- /tags/start/Ohana/src/opihi/help/grid	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/grid	(revision 12606)
@@ -0,0 +1,6 @@
+
+   grid (overlay) (buffer)
+
+   draw a coordinate grid for the given buffer in the 
+   given overlay in Kii.
+
Index: /tags/start/Ohana/src/opihi/help/header
===================================================================
--- /tags/start/Ohana/src/opihi/help/header	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/header	(revision 12606)
@@ -0,0 +1,8 @@
+
+   header (buffer)
+
+   print the header information for the given buffer.  The header
+   information is Meta-information associated with an image.  It is
+   well-defined for the FITS images, but may not exist for some of the
+   other possible data types.  
+
Index: /tags/start/Ohana/src/opihi/help/help
===================================================================
--- /tags/start/Ohana/src/opihi/help/help	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/help	(revision 12606)
@@ -0,0 +1,7 @@
+
+   help (function)
+
+   print the contents of the help file.  
+   typing "help" without an argument will list the available help
+   files.  
+
Index: /tags/start/Ohana/src/opihi/help/histogram
===================================================================
--- /tags/start/Ohana/src/opihi/help/histogram	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/histogram	(revision 12606)
@@ -0,0 +1,8 @@
+
+   histogram <buffer> <x> <y> [-region sx sy nx ny] [-range min max]
+
+   calculate a histogram of the image pixel values in the given
+   buffer, optionally constrained to the given region, with optional
+   max and min values.  the results are placed in the vectors x and y,
+   which contain the pixel values and the number of occurences.
+
Index: /tags/start/Ohana/src/opihi/help/if
===================================================================
--- /tags/start/Ohana/src/opihi/help/if	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/if	(revision 12606)
@@ -0,0 +1,22 @@
+
+   if (logic)
+     (commands)
+   end
+
+   or:
+
+   if (logic)
+     (commands)
+   else 
+     (commnds)
+   end
+
+   logical block.  The commands are performed subject to the logical
+   condition.  The syntax is simplified C:  
+   examples: (x = 6), (x < 6) , (x ! 6), ((x = 6) | (x > 10))
+
+   there are no delimiter characters.
+
+   See also: for, macro
+
+   
Index: /tags/start/Ohana/src/opihi/help/images
===================================================================
--- /tags/start/Ohana/src/opihi/help/images	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/images	(revision 12606)
@@ -0,0 +1,9 @@
+
+  images 
+
+  plot the outlines of images in the photometry database and list
+  along with relevant information.  An example of relevant data is the
+  image time, which can be used in other functions to define a specific
+  image or a range of images relevant for the function.
+
+  See also: Database, lcat, pcat
Index: /tags/start/Ohana/src/opihi/help/imstats
===================================================================
--- /tags/start/Ohana/src/opihi/help/imstats	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/imstats	(revision 12606)
@@ -0,0 +1,5 @@
+
+  imstats 
+
+  list interesting statistics for a set of images.
+
Index: /tags/start/Ohana/src/opihi/help/input
===================================================================
--- /tags/start/Ohana/src/opihi/help/input	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/input	(revision 12606)
@@ -0,0 +1,15 @@
+
+   input (filename)
+
+   execute a series of commands given in the file.
+
+   Two special examples:  
+   ~/.manarc is loaded on startup, which give the user a place to
+   define personal macros, or interesting variables, etc.
+
+   If mana is called in the form "mana file", the file is loaded
+   (after .manarc) before the user is given the command-line prompt.
+   This can be used to invoke mana in a shell script, but care should
+   be taken in a shell-script that the file ends with the word "exit"
+   or "quit", or strange things may happen...
+
Index: /tags/start/Ohana/src/opihi/help/kern
===================================================================
--- /tags/start/Ohana/src/opihi/help/kern	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/kern	(revision 12606)
@@ -0,0 +1,4 @@
+
+   kern buffer (kernel file or -)
+
+   apply a 3x3 kernel to the image.  
Index: /tags/start/Ohana/src/opihi/help/keyword
===================================================================
--- /tags/start/Ohana/src/opihi/help/keyword	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/keyword	(revision 12606)
@@ -0,0 +1,11 @@
+
+  keyword <buffer> (KEYWORD) [variable] [-w value]
+
+  "keyword" extracts the specified keyword from the header of the
+   specified buffer.  If a third word is listed, the value of the
+   keyword is stored in a variable with the given name.  If the -w
+   option is given, the value is written to the header keyword.
+
+   The header Meta-data is well-defined for FITS, but not necessarily
+   for other data types.
+
Index: /tags/start/Ohana/src/opihi/help/labels
===================================================================
--- /tags/start/Ohana/src/opihi/help/labels	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/labels	(revision 12606)
@@ -0,0 +1,23 @@
+
+   labels 
+
+   write a label on the Kapa window.  there are many options:
+
+   -fn font size -- define the font (may be times, helvetica, courier)
+
+   -x "a long line" -- label on the bottom x-axis
+
+   +x "a long line" -- label on the top x-axis
+
+   -y "a long line" -- label on the left y-axis
+
+   +y "a long line" -- label on the right y-axis
+
+   -ul "a long line" -- label on the upper left of plot
+
+   -ll "a long line" -- label on the lower left of plot
+
+   -ur "a long line" -- label on the upper right of plot
+
+   -lr "a long line" -- label on the lower right of plot
+
Index: /tags/start/Ohana/src/opihi/help/lcat
===================================================================
--- /tags/start/Ohana/src/opihi/help/lcat	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/lcat	(revision 12606)
@@ -0,0 +1,10 @@
+
+  lcat [-all]
+
+  list photometry database files in the current region.  if the option
+  -all is given, all database in the region are listed, along with a
+  comment to show if there is data in the file or not.  if the option
+  is not given, only those files with data are listed.
+
+  See also: region, pcat
+
Index: /tags/start/Ohana/src/opihi/help/lcurve
===================================================================
--- /tags/start/Ohana/src/opihi/help/lcurve	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/lcurve	(revision 12606)
@@ -0,0 +1,8 @@
+
+  lcurve RA DEC Radius [-l]
+
+  plot light curves for all stars within Radius of the given
+  coordinates.  The units for all three are decimal degrees.  
+  The option -l autoscales the limits of the plot.  
+
+  See also: limits
Index: /tags/start/Ohana/src/opihi/help/limits
===================================================================
--- /tags/start/Ohana/src/opihi/help/limits	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/limits	(revision 12606)
@@ -0,0 +1,12 @@
+
+   limits min max min max
+   limits x y
+   limits x min max
+   limits min max y
+   
+   set Kapa plot limits.  The x and y axis limits may be explicitly
+   set (first example), or they may be assigned based on the range of
+   values in a pair of vectors (second examples), or one range may be
+   explicit and the other range assigned from a vector.
+
+
Index: /tags/start/Ohana/src/opihi/help/load
===================================================================
--- /tags/start/Ohana/src/opihi/help/load	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/load	(revision 12606)
@@ -0,0 +1,20 @@
+
+   load (overlay) (filename)
+
+  "load" reads a file with objects in SAOimage style into the
+  specified overlay.  If the specified overlay is already used, the
+  new objects are added to the old.  If you do not want this, use
+  "erase" to erase all objects in the overlay first.  Valid overlays
+  may be: 0, red, 1, green, 2, blue, 3, yellow.
+
+Examples of SAOimage style objects:
+BOX   300  200  100 50  : draws a box centered at pixel 300,200 that
+			  is 100 pixels wide, and 50 pixels high
+
+CIRCLE 500 400 200 : draws a circle centered at pixel 500,400 with a
+                     radius of 200 pixels
+
+LINE 100 100 200 200 : draws a line from (100,100) with length (200,200)
+
+  See also: save, erase, contour
+
Index: /tags/start/Ohana/src/opihi/help/macro
===================================================================
--- /tags/start/Ohana/src/opihi/help/macro	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/macro	(revision 12606)
@@ -0,0 +1,11 @@
+
+   macro (name)
+
+   create a macro.  the commands are entered until the word 'end' is
+   reached.  nested if, for, and macro definitions use the
+   appropriately matched occurances of the 'end'.
+
+   Within a macro, the command-line arguments are refered to as $1,
+   $2, etc.  The number of command-line arguments is given by $0.
+
+   
Index: /tags/start/Ohana/src/opihi/help/memory
===================================================================
--- /tags/start/Ohana/src/opihi/help/memory	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/memory	(revision 12606)
@@ -0,0 +1,12 @@
+
+  memory [x]
+
+  list the currently used memory.  This gives a (possibly very) long
+  listing of the size of every allocated piece of memory.  Placing
+  anything after the word "memory" gives a summary also.  This is
+  useful to see just how close you are to filling your computer's
+  entire memory (Does not include memory allocated to Kii!)
+
+  See Also: buffers
+
+
Index: /tags/start/Ohana/src/opihi/help/mextract
===================================================================
--- /tags/start/Ohana/src/opihi/help/mextract	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/mextract	(revision 12606)
@@ -0,0 +1,12 @@
+
+ mextract (filename) (value) [-g / -a Ncol]
+
+ extracts a vector from the photometry database.  The name also
+ specifies the type of data extracted (and is case insensitive).  Only
+ certain names may be used.
+
+ The possible values are:
+ ra, dec, mag, dmag, Mcal, Mrel, source, time, dR, dD
+
+
+ Note: this routine extracts the individual measurements.
Index: /tags/start/Ohana/src/opihi/help/output
===================================================================
--- /tags/start/Ohana/src/opihi/help/output	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/output	(revision 12606)
@@ -0,0 +1,10 @@
+
+  output (filename or "stdout")
+
+  redirect the output to a file (concat to the end of the file).  This
+  can also be done with the UNIX ">".  However, this command is useful
+  to send information to a file for a part of a Mana session.  For
+  example, you can save results of a "stats" command.
+
+  See Also: input, stats
+
Index: /tags/start/Ohana/src/opihi/help/pause
===================================================================
--- /tags/start/Ohana/src/opihi/help/pause	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/pause	(revision 12606)
@@ -0,0 +1,9 @@
+
+  pause (N)
+
+  pause N seconds.  This suspends Mana (not Ki'i) for N seconds.  Be
+careful:  Typing pause 100000 may be a bad idea!  (you can only get
+out of this with a cntl-C, which also kills Mana).
+
+  See Also: wait
+
Index: /tags/start/Ohana/src/opihi/help/pcat
===================================================================
--- /tags/start/Ohana/src/opihi/help/pcat	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/pcat	(revision 12606)
@@ -0,0 +1,9 @@
+
+  pcat [-all]
+
+  plot outlines of photometry database files in the current region.
+  if the option -all is given, all database in the region are listed.
+  if the option is not given, only those files with data are listed.
+
+  See also: region, lcat
+
Index: /tags/start/Ohana/src/opihi/help/plot
===================================================================
--- /tags/start/Ohana/src/opihi/help/plot	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/plot	(revision 12606)
@@ -0,0 +1,13 @@
+
+   plot <x> <y> [-dx dx] [-dy dy] [+dx dx] [+dy dy]
+
+   plot a pair of vectors.  the options allow for errorbars.  If only
+   one of -dy or +dy is given, the given vector is used for the
+   errorbar.  If both are given, -dy defines the lower errorbar, while
+   +dy defines the upper errorbar.  This allows for assymetric errors
+   in a trivial fashion.  The same applies to the -dx, +dx values.  
+
+   The vectors are plotted with the current plot style.  See style for
+   all of the options.
+
+
Index: /tags/start/Ohana/src/opihi/help/print
===================================================================
--- /tags/start/Ohana/src/opihi/help/print	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/print	(revision 12606)
@@ -0,0 +1,4 @@
+
+  print X Y
+
+  write a pair of vectors to a disk file.  
Index: /tags/start/Ohana/src/opihi/help/profile
===================================================================
--- /tags/start/Ohana/src/opihi/help/profile	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/profile	(revision 12606)
@@ -0,0 +1,6 @@
+
+   profile <buffer> <X vector> <Y vector> x y N
+
+   Find the radial profile of an image at the location x, y.  the
+   radius is placed in the X vector and the pixel value is placed in
+   the Y vector.   
Index: /tags/start/Ohana/src/opihi/help/ps
===================================================================
--- /tags/start/Ohana/src/opihi/help/ps	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/ps	(revision 12606)
@@ -0,0 +1,8 @@
+
+   ps [-g]
+
+   create a PostScript file from the Kii window (or Kapa window if -g
+   is given).  Kii produces a file called Ximage.ps, while Kapa
+   produces a file called Xgraph.ps
+
+   Color postscript is an obvious, but unimplemented extension...
Index: /tags/start/Ohana/src/opihi/help/pwd
===================================================================
--- /tags/start/Ohana/src/opihi/help/pwd	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/pwd	(revision 12606)
@@ -0,0 +1,5 @@
+
+   pwd
+
+   print current working directory
+
Index: /tags/start/Ohana/src/opihi/help/rd
===================================================================
--- /tags/start/Ohana/src/opihi/help/rd	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/rd	(revision 12606)
@@ -0,0 +1,10 @@
+
+  rd (buffer) (filename)
+
+  "rd" reads a file into the specified buffer, creating the buffer if
+  none exists.  A buffer name may consist of any letters, numbers, and
+  some limited other characters.  However, the name may not start with
+  a digit.
+
+  See also: wd, tv
+
Index: /tags/start/Ohana/src/opihi/help/read
===================================================================
--- /tags/start/Ohana/src/opihi/help/read	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/read	(revision 12606)
@@ -0,0 +1,10 @@
+
+   read vect col [vect col, ...]
+
+   read vector values from a file.  An arbitrary number of vectors can
+   be specified, and the (whitespace-separated) field number given for
+   each vector.  Data is read from the file defined by "datafile".
+
+   See also: datafile
+
+
Index: /tags/start/Ohana/src/opihi/help/rebin
===================================================================
--- /tags/start/Ohana/src/opihi/help/rebin	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/rebin	(revision 12606)
@@ -0,0 +1,9 @@
+
+  rebin <from> <to> scale
+
+  "rebin" rebins the specified buffer by the given scale factor and
+  places the result in the <to> buffer.  Negative integer values imply
+  expansion, positive numbers imply compression.
+
+  See also: extract
+
Index: /tags/start/Ohana/src/opihi/help/region
===================================================================
--- /tags/start/Ohana/src/opihi/help/region	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/region	(revision 12606)
@@ -0,0 +1,11 @@
+
+  region RA DEC Radius [projection]
+
+  define the current sky region and optionally the projection.  
+  RA, DEC and Radius are all values in decimal degrees.  The possible 
+  values for "projection" are:
+
+  TAN - a tangent plane projection (default, and typical for optical images)
+  SIN - a sine plane projection (more appropriate for polar regions)
+  AIT - aitoff projection (good for the full sky)
+  GLS - ?? (also good for the full sky)
Index: /tags/start/Ohana/src/opihi/help/resid
===================================================================
--- /tags/start/Ohana/src/opihi/help/resid	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/resid	(revision 12606)
@@ -0,0 +1,12 @@
+
+  resid [-im time] [-X] [-l] (photometry file)
+
+  plot the photometry residuals for a photometry database file. 
+  For every star in the database, the average magnitude is plotted 
+  vs the difference between the average magnitude and each existing 
+  measurement for that star.  
+
+  -l		automatically set the plot limits.
+  -X		plot residual divided by photometric error
+  -im time	only plot the residuals for one of the images 
+		in the database, specified by the obseravation time.
Index: /tags/start/Ohana/src/opihi/help/resize
===================================================================
--- /tags/start/Ohana/src/opihi/help/resize	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/resize	(revision 12606)
@@ -0,0 +1,6 @@
+
+   resize Nx Ny
+
+   change the size of the Kii window to have image dimensions Nx x
+   Ny.  
+
Index: /tags/start/Ohana/src/opihi/help/rotate
===================================================================
--- /tags/start/Ohana/src/opihi/help/rotate	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/rotate	(revision 12606)
@@ -0,0 +1,10 @@
+
+   rotate (buffer) (angle) [-center x y]
+
+   rotate the buffer by the given angle.  The angle may also be one of
+   the following special words:
+
+   -flipx - flip in the x direction
+   -flipy - flip in the y direction
+
+   if the optional center is given the rotation is about this position.
Index: /tags/start/Ohana/src/opihi/help/save
===================================================================
--- /tags/start/Ohana/src/opihi/help/save	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/save	(revision 12606)
@@ -0,0 +1,16 @@
+  save (overlay) (filename)
+
+  "save" stores the objects from the specified overlay into the named
+file.  Valid overlays may be: 0, red, 1, green, 2, blue, 3, yellow.
+
+Examples of SAOimage style objects:
+BOX   300  200  100 50  : draws a box centered at pixel 300,200 that
+			  is 100 pixels wide, and 50 pixels high
+
+CIRCLE 500 400 200 : draws a circle centered at pixel 500,400 with a
+                     radius of 200 pixels
+
+LINE 100 100 200 200 : draws a line from (100,100) with length (200,200)
+
+  See also: load, erase, contour
+
Index: /tags/start/Ohana/src/opihi/help/scan
===================================================================
--- /tags/start/Ohana/src/opihi/help/scan	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/scan	(revision 12606)
@@ -0,0 +1,5 @@
+
+   scan (filename) (variable) [Nline]
+
+   place the Nth line in the file in the named variable
+
Index: /tags/start/Ohana/src/opihi/help/set
===================================================================
--- /tags/start/Ohana/src/opihi/help/set	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/set	(revision 12606)
@@ -0,0 +1,41 @@
+
+  set (buffer) = expression..
+
+  perform math operations on images.  there are several allowed
+  operators.  the standard math functions are + - * /.  Exponentiation
+  is performed with ^ (set c = a ^ b).  There are several "logic"
+  operators which need some explanation.
+
+  set c = a < b  -- c is 1 if a < b, 0 otherwise
+  set c = a > b  -- c is 1 if a > b, 0 otherwise
+  set c = m1 & m1 - c is 1 if m1 AND m2 true (non-zero is true)
+  set c = m1 | m1 - c is 1 if m1 OR m2 true (non-zero is true)
+  set c = a << b -- c is the minimum of a and b
+  set c = a >> b -- c is maximum of a and b
+
+  complex operations may be performed:
+
+  set c = a*(a < b) + c*((a < c) | (c < d))
+
+  unary operators also exist:
+
+  exp(a) - e to the power of a
+  ten(a) - 10 to the power of a
+  ln(a) - log base e of a
+  log(a) - log base 10 of a
+  sqrt(a) - square root of a
+  sin(a) - sin of a
+  cos(a) - sin of a
+  tan(a) - sin of a
+  not(a) - logical inverse of a
+  abs(a) - absolute value of a
+  int(a) - integer value of a
+
+  Examples:
+  
+  set a = b + 10  (add 10 to every pixel in b and put the answer in a)
+  set a = a / b   (divide every pixel in a by the corresponding pixel
+                     b and put the answer in a)
+  set b = 10 / a  (divide 10 by every pixel in a and put the answer
+                     in b)
+
Index: /tags/start/Ohana/src/opihi/help/shift
===================================================================
--- /tags/start/Ohana/src/opihi/help/shift	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/shift	(revision 12606)
@@ -0,0 +1,6 @@
+
+   shift buffer dx dy
+
+   shift image by dx,dy pixels (may be fractional values).
+
+   
Index: /tags/start/Ohana/src/opihi/help/simage
===================================================================
--- /tags/start/Ohana/src/opihi/help/simage	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/simage	(revision 12606)
@@ -0,0 +1,7 @@
+
+  simage (filename)
+
+  plot the positions of stars in a CMP file.  This function is a
+  useful test for image comparisons, and astrometry must be determined
+  before the function is run.
+
Index: /tags/start/Ohana/src/opihi/help/stats
===================================================================
--- /tags/start/Ohana/src/opihi/help/stats	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/stats	(revision 12606)
@@ -0,0 +1,10 @@
+
+  stats (buffer) (x) (y) (nx) (ny)
+
+  report the statistics on a portion of an image.  (x) and (y) specify
+the starting corner of the region, (nx) and (ny) specify the width and
+height of the region.  stats reports the mean, sigma, and number of
+pixels in the region.
+
+  See Also: ??
+
Index: /tags/start/Ohana/src/opihi/help/style
===================================================================
--- /tags/start/Ohana/src/opihi/help/style	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/style	(revision 12606)
@@ -0,0 +1,36 @@
+
+   style -- many options
+
+   define or check the Kapa plotting style.  without any command-line arguments,
+   style prints the current style.  
+
+   option definitions:
+
+   -n	window number (0-4), can also be used to change active window.
+   -pt	point style: 
+		0 = filled box
+		1 = open box
+		2 = +
+		3 = X
+		4 = filled triangle
+		5 = blank
+		6 = open triangle 
+		7 = open circle
+		100 = connect pair of points
+   -x	plotting method:
+		0 = connect
+		1 = histogram
+		2 = points
+   -lt	line type:
+		0 = solid
+		1 = dashed
+		2 = dotted??
+   -lw	line weight (0-10)
+   -sz	point size
+   -c   color:
+	black, white, red, orange, 
+	yellow, green, blue, indigo, violet
+   -eb  errorbar with no top
+   +eb  errorbar with top
+
+   See also: plot, box
Index: /tags/start/Ohana/src/opihi/help/subset
===================================================================
--- /tags/start/Ohana/src/opihi/help/subset	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/subset	(revision 12606)
@@ -0,0 +1,12 @@
+
+   subset vec = vec if (logic expression)
+
+   reduce the length of a vector based on logical expression.  The
+   logic expression is some function of vectors of equal length to the
+   main vector.
+
+   for example, we have vectors x and y of the same length:
+   
+   subset X = x if ((y > 100) | (x < 10))
+
+    
Index: /tags/start/Ohana/src/opihi/help/textline
===================================================================
--- /tags/start/Ohana/src/opihi/help/textline	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/textline	(revision 12606)
@@ -0,0 +1,7 @@
+
+   textline x y (line) [-fn (font) size] [-rot angle]
+
+   write the string at the given coordinates and rotation,
+   in the given font.
+
+   (enclose long strings with spaces in quotes)
Index: /tags/start/Ohana/src/opihi/help/tv
===================================================================
--- /tags/start/Ohana/src/opihi/help/tv	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/tv	(revision 12606)
@@ -0,0 +1,13 @@
+
+  tv [-log] (buffer) [zero range]
+
+  display an image in the Ki'i window (X display program).  zero and
+  range specify the data values corresponding to the color mapping.
+  If they are not specified, the old values are used (default is 0,
+  1024).
+
+  If -log is specified the color mapping scale will be logarithmic.  
+
+
+  See Also: Kii, rd, cursor
+
Index: /tags/start/Ohana/src/opihi/help/unsign
===================================================================
--- /tags/start/Ohana/src/opihi/help/unsign	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/unsign	(revision 12606)
@@ -0,0 +1,20 @@
+  unsign
+
+  "unsign" toggles the status of the UNSIGN mode.  Warning: This is a
+non-FITS standard implementation.  The FITS standard does not allow
+for unsigned integer data values, but many sites write CCD images with
+16 bit UNSIGNED data.  Mana looks for a FITS keyword "UNSIGN" to
+determine if an image which is read in has signed or unsigned
+integers.  However, since this is a non-standard concept, many sites
+do not use the UNSIGN flag, yet still write unsigned data.  If the
+user knows the data in the file is unsigned (ie, the user must have
+apriori knowledge -- a FITS no-no!), then the user should set the
+UNSIGN mode to true.  In the event that the UNSIGN mode is set, if a
+FITS file is encountered which contains integers, but which does not
+contain the UNSIGN keyword, Mana will make the default assumption that
+the data is unsigned.  If the SIGNED mode is set, Mana will assume all
+integer FITS files contain signed integers.  
+
+((( should be able to say "unsign <buffer>" to convert the status of a
+buffer to UNSIGN or to toggle the buffer's status, but not yet
+implemented)))
Index: /tags/start/Ohana/src/opihi/help/vectors
===================================================================
--- /tags/start/Ohana/src/opihi/help/vectors	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/vectors	(revision 12606)
@@ -0,0 +1,5 @@
+
+   vectors
+
+   list the currently defined vectors and lengths
+
Index: /tags/start/Ohana/src/opihi/help/wait
===================================================================
--- /tags/start/Ohana/src/opihi/help/wait	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/wait	(revision 12606)
@@ -0,0 +1,5 @@
+
+  wait [anything]
+
+  wait echos the rest of the line and waits for <return> to be typed.
+Very useful for pausing the processing of an input file or a macro.
Index: /tags/start/Ohana/src/opihi/help/wd
===================================================================
--- /tags/start/Ohana/src/opihi/help/wd	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/wd	(revision 12606)
@@ -0,0 +1,29 @@
+
+  wd (buffer) (filename) [BITPIX]
+
+  wd writes a buffer to the specified file in FITS format.  (You may
+need quotes around the filename if there are any /'s in the path).
+The FITS keyword BITPIX may be specified.  Valid values are 8, 16, 32
+(integer formats) and -32, -64 (floating point formats).  If BITPIX is
+unspecified, the original value of the image is used.  The image is
+converted blindly to the format and written out.  This may mean that
+values are rounded (integers), or wrapped by the range of the number
+of bits.  Also beware of the issue of signed vs unsigned images.
+
+  See Also: rd
+
+bitpix  bzero  bscale  file range     data range
+16      0      1       -32k : 32k     -32k : 32k
+16	32k    1       -32k : 32k        0 : 64k
+16	0      2       -32k : 32k     -64k : 64k
+16	0      0.001   -32k : 32k     -32. : 32.
+32	0      1       -2e9 : 2e9     -2e9 : 2e9
+8	0      1       -128 : 128     -128 : 128
+
+so for example, a file with a data range of -128k to +128k written
+with bitpix 16, bzero 0, bscale 1 will have all data outside -32k :
++32k wrapped back in that range.
+
+note: on write, bzero is subtracted from the data before the data is
+      divided by bscale.
+
Index: /tags/start/Ohana/src/opihi/help/which
===================================================================
--- /tags/start/Ohana/src/opihi/help/which	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/which	(revision 12606)
@@ -0,0 +1,5 @@
+
+   which (command)
+
+   give a short summary info line on a command
+
Index: /tags/start/Ohana/src/opihi/help/zplot
===================================================================
--- /tags/start/Ohana/src/opihi/help/zplot	(revision 12606)
+++ /tags/start/Ohana/src/opihi/help/zplot	(revision 12606)
@@ -0,0 +1,7 @@
+
+   zplot x y z min max
+
+   plot the vector pair x and y as a series of points with size scaled
+   by the values in the vector z, with the smallest point having
+   values <= min and the largest having values >= max.
+
Index: /tags/start/Ohana/src/opihi/include/astro.h
===================================================================
--- /tags/start/Ohana/src/opihi/include/astro.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/include/astro.h	(revision 12606)
@@ -0,0 +1,13 @@
+# include "external.h"
+# include "shell.h"
+# include "dvomath.h"
+# include "convert.h"
+# include "display.h"
+# include "data.h"
+
+# ifndef ASTRO_H
+# define ASTRO_H
+
+/* why is nothing in here? */
+
+# endif
Index: /tags/start/Ohana/src/opihi/include/basic.h
===================================================================
--- /tags/start/Ohana/src/opihi/include/basic.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/include/basic.h	(revision 12606)
@@ -0,0 +1,5 @@
+# include "external.h"
+# include "shell.h"
+# include "dvomath.h"
+
+void cleanup ();
Index: /tags/start/Ohana/src/opihi/include/convert.h
===================================================================
--- /tags/start/Ohana/src/opihi/include/convert.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/include/convert.h	(revision 12606)
@@ -0,0 +1,34 @@
+# include "external.h"
+
+# ifndef CONVERT_H
+# define CONVERT_H
+
+/*** values for time formats */
+enum {TIME_NONE, TIME_JD, TIME_MJD, TIME_DATE, TIME_DAYS, TIME_HOURS, TIME_MINUTES, TIME_SECONDS};
+
+/*** conversion functions ***/
+time_t        TimeRef               PROTO((double time, time_t TimeReference, int TimeFormat));
+double        TimeValue             PROTO((time_t time, time_t TimeReference, int TimeFormat));
+int           chk_time              PROTO((char *line));
+time_t        date_to_sec           PROTO((char *date));
+int           dms_to_ddd            PROTO((double *Value, char *string));
+time_t        jd_to_sec             PROTO((double jd));
+time_t        mjd_to_sec            PROTO((double mjd));
+char         *sec_to_date           PROTO((time_t second));
+double        sec_to_jd             PROTO((time_t second));
+double        sec_to_mjd            PROTO((time_t second));
+int           str_to_dtime          PROTO((char *line, double *second));
+int           str_to_radec          PROTO((double *ra, double *dec, char *str1, char *str2));
+int           str_to_time           PROTO((char *line, time_t *second));
+int           hh_hms                PROTO((double hh, int *hr, int *mn, double *sc));
+int           dd_dms                PROTO((double dd, int *dg, int *mn, double *sc));
+int           hms_format            PROTO((char *line, double value));
+int           dms_format            PROTO((char *line, double value));
+int           hh_hm                 PROTO((double hh, int *hr, double *mn));
+
+char         *meade_deg_to_str      PROTO((double deg));
+char         *meade_ra_to_str       PROTO((double deg));
+char         *meade_dec_to_str      PROTO((double deg));
+int           hstgsc_hms_to_deg     PROTO((double *h0, double *h1, double *d0, double *d1, char *string));
+
+# endif
Index: /tags/start/Ohana/src/opihi/include/data.h
===================================================================
--- /tags/start/Ohana/src/opihi/include/data.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/include/data.h	(revision 12606)
@@ -0,0 +1,98 @@
+# include "external.h"
+# include "shell.h"
+# include "dvomath.h"
+# include "convert.h"
+# include "display.h"
+
+# ifndef DATA_H
+# define DATA_H
+
+/* in misc/queues.c */
+void InitQueues ();
+Queue *FindQueue (char *name);
+Queue *CreateQueue (char *name);
+void PushQueue (Queue *queue, char *line);
+char *PopQueue (Queue *queue);
+
+/* in misc/sort.c */
+void sort (double *value, int N);
+void fsort (float *value, int N);
+void sortpair (double *value1, double *value2, int N);
+void fsortpair (float *X, float *Y, int N);
+void sortthree (float *X, float *Y, float *Z, int N);
+void sort_lists (float *X, float *Y, int *S, int N);
+void dsort_lists (double *X, double *Y, int *S, int N);
+
+/* in misc/fft.c */
+void fft (float *Data, int N, int isign);
+void fftold (float *Data, int N, int isign);
+void fftN (float *data, int *nn, int ndim, int isign);
+int IsBinary (int N);
+void fourn (float *data, int *nn, int ndim, int isign);
+
+/* in misc/gaussj.c */
+int gaussj (double **a, int n, double **b, int m);
+int fgaussj (float **a, int n, float **b, int m);
+
+/* in misc/svdcmp.c */
+int svdcmp (float *a, float *w, float *v, int Nx, int Ny);
+
+/* in misc/spline.c */
+void spline (float *x, float *y, int N, float *y2);
+float splint (float *x, float *y, float *y2, int N, float X);
+
+/* misc/mrqmin.c */
+float mrqcof (float *x, float *y, float *dy, int Npts, 
+	      float *par, int Npar, float **ta, float **tb, 
+	      float (funcs)(float, float *, int, float *));
+
+float mrqmin (float *x, float *y, float *dy, int Npts, 
+	      float *par, int Npar, 
+	      float (funcs)(float, float *, int, float *));
+
+int mrqinit (float *x, float *y, float *dy, int Npts, 
+	     float *par, int Npar, 
+	     float (funcs)(float, float *, int, float *));
+
+float **mrqcovar (int Npar);
+
+void mrqfree (int Npar);
+
+/* misc/mrq2dmin.c */
+float mrq2dcof (float *x, float *t, float *y, float *dy, int Npts, 
+		float *par, int Npar, float **ta, float **tb, 
+		float (funcs)(float, float, float *, int, float *));
+
+float mrq2dmin (float *x, float *t, float *y, float *dy, int Npts, 
+		float *par, int Npar, 
+		float (funcs)(float, float, float *, int, float *));
+
+float mrq2dinit (float *x, float *t, float *y, float *dy, int Npts, 
+		 float *par, int Npar, 
+		 float (funcs)(float, float, float *, int, float *));
+
+float **mrq2dcovar (int Npar);
+
+void mrq2dfree (int Npar);
+
+/* misc/powell.c */
+void powell (float *p, int Npar, float (func)() );
+
+/* misc/gaussian.c */
+double gaussian (double x, double mean, double sigma);
+void gauss_init (int Nbin);
+double rnd_gauss (double mean, double sigma);
+
+/* misc/starfuncs.c */
+double get_aperture_stats (Matrix *matrix, int X, int Y, int Npix, int Nborder, double max);
+
+/* misc/precess.c */
+double BtoJ (double in_epoch);
+double get_epoch (char *in_epoch, char mode);
+
+/* misc/graphtools.c */
+void          SetLimits             PROTO((Vector *xvec, Vector *yvec, Graphdata *graphmode));
+void          ApplyLimits           PROTO((int Xgraph, Graphdata *graphmode, int apply));
+
+int read_table_vectors (int argc, char **argv, char *extname);
+# endif
Index: /tags/start/Ohana/src/opihi/include/dimm.h
===================================================================
--- /tags/start/Ohana/src/opihi/include/dimm.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/include/dimm.h	(revision 12606)
@@ -0,0 +1,69 @@
+# include "external.h"
+# include "shell.h"
+# include "dvomath.h"
+# include "convert.h"
+# include "display.h"
+# include "sbig.h"
+
+/* telescope.c */
+double distSky (double r1, double r2, double d1, double d2);
+int getRD (double *r, double *d) ;
+int gotoRD (double r, double d);
+int offset (char *direction, double distance);
+int toffset (char *direction, char *rate, double duration);
+int getXY (double *x, double *y);
+int setRD (double r, double d);
+int setSite (char *sitename, double lon, double lat);
+int setTime (char *lst);
+int getSite (double *lon, double *lat, double *lst);
+int ParkScope();
+int SleepScope();
+int WakeScope();
+
+/* Serial.c */
+int SerialVerbose (int mode);
+int SerialInit (char *port);
+int SerialOpen (char *port);
+int SerialBaudRate (int fdesc, int rate);
+int SerialParity (int fdesc, int parity); 
+int SerialDataBits(int fdesc, int bits); 
+int SerialStopBit(int fdesc, int stpbit); 
+void SerialStop (int fdesc);
+int SerialCommand (char *in, char **out, int wait);
+
+/* camera.c */
+int InitCamera (int port);
+void DumpCameraInfo ();
+void CameraFullSize (int *x, int *y);
+int SetTemperature (double temp);
+double GetTemperature ();
+int DumpCameraStatus ();
+int Exposure (double exptime);
+static int readout_callback (float percent);
+int ReadOut (int x, int y, int dx, int dy, int binning, unsigned short *buffer);
+int OpenShutter ();
+int CloseShutter ();
+
+  /* this image structure stuff is considered for further development */ 
+# if (0)
+/** this Image is incompatible with the DVO Image struct */
+typedef struct {
+
+  /* image data area */
+  int Nx, Ny;
+  char *buffer;
+  int Nbytes;
+
+  /* image metadata */
+  double ccdtemp;
+  double airtemp;
+  double ra, dec, airmass;
+  double exptime;
+  int binning;
+} Image;
+
+/* analysis.c */
+int subtractImage (Image *a, Image *b);
+void statsImage (Image *image, Stats *stats);
+void findStars (Image *image, Stars **stars, int *Nstars, double threshold);
+# endif
Index: /tags/start/Ohana/src/opihi/include/display.h
===================================================================
--- /tags/start/Ohana/src/opihi/include/display.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/include/display.h	(revision 12606)
@@ -0,0 +1,47 @@
+# include "external.h"
+
+# ifndef DISPLAY_H
+# define DISPLAY_H
+
+typedef struct {
+  double xmin, xmax, ymin, ymax;
+  int style, ptype, ltype, etype, ebar, color;
+  double lweight, size;
+  Coords coords;
+  int flipeast, flipnorth;
+} Graphdata;
+
+/*** plotting functions ***/
+int           GetCurrentDevice      PROTO((void));
+int           PrepPlotting          PROTO((int Npts, Graphdata *graphmode));
+int           PlotVector            PROTO((int, float *));
+int           GetGraphData          PROTO((Graphdata *data, int *sock, int *N));
+int           GetGraph              PROTO((Graphdata *data, int *socket, int *N));
+void          InitGraph             PROTO((void));
+int           open_graph            PROTO((int N));
+void          QuitGraph             PROTO((void));
+void          SetGraph              PROTO((Graphdata data));
+void          XGraphDead            PROTO((int input));
+int           GetColor              PROTO((char *name));
+
+/* image (tv) functions */
+int           GetImage              PROTO((int *socket, int *N));
+char         *GetImageName          PROTO((void));
+void          GetImageScale         PROTO((double *zero, double *range));
+void          InitImage             PROTO((void));
+int           open_image            PROTO((int N));
+void          QuitImage             PROTO((void));
+void          SetImageDevice        PROTO((int state));
+void          SetImageName          PROTO((char *name));
+void          SetImageScale         PROTO((double zero, double range));
+void          XImageDead            PROTO((int input));
+int           SelectOverlay         PROTO((char *name, int *number));
+
+/* calling program need to define a function 'get_variable' which
+ * returns the name of the executable for each of KAPA and KII
+ */
+char         *get_variable          PROTO((char *name));
+
+int SendLabel (char *string, int Xgraph, int mode);
+
+# endif
Index: /tags/start/Ohana/src/opihi/include/dvo.h
===================================================================
--- /tags/start/Ohana/src/opihi/include/dvo.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/include/dvo.h	(revision 12606)
@@ -0,0 +1,63 @@
+# include "external.h"
+# include "shell.h"
+# include "dvomath.h"
+# include "convert.h"
+# include "display.h"
+# include "data.h"
+
+# ifndef DVO_H
+# define DVO_H
+
+/* magnitude types */
+enum {MAG_NONE, MAG_INST, MAG_CAT, MAG_SYS, MAG_REL, MAG_CAL, MAG_AVE, MAG_REF};
+
+/* measure params */
+enum {MEAS_ZERO, MEAS_RA, MEAS_DEC, MEAS_MAG, MEAS_dMAG, MEAS_MINST, MEAS_MCAT, 
+      MEAS_MSYS, MEAS_MREL, MEAS_MCAL, MEAS_PHOTCODE, MEAS_TIME, MEAS_dR, MEAS_dD, 
+      MEAS_FWHM, MEAS_DOPHOT, MEAS_XCCD, MEAS_YCCD, MEAS_XMOSAIC, MEAS_YMOSAIC, MEAS_FLAGS, MEAS_EXPTIME, MEAS_AIRMASS};
+
+/* average params */
+enum {AVE_ZERO, AVE_RA, AVE_DEC, AVE_MAG, AVE_REF, AVE_dMAG, AVE_Xm, AVE_Xp, AVE_NMEAS, 
+      AVE_NMISS, AVE_TYPE, AVE_NPHOT, AVE_NCODE, AVE_NCRIT, AVE_FLAG};
+
+typedef struct {
+  char name[64];
+  double RA0, RA1, DEC0, DEC1;
+} RegionFile;
+
+/* aregion, region_list, match_image, LoadImages */
+RegionFile   *find_regions	    PROTO((double Ra, double Dec, double radius, int *Nregions));
+GSCRegion    *get_regions	    PROTO((Image *image, int *Nregions));
+void	      aregion		    PROTO((GSCRegion *region, FILE *f, double ra, double dec, char *path));
+RegionFile   *region_list	    PROTO((char *filename, int *Nregions));
+int	      match_image	    PROTO((Image *image, int Nimage, unsigned int T, short int S));
+Image  	     *LoadImages	    PROTO((int *Nimage));
+void	      image_subset	    PROTO((Image *image, int Nimage, int **Subset, int *Nsubset, Graphdata *graph, int RegionSelect, unsigned long int tzero, double trange, int TimeSelect));
+void	      sort_images	    PROTO((Image *image, int N));
+void	      sortave		    PROTO((Average *ave, int N));
+void	      cprecess		    PROTO((Average *average, int Naverage, double in_epoch, double out_epoch));
+void	      compare		    PROTO((Catalog *catlog1, Catalog *catlog2, Vector *rvec,  Vector *dvec,  Vector *mvec, Vector *drvec, Vector *ddvec, Vector *dmvec, double radius));
+
+/*** photometry functions ***/
+int           SetPhotSelections     PROTO((int *argc, char **argv));
+int           SetImageSelection     PROTO((int mode, Graphdata *graphsky, int state));
+void          FreeImageSelection    PROTO(());
+
+int           InitPhotcodes         PROTO(());
+int           GetPhotcodeInfo       PROTO((char *string, PhotCode **Code, int *Mode));
+
+int           GetAverageParam       PROTO((char *parname));
+int           GetMeasureParam       PROTO((char *parname));
+int           GetMagMode            PROTO((char *string));
+int           SelectMags            PROTO((int Nphot, int Tphot, int Ns, Average *average, Measure *measure, SecFilt *secfilt, int UL));
+void          print_value           PROTO((FILE *f, double value, short int ival));
+int           GetMeasureTypeCode    PROTO((Measure *measure));
+int           DetermineTypeCode     PROTO((Average *average, Measure *measure, int Nphot));
+double        ExtractAverages       PROTO((PhotCode *code, int mode, Average *ave, SecFilt *sec, Measure *meas, int param));
+double       *ExtractMagnitudes     PROTO((PhotCode *code, int mode, Average *ave, SecFilt *sec, Measure *meas, int *n));
+double       *ExtractMeasures       PROTO((PhotCode *code, int mode, Average *ave, SecFilt *sec, Measure *meas, int *nlist, int param));
+double       *ExtractDMag           PROTO((PhotCode **code, int *mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist));
+double       *ExtractMeasuresDMag   PROTO((PhotCode **code, int *mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist));
+double       *ExtractMeasuresByDMag PROTO((PhotCode **code, int *mode, int use_first, Average *average, SecFilt *secfilt, Measure *measure, int *nlist, int param));
+
+# endif
Index: /tags/start/Ohana/src/opihi/include/dvo2.h
===================================================================
--- /tags/start/Ohana/src/opihi/include/dvo2.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/include/dvo2.h	(revision 12606)
@@ -0,0 +1,35 @@
+# include "external.h"
+# include "shell.h"
+# include "dvomath.h"
+# include "convert.h"
+# include "display.h"
+# include "data.h"
+
+# ifndef DVO2_H
+# define DVO2_H
+
+typedef struct {
+  float r, d;
+} SkyCoord;
+
+typedef struct {
+  float Rmin, Rmax;
+  float Dmin, Dmax;
+  int   childS, childE, parent;
+  char  depth, child;
+  char  object, image;
+  char  name[24];
+} SkyRegion; /* 48 bytes */ 
+
+SkyRegion *SkyFindPoint (SkyRegion *db, SkyCoord c, int depth);
+SkyRegion **SkyFindLevels (SkyRegion *db, SkyCoord c, int *Nregion);
+SkyRegion **SkyFindArea (SkyRegion *db, SkyCoord c1, SkyCoord c2, int *nlist);
+SkyRegion *SkyFindAreaDB (SkyRegion *db, SkyRegion *ref, SkyCoord c1, SkyCoord c2, int *Nregion);
+SkyRegion *SkyBuildTable (SkyRegion *seed, int Nseed, int level, int depth);
+
+SkyRegion *SkyMakeRegions (int Nlevels, int *nlist);
+SkyRegion *SkyDivideRegions (SkyRegion *parents, int *N);
+SkyRegion *SkyDivideBiggest (SkyRegion *list, int *nlist);
+SkyRegion *SkyDivide (SkyRegion *in);
+
+# endif
Index: /tags/start/Ohana/src/opihi/include/dvomath.h
===================================================================
--- /tags/start/Ohana/src/opihi/include/dvomath.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/include/dvomath.h	(revision 12606)
@@ -0,0 +1,121 @@
+/*** dvomath.h ***/
+
+# ifndef DVOMATH_H
+# define DVOMATH_H
+
+# define NCHARS 256
+
+enum {ANYVECTOR, NEWVECTOR, OLDVECTOR};
+enum {ANYBUFFER, NEWBUFFER, OLDBUFFER};
+
+/*** typedef structs used by math functions ***/
+typedef struct {
+  int   NLINES;
+  int   Nlines;
+  char **lines;
+  char  *name;
+} Queue;
+
+typedef struct {			/* representation of a variable (0-D) */
+  char     *name;
+  char     *value;
+} Variable;
+
+typedef struct {			/* representation of a vector (1-D) */
+  char name[1024];
+  float *elements;
+  int Nelements;
+} Vector;
+
+typedef struct {			/* representation of buffer (image) */
+  char name[1024];
+  char file[1024];
+  Header header;
+  Matrix matrix;
+  int  bitpix, unsign;
+  double bscale, bzero;
+} Buffer;
+
+typedef struct {			/* math stack structure */
+  char   *name;
+  char    type;
+  float  *ptr;
+  Buffer *buffer;
+  Vector *vector;
+  float   Float;
+} StackVar;
+
+/* math functions */
+char         *dvomath               PROTO((int argc, char **argv, int *size, int maxsize));
+char        **isolate_elements      PROTO((int argc, char **argv, int *nstack));
+StackVar     *convert_to_RPN        PROTO((int argc, char **argv, int *nstack));
+int           check_stack           PROTO((StackVar *stack, int Nstack));
+int           evaluate_stack        PROTO((StackVar *stack, int *Nstack));
+void          init_stack            PROTO((StackVar *stack));
+void          copy_stack	    PROTO((StackVar *stack1, StackVar *stack2));
+void          move_stack	    PROTO((StackVar *stack1, StackVar *stack2));
+void          clean_stack	    PROTO((StackVar *stack, int Nstack));
+void          delete_stack	    PROTO((StackVar *stack, int Nstack));
+int           VV_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           SV_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           VS_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           MV_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           VM_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           MM_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           MS_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           SM_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           SS_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           S_unary               PROTO((StackVar *OUT, StackVar *V1, char *op));
+int           V_unary               PROTO((StackVar *OUT, StackVar *V1, char *op));
+int           M_unary               PROTO((StackVar *OUT, StackVar *V1, char *op));
+
+/* variable handling */
+char         *get_variable          PROTO((char *name));
+char         *get_variable_ptr      PROTO((char *name));
+char         *get_local_variable_ptr PROTO((char *name));
+double        get_double_variable   PROTO((char *name));
+int           DeleteNamedScalar     PROTO((char *name));
+int           IsScalar              PROTO((char *name));
+int           set_variable          PROTO((char *name, double dvalue));
+int           set_int_variable      PROTO((char *name, int ivalue));
+int           set_str_variable      PROTO((char *name, char *value));
+int           set_local_variable    PROTO((char *name, char *value));
+void          InitVariables         PROTO((void));
+void          ListVariables         PROTO((void));
+
+/* vector handling */
+Vector       *InitVector            PROTO((void));
+void          InitVectors           PROTO((void));
+int           CopyVector            PROTO((Vector *out, Vector *in));
+int           MoveVector            PROTO((Vector *out, Vector *in));
+int           DeleteVector          PROTO((Vector *vec));
+int           CopyNamedVector       PROTO((char *out, char *in));
+int           MoveNamedVector       PROTO((char *out, char *in));
+int           DeleteNamedVector     PROTO((char *name));
+int           IsVector              PROTO((char *name));
+int           IsVectorPtr           PROTO((Vector *vec));
+int           ListVectors           PROTO((void));
+Vector       *SelectVector          PROTO((char *name, int mode, int verbose));
+
+/* buffer handling */
+Buffer       *InitBuffer            PROTO((void));
+void          InitBuffers           PROTO((void));
+int           CopyBuffer            PROTO((Buffer *out, Buffer *in));
+int           MoveBuffer            PROTO((Buffer *out, Buffer *in));
+int           DeleteBuffer          PROTO((Buffer *buf));
+int           CopyNamedBuffer       PROTO((char *out, char *in));
+int           MoveNamedBuffer       PROTO((char *out, char *in));
+int           DeleteNamedBuffer     PROTO((char *name));
+int           IsBuffer              PROTO((char *name));
+int           IsBufferPtr           PROTO((Buffer *buf));
+int           PrintBuffers          PROTO((int Long));
+int           CreateBuffer          PROTO((Buffer *buf));
+Buffer       *SelectBuffer          PROTO((char *name, int mode, int verbose));
+void          dump_buffers          PROTO((int n));  /* deprecated? */
+int           SelectOverlay         PROTO((char *name, int *number));
+
+/* why are these in here? */
+int           fits_copy_matrix_info (Matrix *matrix1, Matrix *matrix2);
+int           GetTimeFormat         PROTO((time_t *TimeReference, int *TimeFormat));
+
+# endif
Index: /tags/start/Ohana/src/opihi/include/external.h
===================================================================
--- /tags/start/Ohana/src/opihi/include/external.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/include/external.h	(revision 12606)
@@ -0,0 +1,23 @@
+# include <signal.h>
+# include <unistd.h>
+# include <sys/uio.h>
+# include <fcntl.h>
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <sys/un.h>
+# include <sys/time.h>
+# include <time.h>
+# include <errno.h>
+
+# include <ohana.h>
+# include <fitsio.h>
+# include <loneos.h>
+
+/* provide missing external defines */
+# ifdef MISSING_SOCKET_INFO
+#   define F_SETFL         4   
+#   define O_NONBLOCK       0200000  
+#   define AF_UNIX         1          
+#   define SOCK_STREAM     1          
+#   define ENOENT          2 
+# endif
Index: /tags/start/Ohana/src/opihi/include/hstgsc.h
===================================================================
--- /tags/start/Ohana/src/opihi/include/hstgsc.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/include/hstgsc.h	(revision 12606)
@@ -0,0 +1,24 @@
+
+static double BigDecBounds[] = {0.0, 7.5, 15.0, 22.5, 30.0, 37.5, 45.0, 
+				52.5, 60.0, 67.5, 75.0, 82.5, 90.0,
+				0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, 
+				-52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+static char *DecSections[] = {"N0000", "N0730", "N1500", "N2230", "N3000", "N3730", "N4500", 
+			      "N5230", "N6000", "N6730", "N7500", "N8230", "weirdness", 
+			      "S0000", "S0730", "S1500", "S2230", "S3000", "S3730", "S4500", 
+			      "S5230", "S6000", "S6730", "S7500", "S8230", "weirdness"};
+
+static char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			       "n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			       "s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			       "s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+static char *disk[] = {"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", 
+		       "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "weirdness", 
+		       "disk 1", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", 
+		       "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "weirdness"};
+
+static int NBigRASections [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3, 48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3};
+
+static int NDecLines[] = {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 24, 
+			  0, 597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48};
Index: /tags/start/Ohana/src/opihi/include/inherent.h
===================================================================
--- /tags/start/Ohana/src/opihi/include/inherent.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/include/inherent.h	(revision 12606)
@@ -0,0 +1,47 @@
+/******* List of the Inherent Commands *********/
+int cd         PROTO((int, char **));
+int echo       PROTO((int, char **));
+int exec_break PROTO((int, char **));
+int exec_continue PROTO((int, char **));
+int help       PROTO((int, char **));
+int input      PROTO((int, char **));
+int list_help  PROTO((int, char **));
+int list_vars  PROTO((int, char **));
+int macro      PROTO((int, char **));
+int output     PROTO((int, char **));
+int pwd        PROTO((int, char **));
+int quit       PROTO((int, char **));
+int run_while  PROTO((int, char **));
+int run_for    PROTO((int, char **));
+int run_if     PROTO((int, char **));
+int list       PROTO((int, char **));
+int scan       PROTO((int, char **));
+int shell      PROTO((int, char **));
+int wait       PROTO((int, char **));
+int which      PROTO((int, char **));
+
+/** mapping of the command names to command functions **/
+static Command inherent[] = {  
+  {"cd",      cd,                 "change directory"},
+  {"echo",    echo,               "type this line *"},
+  {"break",   exec_break,         "escape from function *"},
+  {"continue",exec_continue,      "next loop iteration"},
+  {"help",    help,               "get help on a function *"},
+  {"input",   input,              "read command lines from a file *"},
+  {"?",       list_help,          "list commands *"},
+  {"??",      list_vars,          "list variables *"},
+  {"list",    list,               "get variable list"},
+  {"macro",   macro,              "deal with the macros *"}, 
+  {"output",  output,             "redirect output to file"},
+  {"pwd",     pwd,                "print current working directory"},
+  {"exit",    quit,               "exit program *"}, 
+  {"quit",    quit,               "exit program *"},
+  {"while",   run_while,          "while loop"}, 
+  {"for",     run_for,            "for loop"}, 
+  {"if",      run_if,             "logical cases *"}, 
+  {"scan",    scan,               "scan line from keyboard or file to variable *"},
+  {"!",       shell,              "system call"},
+  {"exec",    shell,              "system call"},
+  {"wait",    wait,               "wait until return is typed"},
+  {"which",   which,              "show command *"}
+};
Index: /tags/start/Ohana/src/opihi/include/macro.h
===================================================================
--- /tags/start/Ohana/src/opihi/include/macro.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/include/macro.h	(revision 12606)
@@ -0,0 +1,10 @@
+static Command in_macro[] = {
+  {"create", macro_create, "create a macro *"},
+  {"delete", macro_delete, "delete a macro *"},
+  {"list",   macro_list_f, "list a macro *"},
+  {"edit",   macro_edit,   "edit a macro <not working yet!> *"},
+  {"read",   macro_read,   "read a macro from a file <not working yet!> *"},
+  {"write",  macro_write,  "write a macro to a file <not working yet!> *"}
+};
+
+/*** need to encapsulate the macro command lookup ***/
Index: /tags/start/Ohana/src/opihi/include/mana.h
===================================================================
--- /tags/start/Ohana/src/opihi/include/mana.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/include/mana.h	(revision 12606)
@@ -0,0 +1,7 @@
+
+/* place in program-specific file? */
+# define opihi_name "DVO"
+# define opihi_prompt "dvo: "
+# define opihi_description "Desktop Virtual Observatory\n"
+# define opihi_history ".dvo"
+# define opihi_resource ".dvorc"
Index: /tags/start/Ohana/src/opihi/include/opihi.h
===================================================================
--- /tags/start/Ohana/src/opihi/include/opihi.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/include/opihi.h	(revision 12606)
@@ -0,0 +1,5 @@
+# include "external.h"
+# include "shell.h"
+# include "dvomath.h"
+# include "convert.h"
+# include "display.h"
Index: /tags/start/Ohana/src/opihi/include/scheduler.h
===================================================================
--- /tags/start/Ohana/src/opihi/include/scheduler.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/include/scheduler.h	(revision 12606)
@@ -0,0 +1,64 @@
+
+enum {JOB_BUSY, JOB_EXIT, JOB_CRASH};
+
+/* a task is a description of the wrapping of a job */
+typedef struct {
+  Macro  *exec;				/* name is 'exec' */
+  Macro  *crash;			/* name is 'crash' */
+  Macro  *timeout;
+  Macro  *def;
+
+  int     NEXIT;
+  int     Nexit;
+  Macro **exit;				/* name is exit status */
+
+  int     argc;
+  char  **argv;
+  char   *host;
+
+  char   *name;
+
+  float   poll_period;
+  float   exec_period;
+  float   timeout_period;
+
+  struct timeval last;
+} Task;
+
+typedef struct {
+  int JobID;				/* internal ID for job */
+  int PID;				/* external ID for job */
+
+  Task task;
+
+  struct timeval last;
+  struct timeval start;
+  int state;
+  int exit_status;
+} Job;
+
+
+/* scheduler prototypes */
+void InitTasks ();
+void ListTasks ();
+Task *FindTask (char *name);
+Task *CreateTask (char *name);
+void SetCurrentTask (char *name);
+char *GetCurrentTask ();
+int DeleteTask (Task *task);
+Task *NextTask ();
+int TaskHash (char *input);
+int ShowTask (char *name);
+
+Job *NextJob ();
+void InitJobs ();
+int NextJobID ();
+void ListJobs ();
+Job *FindJob (int JobID);
+Job *CreateJob (Task *task);
+void SetCurrentJob (char *name);
+char *GetCurrentJob ();
+int SubmitJob (Job *job);
+int CheckJob (Job *job);
+int DeleteJob (Job *job);
+void FreeJob (Job *job);
Index: /tags/start/Ohana/src/opihi/include/shell.h
===================================================================
--- /tags/start/Ohana/src/opihi/include/shell.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/include/shell.h	(revision 12606)
@@ -0,0 +1,105 @@
+/*** shell.h ***/
+
+# ifndef SHELL_H
+# define SHELL_H
+
+# define ISVAR(a) (isalnum (a) || (a == ':') || (a == '_'))
+# define ISWORD(a,q) ((q) ? (a != '"') : (isalnum(a) || (a == '/') || (a == '.') || (a == '_') || (a == '-')))
+# define ISNUM(c) (isdigit(c) || (c == '-') || (c == '.'))
+
+/*** typedef structs used by shell functions ***/
+typedef struct {			/* basic opihi command structure */
+  char     *name;
+  Function *func;    
+  char     *help;
+} Command;
+
+typedef struct {			/* a macro (collection of commands) */
+  char   *name;
+  char  **line;
+  int     Nlines;
+} Macro;
+
+typedef struct {			/* a list (macro/loop currently being executed) */
+  char **line;
+  int    n;
+  int    Nlines;
+} List;
+
+/*** globals used to track the shell language concepts  ***/
+List         *lists;			/* variable to store the list of all lists */
+int          Nlists;			/* number of currently available lists */
+
+int 	     interrupt;			/* true if C-C has been pressed */
+int 	     auto_break;		/* if true, zero exit status forces macros to escape */
+int 	     loop_break;		/* set to true when break is called */
+int 	     loop_continue;		/* set to true when continue is called */
+int          is_script;                 /* being run within a shell script */
+
+/*** basic opihi shell functions ***/
+void          initialize            	PROTO((int argc, char **argv));
+void          startup               	PROTO((int argc, char **argv));
+char        **multicommand          	PROTO((char *line, int *nlist));
+int           command               	PROTO((char *, char **));
+char         *expand_vars           	PROTO((char *line));
+char         *expand_vectors        	PROTO((char *line));
+char         *parse                 	PROTO((char *line));
+char        **parse_commands        	PROTO((char *, int *));
+
+int           is_for_loop           	PROTO((char *line));
+int           is_if_block           	PROTO((char *line));
+int           is_list               	PROTO((char *line));
+int           is_loop               	PROTO((char *line));
+int           is_macro_create       	PROTO((char *line));
+
+void          InitCommands              PROTO(());
+void          AddCommand                PROTO((Command *new));
+int           DeleteCommand             PROTO((Command *command));
+Command      *MatchCommand              PROTO((char *name, int VERBOSE, int EXACT));
+void          sort_commands             PROTO((int *seq));
+
+void          SetCurrentMacroData	PROTO((char *name, int depth));
+Macro        *NewMacro			PROTO((char *name));
+int           DeleteMacro		PROTO((Macro *macro));
+Macro        *MatchMacro		PROTO((char *name, int VERBOSE, int EXACT));
+void          InitMacros                PROTO((void));
+char         *GetMacroName              PROTO((void));
+int           GetMacroDepth             PROTO((void));
+
+int           exec_loop                 PROTO((Macro *loop));
+char         *get_next_listentry    	PROTO((int ThisList));
+char         *remove_listentry      	PROTO((int current));
+int           ConfigInit            	PROTO((int *argc, char **argv));
+char         *VarConfig             	PROTO((char *keyword, char *mode, void *ptr));
+FILE         *GetOutfile            	PROTO((void));
+void          InitOutfile           	PROTO((void));
+
+int           push_error                PROTO((char *line));
+int           print_error               PROTO((void));
+void          handle_interrupt      	PROTO((int));
+char        **command_completer     	PROTO((const char *, int, int));
+char         *command_generator     	PROTO((const char *text, int state));
+char        **completion_matches    	PROTO((char *, rl_compentry_func_t *));
+void          print_commands            PROTO((FILE *f));
+void          InitCommands              PROTO((void));
+
+/* command line parsing */
+char         *thisword              	PROTO((char *));
+char         *nextword              	PROTO((char *));
+char         *lastword              	PROTO((char *, char *));
+char         *thisvar               	PROTO((char *));
+char         *aftervar              	PROTO((char *));
+char         *lastvar               	PROTO((char *, char *));
+char         *thiscomm              	PROTO((char *));
+char         *nextcomm              	PROTO((char *));
+
+/* macro functions (mapped to commands) */
+int 	      macro_create 		PROTO((int, char **)); 
+int 	      macro_delete 		PROTO((int, char **)); 
+int 	      macro_edit   		PROTO((int, char **));
+int 	      macro_exec   		PROTO((int, char **));
+int 	      macro_list_f 		PROTO((int, char **));  /* "macro_list" is a readline func */
+int 	      macro_read   		PROTO((int, char **));
+int 	      macro_write  		PROTO((int, char **));
+
+# endif
Index: /tags/start/Ohana/src/opihi/include/user.h
===================================================================
--- /tags/start/Ohana/src/opihi/include/user.h	(revision 12606)
+++ /tags/start/Ohana/src/opihi/include/user.h	(revision 12606)
@@ -0,0 +1,260 @@
+int abszero         PROTO((int, char **));
+int applyfit        PROTO((int, char **));
+int applyfit2d      PROTO((int, char **));
+int badimages       PROTO((int, char **));
+int box             PROTO((int, char **));
+int calextract      PROTO((int, char **));
+int calmextract     PROTO((int, char **));
+int cals            PROTO((int, char **));
+int catlog          PROTO((int, char **));
+int ccd             PROTO((int, char **));
+int ccdextract      PROTO((int, char **));
+int center          PROTO((int, char **));
+int cgrid           PROTO((int, char **));
+int clear           PROTO((int, char **));
+int cmatch          PROTO((int, char **));
+int cmd             PROTO((int, char **));
+int cmdextract      PROTO((int, char **));
+int cmpread         PROTO((int, char **));
+int concat          PROTO((int, char **));
+int contour         PROTO((int, char **));
+int cplot           PROTO((int, char **));
+int create          PROTO((int, char **));
+int csystem         PROTO((int, char **));
+int ctimes          PROTO((int, char **));
+int cursor          PROTO((int, char **));
+int czplot          PROTO((int, char **));
+int datafile        PROTO((int, char **));
+int date            PROTO((int, char **));
+int ddmagextract    PROTO((int, char **));
+int ddmags          PROTO((int, char **));
+int delete          PROTO((int, char **));
+int device          PROTO((int, char **));
+int dmagaves        PROTO((int, char **));
+int dmagextract     PROTO((int, char **));
+int dmagmeas        PROTO((int, char **));
+int dmags           PROTO((int, char **));
+int dmt             PROTO((int, char **));
+int dumpmags        PROTO((int, char **));
+int elixir          PROTO((int, char **));
+int extract         PROTO((int, char **));
+int file            PROTO((int, char **));
+int fit             PROTO((int, char **));
+int fit2d           PROTO((int, char **));
+int gaussjordan     PROTO((int, char **));
+int gcat            PROTO((int, char **));
+int gimages         PROTO((int, char **));
+int grid            PROTO((int, char **));
+int gstar           PROTO((int, char **));
+int gtypes          PROTO((int, char **));
+int histogram       PROTO((int, char **));
+int images          PROTO((int, char **));
+int imbox           PROTO((int, char **));
+int imdata          PROTO((int, char **));
+int imdense         PROTO((int, char **)); 
+int imextract       PROTO((int, char **));
+int imlist          PROTO((int, char **));
+int imphot          PROTO((int, char **));
+int imrough         PROTO((int, char **));
+int imsearch        PROTO((int, char **));
+int imstats         PROTO((int, char **));
+int interpolate     PROTO((int, char **));
+int jpeg            PROTO((int, char **));
+int labels          PROTO((int, char **));
+int lcat            PROTO((int, char **));
+int lcurve          PROTO((int, char **));
+int limits          PROTO((int, char **));
+int list_buffers    PROTO((int, char **));
+int list_vectors    PROTO((int, char **));
+int mcreate         PROTO((int, char **));
+int mextract        PROTO((int, char **));
+int mget            PROTO((int, char **));
+int mset            PROTO((int, char **));
+int pcat            PROTO((int, char **));
+int photcodes       PROTO((int, char **));
+int photresid       PROTO((int, char **));
+int plot            PROTO((int, char **));
+int pmeasure        PROTO((int, char **));
+int precess         PROTO((int, char **));
+int print           PROTO((int, char **));
+int procks          PROTO((int, char **));
+int ps              PROTO((int, char **));
+int rd              PROTO((int, char **));
+int read_vectors    PROTO((int, char **));
+int region          PROTO((int, char **));
+int resid           PROTO((int, char **));
+int resize          PROTO((int, char **));
+int section         PROTO((int, char **));
+int set             PROTO((int, char **));
+int simage          PROTO((int, char **));
+int sort_vectors    PROTO((int, char **));
+int sprintf_opihi   PROTO((int, char **));
+int stats           PROTO((int, char **));
+int style           PROTO((int, char **));
+int subpix          PROTO((int, char **));
+int subraster       PROTO((int, char **));
+int subset          PROTO((int, char **));
+int textline        PROTO((int, char **));
+int tv              PROTO((int, char **));
+int uniq            PROTO((int, char **));
+int vectobuf        PROTO((int, char **));
+int vstat           PROTO((int, char **));
+int wd              PROTO((int, char **));
+int write_vectors   PROTO((int, char **));
+int zap             PROTO((int, char **));
+int zeropts         PROTO((int, char **));
+int zplot           PROTO((int, char **));
+
+static Command user[] = {  
+  {"abszero", 	   abszero,       "find filter zeropts"},
+  {"applyfit",     applyfit,      "apply fit to new vector"},
+  {"applyfit2d",   applyfit2d,    "apply 2-d fit to new vector"},
+  {"badimages",    badimages,     "look for images with anomalous astrometry"},
+  {"badimages",    badimages,     "look for images with anomalous astrometry"},
+  {"box",     	   box,           "draw a box on the plot"},
+  {"calextract",   calextract,    "extract dmags"},
+  {"calextract",   calextract,    "extract dmags"},
+  {"calmextract",  calmextract,   "extract dmags"},
+  {"cals",    	   cals,          "plot calibration data"},
+  {"catalog", 	   catlog,        "plot catalog stars"},
+  {"catalog", 	   catlog,        "plot catalog stars"},
+  {"ccd",     	   ccd,           "plot color-color diagram"},
+  {"ccd",     	   ccd,           "plot color-color diagram"},
+  {"ccdextract",   ccdextract,    "extract star coords from color-color diagram"},
+  {"center",       center,        "center image on coords"},
+  {"center",       center,        "center image on coords"},
+  {"cgrid",   	   cgrid,         "plot sky coordinate grid"},
+  {"cgrid",   	   cgrid,         "plot sky coordinate grid"},
+  {"clear",   	   clear,         "erase plot"},
+  {"cmatch",  	   cmatch,        "match two catalogs"},
+  {"cmatch",  	   cmatch,        "match two catalogs"},
+  {"cmd",     	   cmd,           "plot cmd of stars in current region"},
+  {"cmd",     	   cmd,           "plot cmd of stars in current region"},
+  {"cmdextract",   cmdextract,    "extract stars based on cmd regions"},
+  {"cmpread",      cmpread,       "read data from cmp format files"},
+  {"cmpread",      cmpread,       "read data from cmp format files"},
+  {"concat",  	   concat,        "reduce vector dimension"},
+  {"contour", 	   contour,       "create contour from image"},
+  {"cplot",   	   cplot,         "plot vectors in sky coordinates"},
+  {"cplot",   	   cplot,         "plot vectors in sky coordinates"},
+  {"create",  	   create,        "create a new vector"},
+  {"csystem", 	   csystem,       "convert between coordinate systems"},
+  {"csystem", 	   csystem,       "convert between coordinate systems"},
+  {"ctimes",  	   ctimes,        "convert between time formats"},
+  {"ctimes",  	   ctimes,        "convert between time formats"},
+  {"cursor",  	   cursor,        "get coords from cursor"},
+  {"czplot",  	   czplot,        "plot scaled vectors in sky coordinates"},
+  {"czplot",  	   czplot,        "plot scaled vectors in sky coordinates"},
+  {"datafile",     datafile,      "define file to read vectors"},
+  {"date",    	   date,          "get current date"},
+  {"ddmagextr",    ddmagextract,  "plot magnitude differences"},
+  {"ddmags",       ddmags,        "plot magnitude differences"},
+  {"ddmags",       ddmags,        "plot magnitude differences"},
+  {"delete",  	   delete,        "delete vectors or matrices"},
+  {"device",  	   device,        "set / get current graphics device"},
+  {"dmagaves",     dmagaves,      "plot differential magnitudes between filters"},
+  {"dmagextract",  dmagextract,   "extract stars based on differential magnitudes between filters"},
+  {"dmagmeas",     dmagmeas,      "plot differential magnitudes between filters"},
+  {"dmags",   	   dmags,         "plot differential magnitudes between filters"},
+  {"dmags",   	   dmags,         "plot differential magnitudes between filters"},
+  {"dmt",          dmt,           "plot mag scatter"},
+  {"dmt",          dmt,           "plot mag scatter"},
+  {"dumpmags",     dumpmags,      "custom dB dumping thingy"},
+  {"dumpmags",     dumpmags,      "custom dB dumping thingy"},
+  {"elixir",       elixir,        "get status info from elixir"},
+  {"elixir",       elixir,        "get status info from elixir"},
+  {"extract", 	   extract,       "extract vectors from catalogs"},
+  {"file",    	   file,          "test for a file"},
+  {"fit",     	   fit,           "fit polynomial to vector pair"},
+  {"fit2d",        fit2d,         "fit 2-d polynomial to vector triplet"},
+  {"gaussj",  	   gaussjordan,   "solve Ax = B (N-D)"},
+  {"gcat",         gcat,          "get catalog at location"},
+  {"gcat",         gcat,          "get catalog at location"},
+  {"gimages",      gimages,       "get images at location"},
+  {"gimages",      gimages,       "get images at location"},
+  {"grid",    	   grid,          "plot cartesian grid"},
+  {"gstar",   	   gstar,         "get star statistics"},
+  {"gstar",   	   gstar,         "get star statistics"},
+  {"gtypes",       gtypes,        "get type fractions"},
+  {"gtypes",       gtypes,        "get type fractions"},
+  {"histogram",    histogram,     "generate histogram from vector"},
+  {"images",  	   images,        "plot image boxes"},
+  {"images",  	   images,        "plot image boxes"},
+  {"imbox",   	   imbox,         "plot expected image box"},
+  {"imbox",   	   imbox,         "plot expected image box"},
+  {"imdata",  	   imdata,        "extract data for specific images"},
+  {"imdata",  	   imdata,        "extract data for specific images"},
+  {"imdense", 	   imdense,       "image density plot"},
+  {"imdense", 	   imdense,       "image density plot"},
+  {"imextract",    imextract,     "extract vectors from catalogs"},
+  {"imextract",    imextract,     "extract vectors from catalogs"},
+  {"imlist",  	   imlist,        "list image info"},
+  {"imlist",  	   imlist,        "list image info"},
+  {"imphot",  	   imphot,        "image photometry info"},
+  {"imphot",  	   imphot,        "image photometry info"},
+  {"imrough",      imrough,       "get info from imruf database"},
+  {"imrough",      imrough,       "get info from imruf database"},
+  {"imsearch",     imsearch,      "get info from imreg database"},
+  {"imsearch",     imsearch,      "get info from imreg database"},
+  {"imstats", 	   imstats,       "plot image statistics"},
+  {"imstats", 	   imstats,       "plot image statistics"},
+  {"interpolate",  interpolate,   "interpolate between vector pairs"},
+  {"jpeg",         jpeg,          "write text line on graph"},
+  {"labels",  	   labels,        "define labels for plot"},
+  {"lcat",    	   lcat,          "list catalogs in region"},
+  {"lcat",    	   lcat,          "list catalogs in region"},
+  {"lcurve",  	   lcurve,        "plot lightcurve for a star"},
+  {"lcurve",  	   lcurve,        "plot lightcurve for a star"},
+  {"limits",  	   limits,        "define plot limits"},
+  {"buffers",      list_buffers,  "list the currently allocated buffers"},
+  {"vectors", 	   list_vectors,  "list vectors"},
+  {"local",  	   local,         "define local variables"},
+  {"mcreate", 	   mcreate,       "create a matrix"},
+  {"mextract",	   mextract,      "extract vectors from catalogs"},
+  {"mextract",	   mextract,      "extract vectors from catalogs"},
+  {"mget",    	   mget,          "extract a vector from a matrix"},
+  {"mset",    	   mset,          "insert a vector in a matrix"},
+  {"pcat",    	   pcat,          "plot catalog boundaries"},
+  {"pcat",    	   pcat,          "plot catalog boundaries"},
+  {"photcodes",    photcodes,     "list photometry codes"},
+  {"photcodes",    photcodes,     "list photometry codes"},
+  {"photresid",    photresid,     "plot photometry residuals"},
+  {"plot",    	   plot,          "plot a pair of vectors"},
+  {"pmeasure",	   pmeasure,      "plot individual measurements"},
+  {"pmeasure",	   pmeasure,      "plot individual measurements"},
+  {"precess", 	   precess,       "precess coordinates"},
+  {"precess", 	   precess,       "precess coordinates"},
+  {"print",   	   print,         "write vectors to file"},
+  {"print",   	   print,         "write vectors to file"},
+  {"procks",  	   procks,        "plot rocks"},
+  {"procks",  	   procks,        "plot rocks"},
+  {"ps",      	   ps,            "define labels for plot"},
+  {"rd",           rd,            "load fits image"},
+  {"read",         read_vectors,  "read vectors from datafile"},
+  {"region",  	   region,        "define sky region for plot"},
+  {"region",  	   region,        "define sky region for plot"},
+  {"resid",   	   resid,         "plot residuals"},
+  {"resize",  	   resize,        "set graphics/image window size"},
+  {"section", 	   section,       "define section of graph"},
+  {"set",     	   set,           "vector math"},
+  {"simage",  	   simage,        "plot stars in an image"},
+  {"simage",  	   simage,        "plot stars in an image"},
+  {"sort",    	   sort_vectors,  "sort list of vectors"},
+  {"sprintf", 	   sprintf_opihi, "formated print to variable"},
+  {"stats",   	   stats,         "give statistics on a portion of a buffer"},
+  {"style",   	   style,         "set the style for graph plots"},
+  {"subpix",  	   subpix,        "get subpixel positions"},
+  {"subpix",  	   subpix,        "get subpixel positions"},
+  {"subraster",    subraster,     "subraster of fits image"},
+  {"subset",  	   subset,        "expand vector dimension"},
+  {"textline",     textline,      "write text line on graph"},
+  {"tv",      	   tv,            "display an image on the Kii window"},
+  {"uniq",    	   uniq,          "create a uniq vector subset from a vector"},
+  {"vectobuf",     vectobuf,      "convert vector triplet to buffer"},
+  {"vstat",        vstat,         "get info from imreg database"},
+  {"wd",      	   wd,            "write an image to a file"},
+  {"write",   	   write_vectors, "write vectors to datafile"},
+  {"zap",     	   zap,           "delete pixels"},
+  {"zeropts", 	   zeropts,       "show filter zeropts"},
+  {"zplot",   	   zplot,         "plot x y with size scaled by z"},
+}; 
Index: /tags/start/Ohana/src/opihi/lib.data/Makefile
===================================================================
--- /tags/start/Ohana/src/opihi/lib.data/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.data/Makefile	(revision 12606)
@@ -0,0 +1,93 @@
+include ../../../Configure
+
+HOME    =       $(ROOT)/src/opihi.v2
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+SDIR    =       $(HOME)/lib.data
+#
+DESTBIN =       $(LBIN)
+DESTLIB =       $(LLIB)
+DESTINC =       $(LINC)
+DESTMAN =       $(LMAN)
+HELP    =       $(HOME)/help
+#  
+INCS    =       -I$(INC) -I$(LINC) -I$(XINC)
+LFLAGS  =       -L$(LLIB) -L$(LIB)
+LIBS    =       -lFITS -lsocket -lnsl -lreadline -ltermcap -lohana -lm
+CFLAGS  =       $(INCS)
+CCFLAGS =       $(LIBS) 
+
+# general numerical functions (libdata) #####################
+libdata = \
+$(SDIR)/convert.$(ARCH).o               \
+$(SDIR)/sort.$(ARCH).o                  \
+$(SDIR)/fft.$(ARCH).o			\
+$(SDIR)/gaussj.$(ARCH).o		\
+$(SDIR)/svdcmp.$(ARCH).o		\
+$(SDIR)/spline.$(ARCH).o		\
+$(SDIR)/mrqmin.$(ARCH).o		\
+$(SDIR)/mrq2dmin.$(ARCH).o		\
+$(SDIR)/precess.$(ARCH).o		\
+$(SDIR)/starfuncs.$(ARCH).o		\
+$(SDIR)/powell.$(ARCH).o		\
+$(SDIR)/gaussian.$(ARCH).o		\
+$(SDIR)/graphtools.$(ARCH).o            \
+$(SDIR)/open_graph.$(ARCH).o            \
+$(SDIR)/open_image.$(ARCH).o            \
+$(SDIR)/PlotVectors.$(ARCH).o
+
+libdata:    $(DESTLIB)/libdata.a 
+
+$(LIB)/libdata.$(ARCH).a:   	$(libdata)
+
+# utilities #################################################
+$(BIN)/%.$(ARCH):
+	@if [ ! -d $(BIN) ]; then mkdir -p $(BIN); fi
+	$(CC) $^ -o $@ $(LFLAGS) $(LIBS)
+	@echo "compiled $*"
+	@echo ""
+
+$(DESTBIN)/%: $(BIN)/%.$(ARCH) 
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	rm -f $(DESTBIN)/$*
+	cp $(BIN)/$*.$(ARCH) $(DESTBIN)/$*
+	@echo "installed $*"
+	@echo ""
+
+$(LIB)/%.$(ARCH).a:
+	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
+	rm -f $@
+	ar rcv $@ $^ 
+	ranlib $@
+	@echo "compiled library $*"
+	@echo ""
+
+$(DESTLIB)/%.a: $(LIB)/%.$(ARCH).a
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	@echo ""
+	rm -f $@
+	cp $^ $@
+
+lib%.clean:
+	rm -f $(LIB)/lib$*.$(ARCH).a
+	rm -f $($*)
+	@echo ""
+
+%.clean:
+	rm -f $(BIN)/$*.$(ARCH)
+	@echo ""
+
+%.$(ARCH).o : %.c
+	$(CC) $(CFLAGS) -c $*.c -o $@
+
+clean:
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f $(LIB)/*.$(ARCH).a
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+dist: clean
+	rm -f $(BIN)/*
+	rm -f $(LIB)/*
Index: /tags/start/Ohana/src/opihi/lib.data/PlotVectors.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.data/PlotVectors.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.data/PlotVectors.c	(revision 12606)
@@ -0,0 +1,42 @@
+# include "display.h"
+
+static int Xgraph;
+
+int PrepPlotting (int Npts, Graphdata *graphmode) {
+
+  char buffer[128], buffer2[128];
+
+  if (!GetGraph (NULL, &Xgraph, NULL)) return (FALSE);
+  
+  /* tell kapa to look for the incoming image */
+  write (Xgraph, "PLOT", 4); 
+
+  /* send Xgraph the plot details */
+  sprintf (buffer, "%8d %8d %d %d %d %d %d %f %f ", 
+	   Npts, graphmode[0].style, 
+	   graphmode[0].ptype, graphmode[0].ltype, 
+	   graphmode[0].etype, graphmode[0].ebar, graphmode[0].color, 
+	   graphmode[0].lweight, graphmode[0].size);
+  sprintf (buffer2, "NBYTES: %6d ", strlen (buffer));
+  write (Xgraph, buffer2, 16);
+  write (Xgraph, buffer, strlen (buffer));
+  
+  sprintf (buffer, "%f %f %f %f ", 
+	   graphmode[0].xmin, graphmode[0].xmax, 
+	   graphmode[0].ymin, graphmode[0].ymax);
+  sprintf (buffer2, "NBYTES: %6d ", strlen (buffer));
+  write (Xgraph, buffer2, 16);
+  write (Xgraph, buffer, strlen (buffer));
+  return (TRUE);
+}
+
+int PlotVector (int Npts, float *values) {
+
+  int Nbytes;
+
+  Nbytes = Npts * sizeof (float);
+  write (Xgraph, values, Nbytes);
+  return (TRUE);
+}
+
+/* we don't use GetGraph in PlotVector because it flushes the connection */
Index: /tags/start/Ohana/src/opihi/lib.data/convert.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.data/convert.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.data/convert.c	(revision 12606)
@@ -0,0 +1,556 @@
+# include "convert.h"
+  
+int hh_hms (double hh, int *hr, int *mn, double *sc) {
+
+  int flag;
+
+  flag = SIGN(hh);
+  hh *= flag;
+  hh = 24.0*(hh/24.0 - (int)(hh/24.0));
+  *sc = 60.0*(60.0*hh - (int)(60.0*hh));
+  *mn = 60.0*(hh - (int)hh);
+  *hr = (int) hh;
+  *hr *= flag;
+  return (TRUE);
+}
+ 
+int dd_dms (double dd, int *dg, int *mn, double *sc) {
+
+  int flag;
+
+  flag = SIGN(dd);
+  dd = fabs (dd);
+  *dg = (int) dd;
+  *mn = (int) 60*(dd - *dg);
+  *sc = 3600.0*(dd - *dg - *mn/60.0);
+  if (*sc > 59.99) {
+    *sc = 0;
+    *mn += 1.0;
+  }
+  *dg *= flag;
+  return (TRUE);
+}
+ 
+int hms_format (char *line, double value) {
+
+  int hr, mn;
+  double sc;
+
+  hh_hms (value, &hr, &mn, &sc);
+  hr = (int) value;
+  if (isnan (value))
+    sprintf (line, "xx:xx:xx.xx");
+  else {
+    if (value < 0) {
+      sprintf (line, "-%02d:%02d:%05.2f", abs(hr), mn, sc);
+    } else {
+      sprintf (line, "%02d:%02d:%05.2f", hr, mn, sc);
+    }
+  }      
+  return (TRUE);
+}
+
+int dms_format (char *line, double value) {
+
+  int dg, mn;
+  double sc;
+
+  dd_dms (value, &dg, &mn, &sc);
+  if (value < 0) {
+    sprintf (line, "-%02d:%02d:%05.2f", abs(dg), mn, sc);
+  } else {
+    sprintf (line, "%02d:%02d:%05.2f", dg, mn, sc);
+  }
+  return (TRUE);
+}
+
+/***** extract RA - RA, DEC - DEC from HST GSC entry *****/
+int hstgsc_hms_to_deg (double *h0, double *h1, double *d0, double *d1, char *string) {
+  
+  int flag_d0, flag_d1, flag_h0, flag_h1;
+  double tmp;
+  
+  *d0 = *h0 = *d1 = *h1 = 0;
+
+  flag_h0 = dparse (h0, 1, string);
+  flag_h1 = dparse (h1, 4, string);
+  flag_d0 = dparse (d0, 7, string);
+  flag_d1 = dparse (d1, 9, string);
+  *h0 *= flag_h0;
+  *h1 *= flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  dparse (&tmp, 2, string);
+  *h0 += tmp/60.0;
+  dparse (&tmp, 3, string);
+  *h0 += tmp/3600.0;
+  
+  dparse (&tmp, 5, string);
+  *h1 += tmp/60.0;
+  dparse (&tmp, 6, string);
+  *h1 += tmp/3600.0;
+  
+  dparse (&tmp, 8, string);
+  *d0 += tmp/60.0;
+
+  dparse (&tmp, 10, string);
+  *d1 += tmp/60.0;
+
+  *h0 *= 15*flag_h0;
+  *h1 *= 15*flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  return (TRUE);
+}
+
+/***** convert [-]00:00:00 to 0.0000 ****/
+int dms_to_ddd (double *Value, char *string) {
+  
+  int valid, neg, status;
+  double tmp, value;
+  char *p1, *p2, *px;
+
+  valid = FALSE; 
+  neg = FALSE;
+  stripwhite (string);
+  p1 = string;
+  px = string + strlen(string);
+
+  if (string[0] == '-') { 
+    valid = TRUE; 
+    neg = TRUE;
+    p1 = &string[1];
+  }
+  if (string[0] == '+') { 
+    valid = TRUE; 
+    neg = FALSE;
+    p1 = &string[1];
+  }
+  if (isdigit(string[0])) { 
+    valid = TRUE;
+    p1 = &string[0];
+  }
+  if (!valid) { return (FALSE); }
+
+  status = 1;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) return (FALSE); /* entry not a number: +fred */
+  value = tmp;
+  if (p2 == px) goto escape;    /* entry only number: +1.0 */ 
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:fred */
+  status = 2;
+  value += tmp / 60.0;
+  if (p2 == px) goto escape;    /* entry only number: +1:1 */
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:1:fred */
+  value += tmp / 3600.0;
+
+ escape:
+  if (neg) {
+    value *= -1;
+  }
+  *Value = value;
+
+  return (status);
+}
+
+/**********/
+int str_to_radec (double *ra, double *dec, char *str1, char *str2) {
+
+  double Ra, Dec;
+
+  *ra = *dec = 0;
+  switch (dms_to_ddd (&Ra, str1)) {
+  case 0:
+    fprintf (stderr, "syntax error in RA\n");
+    return (FALSE);
+  case 1:
+    break;
+  case 2:
+    Ra = Ra * 15;
+    break;
+  }
+  switch (dms_to_ddd (&Dec, str2)) {
+  case 0:
+    fprintf (stderr, "syntax error in DEC\n");
+    return (FALSE);
+  case 1:
+  case 2:
+    break;
+  }
+  *ra = Ra;
+  *dec = Dec;
+  return (TRUE);
+}
+
+int hh_hm (double hh, int *hr, double *mn) {
+
+  int flag;
+
+  flag = SIGN(hh);
+  hh = fabs (hh);
+
+  *mn = 60.0*(hh - (int)hh);
+  *hr = (int) hh;
+  *hr *= flag;
+  return (TRUE);
+}
+
+char *meade_deg_to_str (double deg) {
+
+  int hr;
+  double mn;
+  char *line;
+
+  ALLOCATE (line, char, 16);
+
+  hh_hm (deg, &hr, &mn);
+
+  sprintf (line, "%03d:%04.1f", abs(hr), mn);
+  return (line);
+}
+
+char *meade_ra_to_str (double deg) {
+
+  int hr;
+  double mn;
+  char *line;
+
+  ALLOCATE (line, char, 16);
+
+  hh_hm (deg/15.0, &hr, &mn);
+
+  sprintf (line, "%02d:%04.1f", abs(hr), mn);
+  return (line);
+}
+
+char *meade_dec_to_str (double deg) {
+
+  int hr;
+  double mn;
+  char *line;
+
+  ALLOCATE (line, char, 16);
+
+  hh_hm (deg, &hr, &mn);
+
+  if (deg < 0) {
+    sprintf (line, "-%02d:%04.1f", abs(hr), mn);
+  } else {
+    sprintf (line, "+%02d:%04.1f", hr, mn);
+  }      
+  return (line);
+}
+
+/**********/
+int chk_time (char *line) {
+
+  char *p1, *p2;
+  double tmp;
+  int mode;
+
+  p1 = line;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1 + strlen (p1) - 1) {
+    if (*p2 == 'j') {
+      mode = TIME_JD;
+    }
+    if (*p2 == 'J') {
+      mode = TIME_MJD;
+    }
+    if (*p2 == 'd') {
+      mode = TIME_DAYS;
+    }
+    if (*p2 == 'h') {
+      mode = TIME_HOURS;
+    }
+    if (*p2 == 'm') {
+      mode = TIME_MINUTES;
+    }
+    if (*p2 == 's') {
+      mode = TIME_SECONDS;
+    }
+  } else { 
+    mode = TIME_DATE;
+  }
+  return (mode);
+}
+
+/**********/
+int str_to_time (char *line, time_t *second) {
+  
+  char *tmpline;
+  struct tm *gmt;
+  struct timeval now;
+  double jd;
+  time_t tsec;
+
+  if (!strcasecmp (line, "NOW")) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    *second = now.tv_sec;
+    return (TRUE);
+  }
+    
+  if (!strncasecmp (line, "TODAY", 5)) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    if (line[5]) { /* line has extra data (ie, hh:mm:ss) */
+      tsec = now.tv_sec;
+      ALLOCATE (tmpline, char, 64);
+      gmt   = gmtime (&tsec);
+      sprintf (tmpline, "%04d/%02d/%02d,%s", 
+	       1900 + gmt[0].tm_year, gmt[0].tm_mon+1, gmt[0].tm_mday, &line[6]);
+      *second = date_to_sec (tmpline);
+      free (tmpline);
+      return (TRUE);
+    } else {
+      *second = 86400 * ((int)(now.tv_sec / 86400));
+      return (TRUE); 
+    }
+  }
+    
+  switch (chk_time (line)) {
+  case 0:
+    return (FALSE);
+  case TIME_JD:
+    jd = strtod (line, 0);
+    *second = jd_to_sec (jd);
+    return (TRUE);
+  case TIME_MJD:
+    jd = strtod (line, 0);
+    *second = mjd_to_sec (jd);
+    return (TRUE);
+  case TIME_DATE:
+    *second = date_to_sec (line);
+    return (TRUE);
+  case TIME_DAYS:
+    *second = strtod (line, 0) * 86400.0;
+    return (TRUE);
+  case TIME_HOURS:
+    *second = strtod (line, 0) * 3600.0;
+    return (TRUE);
+  case TIME_MINUTES:
+    *second = strtod (line, 0) * 60.0;
+    return (TRUE);
+  case TIME_SECONDS:
+    *second = strtod (line, 0);
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+
+/**********/
+int str_to_dtime (char *line, double *second) {
+  
+  switch (chk_time (line)) {
+  case 0:
+  case TIME_JD:
+  case TIME_MJD:
+  case TIME_DATE:
+    return (FALSE);
+  case TIME_DAYS:
+    *second = strtod (line, 0) * 86400.0;
+    return (TRUE);
+  case TIME_HOURS:
+    *second = strtod (line, 0) * 3600.0;
+    return (TRUE);
+  case TIME_MINUTES:
+    *second = strtod (line, 0) * 60.0;
+    return (TRUE);
+  case TIME_SECONDS:
+    *second = strtod (line, 0);
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+/**********/
+double sec_to_jd (time_t second) {
+
+  double jd;
+  
+  jd = second/86400.0 + 2440587.5;
+  return (jd);
+}
+
+/**********/
+time_t jd_to_sec (double jd) {
+
+  time_t second;
+
+  second = (jd - 2440587.5)*86400;
+  return (second);
+}
+
+/**********/
+double sec_to_mjd (time_t second) {
+
+  double mjd;
+  
+  mjd = second/86400.0 + 40587.0;
+  return (mjd);
+}
+
+/**********/
+time_t mjd_to_sec (double mjd) {
+
+  time_t second;
+
+  second = (mjd - 40587.0)*86400;
+  return (second);
+}
+
+/**********/
+char *sec_to_date (time_t second) {
+  
+  struct tm *gmt;
+  char *line;
+  
+  ALLOCATE (line, char, 64);
+  gmt   = gmtime (&second);
+  sprintf (line, "%04d/%02d/%02d,%02d:%02d:%02d", 
+	   1900 + gmt[0].tm_year, gmt[0].tm_mon+1, gmt[0].tm_mday, 
+	   gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+  return (line);
+
+}
+
+/***** date in format yyyy/mm/dd,hh:mm:ss *****/
+time_t date_to_sec (char *date) {
+  
+  time_t second;
+  double tmp, jd;
+  struct tm now;
+  char *p1, *p2, *px;
+  
+  p1 = date;
+  px = date + strlen(date);
+  bzero (&now, sizeof(now));
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_year = tmp;
+  if (now.tm_year > 1000) now.tm_year -= 1900;
+  if (now.tm_year <   50) now.tm_year += 100;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mon = tmp - 1; /* mon runs from 0 - 11 */
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mday = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  p1 = p2 + 1;
+  now.tm_hour = tmp;
+  if (p2 == px) goto escape;  
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_min = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_sec = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+ escape:
+  jd = now.tm_mday - 32075 + (int)(1461*(1900 + now.tm_year + 4800 + (int)(((now.tm_mon+1)-14)/12))/4)
+    + (int)(367*((now.tm_mon+1) - 2 - (int)(((now.tm_mon+1) - 14)/12)*12)/12)
+    - (int)(3*(int)((1900 + now.tm_year + 4900 + (int)(((now.tm_mon+1) - 14)/12))/100)/4) - 0.5;
+  
+  second = (jd - 2440587.5)*86400 + 3600.0*now.tm_hour + now.tm_min*60.0 + now.tm_sec;
+
+  return (second);
+}
+
+/* convert UNIX time to a value referenced to the TimeReference in the given unit */
+double TimeValue (time_t time, time_t TimeReference, int TimeFormat) {
+
+  double value, dt;
+
+  dt = (time > TimeReference) ? (time - TimeReference) : -1 * (double)(TimeReference - time);
+  switch (TimeFormat) {
+  case TIME_JD:
+    value = time / 86400.0 + 2440587.5;
+    break;
+  case TIME_MJD:
+    value = time / 86400.0 + 40587.0;
+    break;
+  case TIME_DAYS:
+    value = dt / 86400.0;
+    break;
+  case TIME_HOURS:
+    value = dt / 3600.0;
+    break;
+  case TIME_MINUTES:
+    value = dt / 60.0;
+    break;
+  case TIME_SECONDS:
+  default:
+    value = dt;
+    break;
+  }
+  return (value);
+}
+  
+/* convert time value referenced to the TimeReference in the given unit to UNIX time */
+time_t TimeRef (double value, time_t TimeReference, int TimeFormat) {
+
+  int dt;
+  time_t time;
+
+  switch (TimeFormat) {
+  case TIME_JD:
+    time = (value -  2440587.5) * 86400.0;
+    return (time);
+    break;
+  case TIME_MJD:
+    time = (value -  40587.0) * 86400.0;
+    return (time);
+    break;
+  case TIME_DAYS:
+    dt = value * 86400.0;
+    break;
+  case TIME_HOURS:
+    dt = value * 3600.0;
+    break;
+  case TIME_MINUTES:
+    dt = value * 60.0;
+    break;
+  case TIME_SECONDS:
+  default:
+    dt = value;
+    break;
+  }
+
+  time = TimeReference + dt;
+  return (time);
+}
+
+/* times may be in forms as:
+   20040200450s (N seconds since 1970.0)
+   2440900.232j (julian date)
+   99/02/23,03:22:18 (date string)
+   (separators may be anything except space, +, -)
+   99:02:15:12:23:30
+   99:02:15:12h23m30s
+   */
Index: /tags/start/Ohana/src/opihi/lib.data/fft.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.data/fft.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.data/fft.c	(revision 12606)
@@ -0,0 +1,270 @@
+# include "data.h"
+
+#define FSWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
+
+void fft (float *Data, int N, int isign) {
+
+  int n,mmax,m,j,istep,i;
+  double wtemp,wr,wpr,wpi,wi,theta;
+  float tempr,tempi, *data;
+
+  data = Data;
+  n = N << 1;
+  j = 0;
+
+  for (i = 0; i < n; i+=2) {
+    if (j > i) {
+      FSWAP (data[j], data[i]);
+      FSWAP (data[j+1], data[i+1]);
+    }
+    m = n >> 1;
+    while (m >= 2 && j >= m) {
+      j -= m;
+      m >>= 1;
+    }
+    j += m;
+  }
+  mmax = 2;
+  while (n > mmax) {
+    istep = 2*mmax;
+    theta = 6.28318530717959 / (isign*mmax);
+    wtemp = sin(0.5*theta);
+    wpr = -2.0*wtemp*wtemp;
+    wpi = sin(theta);
+    wr = 1.0;
+    wi = 0.0;
+    for (m = 0; m < mmax; m+=2) {
+      for (i = m; i < n; i+=istep) {
+	j = i + mmax;
+	tempr = wr*data[j] - wi*data[j+1];
+	tempi = wr*data[j+1] + wi*data[j];
+	data[j] = data[i] - tempr;
+	data[j+1] = data[i+1] - tempi;
+	data[i] += tempr;
+	data[i+1] += tempi;
+      }
+      wr = (wtemp = wr)*wpr - wi*wpi+wr;
+      wi = wi*wpr + wtemp*wpi + wi;
+    }
+    mmax = istep;
+  }
+}
+
+void fftold (float *Data, int N, int isign) {
+
+  int n,mmax,m,j,istep,i;
+  double wtemp,wr,wpr,wpi,wi,theta;
+  float tempr,tempi, *data;
+
+  data = Data - 1;
+  n = N << 1;
+  j = 1;
+
+  for (i = 1; i < n; i+=2) {
+    if (j > i) {
+      FSWAP (data[j], data[i]);
+      FSWAP (data[j+1], data[i+1]);
+    }
+    m = n >> 1;
+    while (m >= 2 && j > m) {
+      j -= m;
+      m >>= 1;
+    }
+    j += m;
+  }
+  mmax = 2;
+  while (n > mmax) {
+    istep = 2*mmax;
+    theta = 6.28318530717959 / (isign*mmax);
+    wtemp = sin(0.5*theta);
+    wpr = -2.0*wtemp*wtemp;
+    wpi = sin(theta);
+    wr = 1.0;
+    wi = 0.0;
+    for (m = 1; m < mmax; m+=2) {
+      for (i = m; i <= n; i+=istep) {
+	j = i + mmax;
+	tempr = wr*data[j] - wi*data[j+1];
+	tempi = wr*data[j+1] + wi*data[j];
+	data[j] = data[i] - tempr;
+	data[j+1] = data[i+1] - tempi;
+	data[i] += tempr;
+	data[i+1] += tempi;
+      }
+      wr = (wtemp = wr)*wpr - wi*wpi+wr;
+      wi = wi*wpr + wtemp*wpi + wi;
+    }
+    mmax = istep;
+  }
+}
+
+/* convert indices to zero reference */
+void fftN (float *data, int *nn, int ndim, int isign) {
+
+  int i1,i2,i3,i2rev,i3rev,ip1,ip2,ip3,ifp1,ifp2;
+  int ibit,idim,k1,k2,n,nprev,nrem,ntot;
+  float tempi,tempr;
+  double theta,wi,wpi,wpr,wr,wtemp;
+
+  ntot = 1;
+  for (idim = 0; idim < ndim; idim++) ntot *= nn[idim];
+
+  nprev = 1;
+  for (idim = ndim - 1; idim >= 0; idim--) {
+    n  =  nn[idim];
+    nrem = ntot / (n*nprev);
+    ip1 = nprev << 1;
+    ip2 = ip1*n;
+    ip3 = ip2*nrem;
+    i2rev = 0;
+    for (i2 = 0; i2 < ip2; i2+=ip1) {
+      if (i2 < i2rev) {
+	for (i1 = i2; i1 <= i2+ip1-2; i1+=2) {
+	  for (i3 = i1; i3 < ip3; i3+=ip2) {	
+	    i3rev = i2rev+i3-i2;
+	    FSWAP(data[i3],data[i3rev]);
+	    FSWAP(data[i3+1],data[i3rev+1]);
+	  }
+	}
+      }
+      ibit = ip2 >> 1;
+      while (ibit >= ip1 && i2rev >= ibit) {
+	i2rev -= ibit;
+	ibit >>= 1;
+      }
+      i2rev += ibit;
+    }
+    ifp1 = ip1;
+    while (ifp1 < ip2) {
+      ifp2 = ifp1 << 1;
+      theta = isign*6.28318530717959/(ifp2/ip1);
+      wtemp = sin(0.5*theta);
+      wpr = -2.0*wtemp*wtemp;
+      wpi = sin(theta);
+      wr = 1.0;
+      wi = 0.0;
+      for (i3 = 0; i3 < ifp1; i3+=ip1) {
+	for (i1 = i3; i1 <= i3+ip1-2; i1+=2) {
+	  for (i2 = i1; i2 < ip3; i2+=ifp2) {
+	    k1 = i2;
+	    k2 = k1+ifp1;
+	    tempr = wr*data[k2]-wi*data[k2+1];
+	    tempi = wr*data[k2+1]+wi*data[k2];
+	    data[k2] = data[k1]-tempr;
+	    data[k2+1] = data[k1+1]-tempi;
+	    data[k1] += tempr;
+	    data[k1+1] += tempi;
+	  }
+	}
+	wr = (wtemp = wr)*wpr-wi*wpi+wr;
+	wi = wi*wpr+wtemp*wpi+wi;
+      }
+      ifp1 = ifp2;
+    }
+    nprev *= n;
+  }
+}
+
+#undef FSWAP
+
+/* based on the PRESS routine, this fft takes an array from data[0] to data[2N-1] */
+/* this function takes Data = h(t) and replaces it in situ with H(F) or vice versa.
+   There are assumed to be 2*N input values with 
+   Data[0,2,4,...] the real and Data[1,3,5,...] the imaginary ones.
+   the output is ordered the same.  
+
+   for h(t), values are in time sequence order.
+   for H(F), values are in order F = 0, 1/N, ... 1/2 - 1/N, +/- 1/2, -1/2 + 1/N, ... -1/N 
+
+   no normalization is performed, so a signal of amplitude A sin (w_k * t) will be 
+      give an H(F) value of 0.5 * A * N, and the DC term will have H(0) = A * N.
+
+*/ 
+
+int IsBinary (int N) {
+
+  int i, nbit;
+
+  /* check if number is a binary number */
+  nbit = 0;
+  for (i = 0; i < 8*sizeof(N); i++) {
+    nbit += (N & 0x01);
+    N = (N >> 1);
+  }
+  if (nbit == 1) { 
+    return (1); 
+  } else { 
+    return (0); 
+  }
+
+}  
+
+#define FSWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
+
+void fourn (float *data, int *nn, int ndim, int isign) {
+
+  int i1,i2,i3,i2rev,i3rev,ip1,ip2,ip3,ifp1,ifp2;
+  int ibit,idim,k1,k2,n,nprev,nrem,ntot;
+  float tempi,tempr;
+  double theta,wi,wpi,wpr,wr,wtemp;
+
+  ntot = 1;
+  for (idim = 1; idim <= ndim; idim++)
+    ntot *= nn[idim];
+  nprev = 1;
+  for (idim = ndim; idim >= 1; idim--) {
+    n = nn[idim];
+    nrem = ntot/(n*nprev);
+    ip1 = nprev << 1;
+    ip2 = ip1*n;
+    ip3 = ip2*nrem;
+    i2rev = 1;
+    for (i2 = 1; i2 <= ip2; i2+=ip1) {
+      if (i2 < i2rev) {
+	for (i1 = i2; i1 <= i2+ip1-2; i1+=2) {
+	  for (i3 = i1; i3 <= ip3;i3+=ip2) {
+	    i3rev = i2rev+i3-i2;
+	    FSWAP(data[i3],data[i3rev]);
+	    FSWAP(data[i3+1],data[i3rev+1]);
+	  }
+	}
+      }
+      ibit = ip2 >> 1;
+      while (ibit >= ip1 && i2rev > ibit) {
+	i2rev -=  ibit;
+	ibit >>= 1;
+      }
+      i2rev += ibit;
+    }
+    ifp1 = ip1;
+    while (ifp1 < ip2) {
+      ifp2 = ifp1 << 1;
+      theta = isign*6.28318530717959/(ifp2/ip1);
+      wtemp = sin(0.5*theta);
+      wpr  =  -2.0*wtemp*wtemp;
+      wpi = sin(theta);
+      wr = 1.0;
+      wi = 0.0;
+      for (i3 = 1;i3<=ifp1;i3+=ip1) {
+	for (i1 = i3;i1<=i3+ip1-2;i1+=2) {
+	  for (i2 = i1;i2<=ip3;i2+=ifp2) {
+	    k1 = i2;
+	    k2 = k1+ifp1;
+	    tempr = wr*data[k2]-wi*data[k2+1];
+	    tempi = wr*data[k2+1]+wi*data[k2];
+	    data[k2] = data[k1]-tempr;
+	    data[k2+1] = data[k1+1]-tempi;
+	    data[k1] += tempr;
+	    data[k1+1] += tempi;
+	  }
+	}
+	wr = (wtemp = wr)*wpr-wi*wpi+wr;
+	wi = wi*wpr+wtemp*wpi+wi;
+      }
+      ifp1 = ifp2;
+    }
+    nprev *= n;
+  }
+}
+
+#undef FSWAP
Index: /tags/start/Ohana/src/opihi/lib.data/gaussian.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.data/gaussian.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.data/gaussian.c	(revision 12606)
@@ -0,0 +1,66 @@
+# include "data.h"
+
+static int Ngaussint;
+static double *gaussint;
+
+extern double drand48();
+
+double gaussian (double x, double mean, double sigma) {
+
+  double f;
+
+  f = exp (-0.5 * SQ(x - mean) / SQ(sigma)) / sqrt(2 * M_PI * SQ(sigma));
+
+  return (f);
+
+}
+
+/* integrate a gaussian from -5 sigma to +5 sigma */
+void gauss_init (int Nbin) {
+ 
+  int i;
+  long A, B;
+  double val, x, dx, dx1, dx2, dx3, df;
+  double mean, sigma;
+ 
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+ 
+  Ngaussint = Nbin;
+  ALLOCATE (gaussint, double, Ngaussint + 1);
+
+  val = 0;
+  dx = 1.0 / Ngaussint;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+  mean = 0.0;
+  sigma = 1.0;
+ 
+  for (i = 0, x = -7.0; (i < Ngaussint) && (x < 7.0); x += dx)  {
+    df = (3.0*gaussian(x    , mean, sigma) + 
+          9.0*gaussian(x+dx1, mean, sigma) +
+          9.0*gaussian(x+dx2, mean, sigma) + 
+          3.0*gaussian(x+dx3, mean, sigma)) * (dx1/8.0);
+    val += df;
+    if (val > (i / (double) Ngaussint)) {
+      gaussint[i] = x + dx / 2.0;
+      i++;
+    }
+  }
+}
+
+double rnd_gauss (double mean, double sigma) {
+ 
+  int i;
+  double y;
+ 
+  y = drand48();
+  i = Ngaussint*y;
+  y = gaussint[i]*sigma + mean;
+ 
+  return (y);
+ 
+}
+ 
Index: /tags/start/Ohana/src/opihi/lib.data/gaussj.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.data/gaussj.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.data/gaussj.c	(revision 12606)
@@ -0,0 +1,150 @@
+# include "data.h"
+
+int gaussj (double **a, int n, double **b, int m) {
+
+  int *indxc,*indxr,*ipiv;
+  int i, icol, irow, j, k, l, ll;
+  double big,dum,pivinv;
+  
+  ALLOCATE (indxc, int, n);
+  ALLOCATE (indxr, int, n);
+  ALLOCATE (ipiv, int, n);
+  for (j = 0; j < n; j++) 
+    ipiv[j] = 0;
+
+  for (i = 0; i < n; i++) {
+    big = 0.0;
+    for (j = 0; j < n; j++) {
+      if (ipiv[j] != 1) {
+	for (k = 0; k < n; k++) {
+	  if (ipiv[k] == 0) {
+	    if (fabs (a[j][k]) >= big) {
+	      big  = fabs (a[j][k]);
+	      irow = j;
+	      icol = k;
+	    }
+	  } 
+	  else 
+	    if (ipiv[k] > 1) {
+	      fprintf (stderr, "GAUSSJ: Singular Matrix! (1)\n");
+	      return (0);
+	    }
+	}
+      }
+    }
+    ipiv[icol]++;
+    if (irow != icol) {
+      for (l = 0; l < n; l++) 
+	SWAP (a[irow][l], a[icol][l]);
+      for (l = 0; l < m; l++) 
+	SWAP (b[irow][l], b[icol][l]);
+    }
+    indxr[i] = irow;
+    indxc[i] = icol;
+    if (a[icol][icol] == 0.0) {
+      fprintf (stderr, "GAUSSJ: Singular Matrix! (2)\n");
+      return (0);
+    }
+    pivinv = 1.0 / a[icol][icol];
+    a[icol][icol] = 1.0;
+    for (l = 0; l < n; l++) 
+      a[icol][l] *= pivinv;
+    for (l = 0; l < m; l++) 
+      b[icol][l] *= pivinv;
+    for (ll = 0; ll < n; ll++) {
+      if (ll != icol) {
+	dum = a[ll][icol];
+	a[ll][icol] = 0.0;
+	for (l = 0; l < n; l++) 
+	  a[ll][l] -= a[icol][l]*dum;
+	for (l = 0; l < m; l++) 
+	  b[ll][l] -= b[icol][l]*dum;
+      }
+    }
+  }
+
+  for (l = n - 1; l >= 0; l--) {
+    if (indxr[l] != indxc[l])
+      for (k = 0; k < n; k++)
+	SWAP (a[k][indxr[l]], a[k][indxc[l]]);
+  }
+  free (ipiv);
+  free (indxr);
+  free (indxc);
+  return (1);
+}
+
+
+int fgaussj (float **a, int n, float **b, int m) {
+
+  int *indxc,*indxr,*ipiv;
+  int i, icol, irow, j, k, l, ll;
+  float big,dum,pivinv;
+  
+  ALLOCATE (indxc, int, n);
+  ALLOCATE (indxr, int, n);
+  ALLOCATE (ipiv, int, n);
+  for (j = 0; j < n; j++) 
+    ipiv[j] = 0;
+
+  for (i = 0; i < n; i++) {
+    big = 0.0;
+    for (j = 0; j < n; j++) {
+      if (ipiv[j] != 1) {
+	for (k = 0; k < n; k++) {
+	  if (ipiv[k] == 0) {
+	    if (fabs (a[j][k]) >= big) {
+	      big  = fabs (a[j][k]);
+	      irow = j;
+	      icol = k;
+	    }
+	  } 
+	  else 
+	    if (ipiv[k] > 1) {
+	      fprintf (stderr, "GAUSSJ: Singular Matrix! (1)\n");
+	      return (0);
+	    }
+	}
+      }
+    }
+    ipiv[icol]++;
+    if (irow != icol) {
+      for (l = 0; l < n; l++) 
+	SWAP (a[irow][l], a[icol][l]);
+      for (l = 0; l < m; l++) 
+	SWAP (b[irow][l], b[icol][l]);
+    }
+    indxr[i] = irow;
+    indxc[i] = icol;
+    if (a[icol][icol] == 0.0) {
+      fprintf (stderr, "GAUSSJ: Singular Matrix! (2)\n");
+      return (0);
+    }
+    pivinv = 1.0 / a[icol][icol];
+    a[icol][icol] = 1.0;
+    for (l = 0; l < n; l++) 
+      a[icol][l] *= pivinv;
+    for (l = 0; l < m; l++) 
+      b[icol][l] *= pivinv;
+    for (ll = 0; ll < n; ll++) {
+      if (ll != icol) {
+	dum = a[ll][icol];
+	a[ll][icol] = 0.0;
+	for (l = 0; l < n; l++) 
+	  a[ll][l] -= a[icol][l]*dum;
+	for (l = 0; l < m; l++) 
+	  b[ll][l] -= b[icol][l]*dum;
+      }
+    }
+  }
+
+  for (l = n - 1; l >= 0; l--) {
+    if (indxr[l] != indxc[l])
+      for (k = 0; k < n; k++)
+	SWAP (a[k][indxr[l]], a[k][indxc[l]]);
+  }
+  free (ipiv);
+  free (indxr);
+  free (indxc);
+  return (1);
+}
Index: /tags/start/Ohana/src/opihi/lib.data/graphtools.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.data/graphtools.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.data/graphtools.c	(revision 12606)
@@ -0,0 +1,55 @@
+# include "data.h"
+
+void SetLimits (Vector *xvec, Vector *yvec, Graphdata *graphmode) {
+
+  double maxX, minX, maxY, minY, range;
+  int i;
+
+  if (xvec != NULL) {
+    maxX = minX = xvec[0].elements[0];
+    for (i = 1; i < xvec[0].Nelements; i++) {
+      if (!finite(xvec[0].elements[i])) continue;
+      maxX = MAX (maxX, xvec[0].elements[i]);
+      minX = MIN (minX, xvec[0].elements[i]);
+    }
+    range = maxX - minX;
+    if (range == 0) range = 0.001 * maxX;
+    if (range == 0) range = 0.001;
+    graphmode[0].xmin = minX - 0.05*range;
+    graphmode[0].xmax = maxX + 0.05*range;
+  }
+
+  if (yvec != NULL) {
+    maxY = minY = yvec[0].elements[0];
+    for (i = 1; i < yvec[0].Nelements; i++) {
+      if (!finite(yvec[0].elements[i])) continue;
+      maxY = MAX (maxY, yvec[0].elements[i]);
+      minY = MIN (minY, yvec[0].elements[i]);
+    }
+    range = maxY - minY;
+    if (range == 0) range = 0.0011 * maxY;
+    if (range == 0) range = 0.0011;
+    graphmode[0].ymin = minY - 0.05*range;
+    graphmode[0].ymax = maxY + 0.05*range;
+  }
+  SetGraph (graphmode[0]);
+
+  set_variable ("XMIN", graphmode[0].xmin);
+  set_variable ("XMAX", graphmode[0].xmax);
+  set_variable ("YMIN", graphmode[0].ymin);
+  set_variable ("YMAX", graphmode[0].ymax);
+}
+
+void ApplyLimits (int Xgraph, Graphdata *graphmode, int apply) { 
+
+  char buffer[128], buffer2[65];
+
+  if (!apply) return;
+
+  write (Xgraph, "SLIM", 4);
+  sprintf (buffer, "%f %f %f %f ", graphmode[0].xmin, graphmode[0].xmax, graphmode[0].ymin, graphmode[0].ymax);
+  sprintf (buffer2, "NBYTES: %6d ", strlen (buffer));
+  write (Xgraph, buffer2, 16);
+  write (Xgraph, buffer, strlen (buffer));
+}
+
Index: /tags/start/Ohana/src/opihi/lib.data/mrq2dmin.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.data/mrq2dmin.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.data/mrq2dmin.c	(revision 12606)
@@ -0,0 +1,153 @@
+# include "data.h"  /* only needed for the ALLOCATE def */
+
+/* need to pass in a function of the form:
+
+   funcs (x, t, a, Npar, dyda) 
+
+   returns f (x, t) for Npar parameters a, also df/da at x,t 
+
+   dy carries 1/sig^2 
+
+*/
+
+static float **alpha, **talpha;
+static float **beta, **tbeta;
+static float *partry, *dyda;
+static float ochisq, lambda;
+
+float mrq2dcof (float *x, float *t, float *y, float *dy, int Npts, 
+	      float *par, int Npar, float **ta, float **tb, 
+	      float (funcs)(float, float, float *, int, float *)) {
+
+  int k, j, i;
+  float ydiff, wt, chisq, value;
+
+  for (j = 0; j < Npar; j++) {
+    for (k = 0; k <= j; k++) ta[j][k] = 0.0;
+    tb[j][0] = 0.0;
+  }
+
+  chisq = 0.0;
+  for (i = 0; i < Npts; i++) {
+
+    ydiff = funcs (x[i], t[i], par, Npar, dyda) - y[i];
+    value = SQ(ydiff) * fabs(dy[i]);
+    if (value < 0.0) fprintf (stderr, "neg chi: %f %f\n", value, chisq);
+    chisq += value; 
+    
+    if (!finite (dyda[i])) { dyda[i] = 1e10; }
+    if (!finite (dy[i])) { dyda[i] = 1e10; }
+
+    for (j = 0; j < Npar; j++) {
+      wt = dyda[j] * dy[i];
+      for (k = 0; k <= j; k++) ta[j][k] += wt * dyda[k];
+      tb[j][0] += wt * ydiff;
+    }
+  }
+
+  for (j = 1; j < Npar; j++)
+    for (k = 0; k < j; k++)
+      ta[k][j] = ta[j][k];
+      
+  return (chisq);
+
+}
+
+float mrq2dmin (float *x, float *t, float *y, float *dy, int Npts, 
+	      float *par, int Npar, 
+	      float (funcs)(float, float, float *, int, float *)) {
+
+  int j, k;
+  float chisq;
+
+  /* set up test matrixes for this run */
+  for (j = 0; j < Npar; j++) {
+    for (k = 0; k < Npar; k++) talpha[j][k] = alpha[j][k];
+    talpha[j][j] = alpha[j][j] * (1.0 + lambda);
+    tbeta[j][0] = beta[j][0];
+  }
+
+  if (!fgaussj (talpha, Npar, tbeta, 1)) {
+    lambda *= 10.0;
+    return (ochisq);
+  }
+
+  /* if we keep some fixed, set partry to just them 
+     for (j = 0; j < Npar; j++) partry[j] = par[j]; */
+
+  for (j = 0; j < Npar; j++) partry[j] = par[j] - tbeta[j][0];
+
+  chisq = mrq2dcof (x, t, y, dy, Npts, partry, Npar, talpha, tbeta, funcs);
+
+  /* if good, save temp values */
+  if (chisq < ochisq) {
+    lambda *= 0.1;
+    ochisq = chisq;
+    for (j = 0; j < Npar; j++) {
+      for (k = 0; k < Npar; k++) alpha[j][k] = talpha[j][k];
+      beta[j][0] = tbeta[j][0];
+      par[j] = partry[j];
+    }
+  } else {
+    lambda *= 10.0;
+    chisq = ochisq;
+  }
+
+  return (chisq);
+
+}
+
+float mrq2dinit (float *x, float *t, float *y, float *dy, int Npts, 
+	      float *par, int Npar, 
+	      float (funcs)(float, float, float *, int, float *)) {
+
+  int i;
+
+  ALLOCATE (dyda, float, Npar);
+  ALLOCATE (partry, float, Npar);
+  ALLOCATE (alpha, float *, Npar);
+  ALLOCATE (beta, float *, Npar);
+  ALLOCATE (talpha, float *, Npar);
+  ALLOCATE (tbeta, float *, Npar);
+  for (i = 0; i < Npar; i++) {
+    ALLOCATE (alpha[i], float, Npar);
+    ALLOCATE (beta[i], float, Npar);
+    ALLOCATE (talpha[i], float, Npar);
+    ALLOCATE (tbeta[i], float, Npar);
+  }
+
+  
+  lambda = 0.001;
+  
+  ochisq = mrq2dcof (x, t, y, dy, Npts, par, Npar, alpha, beta, funcs);
+
+  return (ochisq);
+
+}
+
+/* don't invoke this in the middle of a run, only near the end */ 
+float **mrq2dcovar (int Npar) {
+
+  fgaussj (alpha, Npar, beta, 1);
+  return (alpha);
+
+} 
+
+void mrq2dfree (int Npar) {
+
+  int i;
+
+  for (i = 0; i < Npar; i++) {
+    free (alpha[i]);
+    free (talpha[i]);
+    free (beta[i]);
+    free (tbeta[i]);
+  }
+  free (alpha);
+  free (talpha);
+  free (beta);
+  free (tbeta);
+  free (partry);
+  free (dyda);
+
+}
Index: /tags/start/Ohana/src/opihi/lib.data/mrqmin.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.data/mrqmin.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.data/mrqmin.c	(revision 12606)
@@ -0,0 +1,148 @@
+# include "data.h"  /* only needed for the ALLOCATE def */
+
+/* need to pass in a function of the form:
+
+   funcs (x, a, Npar, dyda) 
+
+   returns f (x) for Npar parameters a, also df/da at x 
+
+   dy carries 1/sig^2 
+
+*/
+
+
+static float **alpha, **talpha;
+static float **beta, **tbeta;
+static float *partry, *dyda;
+static float ochisq, lambda;
+
+float mrqcof (float *x, float *y, float *dy, int Npts, 
+	      float *par, int Npar, float **ta, float **tb, 
+	      float (funcs)(float, float *, int, float *)) {
+
+  int k, j, i;
+  float ydiff, wt, chisq;
+
+  for (j = 0; j < Npar; j++) {
+    for (k = 0; k <= j; k++) ta[j][k] = 0.0;
+    tb[j][0] = 0.0;
+  }
+
+  chisq = 0.0;
+  for (i = 0; i < Npts; i++) {
+
+    ydiff = funcs (x[i], par, Npar, dyda) - y[i];
+    chisq += SQ(ydiff) * dy[i];
+
+    for (j = 0; j < Npar; j++) {
+      wt = dyda[j] * dy[i];
+      for (k = 0; k <= j; k++) ta[j][k] += wt * dyda[k];
+      tb[j][0] += wt * ydiff;
+    }
+  }
+
+  for (j = 1; j < Npar; j++)
+    for (k = 0; k < j; k++) 
+      ta[k][j] = ta[j][k];
+
+  return (chisq);
+
+}
+
+float mrqmin (float *x, float *y, float *dy, int Npts, 
+	      float *par, int Npar, 
+	      float (funcs)(float, float *, int, float *)) {
+
+  int j, k;
+  float chisq;
+
+  /* set up test matrixes for this run */
+  for (j = 0; j < Npar; j++) {
+    for (k = 0; k < Npar; k++) talpha[j][k] = alpha[j][k];
+    talpha[j][j] = alpha[j][j] * (1.0 + lambda);
+    tbeta[j][0] = beta[j][0];
+  }
+
+  fgaussj (talpha, Npar, tbeta, 1);
+
+  /* if we keep some fixed, set partry to just them 
+     for (j = 0; j < Npar; j++) partry[j] = par[j]; */
+
+  for (j = 0; j < Npar; j++) partry[j] = par[j] - tbeta[j][0];
+
+  chisq = mrqcof (x, y, dy, Npts, partry, Npar, talpha, tbeta, funcs);
+
+  /* if good, save temp values */
+  if (chisq < ochisq) {
+    lambda *= 0.1;
+    ochisq = chisq;
+    for (j = 0; j < Npar; j++) {
+      for (k = 0; k < Npar; k++) alpha[j][k] = talpha[j][k];
+      beta[j][0] = tbeta[j][0];
+      par[j] = partry[j];
+    }
+  } else {
+    lambda *= 10.0;
+    chisq = ochisq;
+  }
+
+  return (chisq);
+
+}
+
+int mrqinit (float *x, float *y, float *dy, int Npts, 
+	      float *par, int Npar, 
+	      float (funcs)(float, float *, int, float *)) {
+
+  int i;
+
+  ALLOCATE (dyda, float, Npar);
+  ALLOCATE (partry, float, Npar);
+  ALLOCATE (alpha, float *, Npar);
+  ALLOCATE (beta, float *, Npar);
+  ALLOCATE (talpha, float *, Npar);
+  ALLOCATE (tbeta, float *, Npar);
+  for (i = 0; i < Npar; i++) {
+    ALLOCATE (alpha[i], float, Npar);
+    ALLOCATE (beta[i], float, Npar);
+    ALLOCATE (talpha[i], float, Npar);
+    ALLOCATE (tbeta[i], float, Npar);
+  }
+
+  
+  lambda = 0.001;
+  
+  ochisq = mrqcof (x, y, dy, Npts, par, Npar, alpha, beta, funcs);
+
+  return (TRUE);
+}
+
+
+
+/* don't invoke this in the middle of a run, only near the end */ 
+float **mrqcovar (int Npar) {
+
+  fgaussj (alpha, Npar, beta, 1);
+  return (alpha);
+
+} 
+
+
+void mrqfree (int Npar) {
+
+  int i;
+
+  for (i = 0; i < Npar; i++) {
+    free (alpha[i]);
+    free (talpha[i]);
+    free (beta[i]);
+    free (tbeta[i]);
+  }
+  free (alpha);
+  free (talpha);
+  free (beta);
+  free (tbeta);
+  free (partry);
+  free (dyda);
+
+}
Index: /tags/start/Ohana/src/opihi/lib.data/open_graph.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.data/open_graph.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.data/open_graph.c	(revision 12606)
@@ -0,0 +1,254 @@
+# include "display.h"
+# define DEBUG 0
+
+/** this list must match the one in kapa/include/structures.h, and equiv */
+# define NGRAPHCOLORS 23
+static char GRAPHCOLORS[NGRAPHCOLORS][2][15] = {
+  {"black",    "0.00 0.00 0.00"},
+  {"white",    "1.00 1.00 1.00"},
+  {"red",      "1.00 0.00 0.00"}, 
+  {"pink",     "1.00 0.75 0.80"}, 
+  {"orange",   "1.00 0.65 0.00"}, 
+  {"yellow",   "1.00 1.00 0.00"}, 
+  {"wheat",    "0.96 0.87 0.70"}, 
+  {"gold",     "1.00 0.84 0.00"}, 
+  {"green",    "0.00 1.00 0.00"}, 
+  {"darkgreen","0.00 0.40 0.00"}, 
+  {"blue",     "0.00 0.00 1.00"}, 
+  {"skyblue",  "0.53 0.81 0.92"}, 
+  {"indigo",   "0.56 0.16 0.87"}, 
+  {"violet",   "1.00 0.00 0.00"},
+  {"grey10",   "0.10 0.10 0.10"},
+  {"grey20",   "0.20 0.20 0.20"},
+  {"grey30",   "0.30 0.30 0.30"},
+  {"grey40",   "0.40 0.40 0.40"},
+  {"grey50",   "0.50 0.50 0.50"},
+  {"grey60",   "0.60 0.60 0.60"},
+  {"grey70",   "0.70 0.70 0.70"},
+  {"grey80",   "0.80 0.80 0.80"},
+  {"grey90",   "0.90 0.90 0.90"}};
+
+  /* we have space for several kapa windows */
+# define NXGRAPH 5
+
+static int       IsImage = FALSE;
+static int       Active;
+static int       Xgraph[NXGRAPH];  
+static Graphdata graphdata[NXGRAPH];
+
+int GetCurrentDevice () {
+  return (IsImage);
+}
+
+void SetImageDevice (int state) {
+  IsImage = state;
+}
+
+void QuitGraph () {
+
+  int i;
+  
+  for (i = 0; i < NXGRAPH; i++) {
+    if (Xgraph[i] > 0) {
+      write (Xgraph[i], "QUIT", 4);
+    }
+  }
+}
+
+void InitGraph () {
+
+  int i;
+
+  Active = 0;
+  for (i = 0; i < NXGRAPH; i++) {
+    Xgraph[i] = -1;
+
+    graphdata[i].xmin = graphdata[i].ymin = 0.0;
+    graphdata[i].xmax = graphdata[i].ymax = 1.0;
+    graphdata[i].style = graphdata[i].ptype = 0;
+    graphdata[i].ltype = graphdata[i].color = 0;
+    graphdata[i].etype = graphdata[i].ebar = 0;
+    graphdata[i].lweight = graphdata[i].size = 1.0;
+    
+    graphdata[i].coords.pc1_1 = graphdata[i].coords.pc2_2 = 1.0;
+    graphdata[i].coords.pc1_2 = graphdata[i].coords.pc2_1 = 0.0;
+    strcpy (graphdata[i].coords.ctype, "RA---LIN");
+    graphdata[i].coords.crval1 = 0.0;
+    graphdata[i].coords.crval2 = 0.0;
+    graphdata[i].coords.crpix1 = 0.0;
+    graphdata[i].coords.crpix2 = 0.0;
+    graphdata[i].coords.cdelt1 = graphdata[i].coords.cdelt2 = 1.0;
+    graphdata[i].flipeast = TRUE;
+    graphdata[i].flipnorth = FALSE;
+  }
+}
+
+/* set SIGPIPE to this function to close cleanly */ 
+void XGraphDead (int input) {
+  signal (SIGPIPE, XGraphDead);
+  fprintf (stderr, "kapa is dead, must restart\n");
+  Xgraph[Active] = -1;
+}
+
+/** start socketed connection */
+int open_graph (int N) {
+
+  int InitSocket, status, addreslen, Ntry, fd;
+  char temp[128], socket_name[64], *kapa_exec;
+  struct sockaddr_un Address;
+  
+  kapa_exec = get_variable ("KAPA");
+  if (kapa_exec == (char *) NULL) {
+    fprintf (stderr, "variable KAPA not found\n");
+    return (FALSE);
+  }
+
+  sprintf (socket_name, "/tmp/Kapa.XXXXXX");
+  if ((fd = mkstemp (socket_name)) == -1) {
+    fprintf (stderr, "error starting kapa\n");
+    return (FALSE);
+  }
+  close (fd);
+  unlink (socket_name);
+
+  strcpy (Address.sun_path, socket_name); 
+  Address.sun_family = AF_UNIX; 
+  InitSocket = socket (AF_UNIX, SOCK_STREAM, 0); 
+  status = bind (InitSocket, (struct sockaddr *) &Address, sizeof (Address));
+  status = listen (InitSocket, 1);
+  
+  sprintf (temp, "%s %s &", kapa_exec, socket_name);
+  free (kapa_exec);
+
+# if DEBUG
+  fprintf (stderr, "start kapa, press return: %s\n", temp);
+  fscanf (stdin, "%d", &i);
+# else  
+  system (temp);
+# endif
+  
+  addreslen =  sizeof (Address);
+  fcntl (InitSocket, F_SETFL, O_NONBLOCK); 
+
+# define NTRY 200
+  Ntry = 0;
+  while (Ntry < NTRY) {
+    Xgraph[N] = accept (InitSocket, (struct sockaddr *)&Address, &addreslen);
+    if (Xgraph[N] == -1) {
+      if (errno == EAGAIN) {
+	usleep (10000);
+	Ntry ++;
+      } else { 
+	Ntry = NTRY;
+      }
+    } else {
+      Ntry = NTRY;
+    }
+  }
+  if (Xgraph[N] < 0) {
+    fprintf (stderr, "error starting kapa\n");
+    return (FALSE);
+  } else {
+    fcntl (Xgraph[N], F_SETFL, !O_NONBLOCK); 
+    return (TRUE);
+  }
+  
+}
+
+/* return pointers for current Xgraph, set if desired, test, open if needed */
+int GetGraph (Graphdata *data, int *socket, int *N) {
+
+  int i, n;
+  char buffer[70];
+
+  SetImageDevice (FALSE);
+  if (N == (int *) NULL) {
+    n = Active;
+  } else {
+    if (*N >= NXGRAPH) {
+      fprintf (stderr, "invalid Xgraph window %d\n", *N); 
+      return (FALSE);
+    }
+    if (*N < 0) {
+      *N = n = Active;
+    } else {
+      Active = n = *N;
+    }
+  }
+  
+  /* test Xgraph[0], flush junk from pipe */
+  signal (SIGPIPE, XGraphDead);
+  fcntl (Xgraph[n], F_SETFL,  O_NONBLOCK); 
+  for (i = 0; (read (Xgraph[n], buffer, 64) > 0) && (i < 20); i++);
+  fcntl (Xgraph[n], F_SETFL, !O_NONBLOCK); 
+  
+  if (Xgraph[n] < 1) {
+    if (!open_graph(n)) {
+      return (FALSE);
+    }
+  }
+
+  if (data != (Graphdata *) NULL) *data  = graphdata[n];
+  if (socket != (int *) NULL) *socket = Xgraph[n];
+
+  return (TRUE);
+
+}
+
+/* return pointers for given Xgraph, don't set or open */
+int GetGraphData (Graphdata *data, int *sock, int *N) {
+
+  int n;
+
+  if (N == (int *) NULL) {
+    n = Active;
+  } else {
+    if (*N >= NXGRAPH) {
+      fprintf (stderr, "invalid Xgraph window %d\n", *N); 
+      return (FALSE);
+    }
+    if (*N < 0) {
+      n = Active;
+    } else {
+      n = *N;
+    }
+  }
+  
+  if (data != (Graphdata *) NULL) *data  = graphdata[n];
+  if (sock != (int *) NULL) *sock = Xgraph[n];
+
+  return (TRUE);
+
+}
+
+/* assign given values to current Xgraph */
+void SetGraph (Graphdata data) {
+  graphdata[Active] = data;
+}
+
+int GetColor (char *name) {
+
+  int i;
+  
+  for (i = 0; i < NGRAPHCOLORS; i++) {
+    if (!strcmp (name, GRAPHCOLORS[i][0])) {
+      return (i);
+    }	
+  }
+  fprintf (stderr, "color may be one of:\n");
+  for (i = 0; i < NGRAPHCOLORS; i++) {
+    fprintf (stderr, "  %s\n", GRAPHCOLORS[i][0]);
+  }
+  return (-1);
+}	
+
+int SendLabel (char *string, int Xgraph, int mode) {
+
+  char buffer[64];
+
+  write (Xgraph, "LABL", 4);
+  sprintf (buffer, " %6d %6d  ", strlen (string), mode);
+  write (Xgraph, buffer, 16);
+  write (Xgraph, string, strlen (string));
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/lib.data/open_image.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.data/open_image.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.data/open_image.c	(revision 12606)
@@ -0,0 +1,168 @@
+# include "display.h"
+# define DEBUG 0
+
+/* we have space for several kii windows */
+# define NXIMAGE 5
+
+static int       Active;
+static int       Ximage[NXIMAGE];  
+static char      Ximbuffer[NXIMAGE][512];
+static double    Xzero[NXIMAGE];
+static double    Xrange[NXIMAGE];
+
+/* define a structure to carry the relevant image data, eqiv to GraphData? */
+
+void QuitImage () {
+
+  int i;
+  
+  for (i = 0; i < NXIMAGE; i++) {
+    if (Ximage[i] > 0) {
+      write (Ximage[i], "QUIT", 4);
+    }
+  }
+}
+
+
+void InitImage () {
+
+  int i;
+
+  Active = 0;
+  for (i = 0; i < NXIMAGE; i++) {
+    Ximage[i] = -1;
+    Xzero[i] = 0;
+    Xrange[i] = 1024;
+    strcpy (Ximbuffer[i], "none");
+  }
+}
+
+/* set SIGPIPE to this function to close cleanly */ 
+void XImageDead (int input) {
+  signal (SIGPIPE, XImageDead);
+  fprintf (stderr, "kii is dead, must restart\n");
+  Ximage[Active] = -1;
+}
+
+/** start socketed connection */
+int open_image (int N) {
+
+  int InitSocket, status, addreslen;
+  struct sockaddr_un Address;
+  char temp[128], socket_name[64], *kii_exec;
+  int Ntry, fd;
+
+  kii_exec = get_variable ("KII");
+  if (kii_exec == (char *) NULL) {
+    fprintf (stderr, "variable KII not found\n");
+    return (FALSE);
+  }
+
+  sprintf (socket_name, "/tmp/Kii.XXXXXX");
+  if ((fd = mkstemp (socket_name)) == -1) {
+    fprintf (stderr, "error starting kapa\n");
+    return (FALSE);
+  }
+  close (fd);
+  unlink (socket_name);
+
+  strcpy (Address.sun_path, socket_name); 
+  Address.sun_family = AF_UNIX; 
+  InitSocket = socket (AF_UNIX, SOCK_STREAM, 0); 
+  status = bind (InitSocket, (struct sockaddr *) &Address, sizeof (Address));
+  status = listen (InitSocket, 1);
+  
+  sprintf (temp, "%s %s &", kii_exec, socket_name);
+  free (kii_exec);
+
+# if DEBUG
+  fprintf (stderr, "start kii, press return: %s\n", temp);
+  fscanf (stdin, "%d", &i);
+# else  
+  system (temp);
+# endif
+  
+  addreslen =  sizeof (Address);
+  fcntl (InitSocket, F_SETFL, O_NONBLOCK); 
+
+# define NTRY 2000
+  Ntry = 0;
+  while (Ntry < NTRY) {
+    Ximage[N] = accept (InitSocket, (struct sockaddr *)&Address, &addreslen);
+    if (Ximage[N] == -1) {
+      if (errno == EAGAIN) {
+	usleep (10000);
+	Ntry ++;
+      } else { 
+	Ntry = NTRY;
+      }
+    } else {
+      Ntry = NTRY;
+    }
+  }
+
+  if (Ximage[N] < 0) {
+    fprintf (stderr, "error starting kii\n");
+    return (FALSE);
+  } else {
+    fcntl (Ximage[N], F_SETFL, !O_NONBLOCK); 
+    return (TRUE);
+  }
+  
+}
+
+/* return pointers for current Ximage, set if desired, test, open if needed */
+int GetImage (int *socket, int *N) {
+
+  int i, n;
+  char buffer[70];
+
+  SetImageDevice (TRUE);
+  if (N == (int *) NULL) {
+    n = Active;
+  } else {
+    if (*N >= NXIMAGE) {
+      fprintf (stderr, "invalid Ximage window %d\n", *N); 
+      return (FALSE);
+    }
+    if (*N < 0) {
+      *N = n = Active;
+    } else {
+      Active = n = *N;
+    }
+  }
+  
+  /* test Ximage[0], flush junk from pipe */
+  signal (SIGPIPE, XImageDead);
+  fcntl (Ximage[n], F_SETFL,  O_NONBLOCK); 
+  for (i = 0; (read (Ximage[n], buffer, 64) > 0) && (i < 20); i++);
+  fcntl (Ximage[n], F_SETFL, !O_NONBLOCK); 
+  
+  if (Ximage[n] < 1) {
+    if (!open_image(n)) {
+      return (FALSE);
+    }
+  }
+
+  if (socket != (int *) NULL) *socket = Ximage[n];
+
+  return (TRUE);
+
+}
+
+void SetImageName (char *name) {
+  strcpy (Ximbuffer[Active], name);
+}
+
+char *GetImageName () {
+  return (Ximbuffer[Active]);
+}
+  
+void SetImageScale (double zero, double range) {
+  Xzero[Active] = zero;
+  Xrange[Active] = range;
+}
+void GetImageScale (double *zero, double *range) {
+  *zero = Xzero[Active];
+  *range = Xrange[Active];
+}
Index: /tags/start/Ohana/src/opihi/lib.data/powell.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.data/powell.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.data/powell.c	(revision 12606)
@@ -0,0 +1,126 @@
+# include "data.h"
+
+# define FTOL 0.001
+# define ITMAX 200
+
+void linmin (float *p, float *xi, int n, float *fret, float (*func)());
+
+/*** not well tested yet !! ***/
+
+void powell (float *p, int Npar, float (func)() ) {
+  
+  int i, ibig, j, Niter;
+  float t, fptt, fp, del;
+  float *pt, *ptt, *xit, **xi;
+  float ftemp;
+
+  ALLOCATE (pt, float, Npar);
+  ALLOCATE (ptt, float, Npar);
+
+  ALLOCATE (xi, float *, Npar);
+  for (i = 0; i < Npar; i++) {
+    ALLOCATE (xi[i], float, Npar);
+    bzero (xi[i], Npar * sizeof (float));
+    xi[i][i] = 1;
+  }
+  ALLOCATE (xit, float, Npar);
+  
+  ftemp = func (p);
+
+  for (j = 0; j < Npar; j++) pt[j] = p[j];
+
+  for (Niter = 0; Niter < ITMAX; Niter++) {
+    fp = ftemp;
+    ibig = 0;
+    del = 0.0;
+
+    for (i = 0; i < Npar; i++) {
+      for (j = 0; j < Npar; j++) xit[j] = xi[j][i];
+
+      fptt = ftemp;
+      linmin (p, xit, Npar, &ftemp, func);
+
+      if (fabs (fptt - ftemp) > del) {
+	del = fabs (fptt - ftemp);
+	ibig = i;
+      }
+    }
+
+    if (fabs (fp - ftemp) <= 0.5*FTOL*(fabs(fp) + fabs(ftemp))) {
+      free (xit);
+      free (ptt);
+      free (pt);
+      for (i = 0; i < Npar; i++) free (xi[i]);
+      free (xi);
+      return;
+    }
+
+    for (j = 0; j < Npar; j++) {
+      ptt[j] = 2.0*p[j] - pt[j];
+      xit[j] = p[j] - pt[j];
+      pt[j]  = p[j];
+    }
+
+    fptt = func (ptt);
+
+    if (fptt < fp) {
+      t = 2.0*(fp - 2.0*ftemp + fptt) * SQ(fp - ftemp - del) - del * SQ(fp - fptt);
+      if (t < 0.0) {
+	linmin (p, xit, Npar, &ftemp, func);
+	for (j = 0; j < Npar; j++) xi[j][ibig] = xit[j];
+      }
+    }
+  }
+
+  if (Niter == ITMAX) {
+    fprintf (stderr, "Too many iterations in routine POWELL\n");
+    return;
+  }
+
+}
+
+#undef ITMAX
+
+/* 
+   function has N parameters
+   p is the initial guess for the N parameters 
+   xi are the N unit vectors - x[i][j] = delta(i,j)
+   Npar = N parameters
+   
+   FTOL - ending tolerance
+*/
+   
+#define TOL 2.0e-4
+
+int ncom=0;	/* defining declarations */
+float *pcom=0,*xicom=0,(*nrfunc)();
+
+void linmin (float *p, float *xi, int n, float *fret, float (*func)()) {
+
+	int j;
+	float xx,xmin,fx,fb,fa,bx,ax;
+	float brent(),f1dim(),*vector();
+	void mnbrak(),free_vector();
+
+	ncom=n;
+	pcom=vector(1,n);
+	xicom=vector(1,n);
+	nrfunc=func;
+	for (j=1;j<=n;j++) {
+		pcom[j]=p[j];
+		xicom[j]=xi[j];
+	}
+	ax=0.0;
+	xx=1.0;
+	bx=2.0;
+	mnbrak(&ax,&xx,&bx,&fa,&fx,&fb,f1dim);
+	*fret=brent(ax,xx,bx,f1dim,TOL,&xmin);
+	for (j=1;j<=n;j++) {
+		xi[j] *= xmin;
+		p[j] += xi[j];
+	}
+	free_vector(xicom,1,n);
+	free_vector(pcom,1,n);
+}
+
+#undef TOL
Index: /tags/start/Ohana/src/opihi/lib.data/precess.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.data/precess.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.data/precess.c	(revision 12606)
@@ -0,0 +1,49 @@
+# include "data.h"
+    
+double get_epoch (char *in_epoch, char mode) {
+
+  int done;
+  double epoch;
+
+  epoch = 2000.0;
+  done = FALSE;
+  if (in_epoch[0] == 'B') {
+    epoch = BtoJ(atof(&in_epoch[1]));
+    done = TRUE;
+  }
+
+  if (in_epoch[0] == 'J') {
+    epoch = atof(&in_epoch[1]);
+    done = TRUE;
+  }
+
+  if (!done && (mode == 'B')) {
+    epoch = BtoJ(atof(in_epoch));
+    done = TRUE;
+  }
+    
+  if (!done && (mode == 'J')) {
+    epoch = atof(in_epoch);
+    done = TRUE;
+  }
+
+  if (!done) {
+    fprintf (stderr, "error finding epoch %s\n", in_epoch);
+    exit (0);
+  }
+  
+  return (epoch);
+
+}
+
+  
+double BtoJ (double in_epoch) {
+
+  double JD, out_epoch;
+
+  JD = (in_epoch - 1900.0)*365.242198781 + 2415020.31352;
+  out_epoch = 2000.0 + (JD - 2451545.0)/365.25;
+
+  return (out_epoch);
+}
+
Index: /tags/start/Ohana/src/opihi/lib.data/sort.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.data/sort.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.data/sort.c	(revision 12606)
@@ -0,0 +1,292 @@
+# include "data.h"
+
+void sort (double *value, int N) {
+
+  int l,j,ir,i;
+  double temp;
+  
+  if (N < 2) return;
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      temp = value[--l];
+    }
+    else {
+      temp = value[ir];
+      value[ir] = value[0];
+      if (--ir == 0) {
+	value[0] = temp;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && value[j] < value[j+1]) ++j;
+      if (temp < value[j]) {
+	value[i]=value[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    value[i] = temp;
+  }
+}
+
+void fsort (float *value, int N) {
+
+  int l,j,ir,i;
+  float temp;
+  
+  if (N < 2) return;
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      temp = value[--l];
+    }
+    else {
+      temp = value[ir];
+      value[ir] = value[0];
+      if (--ir == 0) {
+	value[0] = temp;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && value[j] < value[j+1]) ++j;
+      if (temp < value[j]) {
+	value[i]=value[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    value[i] = temp;
+  }
+}
+
+void sortpair (double *value1, double *value2, int N) {
+
+  int l,j,ir,i;
+  double temp1, temp2;
+  
+  if (N < 2) return;
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      temp1 = value1[l];
+      temp2 = value2[l];
+    }
+    else {
+      temp1 = value1[ir];
+      temp2 = value2[ir];
+      value1[ir] = value1[0];
+      value2[ir] = value2[0];
+      if (--ir == 0) {
+	value1[0] = temp1;
+	value2[0] = temp2;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && value1[j] < value1[j+1]) ++j;
+      if (temp1 < value1[j]) {
+	value1[i]=value1[j];
+	value2[i]=value2[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    value1[i] = temp1;
+    value2[i] = temp2;
+  }
+}
+
+void fsortpair (float *X, float *Y, int N) {
+
+  int l,j,ir,i;
+  float tX, tY;
+  
+  if (N < 2) return;
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+  }
+}
+
+void sortthree (float *X, float *Y, float *Z, int N) {
+
+  int l,j,ir,i;
+  float tX, tY, tZ;
+  
+  if (N < 2) return;
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tZ = Z[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tZ = Z[ir];
+      Z[ir] = Z[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	Z[0] = tZ;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	Z[i] = Z[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    Z[i] = tZ;
+  }
+}
+
+void sort_lists (float *X, float *Y, int *S, int N) {
+
+  int l,j,ir,i;
+  double tX, tY, tS;
+  
+  if (N < 2) return;
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    S[i] = tS;
+  }
+}
+
+void dsort_lists (double *X, double *Y, int *S, int N) {
+
+  int l,j,ir,i;
+  double tX, tY, tS;
+  
+  if (N < 2) return;
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    S[i] = tS;
+  }
+}
Index: /tags/start/Ohana/src/opihi/lib.data/spline.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.data/spline.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.data/spline.c	(revision 12606)
@@ -0,0 +1,58 @@
+# include "data.h"
+
+/* construct the natural spline for x, y in y2 */
+void spline (float *x, float *y, int N, float *y2) {
+
+  int i;
+  float dy, dx, *tmp;
+  
+  ALLOCATE (tmp, float, N);
+
+  y2[0] = tmp[0] = 0.0;
+  
+  for (i = 1; i < N-1; i++) {
+    dx = (x[i+0] - x[i-1]) / (x[i+1] - x[i-1]);
+    dy = dx * y2[i-1] + 2.0;
+    y2[i] = (dx - 1.0) / dy;
+    tmp[i] = (y[i+1] - y[i+0]) / (x[i+1] - x[i+0]) - (y[i+0] - y[i-1]) / (x[i+0] - x[i-1]);
+    tmp[i] = (6.0 * tmp[i] / (x[i+1] - x[i-1]) - dx*tmp[i-1]) / dy;
+  }
+  
+  y2[N-1] = 0;
+  for (i = N-2; i >= 1; i--)
+    y2[i] = y2[i]*y2[i+1] + tmp[i];
+
+  free (tmp);
+}
+
+/* evaluate spline for x, y, y2 at X */
+float splint (float *x, float *y, float *y2, int N, float X) {
+
+  int i, lo, hi;
+  float dx, a, b, value;
+  
+  /* find correct element in array (x must be sorted) */
+  lo = 0;
+  hi = N-1;
+  while (hi - lo > 1) {
+    i = (hi+lo) >> 1;
+    if (x[i] > X) 
+      hi = i;
+    else 
+      lo = i;
+  }
+
+  /* error condition: duplicate abssisca */
+  dx = x[hi] - x[lo];
+  if (dx == 0.0) {
+    return (HUGE_VAL);
+  }
+
+  /* evaluate spline */
+  a = (x[hi] - X) / dx;
+  b = (X - x[lo]) / dx;
+
+  value = a*y[lo] + b*y[hi] + ((a*a*a - a)*y2[lo] + (b*b*b - b)*y2[hi])*(dx*dx) / 6.0;
+  return (value);
+
+}
Index: /tags/start/Ohana/src/opihi/lib.data/starfuncs.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.data/starfuncs.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.data/starfuncs.c	(revision 12606)
@@ -0,0 +1,89 @@
+# include "data.h"
+
+double get_aperture_stats (Matrix *matrix, int X, int Y, int Npix, int Nborder, double max) {
+
+  double *ring;
+  double x, y, x2, y2, I, sky, FWHMx, FWHMy, value, mag;
+  int i, j, n, Npix2, Nring, Nmax;
+  double Npts, gain, dsky2, dmag;
+  char *string;
+  
+  string = get_variable ("GAIN");
+  if (string == (char *) NULL) {
+    fprintf (stderr, "assuming a value of 1.0\n");
+    gain = 1.0;
+  } else {
+    gain = atof (string);
+  }
+  Nborder = MAX (1, Nborder);
+  Nborder = MIN (1000, Nborder);
+  
+  Npix2 = (int)(0.5*Npix);
+  Npix = 2 * Npix2 + 1;
+  Nring = 4*Nborder*(Nborder + Npix);
+  ALLOCATE (ring, double, Nring);
+  bzero (ring, sizeof(double)*Nring);
+
+  n = 0;  
+  for (j = 0; j < Nborder; j++) {
+    for (i = X - Npix2 - Nborder; i < X + Npix2 + Nborder + 1; i++, n+=2) {
+      ring[n]   = fits_get_matrix_value (matrix, i, (int)(Y - Npix2 - j));
+      ring[n+1] = fits_get_matrix_value (matrix, i, (int)(Y + Npix2 + j));
+    }
+    for (i = Y - Npix2; i < Y + Npix2 + 1; i++, n+=2) {
+      ring[n]   = fits_get_matrix_value (matrix, (int)(X - Npix2 - j), i);
+      ring[n+1] = fits_get_matrix_value (matrix, (int)(X + Npix2 + j), i);
+    }
+  }
+  sort (ring, Nring);
+  for (Npts = sky = dsky2 = 0, i = 0.25*Nring; i < 0.75*Nring; i++, Npts += 1.0) {
+    sky += ring[i];
+    dsky2 += ring[i]*ring[i];
+  }
+  sky = sky / Npts;
+  dsky2 = dsky2 / Npts - sky*sky;
+  free (ring);
+
+  Npts = Nmax = 0;
+  x = y = x2 = y2 = I = 0;
+  for (i = X - Npix2; i < X + Npix2 + 1; i++) {
+    for (j = Y - Npix2; j < Y + Npix2 + 1; j++) {
+      value = fits_get_matrix_value (matrix, i, j);
+      x  += i*(value - sky);
+      y  += j*(value - sky);
+      x2 += i*i*(value - sky);
+      y2 += j*j*(value - sky);
+      I  += (value - sky);
+      Npts ++;
+      if (value > max) {
+	Nmax ++;
+      }
+    }
+  }
+
+  x = x / I;
+  y = y / I;
+  FWHMx = 2.355*sqrt (fabs(x2 / I - x*x));
+  FWHMy = 2.355*sqrt (fabs(y2 / I - y*y));
+  mag = -2.5*log10(I);
+  dmag = sqrt (fabs(1.0 / (gain*I) + Npts*dsky2 / (I*I)));
+  x = x + 1;
+  y = y + 1;
+  
+  set_variable ("Xg", x);
+  set_variable ("Yg", y);
+  set_variable ("SXg", FWHMx);
+  set_variable ("SYg", FWHMy);
+  set_variable ("Sg", sky);
+  set_variable ("dSg", sqrt (fabs (dsky2)));
+  set_variable ("Zg", mag);
+  set_variable ("dZg", dmag);
+  set_variable ("Zcg", I);
+  set_int_variable ("Nsat", Nmax);
+  
+  fprintf (GetOutfile(), "%f %f %f %f %f %f %f %f\n", x, y, FWHMx, FWHMy, sky, I, mag, dmag);
+
+  return (mag);
+
+}
+
Index: /tags/start/Ohana/src/opihi/lib.data/svdcmp.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.data/svdcmp.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.data/svdcmp.c	(revision 12606)
@@ -0,0 +1,210 @@
+# include "data.h"
+
+/*
+  static float at,bt,ct;
+  #define PYTHAG(a,b) ((at=fabs(a)) > (bt=fabs(b)) ? \
+  (ct=bt/at,at*sqrt(1.0+ct*ct)) : (bt ? (ct=at/bt,bt*sqrt(1.0+ct*ct)): 0.0))
+  pythag -> hypot (check on roundoff errors) 
+*/
+
+/* use simple max? */
+#define FSIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
+
+/* n == Nx, m == Ny */
+int svdcmp (float *a, float *w, float *v, int Nx, int Ny) {
+
+  int flag, i, its, j, jj, k, l, nm, status;
+  float c, f, h, s, x, y, z;
+  float anorm=0.0, g = 0.0, scale = 0.0;
+  float *rv1;
+
+  if (Ny < Nx) return (0);
+
+  ALLOCATE (rv1, float, Nx);
+  for (i = 0; i < Nx; i++) {
+    l = i + 1;
+    rv1[i] = scale*g;
+    g = s = scale = 0.0;
+    if (i < Ny) {
+      for (k = i; k < Ny; k++) scale += fabs(a[k*Nx + i]);
+      if (scale) {
+	for (k = i; k < Ny; k++) {
+	  a[k*Nx + i] /= scale;
+	  s += a[k*Nx + i]*a[k*Nx + i];
+	}
+	f = a[i*Nx + i];
+	g  = -FSIGN(sqrt(s), f);
+	h = f*g - s;
+	a[i*Nx + i] = f-g;
+	if (i != Nx - 1) {
+	  for (j = l; j < Nx; j++) {
+	    for (s = 0.0, k = i; k < Ny; k++) s += a[k*Nx + i]*a[k*Nx + j];
+	    f = s/h;
+	    for (k = i; k < Ny; k++) a[k*Nx + j] += f*a[k*Nx + i];
+	  }
+	}
+	for (k = i; k < Ny; k++) a[k*Nx + i] *= scale;
+      }
+    }
+    w[i] = scale*g;
+    g = s = scale = 0.0;
+    if ((i < Ny) && (i != (Nx - 1))) {
+      for (k = l; k < Nx; k++) scale += fabs(a[i*Nx + k]);
+      if (scale) {
+	for (k = l; k < Nx; k++) {
+	  a[i*Nx + k] /= scale;
+	  s += a[i*Nx + k]*a[i*Nx + k];
+	}
+	f = a[i*Nx + l];
+	g = -FSIGN(sqrt(s), f);
+	h = f*g - s;
+	a[i*Nx + l] = f-g;
+	for (k = l; k < Nx; k++) rv1[k] = a[i*Nx + k]/h;
+	if (i != Ny - 1) {
+	  for (j = l; j < Ny; j++) {
+	    for (s = 0.0, k = l; k < Nx; k++) s += a[j*Nx + k]*a[i*Nx + k];
+	    for (k = l; k < Nx; k++) a[j*Nx + k] += s*rv1[k];
+	  }
+	}
+	for (k = l; k < Nx; k++) a[i*Nx + k] *= scale;
+      }
+    }
+    anorm = MAX(anorm, (fabs(w[i]) + fabs(rv1[i])));
+  }
+
+  for (i = Nx - 1; i >= 0; i--) {
+    if (i < Nx - 1) {
+      if (g) {
+	/* isn't l == n to start?? */
+	for (j = l; j < Nx; j++) v[j*Nx + i] = (a[i*Nx + j]/a[i*Nx + l])/g;
+	for (j = l; j < Nx; j++) {
+	  for (s = 0.0, k = l; k < Nx; k++) s += a[i*Nx + k]*v[k*Nx + j];
+	  for (k = l; k < Nx; k++) v[k*Nx + j] += s*v[k*Nx + i];
+	}
+      }
+      for (j = l; j < Nx; j++) v[i*Nx + j] = v[j*Nx + i] = 0.0;
+    }
+    v[i*Nx + i] = 1.0;
+    g = rv1[i];
+    l = i;
+  }
+  for (i = Nx - 1; i >= 0; i--) {
+    l = i + 1;
+    g = w[i];
+    if (i < Nx - 1)
+      for (j = l; j < Nx; j++) a[i*Nx + j] = 0.0;
+    if (g) {
+      g = 1.0/g;
+      if (i != Nx - 1) {
+	for (j = l; j < Nx; j++) {
+	  for (s = 0.0, k = l; k < Ny; k++) s += a[k*Nx + i]*a[k*Nx + j];
+	  f = (s/a[i*Nx + i])*g;
+	  for (k = i; k < Ny; k++) a[k*Nx + j] += f*a[k*Nx + i];
+	}
+      }
+      for (j = i; j < Ny; j++) a[j*Nx + i] *= g;
+    } else {
+      for (j = i; j < Ny; j++) a[j*Nx + i] = 0.0;
+    }
+    ++a[i*Nx + i];
+  }
+
+  status = 1;
+  for (k = Nx - 1; k >= 0; k--) {
+    for (its = 0; its < 30; its++) {
+      flag = 1;
+      for (l = k; l >= 0; l--) {
+	nm = l - 1;
+	if (fabs(rv1[l])+anorm == anorm) {
+	  flag = 0;
+	  break;
+	}
+	if (fabs(w[nm])+anorm == anorm) break;
+      }
+      if (flag) {
+	c = 0.0;
+	s = 1.0;
+	for (i = l; i < k; i++) {
+	  f = s*rv1[i];
+	  if (fabs(f)+anorm != anorm) {
+	    g = w[i];
+	    h = hypot (f, g);
+	    w[i] = h;
+	    h = 1.0/h;
+	    c = g*h;
+	    s = (-f*h);
+	    for (j = 0; j < Ny; j++) {
+	      y = a[j*Nx + nm];
+	      z = a[j*Nx + i];
+	      a[j*Nx + nm] = y*c + z*s;
+	      a[j*Nx + i] = z*c - y*s;
+	    }
+	  }
+	}
+      }
+      z = w[k];
+      if (l == k) {
+	if (z < 0.0) {
+	  w[k] = -z;
+	  for (j = 0; j < Nx; j++) v[j*Nx + k] = (-v[j*Nx + k]);
+	}
+	break;
+      }
+      if (its == 29) status = 0;
+      x = w[l];
+      nm = k-1;
+      y = w[nm];
+      g = rv1[nm];
+      h = rv1[k];
+      f = ((y-z)*(y+z) + (g-h)*(g+h))/(2.0*h*y);
+      g = hypot (f, 1.0);
+      f = ((x-z)*(x+z) + h*((y/(f+FSIGN(g, f)))-h))/x;
+      c = s = 1.0;
+      for (j = l; j < nm; j++) {
+	i = j+1;
+	g = rv1[i];
+	y = w[i];
+	h = s*g;
+	g = c*g;
+	z = hypot (f, h);
+	rv1[j] = z;
+	c = f/z;
+	s = h/z;
+	f = x*c+g*s;
+	g = g*c-x*s;
+	h = y*s;
+	y = y*c;
+	for (jj = 0; jj < Nx; jj++) {
+	  x = v[jj*Nx + j];
+	  z = v[jj*Nx + i];
+	  v[jj*Nx + j] = x*c+z*s;
+	  v[jj*Nx + i] = z*c-x*s;
+	}
+	z = hypot(f, h);
+	w[j] = z;
+	if (z) {
+	  z = 1.0/z;
+	  c = f*z;
+	  s = h*z;
+	}
+	f = (c*g) + (s*y);
+	x = (c*y) - (s*g);
+	for (jj = 0; jj < Ny; jj++) {
+	  y = a[jj*Nx + j];
+	  z = a[jj*Nx + i];
+	  a[jj*Nx + j] = y*c+z*s;
+	  a[jj*Nx + i] = z*c-y*s;
+	}
+      }
+      rv1[l] = 0.0;
+      rv1[k] = f;
+      w[k] = x;
+    }
+  }
+  free(rv1);
+  return (1);
+}
+
+#undef FSIGN
+#undef MAX
+#undef PYTHAG
Index: /tags/start/Ohana/src/opihi/lib.shell/BufferOps.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/BufferOps.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/BufferOps.c	(revision 12606)
@@ -0,0 +1,251 @@
+# include "opihi.h"
+
+static Buffer **buffers;
+static int     Nbuffers;
+
+void InitBuffers () {
+  Nbuffers = 0;
+  ALLOCATE (buffers, Buffer *, 1);
+}
+
+Buffer *InitBuffer () {
+  Buffer *buf;
+
+  ALLOCATE (buf, Buffer, 1);
+  bzero (buf[0].name, 1024);
+  bzero (buf[0].file, 1024);
+  ALLOCATE (buf[0].matrix.buffer, char, 1);
+  ALLOCATE (buf[0].header.buffer, char, 1);
+  return (buf);
+}
+
+int IsBuffer (char *name) {
+ 
+  int i;
+
+  if (name == NULL) return (FALSE);
+
+  for (i = 0; (i < Nbuffers) && (strcmp(buffers[i][0].name, name)); i++);
+  if (i == Nbuffers) return (FALSE);
+  return (TRUE);
+}
+
+int IsBufferPtr (Buffer *buf) {
+ 
+  int i;
+
+  if (buf == NULL) return (FALSE);
+
+  for (i = 0; (i < Nbuffers) && (buffers[i] != buf); i++);
+  if (i == Nbuffers) return (FALSE);
+  return (TRUE);
+}
+
+Buffer *SelectBuffer (char *name, int mode, int verbose) {
+
+  int i;
+
+  if (name == NULL) goto error;
+  if (ISNUM(name[0])) goto error;
+  if (IsVector(name)) goto error;
+
+  for (i = 0; (i < Nbuffers) && (strcmp(buffers[i][0].name, name)); i++);
+  /* is a new buffer */
+  if (i == Nbuffers) { 
+    if (mode == OLDBUFFER) goto error;
+    Nbuffers += 1;
+    REALLOCATE (buffers, Buffer *, Nbuffers);
+    buffers[i] = InitBuffer ();
+    strcpy (buffers[i][0].name, name);
+    return (buffers[i]);
+  } 
+  /* is an old buffer */
+  if (mode == NEWBUFFER) goto error;
+  return (buffers[i]);
+
+ error:
+  if (verbose) fprintf (stderr, "invalid matrix %s\n", name);
+  return (NULL);
+}
+
+int CreateBuffer (Buffer *buf) {
+
+  /* store the default output values */
+  buf[0].bitpix = buf[0].header.bitpix;
+  buf[0].unsign = buf[0].header.unsign;
+  buf[0].bzero  = buf[0].header.bzero;
+  buf[0].bscale = buf[0].header.bscale;
+  
+  /* assign the necessary internal values */
+  buf[0].header.bitpix   = -32;
+  buf[0].header.unsign   = FALSE;
+  buf[0].header.bzero    = 0;
+  buf[0].header.bscale   = 1;
+  
+  /* make some test of the validity of the values */
+
+  /* create the appropriate header and matrix */
+  fits_create_header (&buf[0].header);
+  fits_create_matrix (&buf[0].header, &buf[0].matrix);
+
+  return (TRUE);
+}
+  
+/* copy data from in to out - new memory space */
+int CopyNamedBuffer (char *out, char *in) {
+  Buffer *In, *Out;
+  if ((In  = SelectBuffer (in,  OLDBUFFER, FALSE)) == NULL) return (FALSE);
+  if ((Out = SelectBuffer (out, ANYBUFFER, FALSE)) == NULL) return (FALSE);
+  CopyBuffer (Out, In);
+  return (TRUE);
+}
+
+int CopyBuffer (Buffer *out, Buffer *in) {
+  free (out[0].matrix.buffer);
+  free (out[0].header.buffer);
+  out[0].bitpix = in[0].bitpix;
+  out[0].unsign = in[0].unsign;
+  out[0].bscale = in[0].bscale;
+  out[0].bzero  = in[0].bzero;
+  strcpy (out[0].file, in[0].file);
+  fits_copy_matrix (&in[0].matrix, &out[0].matrix);
+  fits_copy_header (&in[0].header, &out[0].header);
+  return (TRUE);
+}
+
+/* move data from in to out - use old memory space */
+int MoveNamedBuffer (char *out, char *in) {
+  Buffer *In, *Out;
+  if ((In  = SelectBuffer (in,  OLDBUFFER, FALSE)) == NULL) return (FALSE);
+  if ((Out = SelectBuffer (out, ANYBUFFER, FALSE)) == NULL) return (FALSE);
+  MoveBuffer (Out, In);
+  return (TRUE);
+}
+int MoveBuffer (Buffer *out, Buffer *in) {
+  int i, j;
+
+  free (out[0].matrix.buffer);
+  free (out[0].header.buffer);
+  out[0].bitpix = in[0].bitpix;
+  out[0].unsign = in[0].unsign;
+  out[0].bscale = in[0].bscale;
+  out[0].bzero  = in[0].bzero;
+  out[0].matrix = in[0].matrix;
+  out[0].header = in[0].header;
+  strcpy (out[0].file, in[0].file);
+
+  /* delete buffer entry from buffer list, if it exists */
+  for (i = 0; (i < Nbuffers) && (in != buffers[i]); i++);
+  if (i == Nbuffers) return (TRUE);
+
+  free (in);
+  for (j = i; j < Nbuffers - 1; j++) buffers[j] = buffers[j + 1];
+  Nbuffers -= 1;
+  REALLOCATE (buffers, Buffer *, MAX (Nbuffers, 1));
+  return (TRUE);
+}
+
+/* delete by ptr */
+int DeleteBuffer (Buffer *buf) {
+
+  int i, j;
+
+  if (buf == NULL) return (FALSE);
+  for (i = 0; (i < Nbuffers) && (buf != buffers[i]); i++);
+  if (i == Nbuffers) return (FALSE);
+
+  fits_free_header (&buffers[i][0].header);
+  fits_free_matrix (&buffers[i][0].matrix);
+
+  for (j = i; j < Nbuffers - 1; j++) buffers[j] = buffers[j + 1];
+
+  Nbuffers -= 1;
+  REALLOCATE (buffers, Buffer *, MAX (Nbuffers, 1));
+  return (TRUE);
+}
+  
+/* delete by name */
+int DeleteNamedBuffer (char *name) {
+
+  int i, j;
+
+  if (name == NULL) return (FALSE);
+  for (i = 0; (i < Nbuffers) && (strcmp(buffers[i][0].name, name)); i++);
+  if (i == Nbuffers) return (FALSE);
+
+  fits_free_header (&buffers[i][0].header);
+  fits_free_matrix (&buffers[i][0].matrix);
+
+  for (j = i; j < Nbuffers - 1; j++) buffers[j] = buffers[j + 1];
+
+  Nbuffers -= 1;
+  REALLOCATE (buffers, Buffer *, MAX (Nbuffers, 1));
+  return (TRUE);
+}
+
+int SelectOverlay (char *name, int *number) {
+
+  *number = -1;
+  if (!strcmp (name, "red") || !strcmp (name, "0"))
+    *number = 0;
+  if (!strcmp (name, "green") || !strcmp (name, "1"))
+    *number = 1;
+  if (!strcmp (name, "blue") || !strcmp (name, "2"))
+    *number = 2;
+  if (!strcmp (name, "yellow") || !strcmp (name, "3"))
+    *number = 3;
+
+  if (*number < 0) {
+    fprintf (stderr, "valid overlays may be: red (0), green (1), blue (2), yellow (3)\n");
+    return (FALSE);
+  }
+  else {
+    return (TRUE);
+  }
+}
+
+void dump_buffers (int n) {
+
+  int i;
+
+  fprintf (stderr, "try %d\n", n);
+  for (i = 0; i < Nbuffers; i++) {
+    fprintf (stderr, "%d  %x\n", i, (int) buffers[i]);
+    fprintf (stderr, "%d  %x  %s\n", i, (int) buffers[i][0].name, buffers[i][0].name);
+    fprintf (stderr, "%d  %x  %s\n", i, (int) buffers[i][0].file, buffers[i][0].file);
+    fprintf (stderr, "%d  %x  %x\n", i, (int) &buffers[i][0].header, (int) buffers[i][0].header.buffer);
+    fprintf (stderr, "%d  %x  %x\n", i, (int) &buffers[i][0].matrix, (int) buffers[i][0].matrix.buffer);
+    fprintf (stderr, "%d  %d  %d  %f %f\n", i, buffers[i][0].bitpix, buffers[i][0].unsign, buffers[i][0].bscale, buffers[i][0].bzero);
+  }
+}
+
+int PrintBuffers (int Long) {
+
+  int i;
+
+  if (Nbuffers == 0) {
+    fprintf (stderr, "No allocated buffers\n");
+    return (TRUE);
+  }
+  
+  if (Long) {
+    fprintf (GetOutfile(), "    N       name                      file     X     Y    bytes BP  U   bzero     bscale  \n");
+    for (i = 0; i < Nbuffers; i++) {
+      fprintf (GetOutfile(), "%5d %10s %25s %5d %5d %10d %3d %1d %10.4e %10.4e\n",
+	       i, buffers[i][0].name, buffers[i][0].file, 
+	       buffers[i][0].header.Naxis[0], buffers[i][0].header.Naxis[1],
+	       buffers[i][0].header.size + buffers[i][0].matrix.size, buffers[i][0].bitpix, 
+	       buffers[i][0].unsign, buffers[i][0].bzero, buffers[i][0].bscale);
+    }
+    return (TRUE);
+  }
+
+  fprintf (GetOutfile(), "    N       name                      file     X     Y    bytes\n");
+  for (i = 0; i < Nbuffers; i++) {
+    fprintf (GetOutfile(), "%5d %10s %25s %5d %5d %10d\n",
+	     i, buffers[i][0].name, buffers[i][0].file, 
+	     buffers[i][0].header.Naxis[0], buffers[i][0].header.Naxis[1],
+	     buffers[i][0].header.size + buffers[i][0].matrix.size);
+  }
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/lib.shell/CommandOps.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/CommandOps.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/CommandOps.c	(revision 12606)
@@ -0,0 +1,174 @@
+# include "opihi.h"
+
+static Command  *commands;
+static int      Ncommands;
+static int      NCOMMANDS;
+
+void InitCommands () {
+  NCOMMANDS = 20;
+  Ncommands = 0;
+  ALLOCATE (commands, Command, NCOMMANDS);
+}
+
+void AddCommand (Command *new) {
+  
+  commands[Ncommands] = *new;
+  Ncommands ++;
+  if (Ncommands == NCOMMANDS) {
+    NCOMMANDS += 20;
+    REALLOCATE (commands, Command, NCOMMANDS);
+  }
+}
+
+int DeleteCommand (Command *command) {
+
+  int i, Nc;
+
+  Nc = -1;
+  for (i = 0; i < Ncommands; i++) {
+    if (command == &commands[i]) {
+      Nc = i;
+      break;
+    }
+  }
+  if (Nc == -1) {
+    fprintf (stderr, "programming error: command not found\n");
+    return (FALSE);
+  }
+
+  free (commands[Nc].name);
+  for (i = Nc + 1; i < Ncommands; i++)
+    commands[i - 1] = commands[i];
+  Ncommands --;
+  REALLOCATE (commands, Command, Ncommands);
+  return (TRUE);
+}
+
+/* return command which unambiguously matches name */
+Command *MatchCommand (char *name, int VERBOSE, int EXACT) {
+
+  int i, match[10], Nmatch;
+
+  /* try for an exact match first */
+  for (i = 0; i < Ncommands; i++) {
+    if (!strcmp (commands[i].name, name)) {
+      return (&commands[i]);
+    }
+  }
+  if (EXACT) {
+    if (VERBOSE) fprintf (stderr, "no exact match to %s\n", name);
+    return (NULL);
+  }
+
+  /* not found as complete command, try partial */
+  Nmatch = 0;
+  for (i = 0; (Nmatch < 10) && (i < Ncommands); i++) {
+    if (!strncmp (commands[i].name, name, strlen(name))) {  /* found a command */
+      match[Nmatch] = i;
+      Nmatch ++;
+    }
+  }
+  if (Nmatch == 1) return (&commands[match[0]]);
+
+  if (Nmatch > 1) {
+    if (VERBOSE) {
+      fprintf (stderr, "ambiguous command: %s ( ", name);
+      for (i = 0; i < Nmatch; i++) {
+	fprintf (stderr, "%s ", commands[match[i]].name);
+      }
+      fprintf (stderr, ")\n");
+    }
+    return (NULL);
+  }
+  if (VERBOSE) fprintf (stderr, "%s: Command not found.\n", name);
+  return (NULL);
+}  
+
+/* generate a command completion list for readline */
+char *command_generator (const char *text, int state) {
+
+  /* i must be remembered from call to call */
+  static int i, len;
+
+  /* On first call, state is set to 0: initial the state */
+  if (!state) {
+    i = -1;  
+    len = strlen (text);
+  }
+
+  /* Return the next partial match from the command list */
+  for (i++; i < Ncommands; i++) {
+    if (!len) 
+      return (strcreate(commands[i].name));
+    if (!strncmp (commands[i].name, text, len)) {
+      return (strcreate(commands[i].name));
+    }
+  }
+
+  /* If no names matched, then return NULL. */
+  return ((char *)NULL);
+}
+
+/* tell readline to use out command_generator rather than basic completion */
+char **command_completer (const char *text, int start, int end) {
+  
+  char **matches;
+
+  matches = (char **) NULL;
+  
+  if (start == 0)
+    matches = rl_completion_matches (text, command_generator);
+
+  return (matches);
+}
+
+void print_commands (FILE *f) {
+
+  int i, *seq;
+
+  ALLOCATE (seq, int, Ncommands);
+  sort_commands (seq);
+  for (i = 0; i < Ncommands; i++) {
+    fprintf (f, "%-25s -- %s\n", commands[seq[i]].name, commands[seq[i]].help);
+  }
+  free (seq);
+
+  return;
+}
+
+void sort_commands (int *seq) {
+
+  int l,j,ir,i, N;
+  int temp;
+  
+  N = Ncommands;
+  for (i = 0; i < N; i++) 
+    seq[i] = i;
+  
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      temp = seq[--l];
+    }
+    else {
+      temp = seq[ir];
+      seq[ir] = seq[0];
+      if (--ir == 0) {
+        seq[0] = temp;
+        return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && (strcmp (commands[seq[j]].name, commands[seq[j+1]].name) < 0)) ++j;
+      if (strcmp (commands[temp].name, commands[seq[j]].name) < 0) {
+        seq[i]=seq[j];
+        j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    seq[i] = temp;
+  }
+}
Index: /tags/start/Ohana/src/opihi/lib.shell/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/ConfigInit.c	(revision 12606)
@@ -0,0 +1,48 @@
+# include "opihi.h"
+
+static char *GlobalConfig;
+
+int ConfigInit (int *argc, char **argv) {
+
+  char *config, *file;
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    if (file != (char *) NULL) free (file);
+    return (FALSE);
+  }
+
+  GlobalConfig = config;
+
+  free (file);
+  return (TRUE);
+}
+
+char *VarConfig (char *keyword, char *mode, void *ptr) {
+
+  char *answer;
+
+  answer = get_variable (keyword);
+  if (answer != (char *) NULL) {
+
+    if (!strcmp (mode, "%s")) {
+      strcpy ((char *) ptr, answer);
+    } else {
+      if (!strcmp (mode, "%d"))  *(int *) ptr       = atoi (answer);
+      if (!strcmp (mode, "%u"))  *(unsigned *) ptr  = atoi (answer);
+      if (!strcmp (mode, "%ld")) *(long *) ptr      = atoi (answer);
+      if (!strcmp (mode, "%hd")) *(short *) ptr     = atoi (answer);
+      if (!strcmp (mode, "%f"))  *(float *) ptr     = atof (answer);
+      if (!strcmp (mode, "%lf")) *(double *) ptr    = atof (answer);
+    }
+    free (answer);
+    return (ptr);
+  }
+
+  answer = ScanConfig (GlobalConfig, keyword, mode, 0, ptr);
+  return (answer);
+}
+
+  
Index: /tags/start/Ohana/src/opihi/lib.shell/ListOps.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/ListOps.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/ListOps.c	(revision 12606)
@@ -0,0 +1,141 @@
+# include "opihi.h"
+# include "macro.h"
+
+/* return a new string consisting of the next line in the current list */
+char *get_next_listentry (int ThisList) {
+
+  char *output;
+
+  lists[ThisList].n++;
+
+  if (lists[ThisList].n >= lists[Nlists].Nlines) 
+    return ((char *) NULL);
+
+  output = lists[Nlists].line[lists[ThisList].n];
+  
+  return (output);
+
+}
+
+char *remove_listentry (int current) {
+
+  int i;
+  char *output;
+
+  if ((current + 1) >= lists[Nlists].Nlines) 
+    return ((char *) NULL);
+
+  output = lists[Nlists].line[current + 1];
+  
+  for (i = current + 1; i < lists[Nlists].Nlines - 1; i++) {
+    lists[Nlists].line[i] = lists[Nlists].line[i + 1];
+  }
+
+  lists[Nlists].Nlines --;
+  return (output);
+
+}
+
+int is_for_loop (char *line) {
+
+  char *comm;
+
+  comm = thisword (line);
+  if (comm == (char *) NULL) return (FALSE);
+
+  if (strcmp (comm, "for")) {
+    free (comm);
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+int is_macro_create (char *line) {
+
+  int i, N;
+  char *comm;
+  char *this_macro;
+
+
+  comm = thisword (line);
+  if (comm == (char *) NULL)
+    return (FALSE);
+  if (strcmp (comm, "macro")) {
+    free (comm);
+    return (FALSE);
+  }
+  
+  this_macro = thisword (nextword (line));
+
+  if (this_macro == (char *)NULL) {
+    return (FALSE);
+  }
+
+  N = sizeof (in_macro) / sizeof (Command);
+
+  /* find the macro sub-command which matches from the list. */
+  /* if sub-command is not found, assume this is creating a new macro */
+  for (i = 0; i < N; i++) {
+    if (!strcmp (in_macro[i].name, this_macro)) {
+      free (this_macro);
+      return (FALSE);
+    }
+  }
+
+  free (this_macro);
+  return (TRUE);
+
+}
+
+int is_if_block (char *line) {
+
+  char *comm, *temp;
+
+  temp = thisword (nextword (nextword (line)));
+  comm = thisword (line);
+
+  if (comm == NULL) goto escape;
+
+  if (strcmp (comm, "if")) goto escape;
+
+  if ((temp != NULL) && !strcmp (temp, "break")) goto escape;
+
+  free (comm);
+  return (TRUE);
+
+escape: 
+  if (comm != NULL) free (comm);
+  if (temp != NULL) free (temp);
+  return (FALSE);
+}
+
+int is_loop (char *line) {
+
+  char *comm;
+
+  comm = thisword (line);
+  if (comm == (char *) NULL) return (FALSE);
+
+  if (strcmp (comm, "while")) {
+    free (comm);
+    return (FALSE);
+  }
+  free (comm);
+  return (TRUE);
+}
+
+
+int is_list (char *line) {
+  
+  int status;
+
+  status = is_if_block (line);
+  status |= is_macro_create (line);
+  status |= is_for_loop (line);
+  status |= is_loop (line);
+
+  return (status);
+
+}
Index: /tags/start/Ohana/src/opihi/lib.shell/MacroOps.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/MacroOps.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/MacroOps.c	(revision 12606)
@@ -0,0 +1,136 @@
+# include "opihi.h"
+
+static char dot[] = ".";
+
+static Macro *macros;
+static int   Nmacros;
+static int   NMACROS;
+
+static char *MacroName = dot;
+static int   MacroDepth = 0;
+
+void InitMacros () {
+  NMACROS = 20;
+  Nmacros = 0;
+  ALLOCATE (macros, Macro, NMACROS);
+  MacroName = dot;
+  MacroDepth = 0;
+}
+
+void SetCurrentMacroData (char *name, int depth) {
+  MacroName = name;
+  MacroDepth = depth;
+}
+
+char *GetMacroName () {
+  return (MacroName);
+}
+
+int GetMacroDepth () {
+  return (MacroDepth);
+}
+
+Macro *NewMacro (char *name) {
+  
+  macros[Nmacros].name = strcreate (name);;
+  macros[Nmacros].Nlines = 0;
+  ALLOCATE (macros[Nmacros].line, char *, 1);
+  Nmacros ++;
+  if (Nmacros == NMACROS) {
+    NMACROS += 20;
+    REALLOCATE (macros, Macro, NMACROS);
+  }
+  return (&macros[Nmacros-1]);
+}
+
+void ListMacro (Macro *macro) {
+
+  int i;
+
+  if ((macro == NULL) || (macro[0].Nlines == 0)) {
+    fprintf (stderr, "  macro not defined\n");
+    return;
+  }
+  for (i = 0; i < macro[0].Nlines; i++) {
+    fprintf (stderr, "%s\n", macro[0].line[i]);
+  }
+  return;
+}
+
+void FreeMacro (Macro *macro) {
+  
+  int i;
+
+  if (macro == NULL) return;
+
+  for (i = 0; i < macro[0].Nlines; i++) {
+    free (macro[0].line[i]);
+  }
+  free (macro[0].line);
+  free (macro[0].name);
+  return;
+}
+
+int DeleteMacro (Macro *macro) {
+
+  int i, Nm;
+
+  Nm = -1;
+  for (i = 0; i < Nmacros; i++) {
+    if (macro == &macros[i]) {
+      Nm = i;
+      break;
+    }
+  }
+  if (Nm == -1) {
+    fprintf (stderr, "programming error: macro not found\n");
+    return (FALSE);
+  }
+
+  FreeMacro (&macros[Nm]);
+  for (i = Nm + 1; i < Nmacros; i++)
+    macros[i - 1] = macros[i];
+  Nmacros --;
+  return (TRUE);
+}
+
+/* return macro which unambiguously matches name */
+Macro *MatchMacro (char *name, int VERBOSE, int EXACT) {
+
+  int i, match[10], Nmatch;
+
+  /* try for an exact match first */
+  for (i = 0; i < Nmacros; i++) {
+    if (!strcmp (macros[i].name, name)) {
+      return (&macros[i]);
+    }
+  }
+  if (EXACT) {
+    if (VERBOSE) fprintf (stderr, "no exact match to %s\n", name);
+    return (NULL);
+  }
+      
+  /* not found as complete macro, try partial */
+  Nmatch = 0;
+  for (i = 0; (Nmatch < 10) && (i < Nmacros); i++) {
+    if (!strncmp (macros[i].name, name, strlen(name))) {  /* found a macro */
+      match[Nmatch] = i;
+      Nmatch ++;
+    }
+  }
+  if (Nmatch == 1) return (&macros[match[0]]);
+
+  if (Nmatch > 1) {
+    if (VERBOSE) {
+      fprintf (stderr, "ambiguous macro: %s ( ", name);
+      for (i = 0; i < Nmatch; i++) {
+	fprintf (stderr, "%s ", macros[match[i]].name);
+      }
+      fprintf (stderr, ")\n");
+    }
+    return (NULL);
+  }
+  if (VERBOSE) fprintf (stderr, "%s: Macro not found.\n", name);
+  return (NULL);
+}  
+
Index: /tags/start/Ohana/src/opihi/lib.shell/Makefile
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/Makefile	(revision 12606)
@@ -0,0 +1,118 @@
+include ../../../Configure
+
+HOME    =       $(ROOT)/src/opihi.v2
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+MDIR    =       $(HOME)/misc
+SDIR    =       $(HOME)/lib.shell
+#
+DESTBIN =       $(LBIN)
+DESTLIB =       $(LLIB)
+DESTINC =       $(LINC)
+DESTMAN =       $(LMAN)
+HELP    =       $(HOME)/help
+#  
+INCS    =       -I$(INC) -I$(LINC) -I$(XINC)
+LFLAGS  =       -L$(LLIB) -L$(LIB)
+LIBS    =       -lFITS -lsocket -lnsl -lreadline -ltermcap -lohana -lm
+CFLAGS  =       $(INCS)
+CCFLAGS =       $(LIBS) 
+
+# opihi shell functions (libopihi) ########################
+
+shell = \
+$(SDIR)/ConfigInit.$(ARCH).o		\
+$(SDIR)/ListOps.$(ARCH).o	   	\
+$(SDIR)/command.$(ARCH).o               \
+$(SDIR)/CommandOps.$(ARCH).o		\
+$(SDIR)/errors.$(ARCH).o		\
+$(SDIR)/expand_vars.$(ARCH).o           \
+$(SDIR)/expand_vectors.$(ARCH).o        \
+$(SDIR)/exec_loop.$(ARCH).o             \
+$(SDIR)/interrupt.$(ARCH).o	        \
+$(SDIR)/MacroOps.$(ARCH).o		\
+$(SDIR)/macro_create.$(ARCH).o          \
+$(SDIR)/macro_delete.$(ARCH).o          \
+$(SDIR)/macro_edit.$(ARCH).o            \
+$(SDIR)/macro_exec.$(ARCH).o            \
+$(SDIR)/macro_list.$(ARCH).o            \
+$(SDIR)/macro_read.$(ARCH).o            \
+$(SDIR)/macro_write.$(ARCH).o		\
+$(SDIR)/multicommand.$(ARCH).o          \
+$(SDIR)/parse.$(ARCH).o                 \
+$(SDIR)/parse_commands.$(ARCH).o	\
+$(SDIR)/startup.$(ARCH).o		\
+$(SDIR)/string.$(ARCH).o                \
+$(SDIR)/timeformat.$(ARCH).o            \
+$(SDIR)/BufferOps.$(ARCH).o             \
+$(SDIR)/VectorOps.$(ARCH).o             \
+$(SDIR)/check_stack.$(ARCH).o           \
+$(SDIR)/convert_to_RPN.$(ARCH).o	\
+$(SDIR)/evaluate_stack.$(ARCH).o  	\
+$(SDIR)/isolate_elements.$(ARCH).o 	\
+$(SDIR)/dvomath.$(ARCH).o               \
+$(SDIR)/stack_math.$(ARCH).o		\
+$(SDIR)/queues.$(ARCH).o		\
+$(SDIR)/variable.$(ARCH).o	   	\
+$(SDIR)/opihi.$(ARCH).o
+
+libshell:    $(DESTLIB)/libshell.a 
+
+$(LIB)/libshell.$(ARCH).a:   	$(shell)
+
+# dependancy rules for include files ########################
+baseinc = $(INC)/external.h $(INC)/shell.h $(INC)/dvomath.h $(INC)/convert.h $(INC)/display.h 
+
+$(shell)   	 : $(INC)/opihi.h $(baseinc)
+
+# utilities #################################################
+$(BIN)/%.$(ARCH):
+	@if [ ! -d $(BIN) ]; then mkdir -p $(BIN); fi
+	$(CC) $^ -o $@ $(LFLAGS) $(LIBS)
+	@echo "compiled $*"
+	@echo ""
+
+$(DESTBIN)/%: $(BIN)/%.$(ARCH) 
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	rm -f $(DESTBIN)/$*
+	cp $(BIN)/$*.$(ARCH) $(DESTBIN)/$*
+	@echo "installed $*"
+	@echo ""
+
+$(LIB)/%.$(ARCH).a:
+	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
+	rm -f $@
+	ar rcv $@ $^ 
+	ranlib $@
+	@echo "compiled library $*"
+	@echo ""
+
+$(DESTLIB)/%.a: $(LIB)/%.$(ARCH).a
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	@echo ""
+	rm -f $@
+	cp $^ $@
+
+lib%.clean:
+	rm -f $(LIB)/lib$*.$(ARCH).a
+	rm -f $($*)
+	@echo ""
+
+%.clean:
+	rm -f $(BIN)/$*.$(ARCH)
+	@echo ""
+
+%.$(ARCH).o : %.c
+	$(CC) $(CFLAGS) -c $*.c -o $@
+
+clean:
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f $(LIB)/*.$(ARCH).a
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+dist: clean
+	rm -f $(BIN)/*
+	rm -f $(LIB)/*
Index: /tags/start/Ohana/src/opihi/lib.shell/VectorOps.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/VectorOps.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/VectorOps.c	(revision 12606)
@@ -0,0 +1,162 @@
+# include "opihi.h"
+
+static Vector **vectors;
+static int     Nvectors;
+  
+void InitVectors () {
+  Nvectors = 0;
+  ALLOCATE (vectors, Vector *, 1);
+}
+
+Vector *InitVector () {
+  Vector *vec;
+
+  ALLOCATE (vec, Vector, 1);
+  ALLOCATE (vec[0].elements, float, 1);
+  bzero (vec[0].name, 1024);
+  vec[0].Nelements = 0;
+  return (vec);
+}
+
+int IsVector (char *name) {
+ 
+  int i;
+
+  if (name == NULL) return (FALSE);
+
+  for (i = 0; (i < Nvectors) && (strcmp(vectors[i][0].name, name)); i++);
+  if (i == Nvectors) return (FALSE);
+  return (TRUE);
+}
+
+int IsVectorPtr (Vector *vec) {
+ 
+  int i;
+
+  if (vec == NULL) return (FALSE);
+
+  for (i = 0; (i < Nvectors) && (vectors[i] != vec); i++);
+  if (i == Nvectors) return (FALSE);
+  return (TRUE);
+}
+
+Vector *SelectVector (char *name, int mode, int verbose) {
+
+  int i;
+
+  if (name == NULL) goto error;
+  if (ISNUM(name[0])) goto error;
+  if (IsBuffer(name)) goto error;
+
+  for (i = 0; (i < Nvectors) && (strcmp(vectors[i][0].name, name)); i++);
+  /* is a new vector */
+  if (i == Nvectors) { 
+    if (mode == OLDVECTOR) goto error;
+    Nvectors += 1;
+    REALLOCATE (vectors, Vector *, Nvectors);
+    vectors[i] = InitVector ();
+    strcpy (vectors[i][0].name, name);
+    return (vectors[i]);
+  } 
+  /* is an old vector */
+  if (mode == NEWVECTOR) goto error;
+  return (vectors[i]);
+
+ error:
+  if (verbose) fprintf (stderr, "invalid vector %s\n", name);
+  return (NULL);
+}
+  
+/* delete by pointer */
+int DeleteVector (Vector *vec) {
+
+  int i, j;
+
+  if (vec == NULL) return (FALSE);
+
+  for (i = 0; (i < Nvectors) && (vec != vectors[i]); i++);
+  if (i == Nvectors) return (FALSE);
+
+  free (vectors[i][0].elements);
+  for (j = i; j < Nvectors - 1; j++) vectors[j] = vectors[j + 1];
+
+  Nvectors -= 1;
+  REALLOCATE (vectors, Vector *, MAX (Nvectors, 1));
+  return (TRUE);
+}
+  
+/* delete by name */
+int DeleteNamedVector (char *name) {
+
+  int i, j;
+
+  if (name == NULL) return (FALSE);
+  for (i = 0; (i < Nvectors) && (strcmp(vectors[i][0].name, name)); i++);
+  if (i == Nvectors) return (FALSE);
+
+  free (vectors[i][0].elements);
+  for (j = i; j < Nvectors - 1; j++) vectors[j] = vectors[j + 1];
+
+  Nvectors -= 1;
+  REALLOCATE (vectors, Vector *, MAX (Nvectors, 1));
+  return (TRUE);
+}
+
+/* copy data from in to out - new memory space */
+int CopyNamedVector (char *out, char *in) {
+  Vector *In, *Out;
+  if ((In  = SelectVector (in,  OLDVECTOR, FALSE)) == NULL) return (FALSE);
+  if ((Out = SelectVector (out, ANYVECTOR, FALSE)) == NULL) return (FALSE);
+  CopyVector (Out, In);
+  return (TRUE);
+}
+int CopyVector (Vector *out, Vector *in) {
+  free (out[0].elements);
+  out[0].Nelements = in[0].Nelements;
+  ALLOCATE (out[0].elements, float, out[0].Nelements);
+  memcpy (out[0].elements, in[0].elements, out[0].Nelements*sizeof(float));
+  return (TRUE);
+}
+
+/* move data from in to out - use old memory space */
+int MoveNamedVector (char *out, char *in) {
+  Vector *In, *Out;
+  if ((In  = SelectVector (in,  OLDVECTOR, FALSE)) == NULL) return (FALSE);
+  if ((Out = SelectVector (out, ANYVECTOR, FALSE)) == NULL) return (FALSE);
+  MoveVector (Out, In);
+  return (TRUE);
+}
+int MoveVector (Vector *out, Vector *in) {
+  int i, j;
+
+  free (out[0].elements);
+  out[0].Nelements = in[0].Nelements;
+  out[0].elements =  in[0].elements;
+
+  /* delete vector entry from vector list, if it exists */
+  for (i = 0; (i < Nvectors) && (in != vectors[i]); i++);
+  if (i == Nvectors) return (TRUE);
+
+  for (j = i; j < Nvectors - 1; j++) vectors[j] = vectors[j + 1];
+  Nvectors -= 1;
+  REALLOCATE (vectors, Vector *, MAX (Nvectors, 1));
+  return (TRUE);
+}
+
+int ListVectors () {
+
+  int i;
+
+  if (Nvectors == 0) {
+    fprintf (stderr, "No defined vectors\n");
+    return (FALSE);
+  }
+
+  fprintf (GetOutfile(), "    N       name      size\n");
+  for (i = 0; i < Nvectors; i++) {
+    fprintf (GetOutfile(), "%5d %10s %10d\n",
+	     i, vectors[i][0].name, vectors[i][0].Nelements);
+  }
+  return (TRUE);
+}
+  
Index: /tags/start/Ohana/src/opihi/lib.shell/check_stack.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/check_stack.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/check_stack.c	(revision 12606)
@@ -0,0 +1,69 @@
+# include "opihi.h"
+
+int check_stack (StackVar *stack, int Nstack) {
+
+  int i, Nx, Ny, Nv;
+  char *c, line[128];
+
+  Nv = Nx = -1;
+
+  for (i = 0; i < Nstack; i++) {
+    if (stack[i].type == 'X') {
+      /** if this is a number, put it on the list of scalers and move on **/
+      stack[i].Float = strtod (stack[i].name, &c);
+      if (c == stack[i].name + strlen (stack[i].name)) {
+	stack[i].ptr   = &(stack[i].Float);
+	stack[i].type  = 'S';
+	continue;
+      } 
+      /** if this is a matrix, find the dimensions and check with existing values **/
+      if (IsBuffer (stack[i].name)) {
+	stack[i].buffer = SelectBuffer (stack[i].name, OLDBUFFER, TRUE);
+	stack[i].ptr    = (float *) stack[i].buffer[0].matrix.buffer;
+	stack[i].type   = 'M';
+	if (Nx == -1) {
+	  Nx = stack[i].buffer[0].matrix.Naxis[0];
+	  Ny = stack[i].buffer[0].matrix.Naxis[1];
+	} 
+	if ((Nx != stack[i].buffer[0].matrix.Naxis[0]) && (Ny != stack[i].buffer[0].matrix.Naxis[1])) {
+	  push_error ("dimensions don't match");
+	  return (-1);
+	}	
+	if (Nv != -1) {
+	  if ((Nv != Nx) && (Nv != Ny)) {
+	    push_error ("dimensions don't match");
+	    return (-1);
+	  }
+	}	
+	continue;
+      }
+      /** if this is a vector, find the dimensions and check with existing values **/
+      if (IsVector (stack[i].name)) {
+	stack[i].vector = SelectVector (stack[i].name, OLDVECTOR, FALSE);
+	stack[i].ptr    = (float *) stack[i].vector[0].elements;
+	stack[i].type   = 'V';
+
+	if (Nv == -1) Nv = stack[i].vector[0].Nelements;
+	if (Nv != stack[i].vector[0].Nelements) {
+	  push_error ("dimensions don't match");
+	  return (-1);
+	}
+	if (Nx != -1) {
+	  if ((Nx != Nv) && (Ny != Nv)) {
+	    push_error ("dimensions don't match");
+	    return (-1);
+	  }
+	}	
+	continue;
+      }
+      sprintf (line, "unknown object %s", stack[i].name);
+      push_error (line);
+      return (-1);
+    }
+  }
+
+  /* we return a value which is 1 greater than the object dimension */
+  if (Nx != -1) return (2);
+  if (Nv != -1) return (1);
+  return (0);
+}
Index: /tags/start/Ohana/src/opihi/lib.shell/command.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/command.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/command.c	(revision 12606)
@@ -0,0 +1,70 @@
+# include "opihi.h"
+
+int command (char *line, char **outline) {
+
+  int i, status, argc, targc;
+  char **argv, **targv;
+  Command *cmd;
+
+  /* force a space between ! and first word: !ls becomes ! ls */
+  if (line[0] == '!') {
+    REALLOCATE (line, char, strlen(line) + 5);
+    memmove (&line[2], &line[1], strlen(&line[1]) + 1);
+    line[1] = ' ';
+  }
+
+  /* expand anything of the form $fred or $fred$sam, etc */ 
+  line = expand_vars (line);     /* line is freed here, new one allocated */
+  /* expand anything of the form fred[N] */ 
+  line = expand_vectors (line);  /* line is freed here, new one allocated */
+  /* solve math expresions, assign variable, if needed */
+  line = parse (line);        /* line is freed here, new one allocated */
+  /* any entry in line of the form {foo} returns value or tmp vector / buffer */
+  
+  targv = parse_commands (line, &targc);
+  if (targc == 0) {
+    /* empty command or assignment */
+    if (line != (char *) NULL) free (line);
+    *outline = (char *) NULL;
+    return (TRUE);
+  }
+
+  /* this needs some work to use multicommand correctly */
+  ALLOCATE (argv, char *, targc);
+  argc = 0;
+  status = TRUE;
+  for (i = 0; status && (i < targc); i++) {
+    if (targv[i][0] != ';') {
+      argv[argc] = targv[i];
+      argc ++;
+    }
+    if ((targv[i][0] == ';') || (i == targc - 1)) {
+
+      if (argc == 0) continue;
+
+      cmd = MatchCommand (argv[0], TRUE, FALSE);
+      if (cmd != NULL) {
+	REALLOCATE (argv[0], char, strlen(cmd[0].name) + 1);
+	strcpy (argv[0], cmd[0].name);
+	status &= (*cmd[0].func) (argc, argv);
+	if (auto_break && !status) break;
+      }
+      argc = 0;
+    }
+  }
+  for (i = 0; i < targc; i++) free (targv[i]);
+  free (argv);
+  free (targv);
+  *outline = line;
+  if (!status) {
+    char *msg;
+    msg = get_variable ("ERRORMSG");
+    if (msg != (char *) NULL) {
+      fprintf (stderr, "%s\n", msg);
+      free (msg);
+    }
+  }
+  set_int_variable ("STATUS", status);
+  return (status);
+
+}
Index: /tags/start/Ohana/src/opihi/lib.shell/convert_to_RPN.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/convert_to_RPN.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/convert_to_RPN.c	(revision 12606)
@@ -0,0 +1,202 @@
+# include "opihi.h"
+/* # define DUMPSTACK * for tests */
+
+StackVar *convert_to_RPN (int argc, char **argv, int *nstack) {
+  
+  int type, Nx, Ny;
+  int i, j, Nstack, Nop_stack, NSTACK;
+  StackVar *stack, *op_stack;
+
+  /* max total stack size is argc, though should be less, this is safe */
+  NSTACK = argc + 5;
+  ALLOCATE (stack, StackVar, NSTACK);
+  ALLOCATE (op_stack, StackVar, NSTACK);
+  for (i = 0; i < NSTACK; i++) {
+    init_stack (&stack[i]);
+    init_stack (&op_stack[i]);
+  }
+  
+  Nx = Ny = Nstack = Nop_stack = 0;
+  for (i = 0; i < argc; i++) {
+    
+    /* decide on priority of object */
+    type = 0;
+    /* unary operations */
+    if (!strcmp (argv[i], "abs"))   { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "int"))   { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "exp"))   { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "ten"))   { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "log"))   { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "ln"))    { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "sqrt"))  { type = 7; goto gotit; }
+
+    if (!strcmp (argv[i], "sinh"))   { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "cosh"))   { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "asinh"))  { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "acosh"))  { type = 7; goto gotit; }
+
+    if (!strcmp (argv[i], "sin"))   { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "cos"))   { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "tan"))   { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "dsin"))  { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "dcos"))  { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "dtan"))  { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "asin"))  { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "acos"))  { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "atan"))  { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "dasin")) { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "dacos")) { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "datan")) { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "rnd"))   { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "xramp")) { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "yramp")) { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "ramp"))  { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "zero"))  { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "--"))    { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "not"))   { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "isinf")) { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "isnan")) { type = 7; goto gotit; }
+
+    /* binary operations */
+    if (!strcmp (argv[i], "^"))     { type = 6; goto gotit; }
+
+    if (!strcmp (argv[i], "<"))     { type = 5; goto gotit; }
+    if (!strcmp (argv[i], ">"))     { type = 5; goto gotit; }
+    if (!strcmp (argv[i], "&&"))    { type = 5; strcpy (argv[i], "A"); goto gotit; }
+    if (!strcmp (argv[i], "||"))    { type = 5; strcpy (argv[i], "O"); goto gotit; }
+    if (!strcmp (argv[i], "=="))    { type = 5; strcpy (argv[i], "E"); goto gotit; }
+    if (!strcmp (argv[i], "!="))    { type = 5; strcpy (argv[i], "N"); goto gotit; }
+    if (!strcmp (argv[i], "<="))    { type = 5; strcpy (argv[i], "L"); goto gotit; }
+    if (!strcmp (argv[i], ">="))    { type = 5; strcpy (argv[i], "G"); goto gotit; }
+    if (!strcmp (argv[i], ">>"))    { type = 5; strcpy (argv[i], "U"); goto gotit; }
+    if (!strcmp (argv[i], "<<"))    { type = 5; strcpy (argv[i], "D"); goto gotit; }
+
+    if (!strcmp (argv[i], "&"))     { type = 5; goto gotit; }
+    if (!strcmp (argv[i], "|"))     { type = 5; goto gotit; }
+
+    if (!strcmp (argv[i], "/"))     { type = 4; goto gotit; }
+    if (!strcmp (argv[i], "*"))     { type = 4; goto gotit; }
+
+    if (!strcmp (argv[i], "+"))     { type = 3; goto gotit; }
+    if (!strcmp (argv[i], "-"))     { type = 3; goto gotit; }
+	
+    if (!strcmp (argv[i], "("))     { type = 2; goto gotit; }
+    if (!strcmp (argv[i], ")"))     { type = 1; goto gotit; }
+
+  gotit:
+    /* choose how to deal with object */
+    switch (type) {
+    case 6:  /* unary OPs */
+      /* pop previous, higher operators from OP stack to stack */
+      for (j = Nop_stack - 1; (j >= 0) && (op_stack[j].type > type); j--) {
+	strcpy (stack[Nstack].name, op_stack[j].name);
+	stack[Nstack].type = op_stack[j].type;
+	Nstack ++;
+	Nop_stack --;
+      }
+      /* push operator on OP stack */
+      strcpy (op_stack[Nop_stack].name, argv[i]);
+      op_stack[Nop_stack].type = type;
+      Nop_stack ++;
+      break;
+    case 7: /* binary OPs */
+    case 5: /* binary OPs */
+    case 4: 
+    case 3: 
+      /* pop previous, higher or equal operators from OP stack to stack */
+      for (j = Nop_stack - 1; (j >= 0) && (op_stack[j].type >= type); j--) {
+	strcpy (stack[Nstack].name, op_stack[j].name);
+	stack[Nstack].type = op_stack[j].type;
+	Nstack ++;
+	Nop_stack --;
+      }
+      /* push operator on OP stack */
+      strcpy (op_stack[Nop_stack].name, argv[i]);
+      op_stack[Nop_stack].type = type;
+      Nop_stack ++;
+      break;
+    case 2:  
+      /* push operator on OP stack */
+      strcpy (op_stack[Nop_stack].name, argv[i]);
+      op_stack[Nop_stack].type = type;
+      Nop_stack ++;
+      break;
+    case 1: 
+      /* pop rest of operators from OP stack to stack, looking for '(' */
+      for (j = Nop_stack - 1; (j >= 0) && (op_stack[j].type != 2); j--) {
+	strcpy (stack[Nstack].name, op_stack[j].name);
+	stack[Nstack].type = op_stack[j].type;
+	Nstack ++;
+	Nop_stack --;
+      }
+      if ((j == -1) || (op_stack[j].type != 2)) {
+	push_error ("syntax error: mismatched parenthesis");
+	Nstack = 0;
+	goto cleanup;
+      }
+      Nop_stack --;
+      break;
+    case 0:
+      /* place the value (number or vector/matrix name) on stack */
+      /* value of 'X' is used as sentinel until we sort out values */
+      strcpy (stack[Nstack].name, argv[i]);
+      stack[Nstack].type = 'X';
+      Nstack ++;
+      break;
+    }
+  }
+
+  /* dump remaining operators on stack, checking for ')' */
+  for (j = Nop_stack - 1; j >= 0; j--) {
+    if (op_stack[j].type == 2) {
+      push_error ("syntax error: mismatched parenthesis");
+      Nstack = 0;
+      goto cleanup;
+    }
+    strcpy (stack[Nstack].name, op_stack[j].name);
+    stack[Nstack].type = op_stack[j].type;
+    Nstack ++;
+  }
+
+cleanup: 
+  /*** free up unused stack space ***/
+  clean_stack (op_stack, NSTACK);
+  free (op_stack);
+  clean_stack (&stack[Nstack], NSTACK - Nstack);
+  REALLOCATE (stack, StackVar, MAX (Nstack, 1));
+  *nstack = Nstack;
+
+  for (i = 0; i < argc; i++) {
+    free (argv[i]);
+  }
+  free (argv);
+
+#ifdef DUMPSTACK
+  for (i = 0; i < Nstack; i++) {
+    fprintf (stderr, "%s ", stack[i].name);
+  }
+  if (Nstack > 0) fprintf (stderr, "\n");
+  for (i = 0; i < Nstack; i++) {
+    fprintf (stderr, "%d ", stack[i].type);
+  }
+  if (Nstack > 0) fprintf (stderr, "\n");
+#endif
+
+  return (stack);
+
+}
+
+/* here are the rules for parsing a math AOL line to RPN:
+
+   1) if object is a number, push on stack
+   2) if object is a third order operand (exp, sin, cos), push on op stack
+   3) if object is an open paren, push on op stack,
+   4) if object is a second order operand, push on stack
+   5) if object is a first order operand, pop all second order operands from stack 
+   until paren, push on stack
+   6) if object is an end paren, pop all objects from stack until paren, 
+   pop next stack, if third order op
+   7) if end of line, pop all remaining objects, second order first, etc.
+   
+*/
+
Index: /tags/start/Ohana/src/opihi/lib.shell/dvomath.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/dvomath.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/dvomath.c	(revision 12606)
@@ -0,0 +1,89 @@
+# include "opihi.h"
+
+/* return value on success is temp vector/buffer name or scalar value
+   return value on error is NULL, all internals freed? */
+
+char *dvomath (int argc, char **argv, int *size, int validsize) {
+  
+  int  i, Nstack, Ncstack;
+  char   **cstack, *outname;
+  StackVar *stack;
+  Buffer *buf;
+  Vector *vec;
+
+  ALLOCATE (outname, char, 256);
+
+  /* take char array with expression, convert to important elements */
+  cstack = isolate_elements (argc, argv, &Ncstack); 
+
+  /* generate RPN stack from cstack arguments */
+  stack = convert_to_RPN (Ncstack, cstack, &Nstack);
+  if (Nstack < 1) goto error;
+
+  /* distinguish scalar, vector, matrix, check dimensions */
+  *size = check_stack (stack, Nstack);
+  if ((validsize != -1) && (validsize != *size)) goto error;
+  if (*size < 0) goto error;
+
+  switch (*size) {
+    case 0:
+      break;
+    case 1:  /* allocate temp vector */
+      vec = NULL;
+      for (i = 0; (i < 1000) && (vec == NULL); i++) {
+	sprintf (outname, "tmp%03d", i);
+	vec = SelectVector (outname, NEWVECTOR, FALSE);
+      }
+      if (vec == NULL) { 
+	push_error ("too many tmp vectors");
+	goto error;
+      }
+      break;
+    case 2:  /* allocate temp buffer */
+      buf = NULL;
+      for (i = 0; (i < 1000) && (buf == NULL); i++) {
+	sprintf (outname, "tmp%03d", i);
+	buf = SelectBuffer (outname, NEWBUFFER, FALSE);
+      }
+      if (buf == NULL) {
+	push_error ("too many tmp buffers");
+	goto error;
+      }
+      break;
+    default:
+      goto error;
+  }
+
+  /* evaluate operations, free stack on error */
+  if (!evaluate_stack (stack, &Nstack)) {
+    if (*size == 1) DeleteVector (vec);
+    if (*size == 2) DeleteBuffer (buf);
+    goto error;
+  }
+
+  switch (*size) {
+    case 0:
+      sprintf (outname, "%g", stack[0].Float);
+      break;
+
+    case 1:
+      MoveVector (vec, stack[0].vector);
+      free (stack[0].vector);
+      break;
+  
+    case 2:
+      MoveBuffer (buf, stack[0].buffer);
+      free (stack[0].buffer);
+      break;
+  }
+
+  clean_stack (stack, Nstack);
+  free (stack);
+  return (outname);
+
+error:  
+  clean_stack (stack, Nstack);
+  free (stack);
+  free (outname);
+  return (NULL);
+}
Index: /tags/start/Ohana/src/opihi/lib.shell/errors.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/errors.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/errors.c	(revision 12606)
@@ -0,0 +1,16 @@
+# include "opihi.h"
+
+static char errorline[1024];
+
+int push_error (char *line) {
+
+  bzero (errorline, 1024);
+  strncpy (errorline, line, 1023);
+  return (TRUE);
+}
+
+int print_error () {
+
+  fprintf (stderr, "%s\n", errorline);
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/lib.shell/evaluate_stack.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/evaluate_stack.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/evaluate_stack.c	(revision 12606)
@@ -0,0 +1,183 @@
+# include "opihi.h"
+# define VERBOSE 0
+
+int evaluate_stack (StackVar *stack, int *Nstack) {
+  
+  int i, j, Nvar, Nout, status;
+  StackVar tmp_stack;
+  Nout = Nvar = 0;
+
+  init_stack (&tmp_stack);
+
+  if (*Nstack == 1) {
+    if (stack[0].type == 'S') {
+      S_unary (&tmp_stack, &stack[0], "=");
+      move_stack (&stack[0], &tmp_stack);
+      return (TRUE);
+    }
+    if (stack[0].type == 'V') {
+      V_unary (&tmp_stack, &stack[0], "=");
+      move_stack (&stack[0], &tmp_stack);
+      return (TRUE);
+    }
+    if (stack[0].type == 'M') {
+      M_unary (&tmp_stack, &stack[0], "=");
+      move_stack (&stack[0], &tmp_stack);
+      return (TRUE);
+    }
+    fprintf (stderr, "syntax error!\n");
+    free (tmp_stack.name);
+    return (FALSE);
+  }      
+    
+  for (i = 0; i < *Nstack; i++) {
+
+    if (VERBOSE) {
+      fprintf (stderr, "%d: ", i);
+      for (j = 0; j < *Nstack; j++) {
+	fprintf (stderr, "%s ", stack[j].name);
+      }
+      if (*Nstack > 0) fprintf (stderr, "\n");
+      fprintf (stderr, "%d: ", i);
+      for (j = 0; j < *Nstack; j++) {
+	fprintf (stderr, "%d ", stack[j].type);
+      }
+      if (*Nstack > 0) fprintf (stderr, "\n");
+    }
+
+    /***** binary operators *****/
+    if ((stack[i].type == 3) || (stack[i].type == 4) || (stack[i].type == 5) || (stack[i].type == 6)) {
+
+      if (i < 2) {  /* need two variables to operate on */
+	fprintf (stderr, "syntax error\n");
+	free (tmp_stack.name); 
+	return (FALSE);
+      }
+      if (!strncasecmp (&stack[i - 2].type, "V", 1) && !strncasecmp (&stack[i - 1].type, "V", 1)) 
+	status = VV_binary (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name);
+      if (!strncasecmp (&stack[i - 2].type, "V", 1) && !strncasecmp (&stack[i - 1].type, "S", 1)) 
+	status = VS_binary (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name);
+      if (!strncasecmp (&stack[i - 2].type, "S", 1) && !strncasecmp (&stack[i - 1].type, "V", 1)) 
+	status = SV_binary (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name);
+      if (!strncasecmp (&stack[i - 2].type, "M", 1) && !strncasecmp (&stack[i - 1].type, "V", 1)) 
+	status = MV_binary (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name);
+      if (!strncasecmp (&stack[i - 2].type, "V", 1) && !strncasecmp (&stack[i - 1].type, "M", 1)) 
+	status = VM_binary (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name);
+      if (!strncasecmp (&stack[i - 2].type, "M", 1) && !strncasecmp (&stack[i - 1].type, "M", 1)) 
+	status = MM_binary (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name);
+      if (!strncasecmp (&stack[i - 2].type, "M", 1) && !strncasecmp (&stack[i - 1].type, "S", 1)) 
+	status = MS_binary (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name);
+      if (!strncasecmp (&stack[i - 2].type, "S", 1) && !strncasecmp (&stack[i - 1].type, "M", 1)) 
+	status = SM_binary (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name);
+      if (!strncasecmp (&stack[i - 2].type, "S", 1) && !strncasecmp (&stack[i - 1].type, "S", 1)) 
+	status = SS_binary (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name);
+      if (!status) {
+	free (tmp_stack.name);
+	return (FALSE);
+      }
+      move_stack (&stack[i-2], &tmp_stack);
+      delete_stack (&stack[i-1], 2);
+      for (j = i + 1; j < *Nstack; j++) {
+	copy_stack (&stack[j - 2], &stack[j]);
+      }
+      *Nstack -= 2;
+      i -= 2;
+      init_stack (&tmp_stack);
+      continue;
+    }
+
+    /***** unary operators **/
+    if (stack[i].type == 7) {
+
+      if (i < 1) {  /* need one variable to operate on */
+	fprintf (stderr, "syntax error\n");
+	free (tmp_stack.name);
+	return (FALSE);
+      }
+      
+      if (!strncasecmp (&stack[i - 1].type, "M", 1)) 
+	M_unary (&tmp_stack, &stack[i - 1], stack[i].name);
+      if (!strncasecmp (&stack[i - 1].type, "V", 1)) 
+	V_unary (&tmp_stack, &stack[i - 1], stack[i].name);
+      if (!strncasecmp (&stack[i - 1].type, "S", 1)) 
+	S_unary (&tmp_stack, &stack[i - 1], stack[i].name);
+
+      move_stack (&stack[i-1], &tmp_stack);
+      delete_stack (&stack[i], 1);
+      for (j = i + 1; j < *Nstack; j++) {
+	copy_stack (&stack[j - 1], &stack[j]);
+      }
+      init_stack (&tmp_stack);
+      *Nstack -= 1;
+      i -= 1;
+      continue;
+    } 
+  }
+  free (tmp_stack.name);
+
+  if (*Nstack > 1) {
+    fprintf (stderr, "syntax error\n");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+/* copy data to new stack variable */
+void copy_stack (StackVar *stack1, StackVar *stack2) {
+  stack1[0].name   = stack2[0].name  ;
+  stack1[0].type   = stack2[0].type  ;
+  stack1[0].ptr    = stack2[0].ptr   ;
+  stack1[0].buffer = stack2[0].buffer;
+  stack1[0].vector = stack2[0].vector;
+  stack1[0].Float  = stack2[0].Float ;
+  if (!strncasecmp (&stack1[0].type, "S", 1)) {
+    stack1[0].ptr    = &stack1[0].Float;
+  }
+}
+
+/* replace data with new stack variable */
+void move_stack (StackVar *stack1, StackVar *stack2) {
+  if (stack1[0].name != (char *) NULL) 
+    free (stack1[0].name);
+  copy_stack (stack1, stack2);
+}
+
+/* delete name and data */
+void clean_stack (StackVar *stack, int Nstack) {
+
+  int i;
+
+  for (i = 0; i < Nstack; i++) {
+    if (IsBufferPtr (stack[i].buffer) && (stack[i].type == 'm')) {
+      if (VERBOSE) fprintf (stderr, "free %s (buff) (%x)\n", stack[i].name, (int) stack[i].buffer);
+      free (stack[i].buffer[0].header.buffer);
+      free (stack[i].buffer[0].matrix.buffer);
+      free (stack[i].buffer);
+      stack[i].buffer = NULL;
+    }	
+    if (IsVectorPtr (stack[i].vector) && (stack[i].type == 'v')) {
+      if (VERBOSE) fprintf (stderr, "free %s (vect) (%x)\n", stack[i].name, (int) stack[i].vector);
+      free (stack[i].vector[0].elements);
+      free (stack[i].vector);
+      stack[i].vector = NULL;
+    }	
+    if (VERBOSE) fprintf (stderr, "free %s (name) (%d) (%x)\n", stack[i].name, i, (int) stack[i].name);
+    free (stack[i].name);
+    stack[i].name = NULL;
+  }
+
+}
+
+/* delete name only, not data */
+void delete_stack (StackVar *stack, int Nstack) {
+  int i;
+  for (i = 0; i < Nstack; i++) {
+    free (stack[i].name);
+  }
+}
+
+void init_stack (StackVar *stack) {
+  stack[0].buffer = NULL;
+  stack[0].vector = NULL;
+  stack[0].name = strncreate ("tmp", NCHARS);
+}
Index: /tags/start/Ohana/src/opihi/lib.shell/exec_loop.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/exec_loop.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/exec_loop.c	(revision 12606)
@@ -0,0 +1,48 @@
+# include "opihi.h"
+
+int exec_loop (Macro *loop) {
+
+  int n, Nlines, j, status, ThisList, Signal;
+  char *outline;
+  
+  /* increase the shell level (Nlists) by one */
+  Nlists ++;
+  ThisList = Nlists;
+  REALLOCATE (lists, List, MAX (ThisList, 0) + 1);
+  
+  /* copy the macro to the current list */
+  lists[ThisList].Nlines = loop[0].Nlines;
+  ALLOCATE (lists[ThisList].line, char *, MAX (lists[ThisList].Nlines, 1));
+  for (j = 0; j < lists[ThisList].Nlines; j++) {
+    lists[ThisList].line[j] = strcreate (loop[0].line[j]);
+  }
+
+  /* set up interrupts */
+  Signal = (int) signal (SIGINT, handle_interrupt);
+  interrupt = FALSE;
+
+  /* process the list */
+  loop_continue = loop_break = FALSE;
+  status = TRUE;
+  Nlines = lists[ThisList].Nlines;
+  for (n = 0; (n < Nlines) && !interrupt; n++) {
+    lists[ThisList].n = n; 
+    status = command (lists[ThisList].line[n], &outline);
+    n = lists[ThisList].n;
+    Nlines = lists[ThisList].Nlines;
+    if (outline != NULL) free (outline);
+    if (auto_break && !status) loop_break = TRUE;
+    if (loop_break || loop_continue) break;
+  }
+  signal (SIGINT, (void *) Signal);
+
+  /* free up the list and decrement the shell level */
+  free (lists[ThisList].line);
+  Nlists --;
+  REALLOCATE (lists, List, MAX (Nlists, 0) + 1);
+
+  if (loop_break) return (FALSE);
+  return (TRUE);
+}
+
+/** note that the list number runs from 1 - Nlists+1 **/
Index: /tags/start/Ohana/src/opihi/lib.shell/expand_vars.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/expand_vars.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/expand_vars.c	(revision 12606)
@@ -0,0 +1,103 @@
+# include "opihi.h"
+
+char *expand_vars (char *line) {
+
+  char *L, *N, *V0, *V1, *Val, *newline, *c, found;
+  int done, MacroDepth;
+
+  if (line == NULL) return (NULL);
+  MacroDepth = GetMacroDepth ();
+
+  found = FALSE;
+  ALLOCATE (newline, char, 1024);  /* WARNING: this limits the length of the input line */
+
+  /* look for form $a$b..$n and expand only the last ones */
+  for (L = line, N = newline; *L != 0; N++, L++) {  /* loop until end of line */
+    for (done = FALSE; !done;) {
+      if (*L == 0) done = TRUE;
+      if (*L == '$') {
+	V1 = aftervar(L);
+	if ((V1 != NULL) && (*V1 != '$')) done = TRUE;
+	if (V1 == NULL) done = TRUE;
+      }
+      if (!done) { 
+	*N = *L;
+	 L++; 
+	 N++;
+      }
+    }
+
+    if (*L == 0) break;
+
+    V1 = aftervar (L);           /* V1 points to the first non-whitespace after the variable */
+    V0 = thisvar (L);            /* V0 points to the name of the var */
+    /* note: V1 points to a fraction of L, it does not need to be freed */
+
+    /* no variable name */
+    if (V0 == NULL) {
+      *N = *L;
+      continue;
+    }
+
+    /* variable assignment (skip these variables) */
+    if ((L == line) && (V1 != NULL)) {
+      if ((*V1 == '=') || !strcmp (V1, "++") || !strcmp (V1, "--")) {
+	*N = *L;
+	continue;
+      }
+    }
+
+    found = TRUE;
+    for (c = V0; isdigit(*c); c++); /* test if this is a macro argument variable (ie, $1.2) */
+    if (*c == 0) {  /* all digit var == macro parameter */
+      if (!MacroDepth) {
+	fprintf (stderr, "not in a macro\n");
+	goto error;
+      } else { /* if we are executing a macro, attach the list depth to the front, pass on down the line */
+	ALLOCATE (c, char, 1024);
+	sprintf (c, "%d.%s", MacroDepth, V0);
+	free (V0);
+	V0 = c;
+      }
+    }
+
+    Val = get_variable_ptr (V0);
+    if (Val == NULL) {   /* var was not found! */
+      fprintf (stderr, "variable %s not found\n", V0);
+      goto error;
+    }
+    for (; *Val != 0; N++, Val++)  {
+      *N = *Val; /* place the value of the variable in the newline */
+    }
+
+    for (N--,L++; ISVAR(*L); L++);
+    L--;
+
+    if (V0 != NULL) free (V0);
+  }
+
+  *N = 0;
+  free (line);
+  REALLOCATE (newline, char, strlen (newline) + 1);
+  if (found) { /* try again for new variables */
+    newline = expand_vars (newline);
+  }
+  return (newline);
+
+error:
+  free (line);
+  free (V0);
+  free (newline);
+  return (NULL);
+}
+
+
+  /************************
+    we go through the line looking for the dollar signs ($) marking the 
+    variables.  We don't expand a variable if it is the first thing on the line 
+    AND it is followed by an equals sign.  
+    that is, don't expand if:
+    V0 = NULL ($ is last non-blank char on line -- no variable) or
+    V1[0] is = (assignment of variable value), AND L == line (ie, at beginning of line)
+    *************************/
+
Index: /tags/start/Ohana/src/opihi/lib.shell/expand_vectors.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/expand_vectors.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/expand_vectors.c	(revision 12606)
@@ -0,0 +1,95 @@
+# include "opihi.h"
+
+char *expand_vectors (char *line) {
+
+  char *newline, *tmpline, *val;
+  char *L, *N, *p, *q, *w;
+  int n, I, size;
+  double f1;
+  Vector *vec;
+
+  if (line == NULL) return (NULL);
+
+  ALLOCATE (newline, char, 1024);  /* WARNING: this limits the length of the input line */
+  ALLOCATE (tmpline, char, 1024);  /* WARNING: this limits the length of the input line */
+
+  /* look for form fred[stuff] */
+  /* skip first word (command) */
+  L = nextword (line);
+  if (L == NULL) {
+    free (newline);
+    return (line);
+  }
+
+  n = L - line;
+  strncpy (newline, line, n);
+  N = newline + n;
+  while (1) {
+    /* find vector subscript */
+    p = strchr (L, '[');
+    q = strchr (L, ']');
+    if ((p == NULL) && (q != NULL)) goto dumpline;
+    if ((p != NULL) && (q == NULL)) goto dumpline;
+    if ((p == NULL) && (q == NULL)) goto dumpline;
+    if (p > q) goto dumpline; /* odd state: unmatched pair: ][ */
+    n = (int) (q - p - 1);
+    if (n == 0) {
+      ALLOCATE (val, char, 64);
+      sprintf (val, "-1");
+    } else {
+      strncpy (tmpline, p+1, n);
+      tmpline[n] = 0;
+      val = dvomath (1, &tmpline, &size, 0);
+      if (val == NULL) goto dumpline; /* not really a vector */
+    }
+    /* find vector name */
+    for (w = p - 1; (w >= line) && !whitespace(*w) && (isalnum(*w) || (*w == ':') || (*w == '_')); w--);
+    w ++;
+    n = (int)(p - w);
+    strncpy (tmpline, w, n);
+    tmpline[n] = 0;
+    if ((vec = SelectVector (tmpline, OLDVECTOR, TRUE)) == NULL) {
+      free (val);
+      goto dumpline;
+    }
+    /* find vector element */
+    I = atoi (val);
+    free (val);
+    if (I >= vec[0].Nelements) {
+      fprintf (stderr, "vector subscript out of range\n"); 
+      goto escape;
+    }
+    if (I < 0) {
+      f1 = vec[0].Nelements;
+    } else {
+      f1 = vec[0].elements[I];
+    }
+    if ((int)f1 == f1) 
+      sprintf (tmpline, "%.0f", f1);
+    else
+      sprintf (tmpline, "%.9g", f1);
+    /* interpolate vector element */
+    n = (int) (w - L);
+    strncpy (N, L, n);
+    N += n;
+    n = strlen (tmpline);
+    strncpy (N, tmpline, n);
+    N += n;
+    L = q + 1;
+  }
+
+dumpline:
+  n = strlen (L);
+  strncpy (N, L, n);
+  N[n] = 0;
+  free (line);
+  free (tmpline);
+  return (newline);
+  
+escape:
+  free (line);
+  free (newline);
+  free (tmpline);
+  return (NULL);
+}
+
Index: /tags/start/Ohana/src/opihi/lib.shell/interrupt.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/interrupt.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/interrupt.c	(revision 12606)
@@ -0,0 +1,51 @@
+# include "opihi.h"
+
+static int Nint = 0;
+
+/* return FALSE if we are called many times in a row 
+   without a valid answer or any answer */
+
+void handle_interrupt (int input) {
+  
+  char string[64];
+  int Nask;
+
+  signal (SIGINT, SIG_IGN);
+
+  Nask = 0;
+  Nint ++;
+  if (Nint > 10) { 
+    interrupt = TRUE;
+    return;
+  }
+  if (Nint > 100) { 
+    exit (3);
+  }
+  
+  while (1) {
+    fprintf (stderr, "operation halted, continue? (y/n) ");
+    fscanf (stdin, "%s", string);
+    
+    if ((string[0] == 'y') || (string[0] == 'Y')) {
+      interrupt = FALSE;
+      signal (SIGINT, handle_interrupt);
+      Nint = 0;
+      return;
+    }
+
+    if ((string[0] == 'n') || (string[0] == 'N')) {
+      interrupt = TRUE;
+      signal (SIGINT, handle_interrupt);
+      Nint = 0;
+      return;
+    }
+    Nask ++;
+    if (Nask > 10) {
+      interrupt = TRUE;
+      signal (SIGINT, handle_interrupt);
+      Nint = 0;
+      return;
+    }
+  }  
+
+}
Index: /tags/start/Ohana/src/opihi/lib.shell/isolate_elements.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/isolate_elements.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/isolate_elements.c	(revision 12606)
@@ -0,0 +1,181 @@
+# include "opihi.h"
+
+/* local private functions */
+void InsertValue (char c);
+void EndOfString (void);
+int IsAnOp (char *c);
+int IsTwoOp (char *c);
+
+/* local private static variables */
+int Nchar, Nout, NOUT;
+char **out;
+
+char **isolate_elements (int Nin, char **in, int *nout) {
+  
+  int i, j, minus, negate, plus, posate, OpStat, SciNotation;
+
+  NOUT = Nin;
+  Nchar = Nout = 0;
+  ALLOCATE (out, char *, NOUT);
+  ALLOCATE (out[Nout], char, NCHARS);
+
+  for (i = 0; i < Nin; i++) {
+    for (j = 0; j < strlen(in[i]); j++) {
+      SciNotation = FALSE;
+      /* identify 'negate' or 'minus' ops */
+      negate = minus = FALSE;
+      if (in[i][j] == '-') { 
+	minus = TRUE;  
+	/* if - is first thing on line, must be a negator */
+	if ((Nout == 0) && (Nchar == 0)) {  
+	  minus = FALSE;
+	  negate = TRUE;
+	  goto skip1;
+	}
+	/* check previous entry on line */
+	if (Nchar) {
+	  OpStat = IsAnOp (out[Nout]);
+	  if (out[Nout][0] == ')') OpStat = FALSE;
+	} else {
+	  OpStat = IsAnOp (out[Nout-1]);
+	  if (out[Nout-1][0] == ')') OpStat = FALSE;
+	}
+	/* if - follows an operator, must be negator */
+	if (OpStat) {
+	  minus = FALSE;
+	  negate = TRUE;
+	  goto skip1;
+	}
+	/* if - follows 'e' is part of 1e-5 */
+	if (j == 0) goto skip1;
+	if ((in[i][j-1] == 'e') || (in[i][j-1] == 'E')) {
+	  SciNotation = TRUE;
+	  negate = minus = FALSE;
+	}
+      }
+    skip1:
+      /* idenfity 'posate' or 'plus' ops */
+      posate = plus = FALSE;
+      if (in[i][j] == '+') { 
+	plus = TRUE;  
+	/* if + is first thing on line, must be a posator */
+	if ((Nout == 0) && (Nchar == 0)) {  
+	  plus = FALSE;
+	  posate = TRUE;
+	  goto skip2;
+	}
+	/* check previous entry on line */
+	if (Nchar) {
+	  OpStat = IsAnOp (out[Nout]);
+	  if (out[Nout][0] == ')') OpStat = FALSE;
+	} else {
+	  OpStat = IsAnOp (out[Nout-1]);
+	  if (out[Nout-1][0] == ')') OpStat = FALSE;
+	}
+	/* if + follows an operator, must be posator */
+	if (OpStat) {
+	  plus = FALSE;
+	  posate = TRUE;
+	  goto skip2;
+	}
+	/* if + follows 'e' is part of 1e+5 */
+	if (j == 0) goto skip2;
+	if ((in[i][j-1] == 'e') || (in[i][j-1] == 'E')) {
+	  SciNotation = TRUE;
+	  posate = plus = FALSE;
+	}
+      }
+    skip2:
+      /* operators */
+      if (negate || minus || posate || plus || (IsAnOp (&in[i][j]) && !SciNotation)) {
+	if (posate) goto skip3;
+	EndOfString ();
+	/* copy operator to out[Nout] */
+	InsertValue (in[i][j]);
+	if (negate) InsertValue ('-');
+
+	if (IsTwoOp (&in[i][j])) {
+	  InsertValue (in[i][j+1]);
+	  j++;
+	} 
+	EndOfString ();
+      } else {
+	if (!whitespace (in[i][j])) {
+	  InsertValue (in[i][j]);
+	} else {
+	  EndOfString ();
+	}
+      }
+    skip3:
+      continue;
+    }
+    EndOfString ();
+  }
+
+  /* one extra entry is allocated, free here */
+  free (out[Nout]);
+  *nout = Nout;
+  return (out);
+
+}
+
+void InsertValue (char c) {
+  out[Nout][Nchar] = c;
+  Nchar ++;
+  out[Nout][Nchar] = 0;
+}
+
+void EndOfString () {
+  if (Nchar > 0) {
+    out[Nout][Nchar] = 0;
+    Nout ++;
+    Nchar = 0;
+    
+    if (Nout >= NOUT - 1) {
+      NOUT += 10; 
+      REALLOCATE (out, char *, NOUT); 
+    } 
+    ALLOCATE (out[Nout], char, NCHARS); 
+  }
+}
+
+int IsAnOp (char *c) {
+
+  if (!strncmp (c, "*",  1)) return (TRUE);
+  if (!strncmp (c, "/",  1)) return (TRUE);
+  if (!strncmp (c, "+",  1)) return (TRUE);
+  if (!strncmp (c, "-",  1)) return (TRUE);
+  if (!strncmp (c, "^",  1)) return (TRUE);
+  if (!strncmp (c, "(",  1)) return (TRUE);
+  if (!strncmp (c, ")",  1)) return (TRUE);
+  if (!strncmp (c, "&",  1)) return (TRUE);
+  if (!strncmp (c, "|",  1)) return (TRUE);
+  if (!strncmp (c, ">",  1)) return (TRUE);
+  if (!strncmp (c, "<",  1)) return (TRUE);
+  if (!strncmp (c, "<<", 2)) return (TRUE);
+  if (!strncmp (c, ">>", 2)) return (TRUE);
+  if (!strncmp (c, "&&", 2)) return (TRUE);
+  if (!strncmp (c, "||", 2)) return (TRUE);
+  if (!strncmp (c, "==", 2)) return (TRUE);
+  if (!strncmp (c, "!=", 2)) return (TRUE);
+  if (!strncmp (c, "<=", 2)) return (TRUE);
+  if (!strncmp (c, ">=", 2)) return (TRUE);
+
+  return (FALSE);
+
+}
+
+int IsTwoOp (char *c) {
+
+  if (!strncmp (c, "<<", 2)) return (TRUE);
+  if (!strncmp (c, ">>", 2)) return (TRUE);
+  if (!strncmp (c, "&&", 2)) return (TRUE);
+  if (!strncmp (c, "||", 2)) return (TRUE);
+  if (!strncmp (c, "==", 2)) return (TRUE);
+  if (!strncmp (c, "!=", 2)) return (TRUE);
+  if (!strncmp (c, "<=", 2)) return (TRUE);
+  if (!strncmp (c, ">=", 2)) return (TRUE);
+
+  return (FALSE);
+
+}
Index: /tags/start/Ohana/src/opihi/lib.shell/macro_create.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/macro_create.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/macro_create.c	(revision 12606)
@@ -0,0 +1,115 @@
+# include "opihi.h"
+# define D_NLINES 100
+# define prompt "> "
+int macro_exec   PROTO((int, char **));
+
+static char helpline[] = "(macro)";
+
+int macro_create (int argc, char **argv) {
+
+  int ThisList, depth, i, done, NLINES, N;
+  char *input, *help;
+  Command *cmd;
+  Macro *macro;
+
+  help = helpline;
+  if ((N = get_argument (argc, argv, "-c"))) {
+    remove_argument (N, &argc, argv);
+    help = strcreate(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: macro <name> [-c \"comment line\"]\n");
+    fprintf (stderr, "  (enter commands, end with the word 'END')\n");
+    return (FALSE);
+  }
+
+  /**** Check for existence of this macro ****/
+  cmd = MatchCommand (argv[1], FALSE, TRUE);
+  macro = MatchMacro (argv[1], FALSE, TRUE);
+  
+  if ((macro == NULL) && (cmd != NULL)) {
+    fprintf (stderr, "cannot redefine inherent command %s\n", argv[1]);
+    return (FALSE);
+  }
+  if ((macro != NULL) && (cmd == NULL)) {
+    fprintf (stderr, "programming error: macro not in command list (%s)\n", argv[1]);
+    return (FALSE);
+  }
+
+  if (macro == NULL) { /**** New Macro ****/
+    ALLOCATE (cmd, Command, 1);
+    cmd[0].name = strcreate (argv[1]);
+    cmd[0].help = help;
+    cmd[0].func = macro_exec;
+    AddCommand (cmd);
+    free (cmd);
+
+    macro = NewMacro (argv[1]);
+  } else { /**** Old Macro ****/
+    /* replace existing command help with new value */
+    if (cmd[0].help != helpline) 
+      free (cmd[0].help);
+    cmd[0].help = help;
+  }
+
+  /* reallocate space for macro lines */
+  NLINES = D_NLINES;
+  for (i = 0; i < macro[0].Nlines; i++) free (macro[0].line[i]);
+  ALLOCATE (macro[0].line, char *, NLINES);
+
+  /* read in macro
+     If we are entering at the keyboard (Nlists == 0), use readline.
+     Otherwise, read from the current list
+     End when we hit the final "END" (the true END -- we count macro defines!!) */
+     
+  depth = 0;
+  ThisList = Nlists;
+  for (i = 0, done = FALSE; !done; ) {
+
+    /* get the next line (from correct place) */
+    if (ThisList == 0) 
+      input = readline (prompt);
+    else 
+      input = get_next_listentry (ThisList);
+
+    if ((ThisList == 0) && (input == (char *) NULL)) {
+      fprintf (stderr, "end macro with 'END'\n");
+      continue;
+    }
+
+    if ((ThisList > 0) && (input == (char *) NULL)) {
+      fprintf (stderr, "missing 'END' in macro definition\n");
+      input = strcreate ("end");
+    }
+
+    stripwhite (input);
+
+    /* test for new macro (or other list, in the future?) */
+    if (is_list (input)) depth ++;
+
+    /* test for end of nested list -- if not nested, END refers to this macro */
+    if (!strncasecmp (input, "END", 3)) {
+      depth --;
+      if (depth < 0) { /* we hit the last "END", macro is done */
+	free (input);
+	macro[0].Nlines = i;
+	if (macro[0].Nlines == 0) 
+	  i = 1;
+	REALLOCATE (macro[0].line, char *, i);
+	return (TRUE);
+      }
+    }
+
+    if (*input) { 
+      macro[0].line[i] = input;
+      i++;
+      if (i == NLINES - 1) {
+	NLINES += D_NLINES;
+	REALLOCATE (macro[0].line, char *, NLINES);
+      }
+    }
+  }
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/lib.shell/macro_delete.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/macro_delete.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/macro_delete.c	(revision 12606)
@@ -0,0 +1,28 @@
+# include "opihi.h"
+
+int macro_delete (int argc, char **argv) {
+
+  Command *cmd;
+  Macro *macro;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: macro delete <macro>\n");
+    return (FALSE);
+  }
+
+  macro = MatchMacro (argv[1], FALSE, TRUE);
+  if (macro == NULL) {
+    fprintf (stderr, "Macro %s not found\n", argv[1]);
+    return (FALSE);
+  }
+  cmd = MatchCommand (argv[1], FALSE, TRUE);
+  if (cmd == NULL) {
+    fprintf (stderr, "programming error: macro exists but not command\n");
+    return (FALSE);
+  }
+
+  DeleteMacro (macro);
+  DeleteCommand (cmd);
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/lib.shell/macro_edit.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/macro_edit.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/macro_edit.c	(revision 12606)
@@ -0,0 +1,9 @@
+# include "opihi.h"
+
+int macro_edit (int argc, char **argv) {
+
+  fprintf (stderr, "this function is not implemented yet\n");
+  return (FALSE);
+
+}
+
Index: /tags/start/Ohana/src/opihi/lib.shell/macro_exec.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/macro_exec.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/macro_exec.c	(revision 12606)
@@ -0,0 +1,45 @@
+# include "opihi.h"
+
+int macro_exec (int argc, char **argv) {
+
+  int i, status, MacroDepth;
+  char *PreviousName, **params, tmp[1024];
+  Macro *macro;
+  
+  macro = MatchMacro (argv[0], FALSE, TRUE);
+  if (macro == NULL) {
+    fprintf (stderr, "%s: Command not found.\n", argv[0]);
+    return (FALSE);
+  }
+
+  /* increase MacroDepth by one - governs macro args */
+  PreviousName = GetMacroName ();
+  MacroDepth = GetMacroDepth ();
+  MacroDepth ++;
+  SetCurrentMacroData (macro[0].name, MacroDepth);
+
+  ALLOCATE (params, char *, argc);
+  sprintf (tmp, "%d.%d", MacroDepth, 0);
+  params[0] = strcreate (tmp);
+  sprintf (tmp, "%d", argc);
+  set_str_variable (params[0], tmp);
+  for (i = 1; i < argc; i++) {
+    sprintf (tmp, "%d.%d", MacroDepth, i);
+    params[i] = strcreate (tmp);
+    set_str_variable (params[i], argv[i]);
+  }
+
+  /* process this list */
+  status = exec_loop (&macro[0]);
+
+  /* clear out the command line variables */
+  for (i = 0; i < argc; i++) {
+    DeleteNamedScalar (params[i]);
+    free (params[i]);
+  }
+  free (params);
+  
+  MacroDepth --;
+  SetCurrentMacroData (PreviousName, MacroDepth);
+  return (status);
+}
Index: /tags/start/Ohana/src/opihi/lib.shell/macro_list.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/macro_list.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/macro_list.c	(revision 12606)
@@ -0,0 +1,23 @@
+# include "opihi.h"
+
+int macro_list_f (int argc, char **argv) {
+
+  int i;
+  Macro *macro;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: macro list <macro>\n");
+    return (FALSE);
+  }
+
+  macro = MatchMacro (argv[0], FALSE, TRUE);
+  if (macro == NULL) {
+    fprintf (stderr, "%s: Macro not found\n", argv[1]);
+    return (FALSE);
+  }
+
+  for (i = 0; i < macro[0].Nlines; i++) {
+    fprintf (stderr, "%s\n", macro[0].line[i]);
+  }
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/lib.shell/macro_read.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/macro_read.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/macro_read.c	(revision 12606)
@@ -0,0 +1,9 @@
+# include "opihi.h"
+
+int macro_read (int argc, char **argv) {
+
+  fprintf (stderr, "this function is not implemented yet\n");
+  return (FALSE);
+
+}
+
Index: /tags/start/Ohana/src/opihi/lib.shell/macro_write.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/macro_write.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/macro_write.c	(revision 12606)
@@ -0,0 +1,9 @@
+# include "opihi.h"
+
+int macro_write (int argc, char **argv) {
+
+  fprintf (stderr, "this function is not implemented yet\n");
+  return (FALSE);
+
+}
+
Index: /tags/start/Ohana/src/opihi/lib.shell/multicommand.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/multicommand.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/multicommand.c	(revision 12606)
@@ -0,0 +1,16 @@
+# include "opihi.h"
+
+char **multicommand (char *line, int *nlist) {
+
+  char **list;
+  int Nlist, NLIST;
+
+  Nlist = 0;
+  NLIST = 10;
+  ALLOCATE (list, char *, NLIST);
+
+  list[0] = strcreate (line);
+  *nlist = 1;
+  return (list);
+}
+
Index: /tags/start/Ohana/src/opihi/lib.shell/opihi.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/opihi.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/opihi.c	(revision 12606)
@@ -0,0 +1,47 @@
+# include "opihi.h"
+
+/******************/
+int main (int argc, char **argv) {
+
+  int i, Nbad, Nlist, status;
+  char **list, *line, *outline, *prompt, *history;
+
+  initialize (argc, argv);
+  startup (argc, argv);
+  prompt = get_variable("PROMPT");
+  history = get_variable("HISTORY");
+  welcome ();
+
+  Nbad = 0;
+  while (1) {  /** must exit with command "exit" or "quit" */
+    if (Nbad == 10) exit (3);
+
+    line = readline (prompt);
+    if (line == NULL) {
+      fprintf (stdout, "Use \"quit\" to exit\n");
+      Nbad ++;
+      continue;
+    }
+    Nbad = 0;
+
+    stripwhite (line);
+    if (*line) {
+      list = multicommand (line, &Nlist);
+      for (i = 0; i < Nlist; i++) {
+	status = command (list[i], &outline);
+	if (outline != NULL) free (outline);
+      }
+      add_history (line);
+      append_history (1, history);
+      free (line);
+      free (list);
+    }
+    line = (char *) NULL;
+  }
+}
+
+  /* this needs some work to use multicommand correctly 
+     multicommand is currently a do-nothing function.  
+     if we want multicommand to interact with the list/macro style commands, 
+     we need a command to push all the elements of the line onto the command stack.
+   */
Index: /tags/start/Ohana/src/opihi/lib.shell/parse.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/parse.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/parse.c	(revision 12606)
@@ -0,0 +1,261 @@
+# include "opihi.h"
+
+void interpolate_slash (char *line);
+
+char *parse (char *line) {
+
+  double fval;
+  char *newline, *N, *L, *val, *B, *V, *V0, *V1, *end, *c1, *c2;
+  int Nval, Nbytes, status, size;
+  FILE *f;
+  Vector *vec;
+
+  val = V0 = NULL;
+
+  if (line == (char *) NULL) goto error;
+
+  /* case 1: $var = expression */
+  if (line[0] == '$') {  
+    /* find the target variable name and the rest of the line */
+    interpolate_slash (line);
+    V0 = thisvar (line);
+    if (V0 == NULL) goto error;
+    V1 = aftervar (line);
+    if (V1 == NULL) goto error;
+ 
+    /* increment operator */
+    if (!strcmp (V1, "++")) {
+      val = get_variable (V0);
+      if (val == NULL) {
+	fval = 1.0;
+      } else {
+	fval = atof (val) + 1.0;
+      }
+      set_variable (V0, fval);
+      goto escape;
+    }
+
+    /* decrement operator */
+    if (!strcmp (V1, "--")) {
+      val = get_variable (V0);
+      if (val == NULL) {
+	fval = -1.0;
+      } else {
+	fval = atof (val) - 1.0;
+      }
+      set_variable (V0, fval);
+      goto escape;
+    }
+
+    /* not an assignement, syntax error */
+    if (*V1 != '=') goto error;
+
+    /* find first non-whitespace character after = */
+    V1 ++;
+    while (isspace (*V1)) V1++;
+    if (*V1 == 0) goto error;
+
+    /* command replacement.  execute the line, place answer in val. */
+    if (*V1 == '`') {
+
+      /* look for end of line, must be ` */
+      B = V1 + strlen (V1) - 1;
+      if (*B != '`') goto error;
+
+      /* val will hold the result */
+      ALLOCATE (val, char, 1024);
+
+      /* B is the command to be executed */
+      B = strncreate (V1 + 1, strlen(V1) - 2);
+      f = popen (B, "r");
+      Nbytes = fread (val, 1, 1023, f);
+      val[Nbytes] = 0;
+      status = pclose (f);
+      free (B);
+
+      if (status) fprintf (stderr, "warning: exit status of command %d\n", status);
+
+      for (B = val; *B != 0; B++) {
+	if (*B == '\n') *B = ' ';
+      }
+    } else {
+      /* dvomath returns a new string, or NULL, with the result of the expression */
+      val = dvomath (1, &V1, &size, 0);
+      if (val == NULL) { 
+	while (whitespace (*V1)) V1++;
+	val = strcreate (V1);
+      } 
+    }
+    /* both dvomath and command replacement create (char *) val */
+    set_str_variable (V0, val);
+    goto escape;  /* frees temp variables */
+  }
+
+  /* case 2: vect[N] = value */
+  V0 = thiscomm (line);
+  if (strchr(V0, '[') != (char *) NULL) { 
+    /* get vector name (left in V0) */
+    N = strchr (V0, '[');
+    if (N == V0) goto error;
+
+    /* get bracket contents (left in V) */
+    L = strchr (V0, ']');
+    if (L == (char *) NULL) goto error;
+    if (L != V0 + strlen (V0) - 1) goto error;
+
+    *N = 0;
+    V = strncreate (N+1, L - N - 1);
+
+    /* expand value in parenthesis */
+    val = dvomath (1, &V, &size, 0);
+    if (val == NULL) {
+      print_error ();
+      goto error;
+    }
+    Nval = atoi (val);
+    free (V);
+
+    /* find vector */
+    if ((vec = SelectVector (V0, OLDVECTOR, TRUE)) == NULL) goto error;
+    free (V0); V0 = (char *) NULL;
+    if (Nval >= vec[0].Nelements) {
+      fprintf (stderr, "no element %d\n", Nval);
+      goto escape;
+    }
+
+    /* find value for assignment */
+    V1 = nextcomm (line);
+    if (V1 == (char *) NULL) goto error;
+    if (V1[0] != '=') goto error;
+    V1 ++;
+    B = thisword (V1);
+    if (B == (char *) NULL) goto error;
+
+    /*** assign vector element to value ***/
+    val = dvomath (1, &V1, &size, 0); 
+    if (val == (char *) NULL) {
+      print_error ();
+      goto error;
+    }
+    vec[0].elements[Nval] = atof (val);
+    goto escape;
+  }
+  free (V0); V0 = (char *) NULL;
+
+  /* case 3: {expression} */
+  ALLOCATE (newline, char, 1024);
+  for (L = line, N = newline; *L != 0; L++, N++) { 
+
+    /* copy elements from L (line) to N (newline) until we hit a '{' */
+    for (; (*L != '{') && (*L != 0); L++, N++) *N = *L;
+    if (*L == 0) break;
+
+    if ((L != line) && (*(L-1) == 0x5c)) {
+      N--;
+      *N = *L;
+      continue;
+    }
+
+    /* check on the syntax of the line */
+    L++;
+    c1 = strchr (L, '}');
+    if (c1 == NULL) {
+      fprintf (stderr, "no close brackets!\n");
+      goto escape;
+    }
+    c2 = strchr (L, '{');
+    if ((c2 != NULL) && (c2 < c1)) {
+      fprintf (stderr, "can't nest brackets!\n");
+      goto escape;
+    }
+    end = c1;
+    *c1 = 0;
+
+    /* value in brackets must be an expression of some sort */
+    val = dvomath (1, &L, &size, -1);
+    if (val == NULL) {
+      print_error ();
+      goto escape;
+    } 
+    /* copy val to outline */
+    for (V = val; *V != 0; V++,N++) *N = *V;
+    L = end;
+    N--;
+    free (val); val = (char *) NULL;
+  }
+  
+  *N = 0;
+  free (line); line = (char *) NULL;
+
+  /* \ protects next character */
+  interpolate_slash (newline);
+  
+  REALLOCATE (newline, char, strlen (newline) + 1);
+  return (newline); 
+
+  error:
+  fprintf (stderr, "syntax error\n");
+
+  escape:
+  if (line != (char *) NULL) free (line);
+  if (val != (char *) NULL) free (val);
+  if (V0 != (char *) NULL) free (V0);
+  return (NULL);
+}
+
+/* replace all instances of \A with A in line */
+void interpolate_slash (char *line) {
+
+  char *in, *out;
+
+  for (in = out = line; *in != 0; in++, out++) {
+    if (*in == 0x5c) in++;
+    *out = *in;
+    if (*in == 0) return;
+  }
+  *out = *in;
+}
+
+  /* this routine looks for math and/or logic expressions that 
+     need to be evaluated and passes them on to "parenthesis",
+     which evaluates the expression */
+
+  /* There are two situations now which define an expression to 
+     be evaluated:
+     1) $var = expression   -- everything after the = must be a math expression or a string
+     2) {expression}        -- everything within the {} must be a math expression
+   */
+
+  /* case 1: $var = expression.  test that
+     a) there is a $ as the first character
+     b) the variable defined by that $ is not null
+     c) there is an = sign following the variable
+     d) there is something following the = sign
+     */
+  
+  /* case 2: vect[N] = expression. check syntax:
+     a) last char must be ]
+     b) word must contain [
+     c) between [ & ] must be an integer
+     d) vector must exist
+     e) there is an = sign following the first word
+     f) there is something following the = sign
+  */
+     
+
+  /* case 3: we hunt for '{', and then the first '}' and pass everything
+     inbetween.  no nested {{}}s are allowed! */
+  
+/* thisword ALLOCATES
+   thisvar  ALLOCATES
+   thiscomm ALLOCATES
+   
+   nextword !ALLOCATE
+   nextcomm !ALLOCATE
+   
+   lastword !ALLOCATE
+   lastvar !ALLOCATE
+   
+   aftervar !ALLOCATE
+*/   
+
Index: /tags/start/Ohana/src/opihi/lib.shell/parse_commands.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/parse_commands.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/parse_commands.c	(revision 12606)
@@ -0,0 +1,50 @@
+# include "opihi.h"
+# define D_NARG 10
+
+char **parse_commands (char *line, int *argc) {
+
+  int i, j, NARG;
+  char *c;
+  char **argv;
+
+  NARG = D_NARG;
+  ALLOCATE (argv, char *, NARG);
+
+  argv[0] = thisword (line);
+  if (argv[0] == (char *) NULL) {
+    free (argv);
+    *argc = 0;
+    return ((char **) NULL);
+  }
+
+  c = nextword (line);
+  for (i = 1; c != (char *) NULL; i++) {
+    argv[i] = thisword (c);
+    if (argv[i] == (char *) NULL) {
+      for (j = 0; j < i; j++) 
+	free (argv[i]);
+      free (argv);
+      *argc = 0;
+      return (argv);
+    }
+    c = nextword (c);
+    if (i == NARG - 1) {
+      NARG += D_NARG;
+      REALLOCATE (argv, char *, NARG);
+    }
+  }
+  REALLOCATE (argv, char *, i);
+  *argc = i;
+
+  return (argv);
+
+}
+
+  /* parse out the command line into (char **argv).  line looks like:
+     command word word word ... */
+
+  /* argv[0] and argv[1..argc-1] are handled differently because
+     the syntax of a valid command and a valid word are slighly 
+     different (not that this is obviously wanted...) */
+
+
Index: /tags/start/Ohana/src/opihi/lib.shell/queues.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/queues.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/queues.c	(revision 12606)
@@ -0,0 +1,93 @@
+# include "opihi.h"
+
+/* these functions are somewhat fragile: we cannot do multiple 
+   CreateQueue / FindQueue operations in a row or the pointers 
+   will get messed up
+   do we need a 'delete queue' function?
+*/
+
+Queue *queues;   /* queue to store the list of all queues */
+int   Nqueues;   /* number of currently available queues */
+
+void InitQueues () {
+  Nqueues = 0;
+  ALLOCATE (queues, Queue, 1); 
+}
+
+/* list known queues */
+void ListQueues () {
+
+  int i;
+
+  for (i = 0; i < Nqueues; i++) {
+    fprintf (stderr, "%-15s %3d\n", queues[i].name, queues[i].Nlines);
+  }
+  return;
+}
+
+/* return the given queue */
+Queue *FindQueue (char *name) {
+
+  int i;
+
+  for (i = 0; i < Nqueues; i++) {
+    if (!strcmp (queues[i].name, name)) {
+      return (&queues[i]);
+    }
+  }
+  return (NULL);
+}
+
+/* make a new named queue */
+Queue *CreateQueue (char *name) {
+
+  Queue *queue;
+
+  queue = FindQueue (name);
+  if (queue != NULL) return (queue);
+
+  Nqueues ++;
+  REALLOCATE (queues, Queue, Nqueues);
+  queue = &queues[Nqueues - 1];
+  queue[0].Nlines = 0;
+  queue[0].NLINES = 10;
+  queue[0].name = strcreate (name);
+  ALLOCATE (queue[0].lines, char *, queue[0].NLINES);
+  return (queue);
+}
+
+void PushQueue (Queue *queue, char *line) {
+
+  int N;
+
+  N = queue[0].Nlines;
+  queue[0].lines[N] = strcreate (line);
+  queue[0].Nlines ++;
+  if (queue[0].Nlines == queue[0].NLINES) {
+    queue[0].NLINES += 10;
+    REALLOCATE (queue[0].lines, char *, queue[0].NLINES);
+  }    
+  return;
+}
+
+char *PopQueue (Queue *queue) {
+
+  int i;
+  char *line;
+
+  if (queue[0].Nlines == 0) return (NULL);
+  line = queue[0].lines[0];
+
+  for (i = 1; i < queue[0].Nlines; i++) {
+    queue[0].lines[i-1] = queue[0].lines[i];
+  }
+  queue[0].Nlines --;
+
+  if (queue[0].Nlines < queue[0].NLINES - 20) {
+    queue[0].NLINES -= 20;
+    queue[0].NLINES = MAX (queue[0].NLINES, 10);
+    REALLOCATE (queue[0].lines, char *, queue[0].NLINES);
+  }    
+  return (line);
+}
+
Index: /tags/start/Ohana/src/opihi/lib.shell/stack_math.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/stack_math.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/stack_math.c	(revision 12606)
@@ -0,0 +1,1251 @@
+# include "opihi.h"
+
+/* the result of a matrix operation must go into a temp variable,
+   labeled by "m". if one of the input matrices is already a temp variable, we 
+   can continue using it this round 
+   */
+
+int VV_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  int i, Nx;
+  float *out, *M1, *M2;
+  
+  Nx = V1[0].vector[0].Nelements;
+  if (Nx != V2[0].vector[0].Nelements) {
+    return (FALSE);
+  }
+
+  if (V1[0].type == 'v') {  /** use V1 as temp buffer **/
+    OUT[0].vector = V1[0].vector;
+    V1[0].type = 'V'; /* prevent it from being freed below */
+  } else {
+    if (V2[0].type == 'v') { /** use V2 as temp buffer, but header of V1 **/
+      OUT[0].vector = V2[0].vector;
+      V2[0].type = 'V'; /* prevent it from being freed below */
+    } else {  /* no spare temp buffer */
+      OUT[0].vector = InitVector ();
+      CopyVector (OUT[0].vector, V1[0].vector);
+    }
+  }
+  OUT[0].type = 'v'; /*** <<--- says this is a temporary matrix ***/
+  strcpy (OUT[0].name, "tmp");
+  M1  = V1[0].ptr;
+  M2  = V2[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].vector[0].elements;
+
+  switch (op[0]) { 
+  case '+': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++)
+      *out = *M1 + *M2;
+    break; 
+  case '-': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++)
+      *out = *M1 - *M2;
+    break; 
+  case '*': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++)
+      *out = *M1 * *M2;
+    break; 
+  case '/': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++)
+      *out = *M1 / *M2;
+    break; 
+  case 0x5e: 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = pow (*M1, *M2);
+    break; 
+  case 'D': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = MIN (*M1, *M2);
+    break; 
+  case 'U': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = MAX (*M1, *M2);
+    break; 
+  case '<': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = (*M1 < *M2) ? 1 : 0;
+    break; 
+  case '>': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = (*M1 > *M2) ? 1 : 0;
+    break; 
+  case '&': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = ((int)*M1 & (int)*M2);
+    break; 
+  case '|': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = ((int)*M1 | (int)*M2);
+    break; 
+  case 'E': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = (*M1 == *M2) ? 1 : 0;
+    break; 
+  case 'N': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = (*M1 != *M2) ? 1 : 0;
+    break; 
+  case 'L': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = (*M1 <= *M2) ? 1 : 0;
+    break; 
+  case 'G': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = (*M1 >= *M2) ? 1 : 0;
+    break; 
+  case 'A': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = (*M1 && *M2) ? 1 : 0;
+    break; 
+  case 'O': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = (*M1 || *M2) ? 1 : 0;
+    break; 
+  default:
+    fprintf (stderr, "error: op %c not defined!\n", op[0]);
+  }
+
+  /** free up any temporary buffers: **/
+
+  if (V1[0].type == 'v') {
+    free (V1[0].vector[0].elements);
+    free (V1[0].vector);
+  }
+  if (V2[0].type == 'v') {
+    free (V2[0].vector[0].elements);
+    free (V2[0].vector);
+  }
+
+  /* at the end, V1 and V2 are deleted only if they were temporary */
+  return (TRUE);
+
+}
+
+int SV_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  int i, Nx;
+  float *out, *M1, *M2;
+  
+  Nx = V2[0].vector[0].Nelements;
+
+  if (V2[0].type == 'v') { /** use V2 as temp buffer, but header of V1 **/
+    OUT[0].vector = V2[0].vector;
+    V2[0].type = 'V'; /* prevent it from being freed below */
+  } else {  /* no spare temp buffer */
+    OUT[0].vector = InitVector ();
+    CopyVector (OUT[0].vector, V2[0].vector);
+  }
+  OUT[0].type = 'v';   /*** <<--- says this is a temporary matrix ***/
+  strcpy (OUT[0].name, "tmp");
+  M1  = V1[0].ptr;
+  M2  = V2[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].vector[0].elements;
+
+  switch (op[0]) { 
+  case '+': 
+    for (i = 0; i < Nx; i++, out++, M2++)
+      *out = *M1 + *M2;
+    break; 
+  case '-': 
+    for (i = 0; i < Nx; i++, out++, M2++)
+      *out = *M1 - *M2;
+    break; 
+  case '*': 
+    for (i = 0; i < Nx; i++, out++, M2++)
+      *out = *M1 * *M2;
+    break; 
+  case '/': 
+    for (i = 0; i < Nx; i++, out++, M2++)
+      *out = *M1 / *M2;
+    break; 
+  case 0x5e: 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = pow (*M1, *M2);
+    break; 
+  case 'D': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = MIN (*M1, *M2);
+    break; 
+  case 'U': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = MAX (*M1, *M2);
+    break; 
+  case '<': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = (*M1 < *M2) ? 1 : 0;
+    break; 
+  case '>': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = (*M1 > *M2) ? 1 : 0;
+    break; 
+  case '&': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = ((int)*M1 & (int)*M2);
+    break; 
+  case '|': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = ((int)*M1 | (int)*M2);
+    break; 
+  case 'E': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = (*M1 == *M2) ? 1 : 0;
+    break; 
+  case 'N': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = (*M1 != *M2) ? 1 : 0;
+    break; 
+  case 'L': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = (*M1 <= *M2) ? 1 : 0;
+    break; 
+  case 'G': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = (*M1 >= *M2) ? 1 : 0;
+    break; 
+  case 'A': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = (*M1 && *M2) ? 1 : 0;
+    break; 
+  case 'O': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = (*M1 || *M2) ? 1 : 0;
+    break; 
+  default:
+    fprintf (stderr, "error: op %c not defined!\n", op[0]);
+  }
+
+  /** free up any temporary buffers: **/
+  if (V2[0].type == 'v') {
+    free (V2[0].vector[0].elements);
+    free (V2[0].vector);
+  }
+
+  /* at the end, V1 and V2 are deleted only if they were temporary */
+  return (TRUE);
+
+}
+
+int VS_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  int i, Nx;
+  float *out, *M1, *M2;
+  
+  Nx = V1[0].vector[0].Nelements;
+
+  if (V1[0].type == 'v') { /** use V1 as temp buffer **/
+    OUT[0].vector = V1[0].vector;
+    V1[0].type = 'V'; /* prevent it from being freed below */
+  } else {  /* no spare temp buffer */
+    OUT[0].vector = InitVector ();
+    CopyVector (OUT[0].vector, V1[0].vector);
+  }
+  OUT[0].type = 'v';   /*** <<--- says this is a temporary matrix ***/
+  strcpy (OUT[0].name, "tmp");
+  M1  = V1[0].ptr;
+  M2  = V2[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].vector[0].elements;
+
+  switch (op[0]) { 
+  case '+': 
+    for (i = 0; i < Nx; i++, out++, M1++)
+      *out = *M1 + *M2;
+    break; 
+  case '-': 
+    for (i = 0; i < Nx; i++, out++, M1++)
+      *out = *M1 - *M2;
+    break; 
+  case '*': 
+    for (i = 0; i < Nx; i++, out++, M1++)
+      *out = *M1 * *M2;
+    break; 
+  case '/': 
+    for (i = 0; i < Nx; i++, out++, M1++)
+      *out = *M1 / *M2;
+    break; 
+  case 0x5e: 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = pow (*M1, *M2);
+    break; 
+  case 'D': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = MIN (*M1, *M2);
+    break; 
+  case 'U': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = MAX (*M1, *M2);
+    break; 
+  case '<': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = (*M1 < *M2) ? 1 : 0;
+    break; 
+  case '>': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = (*M1 > *M2) ? 1 : 0;
+    break; 
+  case '&': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = ((int)*M1 & (int)*M2);
+    break; 
+  case '|': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = ((int)*M1 | (int)*M2);
+    break; 
+  case 'E': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = (*M1 == *M2) ? 1 : 0;
+    break; 
+  case 'N': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = (*M1 != *M2) ? 1 : 0;
+    break; 
+  case 'L': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = (*M1 <= *M2) ? 1 : 0;
+    break; 
+  case 'G': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = (*M1 >= *M2) ? 1 : 0;
+    break; 
+  case 'A': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = (*M1 && *M2) ? 1 : 0;
+    break; 
+  case 'O': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = (*M1 || *M2) ? 1 : 0;
+    break; 
+  default:
+    fprintf (stderr, "error: op %c not defined!\n", op[0]);
+  }
+
+  /** free up any temporary buffers: **/
+
+  if (V1[0].type == 'v') {
+    free (V1[0].vector[0].elements);
+    free (V1[0].vector);
+  }
+  /* at the end, V1 and V2 are deleted only if they were temporary */
+  return (TRUE);
+
+}
+
+int MV_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  int i, j, Nx, Ny;
+  float *out, *M1, *M2;
+  
+  Nx = V1[0].buffer[0].matrix.Naxis[0];
+  Ny = V1[0].buffer[0].matrix.Naxis[1];
+  if (Ny != V2[0].vector[0].Nelements) {
+    fprintf (stderr, "dimension mismatch\n");
+    return (FALSE);
+  }
+
+  /* if possible, use V1 as temp buffer, otherwise create new one */
+  if (V1[0].type == 'm') {  
+    OUT[0].buffer = V1[0].buffer;
+    V1[0].type = 'M'; /* prevent it from being freed below */
+  } else {  
+    /* do buffer.matrix.buffer and buffer.header.buffer get correctly zeroed? */
+    OUT[0].buffer = InitBuffer ();
+    CopyBuffer (OUT[0].buffer, V1[0].buffer);
+  }
+  OUT[0].type = 'm'; /*** <<--- says this is a temporary matrix ***/
+  strcpy (OUT[0].name, "tmp");
+  M1  = V1[0].ptr;
+  M2  = V2[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].buffer[0].matrix.buffer;
+
+  switch (op[0]) { 
+  case '+': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++)
+        *out = *M1 + *M2;
+    }
+    break; 
+  case '-': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++)
+        *out = *M1 - *M2;
+    }
+    break; 
+  case '*': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++)
+        *out = *M1 * *M2;
+    }
+    break; 
+  case '/': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++)
+        *out = *M1 / *M2;
+    }
+    break; 
+  case 0x5e: 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = pow (*M1, *M2);
+    }
+    break; 
+  case 'D': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = MIN (*M1, *M2);
+    }
+    break; 
+  case 'U': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = MAX (*M1, *M2);
+    }
+    break; 
+  case '<': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = (*M1 < *M2) ? 1 : 0;
+    }
+    break; 
+  case '>': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = (*M1 > *M2) ? 1 : 0;
+    }
+    break; 
+  case '&': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = ((int)*M1 & (int)*M2);
+    }
+    break; 
+  case '|': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = ((int)*M1 | (int)*M2);
+    }
+    break; 
+  case 'E': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = (*M1 == *M2) ? 1 : 0;
+    }
+    break; 
+  case 'N': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = (*M1 != *M2) ? 1 : 0;
+    }
+    break; 
+  case 'L': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = (*M1 <= *M2) ? 1 : 0;
+    }
+    break; 
+  case 'G': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = (*M1 >= *M2) ? 1 : 0;
+    }
+    break; 
+  case 'A': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = (*M1 && *M2) ? 1 : 0;
+    }
+    break; 
+  case 'O': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = (*M1 || *M2) ? 1 : 0;
+    }
+    break; 
+  default:
+    fprintf (stderr, "error: op %c not defined!\n", op[0]);
+  }
+
+  /** free up any temporary buffers: **/
+
+  if (V1[0].type == 'm') {
+    free (V1[0].buffer[0].header.buffer);
+    free (V1[0].buffer[0].matrix.buffer);
+    free (V1[0].buffer);
+  }
+  if (V2[0].type == 'v') {
+    free (V2[0].vector[0].elements);
+    free (V2[0].vector);
+  }
+  /* at the end, V1 and V2 are deleted only if they were temporary */
+  return (TRUE);
+
+}
+
+
+int VM_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  int i, j, Nx, Ny;
+  float *out, *M1, *M2;
+  
+  Nx = V2[0].buffer[0].matrix.Naxis[0];
+  Ny = V2[0].buffer[0].matrix.Naxis[1];
+  if (Nx != V1[0].vector[0].Nelements) {
+    return (FALSE);
+  }
+
+  /* if possible, use V2 as temp buffer, otherwise create new one */
+  if (V2[0].type == 'm') {
+    OUT[0].buffer = V2[0].buffer;
+    V2[0].type = 'M'; /* prevent it from being freed below */
+  } else {  /* no spare temp buffer */
+    OUT[0].buffer = InitBuffer ();
+    CopyBuffer (OUT[0].buffer, V2[0].buffer);
+  }
+  OUT[0].type = 'm'; /*** <<--- says this is a temporary matrix ***/
+  strcpy (OUT[0].name, "tmp");
+  M1  = V1[0].ptr;
+  M2  = V2[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].buffer[0].matrix.buffer;
+
+  switch (op[0]) { 
+  case '+': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++)
+        *out = *M1 + *M2;
+    }
+    break; 
+  case '-': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++)
+        *out = *M1 - *M2;
+    }
+    break; 
+  case '*': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++)
+        *out = *M1 * *M2;
+    }
+    break; 
+  case '/': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++)
+        *out = *M1 / *M2;
+    }
+    break; 
+  case 0x5e: 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = pow (*M1, *M2);
+    }
+    break; 
+  case 'D': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = MIN (*M1, *M2);
+    }
+    break; 
+  case 'U': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = MAX (*M1, *M2);
+    }
+    break; 
+  case '<': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = (*M1 < *M2) ? 1 : 0;
+    }
+    break; 
+  case '>': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = (*M1 > *M2) ? 1 : 0;
+    }
+    break; 
+  case '&': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = ((int)*M1 & (int)*M2);
+    }
+    break; 
+  case '|': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = ((int)*M1 | (int)*M2);
+    }
+    break; 
+  case 'E': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = (*M1 == *M2) ? 1 : 0;
+    }
+    break; 
+  case 'N': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = (*M1 != *M2) ? 1 : 0;
+    }
+    break; 
+  case 'L': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = (*M1 <= *M2) ? 1 : 0;
+    }
+    break; 
+  case 'G': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = (*M1 >= *M2) ? 1 : 0;
+    }
+    break; 
+  case 'A': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = (*M1 && *M2) ? 1 : 0;
+    }
+    break; 
+  case 'O': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = (*M1 || *M2) ? 1 : 0;
+    }
+    break; 
+  default:
+    fprintf (stderr, "error: op %c not defined!\n", op[0]);
+  }
+
+  /** free up any temporary buffers: **/
+
+  if (V1[0].type == 'v') {
+    free (V1[0].vector[0].elements);
+    free (V1[0].vector);
+  }
+  if (V2[0].type == 'm') {
+    free (V2[0].buffer[0].header.buffer);
+    free (V2[0].buffer[0].matrix.buffer);
+    free (V2[0].buffer);
+  }
+  /* at the end, V1 and V2 are deleted only if they were temporary */
+  return (TRUE);
+
+}
+
+int MM_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  int i, Nx, Ny;
+  float *out, *M1, *M2;
+  
+  Nx = V1[0].buffer[0].matrix.Naxis[0];
+  Ny = V1[0].buffer[0].matrix.Naxis[1];
+
+  if (V1[0].type == 'm') {  /** use V1 as temp buffer **/
+    OUT[0].buffer = V1[0].buffer;
+    V1[0].type = 'M'; /* prevent it from being freed below */
+  } else {
+    if (V2[0].type == 'm') { /** use V2 as temp buffer, but header of V1 **/
+      OUT[0].buffer = V2[0].buffer;
+      V2[0].type = 'M'; /* prevent it from being freed below */
+    } else {  /* no spare temp buffer */
+      OUT[0].buffer = InitBuffer ();
+      CopyBuffer (OUT[0].buffer, V1[0].buffer);
+    }
+  }
+  OUT[0].type = 'm'; /*** <<--- says this is a temporary matrix ***/
+  strcpy (OUT[0].name, "tmp");
+  M1  = V1[0].ptr;
+  M2  = V2[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].buffer[0].matrix.buffer;
+
+  switch (op[0]) { 
+  case '+': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
+      *out = *M1 + *M2;
+    break; 
+  case '-': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
+      *out = *M1 - *M2;
+    break; 
+  case '*': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
+      *out = *M1 * *M2;
+    break; 
+  case '/': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
+      *out = *M1 / *M2;
+    break; 
+  case 0x5e: 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = pow (*M1, *M2);
+    break; 
+  case 'D': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = MIN (*M1, *M2);
+    break; 
+  case 'U': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = MAX (*M1, *M2);
+    break; 
+  case '<': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = (*M1 < *M2) ? 1 : 0;
+    break; 
+  case '>': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = (*M1 > *M2) ? 1 : 0;
+    break; 
+  case '&': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = ((int)*M1 & (int)*M2);
+    break; 
+  case '|': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = ((int)*M1 | (int)*M2);
+    break; 
+  case 'E': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = (*M1 == *M2) ? 1 : 0;
+    break; 
+  case 'N': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = (*M1 != *M2) ? 1 : 0;
+    break; 
+  case 'L': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = (*M1 <= *M2) ? 1 : 0;
+    break; 
+  case 'G': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = (*M1 >= *M2) ? 1 : 0;
+    break; 
+  case 'A': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = (*M1 && *M2) ? 1 : 0;
+    break; 
+  case 'O': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = (*M1 || *M2) ? 1 : 0;
+    break; 
+  default:
+    fprintf (stderr, "error: op %c not defined!\n", op[0]);
+  }
+
+  /** free up any temporary buffers: **/
+
+  if (V1[0].type == 'm') {
+    free (V1[0].buffer[0].header.buffer);
+    free (V1[0].buffer[0].matrix.buffer);
+    free (V1[0].buffer);
+  }
+  if (V2[0].type == 'm') {
+    free (V2[0].buffer[0].header.buffer);
+    free (V2[0].buffer[0].matrix.buffer);
+    free (V2[0].buffer);
+  }
+  /* at the end, V1 and V2 are deleted only if they were temporary */
+  return (TRUE);
+
+}
+
+
+int MS_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  int i, Nx, Ny;
+  float *out, *M1, *M2;
+  
+  Nx = V1[0].buffer[0].matrix.Naxis[0];
+  Ny = V1[0].buffer[0].matrix.Naxis[1];
+
+  /* if possible, use V1 as temp buffer, otherwise create new one */
+  if (V1[0].type == 'm') {
+    OUT[0].buffer = V1[0].buffer;
+    V1[0].type = 'M'; /* prevent it from being freed below */
+  } else {
+    OUT[0].buffer = InitBuffer ();
+    CopyBuffer (OUT[0].buffer, V1[0].buffer);
+  }
+  OUT[0].type = 'm';      /*** <<--- says this is a temporary matrix ***/
+  strcpy (OUT[0].name, "tmp");
+  M1  = V1[0].ptr;
+  M2  = V2[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].buffer[0].matrix.buffer;
+
+  switch (op[0]) { 
+  case '+': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++)
+      *out = *M1 + *M2;
+    break; 
+  case '-': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++)
+      *out = *M1 - *M2;
+    break; 
+  case '*': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++)
+      *out = *M1 * *M2;
+    break; 
+  case '/': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++)
+      *out = *M1 / *M2;
+    break; 
+  case 0x5e: 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = pow (*M1, *M2);
+    break; 
+  case 'D': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = MIN (*M1, *M2);
+    break; 
+  case 'U': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = MAX (*M1, *M2);
+    break; 
+  case '<': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = (*M1 < *M2) ? 1 : 0;
+    break; 
+  case '>': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = (*M1 > *M2) ? 1 : 0;
+    break; 
+  case '&': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = ((int)*M1 & (int)*M2);
+    break; 
+  case '|': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = ((int)*M1 | (int)*M2);
+    break; 
+  case 'E': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = (*M1 == *M2) ? 1 : 0;
+    break; 
+  case 'N': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = (*M1 != *M2) ? 1 : 0;
+    break; 
+  case 'L': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = (*M1 <= *M2) ? 1 : 0;
+    break; 
+  case 'G': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = (*M1 >= *M2) ? 1 : 0;
+    break; 
+  case 'A': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = (*M1 && *M2) ? 1 : 0;
+    break; 
+  case 'O': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = (*M1 || *M2) ? 1 : 0;
+    break; 
+  default:
+    fprintf (stderr, "error: op %c not defined!\n", op[0]);
+  }
+
+  if (V1[0].type == 'm') {
+    free (V1[0].buffer[0].header.buffer);
+    free (V1[0].buffer[0].matrix.buffer);
+    free (V1[0].buffer);
+  }
+  return (TRUE);
+
+}
+
+
+int SM_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  int i, Nx, Ny;
+  float *out, *M1, *M2;
+  
+  Nx = V2[0].buffer[0].matrix.Naxis[0];
+  Ny = V2[0].buffer[0].matrix.Naxis[1];
+
+  if (V2[0].type == 'm') {  /* V2[0] is NOT temporary, we can't use it for storage */
+    OUT[0].buffer = V2[0].buffer;
+    V2[0].type = 'M'; /* prevent it from being freed below */
+  } else {
+    OUT[0].buffer = InitBuffer ();
+    CopyBuffer (OUT[0].buffer, V2[0].buffer);
+  }
+  OUT[0].type = 'm'; /*** <<--- says this is a temporary matrix ***/
+  strcpy (OUT[0].name, "tmp");
+  M1  = V1[0].ptr;
+  M2  = V2[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].buffer[0].matrix.buffer;
+
+  switch (op[0]) { 
+  case '+': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++)
+      *out = *M1 + *M2;
+    break; 
+  case '-': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++)
+      *out = *M1 - *M2;
+    break; 
+  case '*': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++)
+      *out = *M1 * *M2;
+    break; 
+  case '/': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++)
+      *out = *M1 / *M2;
+    break; 
+  case 0x5e: 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++)
+      *out = pow (*M1, *M2);
+    break; 
+  case 'D': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = MIN (*M1, *M2);
+    break; 
+  case 'U': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = MAX (*M1, *M2);
+    break; 
+  case '<': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = (*M1 < *M2) ? 1 : 0;
+    break; 
+  case '>': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = (*M1 > *M2) ? 1 : 0;
+    break; 
+  case '&': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = ((int)*M1 & (int)*M2);
+    break; 
+  case '|': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = ((int)*M1 | (int)*M2);
+    break; 
+  case 'E': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = (*M1 == *M2) ? 1 : 0;
+    break; 
+  case 'N': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = (*M1 != *M2) ? 1 : 0;
+    break; 
+  case 'L': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = (*M1 <= *M2) ? 1 : 0;
+    break; 
+  case 'G': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = (*M1 >= *M2) ? 1 : 0;
+    break; 
+  case 'A': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = (*M1 && *M2) ? 1 : 0;
+    break; 
+  case 'O': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = (*M1 || *M2) ? 1 : 0;
+    break; 
+  default:
+    fprintf (stderr, "error: op %c not defined!\n", op[0]);
+  }
+
+  if (V2[0].type == 'm') {
+    free (V2[0].buffer[0].header.buffer);
+    free (V2[0].buffer[0].matrix.buffer);
+    free (V2[0].buffer);
+  }
+  return (TRUE);
+
+}
+
+
+int SS_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  float *M1, *M2, *out;
+  
+  M1  = V1[0].ptr;
+  M2  = V2[0].ptr;
+  OUT[0].ptr = V1[0].ptr;
+  out = OUT[0].ptr;
+  strcpy (OUT[0].name, "tmp");
+
+  switch (op[0]) { 
+  case '+': 
+    *out = *M1 + *M2;
+    break;    
+  case '-': 
+    *out = *M1 - *M2;
+    break;    
+  case '*': 
+    *out = *M1 * *M2;
+    break;    
+  case '/': 
+    *out = *M1 / *M2;
+    break; 
+  case 0x5e: 
+    *out = pow (*M1, *M2);
+    break; 
+  case 'D': 
+    *out = MIN (*M1, *M2);
+    break; 
+  case 'U': 
+    *out = MAX (*M1, *M2);
+    break; 
+  case '<': 
+    *out = (*M1 < *M2) ? 1 : 0;
+    break; 
+  case '>': 
+    *out = (*M1 > *M2) ? 1 : 0;
+    break; 
+  case '&': 
+    *out = ((int)*M1 & (int)*M2);
+    break; 
+  case '|': 
+    *out = ((int)*M1 | (int)*M2);
+    break; 
+  case 'E': 
+    *out = (*M1 == *M2) ? 1 : 0;
+    break; 
+  case 'N': 
+    *out = (*M1 != *M2) ? 1 : 0;
+    break; 
+  case 'L': 
+    *out = (*M1 <= *M2) ? 1 : 0;
+    break; 
+  case 'G': 
+    *out = (*M1 >= *M2) ? 1 : 0;
+    break; 
+  case 'A': 
+    *out = (*M1 && *M2) ? 1 : 0;
+    break; 
+  case 'O': 
+    *out = (*M1 || *M2) ? 1 : 0;
+    break; 
+  default:
+    fprintf (stderr, "error: op %c not defined!\n", op[0]);
+  }
+  OUT[0].Float = *(OUT[0].ptr);
+  OUT[0].type = 'S';
+  return (TRUE);
+
+}
+
+int S_unary (StackVar *OUT, StackVar *V1, char *op) {
+
+  float *out, *M1;
+  
+  out = OUT[0].ptr = V1[0].ptr;
+  M1  = V1[0].ptr;
+
+  if (!strcmp (op, "="))     {    }
+  if (!strcmp (op, "abs"))   {    *out = fabs(*M1);           }
+  if (!strcmp (op, "int"))   {    *out = (float)(int)(*M1);   }
+  if (!strcmp (op, "exp"))   {    *out = exp (*M1);           }
+  if (!strcmp (op, "ten"))   {    *out = pow (10.0,*M1);      }
+  if (!strcmp (op, "log"))   {    *out = log10 (*M1);         }
+  if (!strcmp (op, "ln"))    {    *out = log (*M1);           }
+  if (!strcmp (op, "sqrt"))  {    *out = sqrt (*M1);          }
+
+  if (!strcmp (op, "sinh"))  {    *out = sinhf (*M1);         }
+  if (!strcmp (op, "cosh"))  {    *out = coshf (*M1);         }
+  if (!strcmp (op, "asinh")) {    *out = asinhf (*M1);        }
+  if (!strcmp (op, "acosh")) {    *out = acoshf (*M1);        }
+
+  if (!strcmp (op, "sin"))   {    *out = sin (*M1);           }
+  if (!strcmp (op, "cos"))   {    *out = cos (*M1);           }
+  if (!strcmp (op, "tan"))   {    *out = tan (*M1);           }
+  if (!strcmp (op, "dsin"))  {    *out = sin (*M1*RAD_DEG);   }
+  if (!strcmp (op, "dcos"))  {    *out = cos (*M1*RAD_DEG);   }
+  if (!strcmp (op, "dtan"))  {    *out = tan (*M1*RAD_DEG);   }
+  if (!strcmp (op, "asin"))  {    *out = asin (*M1);          }
+  if (!strcmp (op, "acos"))  {    *out = acos (*M1);          }
+  if (!strcmp (op, "atan"))  {    *out = atan (*M1);          }
+  if (!strcmp (op, "dasin")) {    *out = asin (*M1)*DEG_RAD;  }
+  if (!strcmp (op, "dacos")) {    *out = acos (*M1)*DEG_RAD;  }
+  if (!strcmp (op, "datan")) {    *out = atan (*M1)*DEG_RAD;  }
+  if (!strcmp (op, "rnd"))   {    *out = drand48();           }
+  if (!strcmp (op, "not"))   {    *out = !(*M1);              }
+  if (!strcmp (op, "--"))    {    *out = - (*M1);             }
+  if (!strcmp (op, "isinf")) {    *out = !finite(*M1);        }
+  if (!strcmp (op, "isnan")) {    *out = isnan(*M1);          } 
+
+  OUT[0].Float = *out;
+  OUT[0].type = 'S';
+  return (TRUE);
+
+}
+
+int V_unary (StackVar *OUT, StackVar *V1, char *op) {
+
+  int i, Nx;
+  float *out, *M1;
+  
+  Nx = V1[0].vector[0].Nelements;
+ 
+  if (V1[0].type == 'v') {  /** use V1 as temp buffer **/
+    OUT[0].vector = V1[0].vector;
+    V1[0].type = 'V'; /* prevent it from being freed below */
+  } else {  /* no spare temp buffer */
+    OUT[0].vector = InitVector ();
+    CopyVector (OUT[0].vector, V1[0].vector);
+  }
+  OUT[0].type = 'v'; /*** <<--- says this is a temporary matrix ***/
+  M1  = V1[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].vector[0].elements;
+
+  if (!strcmp (op, "="))     { } /* already set equal */
+  if (!strcmp (op, "abs"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = fabs(*M1);         }}
+  if (!strcmp (op, "int"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = (float)(int)(*M1); }}
+  if (!strcmp (op, "exp"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = exp(*M1);          }}
+  if (!strcmp (op, "ten"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = pow(10.0,*M1);     }}
+  if (!strcmp (op, "log"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = log10(*M1);        }}
+  if (!strcmp (op, "ln"))    { for (i = 0; i < Nx; i++, out++, M1++) { *out = log(*M1);          }}
+  if (!strcmp (op, "sqrt"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = sqrt(*M1);         }}
+
+  if (!strcmp (op, "sinh"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = sinhf(*M1);       }}
+  if (!strcmp (op, "cosh"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = coshf(*M1);       }}
+  if (!strcmp (op, "asinh"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = asinhf(*M1);      }}
+  if (!strcmp (op, "acosh"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = acoshf(*M1);      }}
+
+  if (!strcmp (op, "sin"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = sin(*M1);          }}
+  if (!strcmp (op, "cos"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = cos(*M1);          }}
+  if (!strcmp (op, "tan"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = tan(*M1);          }}
+  if (!strcmp (op, "dsin"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = sin(*M1*RAD_DEG);  }}
+  if (!strcmp (op, "dcos"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = cos(*M1*RAD_DEG);  }}
+  if (!strcmp (op, "dtan"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = tan(*M1*RAD_DEG);  }}
+  if (!strcmp (op, "asin"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = asin(*M1);         }}
+  if (!strcmp (op, "acos"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = acos(*M1);         }}
+  if (!strcmp (op, "atan"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = atan(*M1);         }}
+  if (!strcmp (op, "dasin")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = asin(*M1)*DEG_RAD; }}
+  if (!strcmp (op, "dacos")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = acos(*M1)*DEG_RAD; }}
+  if (!strcmp (op, "datan")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = atan(*M1)*DEG_RAD; }}
+  if (!strcmp (op, "rnd"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = drand48();         }}
+  if (!strcmp (op, "ramp"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = i;                 }}
+  if (!strcmp (op, "zero"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = 0;                 }}
+  if (!strcmp (op, "not"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = !(*M1);            }}
+  if (!strcmp (op, "--"))    { for (i = 0; i < Nx; i++, out++, M1++) { *out = -(*M1);            }}
+  if (!strcmp (op, "isinf")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = !finite(*M1);      }}
+  if (!strcmp (op, "isnan")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = isnan(*M1);        }}
+
+  /* xramp and yramp only make sense in for matrices. for vectors, xramp = ramp, yramp = zero */
+  if (!strcmp (op, "xramp")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = i;                 }}
+  if (!strcmp (op, "yramp")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = 0;                 }}
+
+  if (V1[0].type == 'v') {
+    free (V1[0].vector[0].elements);
+    free (V1[0].vector);
+  }  
+  return (TRUE);
+
+}
+
+int M_unary (StackVar *OUT, StackVar *V1, char *op) {
+
+  int i, j, Nx, Ny;
+  float *out, *M1;
+  
+  Nx = V1[0].buffer[0].matrix.Naxis[0];
+  Ny = V1[0].buffer[0].matrix.Naxis[1];
+
+  if (V1[0].type == 'm') {
+    OUT[0].buffer = V1[0].buffer;
+    V1[0].type = 'M'; /* prevent it from being freed below */
+  } else {
+    OUT[0].buffer = InitBuffer ();
+    CopyBuffer (OUT[0].buffer, V1[0].buffer);
+  }
+  OUT[0].type = 'm';      /*** <<--- says this is a temporary matrix ***/
+  M1  = V1[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].buffer[0].matrix.buffer;
+
+  if (!strcmp (op, "="))     { }
+  if (!strcmp (op, "abs"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = fabs(*M1);         }}
+  if (!strcmp (op, "int"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = (float)(int)(*M1); }}
+  if (!strcmp (op, "exp"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = exp(*M1);          }}
+  if (!strcmp (op, "ten"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = pow(10.0,*M1);     }}
+  if (!strcmp (op, "log"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = log10(*M1);        }}
+  if (!strcmp (op, "ln"))    { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = log(*M1);          }}
+  if (!strcmp (op, "sqrt"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = sqrt(*M1);         }}
+
+  if (!strcmp (op, "sinh"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = sinhf(*M1);        }}
+  if (!strcmp (op, "cosh"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = coshf(*M1);        }}
+  if (!strcmp (op, "asinh")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = asinhf(*M1);       }}
+  if (!strcmp (op, "acosh")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = acoshf(*M1);       }}
+
+  if (!strcmp (op, "sin"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = sin(*M1);          }}
+  if (!strcmp (op, "cos"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = cos(*M1);          }}
+  if (!strcmp (op, "tan"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = tan(*M1);          }}
+  if (!strcmp (op, "dsin"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = sin(*M1*RAD_DEG);  }}
+  if (!strcmp (op, "dcos"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = cos(*M1*RAD_DEG);  }}
+  if (!strcmp (op, "dtan"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = tan(*M1*RAD_DEG);  }}
+  if (!strcmp (op, "asin"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = asin(*M1);         }}
+  if (!strcmp (op, "acos"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = acos(*M1);         }}
+  if (!strcmp (op, "atan"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = atan(*M1);         }}
+  if (!strcmp (op, "dasin")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = asin(*M1)*DEG_RAD; }}
+  if (!strcmp (op, "dacos")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = acos(*M1)*DEG_RAD; }}
+  if (!strcmp (op, "datan")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = atan(*M1)*DEG_RAD; }}
+  if (!strcmp (op, "not"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = !(*M1);            }}
+  if (!strcmp (op, "--"))    { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = -(*M1);            }}
+  if (!strcmp (op, "rnd"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = drand48();         }}
+  if (!strcmp (op, "ramp"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = i;                 }}
+  if (!strcmp (op, "zero"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = 0;                 }}
+  if (!strcmp (op, "isinf")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = !finite(*M1);      }}
+  if (!strcmp (op, "isnan")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = isnan(*M1);        }}
+
+  /* xrm and yrm only make sense in for matrices. see special meaning for vectors */
+  if (!strcmp (op, "xramp")) {
+    for (j = 0; j < Ny; j++) {
+      for (i = 0; i < Nx; i++, out++, M1++) {
+        *out = i;
+      }
+    }
+  }
+  if (!strcmp (op, "yramp")) {
+    for (j = 0; j < Ny; j++) {
+      for (i = 0; i < Nx; i++, out++, M1++) {
+        *out = j;
+      }
+    }
+  }
+  
+  if (V1[0].type == 'm') {
+    free (V1[0].buffer[0].header.buffer);
+    free (V1[0].buffer[0].matrix.buffer);
+    free (V1[0].buffer);
+  }
+  return (TRUE);
+
+}
+
+/*********************** fits copy header ***********************************/
+int fits_copy_matrix_info (Matrix *matrix1, Matrix *matrix2) {
+
+  int i;
+
+  /* copy all but the matrix */
+
+  matrix2[0].unsign = matrix1[0].unsign;
+  matrix2[0].bitpix = matrix1[0].bitpix;
+  matrix2[0].size   = matrix1[0].size;
+  matrix2[0].bzero  = matrix1[0].bzero;
+  matrix2[0].bscale = matrix1[0].bscale;
+  matrix2[0].Naxes  = matrix1[0].Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++) 
+    matrix2[0].Naxis[i] = matrix1[0].Naxis[i];
+
+
+  return (TRUE);
+}       
Index: /tags/start/Ohana/src/opihi/lib.shell/startup.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/startup.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/startup.c	(revision 12606)
@@ -0,0 +1,149 @@
+# include "opihi.h"
+
+/* program-independent initialization */
+void startup (int argc, char **argv) {
+
+  long A, B;
+    
+  signal (SIGINT, SIG_IGN);
+
+  /* init srand for rnd numbers elsewhere */
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+ 
+  if (0) {
+    /* fix the history list to remove the timestamp */
+    char *c;
+    int i;
+    HIST_ENTRY **entry;
+    
+    entry = history_list ();
+    if (entry != (HIST_ENTRY **) NULL) {
+      for (i = 0; entry[i]; i++) {
+	if ((strlen (entry[i][0].line) > 19) &&
+	    (entry[i][0].line[2] == '/') && 
+	    (entry[i][0].line[5] == '/') && 
+	    (entry[i][0].line[11] == ':') && 
+	    (entry[i][0].line[14] == ':') && 
+	    (entry[i][0].line[17] == ':')) {
+	  c = entry[i][0].line + 19;
+	  memmove (entry[i][0].line, c, strlen(c) + 1);
+	}
+      }
+    }
+  }
+  
+  /* keep these? 
+     set_int_variable ("UNSIGN", 0);
+     FT_UNSIGN_MODE = FALSE;
+  */
+
+  {
+    
+    int i, N, status, ONLY_INPUT, LOAD_RC;
+    char *line, *home, *outline, *varname;
+    char *rcfile, **list;
+    int Nlist, NLIST;
+    static char dot[] = ".";
+   
+    /* load in interesting environment variables */
+    ALLOCATE (line, char, 1024);
+    
+    home = getenv ("HOME");
+    if (home == NULL) home = dot;
+    set_str_variable ("HOME", home);
+    set_str_variable ("KII", "kii");
+    set_str_variable ("KAPA", "kapa");
+
+# if 0    
+    help = getenv ("MANA-HELP");
+    if (help == (char *) NULL) {
+      /* try in exec path */
+      ALLOCATE (help, char, 1024);
+      execdir = findexec (argc, argv);
+      if (execdir == (char *) NULL) {
+	fprintf (stderr, "error with executable name: can't resolve path\n");
+	execdir = strcreate (".");
+      }
+      execname = filebasename (argv[0]);
+      sprintf (help, "%s/%s.hlp", execdir, execname);
+    }
+    set_str_variable ("HELPDIR", help);
+# endif
+
+    if (!ConfigInit (&argc, argv)) {
+      fprintf (stderr, "can't find config file. some functions will be unavailable\n");
+    }
+
+    LOAD_RC = TRUE;
+    if ((N = get_argument (argc, argv, "--norc"))) {
+      remove_argument (N, &argc, argv);
+      LOAD_RC = FALSE;
+    }
+    
+    ONLY_INPUT = FALSE;
+    if ((N = get_argument (argc, argv, "--only"))) {
+      remove_argument (N, &argc, argv);
+      ONLY_INPUT = TRUE;
+    }
+
+    /* load cmdline files */
+    Nlist = 0;
+    NLIST = 10;
+    ALLOCATE (list, char *, NLIST);
+    while ((N = get_argument (argc, argv, "--load"))) {
+      remove_argument (N, &argc, argv);
+      list[Nlist] = strcreate (argv[N]);
+      remove_argument (N, &argc, argv);
+      Nlist++;
+      if (Nlist == NLIST) {
+	NLIST += 10;
+	REALLOCATE (list, char *, NLIST);
+      }
+    }
+
+    is_script = TRUE;
+    if (argc == 1) is_script = FALSE;
+    set_int_variable ("SCRIPT", is_script);
+
+    if (LOAD_RC && !is_script) {
+      rcfile = get_variable ("RCFILE");
+      sprintf (line, "input %s/%s", home, rcfile);
+      status = command (line, &outline);
+      if (outline != (char *) NULL) 
+	free (outline);
+      free (home);
+    }
+      
+    set_int_variable ("argv:n", 0);
+    if (is_script) {
+      /* first argument in input script, rest are argv */
+      list[Nlist] = strcreate (argv[1]);
+      Nlist ++;
+      /* generate list argv:0 - argv:n from arguments */
+      ALLOCATE (varname, char, 256);
+      for (i = 2; i < argc; i++) {
+	sprintf (varname, "argv:%d", i - 2);
+	set_str_variable (varname, argv[i]);
+      }
+      set_int_variable ("argv:n", i - 2);
+      free (varname);
+    }
+
+    /* execute command-line entries */
+    for (i = 0; i < Nlist; i++) {
+      ALLOCATE (line, char, 1024);
+      sprintf (line, "input %s", list[i]);
+      status = command (line, &outline);
+      if (outline != (char *) NULL) free (outline);
+    }
+    free (list);
+
+    /* if this is not an interactive session, exit here */
+    if (ONLY_INPUT) exit (2);
+    if (is_script) exit (2);
+    if (!isatty (STDIN_FILENO)) exit (2);
+    if (!isatty (STDOUT_FILENO)) exit (2);
+  }
+}
Index: /tags/start/Ohana/src/opihi/lib.shell/string.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/string.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/string.c	(revision 12606)
@@ -0,0 +1,240 @@
+# include "opihi.h"
+
+/**********************************************************************/
+/* returns a pointer to an isolated string containing the first word,
+   removing leading whitespace.  A "word" is a contiguous set of 
+   characters from the set: alphanumerics, and any of: / . _ -
+   Any other single, non-whitespace characters are considered to be 
+   complete words in themselves.  Any characters surrounded by quotes 
+   make a single word 
+*/
+
+char *thisword (char *string) {
+
+  int i, j, N;
+  char *word;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (i = 0; whitespace (string[i]); i++);
+  if (string[i] == 0) return ((char *)NULL);
+  if (string[i] == ';') {
+    word = strncreate (&string[i], 1);
+    return (word);
+  }
+
+  /* a string of characters contained within double quotes is 
+      a single entry.  check that there are pairs of quotes,
+      return only the string between the quotes */
+  if (string[i] == '"') { 
+    i++;
+    if (string[i] == 0) return ((char *) NULL);
+    for (j = i; (string[j] != 0) && (string[j] != '"'); j++);
+    if (string[j] == 0) {
+      fprintf (stderr, "misbalanced quotes\n");
+      return ((char *)NULL);
+    }
+    word = strncreate (&string[i], j - i);
+    return (word);
+  } 
+
+  /* a string of characters contained within parentheses is 
+      a single entry.  check that there are matched pairs of
+      parentheses, return string, including exterior parentheses */
+  if (string[i] == '(') { 
+    i++;
+    N = 1;
+    if (string[i] == 0) return ((char *) NULL);
+    for (j = i; (string[j] != 0) && (N > 0); j++) {
+      if (string[j] == '(') {
+	N++;
+      }
+      if (string[j] == ')') {
+	N--;
+      }
+    }
+    if ((string[j] == 0) && (N != 0)) {
+      fprintf (stderr, "misbalanced parenthesis\n");
+      return ((char *)NULL);
+    }
+    word = strncreate (&string[i-1], j - i + 1);
+    return (word);
+  } 
+
+
+  for (j = i; (string[j] != 0) && (string[j] != ';') && !whitespace(string[j]); j++);
+  word = strncreate (&string[i], j - i);
+  return (word);
+
+}
+
+/* returns a pointer to an isolated string containing the first command,
+   removing leading whitespace.  A command ends with the first non whitespace */
+char *thiscomm (char *string) {
+
+  int i, j;
+  char *word;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (i = 0; whitespace (string[i]); i++);
+  if (string[i] == 0) return ((char *)NULL);
+
+  for (j = i; ((string[j] != 0) && !whitespace (string[j])); j++);
+  if (i == j) return ((char *) NULL);
+
+  word = strncreate (&string[i], j - i);
+  return (word);
+
+}
+
+/* take a pointer to the beginning of a variable (ie $foo)
+and extract only the variable name (eg, foo) */
+
+char *thisvar (char *string) {
+
+  int i;
+  char *word;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+  if (string[0] != '$') return ((char *) NULL);
+
+  for (i = 1; ISVAR(string[i]); i++);
+  if (i == 1) return ((char *) NULL);
+
+  word = strncreate (&string[1], i - 1);
+  return (word);
+
+}
+
+
+/**********************************************************************/
+/* returns a pointer to the next word, or (char *) NULL if there is not a next word */
+char *nextword (char *string) {
+
+  int i, j;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (i = 0; whitespace (string[i]); i++);
+  if (string[i] == 0) return ((char *)NULL);
+
+  if (string[i] == '"') { 
+    i++;
+    if (string[i] == 0) return ((char *) NULL);
+    for (; (string[i] != 0) && (string[i] != '"'); i++);
+    if (string[i] == 0) {
+      fprintf (stderr, "misbalanced quotes\n");
+      return ((char *)NULL);
+    }
+    i++;
+    for (; (string[i] != 0) && whitespace (string[i]); i++);
+    if (string[i] == 0) return ((char *) NULL);
+    return (&string[i]);
+  } 
+
+  if (string[i] == '(') { 
+    i++; 
+    j = 1;
+    if (string[i] == 0) return ((char *) NULL);
+    for (; (string[i] != 0) && (j > 0); i++) {
+      if (string[i] == '(') {
+	j++;
+      }
+      if (string[i] == ')') {
+	j--;
+      }
+    }
+    if ((string[i] == 0) && (j != 0)) {
+      fprintf (stderr, "misbalanced parenthesis\n");
+      return ((char *)NULL);
+    }
+    for (; (string[i] != 0) && whitespace (string[i]); i++);
+    if (string[i] == 0) return ((char *) NULL);
+    return (&string[i]);
+  } 
+
+  if (string[i] == ';') i++;
+  for (; (string[i] != 0) && (string[i] != ';') && !whitespace(string[i]); i++);
+  for (; (string[i] != 0) && whitespace (string[i]); i++);
+  if (string[i] == 0) return ((char *) NULL);
+
+  return (&string[i]);
+}
+
+/* returns a pointer to the next command, or (char *) NULL 
+   if there is not a next command.  A command is bounded by whitespace */
+char *nextcomm (char *string) {
+
+  int i;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+  
+  for (i = 0; (string[i] != 0) && !whitespace (string[i]); i++);
+  if (string[i] == 0) return ((char *) NULL);
+  
+  for (; whitespace (string[i]); i++);
+  if (string[i] == 0) return ((char *) NULL);
+
+  return (&string[i]);
+}
+
+/* returns a pointer to the previous word,
+   or (char *) NULL if there is not a previous word
+*/
+char *lastword (char *string, char *c) {
+
+  if (string == (char *) NULL) return ((char *) NULL);
+  if (c == (char *) NULL) return ((char *) NULL);
+
+  for (; !whitespace(*c) && (c >= string); c--);
+  if (c < string) return ((char *)NULL);
+
+  for (; whitespace(*c) && (c >= string); c--);
+  if (c < string)
+    return ((char *)NULL);
+  for (; !whitespace(*c) && (c >= string); c--);
+  c++;
+  return (c);
+}
+
+
+
+/* take a pointer to the beginning of a variable (ie $fred) and return
+   a pointer to the next thing (non whitespace) which is not part of the
+   variable extract only the variable name */
+
+char *aftervar (char *string) {
+
+  int i, j;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+  if (string[0] != '$') return ((char *) NULL);
+
+  for (i = 1; ISVAR(string[i]); i++);
+  if (i == 1) return ((char *) NULL);
+
+  for (j = i; whitespace (string[j]); j++);
+  if (string[j] == 0) return ((char *)NULL);
+
+  return (&string[j]);
+
+}
+
+
+/* returns a pointer to the previous var, 
+   or (char *) NULL if there is not a previous word
+*/
+char *lastvar (char *string, char *c) {
+
+  if (string == (char *) NULL) return ((char *) NULL);
+  if (c == (char *) NULL) return ((char *) NULL);
+
+  for (; (c >= string) && whitespace(*c); c--);
+  if (c < string) return ((char *)NULL);
+
+  for (; (c >= string) && ISVAR(*c) ; c--);
+  if ((c < string) || (*c != '$')) return ((char *)NULL);
+
+  return (c);
+}
Index: /tags/start/Ohana/src/opihi/lib.shell/timeformat.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/timeformat.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/timeformat.c	(revision 12606)
@@ -0,0 +1,30 @@
+# include "opihi.h"
+
+int GetTimeFormat (time_t *TimeReference, int *TimeFormat) {
+
+  char *p;
+
+  *TimeReference = 0;
+  if ((p = get_variable ("TIMEREF")) != (char *) NULL) {
+    if (!str_to_time (p, TimeReference)) {
+      fprintf (stderr, "error in TIME_REF format\n");
+      return (FALSE);
+    }
+    free (p);
+  }
+  *TimeFormat = FALSE;
+  if ((p = get_variable ("TIMEFORMAT")) != (char *) NULL) {
+    if (!strcasecmp (p, "JD")) *TimeFormat     = TIME_JD;
+    if (!strcasecmp (p, "MJD")) *TimeFormat    = TIME_MJD;
+    if (!strcasecmp (p, "date")) *TimeFormat   = TIME_DATE;
+    if (!strcasecmp (p, "days")) *TimeFormat   = TIME_DAYS;
+    if (!strcasecmp (p, "hours")) *TimeFormat  = TIME_HOURS;
+    if (!strcasecmp (p, "min")) *TimeFormat    = TIME_MINUTES;
+    if (!strcasecmp (p, "sec")) *TimeFormat    = TIME_SECONDS;
+    if (!*TimeFormat) fprintf (stderr, "unknown TIME_FORMAT\n");
+    free (p);
+    return (FALSE);
+  }
+  if (!*TimeFormat) *TimeFormat = TIME_SECONDS;
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/lib.shell/variable.c
===================================================================
--- /tags/start/Ohana/src/opihi/lib.shell/variable.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib.shell/variable.c	(revision 12606)
@@ -0,0 +1,242 @@
+# include "opihi.h"
+
+Variable *variables;   /* variable to store the list of all variables */
+int      Nvariables;   /* number of currently available variables */
+
+void InitVariables () {
+  Nvariables = 0;
+  ALLOCATE (variables, Variable, 1); 
+}
+
+int set_local_variable (char *name, char *value) {
+
+  int i;
+  char *local, *MacroName;
+
+  /* a local variable has the form (macroname).(varname) */
+  MacroName = GetMacroName ();
+
+  /* look for global variable (warning or error)
+  for (i = 0; i < Nvariables; i++) {
+    if (!strcmp (name, variables[i].name)) {
+      fprintf (stderr, "warning: local variable overrides global name\n");
+    }
+  } */
+
+  /* look for existing local variable */
+  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
+  sprintf (local, "%s.%s", MacroName, name);
+  for (i = 0; i < Nvariables; i++) {
+    if (!strcmp (local, variables[i].name)) {
+      free (variables[i].value);
+      free (local);
+      variables[i].value = strcreate (value);
+      return (TRUE);
+    }
+  }
+  /* NEW variable */
+  Nvariables ++;
+  REALLOCATE (variables, Variable, Nvariables);
+  variables[Nvariables - 1].name = local;
+  variables[Nvariables - 1].value = strcreate (value);
+  return (TRUE);
+}
+
+int set_str_variable (char *name, char *value) {
+
+  int i;
+  char *local, *MacroName;
+
+  MacroName = GetMacroName ();
+
+  /* look for local variable first */
+  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
+  sprintf (local, "%s.%s", MacroName, name);
+  for (i = 0; i < Nvariables; i++) {
+    if (!strcmp (local, variables[i].name)) {
+      free (variables[i].value);
+      free (local);
+      variables[i].value = strcreate (value);
+      return (TRUE);
+    }
+  }
+  free (local);
+
+  /* look for global variable */
+  for (i = 0; i < Nvariables; i++) {
+    if (!strcmp (name, variables[i].name)) {
+      free (variables[i].value);
+      variables[i].value = strcreate (value);
+      return (TRUE);
+    }
+  }
+  /* NEW variable */
+  Nvariables ++;
+  REALLOCATE (variables, Variable, Nvariables);
+  variables[Nvariables - 1].name = strcreate (name);
+  variables[Nvariables - 1].value = strcreate (value);
+  return (TRUE);
+}
+
+int set_variable (char *name, double dvalue) {
+
+  char value[1024];
+
+  sprintf (value, "%.9g", dvalue);
+  set_str_variable (name, value);
+  return (TRUE);
+}
+
+int set_int_variable (char *name, int ivalue) {
+
+  char value[1024];
+
+  sprintf (value, "%d", ivalue);
+  set_str_variable (name, value);
+  return (TRUE);
+}
+
+char *get_variable_ptr (char *name) {
+  
+  int i;
+  char *local, *MacroName;
+
+  MacroName = GetMacroName ();
+
+  /* look for local variable first */
+  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
+  sprintf (local, "%s.%s", MacroName, name);
+  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
+    if (!strcmp(local, variables[i].name)) {
+      free (local);
+      return (variables[i].value);
+    }
+  }
+  free (local);
+
+  /* look for global variable */
+  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
+    if (!strcmp(name, variables[i].name)) {
+      return (variables[i].value);
+    }
+  }
+  return ((char *) NULL);
+}
+
+char *get_variable (char *name) {
+  
+  int i;
+  char *local, *MacroName;
+
+  MacroName = GetMacroName ();
+
+  /* look for local variable first */
+  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
+  sprintf (local, "%s.%s", MacroName, name);
+  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
+    if (!strcmp(local, variables[i].name)) {
+      free (local);
+      return (strcreate (variables[i].value));
+    }
+  }
+  free (local);
+
+  /* look for global variable */
+  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
+    if (!strcmp(name, variables[i].name)) {
+      return (strcreate (variables[i].value));
+    }
+  }
+  return ((char *) NULL);
+}
+
+char *get_local_variable_ptr (char *name) {
+  
+  int i;
+  char *local, *MacroName;
+
+  MacroName = GetMacroName ();
+
+  /* look for local variable first */
+  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
+  sprintf (local, "%s.%s", MacroName, name);
+  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
+    if (!strcmp(local, variables[i].name)) {
+      free (local);
+      return (variables[i].value);
+    }
+  }
+  free (local);
+  return ((char *) NULL);
+}
+
+double get_double_variable (char *name) {
+  
+  int i;
+  char *local, *MacroName;
+
+  MacroName = GetMacroName ();
+
+  /* look for local variable first */
+  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
+  sprintf (local, "%s.%s", MacroName, name);
+  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
+    if (!strcmp(local, variables[i].name)) {
+      free (local);
+      return (atof (variables[i].value));
+    }
+  }
+  free (local);
+
+  /* look for global variable */
+  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
+    if (!strcmp(name, variables[i].name)) {
+      return (atof (variables[i].value));
+    }
+  }
+  return (0.0);
+}
+
+int DeleteNamedScalar (char *name) {
+
+  int i, j;
+
+  for (i = 0; i < Nvariables; i++) {
+    if (!strcmp (name, variables[i].name)) {
+      free (variables[i].name);
+      free (variables[i].value);
+      for (j = i; j < Nvariables - 1; j++) {
+	variables[j] = variables[j + 1];
+      }
+      Nvariables --;
+      REALLOCATE (variables, Variable, MAX (Nvariables, 1));
+      return (TRUE);
+    }
+  }
+  return (FALSE);
+}
+
+int IsScalar (char *name) { 
+
+  int i;
+
+  for (i = 0; i < Nvariables; i++) {
+    if (!strcmp (name, variables[i].name)) return (TRUE);
+  }
+  return (FALSE);
+}
+
+void ListVariables () {
+
+  int i;
+
+  if (Nvariables == 0) {
+    fprintf (stderr, "No defined variables\n");
+    return;
+  }
+
+  for (i = 0; i < Nvariables; i++) {
+    fprintf (stderr, "%s = %s\n", variables[i].name, variables[i].value);
+  }
+  return;
+}
Index: /tags/start/Ohana/src/opihi/lib/.cvsignore
===================================================================
--- /tags/start/Ohana/src/opihi/lib/.cvsignore	(revision 12606)
+++ /tags/start/Ohana/src/opihi/lib/.cvsignore	(revision 12606)
@@ -0,0 +1,1 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
Index: /tags/start/Ohana/src/opihi/mana/Makefile
===================================================================
--- /tags/start/Ohana/src/opihi/mana/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/opihi/mana/Makefile	(revision 12606)
@@ -0,0 +1,122 @@
+include ../../../Configure
+
+default: all
+
+HOME    =       $(ROOT)/src/opihi.v2
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+HELP    =       $(HOME)/help
+SDIR    =       $(HOME)/mana
+#
+DESTBIN =       $(LBIN)
+DESTLIB =       $(LLIB)
+DESTINC =       $(LINC)
+DESTMAN =       $(LMAN)
+#  
+INCS    =       -I$(INC) -I$(LINC) -I$(XINC)
+LFLAGS  =       -L$(LLIB) -L$(LIB)
+LIBS1   =       -lFITS -lsocket -lnsl -lreadline -ltermcap -lohana -lm
+LIBS2   =       -lbasiccmd -ldatacmd -lastrocmd -lshell -ldata 
+LIBS    =       $(LIBS2) $(LIBS1) 
+CFLAGS  =       $(INCS)
+CCFLAGS =       $(LIBS) 
+
+# mana user commands and support functions ########################
+
+mana = \
+$(SDIR)/mana.$(ARCH).o
+
+all: mana
+
+mana: $(BIN)/mana.$(ARCH)
+	@echo done
+
+$(BIN)/mana.$(ARCH) : $(mana)
+
+install: $(DESTBIN)/mana
+
+# these need to have a better home
+# $(SDIR)/demux.$(ARCH).o		  	\
+# $(SDIR)/elixir.$(ARCH).o	  	\
+# $(SDIR)/adc.$(ARCH).o             	\
+# $(SDIR)/focus.$(ARCH).o		  	\
+# $(SDIR)/simsignal.$(ARCH).o	  	\
+
+# utilities #################################################
+$(BIN)/%.$(ARCH):
+	@if [ ! -d $(BIN) ]; then mkdir -p $(BIN); fi
+	$(CC) $^ -o $@ $(LFLAGS) $(LIBS)
+	@echo "compiled $*"
+	@echo ""
+
+$(DESTBIN)/%: $(BIN)/%.$(ARCH) 
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	rm -f $(DESTBIN)/$*
+	cp $(BIN)/$*.$(ARCH) $(DESTBIN)/$*
+	@echo "installed $*"
+	@echo ""
+
+$(LIB)/%.$(ARCH).a:
+	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
+	rm -f $@
+	ar rcv $@ $^ 
+	ranlib $@
+	@echo "compiled library $*"
+	@echo ""
+
+$(DESTLIB)/%.a: $(LIB)/%.$(ARCH).a
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	@echo ""
+	rm -f $@
+	cp $^ $@
+
+clean:
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f $(LIB)/*.$(ARCH).a
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+dist: clean
+	rm -f $(BIN)/*
+	rm -f $(LIB)/*
+
+lib%.clean:
+	rm -f $(LIB)/lib$*.$(ARCH).a
+	rm -f $($*)
+	@echo ""
+
+%.clean:
+	rm -f $(BIN)/$*.$(ARCH)
+	@echo ""
+
+%.$(ARCH).o : %.c
+	$(CC) $(CFLAGS) -c $*.c -o $@
+
+
+
+## -*- makefile -*- 
+# deprecated functions: verify & delete
+#$(SDIR)/abszero.$(ARCH).o \
+#$(SDIR)/cals.$(ARCH).o \
+#$(SDIR)/dumpmags.$(ARCH).o \
+#$(SDIR)/extract.$(ARCH).o \
+#$(SDIR)/gtypes.$(ARCH).o \
+#$(SDIR)/photresid.$(ARCH).o \
+#$(SDIR)/resid.$(ARCH).o \
+#$(SDIR)/zeropts.$(ARCH).o
+#$(SDIR)/objload.$(ARCH).o \ - make sure we have vect to tv
+#$(SDIR)/ccdextract.$(ARCH).o \
+#$(SDIR)/cmdextract.$(ARCH).o \
+#$(SDIR)/dmagextract.$(ARCH).o \
+#$(SDIR)/ddmagextract.$(ARCH).o \
+
+# future functions, not fully implemented
+#$(SDIR)/detrend.$(ARCH).o \
+#$(SDIR)/getxtra.$(ARCH).o \
+#$(SDIR)/addxtra.$(ARCH).o \
+
+# functions that need to be updated
+#$(SDIR)/gregions.$(ARCH).o \
+
Index: /tags/start/Ohana/src/opihi/mana/adc.c
===================================================================
--- /tags/start/Ohana/src/opihi/mana/adc.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/mana/adc.c	(revision 12606)
@@ -0,0 +1,117 @@
+# include "dimm.h"
+
+# define DIGITAL_OUT 0x40
+# define ANALOG_IN_INIT 0x00
+# define ANALOG_IN_HIGH 0xa1
+# define ANALOG_IN_LOW  0x91
+
+static char SerialConnected = FALSE;
+static unsigned char DigitalOutState = 0x00;
+static struct timeval reftime; 
+static char reftimeset = FALSE;
+
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+
+int adc (int argc, char **argv) {
+  
+  struct timeval now;
+  int i, N, mode, hi, lo, value;
+  unsigned char setbit, output[5], *input;
+  double dtime;
+
+  if (N = get_argument (argc, argv, "-reset")) {
+    remove_argument (N, &argc, argv);
+    gettimeofday (&reftime, (struct timeval *) NULL);
+    reftimeset = TRUE;
+    return (TRUE);
+  }
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: adc ai N (variable)\n");
+    fprintf (stderr, "USAGE: adc di N (variable)\n");
+    fprintf (stderr, "USAGE: adc do N mode\n");
+    return (FALSE);
+  }
+
+  if (!SerialConnected) {
+    if (!SerialInit ('b')) {
+      fprintf (stderr, "error opening serial line\n");
+      return (FALSE);
+    }
+    SerialConnected = TRUE;
+  }
+
+  if (!reftimeset) {
+    gettimeofday (&reftime, (struct timeval *) NULL);
+    reftimeset = TRUE;
+  }      
+
+  gettimeofday (&now, (struct timeval *) NULL);
+  dtime = DTIME (now, reftime);
+  set_variable ("TIME", dtime);
+  
+  /* set the digital outputs */
+  if (!strcmp (argv[1], "do")) {
+    N = atof (argv[2]);
+    if ((N < 1) || (N > 6)) {
+      fprintf (stderr, "digital output is between 1 and 6\n");
+      return (FALSE);
+    }
+    if (!strcasecmp (argv[3], "on")) {
+      mode = TRUE;
+    } else {
+      mode = FALSE;
+    }
+    setbit = (0x01 << N-1);
+    if (mode) {
+      DigitalOutState |= setbit;
+    } else {
+      DigitalOutState &= ~setbit;
+    }      
+    output[0] = (DIGITAL_OUT | DigitalOutState);
+    output[1] = 0;
+    SerialCommand (output, &input, 50);
+    fprintf (stderr, "%x (%x, %x) -> %x (%d, %d)\n", 
+	     output[0], setbit, DigitalOutState, input[0], 
+	     strlen(input), strlen(output));
+    free (input);
+    return (TRUE);
+  }
+  /* read the analog inputs */
+  if (!strcmp (argv[1], "ai")) {
+    N = atof (argv[2]);
+    if ((N < 2) || (N > 16)) {
+      fprintf (stderr, "analog input is between 2 and 16\n");
+      fprintf (stderr, " (problem with 1 for the moment...)\n");
+      return (FALSE);
+    }
+    /* init A/D converter */
+    output[0] = (ANALOG_IN_INIT | (N-1));
+    output[1] = 0;
+    SerialCommand (output, &input, 50);
+    free (input);
+
+    usleep (10000);
+    /* get high byte */
+    output[0] = ANALOG_IN_HIGH;
+    output[1] = 0;
+    do {
+      SerialCommand (output, &input, 50);
+      hi = input[0];
+      free (input);
+    } while (hi & 0x80);
+
+    output[0] = ANALOG_IN_LOW;
+    output[1] = 0;
+    SerialCommand (output, &input, 50);
+    /* fprintf (stderr, "%x -> %x\n", output[0], input[0]); */
+    lo = input[0];
+    free (input);
+    value = ((hi & 0x0f) << 8) | lo;
+    if (hi & 0x10) { value = -value; }
+    set_variable (argv[3], 0.0001*value);
+    return (TRUE);
+  }
+
+
+}
Index: /tags/start/Ohana/src/opihi/mana/demux.c
===================================================================
--- /tags/start/Ohana/src/opihi/mana/demux.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/mana/demux.c	(revision 12606)
@@ -0,0 +1,72 @@
+# include "dimm.h"
+
+int demux (int argc, char **argv) {
+  
+  int i, j, k, N;
+  float *out, *in, *inptr, **outptr;
+  int nx, ny, Nx, Ny, NX, NY, Nmux, Nbuf;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: demux <buffer> nx ny\n");
+    return (FALSE);
+  }
+
+  if (!SelectBuffer (&Nbuf, argv[1], OLDBUFFER)) return (FALSE);
+
+  nx = atof (argv[2]);
+  ny = atof (argv[3]);
+  Nmux = nx*ny;
+
+  Nx = buffers[Nbuf].matrix.Naxis[0];
+  Ny = buffers[Nbuf].matrix.Naxis[1];
+
+  NX = Nx / nx;
+  NY = Ny / ny;
+
+  inptr = in = (float *) buffers[Nbuf].matrix.buffer;  /* don't lose reference */
+
+  ALLOCATE (out, float, Nx*Ny);
+  ALLOCATE (outptr, float *, Nmux);
+  
+  for (N = i = 0; i < nx; i++) {
+    for (j = 0; j < ny; j++, N++) {
+      outptr[N] = &out[i*NX + j*NX*NY*nx];
+    }
+  }
+
+  for (N = j = 0; j < NY; j++) {
+    for (i = 0; i < NX; i++) {
+      for (k = 0; k < Nmux; k++) {
+	*outptr[k] = *inptr;
+	outptr[k] ++;
+	inptr ++;
+      }
+    }
+    for (k = 0; k < Nmux; k++) outptr[k] += NX;
+  }
+
+  /*
+  for (X = Y = x = y = i = 0; i < NX*NY; i++) {
+    out[X + Y*NX + x*NX*(Y+1) + y*NX*NY*nx] = *in;
+    X++;
+    if (X == NX) {
+      X = 0;
+      Y++;
+    }
+    if (Y == NY) {
+      Y = 0;
+      x++;
+    }
+    if (x == nx) {
+      x = 0;
+      y++;
+    }
+  }
+  */
+
+  free (in);
+  buffers[Nbuf].matrix.buffer = (char *) out;
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/opihi/mana/elixir.c
===================================================================
--- /tags/start/Ohana/src/opihi/mana/elixir.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/mana/elixir.c	(revision 12606)
@@ -0,0 +1,162 @@
+# include "dimm.h"
+
+int elixir (int argc, char **argv) {
+  
+  char message[256], cmd[256], ElixirBase[256];
+  char fifo[256], fifodir[256], msgfile[256];
+  char *answer;
+  int N;
+
+  sprintf (cmd, "STATUS");
+  if (N = get_argument (argc, argv, "-time")) {
+    remove_argument (N, &argc, argv);
+    sprintf (cmd, "TIMES");
+  }
+  if (N = get_argument (argc, argv, "-live")) {
+    remove_argument (N, &argc, argv);
+    sprintf (cmd, "ALIVE");
+  }
+  if (N = get_argument (argc, argv, "-stop")) {
+    remove_argument (N, &argc, argv);
+    sprintf (cmd, "STOP");
+  }
+  if (N = get_argument (argc, argv, "-kill")) {
+    remove_argument (N, &argc, argv);
+    sprintf (cmd, "ABORT");
+  }
+ 
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: elixir (elixir) [-time] [-live]\n");
+    return (FALSE);
+  }
+
+  if (!VarConfig (argv[1], "%s", ElixirBase)) {
+    fprintf (stderr, "elixir %s not in config file\n", argv[1]);
+    return (FALSE);
+  }
+  sprintf (fifo, "%s.msg", ElixirBase);
+  if (!VarConfig ("FIFOS", "%s", fifodir)) {
+    fprintf (stderr, "FIFOS not in config, using local /tmp\n");
+    strcpy (fifodir, "/tmp");
+  }
+  sprintf (fifo, "%s.msg", ElixirBase);
+
+  sprintf (msgfile, "%s/EMsg.XXXXXX", fifodir);
+  mkstemp (msgfile);
+  sprintf (message, "%s %s", cmd, msgfile);
+  unlink (msgfile);
+
+  if (!WriteMsg (fifo, message)) {
+    fprintf (stderr, "can't access fifo %s\n", fifo);
+    return (FALSE);
+  }
+
+  if (ReadMsg (msgfile, &answer)) {
+    fprintf (stderr, "%s\n", answer);
+  } 
+  unlink (msgfile);
+  return (TRUE);
+  
+}
+
+int WriteMsg (char *fifo, char *message) {
+
+  int fd, state, mode;
+  FILE *f;
+
+  /* check lockfile */
+  fd = setlockfile2 (fifo, 2.0, LCK_XCLD, &state);
+  if (fd == -1) return (0);
+  f = fdopen (fd, "r+");
+  if (f == (FILE *) NULL) {
+    mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    fchmod (fd, mode);
+    clearlockfile2 (fifo, fd, LCK_XCLD, &state);
+    return (0);
+  }
+
+  /* write message to end of file */
+  fseek (f, 0, SEEK_END);
+  fprintf (f, "%s\n", message);
+
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  fchmod (fd, mode);
+
+  clearlockfile2 (fifo, fd, LCK_XCLD, &state);
+  fclose (f);
+
+  return (1);
+
+}
+
+int ReadMsg (char *fifo, char **message) {
+
+  int i, nbytes, Nbytes, NBYTES;
+  char *buffer;
+  int fd, state, mode;
+  FILE *f;
+  struct stat filestat;
+
+  /* wait (2 sec) for file to exist, then try to read it */
+  for (i = 0; (stat (fifo, &filestat) == -1) && (i < 20); i++) {
+    usleep (100000);
+  }
+  if (i >= 20) {
+    fprintf (stderr, "no response\n");
+    return (0);
+  }
+
+  /* check lockfile */
+  fd = setlockfile2 (fifo, 2.0, LCK_XCLD, &state);
+  if (fd == -1) {
+    fprintf (stderr, "message locked (%d)\n", state);
+    return (0);
+  }
+  f = fdopen (fd, "r+");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "message blocked\n");
+    mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    fchmod (fd, mode);
+    clearlockfile2 (fifo, fd, LCK_XCLD, &state);
+    return (0);
+  }
+
+  /* if file is empty, return 0 */
+  if (state == LCK_EMPTY) {
+    mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    fchmod (fd, mode);
+    clearlockfile2 (fifo, fd, LCK_XCLD, &state);
+    fclose (f);
+    return (0);
+  }  
+
+  Nbytes = 0;
+  NBYTES = 0x1000;
+  ALLOCATE (buffer, char, NBYTES);
+  while (TRUE) {
+    nbytes = fread (&buffer[Nbytes], 1, 0x1000, f);
+    if (nbytes < 0) { 
+      fprintf (stderr, "error in ReadMsg -- got -1 bytes\n");
+      return (0);
+    }
+    if (nbytes == 0) break;
+    Nbytes += nbytes;
+    NBYTES += 0x1000;
+    REALLOCATE (buffer, char, NBYTES);
+  }
+  buffer[Nbytes] = 0;
+
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  fchmod (fd, mode);
+  clearlockfile2 (fifo, fd, LCK_XCLD, &state);
+  fclose (f);
+
+  if (Nbytes == 0) {
+    free (buffer);
+    return (0);
+  }
+
+  *message = buffer;
+  return (1);
+
+}
Index: /tags/start/Ohana/src/opihi/mana/focus.c
===================================================================
--- /tags/start/Ohana/src/opihi/mana/focus.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/mana/focus.c	(revision 12606)
@@ -0,0 +1,68 @@
+# include "dimm.h"
+
+int focus (int argc, char **argv) {
+  
+  if (argc < 2) goto usage;
+
+  if (!strcasecmp (argv[1], "init")) {
+    if (argc != 3) {
+      fprintf (stderr, "USAGE: focus init (port)\n");
+      return (FALSE);
+    }
+    if (!SerialInit (argv[2])) return (FALSE);
+    fprintf (stderr, "focus on port %s\n", argv[2]);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "pos")) {
+
+    int status, servo, angle;
+    char *answer = (char *) NULL;
+    char line[64];
+
+    if (argc != 4) {
+      fprintf (stderr, "USAGE: focus pos Nservo (angle)\n");
+      return (FALSE);
+    }
+
+    servo = atoi (argv[2]);
+    angle = atoi (argv[3]);
+
+    sprintf (line, "%c%c%c\n", 0xff, servo, angle);
+    status = SerialCommand (line, &answer, 10);
+    fprintf (stderr, "status: %d\n", status);
+    if (answer != (char *) NULL) {
+      fprintf (stderr, "answer: ..%s..\n", answer);
+    }
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "raw")) {
+
+    int status, value;
+    char *answer = (char *) NULL;
+    char line[64];
+
+    if (argc != 3) {
+      fprintf (stderr, "USAGE: focus raw value\n");
+      return (FALSE);
+    }
+
+    value = atoi (argv[2]);
+
+    sprintf (line, "%c", value);
+    status = SerialCommand (line, &answer, 10);
+    fprintf (stderr, "status: %d\n", status);
+    if (answer != (char *) NULL) {
+      fprintf (stderr, "answer: ..%s..\n", answer);
+    }
+    return (TRUE);
+  }
+
+ usage:
+  fprintf (stderr, "focus init port\n");
+  fprintf (stderr, "focus pos (string)\n");
+  fprintf (stderr, "focus raw (value)\n");
+  return (FALSE);
+}
+
Index: /tags/start/Ohana/src/opihi/mana/mana.c
===================================================================
--- /tags/start/Ohana/src/opihi/mana/mana.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/mana/mana.c	(revision 12606)
@@ -0,0 +1,79 @@
+# include "opihi.h"
+
+# define opihi_name "MANA"
+# define opihi_prompt "mana: "
+# define opihi_description "an image manipulation tool\n"
+# define opihi_history ".mana"
+# define opihi_rcfile ".manarc"
+
+void InitBasic ();
+void InitData ();
+void InitAstro ();
+
+
+void welcome () {
+  fprintf (stderr, "\n");
+  fprintf (stderr, "Welcome to %s - %s\n\n", opihi_name, opihi_description);
+}
+
+/* program-dependent initialization */
+void initialize (int argc, char **argv) {
+  
+  FILE *f;
+
+  auto_break = TRUE;
+
+  Nlists = 0;
+  ALLOCATE (lists, List, 1); 
+
+  /* init functions required by libraries */
+  /* -libopihi */
+  InitCommands ();
+  InitMacros ();
+  InitBuffers ();
+  InitVectors ();
+  InitVariables ();
+
+  /* -libdisplay */
+  InitGraph ();
+  InitImage ();
+
+  /* load the commands used by this implementation */
+  InitBasic ();
+  InitData ();
+  InitAstro ();
+  InitOutfile ();
+
+  rl_readline_name = opihi_name;
+  rl_attempted_completion_function = command_completer;
+
+  set_str_variable ("HISTORY", opihi_history);
+  set_str_variable ("PROMPT", opihi_prompt);
+  set_str_variable ("RCFILE", opihi_rcfile);
+
+  /* here we open the history file for append.  it this fails, we
+     won't be able to write to it, warn the user.  otherwise, this
+     creates the file readline will write to, if it did not exist */  
+
+  /* check history file */
+  /* rewrite with fstat or stat */
+  f = fopen (opihi_history, "a");
+  if (f == NULL) /* no current history file here */
+    fprintf (stderr, "can't save history.\n");
+  else
+    fclose (f);
+  
+  stifle_history (200);
+  read_history (opihi_history);
+
+  signal (SIGINT, SIG_IGN);
+  return;
+}
+
+/* add program-dependent exit functions here */
+void cleanup () {
+  /* -libdisplay */
+  QuitImage ();
+  QuitGraph ();
+  return;
+}
Index: /tags/start/Ohana/src/opihi/mana/opihi.c
===================================================================
--- /tags/start/Ohana/src/opihi/mana/opihi.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/mana/opihi.c	(revision 12606)
@@ -0,0 +1,74 @@
+# include "opihi.h"
+
+# define opihi_name "Opihi"
+# define opihi_prompt "opihi: "
+# define opihi_description "Opihi - test shell\n"
+# define opihi_history ".opihi"
+# define opihi_rcfile ".opihirc"
+
+void InitBasic ();
+
+void welcome () {
+  fprintf (stderr, "\n");
+  fprintf (stderr, "Welcome to %s - %s\n\n", opihi_name, opihi_description);
+}
+
+/* program-dependent initialization */
+void initialize (int argc, char **argv) {
+  
+  FILE *f;
+
+  auto_break = TRUE;
+
+  Nlists = 0;
+  ALLOCATE (lists, List, 1); 
+
+  /* init functions required by libraries */
+  /* -libopihi */
+  InitCommands ();
+  InitMacros ();
+  InitBuffers ();
+  InitVectors ();
+  InitVariables ();
+
+  /* -libdisplay
+  InitGraph ();
+  InitImage (); */
+
+  /* load the commands used by this implementation */
+  InitBasic ();
+  InitOutfile ();
+
+  rl_readline_name = opihi_name;
+  rl_attempted_completion_function = command_completer;
+
+  set_str_variable ("HISTORY", opihi_history);
+  set_str_variable ("PROMPT", opihi_prompt);
+  set_str_variable ("RCFILE", opihi_rcfile);
+
+  /* here we open the history file for append.  it this fails, we
+     won't be able to write to it, warn the user.  otherwise, this
+     creates the file readline will write to, if it did not exist */  
+
+  /* check history file */
+  /* rewrite with fstat or stat */
+  f = fopen (opihi_history, "a");
+  if (f == NULL) /* no current history file here */
+    fprintf (stderr, "can't save history.\n");
+  else
+    fclose (f);
+  
+  stifle_history (200);
+  read_history (opihi_history);
+
+  signal (SIGINT, SIG_IGN);
+  return;
+}
+
+/* add program-dependent exit functions here */
+void cleanup () {
+  /* -libdisplay
+  QuitImage ();
+  QuitGraph (); */
+  return;
+}
Index: /tags/start/Ohana/src/opihi/mana/simsignal.c
===================================================================
--- /tags/start/Ohana/src/opihi/mana/simsignal.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/mana/simsignal.c	(revision 12606)
@@ -0,0 +1,50 @@
+# include "dimm.h"
+
+int simsignal (int argc, char **argv) {
+  
+  int Nvect, Nbin, Nbit, i, ivalue, jvalue, Nshift, mask, scale;
+  float *buf;
+  double cvalue, dvalue, sigma, SN, period;
+  double rnd_gauss ();
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: simsignal (vector) Nbin Nbits period\n");
+    return (FALSE);
+  }
+
+  if (!SelectVector (&Nvect, argv[1], ANYVECTOR)) return (FALSE);
+  Nbin = atof (argv[2]);
+  Nbit = atof (argv[3]);
+  /* SN = atof (argv[4]); */
+  period = atof (argv[4]);
+
+  vectors[Nvect].Nelements = Nbin;
+  REALLOCATE (vectors[Nvect].elements, float, vectors[Nvect].Nelements);
+
+  scale = (0x1 << Nbit) - 1;
+
+  buf = vectors[Nvect].elements;
+  for (i = 0; i < Nbin; i++, buf++) {
+    ivalue = scale * 0.5 * (sin (i*2*M_PI/period) + 1) + 0.5;
+    /*
+    dvalue = rnd_gauss (cvalue, sigma);
+    cvalue = (dvalue + range) / (2.0*range);
+    dvalue = MAX (0, MIN (0.99999, cvalue));
+    ivalue = scale * dvalue;
+    *buf = (2.0 * range * ((double) ivalue + 0.5)) / scale - range; 
+    */
+    *buf = ivalue;
+  }
+
+  return (TRUE);
+}
+
+/* 
+
+8 bit = 2^8
+
+  gauss_init (2*scale);
+  sigma = 2.0 / SN;
+  range = 1 + 5*sigma;
+
+*/
Index: /tags/start/Ohana/src/opihi/mana/tests.c
===================================================================
--- /tags/start/Ohana/src/opihi/mana/tests.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/mana/tests.c	(revision 12606)
@@ -0,0 +1,108 @@
+# include "opihi.h"
+
+run_tests () {
+
+  /* test1 ();
+     test1b ();
+     test2 ();
+     test3 (); */
+  test4 (); 
+  test5 ();
+}
+
+test1 () {
+
+  int i, size;
+  char *test, *line;
+
+  fprintf (stderr, "starting test 1...  ");
+  ALLOCATE (test, char, 256);
+  sprintf (test, "100");
+  for (i = 0; i < 1000000; i++) {
+    line = dvomath (1, &test, &size, 0);
+    if (line != NULL) free (line);
+  }
+  fprintf (stderr, "done with test 1\n");
+  sleep (1);
+}
+
+test1b () {
+
+  int i, size;
+  char *test, *line;
+
+  fprintf (stderr, "starting test 1b...  ");
+  ALLOCATE (test, char, 256);
+  sprintf (test, "dsin(45)");
+  for (i = 0; i < 1000000; i++) {
+    line = dvomath (1, &test, &size, 0);
+    if (line != NULL) free (line);
+  }
+  fprintf (stderr, "done with test 1b\n");
+  sleep (1);
+}
+
+test2 () {
+
+  int i, size;
+  char *test, *line;
+
+  fprintf (stderr, "starting test 2...  ");
+  ALLOCATE (test, char, 256);
+  sprintf (test, "5 * 100");
+  for (i = 0; i < 1000000; i++) {
+    line = dvomath (1, &test, &size, 0);
+    if (line != NULL) free (line);
+  }
+  fprintf (stderr, "done with test 2\n");
+  sleep (1);
+}
+
+test3 () {
+
+  int i, size;
+  char *test, *line;
+
+  fprintf (stderr, "starting test 3...  ");
+  ALLOCATE (test, char, 256);
+  sprintf (test, "5 * dsin(45)");
+  for (i = 0; i < 1000000; i++) {
+    line = dvomath (1, &test, &size, 0);
+    if (line != NULL) free (line);
+  }
+  fprintf (stderr, "done with test 3\n");
+  sleep (1);
+}
+
+test4 () {
+
+  int i;
+  char *test, *line;
+
+  fprintf (stderr, "starting test 4...  ");
+  for (i = 0; i < 1000000; i++) {
+    ALLOCATE (test, char, 256);
+    sprintf (test, "$N = 100");
+    line = parse (test);
+    if (line != NULL) free (line);
+  }
+  fprintf (stderr, "done with test 4\n");
+  sleep (1);
+}
+
+test5 () {
+
+  int i;
+  char *test, *line;
+
+  fprintf (stderr, "starting test 5...  ");
+  for (i = 0; i < 1000000; i++) {
+    ALLOCATE (test, char, 256);
+    sprintf (test, "echo {100 * 800}");
+    line = parse (test);
+    if (line != NULL) free (line);
+  }
+  fprintf (stderr, "done with test 5\n");
+  sleep (1);
+}
+
Index: /tags/start/Ohana/src/opihi/pantasks/JobOps.c
===================================================================
--- /tags/start/Ohana/src/opihi/pantasks/JobOps.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/pantasks/JobOps.c	(revision 12606)
@@ -0,0 +1,220 @@
+# include "opihi.h"
+# include "scheduler.h"
+
+# define MAX_N_JOBS 1000
+static char *JobIDList;
+static int   JobIDPtr = 0;
+
+static char dot[] = ".";
+
+static Job *jobs;
+static int   Njobs;
+static int   NJOBS;
+
+static char *JobName = dot;
+static int   CurrentJob = 0;
+
+/* provide a mechanism to loop over the list of jobs */
+Job *NextJob () {
+  
+  Job *job;
+
+  if (CurrentJob >= Njobs) {
+    CurrentJob = 0;
+    return (NULL);
+  }
+
+  job = &jobs[CurrentJob];
+  CurrentJob ++;
+  return (job);
+}
+
+void InitJobs () {
+  NJOBS = 20;
+  Njobs = 0;
+  ALLOCATE (jobs, Job, NJOBS);
+  JobName = dot;
+
+  ALLOCATE (JobIDList, char, MAX_N_JOBS);
+  bzero (JobIDList, MAX_N_JOBS*sizeof(char));
+}
+
+/* return next unique ID, recycle every MAX_N_JOBS */
+int NextJobID () {
+
+  int Ntry;
+
+  JobIDPtr ++;
+  if (JobIDPtr >= MAX_N_JOBS) JobIDPtr = 0;
+
+  Ntry = 0;
+  while (JobIDList[JobIDPtr]) {
+    Ntry ++;
+    JobIDPtr ++;
+    if (JobIDPtr >= MAX_N_JOBS) JobIDPtr = 0;
+    if (Ntry == MAX_N_JOBS) return (-1);
+  }
+  JobIDList[JobIDPtr] = TRUE;
+  return (JobIDPtr);
+}
+
+/* list known jobs */
+void ListJobs () {
+
+  int i;
+
+  for (i = 0; i < Njobs; i++) {
+    fprintf (stderr, "%d: %-15s %5d %20s (%x)\n", Njobs, jobs[i].task.name, jobs[i].JobID, jobs[i].task.argv[0], jobs[i].task.argv);
+  }
+  return;
+}
+
+/* return job with given name */
+Job *FindJob (int JobID) {
+
+  int i;
+
+  /* try for an exact match first */
+  for (i = 0; i < Njobs; i++) {
+    if (jobs[i].JobID == JobID) {
+      return (&jobs[i]);
+    }
+  }
+  return (NULL);
+}  
+
+/* make a new job from a task */
+Job *CreateJob (Task *task) {
+  
+  int i;
+
+  jobs[Njobs].JobID = NextJobID ();
+  jobs[Njobs].PID = 0;
+  jobs[Njobs].task = task[0];
+
+  /* we need our own copy of task[0].argv */
+  ALLOCATE (jobs[Njobs].task.argv, char *, MAX (jobs[Njobs].task.argc, 1));
+  for (i = 0; i < jobs[Njobs].task.argc; i++) {
+    jobs[Njobs].task.argv[i] = strcreate (task[0].argv[i]);
+  }
+  jobs[Njobs].task.host = strcreate (task[0].host);
+
+  Njobs ++;
+  if (Njobs == NJOBS) {
+    NJOBS += 20;
+    REALLOCATE (jobs, Job, NJOBS);
+  }
+  return (&jobs[Njobs-1]);
+}
+
+void SetCurrentJob (char *name) {
+  JobName = name;
+}
+
+char *GetCurrentJob () {
+  return (JobName);
+}
+
+void FreeJob (Job *job) {
+  
+  int i;
+
+  if (job == NULL) return;
+
+  if ((job[0].JobID >= 0) || (job[0].JobID < MAX_N_JOBS)) {
+    JobIDList[job[0].JobID] = FALSE;
+  }
+
+  for (i = 0; i < job[0].task.argc; i++) {
+    free (job[0].task.argv[i]);
+  }
+  free (job[0].task.argv);
+  free (job[0].task.host);
+  return;
+}
+
+int DeleteJob (Job *job) {
+
+  int i, Nm;
+
+  Nm = -1;
+  for (i = 0; i < Njobs; i++) {
+    if (job == &jobs[i]) {
+      Nm = i;
+      break;
+    }
+  }
+  if (Nm == -1) {
+    fprintf (stderr, "programming error: job not found\n");
+    return (FALSE);
+  }
+
+  FreeJob (&jobs[Nm]);
+  for (i = Nm + 1; i < Njobs; i++)
+    jobs[i - 1] = jobs[i];
+  Njobs --;
+
+  CurrentJob --;
+  CurrentJob = MAX (CurrentJob, 0);
+
+  return (TRUE);
+}
+
+/* this needs to: 1) distinguish local from controller jobs
+   2) fork the local jobs in the background
+   3) send the controller jobs to the controller */
+
+int SubmitJob (Job *job) {
+
+  int i, Nchar;
+  char *string;
+
+  Nchar = 0;
+  for (i = 0; i < job[0].task.argc; i++) {
+    Nchar += strlen (job[0].task.argv[i]) + 1;
+  }
+  ALLOCATE (string, char, Nchar);
+  bzero (string, Nchar);
+
+  strcat (string, job[0].task.argv[0]);
+  for (i = 1; i < job[0].task.argc; i++) {
+    strcat (string, " ");
+    strcat (string, job[0].task.argv[i]);
+  }
+  
+  fprintf (stderr, "executing job %d ...%s...\n", job[0].JobID, string);
+  free (string);
+
+  /* reset clock for start and poll-test */
+  gettimeofday (&job[0].start, (void *) NULL);
+  job[0].last = job[0].start;
+  
+  return (TRUE);
+}
+
+int CheckJob (Job *job) {
+
+  float f;
+  f = drand48 ();
+
+  if ((0.00 < f) && (f < 0.25)) {
+    job[0].state = JOB_BUSY;
+    job[0].exit_status = -1;
+    return (JOB_BUSY);
+  }
+  if ((0.25 < f) && (f < 0.50)) {
+    job[0].state = JOB_BUSY;
+    job[0].exit_status = -1;
+    return (JOB_CRASH);
+  }
+  if ((0.50 < f) && (f < 0.75)) {
+    job[0].state = JOB_BUSY;
+    job[0].exit_status = 0;
+    return (JOB_EXIT);
+  }
+  if ((0.75 < f) && (f < 1.00)) {
+    job[0].state = JOB_BUSY;
+    job[0].exit_status = 1;
+    return (JOB_EXIT);
+  }
+}
Index: /tags/start/Ohana/src/opihi/pantasks/Makefile
===================================================================
--- /tags/start/Ohana/src/opihi/pantasks/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/opihi/pantasks/Makefile	(revision 12606)
@@ -0,0 +1,124 @@
+include ../../../Configure
+
+default: all
+
+HOME    =       $(ROOT)/src/opihi.v2
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+HELP    =       $(HOME)/help
+SDIR    =       $(HOME)/sched
+#
+DESTBIN =       $(LBIN)
+DESTLIB =       $(LLIB)
+DESTINC =       $(LINC)
+DESTMAN =       $(LMAN)
+#  
+INCS    =       -I$(INC) -I$(LINC) -I$(XINC)
+LFLAGS  =       -L$(LLIB) -L$(LIB)
+LIBS1   =       -lFITS -lsocket -lnsl -lreadline -ltermcap -lohana -lm
+LIBS2   =       -lbasiccmd -ldatacmd -lastrocmd -lshell -ldata 
+LIBS    =       $(LIBS2) $(LIBS1) 
+CFLAGS  =       $(INCS)
+CCFLAGS =       $(LIBS) 
+
+# sched user commands and support functions ########################
+
+sched = \
+$(SDIR)/schedule.$(ARCH).o \
+$(SDIR)/task.$(ARCH).o \
+$(SDIR)/task_command.$(ARCH).o \
+$(SDIR)/task_host.$(ARCH).o \
+$(SDIR)/task_macros.$(ARCH).o \
+$(SDIR)/task_periods.$(ARCH).o \
+$(SDIR)/JobOps.$(ARCH).o \
+$(SDIR)/TaskOps.$(ARCH).o \
+$(SDIR)/init.$(ARCH).o \
+$(SDIR)/scheduler.$(ARCH).o
+
+all: scheduler
+
+scheduler: $(BIN)/scheduler.$(ARCH)
+	@echo done
+
+$(BIN)/scheduler.$(ARCH) : $(sched)
+
+install: $(DESTBIN)/scheduler
+
+# utilities #################################################
+$(BIN)/%.$(ARCH):
+	@if [ ! -d $(BIN) ]; then mkdir -p $(BIN); fi
+	$(CC) $^ -o $@ $(LFLAGS) $(LIBS)
+	@echo "compiled $*"
+	@echo ""
+
+$(DESTBIN)/%: $(BIN)/%.$(ARCH) 
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	rm -f $(DESTBIN)/$*
+	cp $(BIN)/$*.$(ARCH) $(DESTBIN)/$*
+	@echo "installed $*"
+	@echo ""
+
+$(LIB)/%.$(ARCH).a:
+	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
+	rm -f $@
+	ar rcv $@ $^ 
+	ranlib $@
+	@echo "compiled library $*"
+	@echo ""
+
+$(DESTLIB)/%.a: $(LIB)/%.$(ARCH).a
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	@echo ""
+	rm -f $@
+	cp $^ $@
+
+clean:
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f $(LIB)/*.$(ARCH).a
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+dist: clean
+	rm -f $(BIN)/*
+	rm -f $(LIB)/*
+
+lib%.clean:
+	rm -f $(LIB)/lib$*.$(ARCH).a
+	rm -f $($*)
+	@echo ""
+
+%.clean:
+	rm -f $(BIN)/$*.$(ARCH)
+	@echo ""
+
+%.$(ARCH).o : %.c
+	$(CC) $(CFLAGS) -c $*.c -o $@
+
+
+
+## -*- makefile -*- 
+# deprecated functions: verify & delete
+#$(SDIR)/abszero.$(ARCH).o \
+#$(SDIR)/cals.$(ARCH).o \
+#$(SDIR)/dumpmags.$(ARCH).o \
+#$(SDIR)/extract.$(ARCH).o \
+#$(SDIR)/gtypes.$(ARCH).o \
+#$(SDIR)/photresid.$(ARCH).o \
+#$(SDIR)/resid.$(ARCH).o \
+#$(SDIR)/zeropts.$(ARCH).o
+#$(SDIR)/objload.$(ARCH).o \ - make sure we have vect to tv
+#$(SDIR)/ccdextract.$(ARCH).o \
+#$(SDIR)/cmdextract.$(ARCH).o \
+#$(SDIR)/dmagextract.$(ARCH).o \
+#$(SDIR)/ddmagextract.$(ARCH).o \
+
+# future functions, not fully implemented
+#$(SDIR)/detrend.$(ARCH).o \
+#$(SDIR)/getxtra.$(ARCH).o \
+#$(SDIR)/addxtra.$(ARCH).o \
+
+# functions that need to be updated
+#$(SDIR)/gregions.$(ARCH).o \
+
Index: /tags/start/Ohana/src/opihi/pantasks/TaskOps.c
===================================================================
--- /tags/start/Ohana/src/opihi/pantasks/TaskOps.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/pantasks/TaskOps.c	(revision 12606)
@@ -0,0 +1,142 @@
+# include "opihi.h"
+# include "scheduler.h"
+
+static char dot[] = ".";
+
+static Task *tasks;
+static int   Ntasks;
+static int   NTASKS;
+
+static char *TaskName = dot;
+
+static int   CurrentTask = 0;
+
+/* provide a mechanism to loop over the list of tasks */
+Task *NextTask () {
+  
+  Task *task;
+
+  if (CurrentTask >= Ntasks) {
+    CurrentTask = 0;
+    return (NULL);
+  }
+
+  task = &tasks[CurrentTask];
+  CurrentTask ++;
+  return (task);
+}
+
+void InitTasks () {
+  NTASKS = 20;
+  Ntasks = 0;
+  ALLOCATE (tasks, Task, NTASKS);
+  TaskName = dot;
+}
+
+/* list known tasks */
+void ListTasks () {
+
+  int i;
+
+  for (i = 0; i < Ntasks; i++) {
+    fprintf (stderr, "%-15s %20s\n", tasks[i].name, tasks[i].argv[0]);
+  }
+  return;
+}
+
+/* show details of a task */
+int ShowTask (char *name) {
+
+  int i;
+  Task *task;
+
+  task = FindTask (name);
+  if (task == NULL) {
+    fprintf (stderr, "task %s not found\n", name);
+    return (FALSE);
+  }
+
+  fprintf (stderr, "macro %s\n", task[0].name);
+
+  fprintf (stderr, "command: ");
+  for (i = 0; i < task[0].argc; i++) {
+    fprintf (stderr, "%s ", task[0].argv[i]);
+  }
+
+  fprintf (stderr, "host: %s\n", task[0].host);
+  fprintf (stderr, "time periods: exec: %f  poll: %f  timeout: %f\n", 
+	   task[0].exec_period, task[0].poll_period, task[0].timeout_period);
+
+  fprintf (stderr, "pre-execute macro\n");
+  ListMacro (task[0].exec);
+
+  fprintf (stderr, "timeout macro\n");
+  ListMacro (task[0].timeout);
+
+  fprintf (stderr, "crash macro\n");
+  ListMacro (task[0].crash);
+
+  fprintf (stderr, "default exit macro\n");
+  ListMacro (task[0].def);
+
+  for (i = 0; i < task[0].Nexit; i++) {
+    fprintf (stderr, "exit macro (status == %d)\n", atoi(task[0].exit[i][0].name));
+    ListMacro (task[0].exit[i]);
+  }
+
+  return (TRUE);
+}
+
+/* return task with given name */
+Task *FindTask (char *name) {
+
+  int i;
+
+  /* try for an exact match first */
+  for (i = 0; i < Ntasks; i++) {
+    if (!strcmp (tasks[i].name, name)) {
+      return (&tasks[i]);
+    }
+  }
+  return (NULL);
+}  
+
+/* make a new named task */
+Task *CreateTask (char *name) {
+  
+  tasks[Ntasks].name = strcreate (name);;
+
+  tasks[Ntasks].host = NULL;
+
+  tasks[Ntasks].argc = 0;
+  tasks[Ntasks].argv = NULL;
+
+  tasks[Ntasks].exec = NULL;
+  tasks[Ntasks].crash = NULL;
+  tasks[Ntasks].timeout = NULL;
+
+  tasks[Ntasks].Nexit = 0;
+  tasks[Ntasks].NEXIT = 10;
+  ALLOCATE (tasks[Ntasks].exit, Macro *, tasks[Ntasks].NEXIT);
+  /* don't free tasks[0].exit, keep at least 1 allocated */
+
+  tasks[Ntasks].exec_period = 1.0;
+  tasks[Ntasks].poll_period = 1.0;
+  tasks[Ntasks].timeout_period = 1.0;
+
+  Ntasks ++;
+  if (Ntasks == NTASKS) {
+    NTASKS += 20;
+    REALLOCATE (tasks, Task, NTASKS);
+  }
+  return (&tasks[Ntasks-1]);
+}
+
+void SetCurrentTask (char *name) {
+  TaskName = name;
+}
+
+char *GetCurrentTask () {
+  return (TaskName);
+}
+
Index: /tags/start/Ohana/src/opihi/pantasks/init.c
===================================================================
--- /tags/start/Ohana/src/opihi/pantasks/init.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/pantasks/init.c	(revision 12606)
@@ -0,0 +1,29 @@
+# include "basic.h"
+# include "scheduler.h"
+
+int task	    PROTO((int, char **));
+int task_host	    PROTO((int, char **));
+int task_macros	    PROTO((int, char **));
+int task_command    PROTO((int, char **));
+int task_periods    PROTO((int, char **));
+int schedule        PROTO((int, char **));
+
+static Command cmds[] = {  
+  {"task",      task,         "define a schedulable task"},
+  {"host",      task_host,    "define host machine for a task"},
+  {"task.exit", task_macros,  "define exit macros for a task"},
+  {"task.exec", task_macros,  "define pre-exec macro for a task"},
+  {"command",   task_command, "define executed command for a task"},
+  {"periods",   task_periods, "define time scales for a task"},
+  {"schedule",  schedule,     "schedule the tasks"},
+}; 
+
+void InitSched () {
+  
+  int i;
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+
+}
Index: /tags/start/Ohana/src/opihi/pantasks/sched.txt
===================================================================
--- /tags/start/Ohana/src/opihi/pantasks/sched.txt	(revision 12606)
+++ /tags/start/Ohana/src/opihi/pantasks/sched.txt	(revision 12606)
@@ -0,0 +1,52 @@
+
+scheduler commands:
+
+task (taskname)
+ - define a new task
+ - loads task-related commands from list / readline
+ - commands are parsed on load
+ - end with end (like if / for)
+
+task.exit (value)
+ - define a new task macro for this exit condition
+   (value) may be an exit status (number)
+   (value) may be 'timeout'
+   (value) may be 'crash' ?
+ - commands are parsed on execution (not on definition)
+
+task.exec
+ - define a task macro for exec condition
+ - commands are parsed on execution (not on definition)
+
+command (args) (args)
+ - defines command associated with task
+ - may be in task or in task.macro (exit/exec)
+   (in task, command line is static; in task.macro, command line is expanded for each instance)
+
+host (machine)
+ - defines preferred host
+ - may be in task or in task.macro (exit/exec)
+   (in task, value is static; in task.macro, value is defined for each instance)
+
+stderr (file / variable)
+ - defines destination for stderr capture from task
+ - written to destination at end of execution?
+
+stdout (file / variable)
+ - defines destination for stdout capture from task
+ - written to destination at end of execution?
+
+periods -poll 1
+periods -exec 30
+periods -timeout 2
+ - defines relevant time-scale for the task
+
+schedule
+ - runs the scheduler loop, executing the various tasks
+
+scheduler functions:
+
+InitTasks ();
+FindTask ();
+CreateTask ();
+
Index: /tags/start/Ohana/src/opihi/pantasks/schedule.c
===================================================================
--- /tags/start/Ohana/src/opihi/pantasks/schedule.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/pantasks/schedule.c	(revision 12606)
@@ -0,0 +1,134 @@
+# include "basic.h"
+# include "scheduler.h"
+
+int schedule (int argc, char **argv) {
+
+  Job *job;
+  Task *task;
+  Macro *macro;
+  struct timeval now;
+  double dtime;
+  int i, found, status;
+  int Ntest;
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: schedule\n");
+    return (FALSE);
+  }
+
+  /*
+  task = NextTask ();
+  CreateJob (task);
+  CreateJob (task);
+  job = NextJob ();
+  DeleteJob (job);
+  CreateJob (task);
+  return (FALSE);
+  */
+
+  /* start the clock for all tasks */
+  while ((task = NextTask ()) != NULL) {
+    gettimeofday (&task[0].last, (void *) NULL);
+  }
+
+  Ntest = 0;
+
+  while (1) {
+    if (Ntest > 5) { 
+      ListJobs ();
+      Ntest = 0;
+    }
+    usleep (10000);
+    Ntest ++;
+
+    /** test all tasks **/
+    while ((task = NextTask ()) != NULL) {
+
+      /* check exec period (ready to run again?) */
+      gettimeofday (&now, (void *) NULL);
+      dtime = DTIME (now, task[0].last);
+      if (dtime < task[0].exec_period) continue;
+
+      SetCurrentTask (task[0].name);
+      fprintf (stderr, "trying task %s\n", task[0].name);
+
+      /* run task.exec macro */
+      if (task[0].exec != NULL) {
+	status = exec_loop (task[0].exec);
+	if (!status) continue;
+      }
+
+      /* is task valid ?(argc, argv) */
+
+      /* construct job from task */
+      job = CreateJob (task);
+
+      /* execute job */
+      SubmitJob (job);
+
+      /* reset timer on task (don't do this if Create/Submit fails)*/
+      gettimeofday (&task[0].last, (void *) NULL);
+
+    }
+
+    /** test all jobs **/
+    while ((job = NextJob ()) != NULL) {
+
+      /* check poll period (ready to run again?) */
+      gettimeofday (&now, (void *) NULL);
+
+      dtime = DTIME (now, job[0].last);
+      if (dtime >= job[0].task.poll_period) {
+	/* check current status */
+	status = CheckJob (job);
+	switch (status) {
+	case JOB_BUSY:
+	  fprintf (stderr, "job %s (%d) busy\n", job[0].task.name, job[0].JobID);
+	  break;
+
+	case JOB_CRASH:
+	  fprintf (stderr, "job %s (%d) crash\n", job[0].task.name, job[0].JobID);
+	  if (job[0].task.crash != NULL) {
+	    exec_loop (job[0].task.crash);
+	  }
+	  DeleteJob (job);
+	  continue;
+	  break;
+
+	case JOB_EXIT:
+	  fprintf (stderr, "job %s (%d) exit\n", job[0].task.name, job[0].JobID);
+	  /* look for corresponding exit macro */
+	  macro = job[0].task.def;
+	  for (i = 0; i < job[0].task.Nexit; i++) {
+	    if (job[0].exit_status == atoi(job[0].task.exit[i][0].name)) {
+	      macro = job[0].task.exit[i];
+	      break;
+	    }
+	  }
+	  if (macro != NULL) exec_loop (macro);
+	  DeleteJob (job);
+	  continue;
+	  break;
+
+	default:
+	  fprintf (stderr, "unknown exit status\n");
+	  break;
+	}
+	job[0].last = now;
+      }
+
+      dtime = DTIME (now, job[0].start);
+      if (dtime >= job[0].task.timeout_period) {
+	fprintf (stderr, "timeout on %s\n", job[0].task.name);
+	if (job[0].task.timeout != NULL) {
+	  exec_loop (job[0].task.timeout);
+	}
+	DeleteJob (job);
+	continue;
+      }
+    }
+  }
+
+  return (TRUE);
+
+}
Index: /tags/start/Ohana/src/opihi/pantasks/scheduler.c
===================================================================
--- /tags/start/Ohana/src/opihi/pantasks/scheduler.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/pantasks/scheduler.c	(revision 12606)
@@ -0,0 +1,81 @@
+# include "opihi.h"
+# include "scheduler.h"
+
+# define opihi_name "scheduler"
+# define opihi_prompt "sched: "
+# define opihi_description "parallel task scheduler\n"
+# define opihi_history ".sched"
+# define opihi_rcfile ".schedrc"
+
+void InitBasic ();
+void InitData ();
+void InitSched ();
+
+void welcome () {
+  fprintf (stderr, "\n");
+  fprintf (stderr, "Welcome to %s - %s\n\n", opihi_name, opihi_description);
+}
+
+/* program-dependent initialization */
+void initialize (int argc, char **argv) {
+  
+  FILE *f;
+
+  auto_break = TRUE;
+
+  Nlists = 0;
+  ALLOCATE (lists, List, 1); 
+
+  /* init functions required by libraries */
+  /* -libopihi */
+  InitCommands ();
+  InitMacros ();
+  InitBuffers ();
+  InitVectors ();
+  InitVariables ();
+
+  /* -libdisplay */
+  InitGraph ();
+  InitImage ();
+
+  /* load the commands used by this implementation */
+  InitBasic ();
+  InitData ();
+  InitOutfile ();
+  InitSched ();
+  InitTasks ();
+  InitJobs ();
+
+  rl_readline_name = opihi_name;
+  rl_attempted_completion_function = command_completer;
+
+  set_str_variable ("HISTORY", opihi_history);
+  set_str_variable ("PROMPT", opihi_prompt);
+  set_str_variable ("RCFILE", opihi_rcfile);
+
+  /* here we open the history file for append.  it this fails, we
+     won't be able to write to it, warn the user.  otherwise, this
+     creates the file readline will write to, if it did not exist */  
+
+  /* check history file */
+  /* rewrite with fstat or stat */
+  f = fopen (opihi_history, "a");
+  if (f == NULL) /* no current history file here */
+    fprintf (stderr, "can't save history.\n");
+  else
+    fclose (f);
+  
+  stifle_history (200);
+  read_history (opihi_history);
+
+  signal (SIGINT, SIG_IGN);
+  return;
+}
+
+/* add program-dependent exit functions here */
+void cleanup () {
+  /* -libdisplay
+  QuitImage ();
+  QuitGraph (); */
+  return;
+}
Index: /tags/start/Ohana/src/opihi/pantasks/schinit.c
===================================================================
--- /tags/start/Ohana/src/opihi/pantasks/schinit.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/pantasks/schinit.c	(revision 12606)
@@ -0,0 +1,76 @@
+# include "opihi.h"
+
+# define opihi_name "MANA"
+# define opihi_prompt "mana: "
+# define opihi_description "an image manipulation tool\n"
+# define opihi_history ".mana"
+# define opihi_rcfile ".manarc"
+
+void InitBasic ();
+
+void welcome () {
+  fprintf (stderr, "\n");
+  fprintf (stderr, "Welcome to %s - %s\n\n", opihi_name, opihi_description);
+}
+
+/* program-dependent initialization */
+void initialize (int argc, char **argv) {
+  
+  FILE *f;
+
+  auto_break = TRUE;
+
+  Nlists = 0;
+  ALLOCATE (lists, List, 1); 
+
+  /* init functions required by libraries */
+  /* -libopihi */
+  InitCommands ();
+  InitMacros ();
+  InitBuffers ();
+  InitVectors ();
+  InitVariables ();
+
+  /* -libdisplay */
+  InitGraph ();
+  InitImage ();
+
+  /* load the commands used by this implementation */
+  InitBasic ();
+  InitData ();
+  InitAstro ();
+  InitOutfile ();
+
+  rl_readline_name = opihi_name;
+  rl_attempted_completion_function = command_completer;
+
+  set_str_variable ("HISTORY", opihi_history);
+  set_str_variable ("PROMPT", opihi_prompt);
+  set_str_variable ("RCFILE", opihi_rcfile);
+
+  /* here we open the history file for append.  it this fails, we
+     won't be able to write to it, warn the user.  otherwise, this
+     creates the file readline will write to, if it did not exist */  
+
+  /* check history file */
+  /* rewrite with fstat or stat */
+  f = fopen (opihi_history, "a");
+  if (f == NULL) /* no current history file here */
+    fprintf (stderr, "can't save history.\n");
+  else
+    fclose (f);
+  
+  stifle_history (200);
+  read_history (opihi_history);
+
+  signal (SIGINT, SIG_IGN);
+  return;
+}
+
+/* add program-dependent exit functions here */
+void cleanup () {
+  /* -libdisplay
+  QuitImage ();
+  QuitGraph (); */
+  return;
+}
Index: /tags/start/Ohana/src/opihi/pantasks/task.c
===================================================================
--- /tags/start/Ohana/src/opihi/pantasks/task.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/pantasks/task.c	(revision 12606)
@@ -0,0 +1,113 @@
+# include "basic.h"
+# include "scheduler.h"
+# define prompt "> "
+
+enum {TASK_NONE, TASK_EMPTY, TASK_COMMENT, TASK_END, TASK_HOST, TASK_COMMAND, TASK_PERIODS, TASK_EXIT, TASK_EXEC};
+
+int task (int argc, char **argv) {
+
+  int N;
+  int ThisList, status;
+  char *input, *outline;
+  Macro *macro;
+  Task *task;
+
+  if (N = get_argument (argc, argv, "-list")) {
+    remove_argument (N, &argc, argv);
+    ListTasks ();
+    return (TRUE);
+  }
+
+  if (N = get_argument (argc, argv, "-show")) {
+    remove_argument (N, &argc, argv);
+    ShowTask (argv[N]);
+    return (TRUE);
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: task <name>\n");
+    fprintf (stderr, "  (enter commands & task functions; end with the word 'END')\n");
+    return (FALSE);
+  }
+
+  task = FindTask (argv[1]);
+  if (task == NULL) { /**** new task ****/
+    task = CreateTask (argv[1]);
+  }
+  SetCurrentTask (argv[1]);
+
+  /* read in task from appropriate source (keyboard or list) until end */
+
+  /* allowed tokens: command, host, stderr, periods, end */
+
+  ThisList = Nlists;
+  while (1) {
+
+    /* get the next line (from correct place) */
+    if (ThisList == 0) 
+      input = readline (prompt);
+    else 
+      input = get_next_listentry (ThisList);
+
+    if ((ThisList == 0) && (input == (char *) NULL)) {
+      fprintf (stderr, "end task with 'END'\n");
+      continue;
+    }
+    if ((ThisList > 0) && (input == (char *) NULL)) {
+      fprintf (stderr, "missing 'END' in task definition\n");
+      input = strcreate ("end");
+    }
+
+    stripwhite (input);
+    switch (TaskHash (input)) {
+
+      case TASK_EMPTY:
+      case TASK_COMMENT:
+	free (input);
+	break;
+
+      case TASK_END:
+	free (input);
+	return (TRUE);
+	break;
+
+      case TASK_HOST:
+      case TASK_EXIT:
+      case TASK_EXEC:
+      case TASK_COMMAND:
+      case TASK_PERIODS:
+	status = command (input, &outline);
+	if (outline != NULL) free (outline);
+	/* what to do if command is invalid?
+	   if (!status) return (FALSE); */
+	break;
+
+      case TASK_NONE:
+	fprintf (stderr, "unknown task command %s\n", input);
+	break;
+    }
+  }
+  return (TRUE);
+}
+
+int TaskHash (char *input) {
+  
+  int hash;
+  char *command;
+
+  hash = TASK_NONE;
+
+  command = thisword (input);
+  if (command == NULL) return (TASK_EMPTY);
+
+  if (command[0] == '#')                  hash = TASK_COMMENT;
+  if (!strcasecmp (command, "END"))       hash = TASK_END;
+  if (!strcasecmp (command, "HOST"))      hash = TASK_HOST;
+  if (!strcasecmp (command, "COMMAND"))   hash = TASK_COMMAND;
+  if (!strcasecmp (command, "PERIODS"))   hash = TASK_PERIODS;
+  if (!strcasecmp (command, "TASK.EXIT")) hash = TASK_EXIT;
+  if (!strcasecmp (command, "TASK.EXEC")) hash = TASK_EXEC;
+
+  free (command);
+  return (hash);
+}
Index: /tags/start/Ohana/src/opihi/pantasks/task_command.c
===================================================================
--- /tags/start/Ohana/src/opihi/pantasks/task_command.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/pantasks/task_command.c	(revision 12606)
@@ -0,0 +1,50 @@
+# include "basic.h"
+# include "scheduler.h"
+
+int task_command (int argc, char **argv) {
+
+  int i;
+  char *taskname;
+  Task *task;
+
+  if (argc < 2) {
+    fprintf (stderr, "USAGE: command <command> <arg>. ..\n");
+    fprintf (stderr, "  (define command machine for this task (or 'none'))\n");
+    return (FALSE);
+  }
+
+  taskname = GetCurrentTask ();
+  if (taskname == NULL) {
+    fprintf (stderr, "ERROR: not defining or running a task\n");
+    return (FALSE);
+  }
+  task = FindTask (taskname);
+  if (task == NULL) {
+    fprintf (stderr, "ERROR: current task not found??\n");
+    return (FALSE);
+  }
+
+  /* free existing memory used by argv */
+  if (task[0].argc != 0) {
+    for (i = 0; i < task[0].argc; i++) {
+      if (task[0].argv[i] != NULL) free (task[0].argv[i]);
+    }
+    free (task[0].argv);
+  }
+
+  /* create new memory for argv */
+  task[0].argc = argc - 1;
+  ALLOCATE (task[0].argv, char *, MAX (task[0].argc, 1));
+  for (i = 0; i < task[0].argc; i++) {
+    task[0].argv[i] = strcreate (argv[i+1]);
+  }
+  return (TRUE);
+}
+
+
+/** 
+    careful with this: the command is supposed to be realized 
+    for the Job, not the Task (at execution)
+    the code is right, but who calls it when needs to be clarified.
+ **/
+
Index: /tags/start/Ohana/src/opihi/pantasks/task_host.c
===================================================================
--- /tags/start/Ohana/src/opihi/pantasks/task_host.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/pantasks/task_host.c	(revision 12606)
@@ -0,0 +1,33 @@
+# include "basic.h"
+# include "scheduler.h"
+
+int task_host (int argc, char **argv) {
+
+  Task *task;
+  char *taskname;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: host <name>\n");
+    fprintf (stderr, "  (define host machine for this task (or 'none'))\n");
+    return (FALSE);
+  }
+
+  taskname = GetCurrentTask ();
+  if (taskname == NULL) {
+    fprintf (stderr, "ERROR: not defining or running a task\n");
+    return (FALSE);
+  }
+  task = FindTask (taskname);
+  if (task == NULL) {
+    fprintf (stderr, "ERROR: current task not found??\n");
+    return (FALSE);
+  }
+
+  if (task[0].host != NULL) free (task[0].host);
+  task[0].host = NULL;
+
+  if (!strcasecmp (argv[1], "NONE")) return (TRUE);
+
+  task[0].host = strcreate (argv[1]);
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/pantasks/task_macros.c
===================================================================
--- /tags/start/Ohana/src/opihi/pantasks/task_macros.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/pantasks/task_macros.c	(revision 12606)
@@ -0,0 +1,154 @@
+# include "basic.h"
+# include "scheduler.h"
+# define D_NLINES 100
+# define prompt "> "
+
+int task_macros (int argc, char **argv) {
+
+  int i, N, NLINES, done, depth, ThisList;
+  char *taskname, *input;
+  Macro *macro;
+  Task *task;
+
+  if (!strcmp (argv[0], "task.exec") && (argc != 1)) {
+    fprintf (stderr, "USAGE: task.exec\n");
+    fprintf (stderr, "  (define pre-exec macro for this task)\n");
+    return (FALSE);
+  }
+
+  if (!strcmp (argv[0], "task.exit") && (argc != 2)) {
+    fprintf (stderr, "USAGE: task.exit (state)\n");
+    fprintf (stderr, "  (define exit state macro for this task)\n");
+    return (FALSE);
+  }
+
+  taskname = GetCurrentTask ();
+  if (taskname == NULL) {
+    fprintf (stderr, "ERROR: not defining or running a task\n");
+    return (FALSE);
+  }
+  task = FindTask (taskname);
+  if (task == NULL) {
+    fprintf (stderr, "ERROR: current task not found??\n");
+    return (FALSE);
+  }
+
+  /*** identify which Macro in Task this particular macro goes with ***/ 
+  if (!strcmp (argv[0], "task.exec")) {
+    if (task[0].exec != NULL) {
+      FreeMacro (task[0].exec);
+      free (task[0].exec);
+    }
+    ALLOCATE (task[0].exec, Macro, 1);
+    macro = task[0].exec;
+    macro[0].name = strcreate ("exec");
+    goto found;
+  }
+  if (!strcmp (argv[0], "task.exit") && !strcmp (argv[1], "timeout")) {
+    if (task[0].timeout != NULL) {
+      FreeMacro (task[0].timeout);
+      free (task[0].timeout);
+    }
+    ALLOCATE (task[0].timeout, Macro, 1);
+    macro = task[0].timeout;
+    macro[0].name = strcreate ("timeout");
+    goto found;
+  }
+  if (!strcmp (argv[0], "task.exit") && !strcmp (argv[1], "crash")) {
+    if (task[0].crash != NULL) {
+      FreeMacro (task[0].crash);
+      free (task[0].crash);
+    }
+    ALLOCATE (task[0].crash, Macro, 1);
+    macro = task[0].crash;
+    macro[0].name = strcreate ("crash");
+    goto found;
+  }
+  if (!strcmp (argv[0], "task.exit") && !strcmp (argv[1], "default")) {
+    if (task[0].def != NULL) {
+      FreeMacro (task[0].def);
+      free (task[0].def);
+    }
+    ALLOCATE (task[0].def, Macro, 1);
+    macro = task[0].def;
+    macro[0].name = strcreate ("default");
+    goto found;
+  }
+  if (!strcmp (argv[0], "task.exit")) {	/* generic exit function */
+    for (i = 0; i < task[0].Nexit; i++) { /* find exiting exit function with same name */
+      if (!strcmp (task[0].exit[i][0].name, argv[1])) {	/*** replace this one ***/
+	FreeMacro (task[0].exit[i]);
+	free (task[0].exit[i]);
+	ALLOCATE (task[0].exit[i], Macro, 1);
+	macro = task[0].exit[i];
+	macro[0].name = strcreate (argv[1]);
+	goto found;
+      }
+    }
+    /** create a new exit status macro **/
+    N = task[0].Nexit;
+    ALLOCATE (task[0].exit[N], Macro, 1);
+    task[0].Nexit ++;
+    if (task[0].Nexit == task[0].NEXIT) {
+      task[0].NEXIT += 10;
+      REALLOCATE (task[0].exit, Macro *, task[0].NEXIT);
+    }
+    macro = task[0].exit[N];
+    macro[0].name = strcreate (argv[1]);
+    goto found;
+  }
+
+found:
+
+  macro[0].Nlines = 0;
+  NLINES = D_NLINES;
+  ALLOCATE (macro[0].line, char *, NLINES);
+
+  /* load macro lines from appropriate source (readline / list) */
+
+  depth = 0;
+  done = FALSE;
+  ThisList = Nlists;
+  while (!done) {
+
+    /* get the next line (from correct place) */
+    if (ThisList == 0) 
+      input = readline (prompt);
+    else 
+      input = get_next_listentry (ThisList);
+
+    if ((ThisList == 0) && (input == (char *) NULL)) {
+      fprintf (stderr, "end macro with 'END'\n");
+      continue;
+    }
+    if ((ThisList > 0) && (input == (char *) NULL)) {
+      fprintf (stderr, "missing 'END' in macro definition\n");
+      input = strcreate ("end");
+    }
+
+    stripwhite (input);
+
+    /* test for new macro (or other list, in the future?) */
+    if (is_list (input)) depth ++;
+
+    /* test for end of nested list -- if not nested, END refers to this macro */
+    if (!strncasecmp (input, "END", 3)) {
+      depth --;
+      if (depth < 0) { /* we hit the last "END", macro is done */
+	free (input);
+	REALLOCATE (macro[0].line, char *, MAX (1, macro[0].Nlines));
+	return (TRUE);
+      }
+    }
+
+    if (*input) { 
+      macro[0].line[macro[0].Nlines] = input;
+      macro[0].Nlines ++;
+      if (macro[0].Nlines == NLINES - 1) {
+	NLINES += D_NLINES;
+	REALLOCATE (macro[0].line, char *, NLINES);
+      }
+    }
+  }
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/opihi/pantasks/task_periods.c
===================================================================
--- /tags/start/Ohana/src/opihi/pantasks/task_periods.c	(revision 12606)
+++ /tags/start/Ohana/src/opihi/pantasks/task_periods.c	(revision 12606)
@@ -0,0 +1,65 @@
+# include "basic.h"
+# include "scheduler.h"
+
+int task_periods (int argc, char **argv) {
+
+  int N, Poll, Exec, Timeout;
+  float PollValue, ExecValue, TimeoutValue;
+  char *taskname;
+  Task *task;
+
+  Poll = FALSE;
+  if (N = get_argument (argc, argv, "-poll")) {
+    Poll = TRUE;
+    remove_argument (N, &argc, argv);
+    PollValue = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Exec = FALSE;
+  if (N = get_argument (argc, argv, "-exec")) {
+    Exec = TRUE;
+    remove_argument (N, &argc, argv);
+    ExecValue = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Timeout = FALSE;
+  if (N = get_argument (argc, argv, "-timeout")) {
+    Timeout = TRUE;
+    remove_argument (N, &argc, argv);
+    TimeoutValue = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: periods [-poll value] [-exec value] [-timeout value]\n");
+    fprintf (stderr, "  define time periods for this task\n");
+    return (FALSE);
+  }
+
+  taskname = GetCurrentTask ();
+  if (taskname == NULL) {
+    fprintf (stderr, "ERROR: not defining or running a task\n");
+    return (FALSE);
+  }
+  task = FindTask (taskname);
+  if (task == NULL) {
+    fprintf (stderr, "ERROR: current task not found??\n");
+    return (FALSE);
+  }
+
+  if (Poll) task[0].poll_period = PollValue;
+  if (Exec) task[0].exec_period = ExecValue;
+  if (Timeout) task[0].timeout_period = TimeoutValue;
+
+  return (TRUE);
+}
+
+
+/** 
+    careful with this: the command is supposed to be realized 
+    for the Job, not the Task (at execution)
+    the code is right, but who calls it when needs to be clarified.
+ **/
+
Index: /tags/start/Ohana/src/opihi/scripts/sample.sh
===================================================================
--- /tags/start/Ohana/src/opihi/scripts/sample.sh	(revision 12606)
+++ /tags/start/Ohana/src/opihi/scripts/sample.sh	(revision 12606)
@@ -0,0 +1,9 @@
+#!/usr/bin/env dvo
+
+echo "test"
+
+for i 0 $argv:n
+ echo $i $argv:$i
+end
+
+exit 0
Index: /tags/start/Ohana/src/opihi/scripts/sched.pro
===================================================================
--- /tags/start/Ohana/src/opihi/scripts/sched.pro	(revision 12606)
+++ /tags/start/Ohana/src/opihi/scripts/sched.pro	(revision 12606)
@@ -0,0 +1,28 @@
+
+task foo
+  command ls foo baz
+  periods -poll 2.0
+  periods -exec 1.0
+  periods -timeout 5.0
+  host kiawe
+
+  task.exit 0
+    echo "successful job"
+  end
+
+  task.exit 1
+    echo "failed job"
+  end
+
+  task.exit crash
+    echo "crashed job"
+  end
+
+  task.exit timeout
+    echo "job timed out"
+  end
+
+  task.exec
+    echo "starting job foo"
+  end
+end
Index: /tags/start/Ohana/src/opihi/scripts/test.pro
===================================================================
--- /tags/start/Ohana/src/opihi/scripts/test.pro	(revision 12606)
+++ /tags/start/Ohana/src/opihi/scripts/test.pro	(revision 12606)
@@ -0,0 +1,74 @@
+
+macro testloops
+ for i 0 100
+  if ($i < 20)
+   continue
+  end
+  if ($i > 40)
+   break
+  end
+  echo $i
+ end
+end  
+
+# test math parsing
+macro testvars
+ echo testing variable assignment
+ $a = 1
+ echo $a is 1
+ $b = 5*3 + $a
+ echo $b is 16
+
+ $a = `ls`
+ echo $a
+ exec ls
+
+ echo testing in-line math
+ $a = 1
+ echo {1 + 1} is 2
+ echo {2^3} is 8
+ echo {$a + 2} is 3
+
+ echo testing vector assignment
+ create x 0 10
+ set y = x^2
+ echo x[2] is 2
+ echo y[2] is 4
+ lim x y; clear; box; plot x y
+ label -x "x axis" -y "&s y axis"
+end
+
+macro testspeed
+ exec date
+ create x 0 100000
+ for i 0 5000
+  set y = 3*x + $i
+ end
+ exec date
+end
+
+macro testmemory.buffers
+ mcreate a 2048 2048
+ exec date
+ for i 0 500
+  set b = 3*a + 6
+ end
+ exec date
+end
+
+macro testmemory.macros
+ exec date
+ for i 0 1000
+   for j 0 1000
+    $N = $N + 1
+   end
+ end
+ exec date
+end
+
+macro sample
+ $N = 0
+ for j 0 1000000
+  $N = 100
+ end
+end
Index: /tags/start/Ohana/src/opihi/scripts/testloops.pro
===================================================================
--- /tags/start/Ohana/src/opihi/scripts/testloops.pro	(revision 12606)
+++ /tags/start/Ohana/src/opihi/scripts/testloops.pro	(revision 12606)
@@ -0,0 +1,90 @@
+
+macro testloop1
+ local i
+ for i 0 10
+  echo "1: $i"
+    end
+end
+
+macro testloop2
+ local i
+ for i 0 5
+   echo "2: $i"
+   testloop1
+end
+end
+
+macro testlocal1
+ local -static foo
+ echo "1 - foo: $foo"
+ $foo = local.1
+ echo "1 - foo: $foo"
+end
+
+macro testlocal2
+ local foo
+ $foo = local.2
+ echo "2 - foo: $foo"
+ testlocal1
+ echo "2 - foo: $foo"
+ testlocal1
+ echo "2 - foo: $foo"
+end
+
+macro test1
+ # echo step $1
+ if ($1 == 1)
+  echo "break here"
+  break
+ end
+ if ($1 == 2)
+  continue
+ end
+end
+
+# continue
+
+macro test2
+ echo "input test"
+ break
+ echo "error, can't get here"
+end
+
+macro testm
+ break -auto off
+ test1 0
+ # echo $STATUS
+ test1 1
+ # echo $STATUS
+ test1 2
+ # echo $STATUS
+ if ($1 == 10) 
+  test1 1
+  if ($STATUS == 0)
+   echo "breaking it"
+   break
+  end
+ end
+ echo done
+end
+
+echo "done loading"
+
+macro test3
+ for i 0 12
+  echo $i
+  testm $i
+  echo "status: $STATUS"
+ end
+end
+
+macro testL
+ for i 0 10
+  for j 0 10
+   for k 0 10
+    echo $i $j $k
+    mcreate a 1024 1024   
+   end
+  end
+ end
+end
Index: /tags/start/Ohana/src/perl/.mana
===================================================================
--- /tags/start/Ohana/src/perl/.mana	(revision 12606)
+++ /tags/start/Ohana/src/perl/.mana	(revision 12606)
@@ -0,0 +1,238 @@
+99/04/02 13:00:13: echo {24*4}
+99/04/02 13:00:16: quit
+01/06/14 15:51:12: rd a /h/cfh12k/images/591500f-B8.fits
+01/06/14 15:51:13: mtv a
+01/06/14 15:52:04: quit
+01/06/14 15:51:30: rd a /data/koa/cfh12k/01Ak04/581698o.fits -n 9
+01/06/14 15:51:33: mtv a
+01/06/14 15:52:14: rd b /data/koa/cfh12k/01Ak04/582130o.fits -n 9
+01/06/14 15:52:18: mtv b
+01/06/14 15:53:57: rd c /data/koa/cfh12k/01Ak04/582514o.fits -n 9
+01/06/14 15:54:00: mtv c
+01/06/14 15:54:07: cur
+01/06/14 15:54:15: stats a - - - -
+01/06/14 15:54:35: tv a {0.9*$MEDIAN} {0.2*$MEDIAN}
+01/06/14 15:54:45: tv a {0.98*$MEDIAN} {0.04*$MEDIAN}
+01/06/14 15:54:54: stats b - - - -
+01/06/14 15:54:59: tv b {0.98*$MEDIAN} {0.04*$MEDIAN}
+01/06/14 15:55:04: stats c - - - -
+01/06/14 15:55:08: tv c {0.98*$MEDIAN} {0.04*$MEDIAN}
+01/06/14 15:55:29: cur
+01/06/14 15:55:44: tv c {0.99*$MEDIAN} {0.02*$MEDIAN}
+01/06/14 15:56:22: stats a - - - -
+01/06/14 15:56:28: tv a {0.99*$MEDIAN} {0.02*$MEDIAN}
+01/06/14 15:56:49: set A = a / $MEDIAN
+01/06/14 15:56:53: stats b - - - -
+01/06/14 15:56:59: tv b {0.99*$MEDIAN} {0.02*$MEDIAN}
+01/06/14 15:57:07: set B = b / $MEDIAN
+01/06/14 15:57:19: tv A 0.99 0.02
+01/06/14 15:57:26: tv B
+01/06/14 15:57:35: set C = A - B
+01/06/14 15:57:45: tv C -0.01 0.02
+01/06/14 16:22:34: quit
+01/06/15 08:43:08: rd a /h/skyprobe/data/20010614/rawFITS/sp_20010615_02h08m.fits
+01/06/15 08:43:09: mtv a
+01/06/15 08:49:35: quit
+01/06/15 13:55:29: rd a 581689o05.fits
+01/06/15 13:55:30: mtv a
+01/06/15 13:55:35: rd a testdir/581689o/581689o05.fits
+01/06/15 13:55:38: mtv a
+01/06/15 13:56:09: cur
+01/06/15 13:56:16: stats a - - - -
+01/06/15 13:56:29: tv a {0.95*$MEDIAN} {0.1*$MEDIAN}
+01/06/15 13:56:41: tv a {0.99*$MEDIAN} {0.02*$MEDIAN}
+01/06/15 13:56:52: tv a {0.98*$MEDIAN} {0.04*$MEDIAN}
+01/06/15 13:57:00: quit
+01/06/15 17:24:57: quit
+01/06/18 10:30:56: rd a testdir/test05.fits
+01/06/18 10:30:58: mtv a
+01/06/18 10:32:14: quit
+01/06/15 17:48:06: rd a testdir/test04.MIN.fits
+01/06/15 17:48:09: mtv a
+01/06/15 17:48:27: rd a testdir/test01.MIN.fits
+01/06/15 17:48:29: mtv a
+01/06/18 10:38:53: quit
+01/06/18 10:36:12: rd a /data/mele/F52/WY31/564116o.fits -n 3
+01/06/18 10:36:14: mtv a
+01/06/18 10:40:19: quit
+01/06/18 10:56:59: quit
+01/06/18 10:57:12: rd a testdir/581689o/581689o09.fits
+01/06/18 10:57:14: mtv a
+01/06/18 10:57:36: tv a {0.98*$MEDIAN} {0.04*$MEDIAN}
+01/06/18 10:57:48: rd b testdir/581689o/581689o09r.fits
+01/06/18 10:57:49: tv b
+01/06/18 10:57:55: stats b - - - -
+01/06/18 10:58:03: tv b {0.98*$MEDIAN} {0.04*$MEDIAN}
+01/06/18 10:58:43: stats a - - - -
+01/06/18 10:58:48: tv a {0.98*$MEDIAN} {0.04*$MEDIAN}
+01/06/18 10:59:00: stats b - - - -
+01/06/18 10:59:05: tv b {0.98*$MEDIAN} {0.04*$MEDIAN}
+01/06/18 10:59:22: stats a - - - -
+01/06/18 10:59:28: tv a {0.98*$MEDIAN} {0.04*$MEDIAN}
+01/06/18 11:01:26: rd c /data/milo/eugene/elixir/detrend/flat/I/01Ak01.flat.I.09.00.fits
+01/06/18 11:01:30: mtv c
+01/06/18 11:01:45: rd d /data/milo/eugene/elixir/detrend/flat/I/01Ak01.flat.I.09.01.fits
+01/06/18 11:01:50: mtv d
+01/06/18 11:02:05: mtv c
+01/06/18 11:02:10: mtv d
+01/06/18 11:03:09: rd c /data/milo/eugene/elixir/detrend/flat/R/01Ak01.flat.R.09.01.fits
+01/06/18 11:03:21: rd c /data/milo/eugene/elixir/detrend/flat/R/01Ak01.flat.R.09.03.fits
+01/06/18 11:03:24: mtv c
+01/06/18 11:03:50: quit
+01/06/19 10:54:40: echo {1.75 / 5.44}
+01/06/19 11:03:15: quit
+01/06/19 15:32:05: rd a testdir/581692o.df/581692o00.fits
+01/06/19 15:32:07: mtv a
+01/06/19 15:32:44: echo $PACKAG
+01/06/19 15:32:45: echo $PACKAGE
+01/06/19 15:34:15: package elixir
+01/06/19 15:34:19: binmosaic
+01/06/19 15:34:29: binmosaic testdir/581692o.outlist 4
+01/06/19 15:35:16: mtv b
+01/06/19 15:35:52: stats b - - - -
+01/06/19 15:36:06: tv b {0.95*$MEDIAN} {0.1*$MEDIAN}
+01/06/19 15:36:30: tv b {0.98*$MEDIAN} {0.04*$MEDIAN}
+01/06/19 15:36:48: tv b {0.99*$MEDIAN} {0.02*$MEDIAN}
+01/06/19 15:37:05: !ls
+01/06/19 15:37:12: !more test.rlist
+01/06/19 15:37:18: !more testdir/581692o.inlist
+01/06/19 15:37:46: wd b test1.fits -bitpix -32 -bzero 0 -bscale 1
+01/06/19 15:37:55: binmosaic testdir/581692o.inlist 4
+01/06/19 16:32:55: tv b
+01/06/19 16:33:04: stats b - - - -
+01/06/19 16:33:10: tv b {0.95*$MEDIAN} {0.1*$MEDIAN}
+01/06/19 16:33:26: rd a test1.fits
+01/06/19 16:33:30: tv a
+01/06/19 16:33:37: tv b
+01/06/19 16:33:48: stats a - - - -
+01/06/19 16:33:54: tv a {0.95*$MEDIAN} {0.1*$MEDIAN}
+01/06/19 16:34:11: stats b - - - -
+01/06/19 16:34:19: tv b {0.95*$MEDIAN} {0.1*$MEDIAN}
+01/06/20 09:40:10: quit
+01/06/20 09:41:04: for i 1 12
+01/06/20 09:50:22: input /data/milo/eugene/elixir/config/mana/fringe.pro
+01/06/20 09:50:44: input /data/milo/eugene/elixir/config/mana/fringe.pro
+01/06/20 09:50:57: fringelist testdir/581692o.outlist
+01/06/20 09:51:05: input /data/milo/eugene/elixir/config/mana/fringe.pro
+01/06/20 09:51:05: fringelist testdir/581692o.outlist
+01/06/20 09:51:26: input /data/milo/eugene/elixir/config/mana/fringe.pro
+01/06/20 09:51:40: input /data/milo/eugene/elixir/config/mana/fringe.pro
+01/06/20 09:51:41: fringelist testdir/581692o.outlist
+01/06/20 09:54:10: mtv c
+01/06/20 09:54:24: cur
+01/06/20 09:54:34: stats c - - - -
+01/06/20 09:54:44: tv c {0.95*$MEDIAN} {0.1*$MEDIAN}
+01/06/20 09:54:53: tv c {0.98*$MEDIAN} {0.04*$MEDIAN}
+01/06/20 09:56:40: input /data/milo/eugene/elixir/config/mana/fringe.pro
+01/06/20 09:56:47: tvmosaic c
+01/06/20 09:56:51: tvmosaic d
+01/06/20 10:03:21: buffers
+01/06/20 10:03:25: stats a - - - -
+01/06/20 10:03:51: echo $MEAN $SIGMA
+01/06/20 10:04:19: mtv a
+01/06/20 10:04:55: echo $MEDIAN
+01/06/20 10:05:21: clip a {0.9*$MEDIAN} 0.0 {1.1*$MEDIAN} 0.0
+01/06/20 10:05:23: tv a
+01/06/20 10:05:42: stats a - - - - -ignore 0
+01/06/20 10:05:51: echo $MEAN $SIGMA
+01/06/20 10:08:06: echo test # fred
+01/06/20 10:08:15: stats a - - - - # this is a test
+01/06/20 10:10:25: input /data/milo/eugene/elixir/config/mana/fringe.pro
+01/06/20 10:10:37: fringelist testdir/581692o.outlist
+01/06/20 10:13:40: input /data/milo/eugene/elixir/config/mana/fringe.pro
+01/06/20 10:14:27: input /data/milo/eugene/elixir/config/mana/fringe.pro
+01/06/20 10:14:29: fringelist testdir/581692o.outlist
+01/06/20 10:22:10: input /data/milo/eugene/elixir/config/mana/fringe.pro
+01/06/20 10:22:40: fringelist testdir/581692o.outlist testdir/581692o.tenbin testdir/581692o.medbin testdir/581692o.stats
+01/06/20 10:24:32: !ls testdir
+01/06/20 10:28:47: quit
+01/06/20 10:30:21: fred
+01/06/20 10:30:25: exit
+01/06/26 13:49:58: rd a 000000o29517.fits
+01/06/26 13:50:01: rd a /tmp000000o29517.fits
+01/06/26 13:50:04: rd a /tmp/000000o29517.fits
+01/06/26 13:50:05: mtv a
+01/06/26 13:50:16: tv a 6000 3000
+01/06/26 13:50:34: cur -g
+01/06/26 13:50:41: cur
+01/06/26 13:50:56: tv a 8000 1200
+01/06/26 13:51:11: pwd
+01/06/26 13:51:27: rd b /h/eugene/cfh12k/elixir2/detrend/01Ak03/proc/579401o/579401o00.fits
+01/06/26 13:51:31: mtv b
+01/06/26 13:51:38: boxstat
+01/06/26 13:51:55: tv b {0.9*$MEDIAN} {0.2*$MEDIAN}
+01/06/26 13:52:06: tv b {0.95*$MEDIAN} {0.1*$MEDIAN}
+01/06/26 13:52:19: tv b {0.98*$MEDIAN} {0.04*$MEDIAN}
+01/06/26 13:52:59: tv a 8000 1200
+01/06/26 13:53:33: quit
+01/09/07 14:47:45: echo {300*4}
+01/09/07 14:47:51: echo {1440/60}
+01/09/07 14:48:15: {24+45+24+45+24}
+01/09/07 14:48:19: echo {24+45+24+45+24}
+01/09/07 14:48:25: echo {(24+45+24+45+24)/60}
+01/09/07 14:49:53: quit
+01/09/13 14:36:08: echo {337.5 * 0.0185}
+01/09/13 14:36:53: echo {112.5 * 0.0185}
+01/09/13 14:36:59: echo {462.5 * 0.0185}
+01/09/13 14:37:03: echo {102.5 * 0.0185}
+01/09/13 14:37:35: quit
+02/08/22 08:48:39: echo {1e8*500}
+02/08/22 08:48:53: echo {5e7*2000}
+02/08/22 10:29:02: quit
+03/02/13 11:02:46: input /data/elixir2/elixir/config/mana/fringe.pro
+03/02/13 11:02:46: getfitpars /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.med.sublist /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.fitpar
+03/02/13 11:02:46: input /data/elixir2/elixir/config/mana/fringe.pro
+03/02/13 11:02:47: getfrstats /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.fitpar /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.med.statlist /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.med.imstats
+03/02/13 11:02:47: input /data/elixir2/elixir/config/mana/fringe.pro
+03/02/13 11:02:47: getdfstats /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.fitpar /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.def.statlist /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.def.imstats
+03/02/13 11:23:32: input /data/elixir2/elixir/config/mana/fringe.pro
+03/02/13 11:23:33: getfitpars /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.med.sublist /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.fitpar
+03/02/13 11:23:33: input /data/elixir2/elixir/config/mana/fringe.pro
+03/02/13 11:23:33: showfits /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.med.statlist /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.fitpar /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.stats.png
+03/02/13 11:23:35: input /data/elixir2/elixir/config/mana/fringe.pro
+03/02/13 11:23:35: getfrstats /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.fitpar /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.med.statlist /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.med.imstats
+03/02/13 11:23:36: input /data/elixir2/elixir/config/mana/fringe.pro
+03/02/13 11:23:36: getdfstats /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.fitpar /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.def.statlist /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.def.imstats
+03/02/13 11:23:37: input /data/elixir2/elixir/config/mana/fringe.pro
+03/02/13 11:23:37: $RANGE = 0.02
+03/02/13 11:23:37: mkjpegs /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.frlist /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.medbin.jpg /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.tenbin.jpg
+03/02/13 11:29:45: quit
+03/05/15 11:57:07: quit
+03/05/15 14:19:55: input /data/elixir2/srcdir/config/mana/fringe.pro
+03/05/15 14:19:56: getfitpars /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.med.sublist /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.fitpar
+03/05/15 14:19:57: input /data/elixir2/srcdir/config/mana/fringe.pro
+03/05/15 14:19:57: showfits /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.med.statlist /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.fitpar /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.stats.png
+03/05/15 14:20:02: input /data/elixir2/srcdir/config/mana/fringe.pro
+03/05/15 14:20:03: getfrstats /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.fitpar /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.med.statlist /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.med.imstats
+03/05/15 14:25:46: input /data/elixir2/srcdir/config/mana/fringe.pro
+03/05/15 14:25:46: getfitpars /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.med.sublist /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.fitpar
+03/05/15 14:25:46: input /data/elixir2/srcdir/config/mana/fringe.pro
+03/05/15 14:25:47: getfrstats /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.fitpar /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.med.statlist /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.med.imstats
+03/05/15 14:44:29: input /data/elixir2/srcdir/config/mana/fringe.pro
+03/05/15 14:44:30: getfitpars /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.med.sublist /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.fitpar
+03/05/15 14:44:30: input /data/elixir2/srcdir/config/mana/fringe.pro
+03/05/15 14:44:31: showfits /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.med.statlist /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.fitpar /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.stats.png
+03/05/15 14:44:36: input /data/elixir2/srcdir/config/mana/fringe.pro
+03/05/15 14:44:36: getfrstats /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.fitpar /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.med.statlist /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.med.imstats
+03/05/15 14:44:37: input /data/elixir2/srcdir/config/mana/fringe.pro
+03/05/15 14:44:37: getdfstats /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.fitpar /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.def.statlist /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.def.imstats
+03/05/15 14:44:38: input /data/elixir2/srcdir/config/mana/fringe.pro
+03/05/15 14:44:38: $RANGE = 0.02
+03/05/15 14:44:38: mkjpegs /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.frlist /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.medbin.jpg /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.tenbin.jpg
+03/05/15 14:54:53: input /data/elixir2/srcdir/config/mana/fringe.pro
+03/05/15 14:54:54: getfitpars /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.med.sublist /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.fitpar
+03/05/15 14:54:54: input /data/elixir2/srcdir/config/mana/fringe.pro
+03/05/15 14:54:55: getfrstats /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.fitpar /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.med.statlist /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.med.imstats
+03/05/15 14:54:55: input /data/elixir2/srcdir/config/mana/fringe.pro
+03/05/15 14:54:56: getdfstats /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.fitpar /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.def.statlist /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.def.imstats
+03/05/15 15:15:49: input /data/elixir2/srcdir/config/mana/fringe.pro
+03/05/15 15:15:49: getfitpars /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.med.sublist /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.fitpar
+03/05/15 15:15:50: input /data/elixir2/srcdir/config/mana/fringe.pro
+03/05/15 15:15:50: showfits /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.med.statlist /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.fitpar /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.stats.png
+03/05/15 15:15:56: input /data/elixir2/srcdir/config/mana/fringe.pro
+03/05/15 15:15:57: getfrstats /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.fitpar /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.med.statlist /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.med.imstats
+03/05/15 15:15:57: input /data/elixir2/srcdir/config/mana/fringe.pro
+03/05/15 15:15:58: getdfstats /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.fitpar /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.def.statlist /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.def.imstats
+03/05/15 15:15:58: input /data/elixir2/srcdir/config/mana/fringe.pro
+03/05/15 15:15:59: $RANGE = 0.02
+03/05/15 15:15:59: mkjpegs /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.frlist /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.medbin.jpg /data/elixir1/detdir/megacam/03Am03/fringe/03Am03.fringe.i.0.tenbin.jpg
Index: /tags/start/Ohana/src/perl/.status
===================================================================
--- /tags/start/Ohana/src/perl/.status	(revision 12606)
+++ /tags/start/Ohana/src/perl/.status	(revision 12606)
@@ -0,0 +1,60 @@
+elixir status
+elixir flips
+elixir ptolemy
+nav
+nav
+!radec -hms
+region 168.148 6.9777 1.0
+catalog -g -m 14 20
+catalog -g -all -m 14 20
+style -pt 1
+region 168.148 6.9777 1.0
+catalog -g -all -m 14 20
+region 168.148 6.9777 0.3
+region 168.148 6.9777 1.0
+region 168.148 6.9777 0.3
+catalog -g -all -m 14 20
+catalog -g -all -m 10 15
+region 168.148 6.9777 0.3
+catalog -g -all -m 10 15
+nav
+pmeasure -all -m 16 22
+nav
+pmeasure -all -m 16 22
+style -pt 2
+c
+elixir flips
+elixir ptolemy
+elixir flips
+elixir complete
+elixir complete -time
+elixir complete -time
+na
+region
+region 30 0 90 ait
+style -c red; cgrid
+style -c black; images
+box
+region 30 0 90 ait
+style -c red; cgrid
+region 40 0 90 ait
+style -c red; cgrid
+style -c black; images
+clear
+style -c red; cgrid
+style -c black; images
+jpeg -g -name /h/eugene/spplots/allsky.png
+elixir complete
+elixir complete
+elixir complete -time
+elixir complete -time
+elixir complete -time
+elixir complete
+elixir complete
+echo {2500*60/11}
+echo {2500*60/11/3600}
+elixir complte
+elixir complete
+elixir complete -time
+elixir complete
+elixir complete -kill
Index: /tags/start/Ohana/src/perl/Makefile
===================================================================
--- /tags/start/Ohana/src/perl/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/perl/Makefile	(revision 12606)
@@ -0,0 +1,60 @@
+include ../../Configure
+HOME 	=	$(ROOT)/src/perl
+
+DESTBIN	=	$(LBIN)
+
+perl: default
+
+default: install
+
+DADS = \
+dads.detrend dads.jpeg dads.keywords grab.keywords
+
+DETREND = \
+darktime.cfh12k darktime.linear \
+demodemap flatten.mana flatten.flips defringe getfringe defringe.ccd
+
+GENERAL = \
+cfht.names checkconfig mkrun megacenter megacoords \
+update.astrometry.iraf wfi.keywords mefheadunstrip cadc2qso
+
+IMSTATS = \
+imstatqso imstats \
+irstats seeingstats
+
+MKDETREND = \
+create.subset dt.select fixscat fixscat.mef mkscat \
+mkdetrend mosaic.merge mosaic.stats \
+normalize split.mef \
+detflips merge.lists
+
+MKFRINGE = \
+fr.mkmodes fr.modesave fr.modestats \
+fr.ckfile fr.detrend fr.frstats \
+fr.getfringe fr.imdata fr.jpegs \
+fr.medbin.spline fr.medbin.interp fr.mkhtml fr.mklists \
+fr.select mkfringe fr.defringe fr.smooth
+
+POSTRUN = \
+ckastrom ckdetrend ckphotom \
+ckrunid ckvalid elixir.photreport \
+elixir.postrun mktrans mktreport \
+validate rerun.complete elixir.rerun
+
+PTOLEMY = \
+cmp.header imclean.cfht imclean.subaru gastro.raw elixir.export
+
+REALTIME = \
+ckimregdb elixir.link elixir.reload
+
+CODE = $(DADS) $(DETREND) $(GENERAL) $(IMSTATS) $(MKDETREND) $(MKFRINGE) $(POSTRUN) $(PTOLEMY) $(REALTIME)
+
+install:
+	for file in $(CODE); do \
+	(chmod +x src/$$file && cd $(DESTBIN) && rm -f $$file && ln -s $(HOME)/src/$$file .); \
+	done
+
+# utilities #################################################
+clean:	
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
Index: /tags/start/Ohana/src/perl/doc/keywords.txt
===================================================================
--- /tags/start/Ohana/src/perl/doc/keywords.txt	(revision 12606)
+++ /tags/start/Ohana/src/perl/doc/keywords.txt	(revision 12606)
@@ -0,0 +1,130 @@
+
+Elixir data products are modified by several programs, each of which
+needs to make certain additions or changes to the headers.  this is a
+summary of those programs and the relevant keywords.  These programs
+may also add COMMENT and HISTORY fields, but these are ignored.
+
+* basic master bias, flat, dark frames are created by 'imcombred'
+  and adjusted by 'normalize'.
+
+- 'imcombred' adds the following keywords:
+
+IMCMB_DT= 'FLIPS ver 2.0 - Elixir by CFHT - Tue Aug 12 2003 -  9:09:32' / Date 
+IMCMB_AL= 'SIGMA   '           / CCD or SIGMA clipping, Scaled or Weighted Diff
+IMCMB_CA= 'MEAN    '           / Combining algorithm on final stack            
+IMCMB_LS=                  3.5 / Lower threshold for clipping rejection        
+IMCMB_HS=                  3.5 / Lower threshold for clipping rejection        
+IMCMB_FT= 'MASTER_DETREND_SKYFLAT' / Stacked frame type                        
+IMCMB_OP= '1DYMODEL_OVERSCAN + COMPUTED_MODE_RESCALING' / Input operations     
+IMCMB_NI=                   16 / Number of input files                         
+IMCMB_DA=                    T / Dual amplifier A,B (IMCMB_XX list format)     
+IMCMB_IF= 'NAME BIAS_A MODE_A BIAS_B MODE_B' / Input file parameters           
+IMCMB_nn= '712143f.fits[ccd00] 1287 3204 1232 3266' / Input file stats         
+
+- 'normalize' adds the following keywords:
+
+FLATSCAL=         1.0642668848 /                                               
+TVSTART = '2000/1/1          ' / data validity start time
+TVSTOP  = '2001/1/1          ' / data validity start time
+ELCONF  = '03Bm01.flat.g.0   ' / Original Elixir config
+EL_SYS  = '2.0               ' / Elixir System Version
+EL_NRM  = '1.4               ' / Elixir Normalize Version
+REL_DATE= '2003-09-30T15:59:33' / UTC Release Date
+
+* scatter-corrected flats are created by 'fixscat'
+- 'fixscat' adds the following keywords:
+
+EL_SFILE= '02Bm05.scatter.g.36.00.fits' / Scattered Light Image Used
+EL_SVER = 'B.0               ' / Scatter Correction Version
+
+* scatter frames are created by 'mkscat'
+- 'mkscat' adds the following keywords:
+
+TVSTART = '2000/1/1          ' / data validity start time
+TVSTOP  = '2001/1/1          ' / data validity start time
+FILTER  = 'g                 ' / filter uxed for model
+EL_SYS  = '2.0               ' / Elixir System Version
+EL_SVER = 'B.0               ' / Scatter Correction Version
+VERSION = 'B.0               ' / Scatter Correction Version
+
+* master fringe frames are created by 'imcombred' and adjusted by
+  'fr.smooth'
+
+- imcombred adds the following keywords:
+
+IMCMB_DT= 'FLIPS ver 2.1 - Elixir by CFHT - Tue Sep 16 2003 - 14:00:18' / Date 
+IMCMB_AL= 'SIGMA   '           / CCD or SIGMA clipping, Scaled or Weighted Diff
+IMCMB_CA= 'MEDIAN  '           / Combining algorithm on final stack            
+IMCMB_LS=                  2.0 / Lower threshold for clipping rejection        
+IMCMB_HS=                  2.0 / Lower threshold for clipping rejection        
+IMCMB_FT= 'MASTER_DETREND_FRINGE' / Stacked frame type                         
+IMCMB_OP= 'MODE_OFFSETING + FRINGE_RESCALING' / Input operations               
+IMCMB_NI=                   31 / Number of input files                         
+IMCMB_DA=                    F / Dual amplifier A,B (IMCMB_XX list format)     
+IMCMB_IF= 'NAME BIAS MODE SCALING' / Input file parameters                     
+IMCMB_00= '714505o00.fits 0 2582 0.441' / Input file stats                     
+
+- fr.smooth adds the following keywords:
+
+FRNG_C0 =         0.0000000000 / Fringe Cross Correlation linear fit term
+FRNG_C1 =         0.7197280000 / Fringe Cross Correlation linear fit term
+FRNG_SKY=      2882.0000000000 / Fringe Frame sky level
+FRNG_RNG=       -80.0000000000 / Fringe Frame fringe strength
+FRNG_REF= 'ccd13             ' / Fringe Cross Correlation reference chip
+FRNG_PTS= '2003A.frpts.i.36.00.fits' / Fringe Point File
+TVSTART = '2000/1/1          ' / data validity start time
+TVSTOP  = '2001/1/1          ' / data validity stop time
+EL_SYS  = '2.0               ' / Elixir System Version
+
+
+* processed science images are created by 'imred', defringed with
+  'imcombred', and keywords are updated with 'grab.keywords'
+
+- imred adds the following keywords:
+
+IMRED_DT= 'FLIPS ver 2.1 - Elixir by CFHT - Tue Sep 9 2003 - 12:29:37' / Date  
+IMRED_IF= '703406o.fits[ccd00]' / Input file to process by imred               
+IMRED_OF= '703406p00.fits'     / Output file resulting from the process by imre
+IMRED_OP= 'MASK_BP + OVERSCAN + BIAS + DARK_CURRENT + FLAT-FIELD' / Operation(s
+IMRED_MK= '2003A.mask.0.36.00.fits[ccd00]' / Mask of bad pixels (0/1) input fil
+IMRED_OV= '1DYMODEL_OVERSCAN'  / Type of overscan level correction             
+IMRED_BS= '03Am04n.bias.0.18.00.fits[ccd00]' / Bias frame input file           
+IMRED_DK= '03Am04n.dark.300.18.00.fits[ccd00]' / Dark frame input file         
+IMRED_DS=               1.0000 / Dark frame scaling factor                     
+IMRED_DB=                    T / Dark frame first corrected by bias frame      
+IMRED_FF= '03Am04n.flat.r.18.01.fits[ccd00]' / Flat-field frame input file     
+IMRED_NF=                    T / Normalized flat-field                         
+IMRED_SF=          1.009331465 / Output file dynamic stretching factor (BSCALe)
+
+- imcombred adds the following keywords:
+
+IMCMB_DT= 'FLIPS ver 2.1 - Elixir by CFHT - Tue Sep 9 2003 - 12:16:00' / Date  
+IMCMB_AL= 'SD      '           / CCD or SIGMA clipping, Scaled or Weighted Diff
+IMCMB_CA= 'SCALED_DIFFERENCE'  / Combining algorithm on final stack            
+IMCMB_LS=                  2.0 / Lower threshold for clipping rejection        
+IMCMB_HS=                  2.0 / Lower threshold for clipping rejection        
+IMCMB_FT= 'DEFRINGE_SCIENCE'   / Stacked frame type                            
+IMCMB_OP= 'MODE_OFFSETING + FRINGE_RESCALING' / Input operations               
+IMCMB_NI=                    2 / Number of input files                         
+IMCMB_DA=                    F / Dual amplifier A,B (IMCMB_XX list format)     
+IMCMB_IF= 'NAME BIAS MODE SCALING' / Input file parameters                     
+IMCMB_00= '703266p00.det 0 3808 1.000' / Input file stats                      
+IMCMB_01= '03Am04n.fringe.i.18.00.fits[ccd00] 0 4062 1.108' / Input file stats 
+
+- grab.keywords adds the following keywords:
+
+NASTRO  =                   49 / number of stars used for astrometry           
+CERROR  =         0.7334717934 / scatter in astrometry soln (arcsec)           
+PHOT_C  =               25.715 / Nightly zero point - actual                   
+PHOT_C0 =               25.743 / Nightly zero point - nominal                  
+PHOT_CS =                0.017 / Nightly zero point - scatter                  
+PHOT_NS =                    3 / Nightly zero point - N stars                  
+PHOT_NM =                    3 / Nightly zero point - N images                 
+PHOT_X  =                0.083 / Nightly zero point - color term               
+PHOT_K  =                -0.04 / Nightly zero point - airmass term             
+PHOT_C1 = 'r_SDSS            ' / Nightly zero point - color 1                  
+PHOT_C2 = 'i_SDSS            ' / Nightly zero point - color 2                  
+MAG_SAT =              13.8063 / approx saturation (mag)                       
+MAG_LIM =              23.2063 / approx completeness limit (mag)               
+DATEPROC= '2003-09-30T17:14:50' / Processing Date                                      
+EL_SYS  = '2.0                ' / Elixir System Version                               
Index: /tags/start/Ohana/src/perl/doc/mkdetrend-notes.txt
===================================================================
--- /tags/start/Ohana/src/perl/doc/mkdetrend-notes.txt	(revision 12606)
+++ /tags/start/Ohana/src/perl/doc/mkdetrend-notes.txt	(revision 12606)
@@ -0,0 +1,46 @@
+
+files used by mkdetrend:
+
+flips/02Bk06.flat.I.00.0.fits     - master image, unnormalized
+flips/02Bk06.flat.I.00.0.imbin	  - binned master image
+flips/02Bk06.flat.I.00.0.log	  - log
+flips/02Bk06.flat.I.00.0.master	  - list of input images
+flips/02Bk06.flat.I.00.0.medbin	  - binned residual stack (50)
+flips/02Bk06.flat.I.00.0.mef	  - list of mef images
+flips/02Bk06.flat.I.00.0.msplit	  - list of split mef images
+flips/02Bk06.flat.I.00.0.norm	  - master image, normalized
+flips/02Bk06.flat.I.00.0.split	  - list of split images
+flips/02Bk06.flat.I.00.0.stats	  - residual stats per input image
+flips/02Bk06.flat.I.00.0.subset	  - list of images to be stacked
+flips/02Bk06.flat.I.00.0.tenbin	  - binned residual stack (10)
+
+changes:
+
+dt.select2: 
+mkdetrend2
+mode.mkdetrend2
+cfh12k.config.mef
+
+
+chip ID rules:
+
+there are two chip identifiers:  CCD ID & CCD N
+
+CCD ID is an arbitrary string
+CCD N  is a two digit code for the CCDs base on the camera config file
+
+CCD ID: cameraconfig -ccds
+CCD N:  cameraconfig -ccdn
+
+detsearch / imsearch use CCD ID for -ccd filter
+
+filenames of derivative products should use CCD N as a marker
+eg: 654321o.fits -> 654321o23.fits (for megacam ccd23 image)
+
+---
+
+dt.select2    : CCD ID fixed
+merge.lists   : CCD n/a
+create.subset : CCD n/a
+detflips      : CCD n/a - flips path needs to be set?
+normalize     : CCD ID Keyword used to id REF ccd (OK)
Index: /tags/start/Ohana/src/perl/doc/mkfringe.notes
===================================================================
--- /tags/start/Ohana/src/perl/doc/mkfringe.notes	(revision 12606)
+++ /tags/start/Ohana/src/perl/doc/mkfringe.notes	(revision 12606)
@@ -0,0 +1,109 @@
+
+mkfringe file name examples
+
+CONFIG      = 01Ak01.fringe.I.0
+CONF-CCD    = 01Ak01.fringe.I.00.0
+RAWPATH     = /data/koa/cfh12k/01Ak04
+TMPPATH     = /data/elixir2/cfh12k/detrend/01Ak04/proc
+TMPDET-CCD  = /data/elixir2/cfh12k/detrend/01Ak04/proc/543210o/543210o00.fits
+TMPDEF-CCD  = /data/elixir2/cfh12k/detrend/01Ak04/proc/543210o.def/543210o00.fits
+
+ROOT = 543210o
+MODE = SPLIT / MEF
+status = 2 = new image, detrend it please, 1 = use to create master, 0 = don't use
+
+CONFIG.mef, CONFIG.split   [Nimage]
+ RAWPATH ROOT MODE
+ /data/koa/cfh12k/01Ak04 581688o SPLIT
+ /data/koa/cfh12k/01Ak04 581689o MEF
+
+CONFIG.master              [Nimage]
+ RAWPATH ROOT MODE status
+ /data/koa/cfh12k/01Ak04 581688o SPLIT 1
+ /data/koa/cfh12k/01Ak04 581689o MEF   1
+ 
+CONFIG.detrend             [Nimage] 
+ RAWPATH ROOT MODE
+ /data/koa/cfh12k/01Ak04 581688o SPLIT
+ /data/koa/cfh12k/01Ak04 581689o MEF
+
+CONFIG.defringe		   [Nimage]
+ TMPPATH/ROOT CONFIG
+ proc/581688o 01Ak01.fringe.I.0
+
+TMPPATH/ROOT.detlist       [Nccd]
+ TMPDET-CCD
+ proc/581688o/581688o00.fits
+
+TMPPATH/ROOT.deflist       [Nccd]
+ TMPDEF-CCD
+ proc/581688o.def/581688o00.fits
+
+CONF-CCD.ccdstats          [Nimage]
+ TMPDET-CCD (sky) (fringe) 0.0 0.0
+ proc/581688o/581688o00.fits (sky) (fringe) 0.0 0.0
+
+CONFIG.statlist: 
+ CONF-CCD.ccdstats 
+ fringe/01Ak01.fringe.I.00.0.ccdstats
+
+CONFIG.frlist               [Nccd]
+ CONF-CCD.fr.fits 
+ fringe/01Ak01.fringe.I.00.0.fr.fits
+
+CONFIG.smlist               [Nccd]
+ CONF-CCD.sm.fits 
+ fringe/01Ak01.fringe.I.00.0.sm.fits
+
+CONFIG.medbin:
+ HTML/CONFIG.medbin.NNN.jpg
+
+CONFIG.tenbin:
+ HTML/CONFIG.tenbin.NNN.jpg
+
+CONFIG.stats
+ (stats per mosaic)
+
+###### init: (takes CONFIG as input list) (mode.fringe1)
+fr.select I 2001/1/20 2001/2/5 split fringe/01Ak01.fringe.I.0.split
+fr.select I 2001/1/20 2001/2/5 mef   fringe/01Ak01.fringe.I.0.mef
+
+fr.mklists -initial  fringe/01Ak01.fringe.I.0.split fringe/01Ak01.fringe.I.0.mef fringe/01Ak01.fringe.I.0.master
+
+fr.mklists -imlist fringe/01Ak01.fringe.I.CCDNUM.0.ccdstats fringe/01Ak01.fringe.I.0.statlist
+fr.mklists -imlist fringe/01Ak01.fringe.I.CCDNUM.0.fr.fits  fringe/01Ak01.fringe.I.0.frlist
+fr.mklists -imlist fringe/01Ak01.fringe.I.CCDNUM.0.sm.fits  fringe/01Ak01.fringe.I.0.smlist
+
+fr.mklists -mosaic fringe/01Ak01.fringe.I.0.master proc det  (produces proc/ROOT.det/*NN.fits & proc/ROOT.detlist)
+fr.mklists -mosaic fringe/01Ak01.fringe.I.0.master proc def  (produces proc/ROOT.def/*NN.fits & proc/ROOT.deflist)
+fr.mklists -mosaic fringe/01Ak01.fringe.I.0.master proc med  (produces proc/ROOT.med/*NN.fits & proc/ROOT.medlist)
+
+fr.mklists -detrend  fringe/01Ak01.fringe.I.0.master fringe/01Ak01.fringe.I.0.detrend
+fr.mklists -defringe fringe/01Ak01.fringe.I.0.master fringe/01Ak01.fringe.I.0 proc fringe/01Ak01.fringe.I.0.defringe
+
+##### detrend: (takes CONFIG.detrend as input list)  (mode.fringe2)
+fr.detrend /data/koa/cfh12k/01Ak04 581688o SPLIT proc/581688o.det
+fr.medbin  proc/581688o.det 581688o 4 proc/581688o.med
+fr.gtstats proc/581688o.med 581688o 4 proc/581688o.imstats
+
+##### mkstats  (takes CONF-CCD as input list)  (mode.fringe4)
+fr.mklists -inlist  fringe/01Ak01.fringe.I.0.master 00 proc fringe/01Ak01.fringe.I.00.0.inlist
+fr.mklists -imstats fringe/01Ak01.fringe.I.0.master 00 proc fringe/01Ak01.fringe.I.0.imstats
+
+fr.mkstats fringe/01Ak01.fringe.I.00.0.inlist fringe/01Ak01.fringe.I.0.imstats 00 fringe/01Ak01.fringe.I.00.0.ccdstats fringe/01Ak01.fringe.I.0.frstats
+fr.mkrough fringe/01Ak01.fringe.I.00.0.ccdstats fringe/01Ak01.fringe.I.00.0.fr.fits comment
+
+[ fr.smooth fringe/01Ak01.fringe.I.00.0.fr.fits fringe/01Ak01.fringe.I.00.0.sm.fits ]
+
+##### defringe (takes CONFIG.defringe as input)  (mode.fringe3)
+fr.defringe proc/581688o.medlist proc/581688o.imstats fringe/01Ak01.fringe.I.00.0.frlist fringe/01Ak01.fringe.I.00.0.frstats proc/581688o.deflist 
+fr.stats proc/581688o.deflist proc/581688o.tenbin proc/581688o.medbin proc/581688o.stats
+
+# merge (not parallel)
+
+status: 2 = new image, detrend it please, 1 = use to create master, 0 = don't use
+
+fr.mklists -master fringe/01Ak01.fringe.I.0.master fringe/01Ak01.fringe.I.0.detrend
+
+[merge ccdstats > statlist]
+
Index: /tags/start/Ohana/src/perl/doc/mkfringe.txt
===================================================================
--- /tags/start/Ohana/src/perl/doc/mkfringe.txt	(revision 12606)
+++ /tags/start/Ohana/src/perl/doc/mkfringe.txt	(revision 12606)
@@ -0,0 +1,59 @@
+
+mkfringe states & programs [fringe only]
+
+running.init              : mode.fringe1 (config.mosaic)
+
+ - fr.select
+ - fr.mklists -initial
+ - fr.mklists -imlist
+ - fr.mklists -mosaic
+ - fr.mklists -detrend
+ - fr.mklists -maplist
+ - fr.mklists -mlist
+
+running.detrend           : mode.fringe2 (image)
+
+ - fr.ckfile
+ - fr.detrend
+ - fr.medbin.spline
+ - fr.getfringe
+ - fr.imdata
+ - fr.jpegs
+ - fr.mklists -master
+
+running.merge		  : mkfringe (config.mosaic)
+
+ - fr.mklists -subset
+ - fr.frstats -fitpars
+ - fr.frstats -plotstats
+ - fr.frstats -frstats
+ - fr.frstats -dfstats
+ - fr.mklists -imstats
+ - fr.jpegs
+ - fr.mkhtml -imstats
+ - fr.mkhtml -jpglist
+
+running.mkrough           : mkfringe / mode.fringe4 
+
+ - fr.mklists  -subset
+ - fr.frstats  -fitpars
+ - fr.frstats  -frstats
+ - fr.frstats  -dfstats
+ - fr.mklists  -imstats
+ - fr.mklists  -ccdstast
+ - fr.mkrough
+
+running.defringe          : mode.fringe3
+
+ - fr.defringe
+ - fr.getfringe
+ - fr.jpegs
+
+running.smooth            : mode.fringe4
+
+ - fr.smooth
+
+running.reg               : mkfringe
+
+ - detregister
+
Index: /tags/start/Ohana/src/perl/loneos/archive
===================================================================
--- /tags/start/Ohana/src/perl/loneos/archive	(revision 12606)
+++ /tags/start/Ohana/src/perl/loneos/archive	(revision 12606)
@@ -0,0 +1,353 @@
+#!/usr/bin/perl
+
+$dumpspace = "/pallas/d1/";
+$workspace = "/metis/d27/workspace/";
+# $workspace = "/irene/d11/workspace/";
+
+$scriptdir = "/hebe/d27/logs/";
+$donelogfile = $scriptdir . "done.log";
+$scriptfile = $scriptdir . "maestro.dat";
+$flatdir = "/hebe/d27/references/config/";
+
+$database = "/hebe/d27/database/";
+$lockfile = $database . "lock";
+$alockfile = $database . "alock";
+$clockfile = $database . "clock";
+$killfile  = $database . "kill";
+$haltfile  = $database . "halt";
+$reffile = $database . "start.clean";
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    vsystem ("date");
+    vsystem ("notify.pl $ARGV[0] none 0");
+    die "@_";
+}
+
+if (@ARGV < 1) {die "USAGE: archive.pl Noutfile\n"; }
+$Noutfile = $ARGV[0] + 1;
+$outfile = "archive" . $Noutfile . ".log";
+
+print STDERR "starting execution\n";
+vsystem ("date");
+if (-e $killfile) { goodbye "process killed with $killfile"; }
+
+
+if (-e $alockfile) { goodbye "archive lock $alockfile is set"; }
+open (TEMP, ">$alockfile");
+close (TEMP);
+
+# load in done date list
+open (DONELOG, $donelogfile);
+@donelist = ();
+while ($line = <DONELOG>) {
+  chop ($line);
+  @donelist = (@donelist,$line);
+}
+$Ndone = @donelist;
+close (DONELOG);
+
+# load in maestro list
+open (MAESTRO, $scriptfile);
+@todolist = ();
+while ($line = <MAESTRO>) {
+  chop ($line);
+  @todolist = (@todolist,$line);
+}
+$Ntodo = @todolist;
+close (MAESTRO);
+
+# find entries in MAESTRO that are NOT in DONELOG
+@leftlist = ();
+for ($i = 0; $i < $Ntodo; $i ++) {
+    $gotit = 0;
+    for ($j = 0; ($j < $Ndone) && ! $gotit; $j ++) {
+	@entries = split (" ",$todolist[$i]);
+	if ($entries[0] eq $donelist[$j]) {
+	    $gotit = 1;
+	}
+    }
+    if (!$gotit) {
+	@leftlist = (@leftlist, $todolist[$i]);  
+    }
+}
+$Nleft = @leftlist;
+
+if (-e $killfile) { goodbye "process killed with $killfile"; }
+# run controller on unfinished entries
+# we are going to run this in the script directory
+if ($Nleft) {
+    chdir $scriptdir;
+    for ($i = 0; $i < $Nleft; $i++) {
+	print STDERR "unfinished: $leftlist[$i]\n";
+	@entries = split (" ",$leftlist[$i]);
+	$inlist = $entries[0] . ".inlist";
+	$outlist = $entries[0] . ".outlist";
+	$subdir = $entries[0];
+	$photcode = $entries[1];
+	print STDERR "$subdir: $inlist $outlist $photcode\n";
+	if (-e $outlist) {
+	    # partially successful run, restart controller in the middle
+	    $tmp_inlist = $entries[0] . ".tmp_inlist";
+	    $tmpoutlist = $entries[0] . ".tmpoutlist";
+	    if (-e $tmpoutlist) { if (vsystem ("cat $tmpoutlist >> $outlist")) { goodbye "trouble merging $tmpoutlist and $outlist\n"; }}
+	    # partially successful re-start: make sure $outlist is complete
+	    if (parse_outlist ($outlist,$tmp_inlist,1)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s flatten", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    if (parse_outlist ($outlist,$tmp_inlist,2)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s dophot", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    if (parse_outlist ($outlist,$tmp_inlist,3)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s fstat", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    if (parse_outlist ($outlist,$tmp_inlist,4)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s gastro", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    if (parse_outlist ($outlist,$tmp_inlist,5)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s addstar", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    # do inlist entries not in outlist
+	    if (parse_inlist ($inlist,$outlist,$tmp_inlist)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s flatten", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    unless (unlink ($tmpoutlist)) { goodbye "can't unlink $tmpoutlist, why not?"; }
+	    unless (unlink ($tmp_inlist)) { goodbye "can't unlink $tmp_inlist, why not?"; }
+	    vsystem ("cleaning.pl");
+	    if (-e $lockfile) { goodbye "lock file exists"; }
+
+	    print STDERR "done: $entries[0]\n";
+	    open (DONELOG, ">>$donelogfile");
+	    print DONELOG "$entries[0]\n";
+	    close (DONELOG);
+	} else {
+	    $controlflags = "";
+	    docontroller ($subdir, $inlist, $outlist, $photcode, "-s flatten", 1);
+	    print STDERR "done: $subdir\n";
+	    open (DONELOG, ">>$donelogfile");
+	    print DONELOG "$subdir\n";
+	    close (DONELOG);
+	}
+    }
+    unless (unlink ($alockfile)) { goodbye "can't unlink $alockfile, why not?"; }
+    print STDERR "remember to delete images from complete directories\n";
+
+    unless (-e $haltfile) { 
+	print STDERR "re-did unfinished images\n";
+	print STDERR "starting a new archive.pl with output to $outfile\n";
+	vsystem ("notify.pl $ARGV[0] $outfile $Noutfile");
+	vsystem ("archive.pl $Noutfile 1>$outfile 2>&1 &");
+	exit;
+    }
+    goodbye "re-did unfinished images";
+}
+    
+print STDERR "no unfinished nights, slurping a new set\n";
+if (-e $scriptfile) { if (vsystem ("rm $scriptfile")) { goodbye "couldn't delete old MAESTRO file"; }}
+
+if (vsystem ("rsh -n pallas slurp.pl")) { goodbye "couldn't start slurp on pallas"; }
+if (-e $killfile) { goodbye "process killed with $killfile"; }
+if (!-e $scriptfile) {goodbye "slurp failed to download files"; }
+
+print STDERR "done slurping, starting controller runs\n";
+vsystem ("date");
+
+# run controller on the resulting images
+# controller wants to be run in the same directory as the inlists 
+chdir $scriptdir;
+open (MAESTRO, $scriptfile);
+while ($line = <MAESTRO>) {
+    @entries = split (" ",$line);
+    $inlist = $entries[0] . ".inlist";
+    $outlist = $entries[0] . ".outlist";
+    $subdir = $entries[0];
+    $photcode = $entries[1];
+    docontroller ($subdir, $inlist, $outlist, $photcode, "-s flatten", 1);
+    print STDERR "done: $subdir\n";
+    open (DONELOG, ">>$donelogfile");
+    print DONELOG "$entries[0]\n";
+    close (DONELOG);
+}
+close (MAESTRO);
+
+unless (unlink ($alockfile)) { goodbye "can't unlink $alockfile, why not?"; }
+print STDERR "ending execution\n";
+vsystem ("date");
+print STDERR "finished new images";
+
+unless (-e $haltfile) { 
+    print STDERR "starting a new archive.pl with output to $outfile\n";
+    vsystem ("notify.pl $ARGV[0] $outfile $Noutfile");
+    vsystem ("archive.pl $Noutfile 1>$outfile 2>&1 &");
+} else {
+    vsystem ("notify.pl $ARGV[0] none 0");
+}
+exit;
+
+# run nrphot on the altered cpt files and quit
+chdir $database;
+@files = `find . -name "*.cpt" -newer $reffile`;
+$Nfiles = @files;
+print STDERR "N: $Nfiles\n";
+foreach $f (@files) {
+    chop ($f);
+    vsystem ("nrphot -v $f");
+    if (-e $lockfile) { goodbye "lock file exists"; }
+}
+
+# delete inlist files
+
+# do controller (& cleaning if needed), taking care of flats and error conditions
+sub docontroller {
+    if (-e $killfile) { goodbye "process killed with $killfile"; }
+    if (-e $clockfile) { goodbye "lock file $clockfile exists"; }
+    # break up entry line
+    $outsubdir = $_[0];
+    $in = $_[1];
+    $out = $_[2];
+    $phot = $_[3];
+    $flags = $_[4];
+    $clean = $_[5];
+    # create sub-directory in output dir
+    $outdir = $workspace . $outsubdir;
+    unless (-e $outdir) { unless (mkdir ($outdir,0777)) { goodbye "cannot create output directory $outdir"; } }
+    # make link to correct flat
+    $flatlink = $flatdir . "newflat.fits";
+    $realflat = $flatdir . "flatcode" . $phot . ".fits";
+    if (-l $flatlink) { unless (unlink ($flatlink)) { goodbye "cannot unlink $flatlink"; }}
+    if (-e $flatlink) { goodbye "$flatlink exists, but is not a link!"; }
+    unless (symlink ($realflat, $flatlink)) { goodbye "cannot symlink $realflat to $flatlink"; }
+    # run controller and cleanup
+    if (-e $lockfile) { goodbye "lock file exists"; }
+    vsystem ("controller $flags -o $outsubdir $in $out $phot");
+    if (-e $clockfile) { goodbye "lock file $clockfile exists"; }
+    if (-e $lockfile) { goodbye "lock file exists"; }
+    if (-e $killfile) { goodbye "process killed with $killfile"; }
+    if ($clean) {
+	vsystem ("cleaning.pl");
+	if (-e $lockfile) { goodbye "lock file exists"; }
+    }
+}
+
+sub by_filename {
+    @value1 = split (" ", $a);
+    @value2 = split (" ", $b);
+    $value1[0] cmp $value2[0]; 
+}
+    
+# we read from in and write to out those files with 1st 0 in the mode column
+sub parse_outlist {
+    $in = $_[0];
+    $out = $_[1];
+    $mode = $_[2];
+    
+# load inlist
+    open (INLIST, $in);
+    @inarray = ();
+    while ($line = <INLIST>) {
+	chop ($line);
+	@inarray = (@inarray,$line);
+    }
+    $Nin = @inarray;
+    close (INLIST);
+    @inarray = sort by_filename @inarray;
+
+    @outarray = ();
+    for ($k = 0; $k < $Nin; $k++) {
+	@pvalues = split (" ", $inarray[$k]);
+	$more = 1;
+	while ($more) {
+	    print STDERR ".";
+	    @nvalues = split (" ", $inarray[$k+1]);
+	    if ($nvalues[0] cmp $pvalues[0]) {
+		$more = 0;
+	    } else {
+		$pvalues[1] |= $nvalues[1];
+		$pvalues[2] |= $nvalues[2];
+		$pvalues[3] |= $nvalues[3];
+		$pvalues[4] |= $nvalues[4];
+		$pvalues[5] |= $nvalues[5];
+		$k ++;
+	    }
+	}
+	# check the earlier status values: if failed earlier, skip
+	$skip = 0;
+	for ($m = 1; $m < $mode; $m++) { if (!$pvalues[$m]) { $skip = 1; } }
+	if (! $skip && !$pvalues[$mode]) {
+	    $name = $pvalues[0];
+	    $name =~ s/$dumpspace//;
+	    $name =~ s/://;
+	    @outarray = (@outarray,$name);
+	}
+    }
+    $Nout = @outarray;
+    if ($Nout) {
+	open (OUTLIST, ">$out");
+	for ($k = 0; $k < $Nout; $k++) {
+	    print OUTLIST "$outarray[$k]\n";
+	}
+	close (OUTLIST);
+    }
+    $Nout;
+}
+
+sub parse_inlist {
+    $in = $_[0];
+    $out = $_[1];
+    $new = $_[2];
+    
+# load inlist
+    open (INLIST, $in);
+    @inarray = ();
+    while ($line = <INLIST>) {
+	chop ($line);
+	@inarray = (@inarray,$line);
+    }
+    $Nin = @inarray;
+    close (INLIST);
+
+# load inlist
+    open (OUTLIST, $out);
+    @outarray = ();
+    while ($line = <OUTLIST>) {
+	chop ($line);
+	@outarray = (@outarray,$line);
+    }
+    $Nout = @outarray;
+    close (OUTLIST);
+
+# load outlist
+    @newarray = ();
+    for ($k = 0; $k < $Nin; $k++) {
+	$gotit = 0;
+	for ($m = 0; ! $gotit && ($m < $Nout); $m++) {
+	    if ($outarray[$m] =~ /$inarray[$k]/) {
+		$gotit = 1;
+	    }
+	}
+	if (!$gotit) {
+	    @newarray = (@newarray,$inarray[$k]);
+	}
+    }
+    $Nnew = @newarray;
+    if ($Nnew) {
+	open (NEWLIST, ">$new");
+	for ($k = 0; $k < $Nnew; $k++) {
+	    print NEWLIST "$inarray[$k]\n";
+	}
+	close (NEWLIST);
+    }
+    $Nnew;
+}
Index: /tags/start/Ohana/src/perl/loneos/checkoutfail.pl
===================================================================
--- /tags/start/Ohana/src/perl/loneos/checkoutfail.pl	(revision 12606)
+++ /tags/start/Ohana/src/perl/loneos/checkoutfail.pl	(revision 12606)
@@ -0,0 +1,63 @@
+#!/usr/bin/perl
+
+sub by_filename {
+    @value1 = split (" ", $a);
+    @value2 = split (" ", $b);
+    $value1[0] cmp $value2[0]; 
+}
+    
+# we read from in and write to out those files with 1st 0 in the mode column
+sub parse_outlist {
+    $in = $_[0];
+    $mode = $_[1];
+    
+# load inlist
+    open (INLIST, $in);
+    @inarray = ();
+    while ($line = <INLIST>) {
+	chop ($line);
+	@inarray = (@inarray,$line);
+    }
+    $Nin = @inarray;
+    close (INLIST);
+    @inarray = sort by_filename @inarray;
+
+    @outarray = ();
+    for ($k = 0; $k < $Nin; $k++) {
+	@pvalues = split (" ", $inarray[$k]);
+	$more = 1;
+	while ($more) {
+	    @nvalues = split (" ", $inarray[$k+1]);
+	    if ($nvalues[0] cmp $pvalues[0]) {
+		$more = 0;
+	    } else {
+		$pvalues[1] |= $nvalues[1];
+		$pvalues[2] |= $nvalues[2];
+		$pvalues[3] |= $nvalues[3];
+		$pvalues[4] |= $nvalues[4];
+		$pvalues[5] |= $nvalues[5];
+		$k ++;
+	    }
+	}
+	# check the earlier status values: if failed earlier, skip
+	$skip = 0;
+	for ($m = 1; $m < $mode; $m++) { if (!$pvalues[$m]) { $skip = 1; } }
+	if (! $skip && !$pvalues[$mode]) {
+	    $name = $pvalues[0];
+	    $name =~ s/$topdir//;
+	    $name =~ s/://;
+	    @outarray = (@outarray,$name);
+	}
+    }
+    $Nout = @outarray;
+    if ($Nout) {
+	for ($k = 0; $k < $Nout; $k++) {
+	    print STDERR "$mode: $outarray[$k]\n";
+	}
+    }
+    $Nout;
+}
+
+$outlist = $ARGV[0];
+
+parse_outlist ($outlist,5);
Index: /tags/start/Ohana/src/perl/loneos/checkoutlist.pl
===================================================================
--- /tags/start/Ohana/src/perl/loneos/checkoutlist.pl	(revision 12606)
+++ /tags/start/Ohana/src/perl/loneos/checkoutlist.pl	(revision 12606)
@@ -0,0 +1,65 @@
+#!/usr/bin/perl
+
+sub by_filename {
+    @value1 = split (" ", $a);
+    @value2 = split (" ", $b);
+    $value1[0] cmp $value2[0]; 
+}
+    
+# we read from in and write to out those files with 1st 0 in the mode column
+sub parse_outlist {
+    $in = $_[0];
+    $mode = $_[1];
+    
+# load inlist
+    open (INLIST, $in);
+    @inarray = ();
+    while ($line = <INLIST>) {
+	chop ($line);
+	@inarray = (@inarray,$line);
+    }
+    $Nin = @inarray;
+    close (INLIST);
+    @inarray = sort by_filename @inarray;
+
+    @outarray = ();
+    for ($k = 0; $k < $Nin; $k++) {
+	@pvalues = split (" ", $inarray[$k]);
+	$more = 1;
+	while ($more) {
+	    @nvalues = split (" ", $inarray[$k+1]);
+	    if ($nvalues[0] cmp $pvalues[0]) {
+		$more = 0;
+	    } else {
+		$pvalues[1] |= $nvalues[1];
+		$pvalues[2] |= $nvalues[2];
+		$pvalues[3] |= $nvalues[3];
+		$pvalues[4] |= $nvalues[4];
+		$pvalues[5] |= $nvalues[5];
+		$k ++;
+	    }
+	}
+	# check the earlier status values: if failed earlier, skip
+	$skip = 0;
+	for ($m = 1; $m < $mode; $m++) { if (!$pvalues[$m]) { $skip = 1; } }
+	if (! $skip && !$pvalues[$mode]) {
+	    $name = $pvalues[0];
+	    $name =~ s/$topdir//;
+	    $name =~ s/://;
+	    @outarray = (@outarray,$name);
+	}
+    }
+    $Nout = @outarray;
+    if ($Nout) {
+	for ($k = 0; $k < $Nout; $k++) {
+	    print STDOUT "$mode: $outarray[$k]\n";
+	}
+    }
+    $Nout;
+}
+
+$outlist = $ARGV[0];
+
+for ($i = 1; $i < 6; $i++) {
+    parse_outlist ($outlist,$i);
+}
Index: /tags/start/Ohana/src/perl/loneos/cleaning.pl
===================================================================
--- /tags/start/Ohana/src/perl/loneos/cleaning.pl	(revision 12606)
+++ /tags/start/Ohana/src/perl/loneos/cleaning.pl	(revision 12606)
@@ -0,0 +1,30 @@
+#!/usr/bin/perl
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+$database = "/hebe/d27/database/";
+$lockfile = $database . "lock";
+$reffile = $database . "start.clean";
+
+chdir $database;
+
+@files = `find . -name "*.cpt" -newer $reffile`;
+$Nfiles = @files;
+print STDERR "N: $Nfiles\n";
+
+if (-e $lockfile) { die "lock file exists"; }
+
+foreach $f (@files) {
+    chop ($f);
+    vsystem ("markstar -v $f");
+    if (-e $lockfile) { die "lock file exists"; }
+    vsystem ("addusno -v $f");
+    if (-e $lockfile) { die "lock file exists"; }
+    vsystem ("markrock -v $f");
+    if (-e $lockfile) { die "lock file exists"; }
+}
+
Index: /tags/start/Ohana/src/perl/loneos/locks.pl
===================================================================
--- /tags/start/Ohana/src/perl/loneos/locks.pl	(revision 12606)
+++ /tags/start/Ohana/src/perl/loneos/locks.pl	(revision 12606)
@@ -0,0 +1,93 @@
+#!/usr/bin/perl
+
+$topdir  = "/pallas/";
+$scriptdir = "/hebe/d27/logs/";
+$donelogfile = $scriptdir . "done.log";
+$scriptfile = $scriptdir . "maestro.dat";
+$flatdir = "/hebe/d27/references/config/";
+
+$workspace = "/hebe/d27/workspace/";
+$database = "/hebe/d27/database/";
+$lockfile = $database . "lock";
+$alockfile = $database . "alock";
+$clockfile = $database . "clock";
+$killfile  = $database . "kill";
+$haltfile  = $database . "halt";
+$reffile = $database . "start.clean";
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    vsystem ("date");
+    die "@_";
+}
+
+$Narg = @ARGV;
+if ($Narg > 1) {
+    goodbye "USAGE: locks.pl [-reset] [-halt] [-kill] [-dB] [-controller] [-archive]";
+}
+
+unless ($ARGV[0] cmp "-reset") {
+    unlink ($lockfile);
+    unlink ($alockfile);
+    unlink ($clockfile);
+    unlink ($killfile);
+    unlink ($haltfile);
+    exit;
+}
+
+unless ($ARGV[0] cmp "-kill") {
+    open (TEMP, ">$killfile");
+    close (TEMP);
+    exit;
+}
+
+unless ($ARGV[0] cmp "-halt") {
+    open (TEMP, ">$haltfile");
+    close (TEMP);
+    exit;
+}
+
+unless ($ARGV[0] cmp "-dB") {
+    open (TEMP, ">$lockfile");
+    close (TEMP);
+    exit;
+}
+
+unless ($ARGV[0] cmp "-controller") {
+    open (TEMP, ">$clockfile");
+    close (TEMP);
+    exit;
+}
+
+unless ($ARGV[0] cmp "-archive") {
+    open (TEMP, ">$alockfile");
+    close (TEMP);
+    exit;
+}
+
+@locks = ();
+if (-e $lockfile) { @locks = (@locks,$lockfile); }
+if (-e $alockfile) { @locks = (@locks,$alockfile); }
+if (-e $clockfile) { @locks = (@locks,$clockfile); }
+if (-e $killfile) { @locks = (@locks,$killfile); }
+if (-e $haltfile) { @locks = (@locks,$haltfile); }
+
+$Nlocks = @locks;
+
+if ($Nlocks > 0) {
+    print STDERR "locks set:\n";
+    for ($i = 0; $i < $Nlocks; $i++) {
+	print STDERR "$locks[$i]\n";
+    }
+} else {
+    print STDERR "no locks currently set\n";
+}
+
+print STDERR "\n";
+print STDERR "USAGE: locks.pl [-reset] [-kill] [-dB] [-controller] [-archive]\n";
Index: /tags/start/Ohana/src/perl/loneos/notify.pl
===================================================================
--- /tags/start/Ohana/src/perl/loneos/notify.pl	(revision 12606)
+++ /tags/start/Ohana/src/perl/loneos/notify.pl	(revision 12606)
@@ -0,0 +1,12 @@
+#!/usr/bin/perl
+
+$target= "gene\@astro.washington.edu";
+$targetmachine = "astro.washington.edu";
+
+$last = "archive." . $ARGV[0];
+$next = $ARGV[1];
+$N = $ARGV[2];
+
+# system ("echo \"done with $last, starting $next ($N)\" | mail $targetname\@$targetmachine");
+system ("echo \"done with $last, starting $next ($N)\" | mail $target");
+
Index: /tags/start/Ohana/src/perl/loneos/rearchive.pl
===================================================================
--- /tags/start/Ohana/src/perl/loneos/rearchive.pl	(revision 12606)
+++ /tags/start/Ohana/src/perl/loneos/rearchive.pl	(revision 12606)
@@ -0,0 +1,71 @@
+#!/usr/bin/perl
+
+# $dumpspace = "/pallas/d1/";
+# $workspace = "/metis/d27/workspace/";
+# $workspace = "/irene/d11/workspace/";
+
+$database = "/hebe/d27/database/";
+$lockfile = $database . "lock";
+$alockfile = $database . "alock";
+$clockfile = $database . "clock";
+$killfile  = $database . "kill";
+$haltfile  = $database . "halt";
+$reffile = $database . "start.clean";
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    vsystem ("date");
+    die "@_";
+}
+
+if (@ARGV < 1) {die "USAGE: rearchive.pl dir\n"; }
+
+$target = $ARGV[0];
+
+print STDERR "starting execution\n";
+vsystem ("date");
+if (-e $killfile) { goodbye "process killed with $killfile"; }
+
+if (-e $alockfile) { goodbye "archive lock $alockfile is set"; }
+open (TEMP, ">$alockfile");
+close (TEMP);
+
+# untar directory 
+
+if (!-e $target.tgz) { goodbye "target $target.tgz not found"; }
+
+if (vsystem ("gunzip -c $target.tgz | tar xvf -")) { goodbye "untar failed for $target.tgz"; }
+if (vsystem ("ls $target/*.cmp > $target.lst")) { goodbye "failed to get directory listing for $target"; }
+
+open (TEMP, ">$target.log");
+close (TEMP);
+if (!-e $target.log) { goodbye "could not create $target.log"; }
+
+# load in done date list
+open (LISTFILE, $target.lst);
+@listfile = ();
+while ($line = <LISTFILE>) {
+  chop ($line);
+  @listfile = (@listfile,$line);
+}
+$Nlist = @listfile;
+close (LISTFILE);
+
+for ($i = 0; $i < Nlist; $i++) {
+    if (-e $lockfile) { goodbye "database lock $lockfile is set"; }
+    vsystem ("addstar -v $listfile[$i]");
+}
+
+if (-e $lockfile) { goodbye "lock file exists"; }
+vsystem ("cleaning.pl");
+if (-e $lockfile) { goodbye "lock file exists"; }
+
+# vsystem ("rm $target");
+exit;
+
Index: /tags/start/Ohana/src/perl/loneos/slurp
===================================================================
--- /tags/start/Ohana/src/perl/loneos/slurp	(revision 12606)
+++ /tags/start/Ohana/src/perl/loneos/slurp	(revision 12606)
@@ -0,0 +1,223 @@
+#!/usr/bin/env perl
+
+$Ngrab = 5;
+$scriptdir   = "/hebe/d27/logs/";
+$dumpspace   = "/pallas/d1/";
+$tapedrive   = "/dev/rmt/1cn";
+$tapelogfile = $scriptdir . "tape.log";
+$donelogfile = $scriptdir . "processed.log";
+$scriptfile  = $scriptdir . "extracted.log";
+
+# old directories:
+# $topdir  = "/pallas/";
+# $rootdir = "/pallas/d1/";
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "@_\n";
+    vsystem ("unload $tape");
+    vsystem ("lunlock $tapedrive");
+    vsystem ("lunlock $dumpspace");
+    die;
+}
+
+# goodbye ("quit suddenly");
+
+# checkdone (line)
+# returns 1 if not in line (and sets $name), 
+# returns 0 otherwise
+sub checkdone {
+    local($inline) = @_;
+    @entries = split (" ",$inline);
+    $found = 0;
+    if ((@entries[0] > 1996) && (@entries[0] < 2097)) {
+	$found = 1;
+	$name = substr(@entries[0],2,2) . @entries[1] . @entries[2];
+	for ($j = 0; ($j < $Ndone) && ($found); $j++) {
+	    @done = split (" ", $donelist[$j]);
+	    if ($done[0] eq $name) {
+		$found = 0;
+	    }
+	}
+    }
+    $found;
+}
+
+# checktape (name)
+# find all entries which match name and add to dolist
+sub checktape {
+  local($inname) = @_;
+  $j = 0;
+  while ($j < $Ntape) {
+    @entries = split (" ",$tapelist[$j]);
+    if ((@entries[0] > 1996) && (@entries[0] < 2097)) {
+      $tmpname = substr(@entries[0],2,2) . @entries[1] . @entries[2];
+      if ($inname eq $tmpname) {
+	@dolist = (@dolist,$tapelist[$j]);
+	@doname = (@doname,$inname);
+      }
+    }
+    $j ++;
+  }
+}
+
+
+# load in done date list
+open (DONELOG, $donelogfile);
+@donelist = ();
+while ($line = <DONELOG>) {
+  chop ($line);
+  @donelist = (@donelist,$line);
+}
+$Ndone = @donelist;
+close (DONELOG);
+print "Ndone = $Ndone\n";
+
+# load in tape.log list
+open (TAPELOG, $tapelogfile);
+@tapelist = ();
+while ($line = <TAPELOG>) {
+  chop ($line);
+  @tapelist = (@tapelist,$line);
+}
+$Ntape = @tapelist;
+close (TAPELOG);
+# @tapelist = reverse(@tapelist);
+print "Ntape = $Ntape\n";
+
+# find 5 new nights not already in the "donelist"
+$N = 0;
+@tryname = ();
+for ($i = 0; ($i < $Ntape) && ($N < $Ngrab); $i++) {
+    if (&checkdone ($tapelist[$i])) {
+	$j = 0; 
+	$gotit = 0;
+	for ($j = 0; ($j < $N) && (! $gotit); $j++) {
+	    if ($name eq $tryname[$j]) {
+		$gotit = 1;
+	    }
+	}
+	if (! $gotit) {
+	    @tryname = (@tryname, $name);  
+	    $N ++;
+	}
+    }
+}
+$Ntryname = @tryname;
+# tryname has a list of the 980103 style names
+
+# now that we have a list of interesting nights, 
+# get a list of the actual lines from tape.log, 
+# along with a list of the matchine names
+$i = 0;
+@dolist = ();
+@doname = ();
+while ($i < $Ntryname) {
+  &checktape ($tryname[$i]);
+  $i ++;
+}
+
+$i = 0;
+$Ndolist = @dolist;
+@fileno = ();
+@tapeno = ();
+@gbytes = ();
+@photno = ();
+@entry = ();
+while ($i < $Ndolist) {
+    print STDERR "$doname[$i] == $dolist[$i]\n";
+    @words = split (" ",$dolist[$i]);
+    @entry = (@entry,$i);
+    @tapeno = (@tapeno,$words[3]);
+    @fileno = (@fileno,$words[4]);
+    @gbytes = (@gbytes,$words[5]);
+    @photno = (@photno,$words[8]);
+    $i ++;
+}
+
+# delete old downloaded data
+
+$dir = $dumpspace . "9";
+print STDERR "dir: $dir\n";
+@files = <$dir*>;
+$Nfiles = @files;
+print "files: @files\n";
+for ($i = 0; $i < $Nfiles; $i++) {
+    if ((-d $files[$i]) && (-O $files[$i])) {
+	if (vsystem ("rm -r $files[$i]")) { goodbye "error deleting directory $files[$i]"; }
+    }
+}
+
+# now sort the entries by tape and file number:
+
+sub by_tape_and_file { ($tapeno[$a] <=> $tapeno[$b]) || ($fileno[$a] <=> $fileno[$b]); }
+@entry = sort by_tape_and_file @entry;
+
+# lock tape and disk space. keep trying for up to 10 hours
+for ($i = 0; ($i < 30) && vsystem ("llock $dumpspace"); $i++) { system ("sleep 1200"); }
+ if ($i == 100) { goodbye "failed to grab disk space"; }
+for ($i = 0; ($i < 30) && vsystem ("llock $tapedrive"); $i++) { system ("sleep 1200"); }
+ if ($i == 100) { goodbye "failed to grab tape drive"; }
+
+$tape = -1;
+for ($i = 0; $i < $Ndolist; $i++) {
+    # do a df and compare to $gbytes[$entry[$i]]
+    @answer = `df -k $dumpspace`;
+    @tmp = split (" ", $answer[1]);
+    $space = $tmp[3] / (1024*1024);
+    print STDERR "compare $space and $gbytes[$entry[$i]]\n";
+    if (0.95*$space < $gbytes[$entry[$i]]) { last; }
+    # load tape if needed
+    if ($tapeno[$entry[$i]] != $tape) {
+	# unload old tape, load desired tape 
+	if ($tape != -1) { if (vsystem ("unload $tape")) { goodbye "trouble unloading tape $tape"; } }
+	if (vsystem ("load $tapeno[$entry[$i]]")) { goodbye "trouble loading tape $tapeno[$entry[$i]]"; }
+	$tape = $tapeno[$entry[$i]];
+	$j = 0;
+	$offline = 1;
+	# wait for tape to come online before starting anything
+	while (($j < 12) && $offline) {
+	    vsystem ("sleep 10");
+	    $offline = vsystem ("mt -f $tapedrive status");
+	    $j ++;
+	}
+	if ($j == 12) { goodbye "tape still not online!"; }
+	$file = 0;
+    }
+    # advance to first file of interest
+    $nskip = $fileno[$entry[$i]] - $file;
+    if ($nskip > 0) {
+	if (vsystem ("mt -f $tapedrive fsf $nskip")) { goodbye "error advancing tape"; }
+    }
+    # create output directory if it doesn't exist
+    $dir = $dumpspace . $doname[$entry[$i]];
+    unless (-e $dir) {
+	unless (mkdir ($dir,0777)) { goodbye "cannot create output directory $dir"; }
+    }
+    chdir $dir;
+    # extract the files
+    vsystem ("tar -xvfb $tapedrive 128");
+    $file = $fileno[$entry[$i]] + 1;
+}
+$Ndolist = $i;
+
+if (vsystem("unload $tape")) { goodbye "trouble unloading tape $tape"; }
+if (vsystem("lunlock $tapedrive")) { goodbye "trouble unlocking tape drive $tapedrive"; }
+if (vsystem ("lunlock $dumpspace")) { goodbye "trouble unlocking disk drive $dumpspace"; }
+
+open (MAESTRO, ">$scriptfile");
+chdir $dumpspace;
+$i = 0;
+while ($i < $Ndolist) {
+    vsystem ("ls $doname[$entry[$i]]/*b.fits > $scriptdir/$doname[$entry[$i]].inlist");
+    print MAESTRO "$doname[$entry[$i]] $photno[$entry[$i]] \n";
+    $i ++;
+}
+close (MAESTRO);
+
+1;
Index: /tags/start/Ohana/src/perl/loneos/stage1
===================================================================
--- /tags/start/Ohana/src/perl/loneos/stage1	(revision 12606)
+++ /tags/start/Ohana/src/perl/loneos/stage1	(revision 12606)
@@ -0,0 +1,342 @@
+#!/usr/bin/env perl
+
+# in this script, we run flatten, dophot, fstat, and gastro
+# these can be run totally in parallel, so this routine runs
+# independently of the series processing (addstar, markstar, etc)
+# in stage2
+
+# for now these directories are hard-wired.  eventually, they
+# should be looked up in the config file, so all scripts are
+# consistent
+$dumpspace = "/pallas/d1/";
+$workspace = "/metis/d27/workspace/";
+# $workspace = "/irene/d11/workspace/";
+
+$scriptdir = "/hebe/d27/logs/";
+$donelogfile = $scriptdir . "processed.log";
+$scriptfile  = $scriptdir . "extracted.log";
+$flatdir = "/hebe/d27/references/config/";
+
+$database = "/hebe/d27/database/";
+$alockfile = $database . "alock1";     # lock on stage1 (only 1 running at a time)
+$clockfile = $database . "clock1";     # lock on controller
+$killfile  = $database . "kill";       # quickly stop the processing
+$haltfile  = $database . "halt";       # halt processing after this loop
+$reffile = $database . "start.clean";
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    vsystem ("date");
+    vsystem ("notify.pl $ARGV[0] none 0");
+    die "@_";
+}
+
+if (@ARGV < 1) {die "USAGE: stage1 Noutfile\n"; }
+$Noutfile = $ARGV[0] + 1;
+$outfile = "stage1." . $Noutfile . ".log";
+
+print STDERR "starting execution\n";
+vsystem ("date");
+if (-e $killfile) { goodbye "process killed with $killfile"; }
+
+
+if (-e $alockfile) { goodbye "archive lock $alockfile is set"; }
+open (TEMP, ">$alockfile");
+close (TEMP);
+
+# load in done date list
+open (DONELOG, $donelogfile);
+@donelist = ();
+while ($line = <DONELOG>) {
+  chop ($line);
+  @donelist = (@donelist,$line);
+}
+$Ndone = @donelist;
+close (DONELOG);
+
+# load in maestro list
+open (MAESTRO, $scriptfile);
+@todolist = ();
+while ($line = <MAESTRO>) {
+  chop ($line);
+  @todolist = (@todolist,$line);
+}
+$Ntodo = @todolist;
+close (MAESTRO);
+
+# find entries in MAESTRO that are NOT in DONELOG
+@leftlist = ();
+for ($i = 0; $i < $Ntodo; $i ++) {
+    $gotit = 0;
+    for ($j = 0; ($j < $Ndone) && ! $gotit; $j ++) {
+	@todo = split (" ",$todolist[$i]);
+	@done = split (" ",$donelist[$j]);
+	if ($todo[0] eq $done[0]) {
+	    $gotit = 1;
+	}
+    }
+    if (!$gotit) {
+	@leftlist = (@leftlist, $todolist[$i]);  
+    }
+}
+$Nleft = @leftlist;
+
+if (-e $killfile) { goodbye "process killed with $killfile"; }
+# run controller on unfinished entries
+# we are going to run this in the script directory
+if ($Nleft) {
+    chdir $scriptdir;
+    for ($i = 0; $i < $Nleft; $i++) {
+	print STDERR "unfinished: $leftlist[$i]\n";
+	@entries = split (" ",$leftlist[$i]);
+	$inlist = $entries[0] . ".inlist";
+	$outlist = $entries[0] . ".addlist";
+	$subdir = $entries[0];
+	$photcode = $entries[1];
+	print STDERR "$subdir: $inlist $outlist $photcode\n";
+	if (-e $outlist) {
+	    # partially successful run, restart controller in the middle
+	    $tmp_inlist = $entries[0] . ".tmp_inlist";
+	    $tmpoutlist = $entries[0] . ".tmpaddlist";
+	    if (-e $tmpoutlist) { if (vsystem ("cat $tmpoutlist >> $outlist")) { goodbye "trouble merging $tmpoutlist and $outlist\n"; }}
+	    # partially successful re-start: make sure $outlist is complete
+	    if (parse_outlist ($outlist,$tmp_inlist,1)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s flatten", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    if (parse_outlist ($outlist,$tmp_inlist,2)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s dophot", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    if (parse_outlist ($outlist,$tmp_inlist,3)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s fstat", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    if (parse_outlist ($outlist,$tmp_inlist,4)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s gastro", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    # do inlist entries not in outlist
+	    if (parse_inlist ($inlist,$outlist,$tmp_inlist)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s flatten", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    unless (unlink ($tmpoutlist)) { goodbye "can't unlink $tmpoutlist, why not?"; }
+	    unless (unlink ($tmp_inlist)) { goodbye "can't unlink $tmp_inlist, why not?"; }
+	    # done with this night, add to donelogfile
+	    print STDERR "done: $subdir $photcode\n";
+	    open (DONELOG, ">>$donelogfile");
+	    print DONELOG "$subdir $photcode\n";
+	    close (DONELOG);
+	} else {
+	    docontroller ($subdir, $inlist, $outlist, $photcode, "-s flatten", 1);
+	    print STDERR "done: $subdir $photcode\n";
+	    open (DONELOG, ">>$donelogfile");
+	    print DONELOG "$subdir $photcode\n";
+	    close (DONELOG);
+	}
+    }
+    unless (unlink ($alockfile)) { goodbye "can't unlink $alockfile, why not?"; }
+    print STDERR "remember to delete images from complete directories\n";
+
+    unless (-e $haltfile) { 
+	print STDERR "re-did unfinished images\n";
+	print STDERR "starting a new stage1 with output to $outfile\n";
+	vsystem ("notify.pl $ARGV[0] $outfile $Noutfile");
+	vsystem ("stage1 $Noutfile 1>$outfile 2>&1 &");
+	exit;
+    }
+    goodbye "re-did unfinished images";
+}
+    
+# get a new set of data
+print STDERR "no unfinished nights, slurping a new set\n";
+if (-e $scriptfile) { if (vsystem ("rm $scriptfile")) { goodbye "couldn't delete old MAESTRO file"; }}
+
+if (vsystem ("rsh -n pallas slurp")) { goodbye "couldn't start slurp on pallas"; }
+if (-e $killfile) { goodbye "process killed with $killfile"; }
+if (!-e $scriptfile) {goodbye "slurp failed to download files"; }
+
+print STDERR "done slurping, starting controller runs\n";
+vsystem ("date");
+
+# run controller on the resulting images
+# controller wants to be run in the same directory as the inlists 
+$Nruns = 0;
+chdir $scriptdir;
+open (MAESTRO, $scriptfile);
+while ($line = <MAESTRO>) {
+    @entries = split (" ",$line);
+    $inlist = $entries[0] . ".inlist";
+    $outlist = $entries[0] . ".addlist";
+    $subdir = $entries[0];
+    $photcode = $entries[1];
+    docontroller ($subdir, $inlist, $outlist, $photcode, "-s flatten", 1);
+    print STDERR "done: $subdir $photcode\n";
+    open (DONELOG, ">>$donelogfile");
+    print DONELOG "$subdir $photcode\n";
+    close (DONELOG);
+    $Nruns ++;
+}
+close (MAESTRO);
+
+if (Nruns == 0) {
+    print STDERR "no data downloaded in slurp, waiting for a while\n";
+    vsystem ("sleep 3600");
+}
+unless (unlink ($alockfile)) { goodbye "can't unlink $alockfile, why not?"; }
+print STDERR "ending execution\n";
+vsystem ("date");
+print STDERR "finished new images";
+
+unless (-e $haltfile) { 
+    print STDERR "starting a new stage1 with output to $outfile\n";
+    vsystem ("notify.pl $ARGV[0] $outfile $Noutfile");
+    vsystem ("stage1 $Noutfile 1>$outfile 2>&1 &");
+} else {
+    vsystem ("notify.pl $ARGV[0] none 0");
+}
+exit;
+
+# do controller (& cleaning if needed), taking care of flats and error conditions
+sub docontroller {
+    if (-e $killfile) { goodbye "process killed with $killfile"; }
+    if (-e $clockfile) { goodbye "lock file $clockfile exists"; }
+    # break up entry line
+    $outsubdir = $_[0];
+    $in = $_[1];
+    $out = $_[2];
+    $phot = $_[3];
+    $flags = $_[4];
+    $clean = $_[5];
+    # create sub-directory in output dir
+    $outdir = $workspace . $outsubdir;
+    unless (-e $outdir) { unless (mkdir ($outdir,0777)) { goodbye "cannot create output directory $outdir"; } }
+    # make link to correct flat
+    $flatlink = $flatdir . "newflat.fits";
+    $realflat = $flatdir . "flatcode" . $phot . ".fits";
+    if (-l $flatlink) { unless (unlink ($flatlink)) { goodbye "cannot unlink $flatlink"; }}
+    if (-e $flatlink) { goodbye "$flatlink exists, but is not a link!"; }
+    unless (symlink ($realflat, $flatlink)) { goodbye "cannot symlink $realflat to $flatlink"; }
+    # run controller and cleanup
+    vsystem ("control1 $flags -o $outsubdir $in $out $phot");
+    if (-e $clockfile) { goodbye "lock file $clockfile exists"; }
+    if (-e $killfile) { goodbye "process killed with $killfile"; }
+}
+
+sub by_filename {
+    @value1 = split (" ", $a);
+    @value2 = split (" ", $b);
+    $value1[0] cmp $value2[0]; 
+}
+    
+# we read from in and write to out those files with 1st 0 in the mode column
+sub parse_outlist {
+    $in = $_[0];
+    $out = $_[1];
+    $mode = $_[2];
+    
+# load inlist
+    open (INLIST, $in);
+    @inarray = ();
+    while ($line = <INLIST>) {
+	chop ($line);
+	@inarray = (@inarray,$line);
+    }
+    $Nin = @inarray;
+    close (INLIST);
+    @inarray = sort by_filename @inarray;
+
+    @outarray = ();
+    for ($k = 0; $k < $Nin; $k++) {
+	@pvalues = split (" ", $inarray[$k]);
+	$more = 1;
+	while ($more) {
+	    print STDERR ".";
+	    @nvalues = split (" ", $inarray[$k+1]);
+	    if ($nvalues[0] cmp $pvalues[0]) {
+		$more = 0;
+	    } else {
+		$pvalues[1] |= $nvalues[1];
+		$pvalues[2] |= $nvalues[2];
+		$pvalues[3] |= $nvalues[3];
+		$pvalues[4] |= $nvalues[4];
+		$pvalues[5] |= $nvalues[5];
+		$k ++;
+	    }
+	}
+	# check the earlier status values: if failed earlier, skip
+	$skip = 0;
+	for ($m = 1; $m < $mode; $m++) { if (!$pvalues[$m]) { $skip = 1; } }
+	if (! $skip && !$pvalues[$mode]) {
+	    $name = $pvalues[0];
+	    $name =~ s/$dumpspace//;
+	    $name =~ s/://;
+	    @outarray = (@outarray,$name);
+	}
+    }
+    $Nout = @outarray;
+    if ($Nout) {
+	open (OUTLIST, ">$out");
+	for ($k = 0; $k < $Nout; $k++) {
+	    print OUTLIST "$outarray[$k]\n";
+	}
+	close (OUTLIST);
+    }
+    $Nout;
+}
+
+sub parse_inlist {
+    $in = $_[0];
+    $out = $_[1];
+    $new = $_[2];
+    
+# load inlist
+    open (INLIST, $in);
+    @inarray = ();
+    while ($line = <INLIST>) {
+	chop ($line);
+	@inarray = (@inarray,$line);
+    }
+    $Nin = @inarray;
+    close (INLIST);
+
+# load inlist
+    open (OUTLIST, $out);
+    @outarray = ();
+    while ($line = <OUTLIST>) {
+	chop ($line);
+	@outarray = (@outarray,$line);
+    }
+    $Nout = @outarray;
+    close (OUTLIST);
+
+# load outlist
+    @newarray = ();
+    for ($k = 0; $k < $Nin; $k++) {
+	$gotit = 0;
+	for ($m = 0; ! $gotit && ($m < $Nout); $m++) {
+	    if ($outarray[$m] =~ /$inarray[$k]/) {
+		$gotit = 1;
+	    }
+	}
+	if (!$gotit) {
+	    @newarray = (@newarray,$inarray[$k]);
+	}
+    }
+    $Nnew = @newarray;
+    if ($Nnew) {
+	open (NEWLIST, ">$new");
+	for ($k = 0; $k < $Nnew; $k++) {
+	    print NEWLIST "$newarray[$k]\n";
+	}
+	close (NEWLIST);
+    }
+    $Nnew;
+}
Index: /tags/start/Ohana/src/perl/loneos/stage2
===================================================================
--- /tags/start/Ohana/src/perl/loneos/stage2	(revision 12606)
+++ /tags/start/Ohana/src/perl/loneos/stage2	(revision 12606)
@@ -0,0 +1,307 @@
+#!/usr/bin/env perl
+
+# in this script, we run addstar and the cleaning routines
+# these must be run in series, so this routine runs
+# independently of the parallel processing in stage1
+
+# for now these directories are hard-wired.  eventually, they
+# should be looked up in the config file, so all scripts are
+# consistent
+$dumpspace = "/pallas/d1/";
+$workspace = "/metis/d27/workspace/";
+# $workspace = "/irene/d11/workspace/";
+
+#$scriptdir = "/hebe/d27/logs/";
+$scriptdir = "./";
+$addstarfile = $scriptdir . "addstared.log";
+$processfile = $scriptdir . "processed.log";
+$flatdir = "/hebe/d27/references/config/";
+
+$database = "/hebe/d27/database/";
+$lockfile = $database . "lock";      # lock on database files
+$alockfile = $database . "alock2";   # lock on stage2 (only 1 running at a time)
+$clockfile = $database . "clock2";   # lock on control2
+$killfile  = $database . "kill";     # quickly stop the processing
+$haltfile  = $database . "halt";     # halt processing after this loop
+$reffile = $database . "start.clean";
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    vsystem ("date");
+    vsystem ("notify.pl $ARGV[0] none 0");
+    die "@_";
+}
+
+if (@ARGV < 1) {die "USAGE: stage2 Noutfile\n"; }
+$Noutfile = $ARGV[0] + 1;
+$outfile = "stage2." . $Noutfile . ".log";
+
+print STDERR "starting execution\n";
+vsystem ("date");
+if (-e $killfile) { goodbye "process killed with $killfile"; }
+
+if (-e $alockfile) { goodbye "archive lock $alockfile is set"; }
+open (TEMP, ">$alockfile");
+close (TEMP);
+
+$Ntries = 0;
+$Nleft = 0;
+@leftlist = ();
+
+while (! $Nleft) {
+    compare_done_todo ();
+    if (-e $killfile) { goodbye "process killed with $killfile"; }
+    vsystem ("sleep 60");
+    if (-e $killfile) { goodbye "process killed with $killfile"; }
+    $Ntries ++;
+    if ($Ntries == 1440) { goodbye "timeout waiting for new data"; }
+}
+
+if (-e $killfile) { goodbye "process killed with $killfile"; }
+
+chdir $scriptdir;
+
+for ($i = 0; $i < $Nleft; $i++) {
+    print STDERR "adding: $leftlist[$i]\n";
+    @entries = split (" ",$leftlist[$i]);
+    $inlist = $entries[0] . ".addlist";
+    $outlist = $entries[0] . ".outlist";
+    $subdir = $entries[0];
+    $photcode = $entries[1];
+    print STDERR "$subdir: $inlist $outlist $photcode\n";
+    if (-e $outlist) {
+	# partially successful run, restart controller in the middle
+	$tmp_inlist = $entries[0] . ".tmpaddlist";
+	$tmpoutlist = $entries[0] . ".tmpoutlist";
+	if (-e $tmpoutlist) { if (vsystem ("cat $tmpoutlist >> $outlist")) { goodbye "trouble merging $tmpoutlist and $outlist\n"; }}
+	# partially successful re-start: make sure $outlist is complete
+	print STDERR "re-running unfinished entries in outlist\n";
+	if (parse_outlist ($outlist,$tmp_inlist, 4)) {
+	    docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s addstar", 0);
+	    vsystem ("cat $tmpoutlist >> $outlist");
+	}
+	# do inlist entries not in outlist
+	print STDERR "running undone entries in addlist\n";
+	parse_outlist ($inlist,"tmpinlist", 4);
+	parse_outlist ($outlist,"tmpoutlist", 5);
+	if (match_lists ("tmpinlist","tmpoutlist","$tmp_inlist")) {
+	    docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s addstar", 0);
+	    vsystem ("cat $tmpoutlist >> $outlist");
+	}
+	# check ending success
+	unless (unlink ($tmpoutlist)) { goodbye "can't unlink $tmpoutlist, why not?"; }
+	unless (unlink ($tmp_inlist)) { goodbye "can't unlink $tmp_inlist, why not?"; }
+	vsystem ("cleaning.pl");
+	if (-e $lockfile) { goodbye "lock file exists"; }
+	
+	print STDERR "done: $subdir\n";
+	open (DONELOG, ">>$addstarfile");
+	print DONELOG "$subdir\n";
+	close (DONELOG);
+    } else {
+	$controlflags = "";
+	parse_outlist ($inlist,"tmpinlist", 4);
+	docontroller ($subdir, "tmpinlist", $outlist, $photcode, "-s addstar", 1);
+	print STDERR "done: $subdir\n";
+	open (DONELOG, ">>$addstarfile");
+	print DONELOG "$subdir\n";
+	close (DONELOG);
+    }
+}
+unless (unlink ($alockfile)) { goodbye "can't unlink $alockfile, why not?"; }
+print STDERR "remember to delete images from complete directories\n";
+
+unless (-e $haltfile) { 
+    print STDERR "re-did unfinished images\n";
+    print STDERR "starting a new stage2 with output to $outfile\n";
+    vsystem ("notify.pl $ARGV[0] $outfile $Noutfile");
+    vsystem ("stage2 $Noutfile 1>$outfile 2>&1 &");
+    exit;
+}
+goodbye "added images";
+exit;
+
+# do controller (& cleaning if needed), taking care of flats and error conditions
+sub docontroller {
+    if (-e $killfile) { goodbye "process killed with $killfile"; }
+    if (-e $clockfile) { goodbye "lock file $clockfile exists"; }
+    # break up entry line
+    $outsubdir = $_[0];
+    $in = $_[1];
+    $out = $_[2];
+    $phot = $_[3];
+    $flags = $_[4];
+    $clean = $_[5];
+    # run controller and cleanup
+    if (-e $lockfile) { goodbye "lock file exists"; }
+    vsystem ("control2 $flags -o $outsubdir $in $out $phot");
+    if (-e $clockfile) { goodbye "lock file $clockfile exists"; }
+    if (-e $lockfile) { goodbye "lock file exists"; }
+    if (-e $killfile) { goodbye "process killed with $killfile"; }
+    if ($clean) {
+	vsystem ("cleaning.pl");
+	if (-e $lockfile) { goodbye "lock file exists"; }
+    }
+}
+
+sub by_filename {
+    @value1 = split (" ", $a);
+    @value2 = split (" ", $b);
+    $value1[0] cmp $value2[0]; 
+}
+    
+# we read from in and write to out those files with 1st 0 in the mode column
+sub parse_outlist {
+    $in = $_[0];
+    $out = $_[1];
+    $mode = $_[2];
+    
+# load inlist
+    open (INLIST, $in);
+    @inarray = ();
+    while ($line = <INLIST>) {
+	chop ($line);
+	@inarray = (@inarray,$line);
+    }
+    $Nin = @inarray;
+    close (INLIST);
+    @inarray = sort by_filename @inarray;
+
+    @outarray = ();
+    for ($k = 0; $k < $Nin; $k++) {
+	@pvalues = split (" ", $inarray[$k]);
+	$more = 1;
+	while ($more) {
+	    print STDERR ".";
+	    @nvalues = split (" ", $inarray[$k+1]);
+	    if ($nvalues[0] cmp $pvalues[0]) {
+		$more = 0;
+	    } else {
+		$pvalues[1] |= $nvalues[1];
+		$pvalues[2] |= $nvalues[2];
+		$pvalues[3] |= $nvalues[3];
+		$pvalues[4] |= $nvalues[4];
+		$pvalues[5] |= $nvalues[5];
+		$k ++;
+	    }
+	}
+	# in this version, we only care about pvalues[4,5] (addstar) 
+	if (($mode == 4) && $pvalues[4] && !$pvalues[5]) {
+	    $name = $pvalues[0];
+	    $name =~ s/$dumpspace//;
+	    $name =~ s/://;
+	    @outarray = (@outarray,$name);
+	} 
+	if (($mode == 5) && $pvalues[5]) {
+	    $name = $pvalues[0];
+	    $name =~ s/$dumpspace//;
+	    $name =~ s/://;
+	    @outarray = (@outarray,$name);
+	}
+    }
+    $Nout = @outarray;
+    if ($Nout) {
+	open (OUTLIST, ">$out");
+	for ($k = 0; $k < $Nout; $k++) {
+	    print OUTLIST "$outarray[$k]\n";
+	}
+	close (OUTLIST);
+    }
+    $Nout;
+}
+
+# find lines in inlist which are not in outlist
+sub match_lists {
+    $in = $_[0];
+    $out = $_[1];
+    $new = $_[2];
+    
+# load inlist
+    open (INLIST, $in);
+    @inarray = ();
+    while ($line = <INLIST>) {
+	chop ($line);
+	@inarray = (@inarray,$line);
+    }
+    $Nin = @inarray;
+    close (INLIST);
+
+# load outlist
+    open (OUTLIST, $out);
+    @outarray = ();
+    while ($line = <OUTLIST>) {
+	chop ($line);
+	@outarray = (@outarray,$line);
+    }
+    $Nout = @outarray;
+    close (OUTLIST);
+
+# find matched lines 
+    @newarray = ();
+    for ($k = 0; $k < $Nin; $k++) {
+	$gotit = 0;
+	for ($m = 0; ! $gotit && ($m < $Nout); $m++) {
+	    if ($outarray[$m] =~ /$inarray[$k]/) {
+		$gotit = 1;
+	    }
+	}
+	if (!$gotit) {
+	    @newarray = (@newarray,$inarray[$k]);
+	}
+    }
+    $Nnew = @newarray;
+    if ($Nnew) {
+	open (NEWLIST, ">$new");
+	for ($k = 0; $k < $Nnew; $k++) {
+	    print NEWLIST "$newarray[$k]\n";
+	}
+	close (NEWLIST);
+    }
+    $Nnew;
+}
+
+sub compare_done_todo {
+    print STDERR "starting compare\n";
+# load in done date list
+    open (DONELOG, $addstarfile);
+    @donelist = ();
+    while ($line = <DONELOG>) {
+	chop ($line);
+	@donelist = (@donelist,$line);
+    }
+    $Ndone = @donelist;
+    close (DONELOG);
+
+# load in maestro list
+    open (TODOLOG, $processfile);
+    @todolist = ();
+    while ($line = <TODOLOG>) {
+	chop ($line);
+	@todolist = (@todolist,$line);
+    }
+    $Ntodo = @todolist;
+    close (TODOLOG);
+
+# find entries in MAESTRO that are NOT in DONELOG
+    for ($i = 0; $i < $Ntodo; $i ++) {
+	$gotit = 0;
+	for ($j = 0; ($j < $Ndone) && ! $gotit; $j ++) {
+	    @todo = split (" ",$todolist[$i]);
+	    @done = split (" ",$donelist[$j]);
+	    if ($todo[0] eq $done[0]) {
+		$gotit = 1;
+	    }
+	}
+	if (!$gotit) {
+	    @leftlist = (@leftlist, $todolist[$i]);  
+	}
+    }
+    $Nleft = @leftlist;
+    $Nleft;
+}
Index: /tags/start/Ohana/src/perl/loneos/testlogs.pl
===================================================================
--- /tags/start/Ohana/src/perl/loneos/testlogs.pl	(revision 12606)
+++ /tags/start/Ohana/src/perl/loneos/testlogs.pl	(revision 12606)
@@ -0,0 +1,86 @@
+#!/usr/bin/perl
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    vsystem ("date");
+    die "@_";
+}
+
+$Nline = -1;
+while ($line = <STDIN>) {
+    $Nline ++;
+    if ($Nline == 0) {	next; }
+    if ($Nline == 1) {
+	@parts = split (" ",$line);
+	$N1 = $parts[9];
+	next;
+    }
+    if ($Nline == 2) {
+	@parts = split (" ",$line);
+	$N2 = $parts[2];
+	if ($N1 != $N2) {
+	    print STDERR "problem in dophot\n";
+	    exit;
+	}
+	next;
+    }
+    if ($Nline == 3) {
+	@parts = split (" ",$line);
+	$N1 = $parts[10];
+	next;
+    }
+    if ($Nline == 4) {
+	@parts = split (" ",$line);
+	$N2 = $parts[2];
+        if ($N1 != $N2) {
+            print STDERR "problem in fstat\n";
+	    exit;
+        }
+	next;
+    }
+    if ($Nline == 5) {
+	@parts = split (" ",$line);
+	$N1 = $parts[8];
+	next;
+    }
+    if ($Nline == 6) {
+	@parts = split (" ",$line);
+	$N2 = $parts[2];
+        if ($N1 != $N2) {
+            print STDERR "problem in gastro\n";
+            exit;
+        }
+	next;
+    }
+    if ($Nline == 7) {
+	@parts = split (" ",$line);
+	$N1 = $parts[6];
+	next;
+    }
+    if ($Nline == 8) {
+	@parts = split (" ",$line);
+	$N2 = $parts[2];
+        if ($N1 != $N2) {
+            print STDERR "problem in addstar\n";
+            exit;
+        }
+	next;
+    }
+    if ($Nline > 8) {
+	print STDERR "$line\n";
+	print STDERR "too many lines?\n";
+	exit;
+    }
+
+}
+
+if ($Nline != 8) {
+    print STDERR "not enough lines\n";
+    exit;
+}
Index: /tags/start/Ohana/src/perl/new/defringe
===================================================================
--- /tags/start/Ohana/src/perl/new/defringe	(revision 12606)
+++ /tags/start/Ohana/src/perl/new/defringe	(revision 12606)
@@ -0,0 +1,65 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 2) { &usage; }
+
+# command line arguments
+$inlist  = $ARGV[0];
+$outlist = $ARGV[1];
+
+# setup elixir references
+$coordpath = `gconfig FRINGE_COORD_PATH`;  chop $coordpath;
+$confdir   = `gconfig CONFDIR`;            chop $confdir;
+$script    = "$confdir/mana/fringe.pro";   
+
+$filtkwd   = `gconfig FILTER-KEYWORD`;     chop $filtkwd;
+$camerakwd = `gconfig CAMERA-KEYWORD`;     chop $camerakwd;
+$ccdkwd    = `gconfig CCDNUM-KEYWORD`;     chop $ccdkwd;
+
+$Nccd      = `cameraconfig -Nccd`;         chop $Nccd;
+$answer    = `cameraconfig -ccds`;
+@ccds      = split (" ", $answer);
+
+# temporary files needed:
+set imstats=`mktemp /tmp/defringe.XXXXXX`;
+set frstats=`mktemp /tmp/defringe.XXXXXX`;
+
+# calculate imstats for the input image, get stats from fringe image header
+set filtvalue = `head -1 $imlist | fields $filtkwd | awk '{print $2}'`;
+set filter = `filtnames $filtvalue`;
+
+set camera = `head -1 $imlist | fields $camerakwd | awk '{print $2}'`;
+if ("$camera" == "") set camera = "WFI";
+
+# load input / output lists:
+open (FILE, "$inlist");
+@inlist = <FILE>;
+close (FILE);
+
+open (FILE, "$outlist");
+@outlist = <FILE>;
+close (FILE);
+
+if (@inlist != @outlist) { die "ERROR: mismatched lists\n"; }
+ 
+# measure fringe amplitude
+
+
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print STDERR "USAGE: defringe (inlist) (outlist)\n";
+    exit 2;
+}
+
+sub uppercase {
+    return "\U$_[0]\E";
+}
Index: /tags/start/Ohana/src/perl/new/getfringe
===================================================================
--- /tags/start/Ohana/src/perl/new/getfringe	(revision 12606)
+++ /tags/start/Ohana/src/perl/new/getfringe	(revision 12606)
@@ -0,0 +1,80 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 4) { die "USAGE: gtfringe (in.fits) (fringe.coords) (binning) (out.dat)\n"; }
+
+$input   = $ARGV[0];
+$coords  = $ARGV[1];
+$binning = $ARGV[2];
+$output  = $ARGV[3];
+
+# create temporary files:
+$PARFILE = `mktemp /tmp/gtfringe.XXXXXX`;
+$INFILE  = `mktemp /tmp/@gtfringe.XXXXXX`
+$OUTFILE = `mktemp /tmp/gtfringe.XXXXXX`
+
+# convert 
+
+open (FILE, "$inlist");
+@mef = <FILE>;
+close (FILE);
+
+@split = ();
+foreach $name (@mef) {
+    chop ($name);
+
+    # convert name /path/name.fits to /outdir/rootNN.fits
+    @words = split ("/", $name);
+    $root = $words[-1];
+    $root =~ s/.fits//;
+    
+    $new = sprintf "%s/%s%02d.fits", $outdir, $root, $ccd;
+    push @split, $new;
+}
+    
+open (MANA, "|mana --norc");
+
+# define the macro 'split'
+print MANA "macro split\n";
+print MANA " rd a \$1 -n $ccd\n";
+print MANA " keyword a NAXIS1 nx\n";
+print MANA " keyword a NAXIS2 ny\n";
+print MANA " if ((\$nx == 2080) && (\$ny == 4128))\n";
+print MANA "   wd a \$2 -bitpix 16 -bzero 32768 -bscale 1.0\n";
+print MANA "   exec echo \$2 >> $outlist\n";
+print MANA " end\n";
+print MANA "end\n";
+
+# create the macro 'go' with the commands 
+print MANA "macro go\n";
+for ($i = 0; $i < @mef; $i++) {
+    if (-e $split[$i]) { 
+	print STDERR "$split[$i] exists, skipping\n";
+	next; 
+    }
+    print MANA " split $mef[$i] $split[$i]\n";
+}
+# if the macro ends successfully, exit 0
+print MANA " exit 0\n";
+print MANA "end\n";
+
+# if the macro exits before the end, exit 1
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+
+$status = $?;
+print STDERR "mana exit status: $status\n";
+if ($status) {
+    print STDERR "ERROR: problem running split.mef\n";
+    exit 1;
+}
+
+print STDERR "SUCCESS\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
Index: /tags/start/Ohana/src/perl/old/clear.rawdir
===================================================================
--- /tags/start/Ohana/src/perl/old/clear.rawdir	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/clear.rawdir	(revision 12606)
@@ -0,0 +1,258 @@
+#!/usr/bin/env perl
+
+# this script is very much specific to the CFHT data layout
+
+$archive = "/h/archive/current/instrument/cfh12k";
+$force = 0;
+
+# grab the command line arguments:
+@tARGV = ();
+for (; @ARGV > 0; ) {
+
+    if ($ARGV[0] eq "-force") {
+	shift;
+	$force = 1;
+	next;
+    }
+    
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 1) { die "USAGE: clean.rawdir (crunid)\n" ;}
+
+if ($ARGV[0] eq "-current") {
+    $runid = `gconfig -q RUNID`; chop ($runid);
+} else {
+    $runid = $ARGV[0];
+}
+print "runid: $runid\n";
+
+$rawdir = `gconfig -q -D RUNID $runid RAWDIR`; chop ($rawdir);
+if ($rawdir eq "") {
+    print STDERR "can't find config entry RAWDIR\n";
+    exit 1;
+}
+print "rawdir: $rawdir\n";
+
+@meflist = ();
+@splitlist = ();
+
+# load in the MEF files (must be of format 123456x.fits)
+@tlist = <$rawdir/*.fits>;
+foreach $tname (@tlist) { 
+    if ((-f $tname) && ($tname =~ /\d\d\d\d\d\d\w.fits$/)) { 
+	@meflist = (@meflist, $tname); 
+    } 
+}
+
+# load in the SPLIT directories (must be of format 123456x)
+@tlist = <$rawdir/???????>;
+foreach $tname (@tlist) { 
+    if ((-d $tname) && ($tname =~ /\d\d\d\d\d\d\w$/)) { 
+	@splitlist = (@splitlist, $tname); 
+    } 
+}
+$N1 = @meflist;
+$N2 = @splitlist;
+
+foreach $file (@meflist) {
+
+    # grab the root name:
+    $root = mefnames ($file, "root");
+    
+    $arname = "$archive/$root.fits";
+    $newname = $file;
+
+    # check that the file exists in the archive
+    if (-l $file) { next; }
+    if (! -e $arname) { next; }
+    if (! -f $arname) { next; }
+
+    unlink $file;
+    symlink $arname, $newname;
+}
+
+foreach $file (@splitlist) {
+
+    # grab the root name:
+    $root = splitnames ($file, "root");
+    
+    $arname = "$archive/$root.fits";
+    $newname = "$rawdir/$root.fits";
+
+    # check that the file exists in the archive
+    if (! -e $arname) { next; }
+    if (! -f $arname) { next; }
+
+    vsystem ("rm -rf $file\n");
+    symlink $arname, $newname;
+    vsystem ("imsearch -name $root -split2mef\n");
+}
+
+exit 0;
+
+# utilities ##############################################
+
+sub gt_names {
+    # in: filename mode type
+    # out: word
+
+    my ($value);
+
+    $value = "";
+    if ($_[2] eq "MEF")   { $value = mefnames ($_[0], $_[1]); }
+    if ($_[2] eq "SPLIT") { $value = splitnames ($_[0], $_[1]); }
+    
+    return $value;
+}
+
+sub mefnames {
+    # in: (/path/file.fits) (mode) 
+    # out: word
+
+    my($fullname) = $_[0];
+    my($mode) = $_[1];
+    my($answer);
+
+    # split rootdir and filename:
+    my (@words) = split ("/", $fullname);
+    $N = @words;
+
+    if ($mode eq "path") {
+	$answer = "";
+	for ($i = 0; $i < $N - 1; $i++) {
+	    $answer = $answer . $words[$i] . "/";
+	}
+	chop ($answer); # strip off last /
+	if ($answer eq "") { $answer = "."; }
+	return ($answer);
+    }
+    
+    if ($mode eq "root") {
+	$answer = "$words[$N-1]";
+	$answer =~ s/.fits$//;
+	return ($answer);
+    }
+    
+    if ($mode eq "Nccd") {
+	if (! -e $fullname) {
+	    return (0);
+	}
+	$answer = `echo $fullname | fields NEXTEND`;
+	@words = split (" ", $answer);
+	if ($words[1] eq "") {
+	    return (0);
+	}
+	return ($words[1]);
+    }
+    
+    return (0);
+}
+
+sub splitnames {
+    # in: (/path/file) (mode) 
+    # out: word
+    # /path/file is directory containing Nccd fits images
+
+    my($fullname) = $_[0];
+    my($mode) = $_[1];
+    my($answer, $N, $tmpname, @imlist, @words);
+
+    # split rootdir and filename:
+    @words = split ("/", $fullname);
+    $N = @words;
+
+    if ($mode eq "path") {
+	$answer = "";
+	for ($i = 0; $i < $N - 1; $i++) {
+	    $answer = $answer . $words[$i] . "/";
+	}
+	chop ($answer); # strip off last /
+	if ($answer eq "") { $answer = "."; }
+	return ($answer);
+    }
+    
+    if ($mode eq "root") {
+	$answer = "$words[$N-1]";
+	return ($answer);
+    }
+    
+    if ($mode eq "Nccd") {
+	
+	$tmpname = "$fullname/$words[$N-1]";
+	@imlist = <$tmpname??.fits>;
+
+	$Nccd = @imlist;
+	return $Nccd;
+    }
+    
+    return (0);
+}
+
+sub ckimtype {
+    # in: (/path/file)
+    # out: MEF | SPLIT | SINGLE | (NULL)
+    
+    my ($answer, $name, $value);
+    my ($file) = $_[0];
+
+    if (! -e $file) { 
+	print STDOUT "can't open file\n";
+	return ""; 
+    }
+
+    # if /path/file is a directory, it is split:
+    if (-d $file) { return "SPLIT"; }
+
+    # check that the file is a FITS image
+    $answer = `file -L $file`;
+    if ($?) { 
+	print STDOUT "can't open file\n";
+	return ""; 
+    }
+    ($name, $value) = split (" ", $answer);
+    if ($value ne "FITS") { 
+	print STDOUT "not a valid image\n";
+	return ""; 
+    }
+    
+    # check for NAXIS = 0 (MEF) 
+    $answer = `echo $file | fields NAXIS`;
+    # if ($?) { return ""; }
+    ($name, $value) = split (" ", $answer);
+    if ($value eq 0) { return "MEF"; }
+    
+    if ($value == 2) { return "SINGLE"; }
+
+    print STDOUT "not a valid image\n";
+    return "";
+}
+
+sub vsystem {
+    # print STDERR "@_\n";
+    my($status) = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+
+# This program calls several other perl scripts to get information 
+# about the image.  
+# ckrunid   - determine the appropriate Camera Run ID for this image
+# ckastrom  - check for the appropriate astrometry information
+# ckdetrend - check for the appropriate detrend images
+# ckphotom  - check for the appropriate photometry data
+
+# at the moment, there are different calling conventions for each of
+# these functions.  Some take a single name (MEF / SPLIT), some take a
+# reference to the specific CCD (filename CCD MODE).  
+
+# none of the called functions need to find the number of CCDs
+# ckvalid determines the number of CCDs from the header (MEF) or the
+# number of appropriately named FITS files in the directory (SPLIT).
+
Index: /tags/start/Ohana/src/perl/old/create.imlists
===================================================================
--- /tags/start/Ohana/src/perl/old/create.imlists	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/create.imlists	(revision 12606)
@@ -0,0 +1,67 @@
+#!/usr/bin/env perl
+
+# take single list of images, create collection of lists in path, each with files for one image,
+# place list of lists in outlist
+
+if (@ARGV != 3) { die "ERROR: USAGE: create.subset (inlist) (path) (outlist)\n" }
+
+$inlist = $ARGV[0];
+$path = $ARGV[1];
+$outlist = $ARGV[2];
+
+open (FILE, $inlist);
+@inlist = <FILE>;
+close (FILE);
+foreach $name (@inlist) { chop ($name); }
+
+open (OUT, ">$outlist");
+
+while (@inlist) {
+    $name = pop (@inlist); 
+
+    @sublist = ($name);
+    ($subname, $ext) = $name =~ /(\S+)(\d\d\D+)/;
+    ($filename) = $subname =~ /(\d\d\d\d\d\d.)$/;
+    print STDERR "subname: $subname\n";
+    print STDERR "filename: $filename\n";
+    print STDERR "ext: $ext\n";
+    
+    @outlist = ();
+    while (@inlist) {
+	$name = pop (@inlist);
+	
+	if ($name =~ /$subname/) {
+	    push (@sublist, $name);
+	} else {
+	    push (@outlist, $name);
+	}
+    }
+    
+    @sublist = sort @sublist;
+
+    # file lists have names like /path/filename.imlist
+    open (FILE, ">$path/$filename.imlist");
+    foreach $name (@sublist) {
+	print FILE "$name\n";
+    }
+    close (FILE);
+
+    print OUT "$path/$filename.imlist\n";
+
+    @inlist = @outlist;
+}
+
+close (OUT);
+
+###########################################################################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
Index: /tags/start/Ohana/src/perl/old/elixir.grabd
===================================================================
--- /tags/start/Ohana/src/perl/old/elixir.grabd	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/elixir.grabd	(revision 12606)
@@ -0,0 +1,159 @@
+#!/usr/bin/env perl
+
+# this daemon creates links for new images in the elixir TMPDIR tree
+# and registers the images in the elixir database, and sends the image 
+# to imstats for processing.
+
+# the standard elixir config system is used to id the TMPDIR and the 
+# appropriate imstats.fifo, etc.
+
+# TMPDIR should be checked on each scan loop, in case the TMPDIR or
+# RUNID is switched
+
+# make sure the appropriate config file is used.
+
+use English;
+
+# check usage
+if (@ARGV != 0) { die "USAGE: elixir.grabd\n"; }
+
+# what do we do about config file?  demand account be set up correctly?
+$fifos = `gconfig FIFOS`; chop ($fifos);
+if ($?) { die "error in config system\n"; }
+
+# check for existing process and exit
+$pidfile = "$fifos/gradb.pid";
+if (-e $pidfile) {
+    $line = `head -1 $pidfile`;
+    ($ohost, $ouser, $opid) = split (" ", $line);
+
+    print STDERR "elixir.grabd is already being run:\n";
+    print STDERR " machine: $ohost\n";
+    print STDERR " user:    $ouser\n";
+    print STDERR " pid:     $opid\n";
+    print STDERR " pidfile: $pidfile\n";
+    exit 1;
+}
+
+# set process lock file:
+$host = `hostname`; chop ($host);
+$user = getlogin;
+open (FILE, ">$pidfile");
+print FILE "$host $user $PID\n";
+close (FILE);
+
+# place this in the config system?
+$srcdir = "/data/kapu/elixir/cfh12k";
+while (-e $pidfile) {
+    grabfiles ();
+    system ("sleep 60");
+}
+
+# clear process lock file:
+unlink ($pidfile);
+exit 0;
+
+
+##########################################################
+
+sub grabfiles () {
+    
+    $rawdir = `gconfig -q RAWDIR`;  chop $rawdir;
+
+    @files = glob ("$srcdir/*");
+    
+    if (! @files) {
+	system ("sleep 60");
+	return;
+    }
+
+    foreach $name (@files) {
+	if (! -l $name) { next; }
+	
+	# find real path
+	$path = convertlink ($name);
+	$file = filename ($path);
+
+	# set new path (skip if it exists)
+	$new = sprintf "%s/%s", $rawdir, $file;
+	if (-e $new) { 
+	    print STDERR "skipping file\n";
+	    next; 
+	}
+	
+	# print "$name -> $path ($file) -> $new\n";
+
+	# link file to rawdir:
+	symlink ($path, $new);
+	
+	# these files always come in as MEF
+	vsystem ("imsort $new");
+	if ($?) { next; }
+	
+	unlink $name
+    }
+}
+
+
+# utilities ##############################################
+sub vsystem {
+    print STDERR "@_\n";
+    my ($status) = system ("@_");
+    $status;
+}
+
+sub filename { 
+
+    my ($path) = $_[0];
+    my (@tmp);
+    
+    @tmp = split ("/", $path);
+    return $tmp[-1];
+}
+
+sub convertlink {
+    my ($link) = $_[0];
+    my ($file);
+
+    while (-l $link) {
+	$file  = readlink ($link);
+	$path1 = path ($link);
+	$path2 = path ($file);
+	
+	unless ($path2 =~ m|^/|) {
+	    $file = "$path1/$file";
+	}	
+	$link = $file;
+    }
+    return ($link);
+}    
+
+sub usage {
+    
+    if (@ARGV == 1) {
+	print STDERR "\n --- user modes ---\n";
+	print STDERR "create (run) (start) (stop)\n";
+	print STDERR "addqso (runid) (qsoid)\n";
+	print STDERR "delqso (qsoid)\n";
+	print STDERR "sched (runid)\n";
+	print STDERR "status\n";
+	&goodbye;
+    }
+    
+    if (@ARGV > 2) { print STDERR "USAGE: prepare.run (help) [mode]\n"; &goodbye; }
+    
+    &goodbye;
+}
+
+sub path {
+
+    my ($file) = $_[0];
+
+    @words = split ("/", $file);
+
+    pop (@words);
+    
+    $path = join ("/", @words);
+
+    return ($path);
+}
Index: /tags/start/Ohana/src/perl/old/fixlists
===================================================================
--- /tags/start/Ohana/src/perl/old/fixlists	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/fixlists	(revision 12606)
@@ -0,0 +1,43 @@
+#!/usr/bin/env perl
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+if (@ARGV != 3) { die "ERROR: USAGE: fixlists (in) (keep) (out)\n" }
+
+open (FILE, $ARGV[1]);
+@keep = ();
+while ($line = <FILE>) {
+    chop ($line);
+    @keep = (@keep, $line);
+}
+close (FILE);
+
+open (IN, $ARGV[0]);
+open (OUT, ">$ARGV[2]");
+
+for ($j = 0; $line = <IN>; $j++) {
+    chop ($line);
+    $found = 0;
+    for ($i = 0; !$found && ($i < @keep); $i++) {
+	if ($keep[$i] == $j) {
+	    $found = 1;
+	}
+    }
+    if ($found) {
+	print OUT "$line\n";
+    }
+}
+close (IN);
+close (OUT);
+
+print STDERR "SUCCESS\n";
+
+# put the logic for selecting images in this file
Index: /tags/start/Ohana/src/perl/old/fl.split2mef
===================================================================
--- /tags/start/Ohana/src/perl/old/fl.split2mef	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/fl.split2mef	(revision 12606)
@@ -0,0 +1,98 @@
+#!/usr/bin/env perl
+
+# check the usage
+if (@ARGV != 2) { die "USAGE: fl.split2mef (file.master) (splitdir)\n" }
+
+# assign the command line arguments
+$master = $ARGV[0];
+$splitdir = $ARGV[1];
+
+open (FILE, "$master");
+@master = <FILE>;
+close (FILE);
+
+# master contains lines from both split and mef.  
+# convert all to split format, and write to root.mef
+# empty the split file, re-write the master file with new names.
+# when the new mef list is run through split.mef, only un-split entries 
+# will get split
+
+# /data/koa/cfh12k/01Ak05/587554f/587554f04.fits
+# /data/elixir2/cfh12k/detrend/01Ak04/split/582967f00.fits 1
+
+foreach $line (@master) {
+    
+    ($name, $mode) = split (" ", $line);
+
+    # test filename:
+    unless ($name =~ m|/\d\d\d\d\d\d\w\d\d.fits\Z|) {
+	print STDERR "Error with $name: not in split-name format\n";
+	next;
+    }
+
+    ($path, $root1, $root2, $ccd) = $name =~ m|(\S+)/(\d\d\d\d\d\d\w)/(\d\d\d\d\d\d\w)(\d\d).fits\Z|;
+    
+    # test for originally SPLIT image:
+    if ($root1 eq $root2) {
+	# check for existence of mef version file:
+	$new = sprintf "%s/%s.fits", $path, $root1;
+	if (! -e $new)  {
+	    print STDERR "Error, file $new is missing\n";
+	    exit 1;
+	}
+	@newmef = (@newmef, $new);
+
+	# create split version name:
+	$new = sprintf "%s/%s%02d.fits", $splitdir, $root1, $ccd;
+	@split = (@split, $new);
+	@splitmode = (@splitmode, $mode);
+	next;
+    }
+
+    # test for previously MEF -> SPLIT images: 
+    if ($root1 eq "split") {
+	@mef = (@mef, $name);
+	@mefmode = (@mefmode, $mode);
+	next; 
+    }
+    
+    print STDERR "Error with $name - neither split nor mef\n";
+}
+
+# empty *.split file
+$splitname = $master;
+$splitname =~ s/master\Z/split/;
+open (FILE, ">$splitname");
+close (FILE);
+
+# create *.mef file with new mefs (to be split)
+$mefname = $master;
+$mefname =~ s/master\Z/mef/;
+print STDERR "mefname: $mefname\n";
+open (FILE, ">$mefname");
+foreach $name (@newmef) {
+    print FILE "$name\n";
+}
+close (FILE);
+
+# save *.master file
+vsystem ("cp $master $master~");
+
+# re-create *.master file
+open (FILE, ">$master");
+@all = (@mef, @split);
+@allmode = (@mefmode, @splitmode);
+for ($i = 0; $i < @all; $i++) {
+    print FILE "$all[$i] $allmode[$i]\n";
+}
+close (FILE);
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
Index: /tags/start/Ohana/src/perl/old/fr.detrend
===================================================================
--- /tags/start/Ohana/src/perl/old/fr.detrend	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/fr.detrend	(revision 12606)
@@ -0,0 +1,102 @@
+#!/usr/bin/env perl
+# calls flatten.flips, but no direct flips functions
+
+# check the usage
+if ($ARGV[0] eq "-h") { usage (); }
+if ($ARGV[0] eq "-help") { usage (); }
+if (@ARGV != 4) { die "USAGE: fr.detrend (path) (root) (mode) (outdir)\n" }
+
+# assign the command line arguments
+$path = $ARGV[0];
+$root = $ARGV[1];
+$mode = "\U$ARGV[2]\E";
+if (($mode ne "MEF") && ($mode ne "SPLIT")) { die "ERROR: mode must be either -split or -mef\n";}
+$outdir = $ARGV[3];
+if (! -d $outdir) { vsystem ("mkdir -p $outdir"); }
+
+# get info on input image
+$basename = mk_basename ($path, $root, $mode);
+$Nccd = `cameraconfig -Nccd`; chop ($Nccd);
+
+for ($ccd = 0; $ccd < $Nccd; $ccd++) {
+    
+    $infile  = mk_filename ($path, $root, $mode, $ccd);
+    $outfile = mk_filename2 ($outdir, $root, "SPLIT", $ccd);
+
+    $status = vsystem ("flatten.flips -quiet $infile $outfile $ccd $mode");
+    if ($status) { die "ERROR: problem running flatten on $infile\n"; }
+
+}
+
+print STDOUT "SUCCESS: finished with fr.detrend\n";
+exit 0;
+
+sub mk_basename {
+    my ($path) = $_[0];
+    my ($root) = $_[1];
+    my ($mode) = $_[2];
+
+    if ($mode eq "MEF") {
+	$name = sprintf "%s/%s.fits", $path, $root;
+	return $name;
+    }
+    if ($mode eq "SPLIT") {
+	$name = sprintf "%s/%s", $path, $root;
+	return $name;
+    }
+    return "";
+}
+
+sub mk_filename {
+    my ($path) = $_[0];
+    my ($root) = $_[1];
+    my ($mode) = $_[2];
+    my ($ccd)  = $_[3];
+
+    if ($mode eq "MEF") {
+	$name = sprintf "%s/%s.fits", $path, $root;
+	return $name;
+    }
+    if ($mode eq "SPLIT") {
+	$name = sprintf "%s/%s/%s%02d.fits", $path, $root, $root, $ccd;
+	return $name;
+    }
+    return "";
+}
+
+sub mk_filename2 {
+    my ($path) = $_[0];
+    my ($root) = $_[1];
+    my ($mode) = $_[2];
+    my ($ccd)  = $_[3];
+
+    if ($mode eq "MEF") {
+	$name = sprintf "%s/%s.fits", $path, $root;
+	return $name;
+    }
+    if ($mode eq "SPLIT") {
+	$name = sprintf "%s/%s%02d.fits", $path, $root, $ccd;
+	return $name;
+    }
+    return "";
+}
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "\n";
+    print "USAGE: fr.detrend (path) (root) (mode) (outdir)\n";
+    print " path:   path to MEF image or SPLIT dir\n";
+    print " root:   root name of image (MEF = root.fits, SPLIT = root/rootNN.fits)\n";
+    print " mode:   MEF or SPLIT\n";
+    print " outdir: directory for output results (all split)\n";
+    exit 1;
+}
Index: /tags/start/Ohana/src/perl/old/fr.gtstats
===================================================================
--- /tags/start/Ohana/src/perl/old/fr.gtstats	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/fr.gtstats	(revision 12606)
@@ -0,0 +1,75 @@
+#!/usr/bin/env perl
+
+# check the usage
+if ($ARGV[0] eq "-h") { usage (); }
+if ($ARGV[0] eq "-help") { usage (); }
+if (@ARGV != 3) { die "USAGE: fr.gtstats (inlist) (binning) (output)\n" }
+
+# define the path to include FLIPS:
+$flipsconf=`gconfig -q FLIPSCONF`; chop ($flipsconf);
+$flipspath=`gconfig -q FLIPSPATH`; chop ($flipspath);
+$ENV{'PATH'} = "$ENV{'PATH'}:$flipspath";
+$ENV{'FLIPSDIR'} = $flipsconf;
+
+# assign the command line arguments
+$inlist = $ARGV[0];
+$bin    = $ARGV[1];
+$output = $ARGV[2];
+
+# load input list:
+open (FILE, "$inlist");
+@inlist = <FILE>;
+close (FILE);
+
+# gtfringe is appending to the output file:
+unlink ($output);
+
+# we construct the Fringe Coord File from: FRINGE_COORD_PATH/CAMERA-FILTER-CCDNN-FringeCoord.reg
+$fkey      = `gconfig -q FILTER-KEYWORD`;    chop ($fkey);
+$ckey      = `gconfig -q CAMERA-KEYWORD`;    chop ($ckey);
+$coordpath = `gconfig -q FRINGE_COORD_PATH`; chop ($coordpath);
+$Nccd      = `cameraconfig -Nccd`;           chop ($Nccd);
+
+# double check lists size:
+if ($Nccd != @inlist) { die "ERROR: mis-matched image list sizes\n"; }
+
+# find filter and camera from image
+$answer = `echo $inlist[0] | fields $fkey $ckey`;
+($name, $filter, $camera) = split (" ", $answer);
+
+for ($ccd = 0; $ccd < $Nccd; $ccd++) {
+    
+    $infile    = $inlist[$ccd];
+    $coordfile = sprintf "%s/%s-%s-CCD%02d-FringeCoord.reg", $coordpath, $camera, $filter, $ccd;
+
+    # each call to gtfringe adds a line to $output 
+    vsystem ("gtfringe $infile $coordfile $bin $output");
+    if ($?) {
+	print STDERR "ERROR running gtfringe\n";
+	exit 1;
+    }
+}
+
+print STDOUT "SUCCESS: finished with fr.gtstats\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "\n";
+    print "USAGE: fr.gtstats (path) (root) (binning) (output)\n";
+    print " calculate fringe pattern strengths for images in (path)\n";
+    print " path:    path to MEF image or SPLIT dir\n";
+    print " root:    root name of image (MEF: root.fits, SPLIT: root/rootNN.fits)\n";
+    print " binning: binning factor of images\n";
+    print " outdir:  output file\n";
+    exit 1;
+}
Index: /tags/start/Ohana/src/perl/old/fr.medbin
===================================================================
--- /tags/start/Ohana/src/perl/old/fr.medbin	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/fr.medbin	(revision 12606)
@@ -0,0 +1,71 @@
+#!/usr/bin/env perl
+
+# check the usage
+if ($ARGV[0] eq "-h") { usage (); }
+if ($ARGV[0] eq "-help") { usage (); }
+if (@ARGV != 4) { die "USAGE: fr.medbin (path) (root) (factor) (outpath)\n" }
+
+# assign the command line arguments
+$path = $ARGV[0];
+$root = $ARGV[1];
+$factor = $ARGV[2];
+$outpath = $ARGV[3];
+
+$Nccd = `cameraconfig -Nccd`; chop ($Nccd);
+
+# need some extra here: make the hierarchy needed, check exit status
+if (! -d $outpath) { vsystem ("mkdir -p $outpath"); }
+
+open (MANA, "|mana --norc");
+
+print MANA "macro mkmap\n";
+print MANA " rd a \$1\n";
+print MANA " keyword a NAXIS1 nx\n";
+print MANA " keyword a NAXIS2 ny\n";
+print MANA " medianmap a b {\$nx/$factor} {\$ny/$factor} -range 0.25 0.75\n";
+print MANA " wd b \$2\n";
+print MANA "end\n";
+
+print MANA "macro go\n";
+for ($ccd = 0; $ccd < $Nccd; $ccd++) {
+    $infile = sprintf "%s/%s%02d.fits", $path, $root, $ccd;
+    $outfile  = sprintf "%s/%s%02d.fits", $outpath, $root, $ccd;
+    print MANA " mkmap $infile $outfile\n";
+}
+print MANA " exit 0\n";
+print MANA "end\n";
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+if ($?) {
+    print STDERR "ERROR running mana\n";
+    exit 1;
+}
+
+print STDOUT "SUCCESS: finished with fr.detrend\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "\n";
+    print "USAGE: fr.medbin (path) (root) (factor) (outpath)\n";
+    print " path:   path to MEF image or SPLIT dir\n";
+    print " root:   root name of image (MEF = root.fits, SPLIT = root/rootNN.fits)\n";
+    print " mode:   MEF or SPLIT\n";
+    print " outdir: directory for output results (all split)\n";
+    exit 1;
+}
+
+# mana within perl:  we embed the mana functions within a macro to trap the 
+# exit status.  If mana has an error with one of the steps, it will exit the macros and 
+# the second exit will be called. Otherwise, the "go" macro will perform the exit 0
+# and mana will exit with status 0
Index: /tags/start/Ohana/src/perl/old/fr.stats
===================================================================
--- /tags/start/Ohana/src/perl/old/fr.stats	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/fr.stats	(revision 12606)
@@ -0,0 +1,69 @@
+#!/usr/bin/env perl
+
+# check the usage
+if ($ARGV[0] eq "-h") { &usage (); }
+if ($ARGV[0] eq "-help") { &usage (); }
+if (@ARGV != 5) { &usage (); }
+
+# assign the command line arguments
+$list   = $ARGV[0];
+$tenbin = $ARGV[1];
+$medbin = $ARGV[2];
+$stats  = $ARGV[3];
+$range  = $ARGV[4];
+
+# check for files to be processed
+@status = stat ($list);
+if ($status[7] == 0) {
+    print STDERR "no files in source list, skipping\n";
+    exit 1;
+}
+
+# find the appropriate script file
+$confdir = `gconfig -q CONFDIR`; chop ($confdir);
+$script  = "$confdir/mana/fringe.pro";
+
+# test named Xserver, or start vnc on specified machine
+$xhost=`gconfig -q XHOST`; chop ($xhost);
+$xdisp=`gconfig -q XDISP`; chop ($xdisp);
+if (vsystem ("xdpyinfo -display $xdisp")) {
+    print STDERR "X server is not running. start it now on $xhost\n";
+    exit 1;
+}
+$ENV{'DISPLAY'} = $xdisp;
+
+# run mana script:
+open (MANA, "|mana --norc");
+print MANA "input $script\n";
+print MANA "\$RANGE = $range\n";
+print MANA "fringelist $list $tenbin $medbin $stats\n";
+print MANA "exit 1\n";
+close (MANA);
+
+if ($?) {
+    print STDERR "ERROR problem with fr.stats\n";
+    exit 1;
+}
+
+print STDOUT "SUCCESS: finished with fr.stats\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "USAGE: fr.stats (list) (tenbin) (medbin) (stats) (range)\n";
+    exit 1;
+}
+
+# mana within perl:  we embed the mana functions within a macro to trap the 
+# exit status.  If mana has an error with one of the steps, it will exit the macros and 
+# the second exit will be called. Otherwise, the "go" macro will perform the exit 0
+# and mana will exit with status 0
Index: /tags/start/Ohana/src/perl/old/fr.subset
===================================================================
--- /tags/start/Ohana/src/perl/old/fr.subset	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/fr.subset	(revision 12606)
@@ -0,0 +1,232 @@
+#!/usr/bin/env perl
+
+# check the usage
+if ($ARGV[0] eq "-h") { usage (); }
+if ($ARGV[0] eq "-help") { usage (); }
+if (@ARGV != 3) { die "ERROR: USAGE: fr.subset (master) (outdir) (subset)\n" }
+
+$inlist = $ARGV[0];
+$outdir = $ARGV[1];
+$outlist= $ARGV[2];
+
+print STDERR "ERROR: not fixed!!!\n";
+exit 1;
+
+# load in stats lines
+open (FILE,  "$ARGV[0]");
+@list = <FILE>;
+close (FILE);
+
+open (FILE, ">$outlist");
+
+foreach $line (@list) {
+    chop ($line);
+
+    # the infile contains (path) (root) (mode) (flag)
+    ($path, $root, $mode, $stat) = split (" ", $line);
+
+    if ($stat) {
+
+	$basename = mk_basename ($path, $root, $mode);
+	$Nccd = gt_names ($basename, "Nccd", $mode);
+
+	for ($ccd = 0; $ccd < $Nccd; $ccd++) {
+
+	    $outfile = mk_filename ($outdir, $root, "SPLIT", $ccd);
+
+	    print FILE "$outfile\n";
+
+	}
+   }      
+}    
+close (FILE);
+
+print STDERR "SUCCESS\n";
+
+exit 0;
+
+######## cfht MEF/SPLIT name utilities ###########
+
+sub gt_names {
+    # in: filename mode type
+    # out: word
+
+    my ($value);
+
+    $value = "";
+    if ($_[2] eq "MEF")   { $value = mefnames ($_[0], $_[1]); }
+    if ($_[2] eq "SPLIT") { $value = splitnames ($_[0], $_[1]); }
+    
+    return $value;
+}
+
+sub mefnames {
+    # in: (/path/file.fits) (mode) 
+    # out: word
+
+    my($fullname) = $_[0];
+    my($mode) = $_[1];
+    my($answer);
+
+    # split rootdir and filename:
+    my (@words) = split ("/", $fullname);
+    $N = @words;
+
+    if ($mode eq "path") {
+	$answer = "";
+	for ($i = 0; $i < $N - 1; $i++) {
+	    $answer = $answer . $words[$i] . "/";
+	}
+	chop ($answer); # strip off last /
+	if ($answer eq "") { $answer = "."; }
+	return ($answer);
+    }
+    
+    if ($mode eq "root") {
+	$answer = "$words[$N-1]";
+	$answer =~ s/.fits$//;
+	return ($answer);
+    }
+    
+    if ($mode eq "Nccd") {
+	if (! -e $fullname) { return 0; }
+	$answer = `echo $fullname | fields NEXTEND`;
+	@words = split (" ", $answer);
+	if ($words[1] eq "") { return 0; }
+	return ($words[1]);
+    }
+    
+    return (0);
+}
+
+sub splitnames {
+    # in: (/path/file) (mode) 
+    # out: word
+    # /path/file is directory containing Nccd fits images
+
+    my($fullname) = $_[0];
+    my($mode) = $_[1];
+    my($answer, $N, $tmpname, @imlist, @words);
+
+    # split rootdir and filename:
+    @words = split ("/", $fullname);
+    $N = @words;
+
+    if ($mode eq "path") {
+	$answer = "";
+	for ($i = 0; $i < $N - 1; $i++) {
+	    $answer = $answer . $words[$i] . "/";
+	}
+	chop ($answer); # strip off last /
+	if ($answer eq "") { $answer = "."; }
+	return ($answer);
+    }
+    
+    if ($mode eq "root") {
+	$answer = "$words[$N-1]";
+	return ($answer);
+    }
+    
+    if ($mode eq "Nccd") {
+	
+	$tmpname = "$fullname/$words[$N-1]";
+	@imlist = <$tmpname??.fits>;
+
+	$Nccd = @imlist;
+	return $Nccd;
+    }
+    
+    return (0);
+}
+
+sub ckimtype {
+    # in: (/path/file)
+    # out: MEF | SPLIT | SINGLE | (NULL)
+    
+    my ($answer, $name, $value);
+    my ($file) = $_[0];
+
+    if (! -e $file) { 
+	print STDOUT "can't open file\n";
+	return ""; 
+    }
+
+    # if /path/file is a directory, it is split:
+    if (-d $file) { return "SPLIT"; }
+
+    # check that the file is a FITS image
+    $answer = `file -L $file`;
+    if ($?) { 
+	print STDOUT "can't open file\n";
+	return ""; 
+    }
+    ($name, $value) = split (" ", $answer);
+    if ($value ne "FITS") { 
+	print STDOUT "not a valid image\n";
+	return ""; 
+    }
+    
+    # check for NAXIS = 0 (MEF) 
+    $answer = `echo $file | fields NAXIS`;
+    # if ($?) { return ""; }
+    ($name, $value) = split (" ", $answer);
+    if ($value eq 0) { return "MEF"; }
+    
+    if ($value == 2) { return "SINGLE"; }
+
+    print STDOUT "not a valid image\n";
+    return "";
+}
+
+sub mk_basename {
+    my ($path) = $_[0];
+    my ($root) = $_[1];
+    my ($mode) = $_[2];
+
+    if ($mode eq "MEF") {
+	$name = sprintf "%s/%s.fits", $path, $root;
+	return $name;
+    }
+    if ($mode eq "SPLIT") {
+	$name = sprintf "%s/%s", $path, $root;
+	return $name;
+    }
+    return "";
+}
+
+sub mk_filename {
+    my ($path) = $_[0];
+    my ($root) = $_[1];
+    my ($mode) = $_[2];
+    my ($ccd)  = $_[3];
+
+    if ($mode eq "MEF") {
+	$name = sprintf "%s/%s.fits", $path, $root;
+	return $name;
+    }
+    if ($mode eq "SPLIT") {
+	$name = sprintf "%s/%s/%s%02d.fits", $path, $root, $root, $ccd;
+	return $name;
+    }
+    return "";
+}
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "\n";
+    print "USAGE: fr.detrend (path) (root) (mode) (outdir)\n";
+    print " path:   path to MEF image or SPLIT dir\n";
+    print " root:   root name of image (MEF = root.fits, SPLIT = root/rootNN.fits)\n";
+    print " mode:   MEF or SPLIT\n";
+    print " outdir: directory for output results (all split)\n";
+    exit 1;
+}
Index: /tags/start/Ohana/src/perl/old/get.standards
===================================================================
--- /tags/start/Ohana/src/perl/old/get.standards	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/get.standards	(revision 12606)
@@ -0,0 +1,103 @@
+#!/usr/bin/env perl
+
+# this script is very much specific to the CFHT data layout
+
+$VERBOSE = 1;
+$stdpath = "/h/archive/current/01aq97";
+
+$run = "all";
+# grab the command line arguments:
+@tARGV = ();
+for (; @ARGV > 0; ) {
+
+    # by default, all OBJECT images are returned.  specify a run with -run
+    if ($ARGV[0] eq "-run") {
+	shift;
+	$run = $ARGV[0];
+	shift;
+	next;
+    }
+    
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 0) { die "USAGE: ckrunid [-run RunID]\n" ;}
+
+# the archive is supposed to contain only MEF images.  
+# The standard star images might get a few focus or detrend images
+# mixed in, so restrict the glob to only *o.fits images:
+@imlist = <$stdpath/*o.fits>;
+
+# find date range in run list
+foreach $name (@imlist) {
+
+    if ($run eq "all") { 
+	@outlist = (@outlist, $name);
+	next; 
+    }
+
+    $runid = `ckrunid $name`;
+    if ($?) {
+	if ($VERBOSE) { print STDERR "no crunid for $name\n"; }
+	next;
+    }
+    chop ($runid);
+    
+    if ($runid ne $run) {
+	if ($VERBOSE) { print STDERR "wrong crunid for $name ($runid vs $run)\n"; }
+	next;
+    }
+
+    @outlist = (@outlist, $name);
+}
+
+foreach $name (@outlist) {
+    print STDOUT "$name\n";
+}
+
+exit 0;
+
+###################################################################################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub get_jd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5;
+    
+
+    return ($jd);
+
+}
+
+sub get_mjd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5 - 2400000.5;
+    
+
+    return ($jd);
+
+}
+
Index: /tags/start/Ohana/src/perl/old/gtfringe
===================================================================
--- /tags/start/Ohana/src/perl/old/gtfringe	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/gtfringe	(revision 12606)
@@ -0,0 +1,80 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 4) { die "USAGE: gtfringe (in.fits) (fringe.coords) (binning) (out.dat)\n"; }
+
+$input   = $ARGV[0];
+$coords  = $ARGV[1];
+$binning = $ARGV[2];
+$output  = $ARGV[3];
+
+# create temporary files:
+$PARFILE = `mktemp /tmp/gtfringe.XXXXXX`;
+$INFILE  = `mktemp /tmp/@gtfringe.XXXXXX`
+$OUTFILE = `mktemp /tmp/gtfringe.XXXXXX`
+
+# convert 
+
+open (FILE, "$inlist");
+@mef = <FILE>;
+close (FILE);
+
+@split = ();
+foreach $name (@mef) {
+    chop ($name);
+
+    # convert name /path/name.fits to /outdir/rootNN.fits
+    @words = split ("/", $name);
+    $root = $words[-1];
+    $root =~ s/.fits//;
+    
+    $new = sprintf "%s/%s%02d.fits", $outdir, $root, $ccd;
+    push @split, $new;
+}
+    
+open (MANA, "|mana --norc");
+
+# define the macro 'split'
+print MANA "macro split\n";
+print MANA " rd a \$1 -n $ccd\n";
+print MANA " keyword a NAXIS1 nx\n";
+print MANA " keyword a NAXIS2 ny\n";
+print MANA " if ((\$nx == 2080) && (\$ny == 4128))\n";
+print MANA "   wd a \$2 -bitpix 16 -bzero 32768 -bscale 1.0\n";
+print MANA "   exec echo \$2 >> $outlist\n";
+print MANA " end\n";
+print MANA "end\n";
+
+# create the macro 'go' with the commands 
+print MANA "macro go\n";
+for ($i = 0; $i < @mef; $i++) {
+    if (-e $split[$i]) { 
+	print STDERR "$split[$i] exists, skipping\n";
+	next; 
+    }
+    print MANA " split $mef[$i] $split[$i]\n";
+}
+# if the macro ends successfully, exit 0
+print MANA " exit 0\n";
+print MANA "end\n";
+
+# if the macro exits before the end, exit 1
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+
+$status = $?;
+print STDERR "mana exit status: $status\n";
+if ($status) {
+    print STDERR "ERROR: problem running split.mef\n";
+    exit 1;
+}
+
+print STDERR "SUCCESS\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
Index: /tags/start/Ohana/src/perl/old/images.names
===================================================================
--- /tags/start/Ohana/src/perl/old/images.names	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/images.names	(revision 12606)
@@ -0,0 +1,170 @@
+#!/usr/local/bin/perl
+
+$WANT = 0;
+
+# possible things to return:
+$FILE    = 1;
+$PATH    = 2;
+$ROOT    = 3;
+$EXT     = 4;
+$NCCD    = 5;
+$CCD     = 6;
+$BASEEXT = 7;
+$CCDLIST = 8;
+
+while (@ARGV) {
+    
+    $name = shift (@ARGV);
+
+    # provided component(s)
+    if ($name eq "-file") {
+	$file = shift (@ARGV);
+    }
+    if ($name eq "-path") {
+	$path = shift (@ARGV);
+    }
+    if ($name eq "-root") {
+	$root = shift (@ARGV);
+    }
+    if ($name eq "-base") {
+	$base = shift (@ARGV);
+    }
+    if ($name eq "-ext") {
+	$ext = shift (@ARGV);
+    }
+    if ($name eq "-baseext") {
+	$baseext = shift (@ARGV);
+    }
+    if ($name eq "-Nccd") {
+	$Nccd = shift (@ARGV);
+    }
+    if ($name eq "-ccd") {
+	$ccd = shift (@ARGV);
+    }
+    if ($name eq "-mode") {
+	$mode = "\U$ARGV[0]\E";
+	shift (@ARGV);
+    }
+
+    # desired component
+    if ($name eq "+file") {
+	if ($WANT) { &badchoice; }
+	$WANT = $FILE;
+    }
+    if ($name eq "+path") {
+	if ($WANT) { &badchoice; }
+	$WANT = $PATH;
+    }
+    if ($name eq "+root") {
+	if ($WANT) { &badchoice; }
+	$WANT = $ROOT;
+    }
+    if ($name eq "+ext") {
+	if ($WANT) { &badchoice; }
+	$WANT = $EXT;
+    }
+    if ($name eq "+baseext") {
+	if ($WANT) { &badchoice; }
+	$WANT = $BASEEXT;
+    }
+    if ($name eq "+Nccd") {
+	if ($WANT) { &badchoice; }
+	$WANT = $NCCD;
+    }
+    if ($name eq "+ccd") {
+	if ($WANT) { &badchoice; }
+	$WANT = $CCD;
+    }
+    if ($name eq "+mode") {
+	if ($WANT) { &badchoice; }
+	$WANT = $MODE;
+    }
+}
+
+if ($base eq "") { $base = $root; }
+if ($root eq "") { $root = $base; }
+if ($ext eq "") { $ext = "fits"; }
+if ($path eq "") { $path = "."; }
+if ($mode eq "") { $mode = "MEF"; }
+
+if (@ARGV != 0) { &usage; }
+if (!$WANT) { &usage; }
+
+if (0) {
+    print STDERR "want: $WANT\n";
+    print STDERR "file: $file\n";
+    print STDERR "path: $path\n";
+    print STDERR "root: $root\n";
+    print STDERR "base: $base\n";
+    print STDERR "ext: $ext\n";
+    print STDERR "baseext: $baseext\n";
+    print STDERR "Nccd: $Nccd\n";
+    print STDERR "ccd: $ccd\n";
+    print STDERR "mode: $mode\n";
+}
+
+if ($WANT == $FILE) {
+    if ($mode eq "SPLIT") {
+	$output = sprintf "%s/%s%s/%s%02d.%s", $path, $base, $baseext, $root, $ccd, $ext;
+    }
+    if ($mode eq "MEF") {
+	$output = sprintf "%s/%s%s.%s", $path, $base, $baseext, $ext;
+    }
+}
+
+if ($WANT == $PATH) {
+    # split path and filename:
+    @words = split ("/", $file);
+    $N = @words;
+
+    for ($i = 0; $i < $N - 1; $i++) {
+	$output = $output . $words[$i] . "/";
+    }
+    chop ($output);   # strip off last /
+}
+
+if ($WANT == $CCD) {
+    # split path and filename:
+    @words = split ("/", $file);
+    $N = @words;
+
+    for ($i = 0; $i < $N - 1; $i++) {
+	$output = $output . $words[$i] . "/";
+    }
+    chop ($output);   # strip off last /
+}
+
+print STDOUT "$output\n";
+exit 0;
+
+# definition of the path components:
+
+# MEF:
+# /path/root/base.ext
+
+# SPLIT:
+# /path/root/base.ext
+
+# file = 
+# 1: /data/koa/cfh12k/01Ak01/543210f.fits
+# 2: /data/koa/cfh12k/01Ak01/543210f/543210f00.fits
+# 3: /data/koa/cfh12k/01Ak01/543210f.alt/543210f00.fits
+
+# base = 543210f
+# path = /data/koa/cfh12k/01Ak01 
+# root = 543210f (1,2), 543210f.alt (3)
+# ext  = fits
+# ext = "" (1,2), ".alt" (3)
+# Nccd = 12 [for CFH12K]
+# ccd  = NN (1), 00 (2,3)
+
+sub badchoice {
+    print STDERR "only one choice allowed\n"; 
+    exit 1; 
+}
+
+sub usage {
+    print STDERR "USAGE: image.names [options]\n";
+    exit 2;
+}
+
Index: /tags/start/Ohana/src/perl/old/imselect
===================================================================
--- /tags/start/Ohana/src/perl/old/imselect	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/imselect	(revision 12606)
@@ -0,0 +1,189 @@
+#!/usr/bin/env perl
+$SKIPDOME = 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    die "@_";
+}
+
+if (@ARGV != 7) { die "ERROR: USAGE: imselect (ccd) (type) (filter) (tstart) (tend) (output) (-split | -mef)\n" }
+
+$type = "\U$ARGV[1]\E";
+if ($type eq "DARK") { }
+
+if ($type eq "FLAT") {
+    # define some of the relevant parameters
+    $min = 2000;
+    $max = 60000;
+    $minrate = 100;
+    $ratescale = 70;
+    $filter = "\U$ARGV[2]\E";
+    if ($filter eq "B") { $minrate = 0.5  * $ratescale;  }
+    if ($filter eq "V") { $minrate = 1.0  * $ratescale;  }
+    if ($filter eq "R") { $minrate = 3.5  * $ratescale;  }
+    if ($filter eq "I") { $minrate = 14.2 * $ratescale; }
+    if ($filter eq "Z") { $minrate = 10.5 * $ratescale; }
+    if ($filter eq "HA")    { $min = 1000; }
+    if ($filter eq "HAOFF") { $min = 1000; }
+    # probably need to set these in a more intelligent fashion.
+}
+
+# $ccd is ccd number (see camera config), $ARGV[0] is ccd id
+$ccd = `cameraconfig -N $ARGV[0]`; chop ($ccd);
+if ($ccd eq "") { die "ERROR : can't find CCD $ARGV[0]\n"; } 
+
+$Nccd = `cameraconfig -Nccd`; chop ($Nccd);
+$line = `cameraconfig -axes`; chop ($line);
+($Naxis1, $Naxis2) = split (" ", $line);
+
+$mode = "none";
+if ($ARGV[6] eq "-split") { $mode = "split"; }
+if ($ARGV[6] eq "-mef")   { $mode = "mef";   }
+if ($mode eq "none") {
+    die "ERROR: mode must be either -split or -mef\n";
+}
+
+@good = ();
+@marginal = ();
+
+# define filter lines for imsearch.  for flats, there may be alternate filter names to test
+@filtline = ();
+if ($type eq "FLAT") {
+    # convert given filter name to list of possible names:
+    $answer = `filtnames $ARGV[2] -all`;
+    @filtlist = split (" ", $answer);
+
+    foreach $name (@filtlist) {
+	$line = "-type flat -filter $name -mode $mode -trange $ARGV[3] $ARGV[4]";
+	push @filtline, $line;
+    }
+} 
+if ($type eq "BIAS") {
+    push @filtline, "-type bias -mode $mode -trange $ARGV[3] $ARGV[4]";
+} 
+if ($type eq "DARK") {
+    push @filtline, "-type dark -etime $ARGV[2] -mode $mode -trange $ARGV[3] $ARGV[4]";
+} 
+
+# run selection on each possible $filtline
+@list = ();
+foreach $line (@filtline) {
+    @tlist = `imsearch -ccd $ccd $line`;
+    @list = (@list, @tlist);
+}
+$Nlist = @list;
+print STDERR "found $Nlist images\n";
+
+for ($i = 0; $i < $Nlist; $i++) {
+    @words = split (" ",$list[$i]);
+    
+    if ($SKIPDOME) {
+	# a fairly lame and non-robust way to detect dome flats
+	if ($type eq "FLAT") {
+	    @answer = `echo $words[4]/$words[5] | fields OBJECT | grep -i dome`;
+	    if ($answer[0] ne "") { print STDERR "$words[5] rejected: dome flat\n"; next; }
+	}
+    }
+
+    if ($mode eq "split") {
+	# all $Nccd images must exist on disk, split files are assumed to be 
+	# in a subdirectory of their own, .fits extension assumed
+	@answer = <$words[4]/*.fits>;
+	if (@answer != $Nccd) { print STDERR "$words[5] rejected: missing images\n"; next; }
+    }
+
+    # images have to have the correct dimensions
+    if ($mode eq "split") {
+	@answer = `echo $words[4]/$words[5] | fields NAXIS1 NAXIS2`;
+	@wds = split (" ",$answer[0]);
+	$Nx = $wds[1]; $Ny = $wds[2];
+    } else {
+	@answer = `ftable -X 1 $words[4]/$words[5] | grep "^NAXIS1"`;
+	@wds = split (" ",$answer[0]);
+	$Nx = $wds[2];
+	@answer = `ftable -X 1 $words[4]/$words[5] | grep "^NAXIS2"`;
+	@wds = split (" ",$answer[0]);
+	$Ny = $wds[2];
+    }
+    if (($Nx != $Naxis1) || ($Ny != $Naxis2)) { print STDERR "$words[5] rejected: wrong dimensions\n"; next; }
+    
+    # $match is a word unique to the full mosaic image (the rootdir for split, the image for mef) 
+    if ($mode eq "split") { 
+	@answer = split ("/", $words[4]); 
+	$match = $answer[-1]; 
+    } else { 
+	$match = $words[5]; 
+    }
+    @list2 = `imsearch -name $match`;
+    $Nlist2 = @list2;
+    print STDERR "$match: $Nlist2\n";
+    if (@list2 != $Nccd) {
+	print STDERR "$words[5] rejected: missing entries in image database\n";
+	next;
+    }
+
+    if ($type eq "FLAT") {
+
+	if ($SKIPDOME) {
+	    # test for acceptable time (or is probably a dome flat)
+	    @answer = `dusktime $words[8]`;
+	    @wds = split (" ",$answer[0]);
+	    if ($wds[2] < 0) { print STDERR "$words[5] rejected: not twilight\n"; next; }
+	}
+	
+	$range = 1;
+	$rate  = 1;
+
+	# check for counts or flux out of range or any chip
+	for ($j = 0; $rate && $range && ($j < @list2); $j++) {
+	    @words2 = split (" ", $list2[$j]);
+	    
+	    # test for acceptable flux range
+	    if ($words2[11] < $min) { $range = 0; print STDERR "$words[5] rejected: signal too low: $words2[11] vs $min\n"; next; }
+	    if ($words2[11] > $max) { $range = 0; print STDERR "$words[5] rejected: signal too high: $words2[11] vs $max\n"; next; }
+	    
+	    # test for acceptable rate
+	    if (($words2[11] / $words2[7]) < $minrate) { 
+	      $rate = 0; 
+	      $F = $words2[11] / $words2[7];
+	      print STDERR "$words[5] rejected: flux too low: $F vs $minrate\n"; next; }
+	}
+	if (!$range) { next; }
+
+	@marginal = (@marginal, "$words[4]/$words[5]");
+	if (!$rate) { next; }
+    } else {
+	@marginal = (@marginal, "$words[4]/$words[5]");
+    }
+
+    @good = (@good, "$words[4]/$words[5]");
+}
+
+open (LIST, ">$ARGV[5]");
+if (@good > 5) {
+    for ($i = 0; $i < @good; $i++) {
+	print LIST "$good[$i]\n";
+	if (($type eq "BIAS") && ($i > 30)) { last; }
+	if (($type eq "DARK") && ($i > 30)) { last; }
+    }
+} else {
+    print STDERR "warning: limited number of flat images, scraping the bottom\n";
+    for ($i = 0; $i < @marginal; $i++) {
+	print LIST "$marginal[$i]\n";
+    }
+}
+close (LIST);
+print STDERR "SUCCESS\n";
+exit 0;
+
+# we need to select the list of images which satisfy a few criteria:
+# 1) all 12 CCDs must exist
+# 2) stats must be measured for each
+# 3) stats for all 12 must be within range (2000 - 40000)
+# 4) NAXIS1 == 2080 && NAXIS2 == 4128
Index: /tags/start/Ohana/src/perl/old/merge.lists
===================================================================
--- /tags/start/Ohana/src/perl/old/merge.lists	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/merge.lists	(revision 12606)
@@ -0,0 +1,92 @@
+#!/usr/bin/env perl
+
+$update = 0;
+
+# grab the command line arguments:
+@tARGV = ();
+for (; @ARGV > 0; ) {
+
+    # new images get mode of 0, old image keep their mode
+    if ($ARGV[0] eq "-update") {
+	shift;
+	$update = 1;
+	next;
+    }
+    
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 3) { die "USAGE: merge.lists (list.split) (list.msplit) (list.master) [-update]\n" ;}
+
+# load names from SPLIT and MEF
+open (FILE, "$ARGV[0]");
+@split = <FILE>;
+close (FILE);
+
+open (FILE, "$ARGV[1]");
+@mef = <FILE>;
+close (FILE);
+
+# load old names from MASTER
+open (FILE, "$ARGV[2]");
+@master = <FILE>;
+close (FILE);
+
+# merge new entries into a single list, compare with state in master
+@names = (@split, @mef);
+
+@newname = ();
+@newmode = ();
+
+for ($i = 0; $i < @names; $i++) {
+
+    $name = $names[$i]; chop ($name);
+
+    $mode = 1;
+    if ($update) {
+	$mode = 0;
+
+      INNER:
+	foreach $line (@master) {
+	    @words = split (" ", $line);
+	    if ($words[0] eq $name) {
+		$mode = $words[1];
+		last INNER;
+	    }
+	}
+    }
+    @newname = (@newname, $name);
+    @newmode = (@newmode, $mode);
+}
+
+if (! @newname) {
+    print STDERR "ERROR: no relevant ccd images\n";
+    exit 1;
+}
+    
+# check on list: if there are none selected, select all
+$Ngood = 0;
+foreach $mode (@newmode) {
+    if ($mode) {
+	$Ngood ++;
+    }
+}
+if ($Ngood == 0) {
+    foreach $mode (@newmode) {
+	$mode = 1;
+    }
+}
+
+open (FILE, ">$ARGV[2]");
+for ($i = 0; $i < @newname; $i++) {
+    print FILE "$newname[$i] $newmode[$i]\n";
+}
+close (FILE);
+
+# this file must be accessible by www user  
+chmod 0666, $ARGV[2];
+
+print STDOUT "SUCCESS\n";
+exit 0;
Index: /tags/start/Ohana/src/perl/old/mkptolemy.names
===================================================================
--- /tags/start/Ohana/src/perl/old/mkptolemy.names	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/mkptolemy.names	(revision 12606)
@@ -0,0 +1,71 @@
+#!/usr/bin/env perl
+
+$Nccd = 12;
+
+if (@ARGV != 3) { die "USAGE: mkptolemy.names (name) (mode) (dir)\n" ;}
+
+$name = $ARGV[0];
+$mode = "\U$ARGV[1]\E";
+$dir = $ARGV[2];
+
+unless ($name =~ /^\d\d\d\d\d\d\w$/) {
+    print STDERR "name does not match the expected format 555555o\n";
+    exit 1;
+}
+
+for ($ccd = 0; $ccd < $Nccd; $ccd++) {
+
+    if ($mode eq "MEF") {
+	printf "%s/%s.fits %s/%s%02d %02d MEF\n", $dir, $name, $name, $name, $ccd, $ccd;
+    }
+
+    if ($mode eq "SPLIT") {
+	printf "%s/%s/%s%02d.fits %s/%s%02d %02d MEF\n", $dir, $name, $name, $ccd, $name, $name, $ccd, $ccd;
+    }
+
+}
+
+exit 0;
+
+###################################################################################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub get_jd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5;
+    
+
+    return ($jd);
+
+}
+
+sub get_mjd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5 - 2400000.5;
+    
+
+    return ($jd);
+
+}
+
Index: /tags/start/Ohana/src/perl/old/prepare.run
===================================================================
--- /tags/start/Ohana/src/perl/old/prepare.run	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/prepare.run	(revision 12606)
@@ -0,0 +1,349 @@
+#!/usr/bin/env perl
+
+# global vars:
+$atmach  = "druid.cfht.hawaii.edu";
+$runlist = "";
+@runlist = ();
+
+# check usage
+if (@ARGV < 1) {
+    print STDOUT "USAGE: mkrun (mode) [arguments]\n";
+    print STDOUT " mkrun help gives a complete list\n";
+    &goodbye;
+}
+if ($ARGV[0] eq "help") { &usage; }
+
+&set_globals;
+
+# call appropriate command
+if ($ARGV[0] eq "create") { &create (@ARGV); }
+if ($ARGV[0] eq "addqso") { &addqso (@ARGV); }
+if ($ARGV[0] eq "delqso") { &delqso (@ARGV); }
+if ($ARGV[0] eq "status") { &status; }
+if ($ARGV[0] eq "sched")  { &sched  (@ARGV); }
+
+print STDOUT "invalid mkrun command\n";
+exit 1;
+
+sub status {
+
+    &load_runlist;
+    foreach $line (@runlist) {
+	print STDOUT "$line\n";
+    }
+    exit 0;
+}
+
+############
+sub create {
+
+    my (@argv) = @_;
+    
+    if (@argv != 4) {
+	print STDOUT "USAGE: mkrun create (run) (start) (stop)\n";
+	exit 2;
+    }
+
+    $runid = $argv[1];
+    $start = $argv[2];
+    $stop  = $argv[3];
+
+    &load_runlist;
+    
+    $line = grab_runline ($runid);
+    ($Orunid, $Ostart, $Ostop, $qrunid) = split (" ", $line);
+    $line = mk_runline ($runid, $start, $stop, $qrunid);
+    insert_runline ($line);
+
+    &save_runlist;
+    exit 0;
+}
+
+############
+sub addqso {
+
+    my (@argv) = @_;
+    
+    if (@argv != 3) {
+	print STDOUT "USAGE: mkrun addqso (run) (qsorun)\n";
+	exit 2;
+    }
+
+    $runid = $argv[1];
+    $qrunid  = $argv[2];
+
+    &load_runlist;
+    
+    $line = grab_runline ($runid);
+    if ($line eq "") { 
+	print STDERR "run id $runid not in run list\n";
+	exit 1;
+    }
+    ($runid, $start, $stop, $Oqrunid) = split (" ", $line, 4);
+    if ($Oqrunid) {
+	$qrunid = $Oqrunid . " " . $qrunid;
+    } 
+
+    $line = mk_runline ($runid, $start, $stop, $qrunid);
+    insert_runline ($line);
+
+    &save_runlist;
+    exit 0;
+}
+
+############
+sub delqso {
+    my (@argv) = @_;
+    if (@argv != 2) {
+	print STDOUT "USAGE: mkrun addqso (qsorun)\n";
+	exit 2;
+    }
+
+    $qrunid  = $argv[1];
+
+    &load_runlist;
+    
+    # find listed qrunid
+    $match = "";
+  SEARCH:
+    foreach $line (@runlist) {
+	if ($line =~ /^\#/) { next; } # skip commented lines
+	($tmp, $tmp, $tmp, $qlist) = split (" ", $line, 4);
+	@qlist = split (" ", $qlist);
+	foreach $qid (@qlist) {
+	    if ($qrunid ne $qid) { next; }
+	    $match = $line;
+	    last SEARCH;
+	}
+    }
+    if ($match eq "") {
+	print STDERR "QSO run id $qrunid not found in run list\n";
+	exit 1;
+    }
+
+    # recreate $qlist without $qrunid
+    $qlist = "";
+    foreach $qid (@qlist) {
+	if ($qid eq $qrunid) { next; }
+	$qlist = $qlist . $qid . " ";
+    }
+
+    ($runid, $start, $stop) = split (" ", $match);
+
+    $line = mk_runline ($runid, $start, $stop, $qlist);
+    insert_runline ($line);
+
+    &save_runlist;
+    exit 0;
+}
+
+##############
+
+sub sched {
+    my (@argv) = @_;
+    if (@argv != 2) {
+	print STDOUT "USAGE: mkrun sched (runid)\n";
+	exit 2;
+    }
+
+    $runid  = $argv[1];
+    &load_runlist;
+    
+    $line = grab_runline ($runid);
+    ($runid, $start, $stop, $qlist) = split (" ", $line, 4);
+
+    at_loop ($runid, $start, $stop);
+    
+    exit 0;
+}
+
+##############
+sub at_loop {
+    my ($runid, $start, $stop);
+    $runid = $_[0];
+    $start = $_[1];
+    $stop  = $_[2];
+    
+    $mjd_start = date_to_mjd ($start);
+    $mjd_stop  = date_to_mjd ($stop);
+
+    $Nday = $mjd_stop - $mjd_start;
+
+    ($year, $month, $day) = $start =~ /(\d+)\/(\d+)\/(\d+)/;
+    for ($Day = -1; $Day < $Nday; $Day++) {
+	
+	# 'at' needs date in format MM/DD/YYYY or DD.MM.YYYY
+	$tday = $day + $Day;
+	$date = `date -d $year/$month/$tday +%m/%d/%Y`; chop ($date);
+
+	if ($Day == -1) {
+	    atcommand ("clear.rawdir -current >& /h/eugene/cfh12k/logs/clear.log &", "10:00", $date);
+	}
+
+	if ($Day == 0) {
+	    atcommand ("echo RUNID $runid > /h/cfh12k/elixir.run", "10:00", $date);
+	    atcommand ("mkdetrend create $runid $start $stop >& /h/eugene/cfh12k/logs/mkdetrend.log", "10:05", $date);
+	    atcommand ("mkfringe config $runid >& /h/eugene/cfh12k/logs/mkdetrend.log", "10:10", $date);
+	    atcommand ("mkfringe mkconfig $runid >& /h/eugene/cfh12k/logs/mkdetrend.log", "10:15", $date);
+	    
+	    atcommand ("elixir -D mode imstats >& /h/eugene/cfh12k/logs/imstats.log &", "15:00", $date);
+	    atcommand ("elixir -D mode sextract >& /h/eugene/cfh12k/logs/ptolemy.log &", "15:00", $date);
+	    atcommand ("gettemps &", "15:00", $date);
+	    atcommand ("elixir.report &", "15:00", $date);
+	}
+
+	if (($Day > 0) && ($Day < 4)) {
+	    atcommand ("mkdetrend init >& /h/eugene/cfh12k/logs/mkdetrend.log; mkdetrend run >& /h/eugene/cfh12k/logs/mkdetrend.log", "07:00", $date);
+	}
+	if ($Day >= 4) {
+	    atcommand ("mkdetrend update >& /h/eugene/cfh12k/logs/mkdetrend.log", "07:00", $date);
+	}
+	if ($Day > 0) {
+	    # atcommand ("clear /h/cfh12k/images/elixir", "12:00", $date);
+	}
+    }
+}
+
+####### runlist utilities ############################
+sub load_runlist {
+    open (FILE, "$runlist");
+    @runlist = <FILE>;
+    foreach $line (@runlist) {
+	chop ($line);
+    }
+    close (FILE);
+}    
+
+sub save_runlist {
+    open (FILE, ">$runlist");
+    foreach $line (@runlist) {
+	print FILE "$line\n";
+    }
+    close (FILE);
+}    
+
+sub grab_runline {
+    my ($id) = $_[0];
+    my ($line);
+    my ($runid);
+
+    foreach $line (@runlist) {
+	if ($line =~ /^\#/) { next; } # skip commented lines
+	($runid) = split (" ", $line);
+	if ($runid ne $id) { next; }
+	return ($line);
+    }
+    return ("");
+}
+    
+sub insert_runline {
+    my ($runline) = $_[0];
+    my ($line);
+    my ($runid, $id);
+
+    # match the run id lines
+    ($id) = split (" ", $runline);
+    foreach $line (@runlist) {
+	if ($line =~ /^\#/) { next; } # skip commented lines
+	($runid) = split (" ", $line);
+	if ($runid ne $id) { next; }
+	$line = $runline;
+	return 1;
+    }
+    @runlist = (@runlist, $runline);
+    return 0;
+}
+
+sub mk_runline {
+    my ($runid, $start, $stop, $qrunid, $line);
+    $runid  = $_[0];
+    $start  = $_[1];
+    $stop   = $_[2];
+    $qrunid = $_[3];
+
+    $start = date_format ($start);
+    $stop  = date_format ($stop);
+    $line = sprintf "%s %s %s  %s", $runid, $start, $stop, $qrunid;
+    return ($line);
+}
+
+# utilities ##############################################
+
+sub atcommand {
+    my ($cmd, $time, $date);
+    $cmd = $_[0];
+    $time = $_[1];
+    $date = $_[2];
+
+    $line = sprintf "echo %s | at %s %s", $cmd, $time, $date;
+    print STDOUT "$line\n";
+}
+
+
+sub vsystem {
+    # print STDERR "@_\n";
+    my($status) = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub date_format {
+    my ($date) = $_[0];
+    my ($year, $month, $day);
+
+    ($year, $month, $day) = $date =~ /(\d+)\/(\d+)\/(\d+)/;
+    $date = sprintf "%4d/%02d/%02d", $year, $month, $day;
+    return ($date);
+}
+
+sub date_to_mjd {
+    my ($date) = $_[0];
+    my ($year, $month, $day, $mjd);
+
+    ($year, $month, $day) = $date =~ /(\d+)\/(\d+)\/(\d+)/;
+    $mjd = get_mjd ($year, $month, $day);
+
+    return ($mjd);
+}
+
+sub get_mjd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5 - 2400000.5;
+    
+
+    return ($jd);
+
+}
+
+sub set_globals {
+
+    # this should come fron the config system
+#    $runlist = "/data/milo/eugene/elixir/refs/cfh12k.runs";
+    $runlist = "/h/eugene/test.runs";
+}
+
+sub usage {
+    
+    if (@ARGV == 1) {
+	print STDERR "\n --- user modes ---\n";
+	print STDERR "create (run) (start) (stop)\n";
+	print STDERR "addqso (runid) (qsoid)\n";
+	print STDERR "delqso (qsoid)\n";
+	print STDERR "sched (runid)\n";
+	print STDERR "status\n";
+	&goodbye;
+    }
+    
+    if (@ARGV > 2) { print STDERR "USAGE: prepare.run (help) [mode]\n"; &goodbye; }
+    
+    &goodbye;
+}
Index: /tags/start/Ohana/src/perl/old/pt.run
===================================================================
--- /tags/start/Ohana/src/perl/old/pt.run	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/pt.run	(revision 12606)
@@ -0,0 +1,66 @@
+#!/usr/bin/env perl
+
+# USAGE: pt.run (obsid)
+
+if (@ARGV != 1) { die "USAGE: ckvalid (obsid)\n" ;}
+
+$obsid = $ARGV[0];
+$archive = "/h/archive/current/instrument/cfh12k";
+
+# find the run id for this image
+$runid = `ckrunid $archive/$obsid.fits`;
+if ($?) {
+    print STDOUT "$obsid: no run ID\n";
+    exit 1;
+}
+chop ($runid);
+
+# try to use the flt files, if they exist, for headers
+$tmpdir = "/data/elixir2/cfh12k/tmpdata/$runid/$obsid";
+
+print "$tmpdir\n";
+
+@flt = <$tmpdir/*.flt>;
+$Nflt = @flt;
+if ($Nflt != 12) {
+    print STDOUT "not enough *.flt files ($Nflt)\n";
+    @smp = <$tmpdir/*.smp>;
+    if (@smp == 12) {
+	print STDOUT "using old *.smp files\n";
+	@flt = ();
+	foreach $smp (@smp) {
+	    $flt = $smp;
+	    $flt =~ s/smp/flt/;
+	    vsystem ("cp $smp $flt");
+	    @flt = (@flt, "$flt");
+	}
+    } else {
+	exit 1;
+    }
+}
+
+foreach $flt (@flt) {
+    $smp = $flt;
+    $smp =~ s/flt/smp/;
+
+    $sx = $flt;
+    $sx =~ s/flt/sx/;
+
+    vsystem ("imclean -sex $flt $sx $smp");
+    vsystem ("gastro -v $smp");
+
+    # imclean -sex *.flt *.sx *.smp
+    # gastro -v *.smp
+}
+
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    my($status) = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
Index: /tags/start/Ohana/src/perl/old/scheduler
===================================================================
--- /tags/start/Ohana/src/perl/old/scheduler	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/scheduler	(revision 12606)
@@ -0,0 +1,248 @@
+#!/usr/bin/env perl
+
+$ENV{'PATH'} = "$ENV{'PATH'}:/apps/elixir/bin";
+
+$schedule = `gconfig SCHEDULE`; chop $schedule;
+$logdir   = `gconfig LOGDIR`;   chop $logdir;
+$log      = "$logdir/scheduler.log";
+$window   = 0.02; # ~0.5 hours. 
+$machine  = "milo.cfht.hawaii.edu";
+
+$LIST = 0;
+$ALL  = 0;
+$RUN = 0;
+
+# execute any event which is within the time range: 
+# $last + $window < event < NOW + $window
+
+# check usage
+if ($ARGV[0] eq "help")  { &usage; }
+if ($ARGV[0] eq "all")   { &list_all; }
+if ($ARGV[0] eq "list")  { &list_active; }
+if ($ARGV[0] eq "run")   { &run_active; }
+if ($ARGV[0] eq "clear") { &clear_all; }
+print STDERR "scheduler command '$ARGV[0]' not found\n";
+&usage;
+
+sub list_active {
+
+    &set_current_time;  # set $NOWdate, $NOWtime $NOWmjd
+    &load_schedule;     # load into @list
+    &find_previous;     # set $last (last runtime)
+    &find_active;       # fill @execute & @cmdlogs for active commands
+
+    for ($i = 0; $i < @execute; $i++) {
+	print "$execute[$i] ($cmdlogs[$i])\n";
+    }
+    exit 0;
+}
+
+sub run_active {
+
+    &set_current_time;
+    &load_schedule;
+    &find_previous;
+    &find_active;
+
+    # re-create schedule with new PREVIOUS:
+    if (@list && (-e "$schedule")) { 
+	system ("cp $schedule $schedule~"); 
+	open (FILE, ">$schedule");
+	foreach $line (@list) {
+	    if ($line =~ /^\s*PREVIOUS/) { 
+		printf FILE "PREVIOUS %s %s\n", $NOWdate, $NOWtime;
+		next;
+	    }
+	    
+	    print FILE "$line";
+	}    
+	close (FILE);
+    } else {
+	# create a new schedule with PREVIOUS set to NEVER
+	print STDERR "creating $schedule\n";
+	open (FILE, ">$schedule");
+	print FILE "# schedule for scheduler system\n";
+	print FILE "# E. Magnier\n";
+	print FILE "\n";
+	print FILE "# last time scheduler was run:\n";
+	printf FILE "PREVIOUS %s %s\n", $NOWdate, $NOWtime;
+	print FILE "\n";
+	close (FILE);
+    }
+
+    # launch commands one-by-one in background
+    for ($i = 0; $i < @execute; $i++) {
+	docommand ($cmdlogs[$i], $execute[$i]);
+	system ("sleep 60");
+    }
+    exit 0;
+}
+
+# utilities ##############################################
+
+sub docommand {
+    my ($log, $cmd);
+    $log  = $_[0];
+    $cmd  = $_[1];
+
+    $line = sprintf "scheduler.exec $log \"$cmd\" ";
+    vsystem ($line);
+}
+
+
+sub vsystem {
+    print STDERR "@_\n";
+    my($status) = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub load_schedule {
+    open (FILE, "$schedule");
+    @list = <FILE>;
+    close (FILE);
+}
+
+sub clear_all {
+    if (-e $schedule) {
+	vsystem ("cp $schedule $schedule~");
+	vsystem ("rm $schedule");
+    }
+    exit 0;
+}
+
+sub find_previous {
+    $last = 0;
+    $date = "NEVER";
+    # find previous runtime:
+    foreach $line (@list) {
+	if ($line =~ /^\#/) { next; } # skip commented lines
+	unless ($line =~ /^\s*PREVIOUS/) { next; }
+	
+	($tmp, $date, $time) = split (" ", $line);
+	if ($date eq "NEVER") {
+	    $last = 0;
+	    last; 
+	}
+	$last = timedate_to_mjd ($time, $date);
+	last;
+    }
+    print STDERR "run scheduler: $NOWdate $NOWtime (prev: $date $time)\n";
+}
+
+sub find_active {
+
+    @execute = ();
+    @cmdlogs = ();
+    # find relevant commands
+    foreach $line (@list) {
+	if ($line =~ /^\#/) { next; } # skip commented lines
+	if ($line =~ /^\s*PREVIOUS/) { next; }
+	
+	($date, $time, $cmdlog, $command) = split (" ", $line, 4);
+	if ($command eq "") { next; }
+	chop ($command);
+	
+	$mjd = timedate_to_mjd ($time, $date);
+	
+	if ($last + $window > $mjd) { next; }
+	if ($NOWmjd + $window < $mjd) { next; }
+	
+	@cmdlogs = (@cmdlogs, $cmdlog);
+	@execute = (@execute, $command);
+    }
+    
+}
+
+sub set_current_time {
+
+    ($sec, $min, $hour, $day, $mon, $year) = localtime ();
+    $mon += 1;
+    $year += 1900;
+    $NOWdate = sprintf "%s/%02d/%02d", $year, $mon, $day;
+    $NOWtime = sprintf "%02d:%02d:%02d", $hour, $min, $sec;
+    $NOWmjd = timedate_to_mjd ($NOWtime, $NOWdate);
+}
+
+sub date_format {
+    my ($date) = $_[0];
+    my ($year, $month, $day);
+
+    ($year, $month, $day) = $date =~ /(\d+)\/(\d+)\/(\d+)/;
+    $date = sprintf "%4d/%02d/%02d", $year, $month, $day;
+    return ($date);
+}
+
+sub timedate_to_mjd {
+    my ($time) = $_[0];
+    my ($date) = $_[1];
+    my ($mjd, $day);
+
+    $mjd  = date_to_mjd ($date);
+    $day += time_to_day ($time);
+
+    $mjd += $day;
+    return ($mjd);
+}
+    
+
+sub date_to_mjd {
+    my ($date) = $_[0];
+    my ($year, $month, $day, $mjd);
+
+    ($year, $month, $day) = $date =~ /(\d+)\/(\d+)\/(\d+)/;
+    $mjd = get_mjd ($year, $month, $day);
+
+    return ($mjd);
+}
+
+sub time_to_day {
+    my ($time) = $_[0];
+    my ($hour, $min, $sec, $days);
+
+    ($hour, $min, $sec) = split (":", $time);
+    $day = $hour / 24.0 + $min / 1440.0 + $sec / 86400.0;
+
+    return ($day);
+}
+
+sub get_mjd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5 - 2400000.5;
+    
+
+    return ($jd);
+
+}
+
+sub list_all {
+
+    # load schedule:
+    open (FILE, "$schedule");
+    @list = <FILE>;
+    close (FILE);
+    
+    foreach $line (@list) {
+	print "$line";
+    }
+    exit 0;
+}
+
+sub usage {
+    
+    print STDERR "USAGE: scheduler [mode]\n";
+    print STDERR " list  : list all active commands\n";
+    print STDERR " all   : list all commands\n";
+    print STDERR " run   : execute active commands\n";
+    print STDERR " clear : delete schedule\n";
+    &goodbye;
+}
Index: /tags/start/Ohana/src/perl/old/scheduler.exec
===================================================================
--- /tags/start/Ohana/src/perl/old/scheduler.exec	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/scheduler.exec	(revision 12606)
@@ -0,0 +1,21 @@
+#!/bin/csh -f
+
+set logdir = `gconfig LOGDIR`
+set log = "$logdir/scheduler.log"
+
+if ($#argv < 2) then
+ echo "USAGE: scheduler.exec (logfile) (cmd)"
+ exit 2;
+endif
+
+set cmdlog = $1
+shift
+
+set start=`date`
+echo "start: $start - $*" >> $log
+
+csh -c "$*" >>& $cmdlog
+set stat=$status
+
+set stop=`date`
+echo "stop:  $stop $stat $*" >> $log
Index: /tags/start/Ohana/src/perl/old/validate-1.0
===================================================================
--- /tags/start/Ohana/src/perl/old/validate-1.0	(revision 12606)
+++ /tags/start/Ohana/src/perl/old/validate-1.0	(revision 12606)
@@ -0,0 +1,287 @@
+#!/usr/bin/env perl
+
+# validate 
+# -update sends the validation value to the QSO database
+#  1 - valid image
+#  2 - subvalid image (problem, but doesn't matter)
+#  3 - invalid image
+#  4 - data error (missing, corrupted image)
+
+# global constants:
+
+$TRUE  = 1;
+$FALSE = 0;
+$RETRY = $TRUE;
+
+$MODE_UNSET    = 0;
+$MODE_VALID    = 1;
+$MODE_SUBVALID = 2;
+$MODE_INVALID  = 3;
+$MODE_DATAERR  = 4;
+
+$infile = "";
+$update = $FALSE;
+# put this in the CONFIG file:
+$runlist = "/data/milo/eugene/elixir/refs/cfh12k.runs";
+
+# include the CFHT bin directory in the path so we have access to QSO functions:
+$ENV{'PATH'} = "$ENV{'PATH'}:/cfht/bin";
+
+# grab the command line arguments:
+@tARGV = ();
+for (; @ARGV > 0; ) {
+
+    if ($ARGV[0] eq "-update") {
+	shift;
+	$update = $TRUE;
+	next;
+    }
+    if ($ARGV[0] eq "-skip") {
+	shift;
+	$RETRY = $FALSE;
+	next;
+    }
+    if ($ARGV[0] eq "-infile") {
+	shift;
+	$infile = $ARGV[0];
+	shift;
+	next;
+    }
+    
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 1) { die "USAGE: validate (crunid) [-infile filename] [-update]\n" ;}
+
+$crunid = $ARGV[0];
+
+# find qso run id for this camera run id:
+open (FILE, "$runlist");
+@list = <FILE>;
+close (FILE);
+
+# find date range in run list
+foreach $line (@list) {
+    chop ($line);
+    if ($line =~ /^\#/) { next; }
+    ($Crunid, $start, $stop, $Qrunid) = split (" ", $line, 4);
+    if (($start eq "") || ($stop eq "")) { next; }
+    if ($Crunid eq $crunid) { $qrunid = $Qrunid; last; }
+}
+
+print STDERR "qso run ID(s): $qrunid\n";
+
+@valid    = ();
+@invalid  = ();
+@dataerr  = ();
+@subvalid = ();
+
+if ($infile) {
+    # load images from previous output run or source file:
+    open (FILE, $infile);
+    @rawlist = <FILE>;
+    close (FILE);
+    
+    $mode = $MODE_UNSET;
+    @imlist = ();
+    
+  RAWLIST:
+    foreach $name (@rawlist) {
+	chop ($name);
+	
+	if ($name eq "") { next RAWLIST; }
+	    
+	if ($name =~ /^valid images/) {
+	    $mode = $MODE_VALID;
+	    next RAWLIST;
+	}
+	if ($name =~ /^invalid images/) {
+	    $mode = $MODE_INVALID;
+	    next RAWLIST;
+	}
+	if ($name =~ /^subvalid images/) {
+	    $mode = $MODE_SUBVALID;
+	    next RAWLIST;
+	}
+	if ($name =~ /^dataerr images/) {
+	    $mode = $MODE_DATAERR;
+	    next RAWLIST;
+	}
+
+	# plain list of image names (/path/name.fits)
+	if ($mode == $MODE_UNSET) {
+	    # double check on name validity
+	    ($file, $junk) = split (" ", $name, 2);
+	    unless ($file =~ /\d\d\d\d\d\d\w/) { print STDERR "?"; next RAWLIST; }
+	    @imlist = (@imlist, $file);
+	    next RAWLIST;
+	    # if (! -e $file) { print STDERR "x"; next RAWLIST; }
+	}
+	# place image names in the appropriate list
+	if ($mode == $MODE_VALID) {
+	    ($file, $result) = split (":", $name, 2);
+	    @valid = (@valid, $file);
+	    next RAWLIST;
+	}
+	if ($mode == $MODE_INVALID) {
+	    ($file, $result) = split (":", $name, 2);
+	    @invalid = (@invalid, $file);
+	    next RAWLIST;
+	}
+	if ($mode == $MODE_SUBVALID) {
+	    ($file, $result) = split (":", $name, 2);
+	    @subvalid = (@subvalid, $file);
+	    next RAWLIST;
+	}
+	if ($mode == $MODE_DATAERR) {
+	    ($file, $result) = split (":", $name, 2);
+	    @dataerr = (@dataerr, $file);
+	    next RAWLIST;
+	}
+    }
+} else {
+    # load images directly from directory 
+    # this is not sufficient.  we need a better way to get a list of images for 
+    # a given run id (with the current MEF / SPLIT state correct).
+    # 
+    # probably we can just use imsearch -ccd 0
+    $rawdir = `gconfig -q -D RUNID $crunid RAWDIR`;
+    chop ($rawdir);
+    if ($rawdir eq "") {
+	print STDERR "can't find config entry TMPDIR\n";
+	exit 1;
+    }
+    @imlist = ();
+
+    # load in the MEF files (must be of format 123456x.fits)
+    @tlist = <$rawdir/*.fits>;
+    foreach $tname (@tlist) { 
+	if ((-f $tname) && ($tname =~ /\d\d\d\d\d\d\w.fits/)) { 
+	    @imlist = (@imlist, $tname); 
+	} 
+    }
+
+    # load in the SPLIT directories (must be of format 123456x)
+    @tlist = <$rawdir/???????>;
+    foreach $tname (@tlist) { 
+	if ((-d $tname) && ($tname =~ /\d\d\d\d\d\d\w/)) { 
+	    @imlist = (@imlist, $tname); 
+	} 
+    }
+}
+
+# load the QSO validated image list
+@qsovalid = ();
+if ($qrunid) { 
+    @qruns = split (" ", $qrunid);
+    @qsovalid = ();
+    foreach $id (@qruns) {
+	print STDERR "trying $id\n";
+	@answer = `select_val_xexp.sh -U qso_elixir -P op1eliw -qrunid $id`;
+	if ($?) {
+	    print STDERR "error in qso run ID\n";
+	    exit 1;
+	}
+	@qsovalid = (@qsovalid, @answer);
+    }
+}
+foreach $qname (@qsovalid) { chop ($qname); }
+
+if ($RETRY) {
+# evaluate the remaining entries in imlist & invalid:
+    @imlist = (@imlist, @invalid, @dataerr);
+    @invalid = ();
+    @dataerr = ();
+    
+  IMLIST:
+    foreach $name (@imlist) {
+	$answer = `ckvalid $name`;
+	if ($?) { print STDERR "error with $name\n"; }
+	chop ($answer);
+	
+	($file, $result) = split (" ", $answer, 2);
+	@words = split (" ", $answer);
+	
+	if ($words[1] eq "pass") {
+	    @valid = (@valid, $answer);
+	    next IMLIST;
+	}
+	
+	if ($result eq "binned image") {
+	    @subvalid = (@subvalid, $answer);
+	    next IMLIST;
+	}
+	
+	if ($result eq "sub-rastered image") {
+	    @subvalid = (@subvalid, $answer);
+	    next IMLIST;
+	}
+	
+	if ($result eq "wrong image type") {
+	    @subvalid = (@subvalid, $answer);
+	    next IMLIST;
+	}
+	
+	if ($result eq "can't open file") {
+	    @dataerr = (@dataerr, $answer);
+	    next IMLIST;
+	}
+	
+	if ($result eq "no run ID") {
+	    @dataerr = (@dataerr, $answer);
+	    next IMLIST;
+	}
+	
+	if ($result eq "not a valid image") {
+	    @dataerr = (@dataerr, $answer);
+	    next IMLIST;
+	}
+	
+	if ($words[1] eq "fail") {
+	    foreach $line (@qsovalid) {
+		($qname, $qmode, $emode) = split (" ", $line);
+		if ($name =~ /$qname/) {
+		    @invalid = (@invalid, $answer);
+		    next IMLIST;
+		}
+	    }
+	    @subvalid = (@subvalid, $answer);
+	    next IMLIST;
+	}
+	
+	print STDERR "unknown result $answer\n";
+	
+    }
+}
+
+@mode = ('valid',     'subvalid',      'invalid',     'dataerr');
+@code = ($MODE_VALID, $MODE_SUBVALID,  $MODE_INVALID, $MODE_DATAERR);
+
+for ($i = 0; $i < @mode; $i++) {
+    $mode = $mode[$i];
+    $code = $code[$i];
+
+    print STDOUT "$mode images\n";
+    foreach $file (@$mode) {
+	print STDOUT "$file\n";
+	if ($update) { 
+	    @w = split ("/", $file);
+	    $n = substr ($w[-1], 0, 6);
+	    vsystem ("update_xexpe.sh -U qso_elixir -P op1eliw --obsid $n --eval $code >> test.list");
+	}
+    }
+    print STDOUT "\n";
+}
+
+sub vsystem {
+    print STDERR "@_\n";
+    my($status) = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
Index: /tags/start/Ohana/src/perl/src/.mana
===================================================================
--- /tags/start/Ohana/src/perl/src/.mana	(revision 12606)
+++ /tags/start/Ohana/src/perl/src/.mana	(revision 12606)
@@ -0,0 +1,62 @@
+03/01/30 10:35:41: create x 0 10
+03/01/30 10:35:43: echo x[00]
+03/01/30 10:35:45: echo x[05]
+03/01/30 10:36:42: quit
+03/01/30 11:20:28: quit
+03/02/03 17:18:52: echo {169*12}
+03/02/03 17:18:59: echo {169*12*2*4}
+03/02/03 17:19:32: echo {1.5*3600}
+03/02/03 17:20:21: echo {18000*2/(1.5*3600)}
+03/02/03 17:21:28: echo {(1.5*3600)*6*2400}
+03/02/03 17:21:38: echo {(1.5*3600)*6*2400/18000}
+03/02/03 17:25:08: keyword a FILTER
+03/02/03 17:25:15: buffers
+03/02/03 17:26:08: quit
+03/02/12 11:37:58: input /data/elixir2/elixir/config/mana/fringe.pro
+03/02/12 11:37:58: getfitpars /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.I.0.med.sublist /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.I.0.fitpar
+03/02/12 11:37:58: input /data/elixir2/elixir/config/mana/fringe.pro
+03/02/12 11:37:59: getfrstats /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.I.0.fitpar /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.I.0.med.statlist /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.I.0.med.imstats
+03/02/12 11:37:59: input /data/elixir2/elixir/config/mana/fringe.pro
+03/02/12 11:37:59: getfitpars /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.med.sublist /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.fitpar
+03/02/12 11:38:00: input /data/elixir2/elixir/config/mana/fringe.pro
+03/02/12 11:38:01: getfrstats /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.fitpar /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.med.statlist /data/koa/cfh12k/detdir/02Bk07/fringe/02Bk07.fringe.Z.0.med.imstats
+03/02/13 15:35:58: echo {3*60+35-42}
+03/02/13 15:36:17: echo {(144772896-130048976)/(3*60+35-42)}
+03/02/13 15:36:33: echo {(144772896-130048976)/(3*60+35-42)/60}
+03/02/13 15:46:29: quit
+03/02/24 12:38:44: input /data/elixir2/elixir/config/mana/modes.pro
+03/02/24 12:38:44: demodemap 679056p.detlist 679056p.demlist /data/elixir/cfh12k/detrend/modes/2001A.modes.I.12.01.fits 2001A.modes.I.12.01.fits 256
+03/02/24 12:39:58: input /data/elixir2/elixir/config/mana/fringe.pro
+03/02/24 12:39:58: applyfitstats /tmp/defringe.jIkAFy /tmp/defringe.M5q1Cw /tmp/defringe.qtNvpy
+03/02/24 12:44:23: input /data/elixir2/elixir/config/mana/modes.pro
+03/02/24 12:44:24: demodemap 679056p.detlist 679056p.demlist /data/elixir/cfh12k/detrend/modes/2001A.modes.I.12.01.fits 2001A.modes.I.12.01.fits 256
+03/02/24 12:45:37: input /data/elixir2/elixir/config/mana/fringe.pro
+03/02/24 12:45:37: applyfitstats /tmp/defringe.CRUK0I /tmp/defringe.7GdHiJ /tmp/defringe.NLcHKI
+03/05/21 14:39:11: rd a /data/elixir/detrend/cfh12k/scatter/2002A.scatter.R.03.00.fits
+03/05/21 14:39:14: mtva
+03/05/21 14:39:15: mtv a
+03/05/21 14:39:32: tv a 0.95 0.1
+03/05/21 14:39:44: set b = a
+03/05/21 14:39:47: rotate b flipx
+03/05/21 14:39:51: set c = a - b
+03/05/21 14:39:57: tv c -0.05 0.1
+03/05/21 14:40:07: tv c -0.005 0.01
+03/05/21 14:40:13: cur
+03/05/21 14:40:23: quit
+03/07/28 08:53:33: echo {(36-20)/50}
+03/07/28 08:53:46: echo {50/(36-20)}
+03/07/28 08:54:06: echo {1524*50/(36-20)}
+03/07/28 08:54:09: echo {1524*50/(36-20)/3600}
+03/07/28 08:54:43: rd a 653200p00.fits
+03/07/28 08:56:06: quit
+03/10/23 19:03:15: input /data/elixir2/srcdir/config/mana/modes.pro
+03/10/23 19:03:15: list names
+03/10/23 19:03:15: macro go
+03/10/23 19:03:15: go
+03/10/23 19:03:19: input /data/elixir2/srcdir/config/mana/modes.pro
+03/10/23 19:03:19: $CCDBINx = 2
+03/10/23 19:03:19: $CCDBINy = 5
+03/10/23 19:03:19: macro go
+03/10/23 19:03:20: go
+03/10/24 14:04:05: minterp
+03/10/24 14:09:51: quit
Index: /tags/start/Ohana/src/photdbc/Makefile
===================================================================
--- /tags/start/Ohana/src/photdbc/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/Makefile	(revision 12606)
@@ -0,0 +1,72 @@
+include ../../Configure
+HOME    =       $(ROOT)/src/photdbc
+CONFIG  =	$(ROOT)/config
+PROGRAM =       photdbc
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lohana -lFITS -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS)
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+SRCLIST = \
+$(SRC)/photdbc.$(ARCH).o	 \
+$(SRC)/initialize.$(ARCH).o	 \
+$(SRC)/ConfigInit.$(ARCH).o	 \
+$(SRC)/args.$(ARCH).o		 \
+$(SRC)/liststats.$(ARCH).o	 \
+$(SRC)/load_images.$(ARCH).o	 \
+$(SRC)/name_region.$(ARCH).o	 \
+$(SRC)/find_images.$(ARCH).o	 \
+$(SRC)/find_regions.$(ARCH).o	 \
+$(SRC)/get_regions.$(ARCH).o	 \
+$(SRC)/load_catalogs.$(ARCH).o	 \
+$(SRC)/gcatalog.$(ARCH).o 	 \
+$(SRC)/misc.$(ARCH).o		 \
+$(SRC)/time.$(ARCH).o		 \
+$(SRC)/join_stars.$(ARCH).o      \
+$(SRC)/unique_measures.$(ARCH).o \
+$(SRC)/flag_measures.$(ARCH).o   \
+$(SRC)/get_mags.$(ARCH).o        \
+$(SRC)/check_directory.$(ARCH).o \
+$(SRC)/subcatalog.$(ARCH).o      \
+$(SRC)/wcatalog.$(ARCH).o
+
+OBJ = $(SRCLIST)
+
+default: $(PROGRAM)
+
+$(SRCLIST): $(INC)/photdbc.h
+
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:	
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
Index: /tags/start/Ohana/src/photdbc/doc/notes.txt
===================================================================
--- /tags/start/Ohana/src/photdbc/doc/notes.txt	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/doc/notes.txt	(revision 12606)
@@ -0,0 +1,28 @@
+
+- select a region
+
+- load average / measure / secfilt / missing
+
+- construct subset based on selection criteria:
+  - Minst
+  - dMinst
+  - X,Y
+  - R,D
+
+- merge neighbor stars (join within X.X arcsec)
+
+- mark bad measurements:
+
+  - outside area
+  - Minst < cutoff
+  - Mcal > 0.015 (lookup from table?)
+
+  - subset for given filter (match by string?):
+    - 2x 3sigma 
+    - softened chisq > 3.0
+
+- mark objects with fewer than N measurements
+
+
+-----
+
Index: /tags/start/Ohana/src/photdbc/include/photdbc.h
===================================================================
--- /tags/start/Ohana/src/photdbc/include/photdbc.h	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/include/photdbc.h	(revision 12606)
@@ -0,0 +1,103 @@
+# include <ohana.h>
+# include <loneos.h>
+# include <signal.h>
+
+typedef struct {
+  int measure;          // pointer to measure entry
+  unsigned int averef;  // old measures come from multiple averages
+  float R, D;           // actual coordinates of this measure
+} Mpointer;
+
+typedef struct {
+  double median;
+  double mean;
+  double sigma;
+  double error;
+  double chisq;
+  double min;
+  double max;
+  double total;
+  int    Nmeas;
+} StatType;
+
+// need to get RADIUS from Config 
+
+/* global variables */
+int    SHOW_PARAMS;
+int    VERBOSE;
+double JOIN_RADIUS;
+double UNIQ_RADIUS;
+double DMCAL_MIN;;
+char   ImageCat[256];
+char   GSCFILE[256];
+char   CATDIR[256];
+char   PhotCodeFile[256];
+
+double RMIN;
+double RMAX;
+double DMIN;
+double DMAX;
+ 
+double XMIN;
+double XMAX;
+double YMIN;
+double YMAX;
+double MMIN;
+double MMAX;
+
+double DMSYS;
+double DMGAIN;
+double CHISQ_MAX;
+double SIGMA_MAX;
+int    NMEAS_MIN;
+
+PhotCodeData photcodes;
+
+# define FLAG_AREA            0X0001
+# define FLAG_MINST           0X0002
+# define FLAG_DMCAL           0x0004
+# define FLAG_SIGCLIP         0X0008
+# define FLAG_CHISQ           0x0010
+# define FLAG_TOOFEW          0x0020
+# define FLAG_DUPMEAS         0x0040
+
+Image        *find_images (GSCRegion *region, int Nregion, int *Nimages, int **LineNum); 
+GSCRegion    *find_regions (Image *image, int Nimage, int *Nregions, GSCRegion *fullregion); 
+Image        *get_images (int *N); 
+GSCRegion    *get_regions (double minRa, double maxRa, double minDec, double maxDec, int *Nregions); 
+Catalog      *load_catalogs (GSCRegion *region, int Nregion); 
+GSCRegion    *load_images (char *seed, int *nregion); 
+GSCRegion    *name_region (char *name, int *Nregions); 
+char         *sec_to_date (unsigned long second);
+void          ConfigInit (int *argc, char **argv); 
+int           Fseek (FILE *f, long offset, int whence);
+int           args (int argc, char **argv); 
+int           chk_time (char *line);
+int           corner_check (double *x1, double *y1, double *x2, double *y2); 
+int           dms_to_ddd (double *Value, char *string);
+int           edge_check (double *x1, double *y1, double *x2, double *y2); 
+void          flag_measures (Catalog *catalog); 
+int           gcatalog (Catalog *catalog); 
+void          get_mags (Catalog *catalog); 
+void          getfullregion (Image *image, int Nimage, GSCRegion *fullregion); 
+int           hms_to_deg (double *h0, double *h1, double *d0, double *d1, char *string); 
+void          initialize (int argc, char **argv); 
+void          initstats (char *mode); 
+void          join_stars (Catalog *catalog); 
+int           liststats (double *value, double *dvalue, int N, StatType *stats); 
+unsigned long jd_to_sec (double jd);
+unsigned long date_to_sec (char *date);
+double        opening_angle (double x1, double y1, double x2, double y2, double x3, double y3); 
+double        sec_to_jd (unsigned long second);
+void          set_ZP (double ZERO); 
+void          sortA (double *X, int N); 
+void          sortB (double *X, double *Y, int N); 
+void          sortC (double *X, double *Y, double *F1, double *F2, int N); 
+void          sortD (double *X, double *Y, double *Z, int N); 
+void          sort_lists (float *X, float *Y, int *index, int N); 
+void          sort_time (unsigned int *X, int *Y, int N); 
+int           str_to_dtime (char *line, double *second); 
+int           str_to_radec (double *ra, double *dec, char *str1, char *str2);
+int           str_to_time (char *line, unsigned int *second); 
+void          unique_measures (Catalog *catalog);
+void          wcatalog (Catalog *catalog);
Index: /tags/start/Ohana/src/photdbc/src/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/ConfigInit.c	(revision 12606)
@@ -0,0 +1,71 @@
+# include "photdbc.h"
+
+int success = TRUE;
+
+void WarnConfig (char *config, char *key, char * mode, int N, void *var) {
+  if (!ScanConfig (config, key, mode, N, var)) {
+    fprintf (stderr, "missing config variable %s\n", key);
+    success = FALSE;
+  }
+}
+
+void ConfigInit (int *argc, char **argv) {
+
+  double ZERO_POINT, tmp;
+  char *config, *file;
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  WarnConfig (config, "JOIN_RADIUS",            "%lf", 0, &JOIN_RADIUS);
+  WarnConfig (config, "UNIQ_RADIUS",            "%lf", 0, &UNIQ_RADIUS);
+
+  WarnConfig (config, "XMIN",                   "%lf", 0, &XMIN);
+  WarnConfig (config, "XMAX",                   "%lf", 0, &XMAX);
+  WarnConfig (config, "YMIN",                   "%lf", 0, &YMIN);
+  WarnConfig (config, "YMAX",                   "%lf", 0, &YMAX);
+
+  WarnConfig (config, "RMIN",                   "%lf", 0, &RMIN);
+  WarnConfig (config, "RMAX",                   "%lf", 0, &RMAX);
+  WarnConfig (config, "DMIN",                   "%lf", 0, &DMIN);
+  WarnConfig (config, "DMAX",                   "%lf", 0, &DMAX);
+
+  WarnConfig (config, "DMCAL_MIN",              "%lf", 0, &tmp);  DMCAL_MIN = 1000*tmp;
+  WarnConfig (config, "MMIN",                   "%lf", 0, &tmp);  MMIN      = 1000*tmp;
+  WarnConfig (config, "MMAX",                   "%lf", 0, &tmp);  MMAX      = 1000*tmp;
+  WarnConfig (config, "DMSYS",                  "%lf", 0, &tmp);  DMSYS     = SQ(1000*tmp);
+  WarnConfig (config, "DMGAIN",                 "%lf", 0, &DMGAIN); 
+  WarnConfig (config, "SIGMA_MAX",              "%lf", 0, &SIGMA_MAX); SIGMA_MAX *= 1000;
+
+  WarnConfig (config, "CHISQ_MAX",              "%lf", 0, &CHISQ_MAX);
+  WarnConfig (config, "NMEAS_MIN",              "%d",  0, &NMEAS_MIN);
+
+  WarnConfig (config, "IMAGE_CATALOG",          "%s",  0, ImageCat);
+  WarnConfig (config, "GSCFILE",                "%s",  0, GSCFILE);
+  WarnConfig (config, "CATDIR",                 "%s",  0, CATDIR);
+  WarnConfig (config, "PHOTCODE_FILE",          "%s",  0, PhotCodeFile);
+  WarnConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
+
+  if (!success) { 
+    fprintf (stderr, "missing config parameter\n");
+    exit (1);
+  }
+
+  SetZeroPoint (ZERO_POINT);
+
+  if (!LoadPhotcodes (PhotCodeFile)) {
+    fprintf (stderr, "error loading photcodes\n");
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+
+}
Index: /tags/start/Ohana/src/photdbc/src/args.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/args.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/args.c	(revision 12606)
@@ -0,0 +1,25 @@
+# include "photdbc.h"
+
+int args (int argc, char **argv) {
+
+  int N;
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  SHOW_PARAMS = FALSE;
+  if ((N = get_argument (argc, argv, "-params"))) {
+    remove_argument (N, &argc, argv);
+    SHOW_PARAMS = TRUE;
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: photdbc (region)\n");
+    exit (2);
+  } 
+
+}
+
Index: /tags/start/Ohana/src/photdbc/src/check_directory.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/check_directory.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/check_directory.c	(revision 12606)
@@ -0,0 +1,64 @@
+# include "photdbc.h"
+
+check_directory (char *basefile) {
+  
+  FILE *f;
+  char *c, dir[256], filename[256];
+  struct stat filestat;
+  uid_t fuid, uid;
+  gid_t fgid, gid;
+  int status, cmode;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to write to directory */
+  sprintf (filename, "%s\0", basefile);
+  c = strrchr (filename, '/');
+  if (c == (char *) NULL) {
+    strcpy (dir, ".");
+  } else {
+    *c = 0;
+    strcpy (dir, filename);
+  }
+  status = stat (dir, &filestat);
+  if (status == -1) {
+    fprintf (stderr, "directory %s does not exist, creating...\n", dir);
+    cmode = S_IRWXU | S_IRWXG | S_IRWXO;
+    status = mkdir (dir, cmode);
+    if (status == -1) {
+      fprintf (stderr, "ERROR: can't create %s\n", dir);
+      exit (1);
+    }
+  } 
+  status = stat (dir, &filestat);
+  if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRWXU)) ||
+      ((gid == filestat.st_gid) && (filestat.st_mode & S_IRWXG)) || 
+      (filestat.st_mode & S_IRWXO)) {
+  } else {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (1);
+  }
+}
+
+/* uses cp only */
+make_backup (char *filename) {
+
+  int status, cmode;
+  struct stat filestat;
+  char line [256];
+
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, make backup copy */
+    sprintf (line, "cp %s %s~\0", filename, filename);
+    status = system (line);
+    if (status) {
+      fprintf (stderr, "ERROR: unable to create %s~, exiting\n", filename);
+      exit (1);
+    }
+    cmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    sprintf (line, "%s~\0", filename);
+    chmod (line, cmode);
+  }
+  
+}
Index: /tags/start/Ohana/src/photdbc/src/find_images.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/find_images.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/find_images.c	(revision 12606)
@@ -0,0 +1,237 @@
+# include "photdbc.h"
+
+/* this function returns a list of all images which overlap the given
+   set of region files.  All images in the image catalog are tested
+   once, so there is no check that an image already has been included.
+   LineNum stores the locations in the Image database of the list of
+   images */
+
+Image *find_images (GSCRegion *region, int Nregion, int *Nimages, int **LineNum) {
+  
+  Header header;
+  Image *timage, *image;
+  int i, j, k, m, found, nimage, Nimage, NIMAGE, NTIMAGE, Nloop, Nlast;
+  int n, Nim, status, InRange, np, Np;
+  FILE *f;
+  double Xc[5], Yc[5], Xi[5], Yi[5], r, d, dx, dy;
+  char line[256];
+  int *line_number;
+  Coords tcoords;
+
+  if (VERBOSE) fprintf (stderr, "finding images\n");
+
+  /* we make positional comparisons in the projection of catalog */
+  tcoords.crval1 = 0.5*(region[0].RA[0]  + region[0].RA[1]);
+  tcoords.crval2 = 0.5*(region[0].DEC[0] + region[0].DEC[1]);
+  tcoords.crpix1 = tcoords.crpix2 = 0.0;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1  = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2  = tcoords.pc2_1 = 0.0;
+  strcpy (tcoords.ctype, "RA---TAN");
+
+  /* check if image datafile exists, get header, number of images */
+  if (!fits_read_header (ImageCat, &header)) {
+    fprintf (stderr, "ERROR: No images in catalog %s (1)\n", ImageCat);
+    exit (0);
+  }
+  Nimage = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+  if (Nimage == 0) {
+    fprintf (stderr, "ERROR: No images in catalog %s (1)\n", ImageCat);
+    exit (0);
+  }
+
+  /* get ready to read data on images */ 
+  f = fopen (ImageCat, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: trouble opening Image catalog: %s (2)\n", ImageCat);
+    exit (0);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* load all images */
+  ALLOCATE (timage, Image, Nimage);
+  status = Fread (timage, sizeof(Image), Nimage, f, "image");
+  if (status != Nimage) {
+    fprintf (stderr, "ERROR: couldn't read images from image catalog: %s\n", ImageCat);
+    exit (0);
+  }
+
+  nimage = 0;
+  NIMAGE = 100;
+  ALLOCATE (image, Image, NIMAGE);
+  ALLOCATE (line_number, int, NIMAGE);
+  
+  for (i = 0; i < Nimage; i++) {
+      
+# if (0)
+    /* select images by photcode */
+    np = timage[i].source;
+    Np = photcodes.hashcode[np];
+    if (Np < 0) continue;
+    if (photcodes.code[Np].equiv != PHOTCODE) continue;
+
+    /* select images by time */
+    if (TimeSelect) {
+      if (timage[i].tzero < TSTART) continue;
+      if (timage[i].tzero > TSTOP) continue;
+    }
+# endif
+    
+    /* define image corners */
+    Xi[0] = 0;            Yi[0] = 0;
+    Xi[1] = timage[i].NX; Yi[1] = 0;
+    Xi[2] = timage[i].NX; Yi[2] = timage[i].NY;
+    Xi[3] = 0;            Yi[3] = timage[i].NY;
+    Xi[4] = 0;            Yi[4] = 0;
+    found = FALSE;
+    /* transform to tcoords */
+    for (j = 0; j < 5; j++) {
+      XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+      InRange = RD_to_XY (&Xi[j], &Yi[j], r, d, &tcoords);
+      if (!InRange) goto imskip;
+    }
+    /* compare with each region file */
+    for (m = 0; (m < Nregion) && !found; m++) { 
+      /* define catalog corners */
+      Xc[0] = region[m].RA[0]; Yc[0] = region[m].DEC[0];
+      Xc[1] = region[m].RA[1]; Yc[1] = region[m].DEC[0];
+      Xc[2] = region[m].RA[1]; Yc[2] = region[m].DEC[1];
+      Xc[3] = region[m].RA[0]; Yc[3] = region[m].DEC[1];
+      Xc[4] = region[m].RA[0]; Yc[4] = region[m].DEC[0];
+      for (j = 0; j < 5; j++) {
+	r = Xc[j]; d = Yc[j];
+	RD_to_XY (&Xc[j], &Yc[j], r, d, &tcoords);
+      }
+      dx = 0.02*(Xc[2] - Xc[0]);
+      dy = 0.02*(Yc[2] - Yc[0]);
+      Xc[0] -= dx; Yc[0] -= dy;
+      Xc[1] += dx; Yc[1] -= dy;
+      Xc[2] += dx; Yc[2] += dy;
+      Xc[3] -= dx; Yc[3] += dy;
+      Xc[4] -= dx; Yc[4] -= dy;
+      
+      /* check if image corner inside catalog */
+      for (j = 0; (j < 4) && !found; j++) {
+	found |= corner_check (&Xi[j], &Yi[j], &Xc[0], &Yc[0]);
+      }
+      /* check if catalog corner inside image */
+      for (j = 0; (j < 4) && !found; j++) {
+	found |= corner_check (&Xc[j], &Yc[j], &Xi[0], &Yi[0]);
+      }
+      /* check if edges cross */
+      for (j = 0; (j < 4) && !found; j++) {
+	for (k = 0; (k < 4) && !found; k++) {
+	  found |= edge_check (&Xi[j], &Yi[j], &Xc[k], &Yc[k]);
+	}
+      }
+      if (found) {
+	image[nimage] = timage[i]; 
+	if (image[nimage].code == ID_IMAGE_NOCAL) {
+	  image[nimage].code &= ~ID_IMAGE_NOCAL;
+	}	    
+	line_number[nimage] = i;
+	nimage ++;
+	if (nimage == NIMAGE) {
+	  NIMAGE += 100;
+	  REALLOCATE (image, Image, NIMAGE);
+	  REALLOCATE (line_number, int, NIMAGE);
+	}
+      }
+    }
+  imskip:
+  }
+      
+  if (VERBOSE) fprintf (stderr, "found %d images\n", nimage);
+
+  /* we are going to use image[nimage] to represent images not in the database:
+     these are measurements from external sources, like USNO */
+
+  assignMcal (&image[nimage], (double *) NULL, -1);
+  image[nimage].code = ID_IMAGE_NEW;
+  
+  REALLOCATE (image, Image, MAX (nimage + 1, 1));
+  REALLOCATE (line_number, int, MAX (nimage + 1, 1));
+  free (timage);
+  *Nimages = nimage;
+  *LineNum = line_number;
+  fclose (f);
+  return (image);
+}
+
+/* check if line between points 0 and 1 of x1
+   crosses line between points 0 and 1 of x2 */
+int edge_check (double *x1, double *y1, double *x2, double *y2) {
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+/* check if point x1,y1 is in box formed by x2[0-4] */
+int corner_check (double *x1, double *y1, double *x2, double *y2) {
+
+  int i;
+  double theta;
+
+  theta = 0;
+
+  for (i = 0; i < 4; i++) {
+    theta += opening_angle (x2[i], y2[i], x1[0], y1[0], x2[i+1], y2[i+1]); 
+  }
+  if (fabs(theta) > 6) {
+    return (TRUE);
+  } else {
+    return (FALSE);
+  }
+}
+
+/* returns the opening angle between the three points (2 is in middle) 
+   in range -pi to pi */
+
+double opening_angle (double x1, double y1, double x2, double y2, double x3, double y3) {
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
+
Index: /tags/start/Ohana/src/photdbc/src/find_regions.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/find_regions.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/find_regions.c	(revision 12606)
@@ -0,0 +1,102 @@
+# include "photdbc.h"
+
+/* given a list of images, find all region files which overlap these images.
+   if a region file does not exist, we should recognize this fact somehow */
+
+GSCRegion *find_regions (Image *image, int Nimage, int *Nregions, GSCRegion *fullregion) {
+
+  int i, nregions;
+  double x, y;
+  GSCRegion *regions;
+  double MinRA, MaxRA, MinDEC, MaxDEC, ra, dec;
+
+  if (VERBOSE) fprintf (stderr, "finding regions: ");
+  
+  /* find RA and DEC range of images */
+  MinRA = MinDEC = +361;
+  MaxRA = MaxDEC = -361;
+  for (i = 0; i < Nimage; i++) {
+    for (x = 0.0; x <= 1.0; x+=0.25) {
+      for (y = 0.0; y <= 1.0; y+=0.25) {
+	XY_to_RD (&ra, &dec, image[i].NX*(1.1*x - 0.05), image[i].NY*(1.1*y - 0.05), &image[i].coords);
+	MinRA = MIN (ra, MinRA);
+	MaxRA = MAX (ra, MaxRA);
+	MinDEC = MIN (dec, MinDEC);
+	MaxDEC = MAX (dec, MaxDEC);
+      }
+    }
+  }
+
+  /* if images overlap 0,360 boundary, then use -180 to +180 range */
+  if (MaxRA - MinRA > 180) {
+    MinRA = +361;
+    MaxRA = -361;
+    for (i = 0; i < Nimage; i++) {
+      for (x = 0.0; x <= 1.0; x+=0.25) {
+	for (y = 0.0; y <= 1.0; y+=0.25) {
+	  XY_to_RD (&ra, &dec, image[i].NX*(1.1*x - 0.05), image[i].NY*(1.1*y - 0.05), &image[i].coords);
+	  if (ra > 180) ra -= 360;
+	  MinRA = MIN (ra, MinRA);
+	  MaxRA = MAX (ra, MaxRA);
+	}
+      }
+    }
+  }
+
+  fullregion[0].RA[0] = MinRA;
+  fullregion[0].RA[1] = MaxRA;
+  fullregion[0].DEC[0] = MinDEC;
+  fullregion[0].DEC[1] = MaxDEC;
+
+  /* find all region files containing specified ra, dec range */  
+  regions = get_regions (MinRA, MaxRA, MinDEC, MaxDEC, &nregions);
+
+  if (VERBOSE) fprintf (stderr, "%d found\n", nregions);
+
+  *Nregions = nregions;
+  return (regions);
+}
+
+
+void getfullregion (Image *image, int Nimage, GSCRegion *fullregion) {
+
+  int i;
+  double x, y;
+  double MinRA, MaxRA, MinDEC, MaxDEC, ra, dec;
+
+  /* find RA and DEC range of images */
+  MinRA = MinDEC = +361;
+  MaxRA = MaxDEC = -361;
+  for (i = 0; i < Nimage; i++) {
+    for (x = 0.0; x <= 1.0; x+=0.25) {
+      for (y = 0.0; y <= 1.0; y+=0.25) {
+	XY_to_RD (&ra, &dec, image[i].NX*(1.1*x - 0.05), image[i].NY*(1.1*y - 0.05), &image[i].coords);
+	MinRA = MIN (ra, MinRA);
+	MaxRA = MAX (ra, MaxRA);
+	MinDEC = MIN (dec, MinDEC);
+	MaxDEC = MAX (dec, MaxDEC);
+      }
+    }
+  }
+
+  /* if images overlap 0,360 boundary, then use -180 to +180 range */
+  if (MaxRA - MinRA > 180) {
+    MinRA = +361;
+    MaxRA = -361;
+    for (i = 0; i < Nimage; i++) {
+      for (x = 0.0; x <= 1.0; x+=0.25) {
+	for (y = 0.0; y <= 1.0; y+=0.25) {
+	  XY_to_RD (&ra, &dec, image[i].NX*(1.1*x - 0.05), image[i].NY*(1.1*y - 0.05), &image[i].coords);
+	  if (ra > 180) ra -= 360;
+	  MinRA = MIN (ra, MinRA);
+	  MaxRA = MAX (ra, MaxRA);
+	}
+      }
+    }
+  }
+
+  fullregion[0].RA[0] = MinRA;
+  fullregion[0].RA[1] = MaxRA;
+  fullregion[0].DEC[0] = MinDEC;
+  fullregion[0].DEC[1] = MaxDEC;
+}
Index: /tags/start/Ohana/src/photdbc/src/flag_measures.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/flag_measures.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/flag_measures.c	(revision 12606)
@@ -0,0 +1,203 @@
+# include "photdbc.h"
+
+void flag_measures (Catalog *catalog) {
+
+  int i, j, k, m, n, N, found;
+  int *imagelink, Nimage, Nmeasure, Nlist, PhotNsec;
+  unsigned int Time;
+  int Ncode, Photcode, Minst, Mag, BAD_MEASURE;
+  double ra, dec, x, y, Nsigma;
+  double *list, *dlist;
+
+  Image *image;
+  StatType stats;
+
+  if (VERBOSE) fprintf (stderr, "flagging bad measurements\n");
+
+  /* load images */
+  image = get_images (&Nimage);
+
+  PhotNsec = GetPhotcodeNsecfilt ();
+  /* need to replace dMcal with values from external table? */
+
+  /* clear existing measure flags */
+  for (i = 0; i < catalog[0].Nmeasure; i++) catalog[0].measure[i].flags = 0;
+
+  /* generate image index */
+  ALLOCATE (imagelink, int, catalog[0].Nmeasure);
+  for (i = 0; i < catalog[0].Nmeasure; i++) {
+    n = catalog[0].measure[i].averef;
+    Time = catalog[0].measure[i].t;
+    Photcode = catalog[0].measure[i].source;
+    found = FALSE;
+    for (k = 0; !found && (k < Nimage); k++) { 
+      if ((Time == image[k].tzero) && (Photcode == image[k].source)) {
+	imagelink[i] = k;
+	found = TRUE;
+      }
+    }
+    if (!found) {
+      /* some error? */
+    }
+  }
+
+  /* flag by area : find source image, get X,Y coords, set flag */
+  for (i = 0; i < catalog[0].Nmeasure; i++) {
+    n = catalog[0].measure[i].averef;
+    ra  = catalog[0].average[n].R - catalog[0].measure[i].dR / 360000.0;
+    dec = catalog[0].average[n].D - catalog[0].measure[i].dD / 360000.0;
+    k = imagelink[i];
+    RD_to_XY (&x, &y, ra, dec, &image[k].coords);
+    if (x < XMIN) goto flagarea;
+    if (x > XMAX) goto flagarea;
+    if (y < YMIN) goto flagarea;
+    if (y > YMAX) goto flagarea;
+    continue;
+  flagarea:
+    catalog[0].measure[i].flags |= FLAG_AREA;
+  }
+
+  /* flag by Minst */
+  for (i = 0; i < catalog[0].Nmeasure; i++) {
+    Minst = iPhotInst (&catalog[0].measure[i]);
+    if (Minst < MMIN) goto flagminst;
+    if (Minst > MMAX) goto flagminst;
+    continue;
+  flagminst:
+    catalog[0].measure[i].flags |= FLAG_MINST;
+  }
+
+  /* flag by image (dMcal? time from table?) */
+  for (i = 0; i < catalog[0].Nmeasure; i++) {
+    k = imagelink[i];
+    if (image[k].dMcal > DMCAL_MIN) {
+      catalog[0].measure[i].flags |= FLAG_DMCAL;
+    }
+  }
+
+  /* allocate a list for temp storage of mag values */
+  Nlist = 0;
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    Nlist = MAX (Nlist, catalog[0].average[i].Nm);
+  }
+  ALLOCATE (list, double, Nlist);
+  ALLOCATE (dlist, double, Nlist);
+  initstats ("MEAN");
+
+  /* the following sections apply only to PRI/SEC photcodes */
+  for (n = 0; n < photcodes.Ncode; n++) {
+    if (photcodes.code[n].type == PHOT_DEP) continue;
+    if (photcodes.code[n].type == PHOT_REF) continue;
+    Photcode = photcodes.code[n].code;
+    
+    BAD_MEASURE = FLAG_AREA | FLAG_MINST | FLAG_DMCAL;
+    /* 2x 3sigma clipping */
+    for (i = 0; i < catalog[0].Naverage; i++) {
+
+      /* extract good measures, calculate stats */
+      N = 0;
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	if ((Ncode = photcodes.hashcode[catalog[0].measure[m].source]) < 0) continue;
+	if (photcodes.code[Ncode].equiv != Photcode) continue;
+	if (photcodes.code[Ncode].type != PHOT_DEP) continue;
+	if (catalog[0].measure[m].flags & BAD_MEASURE) continue;
+	list[N] = iPhotRel (&catalog[0].measure[m], &catalog[0].average[i],  &catalog[0].secfilt[i*PhotNsec]);
+	dlist[N] = sqrt (SQ(DMGAIN*catalog[0].measure[m].dM) + DMSYS);
+	N++;
+      }
+      if (N < 3) continue;
+      liststats (list, dlist, N, &stats);
+      Nsigma = 3.0;
+      if (N < 10) Nsigma = 0.9*N / sqrt (N - 1);
+
+      /* re-extract good measures, calculate stats */
+      N = 0;
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	if ((Ncode = photcodes.hashcode[catalog[0].measure[m].source]) < 0) continue;
+	if (photcodes.code[Ncode].equiv != Photcode) continue;
+	if (photcodes.code[Ncode].type != PHOT_DEP) continue;
+	if (catalog[0].measure[m].flags & BAD_MEASURE) continue;
+	Mag = iPhotRel (&catalog[0].measure[m], &catalog[0].average[i],  &catalog[0].secfilt[i*PhotNsec]);
+	if (fabs(Mag - stats.mean) > Nsigma*stats.sigma) continue;
+	list[N]  = Mag;
+	dlist[N] = sqrt (SQ(DMGAIN*catalog[0].measure[m].dM) + DMSYS);
+	N++;
+      }
+      if (N > 2) liststats (list, dlist, N, &stats);
+
+      /* flag bad measures */
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	if ((Ncode = photcodes.hashcode[catalog[0].measure[m].source]) < 0) continue;
+	if (photcodes.code[Ncode].equiv != Photcode) continue;
+	if (photcodes.code[Ncode].type != PHOT_DEP) continue;
+	Mag = iPhotRel (&catalog[0].measure[m], &catalog[0].average[i],  &catalog[0].secfilt[i*PhotNsec]);
+	if (fabs(Mag - stats.mean) > Nsigma*stats.sigma) catalog[0].measure[m].flags |= FLAG_SIGCLIP;
+      }
+    }      
+  
+    BAD_MEASURE = FLAG_AREA | FLAG_MINST | FLAG_DMCAL | FLAG_SIGCLIP;
+    /* flag variables */
+    for (i = 0; i < catalog[0].Naverage; i++) {
+      /* extract good measures, calculate chisq */
+      N = 0;
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	if ((Ncode = photcodes.hashcode[catalog[0].measure[m].source]) < 0) continue;
+	if (photcodes.code[Ncode].equiv != Photcode) continue;
+	if (photcodes.code[Ncode].type != PHOT_DEP) continue;
+	if (catalog[0].measure[m].flags & BAD_MEASURE) continue;
+	list[N] = iPhotRel (&catalog[0].measure[m], &catalog[0].average[i],  &catalog[0].secfilt[i*PhotNsec]);
+	dlist[N] = sqrt (SQ(DMGAIN*catalog[0].measure[m].dM) + DMSYS);
+	N++;
+      }
+      liststats (list, dlist, N, &stats);
+      if (stats.chisq < CHISQ_MAX) continue;
+
+      /* flag bad measures */
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	if ((Ncode = photcodes.hashcode[catalog[0].measure[m].source]) < 0) continue;
+	if (photcodes.code[Ncode].equiv != Photcode) continue;
+	if (photcodes.code[Ncode].type != PHOT_DEP) continue;
+	catalog[0].measure[m].flags |= FLAG_CHISQ;
+      }
+    }	
+
+    /* flag too few valid measures */
+    BAD_MEASURE = FLAG_AREA | FLAG_MINST | FLAG_DMCAL | FLAG_SIGCLIP | FLAG_CHISQ;
+    for (i = 0; i < catalog[0].Naverage; i++) {
+      N = 0;
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	if ((Ncode = photcodes.hashcode[catalog[0].measure[m].source]) < 0) continue;
+	if (photcodes.code[Ncode].equiv != Photcode) continue;
+	if (photcodes.code[Ncode].type != PHOT_DEP) continue;
+	if (catalog[0].measure[m].flags & BAD_MEASURE) continue;
+	N++;
+      }
+      if (N == 0) continue; // only flag objects with valid measurements, but too few
+      if (N >= NMEAS_MIN) continue;
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	if ((Ncode = photcodes.hashcode[catalog[0].measure[m].source]) < 0) continue;
+	if (photcodes.code[Ncode].equiv != Photcode) continue;
+	if (photcodes.code[Ncode].type != PHOT_DEP) continue;
+	catalog[0].measure[m].flags |= FLAG_TOOFEW;
+      }
+    }	
+  }
+}
+
+
+/* notes
+   
+   flag by area: uses an inefficient search for the image.  
+   images should be sorted by time and we should use bisection
+   
+   number of loops over Nmeasure: 9
+
+*/
+
Index: /tags/start/Ohana/src/photdbc/src/gcatalog.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/gcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/gcatalog.c	(revision 12606)
@@ -0,0 +1,22 @@
+# include "photdbc.h"
+
+int gcatalog (Catalog *catalog) {
+  
+  char mode, status;
+
+  mode = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+
+  if (!load_catalog (catalog, mode, VERBOSE)) {
+    fprintf (stderr, "ERROR: failure loading catalog %s\n", catalog[0].filename);
+    exit (1);
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "read %d stars from catalog file %s (%d measurements)\n", 
+	     catalog[0].Naverage, catalog[0].filename, catalog[0].Nmeasure);
+  }
+  return (TRUE);
+}
+
+
+
Index: /tags/start/Ohana/src/photdbc/src/get_mags.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/get_mags.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/get_mags.c	(revision 12606)
@@ -0,0 +1,65 @@
+# include "photdbc.h"
+
+void get_mags (Catalog *catalog) {
+
+  int i, j, m, n, N;
+  int Nlist, Nsec, Nsecfilt, Ncode;
+  short int *Mval;
+  int Photcode, BAD_MEASURE;
+  double *list, *dlist;
+  StatType stats;
+
+  if (VERBOSE) fprintf (stderr, "re-calculating photometry\n");
+
+  BAD_MEASURE = FLAG_AREA | FLAG_MINST | FLAG_SIGCLIP | FLAG_CHISQ | FLAG_TOOFEW;
+  Nsecfilt = catalog[0].Nsecfilt;
+
+  /* allocate a list for temp storage of mag values */
+  Nlist = 0;
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    Nlist = MAX (Nlist, catalog[0].average[i].Nm);
+    catalog[0].average[i].M  = NO_MAG;
+    catalog[0].average[i].dM = NO_MAG;
+    catalog[0].average[i].Xm = NO_MAG;
+    for (j = 0; j < Nsecfilt; j++) {
+      catalog[0].secfilt[i*Nsecfilt+j].M  = NO_MAG;
+      catalog[0].secfilt[i*Nsecfilt+j].dM = NO_MAG;
+      catalog[0].secfilt[i*Nsecfilt+j].Xm = NO_MAG;
+    }
+  }
+  ALLOCATE (list, double, Nlist);
+  ALLOCATE (dlist, double, Nlist);
+  initstats ("WT_MEAN");
+
+  /* check on photcode */
+  for (n = 0; n < photcodes.Ncode; n++) {
+    if (photcodes.code[n].type == PHOT_DEP) continue;
+    if (photcodes.code[n].type == PHOT_REF) continue;
+    Photcode = photcodes.code[n].code;
+    Nsec = photcodes.hashNsec[Photcode];
+
+    /* find average magnitudes */
+    for (i = 0; i < catalog[0].Naverage; i++) {
+      N = 0;
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	if ((Ncode = photcodes.hashcode[catalog[0].measure[m].source]) < 0) continue;
+	if (photcodes.code[Ncode].equiv != Photcode) continue;
+	if (photcodes.code[Ncode].type != PHOT_DEP) continue;
+	if (catalog[0].measure[m].flags & BAD_MEASURE) continue;
+	list[N] = PhotRel (&catalog[0].measure[m], &catalog[0].average[i],  &catalog[0].secfilt[i*Nsecfilt]);
+	dlist[N] = sqrt (SQ(DMGAIN*catalog[0].measure[m].dM) + DMSYS);
+	N++;
+      }
+      liststats (list, dlist, N, &stats);
+      if (N < 1) continue;
+    
+      Mval = (Nsec == -1) ? &catalog[0].average[i].M : &catalog[0].secfilt[i*Nsecfilt+Nsec].M;
+      *Mval = stats.mean;
+      Mval = (Nsec == -1) ? &catalog[0].average[i].dM : &catalog[0].secfilt[i*Nsecfilt+Nsec].dM;
+      *Mval = stats.sigma;
+      Mval = (Nsec == -1) ? &catalog[0].average[i].Xm : &catalog[0].secfilt[i*Nsecfilt+Nsec].Xm;
+      *Mval = 100.0*log10(stats.chisq);
+    }
+  }
+}
Index: /tags/start/Ohana/src/photdbc/src/get_regions.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/get_regions.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/get_regions.c	(revision 12606)
@@ -0,0 +1,208 @@
+# include "photdbc.h"
+double BigDecBounds[] = {0.0, 7.5, 15.0, 22.5, 30.0, 37.5, 45.0, 
+			 52.5, 60.0, 67.5, 75.0, 82.5, 90.0,
+			 0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, 
+			 -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+
+double Areas[] = {2700.0, 2665.4505, 2563.567, 2399.5344, 2181.6343, 1920.7299, 1629.5942, 1322.1251, 1012.5, 714.32555, 439.83856, 199.21043, 0.0,
+		  2700.0, 2665.4505, 2563.567, 2399.5344, 2181.6343, 1920.7299, 1629.5942, 1322.1251, 1012.5, 714.32555, 439.83856, 199.21043, 0.0};
+
+char *DecSections[] = {"N0000", "N0730", "N1500", "N2230", "N3000", "N3730", "N4500", 
+		       "N5230", "N6000", "N6730", "N7500", "N8230", "weirdness", 
+		       "S0000", "S0730", "S1500", "S2230", "S3000", "S3730", "S4500", 
+		       "S5230", "S6000", "S6730", "S7500", "S8230", "weirdness"};
+
+char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			"n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			"s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			"s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+char *disk[] = {"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", 
+		"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "weirdness", 
+		"disk 1", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", 
+		"disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "weirdness"};
+
+int NBigRASections [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3, 48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3};
+
+int NDecLines[] = {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 24, 
+                   0, 597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48};
+
+/* returns a list of region files within the desired RA, DEC region */
+GSCRegion *get_regions (double minRa, double maxRa, double minDec, double maxDec, int *Nregions) {
+  
+  char buffer[28800], temp[50];
+  GSCRegion *regions;
+  FILE *f;
+  double RA0, RA1, DEC0, DEC1;
+  int i, j, NBigDec;
+  int NLINES, done, NREGIONS, nregions;
+  
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find regions file %s\n", GSCFILE);
+    exit (0);
+  }
+  
+  NREGIONS = 50;
+  ALLOCATE (regions, GSCRegion, NREGIONS);
+  nregions = 0;
+
+  if ((minDec <= -90) || (maxDec >= 90)) {
+    minRa = 0;
+    maxRa = 360;
+  }
+  
+  /* use the pole regions, if near pole */
+  if (maxDec > 86.25) {
+    sprintf (regions[nregions].filename, "n8230/pole.cpt\0");
+    regions[nregions].RA[0] = 0;
+    regions[nregions].RA[1] = 360;
+    regions[nregions].DEC[0] = 86.25;
+    regions[nregions].DEC[1] = 90.0;
+    nregions ++;
+    if (nregions == NREGIONS) {
+      NREGIONS += 50;
+      REALLOCATE (regions, GSCRegion, NREGIONS);
+    }
+  }
+
+  if (minDec > 86.25) {
+    *Nregions = nregions;
+    return (regions);
+  }
+    
+  if ((minDec < 0) && (maxDec > 0)) {
+    /* Search Both Sides */
+    NBigDec = 0;
+  } else {
+    /* find large DEC region (directory) */
+    NBigDec = -1;
+    for (i = 0; i < 12; i++) {
+      if ((minDec >= BigDecBounds[i]) && (minDec < BigDecBounds[i+1])) {
+	NBigDec = i;
+	break;
+      }
+    }
+    if (NBigDec < 0) {
+      for (i = 13; i < 24; i++) {
+	if ((maxDec < BigDecBounds[i]) && (maxDec >= BigDecBounds[i+1])) {
+	  NBigDec = i;
+	  break;
+	}
+      }
+    }
+  }
+  if (NBigDec < 0) {
+    fprintf (stderr, "ERROR: Dec out of range: %f\n", minDec);
+    *Nregions = 0;
+    return ((GSCRegion *) NULL);
+  }
+  
+  /* count lines before section */
+  NLINES = 0;
+  for (i = 0; i < NBigDec; i++) {
+    NLINES += NDecLines[i];
+  }
+  fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+  
+  /* should be in this section.  if not, there is a problem counting... */
+  /* careful with the 0,360.0 boundary **/
+  done = FALSE;
+  for (j = 0; !done && (NBigDec + j < 25); j++) {
+    fread (buffer, 48*NDecLines[NBigDec + j], 1, f);
+    for (i = 0; (i < NDecLines[NBigDec + j]); i++) {
+      strncpy (temp, &buffer[i*48], 48);
+      temp[49] = 0;
+      hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+      if (RA1 < RA0) RA1 += 360.0;
+      if ((DEC1 > 0) && (minDec < DEC1) && (maxDec > DEC0) && (minRa < RA1) && (maxRa > RA0)) {
+	temp[5] = 0;
+	sprintf (regions[nregions].filename, "%s/%s.cpt\0", Dec2Sections[NBigDec + j], &temp[1]);
+	regions[nregions].RA[0] = RA0;
+	regions[nregions].RA[1] = RA1;
+	regions[nregions].DEC[0] = DEC0;
+	regions[nregions].DEC[1] = DEC1;
+	nregions ++;
+	if (nregions == NREGIONS) {
+	  NREGIONS += 50;
+	  REALLOCATE (regions, GSCRegion, NREGIONS);
+	}
+      }
+      if ((DEC1 < 0) && (minDec < DEC0) && (maxDec > DEC1) && (minRa < RA1) && (maxRa > RA0)) {
+	temp[5] = 0;
+	sprintf (regions[nregions].filename, "%s/%s.cpt\0", Dec2Sections[NBigDec + j], &temp[1]);
+	regions[nregions].RA[0] = RA0;
+	regions[nregions].RA[1] = RA1;
+	regions[nregions].DEC[0] = DEC0;
+	regions[nregions].DEC[1] = DEC1;
+	nregions ++;
+	if (nregions == NREGIONS) {
+	  NREGIONS += 50;
+	  REALLOCATE (regions, GSCRegion, NREGIONS);
+	}
+      }
+      if (((DEC1 > 0) && (maxDec <= DEC1)) || ((DEC1 < 0) && (minDec >= DEC1))) {
+	done = TRUE;
+      }
+    }
+    if (done && (minDec < 0) && (maxDec > 0) && (BigDecBounds[NBigDec + j + 1] > 0)) {
+      /* skip remaining north sections, try south sections */
+      /* count lines before section */
+      NLINES = 0;
+      for (i = 0; i < 13; i++) { 
+	NLINES += NDecLines[i];
+      }
+      fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+      done = FALSE;
+      j = 12;
+    }
+  }
+
+  REALLOCATE (regions, GSCRegion, MAX (1,nregions));
+  *Nregions = nregions;
+  
+  fclose (f);
+  return (regions);
+  
+}
+
+/**********/
+int hms_to_deg (double *h0, double *h1, double *d0, double *d1, char *string) {
+  
+  int flag_d0, flag_d1, flag_h0, flag_h1;
+  double tmp;
+  
+  *d0 = *h0 = *d1 = *h1 = 0;
+
+  flag_h0 = dparse (h0, 1, string);
+  flag_h1 = dparse (h1, 4, string);
+  flag_d0 = dparse (d0, 7, string);
+  flag_d1 = dparse (d1, 9, string);
+  *h0 *= flag_h0;
+  *h1 *= flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  dparse (&tmp, 2, string);
+  *h0 += tmp/60.0;
+  dparse (&tmp, 3, string);
+  *h0 += tmp/3600.0;
+  
+  dparse (&tmp, 5, string);
+  *h1 += tmp/60.0;
+  dparse (&tmp, 6, string);
+  *h1 += tmp/3600.0;
+  
+  dparse (&tmp, 8, string);
+  *d0 += tmp/60.0;
+
+  dparse (&tmp, 10, string);
+  *d1 += tmp/60.0;
+
+  *h0 *= 15*flag_h0;
+  *h1 *= 15*flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/photdbc/src/initialize.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/initialize.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/initialize.c	(revision 12606)
@@ -0,0 +1,38 @@
+# include "photdbc.h"
+
+void initialize (int argc, char **argv) {
+
+  int Np;
+  double tmp;
+
+  /* are these set correctly? */
+  ConfigInit (&argc, argv);
+  args (argc, argv);
+
+  if (SHOW_PARAMS) {
+    fprintf (stderr, "current parameter settings:\n");
+    fprintf (stderr, "VERBOSE:                %d\n", VERBOSE);
+    fprintf (stderr, "JOIN_RADIUS:           %lf\n", JOIN_RADIUS);
+    fprintf (stderr, "UNIQ_RADIUS:           %lf\n", UNIQ_RADIUS);
+						     
+    fprintf (stderr, "XMIN:                  %lf\n", XMIN);
+    fprintf (stderr, "XMAX:                  %lf\n", XMAX);
+    fprintf (stderr, "YMIN:                  %lf\n", YMIN);
+    fprintf (stderr, "YMAX:                  %lf\n", YMAX);
+    fprintf (stderr, "MMIN:                  %lf\n", MMIN);
+    fprintf (stderr, "MMAX:                  %lf\n", MMAX);
+    fprintf (stderr, "DMCAL_MIN:             %lf\n", DMCAL_MIN);
+    fprintf (stderr, "DMSYS:                 %lf\n", DMSYS);
+						     
+    fprintf (stderr, "CHISQ_MAX:             %lf\n", CHISQ_MAX);
+    fprintf (stderr, "NMEAS_MIN:             %lf\n", NMEAS_MIN);
+
+    fprintf (stderr, "IMAGE_CATALOG          %s\n",  ImageCat);
+    fprintf (stderr, "GSCFILE                %s\n",  GSCFILE);
+    fprintf (stderr, "CATDIR                 %s\n",  CATDIR);
+    fprintf (stderr, "PHOTCODE_FILE          %s\n",  PhotCodeFile);
+
+    exit (0);
+  }
+}
+
Index: /tags/start/Ohana/src/photdbc/src/join_stars.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/join_stars.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/join_stars.c	(revision 12606)
@@ -0,0 +1,184 @@
+# include "photdbc.h"
+
+void join_stars (Catalog *catalog) {
+
+  int i, j, k, m, M, Ni, Nj, first_j, Ns1, Ns2;
+  int Naves, Nmeas, Ncurr;
+  int Naverage, Nmeasure, *found, *index;
+  float *X, *Y, dX, dY, dR, RADIUS2;
+  double Sr, Sd, Rmid, Dmid;
+
+  Average *naverage, *average;
+  Measure *nmeasure, *measure;
+  SecFilt *nsecfilt, *secfilt;
+  Mpointer *mpointer;
+  Coords tcoords;
+
+  if (VERBOSE) fprintf (stderr, "joining overlapping stars\n");
+
+  average = catalog[0].average;
+  measure = catalog[0].measure;
+  secfilt = catalog[0].secfilt;
+
+  Naverage = catalog[0].Naverage;
+  Nmeasure = catalog[0].Nmeasure;
+  RADIUS2 = JOIN_RADIUS*JOIN_RADIUS;
+
+  /* reference for coords is this region */
+  Rmid = Dmid = 0;
+  for (i = 0; i < Naverage; i++) {
+    Rmid += average[i].R;
+    Dmid += average[i].D;
+  }
+  Rmid /= Naverage;
+  Dmid /= Naverage;
+
+  /* coordinate system for projection */
+  tcoords.crval1 = Rmid;
+  tcoords.crval2 = Dmid;
+  tcoords.crpix1 = tcoords.crpix2 = 0.0;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1  = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2  = tcoords.pc2_1 = 0.0;
+  tcoords.Npolyterms = 0;
+  strcpy (tcoords.ctype, "RA---TAN");
+  
+  /* project & sort coordinates in local linear frame */
+  ALLOCATE (X, float, Naverage);
+  ALLOCATE (Y, float, Naverage);
+  ALLOCATE (index, int, Naverage);
+  for (i = 0; i < Naverage; i++) {
+    index[i] = i;
+    fRD_to_XY (&X[i], &Y[i], average[i].R, average[i].D, &tcoords);
+  }
+  sort_lists (X, Y, index, Naverage);
+  
+  /* flags to mark if a star has been handled */
+  ALLOCATE (found, int, Naverage);
+  for (i = 0; i < Naverage; i++) found[i] = FALSE;
+
+  ALLOCATE (naverage, Average, Naverage);
+  ALLOCATE (mpointer, Mpointer, Nmeasure);
+  for (i = 0; i < Nmeasure; i++) mpointer[i].averef = -1;
+
+  Naves =  0; // counter for new averages
+  Nmeas =  0; // counter for new measures
+  for (i = j = 0; (i < Naverage) && (j < Naverage); ) {
+    
+    Ni = index[i];
+    Nj = index[j];
+
+    /* a new star, add it to naverage[] */
+    if (!found[i]) { 	
+      naverage[Naves]        = average[Ni];
+      naverage[Naves].offset = Nmeas;
+      for (k = 0; k < average[Ni].Nm; k++) {
+	m = average[Ni].offset + k;
+	mpointer[Nmeas].measure = m;
+	mpointer[Nmeas].averef  = Naves;
+	mpointer[Nmeas].R       = average[Ni].R - measure[m].dR / 360000.0;
+	mpointer[Nmeas].D       = average[Ni].D - measure[m].dD / 360000.0;
+	Nmeas ++;
+      }
+      Ncurr = Naves;
+      found[i] = TRUE;
+      Naves ++;
+    }
+
+    if (found[j]) { j++; continue; }  // don't duplicate
+    if (j == i) {   j++; continue; }  // don't auto-correlate
+
+    dX = X[i] - X[j];
+    if (dX <= -JOIN_RADIUS) { /* X[j] is too large */
+      while (found[i] && (i < Naverage)) i++;
+      continue;
+    }
+    if (dX >= +JOIN_RADIUS) { /* X[i] is too large */
+      j++;
+      continue;
+    }
+
+    first_j = j;
+    for (; (dX > -2*JOIN_RADIUS) && (j < Naverage); j++) {
+      Nj = index[j];
+      if (found[j]) continue;
+      dX = X[i] - X[j];
+      dY = Y[i] - Y[j];
+      dR = dX*dX + dY*dY;
+      if (dR < RADIUS2) {  /* matched star, join to first */
+
+	/* define pointers for new measures */
+	for (k = 0; k < average[Nj].Nm; k++) {
+	  m = average[Nj].offset + k;
+	  mpointer[Nmeas].measure = m;
+	  mpointer[Nmeas].averef  = Ncurr;
+	  mpointer[Nmeas].R       = average[Nj].R - measure[m].dR / 360000.0;
+	  mpointer[Nmeas].D       = average[Nj].D - measure[m].dD / 360000.0;
+	  Nmeas ++;
+	}
+	naverage[Ncurr].Nm += average[Nj].Nm;
+	found[j] = TRUE;
+	
+	/* recalculate naverage[Ncurr].RA,DEC */
+	/* this must be done here to keep the average position consistent
+	   for the next star found */
+	for (Sr = Sd = k = 0; k < naverage[Ncurr].Nm; k++) {
+	  m = naverage[Ncurr].offset + k;
+	  Sr += mpointer[m].R;
+	  Sd += mpointer[m].D;
+	}
+	Sr = Sr / naverage[Ncurr].Nm;
+	Sd = Sd / naverage[Ncurr].Nm;
+	naverage[Ncurr].R = Sr;
+	naverage[Ncurr].D = Sd;
+
+	/* update original measurement offsets */
+	for (k = 0; k < naverage[Ncurr].Nm; k++) {
+	  m = naverage[Ncurr].offset + k;
+	  M = mpointer[m].measure;
+	  measure[M].dR = 360000.0*(Sr - mpointer[m].R);
+	  measure[M].dD = 360000.0*(Sd - mpointer[m].D);
+	}
+
+	/* update current reference star position */
+	fRD_to_XY (&X[i], &Y[i], Sr, Sd, &tcoords);
+      }
+    }
+    while (found[i] && (i < Naverage)) i++;
+    j = first_j;
+  }
+  if (Nmeas != Nmeasure) {
+    fprintf (stderr, "failure to match measures\n");
+  }
+  
+  /* create a new Measure table in the appropriate sequence */
+  ALLOCATE (nmeasure, Measure, Nmeasure);
+  for (i = 0; i < Nmeasure; i++) {
+    nmeasure[i]        = measure[mpointer[i].measure];
+    nmeasure[i].averef = mpointer[i].averef;
+  }
+
+  /* create an empty SecFilt table */
+  ALLOCATE (nsecfilt, SecFilt, Naves*catalog[0].Nsecfilt);
+  bzero (nsecfilt, Naves*catalog[0].Nsecfilt*sizeof(SecFilt));
+
+  free (catalog[0].average);
+  free (catalog[0].measure);
+  free (catalog[0].secfilt);
+
+  catalog[0].average = naverage;
+  catalog[0].measure = nmeasure;
+  catalog[0].secfilt = nsecfilt;
+  
+  catalog[0].Naverage = Naves;
+}
+
+/* notes:
+   merge averages of stars within RADIUS to single stars 
+   updates the average RA and DEC fields
+   creates a new Average table 'naverage' 
+   updates the Measure table to the new sequence
+   generates a new SecFilt table with empty values 
+   does NOT update magnitudes 
+*/   
+   
Index: /tags/start/Ohana/src/photdbc/src/liststats.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/liststats.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/liststats.c	(revision 12606)
@@ -0,0 +1,114 @@
+# include "photdbc.h"
+
+enum {M_MEAN, M_MEDIAN, M_WT_MEAN, M_INNER_MEAN, 
+      M_INNER_WTMEAN, M_CHI_INNER_MEAN, M_CHI_INNER_WTMEAN};
+
+static int statmode;
+
+void initstats (char *mode) {
+
+  statmode = -1;
+  if (!strcmp (mode, "MEAN")) statmode = M_MEAN;
+  if (!strcmp (mode, "MEDIAN")) statmode = M_MEDIAN;
+  if (!strcmp (mode, "WT_MEAN")) statmode = M_WT_MEAN;
+  if (!strcmp (mode, "INNER_MEAN")) statmode = M_INNER_MEAN;
+  if (!strcmp (mode, "INNER_WTMEAN")) statmode = M_INNER_WTMEAN;
+  if (!strcmp (mode, "CHI_INNER_MEAN")) statmode = M_CHI_INNER_MEAN;
+  if (!strcmp (mode, "CHI_INNER_WTMEAN")) statmode = M_CHI_INNER_WTMEAN;
+
+  if (statmode == -1) {
+    fprintf (stderr, "ERROR: invalid stats mode: %s\n", mode);
+    exit (1);
+  }
+}
+
+int liststats (double *value, double *dvalue, int N, StatType *stats) {
+  
+  int i, ks, ke, Nm;
+  double Mo, dMo, M, dM, X2, dS, *chi;
+
+  stats[0].Nmeas = N;
+  stats[0].mean  = 0;
+  if (N < 2) return (FALSE);
+
+  sortB (value, dvalue, N);
+  stats[0].median = value[(int)(0.5*N)];
+  stats[0].min    = value[0];
+  stats[0].max    = value[N-1];
+
+  switch (statmode) {
+  case M_MEDIAN:
+    ks = 0;
+    ke = N;
+    Mo = stats[0].median;
+    Nm = N;
+    goto chisq;
+    break;
+  case M_MEAN:
+  case M_WT_MEAN:
+    ks = 0;
+    ke = N;
+    break;
+  case M_INNER_MEAN:
+  case M_INNER_WTMEAN:
+  case M_CHI_INNER_MEAN:
+  case M_CHI_INNER_WTMEAN:
+    ks = 0.25*N + 0.50;
+    ke = 0.75*N + 0.25;
+    if (N <= 3) {
+      ks = 0;
+      ke = N;
+    }
+    break;
+  }    
+
+  if ((statmode == M_CHI_INNER_MEAN) || (statmode == M_CHI_INNER_WTMEAN)) {
+    ALLOCATE (chi, double, N);
+    for (i = 0; i < N; i++) {
+      chi[i] = (value[i] - stats[0].median) / dvalue[i];
+    }
+    sortD (chi, value, dvalue, N);
+    free (chi);
+  }
+
+  /* calculating the per-star offset based on the weighted average */
+  M = dM = Nm = 0;
+  if ((statmode == M_WT_MEAN) || (statmode == M_INNER_WTMEAN) || (statmode == M_CHI_INNER_WTMEAN)) {
+    for (i = ks; i < ke; i++) {
+      M   += value[i] / SQ (dvalue[i]);
+      dM  += 1.0 / SQ (dvalue[i]);
+      Nm  ++;  
+    }	
+    Mo = M / dM;
+    dMo = sqrt (1.0 / dM);
+  } else {
+    for (i = ks; i < ke; i++) {
+      M   += value[i];
+      dM  += SQ (dvalue[i]);
+      Nm  ++;  
+    }	
+    Mo = M / (double) Nm;
+    dMo = sqrt (dM / (double) Nm);
+  }
+
+ chisq:
+  /* find sigma and chisq */
+  X2 = dS = 0;
+  for (i = ks; i < ke; i++) {
+    M  = SQ (value[i] - Mo);
+    dM = SQ (dvalue[i]);
+    X2 += M / dM;
+    dS += M;
+  }
+  X2 = X2 / Nm;
+  dS = sqrt (dS / Nm);
+
+  stats[0].mean  = Mo;
+  stats[0].Nmeas = Nm;
+  stats[0].chisq = X2;
+  stats[0].sigma = dS;
+  stats[0].error = dMo;
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/photdbc/src/load_catalogs.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/load_catalogs.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/load_catalogs.c	(revision 12606)
@@ -0,0 +1,33 @@
+# include "photdbc.h"
+
+Catalog *load_catalogs (GSCRegion *region, int Nregion) {
+
+  int i, Nstar;
+  Catalog *catalog;
+
+  if (VERBOSE) fprintf (stderr, "loading catalog data\n");
+
+  ALLOCATE (catalog, Catalog, Nregion);
+
+  /* load data from each region file */
+  for (i = 0; i < Nregion; i++) {
+    catalog[i].filename = region[i].filename;  /* don't free region before catalog! */
+    switch (lock_catalog (&catalog[i], LCK_SOFT)) {
+    case 0:
+      fprintf (stderr, "ERROR: can't lock file %s\n", catalog[i].filename);
+      exit (1);
+    case 1:
+      gcatalog (&catalog[i]); /* load from disk */
+      break;
+    case 2:
+      if (VERBOSE) fprintf (stderr, "no data in %s, skipping\n", catalog[i].filename);
+      catalog[i].Naverage = 0;
+      catalog[i].Nmeasure = 0;
+      break;
+    default:
+      fprintf (stderr, "weird lock_catalog exit state\n");
+      exit (1);
+    }
+  }
+  return (catalog);
+}
Index: /tags/start/Ohana/src/photdbc/src/load_images.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/load_images.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/load_images.c	(revision 12606)
@@ -0,0 +1,64 @@
+# include "photdbc.h"
+
+static int   Nimage;
+static int   *Line;
+static Image *image;
+
+GSCRegion *load_images (char *seed, int *nregion) {
+
+  GSCRegion *region;
+  int       Nregion, Ntimage;
+  Image     *timage;
+
+  region = name_region (seed, &Nregion);
+
+  /* find images which supplied all measurements */
+  image = find_images (region, Nregion, &Nimage, &Line);
+  *nregion = Nregion;
+  
+  return (region);
+}
+
+Image *get_images (int *N) {
+  
+  *N = Nimage;
+  return (image);
+}
+
+/*
+void wimages () {
+  
+  int i, status, mode;
+  FILE *f;
+  Header header;
+
+  setMcalFinal (image, Nimage);
+
+  if (!fits_read_header (ImageCat, &header)) {
+    fprintf (stderr, "ERROR: can't find %s\n", ImageCat);
+    exit (0);
+  }
+  
+  f = fopen (ImageCat, "r+");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open image catalog file to append: %s\n", ImageCat);
+    exit (0);
+  }
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  chmod (ImageCat, mode);
+
+  if (VERBOSE) fprintf (stderr, "writing out %d images\n", Nimage);
+  for (i = 0; i < Nimage; i++) {
+    if (image[i].code == ID_IMAGE_NOCAL) image[i].code &= ~ID_IMAGE_NOCAL; 
+    
+    fseek (f, header.size + Line[i]*sizeof(Image), SEEK_SET);
+    status = Fwrite (&image[i], sizeof(Image), 1, f, "image");
+    if (status != 1) {
+      fprintf (stderr, "ERROR: failure writing image data to catalog %s\n", ImageCat);
+      exit (0);
+    }
+  }
+
+  fclose (f);
+}
+*/
Index: /tags/start/Ohana/src/photdbc/src/misc.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/misc.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/misc.c	(revision 12606)
@@ -0,0 +1,273 @@
+
+void sortA (double *X, int N) {
+
+  int l,j,ir,i;
+  double tX;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+  }
+}
+
+void sortB (double *X, double *Y, int N) {
+
+  int l,j,ir,i;
+  double tX, tY;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+  }
+}
+
+void sortC (double *X, double *Y, double *F1, double *F2, int N) {
+
+  int l,j,ir,i;
+  double tX, tY;
+  double t1, t2;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      t1 = F1[l];
+      t2 = F2[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      t1 = F1[ir];
+      F1[ir] = F1[0];
+      t2 = F2[ir];
+      F2[ir] = F2[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	F1[0] = t1;
+	F2[0] = t2;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	F1[i] = F1[j];
+	F2[i] = F2[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    F1[i] = t1;
+    F2[i] = t2;
+  }
+}
+
+void sortD (double *X, double *Y, double *Z, int N) {
+
+  int l,j,ir,i;
+  double tX, tY, tZ;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tZ = Z[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tZ = Z[ir];
+      Z[ir] = Z[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	Z[0] = tZ;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	Z[i] = Z[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    Z[i] = tZ;
+  }
+}
+
+void sort_lists (float *X, float *Y, int *S, int N) {
+
+  int l,j,ir,i;
+  double tX, tY;
+  int tS;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tS = S[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tS = S[ir];
+      S[ir] = S[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	S[0] = tS;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	S[i] = S[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    S[i] = tS;
+  }
+}
+
+void sort_time (unsigned int *X, int *Y, int N) {
+
+  int l,j,ir,i;
+  unsigned int tX;
+  int tY;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+  }
+}
Index: /tags/start/Ohana/src/photdbc/src/name_region.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/name_region.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/name_region.c	(revision 12606)
@@ -0,0 +1,24 @@
+# include "photdbc.h"
+
+GSCRegion *name_region (char *name, int *Nregions) {
+
+  GSCRegion *region;
+  Header header;
+
+  ALLOCATE (region, GSCRegion, 1);
+
+  sprintf (region[0].filename, "%s/%s", CATDIR, name);
+  if (!fits_read_header (region[0].filename, &header)) {
+    if (VERBOSE) fprintf (stderr, "catalog file not yet available: %s\n", region[0].filename);
+    exit (0);
+  }
+  fits_scan (&header, "RA0", "%lf", 1, &region[0].RA[0]);
+  fits_scan (&header, "RA1", "%lf", 1, &region[0].RA[1]);
+  fits_scan (&header, "DEC0", "%lf", 1, &region[0].DEC[0]);
+  fits_scan (&header, "DEC1", "%lf", 1, &region[0].DEC[1]);
+  fits_free_header (&header);
+
+  *Nregions = 1;
+  return (region);
+}
+
Index: /tags/start/Ohana/src/photdbc/src/photdbc.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/photdbc.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/photdbc.c	(revision 12606)
@@ -0,0 +1,52 @@
+# include "photdbc.h"
+
+int main (int argc, char **argv) {
+
+  int Nregion;
+  char filename[1024];
+  Catalog *catalog;
+  GSCRegion *region;
+
+  /* get configuration info, args, lockfile */
+  initialize (argc, argv);
+
+  /* load region and images overlapping region */
+  region = load_images (argv[1], &Nregion);
+
+  /* load catalog data corresponding to region file */
+  catalog = load_catalogs (region, Nregion);
+
+  /* limit number of measures based on selections */
+  catalog = subcatalog (catalog);
+
+  /* limit number of measures based on selections */
+  join_stars (catalog);
+
+  unique_measures (catalog);
+
+  flag_measures (catalog);
+
+  get_mags (catalog);
+
+  unlock_catalog (catalog);
+
+  sprintf (filename, "newdir/%s", argv[1]);
+  catalog[0].filename = filename;
+
+  check_directory (catalog[0].filename);
+  if (!lock_catalog (catalog, LCK_XCLD)) { 
+    fprintf (stderr, "can't lock new catalog file %s\n", catalog[0].filename);
+    exit (1);
+  }
+  wcatalog (catalog);
+}
+
+
+/** this program is somewhat rough: minimal error checking
+    -
+    only one catalog is loaded, corresponding to region file
+    
+
+
+
+ */
Index: /tags/start/Ohana/src/photdbc/src/subcatalog.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/subcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/subcatalog.c	(revision 12606)
@@ -0,0 +1,107 @@
+# include "photdbc.h"
+
+Catalog *subcatalog (Catalog *catalog) {
+  
+  int i, j, offset, ecode;
+  int NAVERAGE, NMEASURE, Naverage, Nmeasure, Nm, Nsecfilt;
+  int mag;
+  Catalog *subcatalog;
+
+  ALLOCATE (subcatalog, Catalog, 1);
+
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  subcatalog[0] = catalog[0];
+
+  /* we are moving only the subset of measurements from catalog[0] to subcatalog[0] */
+  NAVERAGE = 50;
+  NMEASURE = 1000;
+  ALLOCATE (subcatalog[0].average, Average, NAVERAGE);
+  ALLOCATE (subcatalog[0].secfilt, SecFilt, NAVERAGE*Nsecfilt);
+  ALLOCATE (subcatalog[0].measure, Measure, NMEASURE);
+  Nmeasure = Naverage = 0;
+
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    /* exclude stars with too few measurements */
+    if (catalog[0].average[i].Nm < NMEAS_MIN) continue; 
+
+    /* exclude stars not in range */
+    if (catalog[0].average[i].R < RMIN) continue;
+    if (catalog[0].average[i].R > RMAX) continue;
+    if (catalog[0].average[i].D < DMIN) continue;
+    if (catalog[0].average[i].D > DMAX) continue;
+
+    /* assign average and secfilt values */
+    subcatalog[0].average[Naverage] = catalog[0].average[i];
+    subcatalog[0].average[Naverage].offset = Nmeasure;
+    for (j = 0; j < Nsecfilt; j++) {
+      subcatalog[0].secfilt[Nsecfilt*Naverage+j] = catalog[0].secfilt[Nsecfilt*i+j];
+    }
+
+    Nm = 0;
+    for (j = 0; j < catalog[0].average[i].Nm; j++) {
+
+      offset = catalog[0].average[i].offset + j;
+
+      /* exclude measurements by photcode 
+      if (DropPhotcode) {
+	ecode = GetPhotcodeEquivCodebyCode (catalog[0].measure[offset].source);
+	if (ecode == photcode[0].code) continue;
+      }*/
+
+      /* select measurements by quality 
+      if (DropNonStellar && catalog[0].measure[offset].dophot != 1) continue;
+      */
+
+      /* exclude measurements by measurement error */
+      if (catalog[0].measure[offset].dM > SIGMA_MAX) continue;
+
+      /* select measurements by mag limit */
+      mag = iPhotInst (&catalog[0].measure[offset]);
+      if (mag < MMIN) continue;
+      if (mag > MMAX) continue;
+
+      subcatalog[0].measure[Nmeasure]        = catalog[0].measure[offset];
+      subcatalog[0].measure[Nmeasure].averef = Naverage;
+      Nmeasure ++;
+      Nm ++;
+      if (Nmeasure == NMEASURE) {
+	NMEASURE += 1000;
+	REALLOCATE (subcatalog[0].measure, Measure, NMEASURE);
+      }
+    }
+    if (Nm < NMEAS_MIN) { /* enough measurements meet criteria? */
+      Nmeasure -= Nm;
+      continue; 
+    }
+    subcatalog[0].average[Naverage].Nn = 0;
+    subcatalog[0].average[Naverage].Nm = Nm;
+    Naverage ++;
+    if (Naverage == NAVERAGE) {
+      NAVERAGE += 50;
+      REALLOCATE (subcatalog[0].average, Average, NAVERAGE);
+      REALLOCATE (subcatalog[0].secfilt, SecFilt, NAVERAGE*Nsecfilt);
+    }
+  }
+  REALLOCATE (subcatalog[0].average, Average, MAX (Naverage, 1));
+  REALLOCATE (subcatalog[0].measure, Measure, MAX (Nmeasure, 1));
+  REALLOCATE (subcatalog[0].secfilt, SecFilt, Nsecfilt*MAX (Naverage, 1));
+  subcatalog[0].Naverage = Naverage;
+  subcatalog[0].Nmeasure = Nmeasure;
+  subcatalog[0].Nsecfilt = catalog[0].Nsecfilt;
+
+  ALLOCATE (subcatalog[0].missing, Missing, 1);
+  subcatalog[0].Nmissing = 0;
+
+  if (catalog[0].Naverage > 0) free (catalog[0].average);
+  if (catalog[0].Nmeasure > 0) free (catalog[0].measure);
+  if (catalog[0].Naverage > 0) free (catalog[0].secfilt);
+
+  if (VERBOSE) {
+    fprintf (stderr, "%d: using %d stars (%d measures) for catalog\n", i, 
+	     subcatalog[0].Naverage, subcatalog[0].Nmeasure);
+  }
+  
+  return (subcatalog);
+
+}
Index: /tags/start/Ohana/src/photdbc/src/time.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/time.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/time.c	(revision 12606)
@@ -0,0 +1,313 @@
+# include <photdbc.h>
+  
+/***** convert [-]00:00:00 to 0.0000 ****/
+int dms_to_ddd (double *Value, char *string) {
+  
+  int valid, neg, status;
+  double tmp, value;
+  char *p1, *p2, *px;
+
+  valid = FALSE; 
+  neg = FALSE;
+  stripwhite (string);
+  p1 = string;
+  px = string + strlen(string);
+
+  if (string[0] == '-') { 
+    valid = TRUE; 
+    neg = TRUE;
+    p1 = &string[1];
+  }
+  if (string[0] == '+') { 
+    valid = TRUE; 
+    neg = FALSE;
+    p1 = &string[1];
+  }
+  if (isdigit(string[0])) { 
+    valid = TRUE;
+    p1 = &string[0];
+  }
+  if (!valid) { return (FALSE); }
+
+  status = 1;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) return (FALSE); /* entry not a number: +fred */
+  value = tmp;
+  if (p2 == px) goto escape;    /* entry only number: +1.0 */ 
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:fred */
+  status = 2;
+  value += tmp / 60.0;
+  if (p2 == px) goto escape;    /* entry only number: +1:1 */
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:1:fred */
+  value += tmp / 3600.0;
+
+ escape:
+  if (neg) {
+    value *= -1;
+  }
+  *Value = value;
+
+  return (status);
+}
+
+/**********/
+int str_to_radec (double *ra, double *dec, char *str1, char *str2) {
+
+  double Ra, Dec;
+
+  *ra = *dec = 0;
+  switch (dms_to_ddd (&Ra, str1)) {
+  case 0:
+    fprintf (stderr, "syntax error in RA\n");
+    return (FALSE);
+  case 1:
+    break;
+  case 2:
+    Ra = Ra * 15;
+    break;
+  }
+  switch (dms_to_ddd (&Dec, str2)) {
+  case 0:
+    fprintf (stderr, "syntax error in DEC\n");
+    return (FALSE);
+  case 1:
+  case 2:
+    break;
+  }
+  *ra = Ra;
+  *dec = Dec;
+  return (TRUE);
+}
+
+# define FORMAT_DAYS    1
+# define FORMAT_HOURS   2
+# define FORMAT_MINUTES 3
+# define FORMAT_SECONDS 4
+# define FORMAT_JD      5
+# define FORMAT_DATE    6
+
+/**********/
+int chk_time (char *line) {
+
+  char *p1, *p2;
+  double tmp;
+  int mode;
+
+  p1 = line;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1 + strlen (p1) - 1) {
+    if (*p2 == 'd') {
+      mode = FORMAT_DAYS;
+    }
+    if (*p2 == 'h') {
+      mode = FORMAT_HOURS;
+    }
+    if (*p2 == 'm') {
+      mode = FORMAT_MINUTES;
+    }
+    if (*p2 == 's') {
+      mode = FORMAT_SECONDS;
+    }
+    if (*p2 == 'j') {
+      mode = FORMAT_JD;
+    }
+  } else { 
+    mode = FORMAT_DATE;
+  }
+  return (mode);
+}
+
+/**********/
+int str_to_time (char *line, unsigned int *second) {
+  
+  struct timeval now;
+  double jd;
+
+  if (!strcasecmp (line, "NOW")) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    *second = now.tv_sec;
+    return (TRUE);
+  }
+    
+  if (!strcasecmp (line, "TODAY")) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    *second = 86400 * ((int)(now.tv_sec / 86400));
+    return (TRUE);
+  }
+    
+  switch (chk_time (line)) {
+  case 0:
+    return (FALSE);
+  case FORMAT_DAYS:
+    *second = strtod (line, 0) * 86400.0;
+    return (TRUE);
+  case FORMAT_HOURS:
+    *second = strtod (line, 0) * 3600.0;
+    return (TRUE);
+  case FORMAT_MINUTES:
+    *second = strtod (line, 0) * 60.0;
+    return (TRUE);
+  case FORMAT_SECONDS:
+    *second = strtod (line, 0);
+    return (TRUE);
+  case FORMAT_JD:
+    jd = strtod (line, 0);
+    *second = jd_to_sec (jd);
+    return (TRUE);
+  case FORMAT_DATE:
+    *second = date_to_sec (line);
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+/**********/
+int str_to_dtime (char *line, double *second) {
+  
+  switch (chk_time (line)) {
+  case 0:
+  case FORMAT_JD:
+  case FORMAT_DATE:
+    return (FALSE);
+  case FORMAT_DAYS:
+    *second = strtod (line, 0) * 86400.0;
+    return (TRUE);
+  case FORMAT_HOURS:
+    *second = strtod (line, 0) * 3600.0;
+    return (TRUE);
+  case FORMAT_MINUTES:
+    *second = strtod (line, 0) * 60.0;
+    return (TRUE);
+  case FORMAT_SECONDS:
+    *second = strtod (line, 0);
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+/**********/
+double sec_to_jd (unsigned long second) {
+
+  double jd;
+  
+  jd = second/86400.0 + 2440587.5;
+  return (jd);
+}
+
+/**********/
+unsigned long jd_to_sec (double jd) {
+
+  unsigned long int second;
+
+  second = (jd - 2440587.5)*86400;
+  return (second);
+}
+
+/**********/
+char *sec_to_date (unsigned long second) {
+  
+  struct tm *gmt;
+  char *line;
+  
+  ALLOCATE (line, char, 64);
+  gmt   = gmtime (&second);
+  sprintf (line, "%4d/%02d/%02d,%02d:%02d:%02d", 1900+gmt[0].tm_year, gmt[0].tm_mon+1, gmt[0].tm_mday, gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+  return (line);
+
+}
+
+/***** date in format yyyy/mm/dd,hh:mm:ss *****/
+unsigned long date_to_sec (char *date) {
+  
+  unsigned long second;
+  double tmp, jd;
+  struct tm now;
+  char *p1, *p2, *px;
+  
+  p1 = date;
+  px = date + strlen(date);
+  bzero (&now, sizeof(now));
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_year = tmp;
+  if (now.tm_year > 1000) now.tm_year -= 1900;
+  if (now.tm_year <   50) now.tm_year += 100;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mon = tmp - 1; /* mon runs from 0 - 11 */
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mday = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  p1 = p2 + 1;
+  now.tm_hour = tmp;
+  if (p2 == px) goto escape;  
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_min = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_sec = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+ escape:
+  jd = now.tm_mday - 32075 + (int)(1461*(1900 + now.tm_year + 4800 + (int)(((now.tm_mon+1)-14)/12))/4)
+    + (int)(367*((now.tm_mon+1) - 2 - (int)(((now.tm_mon+1) - 14)/12)*12)/12)
+    - (int)(3*(int)((1900 + now.tm_year + 4900 + (int)(((now.tm_mon+1) - 14)/12))/100)/4) - 0.5;
+  
+  second = (jd - 2440587.5)*86400 + 3600.0*now.tm_hour + now.tm_min*60.0 + now.tm_sec;
+
+  return (second);
+}
+
+
+/* times may be in forms as:
+   20040200450s (N seconds since 1970.0)
+   2440900.232j (julian date)
+   99/02/23,03:22:18 (date string)
+   (separators may be anything except space, +, -)
+   99:02:15:12:23:30
+   99:02:15:12h23m30s
+   */
+
+
+/* fseek with timeout - 0.5 sec */
+int Fseek (FILE *f, long offset, int whence) {
+
+  int status, k;
+
+  status = fseek (f, offset, whence);
+  if (status == -1) {
+    int k;
+    /* fprintf (stderr, "problem seeking position: %d\n", errno); */
+    for (k = 0; (k < 10) && ((status = fseek (f, 0, SEEK_SET)) == -1); k++) usleep (50000);
+    if (status == -1) {
+      /* fprintf (stderr, "ERROR: serious problem seeking position: %d\n", errno); */
+      /* clear lock at this point? */
+      return (0);
+    }
+  }
+  return (1);
+}
Index: /tags/start/Ohana/src/photdbc/src/unique_measures.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/unique_measures.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/unique_measures.c	(revision 12606)
@@ -0,0 +1,101 @@
+# include "photdbc.h"
+
+void unique_measures (Catalog *catalog) {
+
+  int i, j, k, m, N;
+  int No, Nm, Nvalid, Nlist;
+  int *ilist;
+  unsigned int *tlist;
+  Measure *mlist, *nmeasure;
+  double dR, dD, R;
+  Average *p;
+
+  if (VERBOSE) fprintf (stderr, "removing duplicate measurements\n");
+
+  /* allocate a list for temp storage of measure values */
+  Nlist = 0;
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    Nlist = MAX (Nlist, catalog[0].average[i].Nm);
+  }
+  ALLOCATE (ilist, int, Nlist);
+  ALLOCATE (tlist, unsigned int, Nlist);
+  ALLOCATE (mlist, Measure, Nlist);
+
+  p = catalog[0].average;
+  for (i = 0; i < catalog[0].Naverage; i++) {
+
+    if (catalog[0].average != p) {
+      fprintf (stderr, "error\n");
+    }
+
+    /* extract list of measurements */
+    N = 0;
+    m = catalog[0].average[i].offset;
+    for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+      ilist[N] = m;
+      tlist[N] = catalog[0].measure[m].t;
+      N++;
+    }
+
+    /* sort the images by time */
+    sort_time (tlist, ilist, N);
+
+    /* look for duplicates */
+    for (j = k = 0; (j < N) && (k < N); j++) {
+      if (j == k) {
+	k++;
+	continue;
+      }
+      if (tlist[j] != tlist[k]) {
+	j++;
+	k = j + 1;
+	continue;
+      }
+      if (catalog[0].measure[ilist[j]].flags & FLAG_DUPMEAS) {
+	j++;
+	k = j + 1;
+	continue;
+      }
+      
+      dR = (catalog[0].measure[ilist[j]].dR - catalog[0].measure[ilist[k]].dR);
+      dD = (catalog[0].measure[ilist[j]].dD - catalog[0].measure[ilist[k]].dD);
+      R = SQ(dR) + SQ(dD);
+      
+      /* dR, dD in 1/100 arcsec, RADIUS is 0.1 arcsec */
+      if (R < UNIQ_RADIUS) {
+	/* matched pair */
+	catalog[0].measure[ilist[k]].flags |= FLAG_DUPMEAS;
+      }
+      k++;
+    }
+  }
+
+  Nvalid = 0;
+  for (i = 0; i < catalog[0].Nmeasure; i++) {
+    if (!(catalog[0].measure[i].flags & FLAG_DUPMEAS)) Nvalid ++;
+  }
+
+  No = 0;
+  ALLOCATE (nmeasure, Measure, MAX (Nvalid, 1));
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    /* copy valid measures to new table, update offset, Nm */
+    Nm = 0;
+    m = catalog[0].average[i].offset;
+    catalog[0].average[i].offset = No;
+    for (j = 0; j < catalog[0].average[i].Nm; j++, m++, No++) {
+      if (catalog[0].measure[m].flags & FLAG_DUPMEAS) continue;
+      nmeasure[No] = catalog[0].measure[m];
+      if (catalog[0].measure[m].averef != i) { 
+	fprintf (stderr, "average reference mismatch!!\n");
+      }
+      Nm ++;
+    }
+    catalog[0].average[i].Nm = Nm;
+  }
+
+  free (catalog[0].measure);
+  catalog[0].measure = nmeasure;
+  catalog[0].Nmeasure = No;
+
+}
+
Index: /tags/start/Ohana/src/photdbc/src/wcatalog.c
===================================================================
--- /tags/start/Ohana/src/photdbc/src/wcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/photdbc/src/wcatalog.c	(revision 12606)
@@ -0,0 +1,25 @@
+# include "photdbc.h"
+
+void wcatalog (Catalog *catalog) {
+  
+  fits_modify (&catalog[0].header, "NRPHOT", "%t", 1, TRUE);
+
+  save_catalog (catalog, VERBOSE);
+
+  if (catalog[0].Naverage) {
+    free (catalog[0].average); 
+    catalog[0].Naverage = 0;
+  }
+  if (catalog[0].Nmeasure) {
+    free (catalog[0].measure); 
+    catalog[0].Nmeasure = 0;
+  }
+  if (catalog[0].Nmissing) {
+    free (catalog[0].missing); 
+    catalog[0].Nmissing = 0;
+  }
+  if (catalog[0].Nsecfilt) {
+    free (catalog[0].secfilt); 
+    catalog[0].Nsecfilt = 0;
+  }
+}
Index: /tags/start/Ohana/src/relphot/Makefile
===================================================================
--- /tags/start/Ohana/src/relphot/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/relphot/Makefile	(revision 12606)
@@ -0,0 +1,79 @@
+include ../../Configure
+HOME    =       $(ROOT)/src/relphot
+CONFIG  =	$(ROOT)/config
+PROGRAM =       relphot
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lohana -lFITS -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS)
+CCFLAGS	=	$(INCS) $(LIBS) 
+
+RELPHOT = \
+$(SRC)/relphot.$(ARCH).o	 \
+$(SRC)/initialize.$(ARCH).o	 \
+$(SRC)/ConfigInit.$(ARCH).o	 \
+$(SRC)/args.$(ARCH).o		 \
+$(SRC)/liststats.$(ARCH).o	 \
+$(SRC)/load_images.$(ARCH).o	 \
+$(SRC)/name_region.$(ARCH).o	 \
+$(SRC)/find_images.$(ARCH).o	 \
+$(SRC)/find_regions.$(ARCH).o	 \
+$(SRC)/get_regions.$(ARCH).o	 \
+$(SRC)/load_catalogs.$(ARCH).o	 \
+$(SRC)/gcatalog.$(ARCH).o 	 \
+$(SRC)/bcatalog.$(ARCH).o	 \
+$(SRC)/GridOps.v2.$(ARCH).o	 \
+$(SRC)/StarOps.$(ARCH).o	 \
+$(SRC)/ImageOps.$(ARCH).o	 \
+$(SRC)/MosaicOps.$(ARCH).o	 \
+$(SRC)/global_stats.$(ARCH).o	 \
+$(SRC)/plot_scatter.$(ARCH).o	 \
+$(SRC)/plotstuff.$(ARCH).o	 \
+$(SRC)/misc.$(ARCH).o		 \
+$(SRC)/time.$(ARCH).o		 \
+$(SRC)/reload_catalogs.$(ARCH).o \
+$(SRC)/free_catalogs.$(ARCH).o   \
+$(SRC)/setMrelFinal.$(ARCH).o 	 \
+$(SRC)/write_coords.$(ARCH).o 	 \
+$(SRC)/setExclusions.$(ARCH).o 	 \
+$(SRC)/wcatalog.$(ARCH).o
+
+OBJ = $(RELPHOT)
+
+default: $(PROGRAM)
+
+$(RELPHOT): $(INC)/relphot.h
+
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:	
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
Index: /tags/start/Ohana/src/relphot/doc/notes.html
===================================================================
--- /tags/start/Ohana/src/relphot/doc/notes.html	(revision 12606)
+++ /tags/start/Ohana/src/relphot/doc/notes.html	(revision 12606)
@@ -0,0 +1,130 @@
+
+<h2> relphot outline </h2>
+
+<ul>
+<li> load data
+     images: match photcode and time range, reset flags
+     measure: select subset matching restritions on:
+       photcode, time, dM, Minst, Mag, dophot == 1
+<li> iterate to find Mcal, image.flags:
+     
+
+
+
+
+
+
+<h2> relphot overview </h2>
+
+<p> relphot has two primary purposes:<br>
+<ul>
+<li> calculate <b>Mcal</b> for images / measures
+<li> calculate <b>Mrel</b> for stars
+</ul>
+
+<p> relphot can also be used to determine the mosaic grid used to generate
+photometrically corrected flats (-grid option).
+
+<h2> data exclusion </h2>
+
+<p> relphot uses only a subset of the photometry data to calculate
+Mcal and Mrel.  In the first stage, calculation of the Mcal values,
+relphot loads the photometry data from each relevant catalog and
+creates an internal subset catalog with the function
+<em>bcatalog</em>, excluding some of the irrelevant data.  In
+addition, it uses flags to mark some of the data as invalid for the
+processing.
+
+<b> bcatalog exclusions </b>
+<ul>
+<li> measure.photcode not equivalent to requested photcode
+<li> measure.dophot != 1
+<li> measure.Mcat > MAG_LIM
+<li> measure.dM > SIGMA_LIM
+<li> measure.Minst out of range (ImagMin - ImagMax) [optional]
+<li> measure.t out of range (TSTART, TSTOP)
+
+<b> flagged data </b>
+
+<b> flagged image data </b>
+
+images can be flagged by setting bits of <b>image.code</b>
+
+stars can be flagged by setting bits of <b>average.code</b>
+
+measures can be flagged by setting bits of <b>measure.flag</b>
+
+<b>image.code</b>
+
+ID_IMAGE_NOCAL : ignore, irrelevant
+ID_IMAGE_POOR  : image measured bad
+ID_IMAGE_SKIP  : externally known bad
+
+dMcal > VALUE       FLAG_IMAGE_SCATTER <em>clean_images</em>
+fabs(Mcal) > VALUE  FLAG_IMAGE_ZEROPT  <em>clean_images</em>
+
+dMcal > VALUE       FLAG_IMAGE_SCATTER <em>clean_mosaics</em>
+fabs(Mcal) > VALUE  FLAG_IMAGE_ZEROPT  <em>clean_mosaics</em>
+
+<em> mark_images </em> does not seem to do anything useful?
+
+<b>average.code</b>
+
+Ngood < MEAS_TOOFEW                     <em>setMrel</em>
+Ngood < MEAS_TOOFEW                     <em>clean_measures</em>
+ChiSq > STAR_CHISQ                      <em>clean_stars</em>
+dM    > STAR_SCATTER                    <em>clean_stars</em>
+
+average.code (STAR_BAD) is not saved by relphot: it is set by
+clean_stars, clean_measures, and setMrel, but not setMrelOutput.
+STAR_BAD should only be internal since it depends on the photcode, but
+is not associated with a specific photcode in the data.  Just in case,
+it is reset to 0 in setMrelFinal.
+
+<b>measure.flag</b>
+
+X,Y out of range                        <em>setExclusions</em>
+3 sigma clipping                        <em>clean_measures</em>
+
+<h2> setting Mrel final value </h2>
+
+setMrelFinal is used to set the final average.Mrel values.  We do this
+in 4 stages.  In each stage, we set the Mrel values for stars which
+have not already been set, based on the current exclusion settings.
+At successive stages, we relax the exclusions, allowing the more
+spurious objects to have a valid Mrel value to be set.  In this loop,
+we actually run setMrelOutput twice: once to get the approximate Mrel
+value, then we flag the outlier measurements with clean_measure,
+then we redetermine the Mrel values on this basis, and mark the stars
+for exclusion from the next iteration.  
+
+exclude on
+ photcode       0 1 2 3
+ time range     0 1 2 3
+ MEAS_POOR      0 1 2 3
+ MEAS_TOOFEW    0 1 2 3
+ dophot == 10   0 1 2 
+ inst mag       0 1 2 
+ dophot != 1,2  0 1  
+ ID_IMAGE_POOR  0 1
+ ID_IMAGE_SKIP  0 1
+ dophot != 1    0
+ measure.dM     0 
+
+for all relphot runs, Mrel is re-calculated, and measures are marked
+at least if they are outliers in mag or ccd area.
+
+setMrel.output needs to do a few things differently from setMrel:
+<ul>
+<li> set measure.Mcal (skipped in setMrel.basic)
+<li> set average.Mrel if N < TOO_FEW (not STAR_BAD) (optional!)
+<li> use MAX (stats.error, stats.sigma) (optionally)
+<li> allow STAR_BAD?
+</ul>
+
+<h2> imphotset </h2>
+
+imphotset allows you to set certain phot.image table entries.  here
+are the options:
+
+imphotset [-photcode code] [-name foo] [-trange (start) (stop)] -flag and value
Index: /tags/start/Ohana/src/relphot/doc/notes.txt
===================================================================
--- /tags/start/Ohana/src/relphot/doc/notes.txt	(revision 12606)
+++ /tags/start/Ohana/src/relphot/doc/notes.txt	(revision 12606)
@@ -0,0 +1,88 @@
+
+- select different calibration options
+- plot various terms
+
+- rationalize Mmos & Mcal (sum(Mcal) -> Mmos)
+
+- options:
+
+  -update:  update phot database 
+  -mosaic:  apply per-mosaic corrections
+  -grid:    apply X,Y-based offset
+  -chips:   apply per-chip corrections
+  -trange:  select images in time range
+  
+
+find_images: selects images in region, filtered by photcode, time range
+
+bcatalog:    selects stars & measurments, filtered by mag limit, photcode, time range
+
+image:  a single ccd
+mosaic: a collection of associate ccds (mosaiclink[image])
+grid:   x,y magnitude correction grid across mosaic 
+fit:    2-d fit of mag offsets across field
+
+
+
+m = Mrel + Mcal + Mmos + Mxy + Mgrid
+
+Mrel  (average)
+Mcal  (image)
+Mmos  (mosaic)
+Mxy   (Xi, Yi) (Xi,Yi per image ??)
+Mgrid (Xm, Ym)
+
+
+ measure -> average           catalog[i].measure[j].averef 
+ average -> measure           catalog[i].average[j].offset, catalog[i].average[j].Nm
+
+ measure -> image             image:  image[cat, meas]
+ image   -> measure           image:  catlist[image], measlist[image]
+
+ measure -> mosaic            mosaic: mosaic[cat, meas]
+ mosaic  -> measure	      mosaic: catlist[mosaic], measlist[mosaic]
+
+ measure -> gridbin           grid:   bin[cat, meas]
+ gridbin -> measure           grid:   catlist[bin], measlist[bin]
+
+ measure -> Xi, Yi -> Mxy     
+
+
+getMmos:
+
+ for (i = 0; i < Nmosaic; i++) {
+
+   for (j = 0; j < Nmeasure[i]; j++) {
+      cat  = catlist[i][j]
+      meas = measlist[i][j]
+
+      M = catalog[cat].measure[meas].M
+      Mcal  = applyMcal  (cat, meas)
+      Mrel  = applyMrel  (cat, meas)
+      Mxy   = applyMxy   (cat, meas)
+      Mgrid = applyMgrid (cat, meas)
+
+      list[n] = M - Mcal - Mrel - Mxy - Mgrid
+    }
+  }
+
+
+
+excluding data points:
+
+star:   N < 2
+image:  
+
+
+--
+
+MAG_LIM      : keep stars brighter than MAG_LIM (Mcat)
+SIGMA_LIM    : keep stars with error < SIGMA_LIM
+STAR_SCATTER : exclude stars with dM > STAR_SCATTER
+IMAGE_SCATTER, NIMAGE_SCATTER : define image scatter limits
+
+
+
+load_images - exclude images 
+
+
Index: /tags/start/Ohana/src/relphot/include/relphot.h
===================================================================
--- /tags/start/Ohana/src/relphot/include/relphot.h	(revision 12606)
+++ /tags/start/Ohana/src/relphot/include/relphot.h	(revision 12606)
@@ -0,0 +1,158 @@
+# include <ohana.h>
+# include <loneos.h>
+
+/* # define GRID_V1 */
+# define GRID_V2
+
+static union { unsigned char c[4]; float f; } f_undef = { 0xff, 0xff, 0xff, 0xfe };
+# define fUNDEF (f_undef.f)
+
+static union { unsigned char c[8]; float d; } d_undef = { 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00 };
+# define dUNDEF (d_undef.d)
+
+typedef struct {
+  double xmin, xmax, ymin, ymax;
+  int style, ptype, ltype, etype, color;
+  double lweight, size;
+} Graphdata;
+
+typedef struct {
+  unsigned int start;
+  unsigned int stop;
+  short int Mcal;
+  short int dMcal;
+  short int Xm;
+  short int secz;
+  char code;
+  Coords coords;
+} Mosaic; 
+
+typedef struct {
+  double median;
+  double mean;
+  double sigma;
+  double error;
+  double chisq;
+  double min;
+  double max;
+  double total;
+  int    Nmeas;
+} StatType;
+
+/* global variables set in parameter file */
+char   ImageCat[256];
+char   ImageTemplate[256];
+char   CatTemplate[256];
+char   GSCFILE[256];
+char   CATDIR[256];
+char   CameraConfig[256];
+
+double MAG_LIM;
+double SIGMA_LIM;
+double IMAGE_SCATTER;
+double IMAGE_OFFSET;
+double STAR_SCATTER;
+double STAR_CHISQ;
+double MIN_ERROR;
+
+int    VERBOSE;
+
+int    NLOOP;
+int    RESET;
+int    UPDATE;
+int    PLOTSTUFF;
+int    SAVEPLOT;
+int    SHOW_PARAMS;
+char   MOSAICNAME[256];
+char   STATMODE[32];
+int    STAR_BAD;
+int    MEAS_BAD;
+int    STAR_TOOFEW;
+int    IMAGE_TOOFEW;
+double IMAGE_GOOD_FRACTION;
+int    IMAGE_BAD;
+int    FREEZE_IMAGES;
+int    USE_GRID;
+int    PLOTDELAY;
+
+int    RELPHOT_GRID_X;
+int    RELPHOT_GRID_Y;
+int    RELPHOT_GRID_BINNING;
+
+PhotCode      *photcode;
+int            PhotPrimary;
+int            PhotNsec;
+int            PhotSec;
+
+int AreaSelect;
+double AreaXmin, AreaXmax, AreaYmin, AreaYmax;
+
+int ImagSelect, ImagMin, ImagMax;
+
+double  PlotMmin, PlotMmax, PlotdMmin, PlotdMmax;
+enum {black, white, red, orange, yellow, green, blue, indigo, violet};
+
+int TimeSelect;
+unsigned int TSTART, TSTOP;
+
+/***** prototypes ****/
+int main (int argc, char **argv);
+Catalog *load_catalogs (GSCRegion *region, int Nregion, GSCRegion *fullregion);
+GSCRegion *load_images (char *seed, int *nregion, GSCRegion *fullregion);
+GSCRegion *name_region (char *name, int *Nregions);
+GSCRegion *find_regions (Image *image, int Nimage, int *Nregions, GSCRegion *fullregion);
+GSCRegion *get_regions (double minRa, double maxRa, double minDec, double maxDec, int *Nregions);
+Image *find_images (GSCRegion *region, int Nregion, int *Nimages, int **LineNum);
+double opening_angle (double x1, double y1, double x2, double y2, double x3, double y3);
+int edge_check (double *x1, double *y1, double *x2, double *y2);
+int corner_check (double *x1, double *y1, double *x2, double *y2);
+int hms_to_deg (double *h0, double *h1, double *d0, double *d1, char *string);
+int bcatalog (Catalog *subcatalog, Catalog *catalog, GSCRegion *fullregion);
+int findMosaics (Catalog *catalog, int Ncatalog);
+int setMmos (Catalog *catalog, int Poor);
+int setMrel (Catalog *catalog, int Ncatalog);
+int setrefcode (Image *image, int Nimage); 
+int args (int argc, char **argv);
+short getMgrid (int meas, int cat);
+short getMcal (int meas, int cat);
+short getMmos (int meas, int cat);
+short getMrel (Catalog *catalog, int meas, int cat);
+void initGrid (int dX, int dY);
+void initGridBins (Catalog *catalog, int Ncatalog);
+void initMosaics (Image *image, int Nimage);
+void initMosaicGrid (Image *image, int Nimage);
+void initMosaicBins (Catalog *catalog, int Ncatalog);
+void initMrel (Catalog *catalog, int Ncatalog);
+void initialize (int argc, char **argv);
+void ConfigInit (int *argc, char **argv);
+void mark_images (Image *image, int Nimage, Image *timage, int Ntimage);
+void setMgrid (Catalog *catalog);
+void dumpGrid ();
+void initImages (Image *input, int N);
+void initImageBins (Catalog *catalog, int Ncatalog);
+void findImages (Catalog *catalog, int Ncatalog);
+void matchImage (Catalog *catalog, int meas, int cat);
+void matchMosaics (Catalog *catalog, int meas, int cat);
+void setMcal (Catalog *catalog, int Poor);
+void clean_images ();
+void clean_stars (Catalog *catalog, int Ncatalog);
+void reload_catalogs (GSCRegion *region, int Nregion, GSCRegion *fullregion);
+void free_catalogs (Catalog *catalog, int Ncatalog);
+
+# ifdef GRID_V1
+int setGridMeasure (int meas, int cat, double X, double Y);
+# endif
+
+# ifdef GRID_V2
+int setGridMeasure (int meas, int cat, double X, double Y, int ccdnum);
+# endif
+
+void set_ZP (double ZERO);
+
+char *GetPhotnamebyCode (PhotCodeData *photcodes, int code);
+StatType statsStarS (Catalog *catalog, int Ncatalog);
+StatType statsStarX (Catalog *catalog, int Ncatalog);
+StatType statsStarN (Catalog *catalog, int Ncatalog);
+StatType statsImageN (Catalog *catalog);
+StatType statsImageX (Catalog *catalog);
+StatType statsImageM (Catalog *catalog);
Index: /tags/start/Ohana/src/relphot/src/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/ConfigInit.c	(revision 12606)
@@ -0,0 +1,70 @@
+# include "relphot.h"
+void GetConfig (char *config, char *field, char *format, int N, void *ptr);
+
+void ConfigInit (int *argc, char **argv) {
+
+  double ZERO_POINT;
+  char  *config, *file;
+  char   PhotCodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  GetConfig (config, "MAG_LIM",                "%lf", 0, &MAG_LIM);
+  GetConfig (config, "SIGMA_LIM",              "%lf", 0, &SIGMA_LIM);
+  GetConfig (config, "STAR_SCATTER",           "%lf", 0, &STAR_SCATTER);
+  GetConfig (config, "IMAGE_SCATTER",          "%lf", 0, &IMAGE_SCATTER);
+  GetConfig (config, "IMAGE_OFFSET",           "%lf", 0, &IMAGE_OFFSET);
+  MAG_LIM *= 1000;
+  SIGMA_LIM *= 1000;
+  STAR_SCATTER *= 1000;
+  IMAGE_SCATTER *= 1000;
+  IMAGE_OFFSET *= 1000;
+
+  GetConfig (config, "STAR_CHISQ",             "%lf", 0, &STAR_CHISQ);
+  GetConfig (config, "STAR_TOOFEW",            "%d",  0, &STAR_TOOFEW);
+  GetConfig (config, "IMAGE_TOOFEW",           "%d",  0, &IMAGE_TOOFEW);
+  GetConfig (config, "IMAGE_GOOD_FRACTION",    "%lf", 0, &IMAGE_GOOD_FRACTION);
+
+  GetConfig (config, "IMAGE_CATALOG",          "%s",  0, ImageCat);
+  GetConfig (config, "IMAGE_CATALOG_TEMPLATE", "%s",  0, ImageTemplate);
+  GetConfig (config, "CATALOG_TEMPLATE",       "%s",  0, CatTemplate);
+  GetConfig (config, "GSCFILE",                "%s",  0, GSCFILE);
+  GetConfig (config, "CATDIR",                 "%s",  0, CATDIR);
+  GetConfig (config, "PHOTCODE_FILE",          "%s",  0, PhotCodeFile);
+  GetConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
+
+  GetConfig (config, "RELPHOT_GRID_X",         "%d",  0, &RELPHOT_GRID_X);
+  GetConfig (config, "RELPHOT_GRID_Y",         "%d",  0, &RELPHOT_GRID_Y);
+  GetConfig (config, "RELPHOT_GRID_BINNING",   "%d",  0, &RELPHOT_GRID_BINNING);
+  GetConfig (config, "CAMERA_CONFIG",          "%s",  0, CameraConfig);
+
+  if (!LoadPhotcodes (PhotCodeFile)) {
+    fprintf (stderr, "error loading photcodes\n");
+    exit (1);
+  }
+  SetZeroPoint (ZERO_POINT);
+
+  free (config);
+  free (file);
+
+}
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr) {
+
+  int status;
+
+  status = ScanConfig (config, field, format, N, ptr);
+  if (!status) {
+    fprintf (stderr, "error in config, cannot find %s\n", field);
+    exit (1);
+  }
+  return;
+}
Index: /tags/start/Ohana/src/relphot/src/GridOps.v1.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/GridOps.v1.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/GridOps.v1.c	(revision 12606)
@@ -0,0 +1,427 @@
+# include "relphot.h"
+
+static int     Ngrid;
+static short   *gridM;
+static short   *gridS;
+static int     *gridN;
+static int      gridX;
+static int      gridY;
+
+static int    **bin;
+static int    **Xmeas;
+static int    **Ymeas;
+
+static int    **clist;
+static int    **mlist;
+static int     *Nlist;
+static int     *NLIST;
+
+void initGrid (int dX, int dY) {
+
+  int i;
+
+  /* define mosaic 2d correction grid */
+  gridX = dX / RELPHOT_GRID_BINNING + 1;
+  gridY = dY / RELPHOT_GRID_BINNING + 1;
+  Ngrid = gridX * gridY;
+
+  ALLOCATE (gridM, short, Ngrid);
+  ALLOCATE (gridS, short, Ngrid);
+  ALLOCATE (gridN, int,   Ngrid);
+  bzero (gridM, Ngrid*sizeof(short));
+  bzero (gridS, Ngrid*sizeof(short));
+  bzero (gridN, Ngrid*sizeof(int));
+
+}
+
+void initGridBins (Catalog *catalog, int Ncatalog) {
+
+  int i, j;
+
+  if (!USE_GRID) return;
+
+  /* define cat,meas -> grid pointers */
+  ALLOCATE (bin, int *, Ncatalog);
+  ALLOCATE (Xmeas, int *, Ncatalog);
+  ALLOCATE (Ymeas, int *, Ncatalog);
+  for (i = 0; i < Ncatalog; i++) {
+    ALLOCATE (bin[i], int, MAX (catalog[i].Nmeasure, 1));
+    ALLOCATE (Xmeas[i], int, MAX (catalog[i].Nmeasure, 1));
+    ALLOCATE (Ymeas[i], int, MAX (catalog[i].Nmeasure, 1));
+    for (j = 0; j < catalog[i].Nmeasure; j++) bin[i][j] = -1;
+  }
+
+  /* define grid -> cat,meas pointers */
+  ALLOCATE (Nlist, int, Ngrid);
+  ALLOCATE (NLIST, int, Ngrid);
+  ALLOCATE (clist, int *, Ngrid);
+  ALLOCATE (mlist, int *, Ngrid);
+
+  for (i = 0; i < Ngrid; i++) {
+    Nlist[i] = 0;
+    NLIST[i] = 100;
+    ALLOCATE (clist[i], int, NLIST[i]);
+    ALLOCATE (mlist[i], int, NLIST[i]);
+  }
+}
+
+void freeGridBins (int Ncatalog) {
+
+  int i;
+
+  if (!USE_GRID) return;
+
+  /* define cat,meas -> grid pointers */
+  for (i = 0; i < Ncatalog; i++) {
+    free (bin[i]);
+    free (Xmeas[i]);
+    free (Ymeas[i]);
+  }
+  free (bin);
+  free (Xmeas);
+  free (Ymeas);
+
+  /* define grid -> cat,meas pointers */
+  for (i = 0; i < Ngrid; i++) {
+    free (clist[i]);
+    free (mlist[i]);
+  }
+  free (Nlist);
+  free (NLIST);
+  free (clist);
+  free (mlist);
+}
+
+int setGridMeasure (int meas, int cat, double X, double Y) {
+
+  int ix, iy, i;
+
+  ix = X / RELPHOT_GRID_BINNING;
+  iy = Y / RELPHOT_GRID_BINNING;
+  if (ix < 0) goto escape;
+  if (iy < 0) goto escape;
+  if (ix >= gridX) goto escape;
+  if (iy >= gridY) goto escape;
+
+  i = ix + iy*gridX;
+
+  bin[cat][meas] = i;
+  Xmeas[cat][meas] = X;
+  Ymeas[cat][meas] = Y;
+  clist[i][Nlist[i]] = cat;
+  mlist[i][Nlist[i]] = meas;
+
+  Nlist[i] ++;
+  if (Nlist[i] == NLIST[i]) {
+    NLIST[i] += 100;
+    REALLOCATE (clist[i], int, NLIST[i]);
+    REALLOCATE (mlist[i], int, NLIST[i]);
+  }	
+  return (TRUE);
+
+ escape:
+  fprintf (stderr, "error: star out of grid\n");
+  exit (1);
+}
+
+short getMgrid (int meas, int cat) {
+
+  int i;
+  short value;
+
+  if (!USE_GRID) return (0);
+  i = bin[cat][meas];
+  if (i == -1) return (NO_MAG);
+
+  value = gridM[i];
+  return (value);
+}
+
+/* determine Mgrid values for all grid bins */
+void setMgrid (Catalog *catalog) {
+
+  int i, j, m, c, n, N, Nmax;
+  double *list, *dlist;
+  short Msys, Mrel, Mcal, Mmos;
+  StatType stats;
+  
+  if (!USE_GRID) return;
+
+  Nmax = Nlist[0];
+  for (i = 0; i < Ngrid; i++) {
+    Nmax = MAX (Nmax, Nlist[i]);
+  }
+  ALLOCATE (list, double, Nmax);
+  ALLOCATE (dlist, double, Nmax);
+
+  for (i = 0; i < Ngrid; i++) {
+
+    N = 0;
+    for (j = 0; j < Nlist[i]; j++) {
+      
+      m = mlist[i][j];
+      c = clist[i][j];
+      
+      if (catalog[c].measure[m].flags & MEAS_BAD) continue;
+      if ((Mcal  = getMcal  (m, c)) == NO_MAG) continue;
+      if ((Mmos  = getMmos  (m, c)) == NO_MAG) continue;
+      if ((Mrel  = getMrel  (catalog, m, c)) == NO_MAG) continue;
+      
+      n = catalog[c].measure[m].averef;
+      Msys = iPhotSys (&catalog[c].measure[m], &catalog[c].average[n], &catalog[c].secfilt[n*PhotNsec]);
+      list[N] = Msys - Mrel - Mcal - Mmos;
+      dlist[N] = MAX (catalog[c].measure[m].dM, MIN_ERROR);
+      N++;
+    }
+
+    liststats (list, dlist, N, &stats);
+    gridM[i] = stats.mean;
+    gridS[i] = stats.sigma;
+    gridN[i] = N;
+  }
+  free (list);
+  free (dlist);
+}
+
+void plot_grid (Catalog *catalog) {
+
+  int i, j, m, c, n, N;
+  short Msys, Mrel, Mcal, Mmos;
+  double *xlist, *Mlist, *dlist, *ylist;
+  Graphdata graphdata;
+
+  if (!USE_GRID) return;
+
+  N = 0;
+  for (i = 0; i < Ngrid; i++) 
+    N += Nlist[i];
+
+  ALLOCATE (xlist, double, N);
+  ALLOCATE (ylist, double, N);
+  ALLOCATE (Mlist, double, N);
+  ALLOCATE (dlist, double, N);
+
+  N = 0;
+  for (i = 0; i < Ngrid; i++) {
+    for (j = 0; j < Nlist[i]; j++) {
+      
+      m = mlist[i][j];
+      c = clist[i][j];
+      
+      if (catalog[c].measure[m].flags & MEAS_BAD) continue;
+      if ((Mcal  = getMcal  (m, c)) == NO_MAG) continue;
+      if ((Mmos  = getMmos  (m, c)) == NO_MAG) continue;
+      if ((Mrel  = getMrel  (catalog, m, c)) == NO_MAG) continue;
+
+      n = catalog[c].measure[m].averef;
+      Msys = iPhotSys (&catalog[c].measure[m], &catalog[c].average[n], &catalog[c].secfilt[n*PhotNsec]);
+
+      xlist[N] = Xmeas[c][m];
+      ylist[N] = Ymeas[c][m];
+      Mlist[N] = Msys - Mrel - Mcal - Mmos;
+      dlist[N] = Msys - Mrel - Mcal - Mmos - gridM[i];
+      Mlist[N] *= 0.001;
+      dlist[N] *= 0.001;
+      N++;
+    }
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.ymin = PlotdMmin;
+  graphdata.ymax = PlotdMmax;
+  plot_list (&graphdata, xlist, Mlist, N, "X vs dM raw", "XdM.png");
+  plot_list (&graphdata, xlist, dlist, N, "X vs dM corrected", "XdMf.png");
+  plot_list (&graphdata, ylist, dlist, N, "Y vs dM corrected", "YdMf.png");
+
+  plot_defaults (&graphdata);
+  plot_list (&graphdata, xlist, ylist, N, "X vs Y", "XY.png");
+
+  free (ylist);
+  free (xlist);
+  free (Mlist);
+  free (dlist);
+
+}
+
+int *SelectRefMosaic (Mosaic **refmosaic, int *Nimage);
+Image *getimage (int N);
+
+void dump_grid () { 
+
+  int i, j, Nx, Ny, Nimage;
+  int *imlist;
+  char *p, *pname, ccdname[80];
+  FILE *f;
+  Header header, theader;
+  Matrix matrix;
+  Mosaic *refmosaic;
+  Image *image;
+    
+  /* select reference mosaic image */
+  imlist = SelectRefMosaic (&refmosaic, &Nimage);
+
+  /* we are writing to this file */
+  f = fopen ("mosaic.fits", "w");
+  if (f == (FILE *) NULL) { 
+    fprintf (stderr, "cannot open %s for output\n", "mosaic.fits");
+    return;
+  }
+
+  /* create empty phu */
+  fits_init_header (&header);
+  header.extend = TRUE;
+  fits_create_header (&header);
+  fits_create_matrix (&header, &matrix);
+  fits_modify (&header, "NEXTEND", "%d", 1, Nimage + 3);
+  fits_modify (&header, "FILTER", "%s", 1, photcode[0].name);
+  fits_modify (&header, "COMMENT", "%S", 1, "Mosaic Photometry Grid Analysis");
+  fits_fwrite_header (f, &header);
+  fits_fwrite_matrix (f, &matrix);
+  fits_free_matrix (&matrix);
+
+  /* save grid mag values */
+  fits_init_header (&theader);
+  theader.Naxes = 2;
+  theader.Naxis[0] = gridX;
+  theader.Naxis[1] = gridY;
+  theader.bitpix   = -32;
+  fits_create_Theader (&theader, "IMAGE");
+  fits_modify (&theader, "FILTER", "%s", 1, photcode[0].name);
+  fits_modify (&theader, "EXTNAME", "%s", 1, "MAG_OFFSET");
+  fits_create_matrix  (&theader, &matrix);
+  for (i = 0; i < gridX; i++) {
+    for (j = 0; j < gridY; j++) {
+      fits_set_matrix_value (&matrix, i, j, (double) gridM[i + j*gridX]);
+    }
+  }
+  write_coords (&theader, &refmosaic[0].coords);
+  fits_fwrite_header (f, &theader);
+  fits_fwrite_matrix (f, &matrix);
+  fits_free_matrix (&matrix);
+
+  /* save grid Nmeas values */
+  fits_modify (&theader, "EXTNAME", "%s", 1, "NMEAS");
+  fits_modify (&theader, "FILTER", "%s", 1, photcode[0].name);
+  fits_create_matrix  (&theader, &matrix);
+  for (i = 0; i < gridX; i++) {
+    for (j = 0; j < gridY; j++) {
+      fits_set_matrix_value (&matrix, i, j, (double) gridN[i + j*gridX]);
+    }
+  }
+  write_coords (&theader, &refmosaic[0].coords);
+  fits_fwrite_header (f, &theader);
+  fits_fwrite_matrix (f, &matrix);
+  fits_free_matrix (&matrix);
+
+  /* save grid sigma values */
+  fits_modify (&theader, "EXTNAME", "%s", 1, "SIGMA");
+  fits_modify (&theader, "FILTER", "%s", 1, photcode[0].name);
+  fits_create_matrix  (&theader, &matrix);
+  for (i = 0; i < gridX; i++) {
+    for (j = 0; j < gridY; j++) {
+      fits_set_matrix_value (&matrix, i, j, (double) gridS[i + j*gridX]);
+    }
+  }
+  write_coords (&theader, &refmosaic[0].coords);
+  fits_fwrite_header (f, &theader);
+  fits_fwrite_matrix (f, &matrix);
+  fits_free_matrix (&matrix);
+
+  /* calculate value for each CCD pixel, write out CCD images */
+  for (i = 0; i < Nimage; i++) {
+    image = getimage (imlist[i]);
+    pname = GetPhotcodeNamebyCode (image[0].source);
+
+    /* this is kind of bogus... */
+    /* pname is CAMERA.FILTER.CCD, grab the CCD */
+    p = strrchr (pname, '.');
+    if (p == (char *) NULL) {
+      fprintf (stderr, "error parsing photcode %s\n", pname);
+      exit (2);
+    }
+    p++;
+    sprintf (ccdname, "ccd%s", p);
+
+    fits_modify (&theader, "EXTNAME", "%s", 1, ccdname);
+    fits_modify (&theader, "FILTER", "%s", 1, photcode[0].name);
+    fits_modify (&theader, "PHOTCODE", "%s", 1, pname);
+    fits_modify (&theader, "NX", "%d", 1, image[i].NX);
+    fits_modify (&theader, "NY", "%d", 1, image[i].NY);
+    write_coords (&theader, &image[0].coords);
+
+    Nx = 2 * image[i].NX / RELPHOT_GRID_BINNING;
+    Ny = 2 * image[i].NY / RELPHOT_GRID_BINNING;
+    theader.Naxis[0] = Nx;
+    theader.Naxis[1] = Ny;
+    fits_modify (&theader, "NAXIS1", "%d", 1, Nx);
+    fits_modify (&theader, "NAXIS2", "%d", 1, Ny);
+    fits_create_matrix  (&theader, &matrix);
+
+    InterpolateGrid ((float *)matrix.buffer, Nx, Ny, &image[0].coords, &refmosaic[0].coords);
+    fits_fwrite_header (f, &theader);
+    fits_fwrite_matrix (f, &matrix);
+    fits_free_matrix (&matrix);
+  }
+}
+
+InterpolateGrid (float *buffer, int Nx, int Ny, Coords *ccd, Coords *gcoords) {
+
+  int i, j;
+  double x, y, r, d, X, Y, dx, dy, dVx, dVy, dVxy;
+  double V00, V01, V10, V11;
+  double wV00, wV01, wV10, wV11;
+  double dV00, dV01, dV10, dV11;
+  double v1, v2, value;
+  int ix, iy, N;
+
+  for (i = 0; i < Nx; i++) {
+    for (j = 0; j < Ny; j++) {
+      x = i * RELPHOT_GRID_BINNING / 2;
+      y = j * RELPHOT_GRID_BINNING / 2;
+      XY_to_RD (&r, &d, x, y, ccd);
+      RD_to_XY (&X, &Y, r, d, gcoords);
+
+      X = X / RELPHOT_GRID_BINNING;
+      Y = Y / RELPHOT_GRID_BINNING;
+
+      ix = (int) X;
+      dx = X - ix;
+      iy = (int) Y;
+      dy = Y - iy;
+
+      if (ix < 0) continue;
+      if (iy < 0) continue;
+      if (ix >= gridX) continue;
+      if (iy >= gridY) continue;
+
+      N = ix + iy*gridX;
+      V00 = gridM[N];
+      V10 = gridM[N + 1];
+      V01 = gridM[N + gridX];
+      V11 = gridM[N + gridX + 1];
+
+      dV00 = gridS[N];
+      dV10 = gridS[N + 1];
+      dV01 = gridS[N + gridX];
+      dV11 = gridS[N + gridX + 1];
+
+      wV00 = (dV00 == 0) ? 0.0 : 1 / SQ(dV00);
+      wV01 = (dV01 == 0) ? 0.0 : 1 / SQ(dV01);
+      wV10 = (dV10 == 0) ? 0.0 : 1 / SQ(dV10);
+      wV11 = (dV11 == 0) ? 0.0 : 1 / SQ(dV11);
+
+      v1 = wV00*V00*(1 + dx*dy - dx - dy) +
+	wV10*V10*(dx - dx*dy) +
+	wV01*V01*(dy - dx*dy) +
+	wV11*V11*(dx*dy);
+
+      v2 = wV00*(1 + dx*dy - dx - dy) +
+	wV10*(dx - dx*dy) +
+	wV01*(dy - dx*dy) +
+	wV11*(dx*dy);
+
+      value = v1 / v2;
+      buffer[j*Nx + i] = value;
+    }
+  }
+}
Index: /tags/start/Ohana/src/relphot/src/GridOps.v2.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/GridOps.v2.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/GridOps.v2.c	(revision 12606)
@@ -0,0 +1,579 @@
+# include "relphot.h"
+
+static int     Ngrid;
+static short   *gridM;
+static short   *gridS;
+static int     *gridN;
+static int      gridX;
+static int      gridY;
+
+static int    **bin;
+static int    **Xmeas;
+static int    **Ymeas;
+
+static int    **clist;
+static int    **mlist;
+static int     *Nlist;
+static int     *NLIST;
+
+static struct {
+  int Nchip;
+  int Mx, My;  /* mosaic size in chips */
+  int Nx, Ny;  /* chip size in pixels */
+  int *Fx, *Fy;  /* chip flip */
+  int *Ox, *Oy;  /* chip offset */
+  char **ccdname;
+} camera;    
+
+# ifdef GRID_V1
+void initGrid (int dX, int dY) {
+
+  int i;
+
+  /* define mosaic 2d correction grid */
+  gridX = dX / RELPHOT_GRID_BINNING + 1;
+  gridY = dY / RELPHOT_GRID_BINNING + 1;
+  Ngrid = gridX * gridY;
+
+  ALLOCATE (gridM, short, Ngrid);
+  ALLOCATE (gridS, short, Ngrid);
+  ALLOCATE (gridN, int,   Ngrid);
+  bzero (gridM, Ngrid*sizeof(short));
+  bzero (gridS, Ngrid*sizeof(short));
+  bzero (gridN, Ngrid*sizeof(int));
+
+}
+# endif
+
+# ifdef GRID_V2
+void initGrid (int dX, int dY) {
+
+  int i;
+  char field[64], *config, line[256];
+
+  /* load camera config file */
+  config = LoadConfigFile (CameraConfig);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find camera config file %s\n", CameraConfig);
+    exit (1);
+  }
+
+  /* load basic mosaic parameters */
+  ScanConfig (config, "NCCD", "%d", 1, &camera.Nchip);
+  ScanConfig (config, "MOSAIC_X", "%d", 1, &camera.Mx);
+  ScanConfig (config, "MOSAIC_Y", "%d", 1, &camera.My);
+  ScanConfig (config, "NAXIS1", "%d", 1, &camera.Nx);
+  ScanConfig (config, "NAXIS2", "%d", 1, &camera.Ny);
+
+  ALLOCATE (camera.Fx, int, camera.Nchip);
+  ALLOCATE (camera.Fy, int, camera.Nchip);
+  ALLOCATE (camera.Ox, int, camera.Nchip);
+  ALLOCATE (camera.Oy, int, camera.Nchip);
+  ALLOCATE (camera.ccdname, char *, camera.Nchip);
+
+  /* load per-chip parameters */
+  for (i = 0; i < camera.Nchip; i++) {
+    ALLOCATE (camera.ccdname[i], char, 256);
+    sprintf (field, "CCD.%d", i);
+    ScanConfig (config, field, "%s", 1, line);
+    sscanf (line, "%s %d %d %d %d", camera.ccdname[i], &camera.Ox[i], &camera.Oy[i], &camera.Fx[i], &camera.Fy[i]);
+  }
+  free (config);
+
+  /* define mosaic 2d correction grid: 
+   * GRID_X is the number of grid pixels per chip in the X direction */
+  gridX = RELPHOT_GRID_X * camera.Mx;
+  gridY = RELPHOT_GRID_Y * camera.My;
+  Ngrid = gridX * gridY;
+
+  ALLOCATE (gridM, short, Ngrid);
+  ALLOCATE (gridS, short, Ngrid);
+  ALLOCATE (gridN, int,   Ngrid);
+  bzero (gridM, Ngrid*sizeof(short));
+  bzero (gridS, Ngrid*sizeof(short));
+  bzero (gridN, Ngrid*sizeof(int));
+
+}
+# endif
+
+void initGridBins (Catalog *catalog, int Ncatalog) {
+
+  int i, j;
+
+  if (!USE_GRID) return;
+
+  /* define cat,meas -> grid pointers */
+  ALLOCATE (bin, int *, Ncatalog);
+  ALLOCATE (Xmeas, int *, Ncatalog);
+  ALLOCATE (Ymeas, int *, Ncatalog);
+  for (i = 0; i < Ncatalog; i++) {
+    ALLOCATE (bin[i], int, MAX (catalog[i].Nmeasure, 1));
+    ALLOCATE (Xmeas[i], int, MAX (catalog[i].Nmeasure, 1));
+    ALLOCATE (Ymeas[i], int, MAX (catalog[i].Nmeasure, 1));
+    for (j = 0; j < catalog[i].Nmeasure; j++) bin[i][j] = -1;
+  }
+
+  /* define grid -> cat,meas pointers */
+  ALLOCATE (Nlist, int, Ngrid);
+  ALLOCATE (NLIST, int, Ngrid);
+  ALLOCATE (clist, int *, Ngrid);
+  ALLOCATE (mlist, int *, Ngrid);
+
+  for (i = 0; i < Ngrid; i++) {
+    Nlist[i] = 0;
+    NLIST[i] = 100;
+    ALLOCATE (clist[i], int, NLIST[i]);
+    ALLOCATE (mlist[i], int, NLIST[i]);
+  }
+}
+
+void freeGridBins (int Ncatalog) {
+
+  int i;
+
+  if (!USE_GRID) return;
+
+  /* define cat,meas -> grid pointers */
+  for (i = 0; i < Ncatalog; i++) {
+    free (bin[i]);
+    free (Xmeas[i]);
+    free (Ymeas[i]);
+  }
+  free (bin);
+  free (Xmeas);
+  free (Ymeas);
+
+  /* define grid -> cat,meas pointers */
+  for (i = 0; i < Ngrid; i++) {
+    free (clist[i]);
+    free (mlist[i]);
+  }
+  free (Nlist);
+  free (NLIST);
+  free (clist);
+  free (mlist);
+}
+
+# ifdef GRID_V1
+int setGridMeasure (int meas, int cat, double X, double Y) {
+
+  int ix, iy, i;
+
+  ix = X / RELPHOT_GRID_BINNING;
+  iy = Y / RELPHOT_GRID_BINNING;
+  if (ix < 0) goto escape;
+  if (iy < 0) goto escape;
+  if (ix >= gridX) goto escape;
+  if (iy >= gridY) goto escape;
+
+  i = ix + iy*gridX;
+
+  bin[cat][meas] = i;
+  Xmeas[cat][meas] = X;
+  Ymeas[cat][meas] = Y;
+  clist[i][Nlist[i]] = cat;
+  mlist[i][Nlist[i]] = meas;
+
+  Nlist[i] ++;
+  if (Nlist[i] == NLIST[i]) {
+    NLIST[i] += 100;
+    REALLOCATE (clist[i], int, NLIST[i]);
+    REALLOCATE (mlist[i], int, NLIST[i]);
+  }	
+  return (TRUE);
+
+escape:
+  fprintf (stderr, "error: star out of grid\n");
+  exit (1);
+}
+# endif
+
+# ifdef GRID_V2
+int setGridMeasure (int meas, int cat, double X, double Y, int ccdnum) {
+
+  int ix, iy, Cx, Cy, i;
+  double x, y;
+
+  /* X, Y are chip coords on chip ccdnum */
+
+  /* normalize X & Y */
+  x = X;
+  if (camera.Fx[ccdnum]) x = camera.Nx - X;
+  y = Y;
+  if (camera.Fy[ccdnum]) y = camera.Ny - Y;
+
+  /* grid coords on the chip */
+  Cx = MIN (MAX ((x / camera.Nx) * RELPHOT_GRID_X, 0), RELPHOT_GRID_X - 1);
+  Cy = MIN (MAX ((y / camera.Ny) * RELPHOT_GRID_Y, 0), RELPHOT_GRID_Y - 1);
+  
+  /* coordinates in the grid */
+  ix = Cx + camera.Ox[ccdnum]*RELPHOT_GRID_X;
+  iy = Cy + camera.Oy[ccdnum]*RELPHOT_GRID_Y;
+
+  i = ix + iy*gridX;
+
+  bin[cat][meas] = i;
+  Xmeas[cat][meas] = x + camera.Ox[ccdnum]*camera.Nx;
+  Ymeas[cat][meas] = Y + camera.Oy[ccdnum]*camera.Ny;
+  clist[i][Nlist[i]] = cat;
+  mlist[i][Nlist[i]] = meas;
+
+  Nlist[i] ++;
+  if (Nlist[i] == NLIST[i]) {
+    NLIST[i] += 100;
+    REALLOCATE (clist[i], int, NLIST[i]);
+    REALLOCATE (mlist[i], int, NLIST[i]);
+  }	
+  return (TRUE);
+
+escape:
+  fprintf (stderr, "error: star out of grid\n");
+  exit (1);
+}
+# endif
+
+short getMgrid (int meas, int cat) {
+
+  int i;
+  short value;
+
+  if (!USE_GRID) return (0);
+  i = bin[cat][meas];
+  if (i == -1) return (NO_MAG);
+
+  value = gridM[i];
+  return (value);
+}
+
+/* determine Mgrid values for all grid bins */
+void setMgrid (Catalog *catalog) {
+
+  int i, j, m, c, n, N, Nmax;
+  double *list, *dlist;
+  short Msys, Mrel, Mcal, Mmos;
+  StatType stats;
+  
+  if (!USE_GRID) return;
+
+  Nmax = Nlist[0];
+  for (i = 0; i < Ngrid; i++) {
+    Nmax = MAX (Nmax, Nlist[i]);
+  }
+  ALLOCATE (list, double, Nmax);
+  ALLOCATE (dlist, double, Nmax);
+
+  for (i = 0; i < Ngrid; i++) {
+
+    N = 0;
+    for (j = 0; j < Nlist[i]; j++) {
+      
+      m = mlist[i][j];
+      c = clist[i][j];
+      
+      if (catalog[c].measure[m].flags & MEAS_BAD) continue;
+      if ((Mcal  = getMcal  (m, c)) == NO_MAG) continue;
+      if ((Mmos  = getMmos  (m, c)) == NO_MAG) continue;
+      if ((Mrel  = getMrel  (catalog, m, c)) == NO_MAG) continue;
+      
+      n = catalog[c].measure[m].averef;
+      Msys = iPhotSys (&catalog[c].measure[m], &catalog[c].average[n], &catalog[c].secfilt[n*PhotNsec]);
+      list[N] = Msys - Mrel - Mcal - Mmos;
+      dlist[N] = MAX (catalog[c].measure[m].dM, MIN_ERROR);
+      N++;
+    }
+
+    liststats (list, dlist, N, &stats);
+    gridM[i] = stats.mean;
+    gridS[i] = stats.sigma;
+    gridN[i] = N;
+  }
+  free (list);
+  free (dlist);
+}
+
+void plot_grid (Catalog *catalog) {
+
+  int i, j, m, c, n, N;
+  short Msys, Mrel, Mcal, Mmos;
+  double *xlist, *Mlist, *dlist, *ylist;
+  Graphdata graphdata;
+
+  if (!USE_GRID) return;
+
+  N = 0;
+  for (i = 0; i < Ngrid; i++) 
+    N += Nlist[i];
+
+  ALLOCATE (xlist, double, N);
+  ALLOCATE (ylist, double, N);
+  ALLOCATE (Mlist, double, N);
+  ALLOCATE (dlist, double, N);
+
+  N = 0;
+  for (i = 0; i < Ngrid; i++) {
+    for (j = 0; j < Nlist[i]; j++) {
+      
+      m = mlist[i][j];
+      c = clist[i][j];
+      
+      if (catalog[c].measure[m].flags & MEAS_BAD) continue;
+      if ((Mcal  = getMcal  (m, c)) == NO_MAG) continue;
+      if ((Mmos  = getMmos  (m, c)) == NO_MAG) continue;
+      if ((Mrel  = getMrel  (catalog, m, c)) == NO_MAG) continue;
+
+      n = catalog[c].measure[m].averef;
+      Msys = iPhotSys (&catalog[c].measure[m], &catalog[c].average[n], &catalog[c].secfilt[n*PhotNsec]);
+
+      xlist[N] = Xmeas[c][m];
+      ylist[N] = Ymeas[c][m];
+      Mlist[N] = Msys - Mrel - Mcal - Mmos;
+      dlist[N] = Msys - Mrel - Mcal - Mmos - gridM[i];
+      Mlist[N] *= 0.001;
+      dlist[N] *= 0.001;
+      N++;
+    }
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.ymin = PlotdMmin;
+  graphdata.ymax = PlotdMmax;
+  plot_list (&graphdata, xlist, Mlist, N, "X vs dM raw", "XdM.png");
+  plot_list (&graphdata, xlist, dlist, N, "X vs dM corrected", "XdMf.png");
+  plot_list (&graphdata, ylist, dlist, N, "Y vs dM corrected", "YdMf.png");
+
+  plot_defaults (&graphdata);
+  plot_list (&graphdata, xlist, ylist, N, "X vs Y", "XY.png");
+
+  free (ylist);
+  free (xlist);
+  free (Mlist);
+  free (dlist);
+
+}
+
+int *SelectRefMosaic (Mosaic **refmosaic, int *Nimage);
+Image *getimage (int N);
+
+void dump_grid () { 
+
+  int i, j, Nx, Ny, Nimage;
+  int *imlist;
+  char *p, *pname, ccdname[80];
+  FILE *f;
+  Header header, theader;
+  Matrix matrix;
+  Mosaic *refmosaic;
+  Image *image;
+    
+  /* select reference mosaic image */
+  imlist = SelectRefMosaic (&refmosaic, &Nimage);
+
+  /* we are writing to this file */
+  f = fopen ("mosaic.fits", "w");
+  if (f == (FILE *) NULL) { 
+    fprintf (stderr, "cannot open %s for output\n", "mosaic.fits");
+    return;
+  }
+
+  /* create empty phu */
+  fits_init_header (&header);
+  header.extend = TRUE;
+  fits_create_header (&header);
+  fits_create_matrix (&header, &matrix);
+  fits_modify (&header, "NEXTEND", "%d", 1, Nimage + 3);
+  fits_modify (&header, "FILTER", "%s", 1, photcode[0].name);
+  fits_modify (&header, "COMMENT", "%S", 1, "Mosaic Photometry Grid Analysis");
+  fits_fwrite_header (f, &header);
+  fits_fwrite_matrix (f, &matrix);
+  fits_free_matrix (&matrix);
+
+  /* save grid mag values */
+  fits_init_header (&theader);
+  theader.Naxes = 2;
+  theader.Naxis[0] = gridX;
+  theader.Naxis[1] = gridY;
+  theader.bitpix   = -32;
+  fits_create_Theader (&theader, "IMAGE");
+  fits_modify (&theader, "FILTER", "%s", 1, photcode[0].name);
+  fits_modify (&theader, "EXTNAME", "%s", 1, "MAG_OFFSET");
+  fits_create_matrix  (&theader, &matrix);
+  for (i = 0; i < gridX; i++) {
+    for (j = 0; j < gridY; j++) {
+      fits_set_matrix_value (&matrix, i, j, (double) gridM[i + j*gridX]);
+    }
+  }
+  write_coords (&theader, &refmosaic[0].coords);
+  fits_fwrite_header (f, &theader);
+  fits_fwrite_matrix (f, &matrix);
+  fits_free_matrix (&matrix);
+
+  /* save grid Nmeas values */
+  fits_modify (&theader, "EXTNAME", "%s", 1, "NMEAS");
+  fits_modify (&theader, "FILTER", "%s", 1, photcode[0].name);
+  fits_create_matrix  (&theader, &matrix);
+  for (i = 0; i < gridX; i++) {
+    for (j = 0; j < gridY; j++) {
+      fits_set_matrix_value (&matrix, i, j, (double) gridN[i + j*gridX]);
+    }
+  }
+  write_coords (&theader, &refmosaic[0].coords);
+  fits_fwrite_header (f, &theader);
+  fits_fwrite_matrix (f, &matrix);
+  fits_free_matrix (&matrix);
+
+  /* save grid sigma values */
+  fits_modify (&theader, "EXTNAME", "%s", 1, "SIGMA");
+  fits_modify (&theader, "FILTER", "%s", 1, photcode[0].name);
+  fits_create_matrix  (&theader, &matrix);
+  for (i = 0; i < gridX; i++) {
+    for (j = 0; j < gridY; j++) {
+      fits_set_matrix_value (&matrix, i, j, (double) gridS[i + j*gridX]);
+    }
+  }
+  write_coords (&theader, &refmosaic[0].coords);
+  fits_fwrite_header (f, &theader);
+  fits_fwrite_matrix (f, &matrix);
+  fits_free_matrix (&matrix);
+
+# ifdef GRID_V1
+  /* calculate pixel values for each CCD pixel, write out CCD images */
+  /* grid pixels are in RA,DEC coords, transform to image and interpolate */
+  for (i = 0; i < Nimage; i++) {
+    image = getimage (imlist[i]);
+    pname = GetPhotcodeNamebyCode (image[0].source);
+
+    /* this is kind of bogus... */
+    /* pname is CAMERA.FILTER.CCD, grab the CCD */
+    p = strrchr (pname, '.');
+    if (p == (char *) NULL) {
+      fprintf (stderr, "error parsing photcode %s\n", pname);
+      exit (2);
+    }
+    p++;
+    sprintf (ccdname, "ccd%s", p);
+
+    fits_modify (&theader, "EXTNAME", "%s", 1, ccdname);
+    fits_modify (&theader, "FILTER", "%s", 1, photcode[0].name);
+    fits_modify (&theader, "PHOTCODE", "%s", 1, pname);
+    fits_modify (&theader, "NX", "%d", 1, image[i].NX);
+    fits_modify (&theader, "NY", "%d", 1, image[i].NY);
+    write_coords (&theader, &image[0].coords);
+
+    Nx = 2 * image[i].NX / RELPHOT_GRID_BINNING;
+    Ny = 2 * image[i].NY / RELPHOT_GRID_BINNING;
+    theader.Naxis[0] = Nx;
+    theader.Naxis[1] = Ny;
+    fits_modify (&theader, "NAXIS1", "%d", 1, Nx);
+    fits_modify (&theader, "NAXIS2", "%d", 1, Ny);
+    fits_create_matrix  (&theader, &matrix);
+
+    InterpolateGrid ((float *)matrix.buffer, Nx, Ny, &image[0].coords, &refmosaic[0].coords);
+    fits_fwrite_header (f, &theader);
+    fits_fwrite_matrix (f, &matrix);
+    fits_free_matrix (&matrix);
+  }
+# endif
+
+# ifdef GRID_V2
+  /* calculate value for each CCD pixel, write out CCD images */
+  /* grid pixels are tied to detector pixels, but are flipped to match focal plane */
+  for (i = 0; i < camera.Nchip; i++) {
+    int ix, iy, x, y, X, Y, bin;
+
+    fits_modify (&theader, "EXTNAME", "%s", 1, camera.ccdname[i]);
+    fits_modify (&theader, "FILTER", "%s", 1, photcode[0].name);
+    fits_modify (&theader, "NX", "%d", 1, camera.Nx);
+    fits_modify (&theader, "NY", "%d", 1, camera.Ny);
+      
+    theader.Naxis[0] = RELPHOT_GRID_X;
+    theader.Naxis[1] = RELPHOT_GRID_Y;
+    fits_modify (&theader, "NAXIS1", "%d", 1, RELPHOT_GRID_X);
+    fits_modify (&theader, "NAXIS2", "%d", 1, RELPHOT_GRID_Y);
+    fits_create_matrix  (&theader, &matrix);
+
+    for (Y = 0; Y < RELPHOT_GRID_Y; Y++) {
+      for (X = 0; X < RELPHOT_GRID_X; X++) {
+	      
+	/* normalize X & Y */
+	x = X;
+	if (camera.Fx[i]) x = RELPHOT_GRID_X - X - 1;
+	y = Y;
+	if (camera.Fy[i]) y = RELPHOT_GRID_Y - Y - 1;
+	      
+	/* coordinates in the grid */
+	ix = x + camera.Ox[i]*RELPHOT_GRID_X;
+	iy = y + camera.Oy[i]*RELPHOT_GRID_Y;
+	      
+	bin = ix + iy*gridX;
+	fits_set_matrix_value (&matrix, X, Y, (double) gridM[bin]);
+      }
+    }
+    fits_fwrite_header (f, &theader);
+    fits_fwrite_matrix (f, &matrix);
+    fits_free_matrix (&matrix);
+  }
+# endif
+
+}
+
+InterpolateGrid (float *buffer, int Nx, int Ny, Coords *ccd, Coords *gcoords) {
+
+  int i, j;
+  double x, y, r, d, X, Y, dx, dy, dVx, dVy, dVxy;
+  double V00, V01, V10, V11;
+  double wV00, wV01, wV10, wV11;
+  double dV00, dV01, dV10, dV11;
+  double v1, v2, value;
+  int ix, iy, N;
+
+  for (i = 0; i < Nx; i++) {
+    for (j = 0; j < Ny; j++) {
+      x = i * RELPHOT_GRID_BINNING / 2;
+      y = j * RELPHOT_GRID_BINNING / 2;
+      XY_to_RD (&r, &d, x, y, ccd);
+      RD_to_XY (&X, &Y, r, d, gcoords);
+
+      X = X / RELPHOT_GRID_BINNING;
+      Y = Y / RELPHOT_GRID_BINNING;
+
+      ix = (int) X;
+      dx = X - ix;
+      iy = (int) Y;
+      dy = Y - iy;
+
+      if (ix < 0) continue;
+      if (iy < 0) continue;
+      if (ix >= gridX) continue;
+      if (iy >= gridY) continue;
+
+      N = ix + iy*gridX;
+      V00 = gridM[N];
+      V10 = gridM[N + 1];
+      V01 = gridM[N + gridX];
+      V11 = gridM[N + gridX + 1];
+
+      dV00 = gridS[N];
+      dV10 = gridS[N + 1];
+      dV01 = gridS[N + gridX];
+      dV11 = gridS[N + gridX + 1];
+
+      wV00 = (dV00 == 0) ? 0.0 : 1 / SQ(dV00);
+      wV01 = (dV01 == 0) ? 0.0 : 1 / SQ(dV01);
+      wV10 = (dV10 == 0) ? 0.0 : 1 / SQ(dV10);
+      wV11 = (dV11 == 0) ? 0.0 : 1 / SQ(dV11);
+
+      v1 = wV00*V00*(1 + dx*dy - dx - dy) +
+	wV10*V10*(dx - dx*dy) +
+	wV01*V01*(dy - dx*dy) +
+	wV11*V11*(dx*dy);
+
+      v2 = wV00*(1 + dx*dy - dx - dy) +
+	wV10*(dx - dx*dy) +
+	wV01*(dy - dx*dy) +
+	wV11*(dx*dy);
+
+      value = v1 / v2;
+      buffer[j*Nx + i] = value;
+    }
+  }
+}
Index: /tags/start/Ohana/src/relphot/src/ImageOps.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/ImageOps.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/ImageOps.c	(revision 12606)
@@ -0,0 +1,465 @@
+# include "relphot.h"
+
+static unsigned int *start;
+static unsigned int *stop;
+static int         **bin;
+
+static int         **clist;
+static int         **mlist;
+static int          *Nlist;
+static int          *NLIST;
+
+static Image        *image;
+static int          Nimage;
+
+void initImages (Image *input, int N) {
+
+  int i, j;
+
+  image = input;
+  Nimage = N;
+
+  ALLOCATE (start,   unsigned, Nimage);
+  ALLOCATE (stop,    unsigned, Nimage);
+
+  for (i = 0; i < Nimage; i++) {
+    start[i] = image[i].tzero - MAX(0.05*image[i].trate*image[i].NY, 1);
+    stop[i]  = image[i].tzero + MAX(1.05*image[i].trate*image[i].NY, 1);
+  }
+}
+
+void initImageBins (Catalog *catalog, int Ncatalog) {
+
+  int i, j;
+
+  ALLOCATE (bin, int *, Ncatalog);
+  for (i = 0; i < Ncatalog; i++) {
+    ALLOCATE (bin[i], int, MAX (catalog[i].Nmeasure, 1));
+    for (j = 0; j < catalog[i].Nmeasure; j++) bin[i][j] = -1;
+  }
+
+  ALLOCATE (Nlist, int, Nimage);
+  ALLOCATE (NLIST, int, Nimage);
+  ALLOCATE (clist, int *, Nimage);
+  ALLOCATE (mlist, int *, Nimage);
+
+  for (i = 0; i < Nimage; i++) {
+    Nlist[i] = 0;
+    NLIST[i] = 100;
+    ALLOCATE (clist[i], int, NLIST[i]);
+    ALLOCATE (mlist[i], int, NLIST[i]);
+  }
+}
+
+void freeImageBins (int Ncatalog) {
+
+  int i;
+
+  for (i = 0; i < Ncatalog; i++) {
+    free (bin[i]);
+  }
+  free (bin);
+  for (i = 0; i < Nimage; i++) {
+    free (clist[i]);
+    free (mlist[i]);
+  }
+  free (clist);
+  free (mlist);
+}
+
+/* select all image equivalent to the current photcode */
+void findImages (Catalog *catalog, int Ncatalog) {
+
+  int i, j, ecode;
+
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Nmeasure; j++) {
+      ecode = GetPhotcodeEquivCodebyCode (catalog[i].measure[j].source);
+      if (photcode[0].code != ecode) continue;
+      matchImage (catalog, j, i);
+    }
+  }
+}
+
+void matchImage (Catalog *catalog, int meas, int cat) {
+
+  int i, ave, ccdnum;
+  double ra, dec, X, Y;
+  char *pname, *filter, *p, base[256];
+  Measure *measure;
+  
+  measure = &catalog[cat].measure[meas];
+  for (i = 0; i < Nimage; i++) {
+    if (image[0].source == -1) continue;
+    if (measure[0].source != image[i].source) continue;
+    if (measure[0].t < start[i]) continue;
+    if (measure[0].t > stop[i]) continue;
+    
+# ifdef GRID_V2 /* this section is added to support GridOps.v2.c */
+    if (USE_GRID) {
+
+      /* identify the ccd on the basis of the photcode name */
+      pname = GetPhotcodeNamebyCode (image[i].source);
+      filter = photcode[0].name;
+      sprintf (base, "%s.%s.", MOSAICNAME, filter);
+      if (strncmp (pname, base, strlen (base))) continue;
+      p = pname + strlen(base);
+      if (*p == 0) continue;
+      ccdnum = atoi (p);
+      /* some ambiguity here between seq number and id number */
+
+      /* add this measurement to the grid cell for this chip */
+      ave = measure[0].averef;
+      ra  = catalog[cat].average[ave].R - measure[0].dR / 360000.0;
+      dec = catalog[cat].average[ave].D - measure[0].dD / 360000.0;
+       
+      /* X,Y always positive-definite in range 0,0 - dX, dY */
+      RD_to_XY (&X, &Y, ra, dec, &image[i].coords);
+      setGridMeasure (meas, cat, X, Y, ccdnum);
+    }
+# endif
+
+    bin[cat][meas] = i;
+
+    clist[i][Nlist[i]] = cat;
+    mlist[i][Nlist[i]] = meas;
+    Nlist[i] ++;
+
+    if (Nlist[i] == NLIST[i]) {
+      NLIST[i] += 100;
+      REALLOCATE (clist[i], int, NLIST[i]);
+      REALLOCATE (mlist[i], int, NLIST[i]);
+    }	
+    return;
+  }
+  /*  fprintf (stderr, "can't find source image for this measurement: %d (%d)\n", measure[0].t, measure[0].source); */
+}
+
+short getMcal (int meas, int cat) {
+
+  int i;
+  short value;
+
+  i = bin[cat][meas];
+  if (i == -1) return (NO_MAG);
+
+  if (image[i].code & IMAGE_BAD)  return (NO_MAG);  
+  value = image[i].Mcal;
+  return (value);
+}
+
+Coords *getCoords (int meas, int cat) {
+
+  int i;
+  short value;
+
+  i = bin[cat][meas];
+  if (i == -1) return (NULL);
+  return (&image[i].coords);
+}
+
+/* determine Mcal values for all images */
+void setMcal (Catalog *catalog, int PoorImages) {
+
+  int i, j, m, c, n, N, Nmax, mark, bad;
+  short Msys, Mrel, Mmos, Mgrid;
+  double *list, *dlist;
+  StatType stats;
+
+  if (FREEZE_IMAGES) return;
+
+  if (PoorImages) {
+    IMAGE_BAD = STAR_BAD = MEAS_BAD = 0;
+  }
+
+  Nmax = 0;
+  for (i = 0; i < Nimage; i++) {
+    Nmax = MAX (Nmax, Nlist[i]);
+  }
+  ALLOCATE (list, double, Nmax);
+  ALLOCATE (dlist, double, Nmax);
+
+  for (i = 0; i < Nimage; i++) {
+    
+    /* on PoorImages run, skip good images */
+    if (PoorImages) {
+      bad = image[i].code & (ID_IMAGE_FEW | ID_IMAGE_POOR | ID_IMAGE_SKIP);
+      if (!bad) continue;
+    }      
+
+    N = 0;
+    for (j = 0; j < Nlist[i]; j++) {
+      
+      m = mlist[i][j];
+      c = clist[i][j];
+      
+      if (catalog[c].measure[m].flags & MEAS_BAD) continue;
+      if ((Mmos  = getMmos  (m, c)) == NO_MAG) continue;
+      if ((Mgrid = getMgrid (m, c)) == NO_MAG) continue;
+      if ((Mrel  = getMrel  (catalog, m, c)) == NO_MAG) continue;
+      
+      n = catalog[c].measure[m].averef;
+      Msys = iPhotSys (&catalog[c].measure[m], &catalog[c].average[n], &catalog[c].secfilt[n*PhotNsec]);
+      list[N] = Msys - Mrel - Mmos - Mgrid;
+      dlist[N] = MAX (catalog[c].measure[m].dM, MIN_ERROR);
+      N++;
+    }
+    /* Nlist[i] is all measurements, N is good measurements */
+
+    /* too few good measurements or too many bad measurements */
+    if (!PoorImages) {
+      mark = (N < IMAGE_TOOFEW) || (N < IMAGE_GOOD_FRACTION*Nlist[i]);
+      if (mark) {
+	image[i].code |= ID_IMAGE_FEW;
+      } else {
+	image[i].code &= ~ID_IMAGE_FEW;
+      }      
+    }
+    
+    liststats (list, dlist, N, &stats);
+    image[i].Mcal  = stats.mean;
+    image[i].dMcal = stats.sigma;
+    image[i].Xm    = 100.0*log10(stats.chisq);
+  }
+  free (list);
+  free (dlist);
+  if (PoorImages) {
+    IMAGE_BAD = ID_IMAGE_POOR | ID_IMAGE_FEW | ID_IMAGE_SKIP;
+    STAR_BAD  = ID_STAR_POOR | ID_STAR_FEW;
+    MEAS_BAD  = ID_MEAS_NOCAL | ID_MEAS_POOR | ID_MEAS_SKIP | ID_MEAS_AREA;
+  }
+  return;
+}
+
+/* mark image if: abs(Mcal) too large, dMcal too large */
+void clean_images () {
+
+  int i, N, mark, Nmark;
+  double *mlist, *slist, *dlist;
+  double MaxOffset, MaxScatter, MedOffset;
+  StatType stats;
+
+  if (FREEZE_IMAGES) return;
+
+  if (VERBOSE) fprintf (stderr, "marking poor images\n");
+
+  ALLOCATE (mlist, double, Nimage);
+  ALLOCATE (slist, double, Nimage);
+  ALLOCATE (dlist, double, Nimage);
+
+  for (i = N = 0; i < Nimage; i++) {
+    if (image[i].code & IMAGE_BAD) continue;
+    mlist[N] = fabs (image[i].Mcal);
+    slist[N] = image[i].dMcal;
+    dlist[N] = 1;
+    N++;
+  }
+  initstats ("MEAN");
+  liststats (mlist, dlist, N, &stats);
+  MaxOffset = MAX (IMAGE_OFFSET, 3*stats.sigma);
+  MedOffset = stats.median;
+  liststats (slist, dlist, N, &stats);
+  MaxScatter = MAX (IMAGE_SCATTER, 2*stats.median);
+  fprintf (stderr, "Mrel: %f, dMrel: %f, Max Scatter: %f, Max Offset: %f\n", 0.001*MedOffset, 0.001*stats.median, 0.001*MaxScatter, 0.001*MaxOffset);
+  
+  Nmark = 0;
+  for (i = 0; i < Nimage; i++) {
+    mark = FALSE;
+    image[i].code &= ~ID_IMAGE_POOR;
+    mark = (image[i].dMcal > MaxScatter) || (fabs(image[i].Mcal - MedOffset) > MaxOffset);
+    if (mark) { 
+      Nmark ++;
+      image[i].code |= ID_IMAGE_POOR;
+    } else {
+      image[i].code &= ~ID_IMAGE_POOR;
+    }
+  }
+
+  fprintf (stderr, "%d images marked poor\n", Nmark);
+  initstats (STATMODE);
+  free (mlist);
+  free (slist);
+  free (dlist);
+}
+
+void plot_images () {
+
+  int i, j, m, c, N, Nmax, bin;
+  short Mrel, Mcal, Mmos;
+  double *xlist, *Mlist, *dlist;
+  Graphdata graphdata;
+
+  if (FREEZE_IMAGES) return;
+
+  ALLOCATE (xlist, double, Nimage);
+  ALLOCATE (dlist, double, Nimage);
+  ALLOCATE (Mlist, double, Nimage);
+
+  /**** dMcal vs airmass ****/
+  for (i = 0; i < Nimage; i++) {
+    Mlist[i] = 0.001*image[i].Mcal;
+    dlist[i] = 0.001*image[i].dMcal;
+    xlist[i] = 0.001*image[i].secz;
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.ymin = PlotdMmin; 
+  graphdata.ymax = PlotdMmax;
+  plot_list (&graphdata, xlist, Mlist, Nimage, "airmass vs Mcal", "airmass.png");
+  plot_defaults (&graphdata);
+  plot_list (&graphdata, Mlist, dlist, Nimage, "Mcal vs dMcal", NULL);
+
+# define NBIN 200
+  REALLOCATE (xlist, double, NBIN);
+  REALLOCATE (Mlist, double, NBIN);
+
+  /**** dMcal histgram ****/
+  for (i = 0; i < NBIN; i++) xlist[i] = 0.0025*i;
+  bzero (Mlist, NBIN*sizeof(double));
+  for (i = 0; i < Nimage; i++) {
+    bin = 0.001*image[i].dMcal / 0.0025;
+    bin = MAX (0, MIN (NBIN - 1, bin));
+    Mlist[bin] += 1.0;
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.style = 1;
+  plot_list (&graphdata, xlist, Mlist, NBIN, "dMcal hist", "dMcalhist.png");
+
+  free (dlist);
+  free (xlist);
+  free (Mlist);
+}
+
+StatType statsImageN (Catalog *catalog) {
+
+  int i, j, k, m, c, n, N, Nmax;
+  double *list, *dlist;
+  StatType stats;
+
+  bzero (&stats, sizeof (StatType));
+  if (FREEZE_IMAGES) return (stats);
+
+  ALLOCATE (list, double, Nimage);
+  ALLOCATE (dlist, double, Nimage);
+
+  n = 0;
+  for (i = 0; i < Nimage; i++) {
+    if (image[i].code & IMAGE_BAD)  continue;
+
+    N = 0;
+    for (j = 0; j < Nlist[i]; j++) {
+
+      m = mlist[i][j];
+      c = clist[i][j];
+
+      if (getMcal  (m, c) == NO_MAG) continue;
+      if (getMmos  (m, c) == NO_MAG) continue;
+      if (getMgrid (m, c) == NO_MAG) continue;
+      N++;
+    }
+    list[n] = N;
+    dlist[n] = 1;
+    n++;
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+StatType statsImageX (Catalog *catalog) {
+
+  int i, j, k, m, n, N, Nmax;
+  double *list, *dlist;
+  StatType stats;
+
+  bzero (&stats, sizeof (StatType));
+  if (FREEZE_IMAGES) return (stats);
+
+  ALLOCATE (list, double, Nimage);
+  ALLOCATE (dlist, double, Nimage);
+
+  n = 0;
+  for (i = 0; i < Nimage; i++) {
+
+    if (image[i].code & IMAGE_BAD)  continue;
+
+    list[n] = pow (10.0, 0.01*image[i].Xm);
+    dlist[n] = 1;
+    n++;
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+StatType statsImageM (Catalog *catalog) {
+
+  int i, j, k, m, n, N, Nmax;
+  double *list, *dlist;
+  StatType stats;
+
+  bzero (&stats, sizeof (StatType));
+  if (FREEZE_IMAGES) return (stats);
+
+  ALLOCATE (list, double, Nimage);
+  ALLOCATE (dlist, double, Nimage);
+
+  n = 0;
+  for (i = 0; i < Nimage; i++) {
+
+    if (image[i].code & IMAGE_BAD)  continue;
+
+    list[n] = 0.001*image[i].Mcal;
+    dlist[n] = 1;
+    n++;
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+StatType statsImagedM (Catalog *catalog) {
+
+  int i, j, k, m, n, N, Nmax;
+  double *list, *dlist;
+  StatType stats;
+
+  bzero (&stats, sizeof (StatType));
+  if (FREEZE_IMAGES) return (stats);
+
+  ALLOCATE (list, double, Nimage);
+  ALLOCATE (dlist, double, Nimage);
+
+  n = 0;
+  for (i = 0; i < Nimage; i++) {
+
+    if (image[i].code & IMAGE_BAD)  continue;
+
+    list[n] = 0.001*image[i].dMcal;
+    dlist[n] = 1;
+    n++;
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+Image *getimages (int *N) {
+
+  *N = Nimage;
+  return (image);
+}
+
+Image *getimage (int N) {
+  return (&image[N]);
+}
+
Index: /tags/start/Ohana/src/relphot/src/MosaicOps.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/MosaicOps.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/MosaicOps.c	(revision 12606)
@@ -0,0 +1,671 @@
+# include "relphot.h"
+
+Image *getimages (int *N);
+
+static int    Nmosaic;
+static Mosaic *mosaic;
+
+static int    *Nimlist;
+static int   **imlist; /* mosaic -> image[] */
+static int   **bin;    /* catalog, measure -> mosaic */
+
+static int   **clist;  /* mosaic -> catalog[] */
+static int   **mlist;  /* mosiac -> measure[] */
+static int    *Nlist;
+static int    *NLIST;
+
+/* find mosaic frames (unique time periods & photcode name matches mosaic) */
+void initMosaics (Image *image, int Nimage) {
+
+  int i, j, status, found, NMOSAIC, *NIMLIST;
+  unsigned int start, stop;
+  char *pname;
+
+  if (!MOSAICNAME[0]) return;
+
+  Nmosaic = 0;
+  NMOSAIC = 10;
+  ALLOCATE (mosaic, Mosaic, NMOSAIC);
+
+  ALLOCATE (imlist, int *, NMOSAIC);
+  ALLOCATE (Nimlist, int, NMOSAIC);
+  ALLOCATE (NIMLIST, int, NMOSAIC);
+
+  /* generate list of unique mosaics */
+  for (i = 0; i < Nimage; i++) {
+
+    /* select valid mosaic images by photcode */
+    pname = GetPhotcodeNamebyCode (image[i].source);
+    status = strncmp (pname, MOSAICNAME, strlen (MOSAICNAME));
+    if (status) continue;
+
+    /* set image time range */
+    start = image[i].tzero - MAX(0.05*image[i].trate*image[i].NY, 1);
+    stop  = image[i].tzero + MAX(1.05*image[i].trate*image[i].NY, 1);
+
+    /* find existing mosaic with this time range */
+    found = FALSE;
+    for (j = 0; !found && (j < Nmosaic); j++) { 
+      if (stop  < mosaic[j].start) continue;
+      if (start > mosaic[j].stop)  continue;
+      found = TRUE;
+
+      /* add image to mosaic image list */
+      imlist[j][Nimlist[j]] = i;
+      Nimlist[j] ++;
+      if (Nimlist[j] == NIMLIST[j]) {
+	NIMLIST[j] += 10;
+	REALLOCATE (imlist[j], int, NIMLIST[j]);
+      }
+
+    }
+    if (found) continue;
+    
+    /* a new mosaic, define ranges */
+    mosaic[Nmosaic].start = start;
+    mosaic[Nmosaic].stop  = stop;
+    mosaic[Nmosaic].Mcal  = 0.0;
+    mosaic[Nmosaic].dMcal = 0.0;
+    mosaic[Nmosaic].Xm    = 0.0;
+    mosaic[Nmosaic].code  = image[i].code;
+    mosaic[Nmosaic].secz  = image[i].secz;
+
+    /* add image to mosaic image list */
+    NIMLIST[Nmosaic] = 10;
+    Nimlist[Nmosaic] = 1;
+    ALLOCATE (imlist[Nmosaic], int, NIMLIST[Nmosaic]);
+    imlist[Nmosaic][0] = i;
+
+    Nmosaic ++;
+    if (Nmosaic == NMOSAIC) {
+      NMOSAIC += 10;
+      REALLOCATE (mosaic, Mosaic, NMOSAIC);
+      REALLOCATE (imlist, int *, NMOSAIC);
+      REALLOCATE (Nimlist, int, NMOSAIC);
+      REALLOCATE (NIMLIST, int, NMOSAIC);
+    }
+  }
+
+  initMosaicGrid (image, Nimage);
+  return;
+}
+
+void initMosaicGrid (Image *image, int Nimage) {
+
+  /* find max dR, dD range for all mosaics */
+  /* define mosaic.coords to cover dR, dD */
+  /* send results to initGridBins */
+
+  int i, j, m, NX, NY;
+  int dXmax, dYmax;
+  double dR, dD, dS, dX, dY;
+  double R, D, Rmin, Rmax, Dmin, Dmax;
+  double Mcal, dMcal, Xm;
+
+  dXmax = dYmax = 0.0;
+  for (i = 0; i < Nmosaic; i++) {
+    Dmin = Rmin =  360.0;
+    Dmax = Rmax = -360.0;
+    dS = 0.0;
+    Mcal = dMcal = Xm = 0;
+    for (j = 0; j < Nimlist[i]; j++) {
+      m = imlist[i][j];
+      NX = image[m].NX;
+      NY = image[m].NY;
+      dS += hypot (image[m].coords.cdelt1*image[m].coords.pc1_1, image[m].coords.cdelt1*image[m].coords.pc2_1);
+      XY_to_RD (&R, &D, 0.0, 0.0, &image[m].coords);
+      Rmin = MIN (Rmin, R);
+      Rmax = MAX (Rmax, R);
+      Dmin = MIN (Dmin, D);
+      Dmax = MAX (Dmax, D);
+      XY_to_RD (&R, &D, (double) NX, 0.0, &image[m].coords);
+      Rmin = MIN (Rmin, R);
+      Rmax = MAX (Rmax, R);
+      Dmin = MIN (Dmin, D);
+      Dmax = MAX (Dmax, D);
+      XY_to_RD (&R, &D, (double) NX, (double) NY, &image[m].coords);
+      Rmin = MIN (Rmin, R);
+      Rmax = MAX (Rmax, R);
+      Dmin = MIN (Dmin, D);
+      Dmax = MAX (Dmax, D);
+      XY_to_RD (&R, &D, 0.0, (double) NY, &image[m].coords);
+      Rmin = MIN (Rmin, R);
+      Rmax = MAX (Rmax, R);
+      Dmin = MIN (Dmin, D);
+      Dmax = MAX (Dmax, D);
+      Mcal += image[m].Mcal;
+      dMcal += image[m].dMcal;
+      Xm += image[m].Xm;
+      /* we are using mosaic.Mcal, not image.Mcal. reset image.Mcal */
+      image[m].Mcal = 0.0;
+      image[m].dMcal = image[m].Xm = NO_MAG;
+    }
+    dS /= Nimlist[i];
+    strcpy (mosaic[i].coords.ctype, "RA---TAN");
+    mosaic[i].coords.crval1 = Rmin;
+    mosaic[i].coords.crval2 = Dmin;
+    mosaic[i].coords.crpix1 = 0.0;
+    mosaic[i].coords.crpix2 = 0.0;
+    mosaic[i].coords.cdelt1 = dS;
+    mosaic[i].coords.cdelt2 = dS;
+    mosaic[i].coords.pc1_1  = 1.0;
+    mosaic[i].coords.pc2_2  = 1.0;
+    mosaic[i].coords.pc1_2  = 0.0;
+    mosaic[i].coords.pc2_1  = 0.0;
+    RD_to_XY (&dX, &dY, Rmax, Dmax, &mosaic[i].coords);
+
+    mosaic[i].Mcal  = Mcal / Nimlist[i];
+    mosaic[i].dMcal = dMcal / Nimlist[i];
+    mosaic[i].Xm    = Xm / Nimlist[i];
+  }
+  if (!USE_GRID) return;
+
+  dXmax = MAX (dXmax, dX);
+  dYmax = MAX (dYmax, dY);
+  initGrid (dXmax, dYmax);
+  return;
+}
+
+void setMcalFinal (Image *image, int Nimage) {
+
+  int i, j, im;
+
+  if (!MOSAICNAME[0]) return;
+
+  for (i = 0; i < Nmosaic; i++) {
+    for (j = 0; j < Nimlist[i]; j++) {
+      im = imlist[i][j];
+      image[im].Mcal = mosaic[i].Mcal;
+      image[im].dMcal = mosaic[i].dMcal;
+      image[im].Xm = mosaic[i].Xm;
+      image[im].code |= (mosaic[i].code & ID_IMAGE_FEW);
+      image[im].code |= (mosaic[i].code & ID_IMAGE_POOR);
+    }
+  }      
+}
+
+void initMosaicBins (Catalog *catalog, int Ncatalog) {
+
+  int i, j;
+
+  /* measure -> mosaic */
+  if (!MOSAICNAME[0]) return;
+  ALLOCATE (bin, int *, Ncatalog);
+  for (i = 0; i < Ncatalog; i++) {
+    ALLOCATE (bin[i], int, MAX (catalog[i].Nmeasure, 1));
+    for (j = 0; j < catalog[i].Nmeasure; j++) bin[i][j] = -1;
+  }
+
+  /* mosaic -> measure */
+  ALLOCATE (Nlist, int, Nmosaic);
+  ALLOCATE (NLIST, int, Nmosaic);
+  ALLOCATE (clist, int *, Nmosaic);
+  ALLOCATE (mlist, int *, Nmosaic);
+
+  for (i = 0; i < Nmosaic; i++) {
+    Nlist[i] = 0;
+    NLIST[i] = 100;
+    ALLOCATE (clist[i], int, NLIST[i]);
+    ALLOCATE (mlist[i], int, NLIST[i]);
+  }
+}
+
+void freeMosaicBins (Ncatalog) {
+
+  int i;
+
+  /* measure -> mosaic */
+  if (!MOSAICNAME[0]) return;
+  for (i = 0; i < Ncatalog; i++) {
+    free (bin[i]);
+  }
+  free (bin);
+
+  /* mosaic -> measure */
+  for (i = 0; i < Nmosaic; i++) {
+    free (clist[i]);
+    free (mlist[i]);
+  }
+  free (Nlist);
+  free (NLIST);
+  free (clist);
+  free (mlist);
+}
+
+int findMosaics (Catalog *catalog, int Ncatalog) {
+  
+  int i, j, ecode;
+
+  if (!MOSAICNAME[0]) return (FALSE);
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Nmeasure; j++) {
+      if (TimeSelect) {
+	if (catalog[i].measure[j].t < TSTART) continue;
+	if (catalog[i].measure[j].t > TSTOP) continue;
+      }
+      ecode = GetPhotcodeEquivCodebyCode (catalog[i].measure[j].source);
+      if (photcode[0].code != ecode) continue;
+      matchMosaics (catalog, j, i);
+    }
+  }
+  
+}
+
+void matchMosaics (Catalog *catalog, int meas, int cat) {
+
+  int i, ave;
+  double ra, dec, X, Y;
+
+  for (i = 0; i < Nmosaic; i++) {
+    if (catalog[cat].measure[meas].t < mosaic[i].start) continue;
+    if (catalog[cat].measure[meas].t > mosaic[i].stop) continue;
+    
+# ifdef GRID_V1
+    if (USE_GRID) {
+      ave = catalog[cat].measure[meas].averef;
+      ra  = catalog[cat].average[ave].R - catalog[cat].measure[meas].dR / 360000.0;
+      dec = catalog[cat].average[ave].D - catalog[cat].measure[meas].dD / 360000.0;
+
+      /* X,Y always positive-definite in range 0,0 - dX, dY */
+      RD_to_XY (&X, &Y, ra, dec, &mosaic[i].coords);
+      setGridMeasure (meas, cat, X, Y);
+    }
+# endif
+
+    bin[cat][meas] = i;
+
+    clist[i][Nlist[i]] = cat;
+    mlist[i][Nlist[i]] = meas;
+    Nlist[i] ++;
+    
+    if (Nlist[i] == NLIST[i]) {
+      NLIST[i] += 100;
+      REALLOCATE (clist[i], int, NLIST[i]);
+      REALLOCATE (mlist[i], int, NLIST[i]);
+    }	
+    return;
+  }
+  fprintf (stderr, "missed measurement\n");
+  return;
+}
+
+short getMmos (int meas, int cat) {
+
+  int i;
+  short value;
+
+  if (!MOSAICNAME[0]) return (0);
+  i = bin[cat][meas];
+  if (i == -1) return (NO_MAG);
+
+  if (mosaic[i].code & IMAGE_BAD) return (NO_MAG);  
+  value = mosaic[i].Mcal;
+  return (value);
+}
+
+int setMmos (Catalog *catalog, int PoorImages) {
+
+  int i, j, m, c, n, N, Nmax, mark, bad;
+  short Msys, Mrel, Mcal, Mgrid;
+  double *list, *dlist, *Mlist, *dMlist;
+  StatType stats;
+  Image *image;
+  Graphdata graphdata;
+
+  if (!MOSAICNAME[0]) return (FALSE);
+
+  image = getimages (&N);
+
+  if (PoorImages) {
+    IMAGE_BAD = 0;
+  }
+
+  Nmax = 0;
+  for (i = 0; i < Nmosaic; i++) {
+    Nmax = MAX (Nmax, Nlist[i]);
+  }
+  ALLOCATE (list, double, Nmax);
+  ALLOCATE (dlist, double, Nmax);
+  ALLOCATE (Mlist, double, Nmax);
+  ALLOCATE (dMlist, double, Nmax);
+
+  for (i = 0; i < Nmosaic; i++) {
+    
+    /* on PoorImages run, skip good images */
+    if (PoorImages) {
+      bad = mosaic[i].code & (ID_IMAGE_FEW | ID_IMAGE_POOR | ID_IMAGE_SKIP);
+      if (!bad) continue;
+    }      
+
+    N = 0;
+    for (j = 0; j < Nlist[i]; j++) {
+      
+      m = mlist[i][j];
+      c = clist[i][j];
+      
+      if (catalog[c].measure[m].flags & MEAS_BAD) continue;
+      if ((Mcal  = getMcal  (m, c)) == NO_MAG) continue;
+      if ((Mgrid = getMgrid (m, c)) == NO_MAG) continue;
+      if ((Mrel  = getMrel  (catalog, m, c)) == NO_MAG) continue;
+      
+      n = catalog[c].measure[m].averef;
+      Msys = iPhotSys (&catalog[c].measure[m], &catalog[c].average[n], &catalog[c].secfilt[n*PhotNsec]);
+      list[N]  = Msys - Mrel - Mcal - Mgrid;
+      dlist[N] = MAX (catalog[c].measure[m].dM, MIN_ERROR);
+      Mlist[N] = 0.001*Msys;
+      dMlist[N] = 0.001*list[N];
+      N++;
+    }
+    /* Nlist[i] is all measurements, N is good measurements */
+
+    /* too few good measurements or too many bad measurements (skip in PoorImages run) */
+
+    if (!PoorImages) {
+      mark = (N < IMAGE_TOOFEW) || (N < IMAGE_GOOD_FRACTION*Nlist[i]);
+      if (mark) {
+	fprintf (stderr, "marked image %s (%d), (%d < %d) || (%d < %f*%d)\n", image[imlist[i][0]].name, i, N, IMAGE_TOOFEW, N, IMAGE_GOOD_FRACTION, Nlist[i]);
+	mosaic[i].code |= ID_IMAGE_FEW;
+      } else {
+	mosaic[i].code &= ~ID_IMAGE_FEW;
+      }
+    }
+    liststats (list, dlist, N, &stats);
+    if (PoorImages) fprintf (stderr, "Mmos: %f %f %d %d\n", stats.mean, stats.sigma, stats.Nmeas, N);
+    mosaic[i].Mcal  = stats.mean;
+    mosaic[i].dMcal = stats.sigma;
+    mosaic[i].Xm    = 100.0*log10(stats.chisq);
+  }
+  free (list);
+  free (dlist);
+  free (Mlist);
+  free (dMlist);
+
+  if (PoorImages) {
+    IMAGE_BAD = ID_IMAGE_POOR | ID_IMAGE_FEW | ID_IMAGE_SKIP;
+    STAR_BAD  = ID_STAR_POOR | ID_STAR_FEW;
+    MEAS_BAD  = ID_MEAS_NOCAL | ID_MEAS_POOR | ID_MEAS_SKIP | ID_MEAS_AREA;
+  }
+  return (TRUE);
+}
+  
+StatType statsMosaicM (Catalog *catalog) {
+
+  int i, n, N, Nmax;
+  double *list, *dlist;
+  StatType stats;
+
+  bzero (&stats, sizeof (StatType));
+  if (!MOSAICNAME[0]) return (stats);
+
+  ALLOCATE (list, double, Nmosaic);
+  ALLOCATE (dlist, double, Nmosaic);
+
+  n = 0;
+  for (i = 0; i < Nmosaic; i++) {
+    if (mosaic[i].code & IMAGE_BAD) continue;
+    list[n] = 0.001*mosaic[i].Mcal;
+    dlist[n] = 1;
+    n++;
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+StatType statsMosaicdM (Catalog *catalog) {
+
+  int i, n, N, Nmax;
+  double *list, *dlist;
+  StatType stats;
+
+  bzero (&stats, sizeof (StatType));
+  if (!MOSAICNAME[0]) return (stats);
+
+  ALLOCATE (list, double, Nmosaic);
+  ALLOCATE (dlist, double, Nmosaic);
+
+  n = 0;
+  for (i = 0; i < Nmosaic; i++) {
+
+    if (mosaic[i].code & IMAGE_BAD) continue;
+    list[n] = 0.001*mosaic[i].dMcal;
+    dlist[n] = 1;
+    n++;
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+StatType statsMosaicN (Catalog *catalog) {
+
+  int i, j, k, m, c, n, N, Nmax;
+  double *list, *dlist;
+  StatType stats;
+
+  bzero (&stats, sizeof (StatType));
+  if (!MOSAICNAME[0]) return (stats);
+
+  ALLOCATE (list, double, Nmosaic);
+  ALLOCATE (dlist, double, Nmosaic);
+
+  n = 0;
+  for (i = 0; i < Nmosaic; i++) {
+    if (mosaic[i].code & IMAGE_BAD)  continue;
+
+    N = 0;
+    for (j = 0; j < Nlist[i]; j++) {
+
+      m = mlist[i][j];
+      c = clist[i][j];
+
+      if (getMcal  (m, c) == NO_MAG) continue;
+      if (getMgrid (m, c) == NO_MAG) continue;
+      if (getMrel  (catalog, m, c) == NO_MAG) continue;
+      N++;
+    }
+    list[n] = N;
+    dlist[n] = 1;
+    n++;
+  }
+  fprintf (stderr, "Nmosaic: %d, n: %d\n", Nmosaic, n);
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+StatType statsMosaicX (Catalog *catalog) {
+
+  int i, n, N, Nmax;
+  double *list, *dlist;
+  StatType stats;
+
+  bzero (&stats, sizeof (StatType));
+  if (!MOSAICNAME[0]) return (stats);
+
+  ALLOCATE (list, double, Nmosaic);
+  ALLOCATE (dlist, double, Nmosaic);
+
+  n = 0;
+  for (i = 0; i < Nmosaic; i++) {
+
+    if (mosaic[i].code & IMAGE_BAD) continue;
+    list[n] = pow(10.0, 0.01*mosaic[i].Xm);
+    dlist[n] = 1;
+    n++;
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+/* mark mosaic if: abs(Mcal - <Mcal>) too large, dMcal too large */
+void clean_mosaics () {
+
+  int i, j, N, mark, Nmark;
+  double *mlist, *slist, *dlist;
+  double MaxOffset, MedOffset, MaxScatter;
+  StatType stats;
+  Image *image;
+
+  if (!MOSAICNAME[0]) return;
+
+  if (VERBOSE) fprintf (stderr, "marking poor mosaics\n");
+
+  ALLOCATE (mlist, double, Nmosaic);
+  ALLOCATE (slist, double, Nmosaic);
+  ALLOCATE (dlist, double, Nmosaic);
+
+  for (i = N = 0; i < Nmosaic; i++) {
+    if (mosaic[i].code & IMAGE_BAD) continue;
+    mlist[N] = mosaic[i].Mcal;
+    slist[N] = mosaic[i].dMcal;
+    dlist[N] = 1;
+    N++;
+  }
+  initstats ("MEAN");
+  liststats (mlist, dlist, N, &stats);
+  MaxOffset = MAX (IMAGE_OFFSET, 2*stats.sigma);
+  MedOffset = stats.median;
+  liststats (slist, dlist, N, &stats);
+  MaxScatter = MAX (IMAGE_SCATTER, 2*stats.median);
+  fprintf (stderr, "Mrel: %f, dMrel: %f, Max Scatter: %f, Max Offset: %f\n", 0.001*MedOffset, 0.001*stats.median, 0.001*MaxScatter, 0.001*MaxOffset);
+  
+  Nmark = 0;
+  for (i = 0; i < Nmosaic; i++) {
+    mark = FALSE;
+    mark = (mosaic[i].dMcal > MaxScatter) || (fabs(mosaic[i].Mcal - MedOffset) > MaxOffset);
+    if (mark) { 
+      Nmark ++;
+      mosaic[i].code |= ID_IMAGE_POOR;
+    } else {
+      mosaic[i].code &= ~ID_IMAGE_POOR;
+    }
+  }
+
+  fprintf (stderr, "%d mosaics marked poor\n", Nmark);
+  initstats (STATMODE);
+  free (mlist);
+  free (slist);
+  free (dlist);
+}
+
+void plot_mosaic_fields (Catalog *catalog) {
+
+  int i, j, m, c, N, ave, Nimage;
+  short Mrel, Mcal, Mmos;
+  double *xlist, *ylist;
+  double Xmin, Xmax, Ymin, Ymax;
+  char string[64];
+  Image *image;
+  Graphdata graphdata;
+
+  if (!MOSAICNAME[0]) return;
+
+  image = getimages (&Nimage);
+
+  N = 0;
+  for (i = 0; i < Nmosaic; i++) 
+    N = MAX (N, Nlist[i]);
+
+  ALLOCATE (xlist, double, N);
+  ALLOCATE (ylist, double, N);
+
+  for (i = 0; i < Nmosaic; i++) {
+    N = 0;
+    Xmin = Ymin = +360.0;
+    Xmax = Ymax = -360.0;
+    for (j = 0; j < Nlist[i]; j++) {
+      
+      m = mlist[i][j];
+      c = clist[i][j];
+      
+      ave = catalog[c].measure[m].averef;
+      xlist[N] = catalog[c].average[ave].R - catalog[c].measure[m].dR / 360000.0;
+      ylist[N] = catalog[c].average[ave].D - catalog[c].measure[m].dD / 360000.0;
+      N++;
+    }
+  
+    sprintf (string, "Mosaic %d", i);
+    plot_defaults (&graphdata);
+    plot_list (&graphdata, xlist, ylist, N, string, NULL);
+  }
+
+  free (ylist);
+  free (xlist);
+}
+
+void plot_mosaics () {
+
+  int i, j, m, c, N, Nmax, bin;
+  short Mrel, Mcal, Mmos;
+  double *xlist, *Mlist, *dlist;
+  Graphdata graphdata;
+
+  if (!MOSAICNAME[0]) return;
+
+  ALLOCATE (xlist, double, Nmosaic);
+  ALLOCATE (dlist, double, Nmosaic);
+  ALLOCATE (Mlist, double, Nmosaic);
+
+  for (i = 0; i < Nmosaic; i++) {
+    Mlist[i] = 0.001*mosaic[i].Mcal;
+    dlist[i] = 0.001*mosaic[i].dMcal;
+    xlist[i] = 0.001*mosaic[i].secz;
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.xmin = 0.95;
+  graphdata.xmax = 2.50;
+  graphdata.ymin = PlotdMmin;
+  graphdata.ymax = PlotdMmax;
+  plot_list (&graphdata, xlist, Mlist, Nmosaic, "airmass vs Mcal", "airmass.png");
+  plot_defaults (&graphdata);
+  plot_list (&graphdata, Mlist, dlist, Nmosaic, "Mcal vs dMcal", NULL);
+
+# define NBIN 200
+  REALLOCATE (xlist, double, NBIN);
+  REALLOCATE (Mlist, double, NBIN);
+
+  /**** dMcal histgram ****/
+  for (i = 0; i < NBIN; i++) xlist[i] = 0.0025*i;
+  bzero (Mlist, NBIN*sizeof(double));
+  for (i = 0; i < Nmosaic; i++) {
+    bin = 0.001*mosaic[i].dMcal / 0.0025;
+    bin = MAX (0, MIN (NBIN - 1, bin));
+    Mlist[bin] += 1.0;
+  }
+  plot_defaults (&graphdata);
+  graphdata.style = 1;
+  plot_list (&graphdata, xlist, Mlist, NBIN, "dMcal hist", "dMcalhist.png");
+
+  free (dlist);
+  free (xlist);
+  free (Mlist);
+}
+
+int *SelectRefMosaic (Mosaic **refmosaic, int *Nimage) {
+
+  int i, Imax, Nmax;
+
+  Imax = 0;
+  Nmax = Nimlist[0];
+  for (i = 0; i < Nmosaic; i++) {
+    if (Nimlist[i] > Nmax) {
+      Imax = i;
+      Nmax = Nimlist[i];
+    }
+  }
+
+  *refmosaic = &mosaic[Imax];
+  *Nimage = Nmax;
+  return (imlist[Imax]);
+}
Index: /tags/start/Ohana/src/relphot/src/StarOps.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/StarOps.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/StarOps.c	(revision 12606)
@@ -0,0 +1,528 @@
+# include "relphot.h"
+
+static int Nmax;
+static double *list;
+static double *dlist;
+
+void initMrel (Catalog *catalog, int Ncatalog) {
+
+  int i, j;
+  
+  Nmax = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      Nmax = MAX (Nmax, catalog[i].average[j].Nm);
+    }
+  }
+
+  ALLOCATE (list, double, MAX (1, Nmax));
+  ALLOCATE (dlist, double, MAX (1, Nmax));
+}  
+
+short getMrel (Catalog *catalog, int meas, int cat) {
+
+  int ave;
+  short value;
+
+  ave = catalog[cat].measure[meas].averef;
+  if (catalog[cat].average[ave].code & STAR_BAD) return (NO_MAG);  
+ 
+  value = PhotPrimary ? catalog[cat].average[ave].M : catalog[cat].secfilt[PhotNsec*ave+PhotSec].M;
+  return (value);
+}
+
+int setMrel (Catalog *catalog, int Ncatalog) {
+
+  int i, j, k, m, N;
+  short Msys, Mcal, Mmos, Mgrid;
+  StatType stats;
+
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* calculate the average value for a single star */
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+      m = catalog[i].average[j].offset;
+
+      N = 0;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	if (catalog[i].measure[m].flags & MEAS_BAD) continue;
+	if ((Mcal  = getMcal  (m, i)) == NO_MAG) continue;
+	if ((Mmos  = getMmos  (m, i)) == NO_MAG) continue;
+	if ((Mgrid = getMgrid (m, i)) == NO_MAG) continue;
+
+	Msys = iPhotSys (&catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]);
+	list[N] = Msys - Mcal - Mmos - Mgrid;
+	dlist[N] = MAX (catalog[i].measure[m].dM, MIN_ERROR);
+	N++;
+      }
+      if (N < STAR_TOOFEW) { /* too few measurements */
+	catalog[i].average[j].code |= ID_STAR_FEW;
+      } else {
+	catalog[i].average[j].code &= ~ID_STAR_FEW;
+      }	
+
+      liststats (list, dlist, N, &stats);
+
+      if (PhotPrimary) {
+	catalog[i].average[j].M = stats.mean;
+	catalog[i].average[j].dM = stats.sigma;
+	catalog[i].average[j].Xm = (stats.Nmeas > 1) ? 100.0*log10(stats.chisq) : NO_MAG;
+      } else {
+	catalog[i].secfilt[PhotNsec*j+PhotSec].M  = stats.mean;
+	catalog[i].secfilt[PhotNsec*j+PhotSec].dM = stats.sigma;
+	catalog[i].secfilt[PhotNsec*j+PhotSec].Xm = (stats.Nmeas > 1) ? 100.0*log10(stats.chisq) : NO_MAG;
+      }      
+    }
+  }
+}
+
+int setMrelOutput (Catalog *catalog, int Ncatalog, int mark) {
+
+  int i, j, k, m, N, Nmax;
+  short Msys, Mcal, Mmos, Mgrid;
+  double *list, *dlist;
+  StatType stats;
+
+  /* Nmeasure is now different, need to reallocate */
+  Nmax = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      Nmax = MAX (Nmax, catalog[i].average[j].Nm);
+    }
+  }
+  ALLOCATE (list, double, MAX (1, Nmax));
+  ALLOCATE (dlist, double, MAX (1, Nmax));
+
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* skip stars already calibrated */
+      if (catalog[i].found[j]) continue;  
+
+      N = 0;
+      m = catalog[i].average[j].offset;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	if (catalog[i].measure[m].flags & MEAS_BAD) continue;
+	if ((Mcal  = getMcal  (m, i)) == NO_MAG) continue;
+	if ((Mmos  = getMmos  (m, i)) == NO_MAG) continue;
+	if ((Mgrid = getMgrid (m, i)) == NO_MAG) continue;
+
+	Msys = iPhotSys (&catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]);
+	list[N] = Msys - Mcal - Mmos - Mgrid;
+	dlist[N] = MAX (catalog[i].measure[m].dM, MIN_ERROR);
+	N++;
+      }
+      if (N < 1) continue;
+
+      liststats (list, dlist, N, &stats);
+      if (mark) catalog[i].found[j] = TRUE;
+
+      /* use sigma or error in dM for output? */
+      if (PhotPrimary) {
+	catalog[i].average[j].M = stats.mean;
+	catalog[i].average[j].dM = MAX (stats.sigma, stats.error);
+	catalog[i].average[j].Xm = (stats.Nmeas > 1) ? 100.0*log10(stats.chisq) : NO_MAG;
+      } else {
+	catalog[i].secfilt[PhotNsec*j+PhotSec].M  = stats.mean;
+	catalog[i].secfilt[PhotNsec*j+PhotSec].dM = MAX (stats.error, stats.sigma);
+	catalog[i].secfilt[PhotNsec*j+PhotSec].Xm = (stats.Nmeas > 1) ? 100.0*log10(stats.chisq) : NO_MAG;
+      }      
+    }
+  }
+
+  free (list);
+  free (dlist);
+}
+
+/* set measure.Mcal for all measures except ID_MEAS_NOCAL and ID_IMAGE_NOCAL */
+int setMcalOutput (Catalog *catalog, int Ncatalog) {
+
+  int i, j, k, m;
+  short Mcal, Mmos, Mgrid;
+
+  MEAS_BAD = ID_MEAS_NOCAL;
+  IMAGE_BAD = ID_IMAGE_NOCAL;
+
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      m = catalog[i].average[j].offset;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	if (catalog[i].measure[m].flags & MEAS_BAD) continue;
+	if ((Mcal  = getMcal  (m, i)) == NO_MAG) continue;
+	if ((Mmos  = getMmos  (m, i)) == NO_MAG) continue;
+	if ((Mgrid = getMgrid (m, i)) == NO_MAG) continue;
+	catalog[i].measure[m].Mcal = Mcal + Mmos + Mgrid;
+      }
+    }
+  }
+  return (TRUE);
+}
+
+void clean_stars (Catalog *catalog, int Ncatalog) {
+
+  int i, j, Ndel, Nave, Ntot, mark;
+  short dM, Xm;
+  double Chisq, MaxScatter, MaxChisq;
+  double *xlist, *slist, *dlist;
+  StatType stats;
+
+  if (VERBOSE) fprintf (stderr, "marking poor stars\n");
+
+  /* find Xm median -> ChiSq lim must be > median */
+  for (i = Ntot = 0; i < Ncatalog; i++) {
+    Ntot += catalog[i].Naverage; 
+  }
+  ALLOCATE (xlist, double, Ntot);
+  ALLOCATE (slist, double, Ntot);
+  ALLOCATE (dlist, double, Ntot);
+  for (i = Ntot = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      if (catalog[i].average[j].code & STAR_BAD) continue;
+      Xm = PhotPrimary ? catalog[i].average[j].Xm : catalog[i].secfilt[PhotNsec*j+PhotSec].Xm;
+      if (Xm == -1) continue;
+      Chisq = pow (10.0, 0.01*Xm);
+      xlist[Ntot] = Chisq;
+      slist[Ntot] = PhotPrimary ? catalog[i].average[j].dM : catalog[i].secfilt[PhotNsec*j+PhotSec].dM;
+      dlist[Ntot] = 1;
+      Ntot ++;
+    }
+  }
+  
+  initstats ("MEAN");
+  liststats (xlist, dlist, Ntot, &stats);
+  MaxChisq = MAX (STAR_CHISQ, 2*stats.median);
+  liststats (slist, dlist, Ntot, &stats);
+  MaxScatter = MAX (STAR_SCATTER, 2*stats.median);
+  fprintf (stderr, "Max Scatter: %f, Max Chisq: %f\n", 0.001*MaxScatter, MaxChisq);
+
+  Ndel = Nave = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      dM = PhotPrimary ? catalog[i].average[j].dM : catalog[i].secfilt[PhotNsec*j+PhotSec].dM;
+      Xm = PhotPrimary ? catalog[i].average[j].Xm : catalog[i].secfilt[PhotNsec*j+PhotSec].Xm;
+      Chisq = pow (10.0, 0.01*Xm);
+      mark = (dM > MaxScatter) || (Xm == NO_MAG) || (Chisq > MaxChisq);
+      if (mark) {
+	catalog[i].average[j].code |= ID_STAR_POOR;
+	Ndel ++;
+      } else {
+	catalog[i].average[j].code &= ~ID_STAR_POOR;
+      }
+      Nave ++;
+    }
+  }
+  fprintf (stderr, "%d stars marked variable, %d total\n", Ndel, Nave);
+  initstats (STATMODE);
+  free (xlist);
+  free (slist);
+  free (dlist);
+}
+
+void clean_measures (Catalog *catalog, int Ncatalog, int final) {
+
+  int i, j, k, m, N, Ndel, Nave, Nmax, image_bad, TOOFEW;
+  int *ilist;
+  double *tlist, *list, *dlist, Ns;
+  short Msys, Mcal, Mmos, Mgrid;
+  StatType stats;
+
+  if (VERBOSE) fprintf (stderr, "marking poor measures\n");
+  /* Nmeasure is now different, need to reallocate */
+  Nmax = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      Nmax = MAX (Nmax, catalog[i].average[j].Nm);
+    }
+  }
+  ALLOCATE (list, double, MAX (1, Nmax));
+  ALLOCATE (dlist, double, MAX (1, Nmax));
+  ALLOCATE (ilist, int, Nmax);
+  ALLOCATE (tlist, double, Nmax);
+  
+  /* it makes no sense to mark 3-sigma outliers with <5 measurements */
+  TOOFEW = MAX (5, STAR_TOOFEW);
+
+  Ns = 3;
+  Ndel = Nave = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* skip bad stars to prevent them from becoming good (on inner sample) */
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+
+      /* on final processing, skip stars already measured */
+      if (final && catalog[i].found[j]) continue;  
+
+      /* accumulate list of valid measurements */
+      m = catalog[i].average[j].offset;
+      N = 0;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	/* if (catalog[i].measure[m].flags & MEAS_BAD) continue; */
+	if ((Mcal  = getMcal  (m, i)) == NO_MAG) continue;
+	if ((Mmos  = getMmos  (m, i)) == NO_MAG) continue;
+	if ((Mgrid = getMgrid (m, i)) == NO_MAG) continue;
+
+	Msys = iPhotSys (&catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]);
+	list[N] = Msys - Mcal - Mmos - Mgrid;
+	dlist[N] = MAX (catalog[i].measure[m].dM, MIN_ERROR);
+	N++;
+      }
+      if (N < TOOFEW) continue;
+
+      /* 3-sigma clip based on stats of inner 50% */
+      initstats ("INNER_MEAN");
+      liststats (list, dlist, N, &stats);
+      stats.sigma = MAX (MIN_ERROR, stats.sigma); /* if measurements agree too well, sigma -> 0.0 */
+      for (k = m = 0; k < N; k++) {
+	if (fabs (list[k] - stats.median) < Ns*stats.sigma) {
+	  list[m] = list[k];
+	  m++;
+	}
+      }
+      initstats ("MEAN");
+      liststats (list, dlist, m, &stats);
+      stats.sigma = MAX (MIN_ERROR, stats.sigma);
+
+      /* apply to list of all relevant measurements, including IMAGE_POOR & IMAGE_FEW */
+      image_bad = IMAGE_BAD;
+      IMAGE_BAD = ID_IMAGE_NOCAL;
+      m = catalog[i].average[j].offset;
+      N = 0;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	/* if (catalog[i].measure[m].flags & MEAS_BAD) continue; */
+	if ((Mcal  = getMcal  (m, i)) == NO_MAG) continue;
+	if ((Mmos  = getMmos  (m, i)) == NO_MAG) continue;
+	if ((Mgrid = getMgrid (m, i)) == NO_MAG) continue;
+
+	Msys = iPhotSys (&catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]);
+	list[N] = Msys - Mcal - Mmos - Mgrid;
+	dlist[N] = MAX (catalog[i].measure[m].dM, MIN_ERROR);
+	ilist[N] = m;
+	N++;
+	Nave ++;
+      }
+      if (N < TOOFEW) continue;
+
+      /* mark bad measures */
+      for (k = 0; k < N; k++) {
+	if (fabs (list[k] - stats.median) > Ns*stats.sigma) {
+	  catalog[i].measure[ilist[k]].flags |= ID_MEAS_POOR;
+	  Ndel ++;
+	}
+      }
+      IMAGE_BAD = image_bad;
+    }
+  }
+  initstats (STATMODE);
+  fprintf (stderr, "%d measures marked poor, %d total\n", Ndel, Nave);
+  free (ilist);
+  free (tlist);
+}
+
+StatType statsStarN (Catalog *catalog, int Ncatalog) {
+
+  int i, j, k, m, n, N, Ntot;
+  double *list, *dlist;
+  StatType stats;
+
+  Ntot = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    Ntot += catalog[i].Naverage; 
+  }
+
+  ALLOCATE (list, double, Ntot);
+  ALLOCATE (dlist, double, Ntot);
+
+  n = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* calculate the average value for a single star */
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+      m = catalog[i].average[j].offset;
+
+      N = 0;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	if (getMcal  (m, i) == NO_MAG) continue;
+	if (getMmos  (m, i) == NO_MAG) continue;
+	if (getMgrid (m, i) == NO_MAG) continue;
+	N++;
+      }
+      
+      list[n] = N;
+      dlist[n] = 1;
+      n++;
+    }
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+StatType statsStarX (Catalog *catalog, int Ncatalog) {
+
+  int i, j, k, m, n, N, Ntot, Xm;
+  double *list, *dlist;
+  StatType stats;
+
+  Ntot = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    Ntot += catalog[i].Naverage; 
+  }
+
+  ALLOCATE (list, double, Ntot);
+  ALLOCATE (dlist, double, Ntot);
+
+  n = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* calculate the average value for a single star */
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+
+      Xm = PhotPrimary ? catalog[i].average[j].Xm : catalog[i].secfilt[PhotNsec*j+PhotSec].Xm;
+      if (Xm == NO_MAG) continue;
+      list[n] = pow (10.0, 0.01*Xm);
+      dlist[n] = 1;
+      n++;
+    }
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+StatType statsStarS (Catalog *catalog, int Ncatalog) {
+
+  int i, j, k, m, n, N, Ntot, dM;
+  double *list, *dlist;
+  StatType stats;
+
+  Ntot = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    Ntot += catalog[i].Naverage; 
+  }
+
+  ALLOCATE (list, double, Ntot);
+  ALLOCATE (dlist, double, Ntot);
+
+  n = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* calculate the average value for a single star */
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+
+      dM = PhotPrimary ? catalog[i].average[j].dM : catalog[i].secfilt[PhotNsec*j+PhotSec].dM;
+      list[n] = 0.001*dM;
+      dlist[n] = 1;
+      n++;
+    }
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+void plot_stars (Catalog *catalog, int Ncatalog) {
+
+  int i, j, m, c, N, bin;
+  short dMrel;
+  double *xlist, *Mlist;
+  Graphdata graphdata;
+
+# define NBIN 200
+  ALLOCATE (xlist, double, NBIN);
+  ALLOCATE (Mlist, double, NBIN);
+
+  for (i = 0; i < NBIN; i++) xlist[i] = 0.0025*i;
+  bzero (Mlist, NBIN*sizeof(double));
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+      dMrel = PhotPrimary ? catalog[i].average[j].dM : catalog[i].secfilt[PhotNsec*j+PhotSec].dM;
+      bin = 0.001*dMrel / 0.0025;
+      bin = MAX (0, MIN (NBIN-1, bin));
+      Mlist[bin] += 1.0;
+    }
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.style = 1;
+  plot_list (&graphdata, xlist, Mlist, NBIN, "dMrel hist", "dMhist.png");
+
+  free (xlist);
+  free (Mlist);
+}
+
+void plot_chisq (Catalog *catalog, int Ncatalog) {
+
+  int i, j, N, Ntotal, value;
+  double *xlist, *ylist;
+  Graphdata graphdata;
+
+  Ntotal = 0;
+  for (i = 0; i < Ncatalog; i++) Ntotal += catalog[i].Naverage;
+
+  ALLOCATE (xlist, double, Ntotal);
+  ALLOCATE (ylist, double, Ntotal);
+
+  N = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      if (catalog[i].average[j].code & STAR_BAD) continue;
+      xlist[N] = PhotPrimary ? 0.001*catalog[i].average[j].M : 0.001*catalog[i].secfilt[PhotNsec*j+PhotSec].M;
+      value    = PhotPrimary ? catalog[i].average[j].Xm : catalog[i].secfilt[PhotNsec*j+PhotSec].Xm;
+      if (value == NO_MAG) continue;
+      ylist[N] = 0.01*value;
+      N++;
+    }
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.ymin = -3.0;
+  plot_list (&graphdata, xlist, ylist, N, "chisq", NULL);
+  free (xlist);
+  free (ylist);
+}
+
+void plot_star_coords (Catalog *catalog, int Ncatalog) {
+
+  int i, j, m, c, N, bin;
+  short Mrel, Mcal, Mmos;
+  double *xlist, *ylist;
+  double Xmin, Ymin, Xmax, Ymax;
+  Graphdata graphdata;
+
+  N = 0; 
+  for (i = 0; i < Ncatalog; i++) {
+    N += catalog[i].Naverage;
+  }
+  ALLOCATE (xlist, double, N);
+  ALLOCATE (ylist, double, N);
+
+  N = 0;
+  Xmin = Ymin = +360.0;
+  Xmax = Ymax = -360.0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      xlist[N] = catalog[i].average[j].R;
+      ylist[N] = catalog[i].average[j].D;
+      N++;
+    }
+  }
+  plot_defaults (&graphdata);
+  plot_list (&graphdata, xlist, ylist, N, "coords", NULL);
+
+  free (xlist);
+  free (ylist);
+}
+
Index: /tags/start/Ohana/src/relphot/src/args.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/args.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/args.c	(revision 12606)
@@ -0,0 +1,175 @@
+# include "relphot.h"
+
+int args (int argc, char **argv) {
+
+  int N;
+
+  /* define time */
+  TimeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-time")) {
+    remove_argument (N, &argc, argv);
+    if (!str_to_time (argv[N], &TSTART)) { 
+      fprintf (stderr, "ERROR: syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!str_to_time (argv[N], &TSTOP)) { 
+      fprintf (stderr, "ERROR: syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    TimeSelect = TRUE;
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  PLOTSTUFF = FALSE;
+  if ((N = get_argument (argc, argv, "-plot"))) {
+    PLOTSTUFF = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  PLOTDELAY = 500000;
+  if ((N = get_argument (argc, argv, "-plotdelay"))) {
+    remove_argument (N, &argc, argv);
+    PLOTDELAY = 1e6*atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  strcpy (STATMODE, "CHI_INNER_WTMEAN");
+  if ((N = get_argument (argc, argv, "-statmode"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (STATMODE, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  NLOOP = 8;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    NLOOP = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  RESET = FALSE;
+  if ((N = get_argument (argc, argv, "-reset"))) {
+    remove_argument (N, &argc, argv);
+    RESET = TRUE;
+  }
+
+  UPDATE = FALSE;
+  if ((N = get_argument (argc, argv, "-update"))) {
+    remove_argument (N, &argc, argv);
+    UPDATE = TRUE;
+  }
+
+  SHOW_PARAMS = FALSE;
+  if ((N = get_argument (argc, argv, "-params"))) {
+    remove_argument (N, &argc, argv);
+    SHOW_PARAMS = TRUE;
+  }
+
+  PlotMmin = 10.0; PlotMmax = 20.0; PlotdMmin = -1.0; PlotdMmax = 1.0;
+  if ((N = get_argument (argc, argv, "-plrange"))) {
+    remove_argument (N, &argc, argv);
+    PlotMmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    PlotMmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    PlotdMmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    PlotdMmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* group images by mosaic, find Mmos */
+  MOSAICNAME[0] = 0;
+  if ((N = get_argument (argc, argv, "-mosaic"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (MOSAICNAME, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  FREEZE_IMAGES = FALSE;
+  if ((N = get_argument (argc, argv, "-imfreeze"))) {
+    remove_argument (N, &argc, argv);
+    FREEZE_IMAGES = TRUE;
+  }
+
+  USE_GRID = FALSE;
+  if ((N = get_argument (argc, argv, "-grid"))) {
+    remove_argument (N, &argc, argv);
+    USE_GRID = TRUE;
+    if (!MOSAICNAME[0]) {
+      fprintf (stderr, "-grid is only valid with -mosaic\n");
+      exit (2);
+    }
+  }
+
+  MIN_ERROR = 1;
+  if ((N = get_argument (argc, argv, "-minerror"))) {
+    remove_argument (N, &argc, argv);
+    MIN_ERROR = 1000.0*atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    /* require MIN_ERROR > 0 */
+  }  
+
+  AreaSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-area"))) {
+    remove_argument (N, &argc, argv);
+    AreaXmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    AreaXmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    AreaYmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    AreaYmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    AreaSelect = TRUE;
+  }
+
+  ImagSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-instmag"))) {
+    remove_argument (N, &argc, argv);
+    ImagMin = 1000*atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    ImagMax = 1000*atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    ImagSelect = TRUE;
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "ERROR: USAGE: nrphot (region) (photcode)\n");
+    fprintf (stderr, "  options: \n");
+    fprintf (stderr, "  -time (start) (stop)\n");
+    fprintf (stderr, "  -v\n");
+    fprintf (stderr, "  -plot\n");
+    fprintf (stderr, "  -plotdelay (seconds)\n");
+    fprintf (stderr, "  -statmode (mode)\n");
+    fprintf (stderr, "  -n (nloop)\n");
+    fprintf (stderr, "  -reset\n");
+    fprintf (stderr, "  -update\n");
+    fprintf (stderr, "  -params\n");
+    fprintf (stderr, "  -mosaic (mosaic)\n");
+    fprintf (stderr, "  -imfreeze\n");
+    fprintf (stderr, "  -grid\n");
+    fprintf (stderr, "  -area Xmin Xmax Ymin Ymax\n");
+    fprintf (stderr, "  -instmag min max\n");
+    fprintf (stderr, "  -\n");
+    fprintf (stderr, "  -\n");
+    fprintf (stderr, "  -\n");
+    fprintf (stderr, "  -\n");
+    fprintf (stderr, "  -\n");
+    fprintf (stderr, "  -\n");
+    fprintf (stderr, "  -\n");
+    fprintf (stderr, "  -\n");
+    fprintf (stderr, "  -\n");
+    fprintf (stderr, "  -\n");
+    exit (2);
+  } 
+
+}
+
Index: /tags/start/Ohana/src/relphot/src/bcatalog.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/bcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/bcatalog.c	(revision 12606)
@@ -0,0 +1,119 @@
+# include "relphot.h"
+
+int bcatalog (Catalog *subcatalog, Catalog *catalog, GSCRegion *fullregion) {
+  
+  int i, j, offset, ecode;
+  int NAVERAGE, NMEASURE, Naverage, Nmeasure, Nm;
+  int mag;
+
+  /* we are moving only the subset of measurements from catalog[0] to subcatalog[0] */
+  NAVERAGE = 50;
+  NMEASURE = 1000;
+  ALLOCATE (subcatalog[0].average, Average, NAVERAGE);
+  ALLOCATE (subcatalog[0].secfilt, SecFilt, NAVERAGE*PhotNsec);
+  ALLOCATE (subcatalog[0].measure, Measure, NMEASURE);
+  Nmeasure = Naverage = 0;
+
+  /* exclude stars not in range or with too few measurements */
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    if (catalog[0].average[i].Nm < 2) continue; 
+    if (catalog[0].average[i].R < fullregion[0].RA[0]) continue;
+    if (catalog[0].average[i].R > fullregion[0].RA[1]) continue;
+    if (catalog[0].average[i].D < fullregion[0].DEC[0]) continue;
+    if (catalog[0].average[i].D > fullregion[0].DEC[1]) continue;
+
+    /* start with all stars good */
+    subcatalog[0].average[Naverage] = catalog[0].average[i];
+    subcatalog[0].average[Naverage].offset = Nmeasure;
+    for (j = 0; j < PhotNsec; j++) {
+      subcatalog[0].secfilt[PhotNsec*Naverage+j] = catalog[0].secfilt[PhotNsec*i+j];
+    }
+
+    if (RESET) {
+      short *p;
+      p = (PhotPrimary) ? &subcatalog[0].average[Naverage].M : &subcatalog[0].secfilt[PhotNsec*Naverage+PhotSec].M;
+      *p = NO_MAG;
+      p = (PhotPrimary) ? &subcatalog[0].average[Naverage].dM : &subcatalog[0].secfilt[PhotNsec*Naverage+PhotSec].dM;
+      *p = NO_MAG;
+      subcatalog[0].average[Naverage].code &= ~ID_STAR_FEW;
+      subcatalog[0].average[Naverage].code &= ~ID_STAR_POOR;
+    }
+
+    Nm = 0;
+    for (j = 0; j < catalog[0].average[i].Nm; j++) {
+
+      offset = catalog[0].average[i].offset + j;
+
+      /* select measurements by photcode */
+      ecode = GetPhotcodeEquivCodebyCode (catalog[0].measure[offset].source);
+      if (ecode != photcode[0].code) continue;
+
+      /* select measurements by time */
+      if (TimeSelect) {
+	if (catalog[0].measure[offset].t < TSTART) continue;
+	if (catalog[0].measure[offset].t > TSTOP) continue;
+      }
+
+      /* select measurements by quality */
+      if (catalog[0].measure[offset].dophot != 1) continue;
+
+      /* select measurements by mag limit */
+      mag = iPhotCat (&catalog[0].measure[offset]);
+      if (mag > MAG_LIM) continue;
+
+      /* select measurements by measurement error */
+      if (catalog[0].measure[offset].dM > SIGMA_LIM) continue;
+
+      /* select measurements by mag limit */
+      if (ImagSelect) {
+	mag = iPhotInst (&catalog[0].measure[offset]);
+	if (mag < ImagMin) continue;
+	if (mag > ImagMax) continue;
+      }
+
+      subcatalog[0].measure[Nmeasure].flags &= ~ID_MEAS_SKIP;
+      subcatalog[0].measure[Nmeasure]        = catalog[0].measure[offset];
+      subcatalog[0].measure[Nmeasure].averef = Naverage;
+      if (RESET) { 
+	subcatalog[0].measure[Nmeasure].Mcal = 0;
+	subcatalog[0].measure[Nmeasure].flags &= 0xff00;
+	subcatalog[0].measure[Nmeasure].flags &= ~ID_MEAS_POOR;
+	subcatalog[0].measure[Nmeasure].flags &= ~ID_MEAS_AREA;
+	subcatalog[0].measure[Nmeasure].flags &= ~ID_MEAS_NOCAL;
+      }
+      Nmeasure ++;
+      Nm ++;
+      if (Nmeasure == NMEASURE) {
+	NMEASURE += 1000;
+	REALLOCATE (subcatalog[0].measure, Measure, NMEASURE);
+      }
+    }
+    if (Nm < 2) { /* enough measurements in band? */
+      Nmeasure -= Nm;
+      continue; 
+    }
+    subcatalog[0].average[Naverage].Nm = Nm;
+    Naverage ++;
+    if (Naverage == NAVERAGE) {
+      NAVERAGE += 50;
+      REALLOCATE (subcatalog[0].average, Average, NAVERAGE);
+      REALLOCATE (subcatalog[0].secfilt, SecFilt, NAVERAGE*PhotNsec);
+    }
+  }
+  REALLOCATE (subcatalog[0].average, Average, MAX (Naverage, 1));
+  REALLOCATE (subcatalog[0].measure, Measure, MAX (Nmeasure, 1));
+  REALLOCATE (subcatalog[0].secfilt, SecFilt, PhotNsec*MAX (Naverage, 1));
+  subcatalog[0].Naverage = Naverage;
+  subcatalog[0].Nmeasure = Nmeasure;
+  subcatalog[0].Nsecfilt = catalog[0].Nsecfilt;
+
+  if (catalog[0].Naverage > 0) free (catalog[0].average);
+  if (catalog[0].Nmeasure > 0) free (catalog[0].measure);
+  if (catalog[0].Naverage > 0) free (catalog[0].secfilt);
+
+  if (VERBOSE) {
+    fprintf (stderr, "%d: using %d stars (%d measures) for catalog\n", i, 
+	     subcatalog[0].Naverage, subcatalog[0].Nmeasure);
+  }
+
+}
Index: /tags/start/Ohana/src/relphot/src/find_images.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/find_images.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/find_images.c	(revision 12606)
@@ -0,0 +1,237 @@
+# include "relphot.h"
+
+/* this function returns a list of all images which overlap the given
+   set of region files.  All images in the image catalog are tested
+   once, so there is no check that an image already has been included.
+   LineNum stores the locations in the Image database of the list of
+   images */
+
+Image *find_images (GSCRegion *region, int Nregion, int *Nimages, int **LineNum) {
+  
+  Header header;
+  Image *timage, *image;
+  int i, j, k, m, found, nimage, Nimage, NIMAGE, NTIMAGE, Nloop, Nlast;
+  int n, Nim, status, InRange, ecode;
+  FILE *f;
+  double Xc[5], Yc[5], Xi[5], Yi[5], r, d, dx, dy;
+  char line[256];
+  int *line_number;
+  Coords tcoords;
+
+  if (VERBOSE) fprintf (stderr, "finding images\n");
+
+  /* we make positional comparisons in the projection of catalog */
+  tcoords.crval1 = 0.5*(region[0].RA[0]  + region[0].RA[1]);
+  tcoords.crval2 = 0.5*(region[0].DEC[0] + region[0].DEC[1]);
+  tcoords.crpix1 = tcoords.crpix2 = 0.0;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1  = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2  = tcoords.pc2_1 = 0.0;
+  strcpy (tcoords.ctype, "RA---TAN");
+
+  /* check if image datafile exists, get header, number of images */
+  if (!fits_read_header (ImageCat, &header)) {
+    fprintf (stderr, "ERROR: No images in catalog %s (1)\n", ImageCat);
+    exit (0);
+  }
+  Nimage = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+  if (Nimage == 0) {
+    fprintf (stderr, "ERROR: No images in catalog %s (1)\n", ImageCat);
+    exit (0);
+  }
+
+  /* get ready to read data on images */ 
+  f = fopen (ImageCat, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: trouble opening Image catalog: %s (2)\n", ImageCat);
+    exit (0);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* load all images */
+  ALLOCATE (timage, Image, Nimage);
+  status = Fread (timage, sizeof(Image), Nimage, f, "image");
+  if (status != Nimage) {
+    fprintf (stderr, "ERROR: couldn't read images from image catalog: %s\n", ImageCat);
+    exit (0);
+  }
+
+  nimage = 0;
+  NIMAGE = 100;
+  ALLOCATE (image, Image, NIMAGE);
+  ALLOCATE (line_number, int, NIMAGE);
+  
+  for (i = 0; i < Nimage; i++) {
+      
+    /* select images by photcode */
+    ecode = GetPhotcodeEquivCodebyCode (timage[i].source);
+    if (ecode != photcode[0].code) continue;
+
+    /* select images by time */
+    if (TimeSelect) {
+      if (timage[i].tzero < TSTART) continue;
+      if (timage[i].tzero > TSTOP) continue;
+    }
+    
+    /* ignore image set to SKIP 
+    if (timage[i].code & ID_IMAGE_SKIP) continue; */ 
+
+    /* define image corners */
+    Xi[0] = 0;            Yi[0] = 0;
+    Xi[1] = timage[i].NX; Yi[1] = 0;
+    Xi[2] = timage[i].NX; Yi[2] = timage[i].NY;
+    Xi[3] = 0;            Yi[3] = timage[i].NY;
+    Xi[4] = 0;            Yi[4] = 0;
+    found = FALSE;
+    /* transform to tcoords */
+    for (j = 0; j < 5; j++) {
+      XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+      InRange = RD_to_XY (&Xi[j], &Yi[j], r, d, &tcoords);
+      if (!InRange) goto imskip;
+    }
+    /* compare with each region file */
+    for (m = 0; (m < Nregion) && !found; m++) { 
+      /* define catalog corners */
+      Xc[0] = region[m].RA[0]; Yc[0] = region[m].DEC[0];
+      Xc[1] = region[m].RA[1]; Yc[1] = region[m].DEC[0];
+      Xc[2] = region[m].RA[1]; Yc[2] = region[m].DEC[1];
+      Xc[3] = region[m].RA[0]; Yc[3] = region[m].DEC[1];
+      Xc[4] = region[m].RA[0]; Yc[4] = region[m].DEC[0];
+      for (j = 0; j < 5; j++) {
+	r = Xc[j]; d = Yc[j];
+	RD_to_XY (&Xc[j], &Yc[j], r, d, &tcoords);
+      }
+      dx = 0.02*(Xc[2] - Xc[0]);
+      dy = 0.02*(Yc[2] - Yc[0]);
+      Xc[0] -= dx; Yc[0] -= dy;
+      Xc[1] += dx; Yc[1] -= dy;
+      Xc[2] += dx; Yc[2] += dy;
+      Xc[3] -= dx; Yc[3] += dy;
+      Xc[4] -= dx; Yc[4] -= dy;
+      
+      /* check if image corner inside catalog */
+      for (j = 0; (j < 4) && !found; j++) {
+	found |= corner_check (&Xi[j], &Yi[j], &Xc[0], &Yc[0]);
+      }
+      /* check if catalog corner inside image */
+      for (j = 0; (j < 4) && !found; j++) {
+	found |= corner_check (&Xc[j], &Yc[j], &Xi[0], &Yi[0]);
+      }
+      /* check if edges cross */
+      for (j = 0; (j < 4) && !found; j++) {
+	for (k = 0; (k < 4) && !found; k++) {
+	  found |= edge_check (&Xi[j], &Yi[j], &Xc[k], &Yc[k]);
+	}
+      }
+      if (found) {
+	image[nimage] = timage[i]; 
+	/* always allow a 'few' image to succeed, if possible */
+	if (image[nimage].code & ID_IMAGE_FEW) { 
+	  image[nimage].code &= ~(ID_IMAGE_FEW | ID_IMAGE_POOR);
+	}
+	if (RESET) {
+	  assignMcal (&image[nimage], (double *) NULL, -1);
+	  image[nimage].dMcal = NO_MAG;
+	  image[nimage].code &= ~ID_IMAGE_POOR;
+	}
+	line_number[nimage] = i;
+	nimage ++;
+	if (nimage == NIMAGE) {
+	  NIMAGE += 100;
+	  REALLOCATE (image, Image, NIMAGE);
+	  REALLOCATE (line_number, int, NIMAGE);
+	}
+      }
+    }
+  imskip:
+  }
+      
+  if (VERBOSE) fprintf (stderr, "found %d images\n", nimage);
+
+  REALLOCATE (image, Image, MAX (nimage, 1));
+  REALLOCATE (line_number, int, MAX (nimage, 1));
+
+  free (timage);
+  *Nimages = nimage;
+  *LineNum = line_number;
+  fclose (f);
+  return (image);
+}
+
+/* check if line between points 0 and 1 of x1
+   crosses line between points 0 and 1 of x2 */
+int edge_check (double *x1, double *y1, double *x2, double *y2) {
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+/* check if point x1,y1 is in box formed by x2[0-4] */
+int corner_check (double *x1, double *y1, double *x2, double *y2) {
+
+  int i;
+  double theta;
+
+  theta = 0;
+
+  for (i = 0; i < 4; i++) {
+    theta += opening_angle (x2[i], y2[i], x1[0], y1[0], x2[i+1], y2[i+1]); 
+  }
+  if (fabs(theta) > 6) {
+    return (TRUE);
+  } else {
+    return (FALSE);
+  }
+}
+
+/* returns the opening angle between the three points (2 is in middle) 
+   in range -pi to pi */
+
+double opening_angle (double x1, double y1, double x2, double y2, double x3, double y3) {
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
+
Index: /tags/start/Ohana/src/relphot/src/find_regions.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/find_regions.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/find_regions.c	(revision 12606)
@@ -0,0 +1,102 @@
+# include "relphot.h"
+
+/* given a list of images, find all region files which overlap these images.
+   if a region file does not exist, we should recognize this fact somehow */
+
+GSCRegion *find_regions (Image *image, int Nimage, int *Nregions, GSCRegion *fullregion) {
+
+  int i, nregions;
+  double x, y;
+  GSCRegion *regions;
+  double MinRA, MaxRA, MinDEC, MaxDEC, ra, dec;
+
+  if (VERBOSE) fprintf (stderr, "finding regions: ");
+  
+  /* find RA and DEC range of images */
+  MinRA = MinDEC = +361;
+  MaxRA = MaxDEC = -361;
+  for (i = 0; i < Nimage; i++) {
+    for (x = 0.0; x <= 1.0; x+=0.25) {
+      for (y = 0.0; y <= 1.0; y+=0.25) {
+	XY_to_RD (&ra, &dec, image[i].NX*(1.1*x - 0.05), image[i].NY*(1.1*y - 0.05), &image[i].coords);
+	MinRA = MIN (ra, MinRA);
+	MaxRA = MAX (ra, MaxRA);
+	MinDEC = MIN (dec, MinDEC);
+	MaxDEC = MAX (dec, MaxDEC);
+      }
+    }
+  }
+
+  /* if images overlap 0,360 boundary, then use -180 to +180 range */
+  if (MaxRA - MinRA > 180) {
+    MinRA = +361;
+    MaxRA = -361;
+    for (i = 0; i < Nimage; i++) {
+      for (x = 0.0; x <= 1.0; x+=0.25) {
+	for (y = 0.0; y <= 1.0; y+=0.25) {
+	  XY_to_RD (&ra, &dec, image[i].NX*(1.1*x - 0.05), image[i].NY*(1.1*y - 0.05), &image[i].coords);
+	  if (ra > 180) ra -= 360;
+	  MinRA = MIN (ra, MinRA);
+	  MaxRA = MAX (ra, MaxRA);
+	}
+      }
+    }
+  }
+
+  fullregion[0].RA[0] = MinRA;
+  fullregion[0].RA[1] = MaxRA;
+  fullregion[0].DEC[0] = MinDEC;
+  fullregion[0].DEC[1] = MaxDEC;
+
+  /* find all region files containing specified ra, dec range */  
+  regions = get_regions (MinRA, MaxRA, MinDEC, MaxDEC, &nregions);
+
+  if (VERBOSE) fprintf (stderr, "%d found\n", nregions);
+
+  *Nregions = nregions;
+  return (regions);
+}
+
+
+getfullregion (Image *image, int Nimage, GSCRegion *fullregion) {
+
+  int i;
+  double x, y;
+  double MinRA, MaxRA, MinDEC, MaxDEC, ra, dec;
+
+  /* find RA and DEC range of images */
+  MinRA = MinDEC = +361;
+  MaxRA = MaxDEC = -361;
+  for (i = 0; i < Nimage; i++) {
+    for (x = 0.0; x <= 1.0; x+=0.25) {
+      for (y = 0.0; y <= 1.0; y+=0.25) {
+	XY_to_RD (&ra, &dec, image[i].NX*(1.1*x - 0.05), image[i].NY*(1.1*y - 0.05), &image[i].coords);
+	MinRA = MIN (ra, MinRA);
+	MaxRA = MAX (ra, MaxRA);
+	MinDEC = MIN (dec, MinDEC);
+	MaxDEC = MAX (dec, MaxDEC);
+      }
+    }
+  }
+
+  /* if images overlap 0,360 boundary, then use -180 to +180 range */
+  if (MaxRA - MinRA > 180) {
+    MinRA = +361;
+    MaxRA = -361;
+    for (i = 0; i < Nimage; i++) {
+      for (x = 0.0; x <= 1.0; x+=0.25) {
+	for (y = 0.0; y <= 1.0; y+=0.25) {
+	  XY_to_RD (&ra, &dec, image[i].NX*(1.1*x - 0.05), image[i].NY*(1.1*y - 0.05), &image[i].coords);
+	  if (ra > 180) ra -= 360;
+	  MinRA = MIN (ra, MinRA);
+	  MaxRA = MAX (ra, MaxRA);
+	}
+      }
+    }
+  }
+
+  fullregion[0].RA[0] = MinRA;
+  fullregion[0].RA[1] = MaxRA;
+  fullregion[0].DEC[0] = MinDEC;
+  fullregion[0].DEC[1] = MaxDEC;
+}
Index: /tags/start/Ohana/src/relphot/src/free_catalogs.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/free_catalogs.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/free_catalogs.c	(revision 12606)
@@ -0,0 +1,13 @@
+# include "relphot.h"
+
+void free_catalogs (Catalog *catalog, int Ncatalog) {
+
+  int i;
+
+  for (i = 0; i < Ncatalog; i++) {
+    free (catalog[i].secfilt);
+    free (catalog[i].average);
+    free (catalog[i].measure);
+  }
+
+}
Index: /tags/start/Ohana/src/relphot/src/gcatalog.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/gcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/gcatalog.c	(revision 12606)
@@ -0,0 +1,26 @@
+# include "relphot.h"
+
+int gcatalog (Catalog *catalog, int FINAL) {
+  
+  char mode, status;
+
+  if (FINAL) {
+    mode = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+  } else {
+    mode = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+  }    
+
+  if (!load_catalog (catalog, mode, VERBOSE)) {
+    fprintf (stderr, "ERROR: failure loading catalog %s\n", catalog[0].filename);
+    exit (1);
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "read %d stars from catalog file %s (%d measurements)\n", 
+	     catalog[0].Naverage, catalog[0].filename, catalog[0].Nmeasure);
+  }
+  return (TRUE);
+}
+
+
+
Index: /tags/start/Ohana/src/relphot/src/get_regions.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/get_regions.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/get_regions.c	(revision 12606)
@@ -0,0 +1,208 @@
+# include "relphot.h"
+double BigDecBounds[] = {0.0, 7.5, 15.0, 22.5, 30.0, 37.5, 45.0, 
+			 52.5, 60.0, 67.5, 75.0, 82.5, 90.0,
+			 0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, 
+			 -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+
+double Areas[] = {2700.0, 2665.4505, 2563.567, 2399.5344, 2181.6343, 1920.7299, 1629.5942, 1322.1251, 1012.5, 714.32555, 439.83856, 199.21043, 0.0,
+		  2700.0, 2665.4505, 2563.567, 2399.5344, 2181.6343, 1920.7299, 1629.5942, 1322.1251, 1012.5, 714.32555, 439.83856, 199.21043, 0.0};
+
+char *DecSections[] = {"N0000", "N0730", "N1500", "N2230", "N3000", "N3730", "N4500", 
+		       "N5230", "N6000", "N6730", "N7500", "N8230", "weirdness", 
+		       "S0000", "S0730", "S1500", "S2230", "S3000", "S3730", "S4500", 
+		       "S5230", "S6000", "S6730", "S7500", "S8230", "weirdness"};
+
+char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			"n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			"s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			"s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+char *disk[] = {"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", 
+		"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "weirdness", 
+		"disk 1", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", 
+		"disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "weirdness"};
+
+int NBigRASections [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3, 48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3};
+
+int NDecLines[] = {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 24, 
+                   0, 597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48};
+
+/* returns a list of region files within the desired RA, DEC region */
+GSCRegion *get_regions (double minRa, double maxRa, double minDec, double maxDec, int *Nregions) {
+  
+  char buffer[28800], temp[50];
+  GSCRegion *regions;
+  FILE *f;
+  double RA0, RA1, DEC0, DEC1;
+  int i, j, NBigDec;
+  int NLINES, done, NREGIONS, nregions;
+  
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find regions file %s\n", GSCFILE);
+    exit (0);
+  }
+  
+  NREGIONS = 50;
+  ALLOCATE (regions, GSCRegion, NREGIONS);
+  nregions = 0;
+
+  if ((minDec <= -90) || (maxDec >= 90)) {
+    minRa = 0;
+    maxRa = 360;
+  }
+  
+  /* use the pole regions, if near pole */
+  if (maxDec > 86.25) {
+    sprintf (regions[nregions].filename, "n8230/pole.cpt\0");
+    regions[nregions].RA[0] = 0;
+    regions[nregions].RA[1] = 360;
+    regions[nregions].DEC[0] = 86.25;
+    regions[nregions].DEC[1] = 90.0;
+    nregions ++;
+    if (nregions == NREGIONS) {
+      NREGIONS += 50;
+      REALLOCATE (regions, GSCRegion, NREGIONS);
+    }
+  }
+
+  if (minDec > 86.25) {
+    *Nregions = nregions;
+    return (regions);
+  }
+    
+  if ((minDec < 0) && (maxDec > 0)) {
+    /* Search Both Sides */
+    NBigDec = 0;
+  } else {
+    /* find large DEC region (directory) */
+    NBigDec = -1;
+    for (i = 0; i < 12; i++) {
+      if ((minDec >= BigDecBounds[i]) && (minDec < BigDecBounds[i+1])) {
+	NBigDec = i;
+	break;
+      }
+    }
+    if (NBigDec < 0) {
+      for (i = 13; i < 24; i++) {
+	if ((maxDec < BigDecBounds[i]) && (maxDec >= BigDecBounds[i+1])) {
+	  NBigDec = i;
+	  break;
+	}
+      }
+    }
+  }
+  if (NBigDec < 0) {
+    fprintf (stderr, "ERROR: Dec out of range: %f\n", minDec);
+    *Nregions = 0;
+    return ((GSCRegion *) NULL);
+  }
+  
+  /* count lines before section */
+  NLINES = 0;
+  for (i = 0; i < NBigDec; i++) {
+    NLINES += NDecLines[i];
+  }
+  fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+  
+  /* should be in this section.  if not, there is a problem counting... */
+  /* careful with the 0,360.0 boundary **/
+  done = FALSE;
+  for (j = 0; !done && (NBigDec + j < 25); j++) {
+    fread (buffer, 48*NDecLines[NBigDec + j], 1, f);
+    for (i = 0; (i < NDecLines[NBigDec + j]); i++) {
+      strncpy (temp, &buffer[i*48], 48);
+      temp[49] = 0;
+      hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+      if (RA1 < RA0) RA1 += 360.0;
+      if ((DEC1 > 0) && (minDec < DEC1) && (maxDec > DEC0) && (minRa < RA1) && (maxRa > RA0)) {
+	temp[5] = 0;
+	sprintf (regions[nregions].filename, "%s/%s.cpt\0", Dec2Sections[NBigDec + j], &temp[1]);
+	regions[nregions].RA[0] = RA0;
+	regions[nregions].RA[1] = RA1;
+	regions[nregions].DEC[0] = DEC0;
+	regions[nregions].DEC[1] = DEC1;
+	nregions ++;
+	if (nregions == NREGIONS) {
+	  NREGIONS += 50;
+	  REALLOCATE (regions, GSCRegion, NREGIONS);
+	}
+      }
+      if ((DEC1 < 0) && (minDec < DEC0) && (maxDec > DEC1) && (minRa < RA1) && (maxRa > RA0)) {
+	temp[5] = 0;
+	sprintf (regions[nregions].filename, "%s/%s.cpt\0", Dec2Sections[NBigDec + j], &temp[1]);
+	regions[nregions].RA[0] = RA0;
+	regions[nregions].RA[1] = RA1;
+	regions[nregions].DEC[0] = DEC0;
+	regions[nregions].DEC[1] = DEC1;
+	nregions ++;
+	if (nregions == NREGIONS) {
+	  NREGIONS += 50;
+	  REALLOCATE (regions, GSCRegion, NREGIONS);
+	}
+      }
+      if (((DEC1 > 0) && (maxDec <= DEC1)) || ((DEC1 < 0) && (minDec >= DEC1))) {
+	done = TRUE;
+      }
+    }
+    if (done && (minDec < 0) && (maxDec > 0) && (BigDecBounds[NBigDec + j + 1] > 0)) {
+      /* skip remaining north sections, try south sections */
+      /* count lines before section */
+      NLINES = 0;
+      for (i = 0; i < 13; i++) { 
+	NLINES += NDecLines[i];
+      }
+      fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+      done = FALSE;
+      j = 12;
+    }
+  }
+
+  REALLOCATE (regions, GSCRegion, MAX (1,nregions));
+  *Nregions = nregions;
+  
+  fclose (f);
+  return (regions);
+  
+}
+
+/**********/
+int hms_to_deg (double *h0, double *h1, double *d0, double *d1, char *string) {
+  
+  int flag_d0, flag_d1, flag_h0, flag_h1;
+  double tmp;
+  
+  *d0 = *h0 = *d1 = *h1 = 0;
+
+  flag_h0 = dparse (h0, 1, string);
+  flag_h1 = dparse (h1, 4, string);
+  flag_d0 = dparse (d0, 7, string);
+  flag_d1 = dparse (d1, 9, string);
+  *h0 *= flag_h0;
+  *h1 *= flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  dparse (&tmp, 2, string);
+  *h0 += tmp/60.0;
+  dparse (&tmp, 3, string);
+  *h0 += tmp/3600.0;
+  
+  dparse (&tmp, 5, string);
+  *h1 += tmp/60.0;
+  dparse (&tmp, 6, string);
+  *h1 += tmp/3600.0;
+  
+  dparse (&tmp, 8, string);
+  *d0 += tmp/60.0;
+
+  dparse (&tmp, 10, string);
+  *d1 += tmp/60.0;
+
+  *h0 *= 15*flag_h0;
+  *h1 *= 15*flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  return (TRUE);
+}
Index: /tags/start/Ohana/src/relphot/src/global_stats.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/global_stats.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/global_stats.c	(revision 12606)
@@ -0,0 +1,51 @@
+# include "relphot.h"
+
+StatType statsImagedM (Catalog *catalog);
+
+StatType statsMosaicdM (Catalog *catalog);
+StatType statsMosaicM (Catalog *catalog);
+StatType statsMosaicN (Catalog *catalog);
+StatType statsMosaicX (Catalog *catalog);
+
+global_stats (Catalog *catalog, int Ncatalog) {
+
+  StatType stN, stX, stS, imN, imX, imM, imD, msM, msX, msN, msD;
+
+  initstats ("MEAN");
+
+  stN = statsStarN (catalog, Ncatalog);
+  stX = statsStarX (catalog, Ncatalog);
+  stS = statsStarS (catalog, Ncatalog);
+
+  imN = statsImageN (catalog);
+  imX = statsImageX (catalog);
+  imM = statsImageM (catalog);
+  imD = statsImagedM (catalog);
+
+  msN = statsMosaicN (catalog);
+  msM = statsMosaicM (catalog);
+  msD = statsMosaicdM (catalog);
+  msX = statsMosaicX (catalog);
+
+  fprintf (stderr, "STATS           median    mean   sigma     min      max  Nmeas\n");
+  fprintf (stderr, "meas / image:   %6.0f  %6.1f  %6.1f  %6.0f  %7.0f  %6d\n",   imN.median, imN.mean, imN.sigma, imN.min, imN.max, imN.Nmeas);
+  fprintf (stderr, "meas / mosaic:  %6.0f  %6.1f  %6.1f  %6.0f  %7.0f  %6d\n",   msN.median, msN.mean, msN.sigma, msN.min, msN.max, msN.Nmeas);
+  fprintf (stderr, "meas / star:    %6.0f  %6.1f  %6.1f  %6.0f  %7.0f  %6d\n",   stN.median, stN.mean, stN.sigma, stN.min, stN.max, stN.Nmeas);
+
+  fprintf (stderr, "chisq image:    %6.1f  %6.1f  %6.1f  %6.1f  %7.1f  %6d\n",   imX.median, imX.mean, imX.sigma, imX.min, imX.max, imX.Nmeas);
+  fprintf (stderr, "chisq mosaic:   %6.1f  %6.1f  %6.1f  %6.1f  %7.1f  %6d\n",   msX.median, msX.mean, msX.sigma, msX.min, msX.max, msX.Nmeas);
+  fprintf (stderr, "chisq star:     %6.1f  %6.1f  %6.1f  %6.1f  %7.1f  %6d\n",   stX.median, stX.mean, stX.sigma, stX.min, stX.max, stX.Nmeas);
+
+  fprintf (stderr, "Mcal image:     %6.3f  %6.3f  %6.3f  %6.3f  %7.3f  %6d\n",   imM.median, imM.mean, imM.sigma, imM.min, imM.max, imM.Nmeas);
+  fprintf (stderr, "dMcal image:    %6.3f  %6.3f  %6.3f  %6.3f  %7.3f  %6d\n",   imD.median, imD.mean, imD.sigma, imD.min, imD.max, imD.Nmeas);
+
+  fprintf (stderr, "Mcal mosaic:    %6.3f  %6.3f  %6.3f  %6.3f  %7.3f  %6d\n",   msM.median, msM.mean, msM.sigma, msM.min, msM.max, msM.Nmeas);
+  fprintf (stderr, "dMcal mosaic:   %6.3f  %6.3f  %6.3f  %6.3f  %7.3f  %6d\n",   msD.median, msD.mean, msD.sigma, msD.min, msD.max, msD.Nmeas);
+
+  fprintf (stderr, "dMrel star:     %6.3f  %6.3f  %6.3f  %6.3f  %7.3f  %6d\n\n", stS.median, stS.mean, stS.sigma, stS.min, stS.max, stS.Nmeas);
+
+  initstats (STATMODE);
+
+}
+
+
Index: /tags/start/Ohana/src/relphot/src/initialize.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/initialize.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/initialize.c	(revision 12606)
@@ -0,0 +1,56 @@
+# include "relphot.h"
+
+void initialize (int argc, char **argv) {
+
+  int Np;
+
+  /* are these set correctly? */
+  ConfigInit (&argc, argv);
+  args (argc, argv);
+
+  if ((photcode = GetPhotcodebyName (argv[2])) == NULL) {
+    fprintf (stderr, "ERROR: photcode %s not found in photcode table\n", argv[2]);
+    exit (1);
+  }
+  if ((photcode[0].type != PHOT_PRI) && (photcode[0].type != PHOT_SEC)) {
+    fprintf (stderr, "photcode %s is not a primary or secondary filter\n", argv[2]);
+    exit (1);
+  }
+
+  PhotPrimary = (photcode[0].type == PHOT_PRI);
+  PhotNsec = GetPhotcodeNsecfilt ();
+  PhotSec = GetPhotcodeNsec (photcode[0].code);
+
+  initstats (STATMODE);
+
+  IMAGE_BAD = ID_IMAGE_POOR | ID_IMAGE_FEW | ID_IMAGE_SKIP;
+  STAR_BAD  = ID_STAR_POOR | ID_STAR_FEW;
+  MEAS_BAD  = ID_MEAS_NOCAL | ID_MEAS_POOR | ID_MEAS_SKIP | ID_MEAS_AREA;
+
+  if (SHOW_PARAMS) {
+    fprintf (stderr, "current parameter settings:\n");
+    if (TimeSelect) {
+      fprintf (stderr, "TimeSelect: TRUE (%s - %s)\n", sec_to_date (TSTART), sec_to_date (TSTOP));
+    } else {
+      fprintf (stderr, "TimeSelect: FALSE\n");
+    }
+    fprintf (stderr, "VERBOSE: %d, PLOTSTUFF: %d\n", VERBOSE, PLOTSTUFF);
+    fprintf (stderr, "GRID_X: %d, GRID_Y: %d, BINNING: %d == Nmx: %d, Nmy: %d\n", 
+	     RELPHOT_GRID_X, 
+	     RELPHOT_GRID_Y, 
+	     RELPHOT_GRID_BINNING, 
+	     (int)(RELPHOT_GRID_X/RELPHOT_GRID_BINNING), (int)(RELPHOT_GRID_Y/RELPHOT_GRID_BINNING));
+
+    fprintf (stderr, "MAG_LIM                %lf\n", MAG_LIM);
+    fprintf (stderr, "STAR_SCATTER           %lf\n", STAR_SCATTER);
+    fprintf (stderr, "IMAGE_SCATTER          %lf\n", IMAGE_SCATTER);
+    fprintf (stderr, "IMAGE_OFFSET           %lf\n", IMAGE_OFFSET);
+    fprintf (stderr, "IMAGE_CATALOG          %s\n",  ImageCat);
+    fprintf (stderr, "IMAGE_CATALOG_TEMPLATE %s\n",  ImageTemplate);
+    fprintf (stderr, "CATALOG_TEMPLATE       %s\n",  CatTemplate);
+    fprintf (stderr, "GSCFILE                %s\n",  GSCFILE);
+    fprintf (stderr, "CATDIR                 %s\n",  CATDIR);
+    exit (0);
+  }
+}
+
Index: /tags/start/Ohana/src/relphot/src/liststats.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/liststats.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/liststats.c	(revision 12606)
@@ -0,0 +1,117 @@
+# include "relphot.h"
+
+enum {M_MEAN, M_MEDIAN, M_WT_MEAN, M_INNER_MEAN, 
+      M_INNER_WTMEAN, M_CHI_INNER_MEAN, M_CHI_INNER_WTMEAN};
+
+static int statmode;
+
+initstats (char *mode) {
+
+  statmode = -1;
+  if (!strcmp (mode, "MEAN")) statmode = M_MEAN;
+  if (!strcmp (mode, "MEDIAN")) statmode = M_MEDIAN;
+  if (!strcmp (mode, "WT_MEAN")) statmode = M_WT_MEAN;
+  if (!strcmp (mode, "INNER_MEAN")) statmode = M_INNER_MEAN;
+  if (!strcmp (mode, "INNER_WTMEAN")) statmode = M_INNER_WTMEAN;
+  if (!strcmp (mode, "CHI_INNER_MEAN")) statmode = M_CHI_INNER_MEAN;
+  if (!strcmp (mode, "CHI_INNER_WTMEAN")) statmode = M_CHI_INNER_WTMEAN;
+
+  if (statmode == -1) {
+    fprintf (stderr, "ERROR: invalid stats mode: %s\n", mode);
+    exit (1);
+  }
+}
+
+int liststats (double *value, double *dvalue, int N, StatType *stats) {
+  
+  int i, ks, ke, Nm;
+  double Mo, dMo, M, dM, X2, dS, *chi;
+
+  stats[0].Nmeas = N;
+  stats[0].mean  = 0;
+  stats[0].sigma = 0;
+  stats[0].error = 0;
+  stats[0].chisq = 0;
+  if (N < 1) return (FALSE);
+
+  sortB (value, dvalue, N);
+  stats[0].median = value[(int)(0.5*N)];
+  stats[0].min    = value[0];
+  stats[0].max    = value[N-1];
+
+  switch (statmode) {
+  case M_MEDIAN:
+    ks = 0;
+    ke = N;
+    Mo = stats[0].median;
+    Nm = N;
+    goto chisq;
+    break;
+  case M_MEAN:
+  case M_WT_MEAN:
+    ks = 0;
+    ke = N;
+    break;
+  case M_INNER_MEAN:
+  case M_INNER_WTMEAN:
+  case M_CHI_INNER_MEAN:
+  case M_CHI_INNER_WTMEAN:
+    ks = 0.25*N + 0.50;
+    ke = 0.75*N + 0.25;
+    if (N <= 3) {
+      ks = 0;
+      ke = N;
+    }
+    break;
+  }    
+
+  if ((statmode == M_CHI_INNER_MEAN) || (statmode == M_CHI_INNER_WTMEAN)) {
+    ALLOCATE (chi, double, N);
+    for (i = 0; i < N; i++) {
+      chi[i] = (value[i] - stats[0].median) / dvalue[i];
+    }
+    sortD (chi, value, dvalue, N);
+    free (chi);
+  }
+
+  /* calculating the per-star offset based on the weighted average */
+  M = dM = Nm = 0;
+  if ((statmode == M_WT_MEAN) || (statmode == M_INNER_WTMEAN) || (statmode == M_CHI_INNER_WTMEAN)) {
+    for (i = ks; i < ke; i++) {
+      M   += value[i] / SQ (dvalue[i]);
+      dM  += 1.0 / SQ (dvalue[i]);
+      Nm  ++;  
+    }	
+    Mo = M / dM;
+    dMo = sqrt (1.0 / dM);
+  } else {
+    for (i = ks; i < ke; i++) {
+      M   += value[i];
+      dM  += SQ (dvalue[i]);
+      Nm  ++;  
+    }	
+    Mo = M / (double) Nm;
+    dMo = sqrt (dM / (double) Nm);
+  }
+
+ chisq:
+  /* find sigma and chisq */
+  X2 = dS = 0;
+  for (i = ks; i < ke; i++) {
+    M  = SQ (value[i] - Mo);
+    dM = SQ (dvalue[i]);
+    X2 += M / dM;
+    dS += M;
+  }
+  X2 = X2 / Nm;
+  dS = sqrt (dS / Nm);
+
+  stats[0].mean  = Mo;
+  stats[0].Nmeas = Nm;
+  stats[0].chisq = X2;
+  stats[0].sigma = dS;
+  stats[0].error = dMo;
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/relphot/src/load_catalogs.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/load_catalogs.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/load_catalogs.c	(revision 12606)
@@ -0,0 +1,45 @@
+# include "relphot.h"
+
+Catalog *load_catalogs (GSCRegion *region, int Nregion, GSCRegion *fullregion) {
+
+  int i, Nstar;
+  char filename[256];
+  Catalog *catalog, tcatalog;
+
+  if (VERBOSE) fprintf (stderr, "loading catalog data\n");
+
+  ALLOCATE (catalog, Catalog, Nregion);
+
+  /* load data from each region file, only use bright stars */
+  for (i = 0; i < Nregion; i++) {
+    sprintf (filename, "%s/%s", CATDIR, region[i].filename);
+    tcatalog.filename = filename;  /* don't free region before catalog! */
+    switch (lock_catalog (&tcatalog, LCK_SOFT)) {
+    case 0:
+      fprintf (stderr, "ERROR: can't lock file %s\n", region[i].filename);
+      exit (1);
+    case 1:
+      gcatalog (&tcatalog, FALSE); /* load from disk */
+      break;
+    case 2:
+      if (VERBOSE) fprintf (stderr, "no data in %s, skipping\n", tcatalog.filename);
+      tcatalog.Naverage = 0;
+      tcatalog.Nmeasure = 0;
+      break;
+    default:
+      fprintf (stderr, "weird lock_catalog exit state\n");
+      exit (1);
+    }
+    bcatalog (&catalog[i], &tcatalog, fullregion);
+  }
+
+  Nstar = 0;
+  for (i = 0; i < Nregion; i++) {
+    Nstar += catalog[i].Naverage;
+  }
+  if (Nstar < 2) { 
+    fprintf (stderr, "insufficient stars %d\n", Nstar);
+    exit (0);
+  }
+  return (catalog);
+}
Index: /tags/start/Ohana/src/relphot/src/load_images.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/load_images.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/load_images.c	(revision 12606)
@@ -0,0 +1,67 @@
+# include "relphot.h"
+
+static int   Nimage;
+static int   *Line;
+static Image *image;
+
+GSCRegion *load_images (char *seed, int *nregion, GSCRegion *fullregion) {
+
+  GSCRegion *region;
+  int       Nregion, Ntimage;
+  Image     *timage;
+
+  region = name_region (seed, &Nregion);
+
+  /* find images which supplied all measurements */
+  timage = find_images (region, Nregion, &Ntimage, &Line);
+  free (Line);
+
+  /* find all region files which touch images */
+  region = find_regions (timage, Ntimage, &Nregion, fullregion);
+  free (timage);
+
+  /* find images which supplied all measurements for all regions */
+  image = find_images (region, Nregion, &Nimage, &Line);
+  getfullregion (image, Nimage, fullregion);
+
+  initImages (image, Nimage);
+  initMosaics (image, Nimage);
+  
+  *nregion = Nregion;
+  return (region);
+
+}
+
+void wimages () {
+  
+  int i, status, mode;
+  FILE *f;
+  Header header;
+
+  setMcalFinal (image, Nimage);
+
+  if (!fits_read_header (ImageCat, &header)) {
+    fprintf (stderr, "ERROR: can't find %s\n", ImageCat);
+    exit (0);
+  }
+  
+  f = fopen (ImageCat, "r+");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open image catalog file to append: %s\n", ImageCat);
+    exit (0);
+  }
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  chmod (ImageCat, mode);
+
+  if (VERBOSE) fprintf (stderr, "writing out %d images\n", Nimage);
+  for (i = 0; i < Nimage; i++) {
+    fseek (f, header.size + Line[i]*sizeof(Image), SEEK_SET);
+    status = Fwrite (&image[i], sizeof(Image), 1, f, "image");
+    if (status != 1) {
+      fprintf (stderr, "ERROR: failure writing image data to catalog %s\n", ImageCat);
+      exit (0);
+    }
+  }
+
+  fclose (f);
+}
Index: /tags/start/Ohana/src/relphot/src/misc.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/misc.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/misc.c	(revision 12606)
@@ -0,0 +1,182 @@
+
+sortA (double *X, int N) {
+
+  int l,j,ir,i;
+  double tX;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+  }
+}
+
+sortB (double *X, double *Y, int N) {
+
+  int l,j,ir,i;
+  double tX, tY;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+  }
+}
+
+sortC (double *X, double *Y, double *F1, double *F2, int N) {
+
+  int l,j,ir,i;
+  double tX, tY;
+  double t1, t2;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      t1 = F1[l];
+      t2 = F2[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      t1 = F1[ir];
+      F1[ir] = F1[0];
+      t2 = F2[ir];
+      F2[ir] = F2[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	F1[0] = t1;
+	F2[0] = t2;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	F1[i] = F1[j];
+	F2[i] = F2[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    F1[i] = t1;
+    F2[i] = t2;
+  }
+}
+
+sortD (double *X, double *Y, double *Z, int N) {
+
+  int l,j,ir,i;
+  double tX, tY, tZ;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tZ = Z[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tZ = Z[ir];
+      Z[ir] = Z[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	Z[0] = tZ;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	Z[i] = Z[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    Z[i] = tZ;
+  }
+}
+
Index: /tags/start/Ohana/src/relphot/src/name_region.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/name_region.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/name_region.c	(revision 12606)
@@ -0,0 +1,24 @@
+# include "relphot.h"
+
+GSCRegion *name_region (char *name, int *Nregions) {
+
+  GSCRegion *region;
+  Header header;
+
+  ALLOCATE (region, GSCRegion, 1);
+
+  sprintf (region[0].filename, "%s/%s", CATDIR, name);
+  if (!fits_read_header (region[0].filename, &header)) {
+    if (VERBOSE) fprintf (stderr, "catalog file not yet available: %s\n", region[0].filename);
+    exit (0);
+  }
+  fits_scan (&header, "RA0", "%lf", 1, &region[0].RA[0]);
+  fits_scan (&header, "RA1", "%lf", 1, &region[0].RA[1]);
+  fits_scan (&header, "DEC0", "%lf", 1, &region[0].DEC[0]);
+  fits_scan (&header, "DEC1", "%lf", 1, &region[0].DEC[1]);
+  fits_free_header (&header);
+
+  *Nregions = 1;
+  return (region);
+}
+
Index: /tags/start/Ohana/src/relphot/src/plot_scatter.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/plot_scatter.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/plot_scatter.c	(revision 12606)
@@ -0,0 +1,61 @@
+# include "relphot.h"
+   
+plot_scatter (Catalog *catalog, int Ncatalog) {
+
+  char c;
+  int i, j, k, m, N, Ntot;
+  short Mrel, Mcal, Mmos, Mgrid;
+  double *xlist, *ylist, *ilist;
+  StatType stats;
+  Graphdata graphdata;
+
+  Ntot = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      Ntot += catalog[i].average[j].Nm;
+    }
+  }
+  ALLOCATE (xlist, double, Ntot);
+  ALLOCATE (ylist, double, Ntot);
+  ALLOCATE (ilist, double, Ntot);
+
+  N = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* calculate the average value for a single star */
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+      m = catalog[i].average[j].offset;
+
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	if (catalog[i].measure[m].flags & MEAS_BAD) continue;
+	if ((Mcal  = getMcal  (m, i)) == NO_MAG) continue;
+	if ((Mmos  = getMmos  (m, i)) == NO_MAG) continue;
+	if ((Mgrid = getMgrid (m, i)) == NO_MAG) continue;
+
+	Mrel = PhotPrimary ? catalog[i].average[j].M : catalog[i].secfilt[PhotNsec*j+PhotSec].M;
+	xlist[N] = Mrel;
+	ylist[N] = iPhotSys (&catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]) - Mcal - Mmos - Mgrid - Mrel;
+	ilist[N] = PhotInst (&catalog[i].measure[m]);
+	xlist[N] *= 0.001;
+	ylist[N] *= 0.001;
+	N++;
+      }
+    }
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.xmin = PlotMmin;
+  graphdata.xmax = PlotMmax;
+  graphdata.ymin = PlotdMmin;
+  graphdata.ymax = PlotdMmax;
+  plot_list (&graphdata, xlist, ylist, N, "mag vs dmag", "Mag.png");
+
+  plot_defaults (&graphdata);
+  graphdata.ymin = PlotdMmin;
+  graphdata.ymax = PlotdMmax;
+  plot_list (&graphdata, ilist, ylist, N, "imag vs dmag", NULL);
+  free (xlist);
+  free (ylist);
+  free (ilist);
+}
Index: /tags/start/Ohana/src/relphot/src/plotstuff.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/plotstuff.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/plotstuff.c	(revision 12606)
@@ -0,0 +1,224 @@
+# include "relphot.h"
+# include <signal.h>
+
+static int Xgraph[5] = {0,0,0,0,0};
+static int active;
+
+void XDead () {
+  signal (SIGPIPE, XDead);
+  fprintf (stderr, "kapa is dead, must restart\n");
+  Xgraph[active] = -1;
+}
+
+int open_graph (int N) {
+
+# ifdef ANSI
+#   define F_SETFL      4   
+#   define O_NONBLOCK 0200000  
+#   define       AF_UNIX         1          
+#   define       SOCK_STREAM     1          
+#define ENOENT          2       /* No such file or directory    */
+# endif /* ANSI */
+
+  int i, InitSocket, status, addreslen;
+  struct sockaddr_un Address;
+  char temp[100], *display_name;
+  char socket_name[100];
+  FILE *f;
+  
+  active = N;
+  sprintf (socket_name, "/tmp/kapa%d", N);
+  sprintf (temp, "rm -f %s", socket_name);
+  system (temp);
+    
+  strcpy (Address.sun_path, socket_name); 
+  Address.sun_family = AF_UNIX; 
+  InitSocket = socket (AF_UNIX, SOCK_STREAM, 0); 
+  status = bind (InitSocket, &Address, sizeof (Address));
+  status = listen (InitSocket, 1);
+  
+  sprintf (temp, "kapa %s &", socket_name);
+# ifndef DEBUG
+  system (temp);
+# else  
+  fprintf (stderr, "start kapa, press return: %s\n", temp);
+  fscanf (stdin, "%d", &i);
+# endif
+  
+  addreslen =  sizeof (Address);
+  Xgraph[N] = accept (InitSocket, &Address, &addreslen);
+  if (Xgraph[N] < 0) {
+    fprintf (stderr, "error starting kapa\n");
+    return (FALSE);
+  }
+  else {
+    return (TRUE);
+  }
+  
+}
+
+void DonePlotting (Graphdata *graphmode, int N) {
+  char buffer[65], buffer2[65];
+
+  if (Xgraph[N] == 0) return;
+
+  write (Xgraph[N], "DBOX", 4);
+  sprintf (buffer, "%f %f %f %f", graphmode[0].xmin, graphmode[0].xmax, graphmode[0].ymin, graphmode[0].ymax);
+  sprintf (buffer2, "NBYTES: %6d", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+
+  sprintf (buffer, "%s %s %s", "2222", "2222", "2222");
+  sprintf (buffer2, "NBYTES: %6d", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+}
+
+void JpegPlot (Graphdata *graphmode, int N, char *filename) {
+  char buffer[65], buffer2[65];
+
+  if (Xgraph[N] == 0) return;
+
+  write (Xgraph[N], "PNGF", 4);
+  sprintf (buffer, "LEN: %11d", strlen (filename));
+  write (Xgraph[N], buffer, 16);
+  write (Xgraph[N], filename, strlen (filename));
+  read (Xgraph[N], buffer, 4);
+}
+
+void PSPlot (Graphdata *graphmode, int N, char *filename) {
+  char buffer[65], buffer2[65];
+
+  if (Xgraph[N] == 0) return;
+
+  write (Xgraph[N], "PSIT", 4);
+  sprintf (buffer, "LEN: %11d", strlen (filename));
+  write (Xgraph[N], buffer, 16);
+  write (Xgraph[N], filename, strlen (filename));
+  read (Xgraph[N], buffer, 4);
+}
+
+void PrepPlotting (int Npts, Graphdata *graphmode, int N) {
+
+  int i, status;
+  char buffer[128], buffer2[128];
+
+  active = N;
+  if (Npts < 1) return;
+
+  if (Xgraph[N] < 1) if (!open_graph(N)) return;
+
+  /* test Xgraph[N], flush junk from pipe */
+  signal (SIGPIPE, XDead);
+  fcntl (Xgraph[N], F_SETFL,  O_NONBLOCK); 
+  for (i = 0; (read (Xgraph[N], buffer, 64) > 0) && (i < 20); i++);
+  fcntl (Xgraph[N], F_SETFL, !O_NONBLOCK); 
+  
+  write (Xgraph[N], "ERAS", 4);
+  
+  /* tell kapa to look for the incoming image */
+  status = write (Xgraph[N], "PLOT", 4); 
+
+  /* send Xgraph[N] the plot details */
+  sprintf (buffer, "%8d %8d %d %d %d %d %f %f", 
+	   Npts, graphmode[0].style, 
+	   graphmode[0].ptype, graphmode[0].ltype, 
+	   graphmode[0].etype, graphmode[0].color, 
+	   graphmode[0].lweight, graphmode[0].size);
+  sprintf (buffer2, "NBYTES: %6d", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+  
+  sprintf (buffer, "%f %f %f %f", 
+	   graphmode[0].xmin, graphmode[0].xmax, 
+	   graphmode[0].ymin, graphmode[0].ymax);
+  sprintf (buffer2, "NBYTES: %6d", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+
+}
+
+void PlotLabel (char *string, int N) {
+
+  char buffer[32];
+
+  if (Xgraph[N] == 0) return;
+
+  write (Xgraph[N], "LABL", 4);
+  sprintf (buffer, " %6d %6d", strlen (string), 2);
+  write (Xgraph[N], buffer, 16);
+  write (Xgraph[N], string, strlen (string));
+}
+
+void PlotVector (int Npts, double *vect, int mode, int N) {
+
+  float *values;
+  int i, Nbytes;
+
+  active = N;
+  if (Npts < 1) return;
+
+  ALLOCATE (values, float, Npts);
+  for (i = 0; i < Npts; i++) {
+    values[i] = vect[i];
+  }
+
+  Nbytes = Npts * sizeof (float);
+  write (Xgraph[N], values, Nbytes);
+  free (values);
+
+}
+
+plot_list (Graphdata *graphdata, double *xlist, double *ylist, int N, char *label, char *file) {
+
+  int i;
+  char c;
+  StatType stats;
+  
+  stats.min = stats.max = xlist[0];
+  for (i = 0; i < N; i++) {
+    stats.min = MIN (stats.min, xlist[i]);
+    stats.max = MAX (stats.max, xlist[i]);
+  }
+  if (graphdata[0].xmin == dUNDEF) graphdata[0].xmin = 1.05*stats.min - 0.05*stats.max;
+  if (graphdata[0].xmax == dUNDEF) graphdata[0].xmax = 1.05*stats.max - 0.05*stats.min;
+
+  stats.min = stats.max = ylist[0];
+  for (i = 0; i < N; i++) {
+    stats.min = MIN (stats.min, ylist[i]);
+    stats.max = MAX (stats.max, ylist[i]);
+  }
+  if (graphdata[0].ymin == dUNDEF) graphdata[0].ymin = 1.05*stats.min - 0.05*stats.max;
+  if (graphdata[0].ymax == dUNDEF) graphdata[0].ymax = 1.05*stats.max - 0.05*stats.min;
+
+  PrepPlotting (N, graphdata, 0);
+  PlotVector (N, xlist, 0, 0);
+  PlotVector (N, ylist, 1, 0);
+  if (label != NULL) PlotLabel (label, 0);
+  DonePlotting (graphdata, 0);
+
+  if ((file != NULL) && SAVEPLOT) JpegPlot (graphdata, 0, file);
+  if (PLOTDELAY > 500000) {
+    fprintf (stdout, "press return\n"); 
+    fscanf (stdin, "%*c");
+  } else {
+    usleep (PLOTDELAY);
+  }
+}
+
+plot_defaults (Graphdata *graphdata) {
+
+  graphdata[0].style = 2;
+  graphdata[0].ptype = 2;
+  graphdata[0].ltype = 0;
+  graphdata[0].etype = 0;
+  graphdata[0].color = black;
+  graphdata[0].lweight = 0;
+  graphdata[0].size = 0.5;
+
+  graphdata[0].xmin = dUNDEF;
+  graphdata[0].xmax = dUNDEF;
+  graphdata[0].ymin = dUNDEF;
+  graphdata[0].ymax = dUNDEF;
+   
+}
Index: /tags/start/Ohana/src/relphot/src/reload_catalogs.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/reload_catalogs.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/reload_catalogs.c	(revision 12606)
@@ -0,0 +1,46 @@
+# include "relphot.h"
+
+void reload_catalogs (GSCRegion *region, int Nregion, GSCRegion *fullregion) {
+
+  int i;
+  char filename[256];
+  Catalog catalog;
+
+  if (VERBOSE) fprintf (stderr, "re-loading catalog data\n");
+
+  /* load data from each region file */
+  for (i = 0; i < Nregion; i++) {
+    sprintf (filename, "%s/%s", CATDIR, region[i].filename);
+    catalog.filename = filename;  /* don't free region before catalog! */
+    switch (lock_catalog (&catalog, LCK_XCLD)) {
+    case 0:
+      fprintf (stderr, "ERROR: can't lock file %s\n", region[i].filename);
+      exit (1);
+    case 1:
+      gcatalog (&catalog, TRUE); /* load from disk */
+      break;
+    case 2:
+      if (VERBOSE) fprintf (stderr, "no data in %s, skipping\n", catalog.filename);
+      unlock_catalog (&catalog);
+      continue;
+      break;
+    default:
+      fprintf (stderr, "weird lock_catalog exit state\n");
+      exit (1);
+    }
+    initImageBins  (&catalog, 1);
+    initMosaicBins (&catalog, 1);
+    initGridBins   (&catalog, 1);
+
+    findImages (&catalog, 1);
+    findMosaics (&catalog, 1);
+
+    setMrelFinal (&catalog);
+    wcatalog (&catalog); 
+    unlock_catalog (&catalog);
+
+    freeImageBins (1);
+    freeMosaicBins (1);
+    freeGridBins (1);
+  }
+}
Index: /tags/start/Ohana/src/relphot/src/relphot.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/relphot.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/relphot.c	(revision 12606)
@@ -0,0 +1,85 @@
+# include "relphot.h"
+/** I'm not currently setting the lockfiles.  this should be fixed! **/
+
+int main (int argc, char **argv) {
+
+  char c;
+  int i, Ncatalog;
+  Catalog *catalog, tcatalog;
+  GSCRegion fullregion, *region;
+
+  /* get configuration info, args */
+  initialize (argc, argv);
+
+  /* load regions and images based on seed region */
+  region = load_images (argv[1], &Ncatalog, &fullregion);
+
+  /* load catalog data from region files */
+  catalog = load_catalogs (region, Ncatalog, &fullregion);
+
+  /* match measurements with images, mosaics */
+  initImageBins  (catalog, Ncatalog);
+  initMosaicBins (catalog, Ncatalog);
+  initGridBins   (catalog, Ncatalog);
+  initMrel (catalog, Ncatalog);
+
+  findImages (catalog, Ncatalog);
+  findMosaics (catalog, Ncatalog);  /* also sets Grid values */
+  SAVEPLOT = FALSE;
+
+  setExclusions (catalog, Ncatalog);
+
+  if (PLOTSTUFF) {
+    plot_star_coords (catalog, Ncatalog);
+    plot_mosaic_fields (catalog);
+  }
+
+  /* determine fit values */
+  for (i = 0; i < NLOOP; i++) {
+    setMrel  (catalog, Ncatalog);
+    setMcal  (catalog, FALSE);
+    setMmos  (catalog, FALSE);
+    setMgrid (catalog);
+    
+    if (PLOTSTUFF) {
+      plot_scatter (catalog, Ncatalog); 
+      plot_grid (catalog); 
+      plot_mosaics ();
+      plot_images ();
+      plot_stars (catalog, Ncatalog);
+      plot_chisq (catalog, Ncatalog);
+    }
+    if ((i == 1) || (i == 5) || (i ==  9) || (i == 13)) clean_measures (catalog, Ncatalog, FALSE); 
+    if ((i == 2) || (i == 6) || (i == 10) || (i == 14)) clean_stars (catalog, Ncatalog);
+    if ((i == 4) || (i == 8) || (i == 12) || (i == 16)) clean_mosaics (catalog, Ncatalog);
+    if ((i == 4) || (i == 8) || (i == 12) || (i == 16)) clean_images ();
+    global_stats (catalog, Ncatalog);
+  }
+
+  SAVEPLOT = TRUE;
+  plot_scatter (catalog, Ncatalog); 
+  plot_grid (catalog); 
+  plot_mosaics ();
+  plot_images ();
+  plot_stars (catalog, Ncatalog);
+  plot_chisq (catalog, Ncatalog);
+
+  if (USE_GRID) dump_grid ();
+  if (!UPDATE) exit (0);
+
+  /* set Mcal & Mmos for bad images */
+  setMcal  (catalog, TRUE);
+  setMmos  (catalog, TRUE);
+
+  /* at this point, we have correct cal coeffs in the image/mosaic structures */
+  free_catalogs (catalog, Ncatalog);
+  freeImageBins (Ncatalog);
+  freeMosaicBins (Ncatalog);
+  freeGridBins (Ncatalog);
+
+  /* load catalog data from region files, update Mrel include all data */
+  reload_catalogs (region, Ncatalog, &fullregion);
+  wimages (); 
+
+}
+
Index: /tags/start/Ohana/src/relphot/src/setExclusions.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/setExclusions.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/setExclusions.c	(revision 12606)
@@ -0,0 +1,56 @@
+# include "relphot.h"
+
+Coords *getCoords (int meas, int cat);
+
+int setExclusions (Catalog *catalog, int Ncatalog) {
+
+  int i, j, k, m, Narea, Nnocal, ecode;
+  Coords *coords;
+  double r, d, x, y;
+
+  Nnocal = Narea = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      m = catalog[i].average[j].offset;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+
+	/* select measurements by photcode */
+	ecode = GetPhotcodeEquivCodebyCode (catalog[i].measure[m].source);
+	if (ecode != photcode[0].code) goto mark_nocal;
+	
+	/* select measurements by time */
+	if (TimeSelect) {
+	  if (catalog[i].measure[m].t < TSTART) goto mark_nocal;
+	  if (catalog[i].measure[m].t > TSTOP) goto mark_nocal;
+	}
+
+	/* select measurements by mag limit */
+	if (AreaSelect) {
+	  r = catalog[i].average[j].R + catalog[i].measure[m].dR / 360000.0;
+	  d = catalog[i].average[j].D + catalog[i].measure[m].dD / 360000.0;
+	  if ((coords = getCoords (m, i)) == NULL) goto markbad;
+	  RD_to_XY (&x, &y, r, d, coords);
+	  if (x < AreaXmin) goto markbad;
+	  if (x > AreaXmax) goto markbad;
+	  if (y < AreaYmin) goto markbad;
+	  if (y > AreaYmax) goto markbad;
+	}
+	continue;
+
+      markbad:
+	catalog[i].measure[m].flags |= ID_MEAS_AREA;
+	Narea ++;
+	continue;
+	
+      mark_nocal:
+	catalog[i].measure[m].flags |= ID_MEAS_NOCAL;
+	Nnocal ++;
+	continue;
+      }
+    }
+  }
+  if (VERBOSE) fprintf (stderr, "%d measurements marked by area\n", Narea);
+  if (VERBOSE) fprintf (stderr, "%d measurements marked nocal\n", Nnocal);
+}
+
+
Index: /tags/start/Ohana/src/relphot/src/setMrelFinal.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/setMrelFinal.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/setMrelFinal.c	(revision 12606)
@@ -0,0 +1,157 @@
+# include "relphot.h"
+
+void skip_measurements (Catalog *catalog, int pass);
+Image *getimages (int *N);
+
+void setMrelFinal (Catalog *catalog) {
+
+  int i, j, m, ecode;
+  short *p;
+
+  /* if we reset the catalog, reset all the current measurements */
+  if (RESET) {
+
+    for (i = 0; i < catalog[0].Naverage; i++) {
+      p = (PhotPrimary) ? &catalog[0].average[i].M : &catalog[0].secfilt[PhotNsec*i+PhotSec].M;
+      *p = NO_MAG;
+      p = (PhotPrimary) ? &catalog[0].average[i].dM : &catalog[0].secfilt[PhotNsec*i+PhotSec].dM;
+      *p = NO_MAG;
+      p = (PhotPrimary) ? &catalog[0].average[i].Xm : &catalog[0].secfilt[PhotNsec*i+PhotSec].Xm;
+      *p = NO_MAG;
+
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	
+	/* select measurements by photcode */
+	ecode = GetPhotcodeEquivCodebyCode (catalog[0].measure[m].source);
+	if (ecode != photcode[0].code) continue;
+	
+	/* select measurements by time */
+	if (TimeSelect) {
+	  if (catalog[0].measure[m].t < TSTART) continue;
+	  if (catalog[0].measure[m].t > TSTOP) continue;
+	}
+	
+	catalog[0].measure[m].Mcal = 0;
+	catalog[0].measure[m].flags &= 0xff00;
+	catalog[0].measure[m].flags &= ~ID_MEAS_POOR;
+	catalog[0].measure[m].flags &= ~ID_MEAS_SKIP;
+	catalog[0].measure[m].flags &= ~ID_MEAS_AREA;
+	catalog[0].measure[m].flags &= ~ID_MEAS_NOCAL;
+      }
+    }
+  }
+
+  setExclusions (catalog, 1);  /* mark by area */
+
+  /* set catalog[0].found[i] = FALSE */
+  ALLOCATE (catalog[0].found, int, MAX (1, catalog[0].Naverage));
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    catalog[0].found[i] = FALSE;
+  }
+
+  for (i = 0; i < 5; i++) {
+    skip_measurements (catalog, i);       /* set ID_MEAS_SKIP for measures to be skipped */
+    setMrelOutput  (catalog, 1, FALSE);   /* set Mrel using all measures not skipped */
+    clean_measures (catalog, 1, TRUE);    /* mark outliers ID_MEAS_POOR */
+    setMrelOutput  (catalog, 1, TRUE);    /* set Mrel using remaining measures */
+  }
+  setMcalOutput (catalog, 1);
+
+  /* clear ID_STAR_POOR, ID_STAR_FEW, ID_MEAS_NOCAL values before writing ??? */
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    catalog[0].average[i].code &= ~ID_STAR_FEW;
+    catalog[0].average[i].code &= ~ID_STAR_POOR;
+    m = catalog[0].average[i].offset;
+    for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+      catalog[0].measure[m].flags &= ~ID_MEAS_NOCAL;
+    }
+  }
+}
+
+/* ID_MEAS_SKIP marks measurements which were not used to calculate Mrel */
+void skip_measurements (Catalog *catalog, int pass) {
+
+  int i, j, k, m, Nimage, ecode, d1, d2;
+  int Ntot, Ntry, Nkeep, Nskip;
+  short mag;
+  Image *image;
+
+  Ntot = Ntry = Nskip = Nkeep = 0;
+
+  /* allow measures from images marked POOR and FEW */
+  if (pass >= 3) IMAGE_BAD = ID_IMAGE_NOCAL;
+  
+  /* allow measures marked as outliers (POOR) and off image region (AREA) */
+  if (pass >= 3) MEAS_BAD = ID_MEAS_NOCAL | ID_MEAS_SKIP;
+
+  /* mark measures which should be ignored on second pass */
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    Ntot += catalog[0].average[i].Nm;
+    if (catalog[0].found[i]) continue;
+
+    m = catalog[0].average[i].offset;
+    for (k = 0; k < catalog[0].average[i].Nm; k++, m++) {
+      Ntry++;
+
+      /* clear SKIP for all measures at first */
+      catalog[0].measure[m].flags &= ~ID_MEAS_SKIP;
+
+      /** never use these measurements (wrong photcode, bad time range) */
+      /* skipped via NOCAL, don't mark as skipped */
+      ecode = GetPhotcodeEquivCodebyCode (catalog[0].measure[m].source);
+      if (ecode != photcode[0].code) continue;
+
+      /* skip measurements by time range */
+      if (TimeSelect) {
+	if (catalog[0].measure[m].t < TSTART) goto skip;
+	if (catalog[0].measure[m].t > TSTOP) goto skip;
+      }
+
+      /* skip measurements with sat. dophot values */
+      if ((pass < 4) && (catalog[0].measure[m].dophot == 10)) goto skip;
+
+      /* skip measurements from BAD images and mosaics */
+      if ((getMcal  (m, 0)) == NO_MAG) goto skip;
+      if ((getMmos  (m, 0)) == NO_MAG) goto skip;
+
+      /* skip measurements by inst mag limit */
+      if ((pass < 4) && ImagSelect) {
+	mag = iPhotInst (&catalog[0].measure[m]);
+	if (mag < ImagMin) goto skip;
+	if (mag > ImagMax) goto skip;
+      }
+
+      d1 = (catalog[0].measure[m].dophot == 1);
+      d2 = (catalog[0].measure[m].dophot == 2);
+
+      /* skip measurements by measurement error */
+      if ((pass < 2) && !(d1 || d2)) goto skip;
+
+      /* if ((pass < 1) && (catalog[0].measure[m].dM > SIGMA_LIM)) goto skip; */
+      if ((pass < 1) && !d1) goto skip;
+      Nkeep ++;
+
+      continue;
+
+    skip:
+      catalog[0].measure[m].flags |= ID_MEAS_SKIP;
+      Nskip ++;
+    }
+  }
+  fprintf (stderr, "pass %d, Ntot: %d, Ntry: %d, Nskip: %d, Nkeep: %d\n",
+	   pass, Ntot, Ntry, Nskip, Nkeep);
+}
+
+/* dophot types:
+
+   1 - star
+   2 - galaxy
+   3 - star
+   4 - weak
+   5 - edge
+   7 - weak
+   9 - weak
+   10 - sat
+*/
+
Index: /tags/start/Ohana/src/relphot/src/time.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/time.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/time.c	(revision 12606)
@@ -0,0 +1,321 @@
+# include <ohana.h>
+
+int dms_to_ddd (double *Value, char *string);
+int str_to_radec (double *ra, double *dec, char *str1, char *str2);
+int chk_time (char *line);
+double sec_to_jd (unsigned long second);
+unsigned long int jd_to_sec (double jd);
+char *sec_to_date (unsigned long second);
+unsigned long date_to_sec (char *date);
+  
+/***** convert [-]00:00:00 to 0.0000 ****/
+int dms_to_ddd (double *Value, char *string) {
+  
+  int valid, neg, status;
+  double tmp, value;
+  char *p1, *p2, *px;
+
+  valid = FALSE; 
+  neg = FALSE;
+  stripwhite (string);
+  p1 = string;
+  px = string + strlen(string);
+
+  if (string[0] == '-') { 
+    valid = TRUE; 
+    neg = TRUE;
+    p1 = &string[1];
+  }
+  if (string[0] == '+') { 
+    valid = TRUE; 
+    neg = FALSE;
+    p1 = &string[1];
+  }
+  if (isdigit(string[0])) { 
+    valid = TRUE;
+    p1 = &string[0];
+  }
+  if (!valid) { return (FALSE); }
+
+  status = 1;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) return (FALSE); /* entry not a number: +fred */
+  value = tmp;
+  if (p2 == px) goto escape;    /* entry only number: +1.0 */ 
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:fred */
+  status = 2;
+  value += tmp / 60.0;
+  if (p2 == px) goto escape;    /* entry only number: +1:1 */
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:1:fred */
+  value += tmp / 3600.0;
+
+ escape:
+  if (neg) {
+    value *= -1;
+  }
+  *Value = value;
+
+  return (status);
+}
+
+/**********/
+int str_to_radec (double *ra, double *dec, char *str1, char *str2) {
+
+  double Ra, Dec;
+
+  *ra = *dec = 0;
+  switch (dms_to_ddd (&Ra, str1)) {
+  case 0:
+    fprintf (stderr, "syntax error in RA\n");
+    return (FALSE);
+  case 1:
+    break;
+  case 2:
+    Ra = Ra * 15;
+    break;
+  }
+  switch (dms_to_ddd (&Dec, str2)) {
+  case 0:
+    fprintf (stderr, "syntax error in DEC\n");
+    return (FALSE);
+  case 1:
+  case 2:
+    break;
+  }
+  *ra = Ra;
+  *dec = Dec;
+  return (TRUE);
+}
+
+# define FORMAT_DAYS    1
+# define FORMAT_HOURS   2
+# define FORMAT_MINUTES 3
+# define FORMAT_SECONDS 4
+# define FORMAT_JD      5
+# define FORMAT_DATE    6
+
+/**********/
+int chk_time (char *line) {
+
+  char *p1, *p2;
+  double tmp;
+  int mode;
+
+  p1 = line;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1 + strlen (p1) - 1) {
+    if (*p2 == 'd') {
+      mode = FORMAT_DAYS;
+    }
+    if (*p2 == 'h') {
+      mode = FORMAT_HOURS;
+    }
+    if (*p2 == 'm') {
+      mode = FORMAT_MINUTES;
+    }
+    if (*p2 == 's') {
+      mode = FORMAT_SECONDS;
+    }
+    if (*p2 == 'j') {
+      mode = FORMAT_JD;
+    }
+  } else { 
+    mode = FORMAT_DATE;
+  }
+  return (mode);
+}
+
+/**********/
+int str_to_time (char *line, unsigned int *second) {
+  
+  struct timeval now;
+  double jd;
+
+  if (!strcasecmp (line, "NOW")) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    *second = now.tv_sec;
+    return (TRUE);
+  }
+    
+  if (!strcasecmp (line, "TODAY")) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    *second = 86400 * ((int)(now.tv_sec / 86400));
+    return (TRUE);
+  }
+    
+  switch (chk_time (line)) {
+  case 0:
+    return (FALSE);
+  case FORMAT_DAYS:
+    *second = strtod (line, 0) * 86400.0;
+    return (TRUE);
+  case FORMAT_HOURS:
+    *second = strtod (line, 0) * 3600.0;
+    return (TRUE);
+  case FORMAT_MINUTES:
+    *second = strtod (line, 0) * 60.0;
+    return (TRUE);
+  case FORMAT_SECONDS:
+    *second = strtod (line, 0);
+    return (TRUE);
+  case FORMAT_JD:
+    jd = strtod (line, 0);
+    *second = jd_to_sec (jd);
+    return (TRUE);
+  case FORMAT_DATE:
+    *second = date_to_sec (line);
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+/**********/
+int str_to_dtime (char *line, double *second) {
+  
+  switch (chk_time (line)) {
+  case 0:
+  case FORMAT_JD:
+  case FORMAT_DATE:
+    return (FALSE);
+  case FORMAT_DAYS:
+    *second = strtod (line, 0) * 86400.0;
+    return (TRUE);
+  case FORMAT_HOURS:
+    *second = strtod (line, 0) * 3600.0;
+    return (TRUE);
+  case FORMAT_MINUTES:
+    *second = strtod (line, 0) * 60.0;
+    return (TRUE);
+  case FORMAT_SECONDS:
+    *second = strtod (line, 0);
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+/**********/
+double sec_to_jd (unsigned long second) {
+
+  double jd;
+  
+  jd = second/86400.0 + 2440587.5;
+  return (jd);
+}
+
+/**********/
+unsigned long int jd_to_sec (double jd) {
+
+  unsigned long int second;
+
+  second = (jd - 2440587.5)*86400;
+  return (second);
+}
+
+/**********/
+char *sec_to_date (unsigned long second) {
+  
+  struct tm *gmt;
+  char *line;
+  
+  ALLOCATE (line, char, 64);
+  gmt   = gmtime (&second);
+  sprintf (line, "%4d/%02d/%02d,%02d:%02d:%02d", 1900+gmt[0].tm_year, gmt[0].tm_mon+1, gmt[0].tm_mday, gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+  return (line);
+
+}
+
+/***** date in format yyyy/mm/dd,hh:mm:ss *****/
+unsigned long date_to_sec (char *date) {
+  
+  unsigned long second;
+  double tmp, jd;
+  struct tm now;
+  char *p1, *p2, *px;
+  
+  p1 = date;
+  px = date + strlen(date);
+  bzero (&now, sizeof(now));
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_year = tmp;
+  if (now.tm_year > 1000) now.tm_year -= 1900;
+  if (now.tm_year <   50) now.tm_year += 100;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mon = tmp - 1; /* mon runs from 0 - 11 */
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mday = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  p1 = p2 + 1;
+  now.tm_hour = tmp;
+  if (p2 == px) goto escape;  
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_min = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_sec = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+ escape:
+  jd = now.tm_mday - 32075 + (int)(1461*(1900 + now.tm_year + 4800 + (int)(((now.tm_mon+1)-14)/12))/4)
+    + (int)(367*((now.tm_mon+1) - 2 - (int)(((now.tm_mon+1) - 14)/12)*12)/12)
+    - (int)(3*(int)((1900 + now.tm_year + 4900 + (int)(((now.tm_mon+1) - 14)/12))/100)/4) - 0.5;
+  
+  second = (jd - 2440587.5)*86400 + 3600.0*now.tm_hour + now.tm_min*60.0 + now.tm_sec;
+
+  return (second);
+}
+
+
+/* times may be in forms as:
+   20040200450s (N seconds since 1970.0)
+   2440900.232j (julian date)
+   99/02/23,03:22:18 (date string)
+   (separators may be anything except space, +, -)
+   99:02:15:12:23:30
+   99:02:15:12h23m30s
+   */
+
+
+/* fseek with timeout - 0.5 sec */
+int Fseek (FILE *f, long offset, int whence) {
+
+  int status, k;
+
+  status = fseek (f, offset, whence);
+  if (status == -1) {
+    int k;
+    /* fprintf (stderr, "problem seeking position: %d\n", errno); */
+    for (k = 0; (k < 10) && ((status = fseek (f, 0, SEEK_SET)) == -1); k++) usleep (50000);
+    if (status == -1) {
+      /* fprintf (stderr, "ERROR: serious problem seeking position: %d\n", errno); */
+      /* clear lock at this point? */
+      return (0);
+    }
+  }
+  return (1);
+}
Index: /tags/start/Ohana/src/relphot/src/wcatalog.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/wcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/wcatalog.c	(revision 12606)
@@ -0,0 +1,25 @@
+# include "relphot.h"
+
+void wcatalog (Catalog *catalog) {
+  
+  fits_modify (&catalog[0].header, "NRPHOT", "%t", 1, TRUE);
+
+  save_catalog (catalog, VERBOSE);
+
+  if (catalog[0].Naverage) {
+    free (catalog[0].average); 
+    catalog[0].Naverage = 0;
+  }
+  if (catalog[0].Nmeasure) {
+    free (catalog[0].measure); 
+    catalog[0].Nmeasure = 0;
+  }
+  if (catalog[0].Nmissing) {
+    free (catalog[0].missing); 
+    catalog[0].Nmissing = 0;
+  }
+  if (catalog[0].Nsecfilt) {
+    free (catalog[0].secfilt); 
+    catalog[0].Nsecfilt = 0;
+  }
+}
Index: /tags/start/Ohana/src/relphot/src/write_coords.c
===================================================================
--- /tags/start/Ohana/src/relphot/src/write_coords.c	(revision 12606)
+++ /tags/start/Ohana/src/relphot/src/write_coords.c	(revision 12606)
@@ -0,0 +1,29 @@
+# include "relphot.h"
+
+# define CD_COORDS 1
+
+void write_coords (Header *header, Coords *coords) {
+
+  fits_modify (header, "CTYPE1",   "%s",  1, "RA---TAN");
+  fits_modify (header, "CTYPE2",   "%s",  1, "DEC--TAN");
+
+  fits_modify (header, "CRVAL1",   "%lf", 1, coords[0].crval1);
+  fits_modify (header, "CRVAL2",   "%lf", 1, coords[0].crval2);  
+
+  fits_modify (header, "CRPIX1",   "%lf", 1, coords[0].crpix1);
+  fits_modify (header, "CRPIX2",   "%lf", 1, coords[0].crpix2);
+
+# if (CD_COORDS)  
+  fits_modify (header, "CD1_1",    "%le", 1, coords[0].pc1_1 * coords[0].cdelt1);
+  fits_modify (header, "CD2_1",    "%le", 1, coords[0].pc2_1 * coords[0].cdelt1);
+  fits_modify (header, "CD1_2",    "%le", 1, coords[0].pc1_2 * coords[0].cdelt2);
+  fits_modify (header, "CD2_2",    "%le", 1, coords[0].pc2_2 * coords[0].cdelt2);
+# else
+  fits_modify (header, "CDELT1",   "%le", 1, coords[0].cdelt1); 
+  fits_modify (header, "CDELT2",   "%le", 1, coords[0].cdelt2);
+  fits_modify (header, "PC001001", "%le", 1, coords[0].pc1_1);
+  fits_modify (header, "PC001002", "%le", 1, coords[0].pc1_2);
+  fits_modify (header, "PC002001", "%le", 1, coords[0].pc2_1);
+  fits_modify (header, "PC002002", "%le", 1, coords[0].pc2_2);
+# endif
+}
Index: /tags/start/Ohana/src/shell/Makefile
===================================================================
--- /tags/start/Ohana/src/shell/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/shell/Makefile	(revision 12606)
@@ -0,0 +1,43 @@
+include ../../Configure
+HOME 	=	$(ROOT)/src/shell
+
+DESTBIN	=	$(LBIN)
+
+shell:
+
+default: install
+
+DADS = \
+dads.cleanup
+
+GENERAL = \
+block checkdisks dumptape \
+fits2jpeg gopsfphot gosexphot \
+setpath scattercorrection \
+vncstart vnccheck
+
+IMSTATS = \
+irsex sexstats
+
+MKDETREND = \
+detstats rm.elixir
+
+REALTIME = \
+el_plots elixir.fork elixir.launch \
+getfocus getseeing gettemps mkjpeg
+
+SKYPROBE = \
+sp_command sp_phot \
+sp_plots sp_sexphot
+
+CODE = $(DADS) $(GENERAL) $(IMSTATS) $(MKDETREND) $(POSTRUN) $(PTOLEMY) $(REALTIME) $(SKYPROBE)
+
+install:
+	for file in $(CODE); do \
+	(chmod +x src/$$file && cd $(DESTBIN) && rm -f $$file && ln -s $(HOME)/src/$$file .); \
+	done
+
+# utilities #################################################
+clean:	
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
Index: /tags/start/Ohana/src/shell/doc/flips.notes
===================================================================
--- /tags/start/Ohana/src/shell/doc/flips.notes	(revision 12606)
+++ /tags/start/Ohana/src/shell/doc/flips.notes	(revision 12606)
@@ -0,0 +1,51 @@
+
+Some of the Elixir scripts call Flips programs.  Here is a list of the
+programs in Flips being used by Elixir:
+
+fr.defringe   : flipsrun (imcombred)
+fr.gtfringe   : flipsrun (imstat)
+defringe      : flipsrun (imcombred)
+doflips       : flatccd
+doflips       : darkccd
+flatten.flips : redccd 
+fr.mkrough    : flipsrun (imcombred)
+fr.smooth     : flipsrun (imfilter)
+gtfringe      : flipsrun (imstat)
+
+noni: file *
+RCS:            directory
+block:          C shell script text
+checkdisks:     C shell script text
+dads.cleanup:   C shell script text
+dads.remef:     C shell script text  - to be deprecated?
+dads.split:     C shell script text  - to be deprecated
+defringe:       C shell script text  - perl
+detstats:       C shell script text  - (mkdetrend)
+doflips:        C shell script text  - perl/detflips
+dumptape:       C shell script text
+el_plots:       C shell script text
+elixir.fork:    C shell script text
+elixir.launch:  C shell script text
+fits2jpeg:      C shell script text
+flatten.flips:  C shell script text  - perl
+flatten.subaru: C shell script text  - old
+fr.defringe:    C shell script text  - perl
+fr.mkrough:     C shell script text  - perl/detflips
+fr.smooth:      C shell script text  - perl TBD
+getfocus:       C shell script text
+getfringe:      bash shell script    - perl
+getseeing:      C shell script text
+gettemps:       C shell script text
+gopsfphot:      C shell script text
+gosexphot:      C shell script text
+irsex:          C shell script text
+mk.ptlist:      C shell script text
+mkjpeg:         C shell script text
+pt.export:      C shell script text
+rm.elixir:      C shell script text
+setpath:        C shell script text
+sexstats:       C shell script text
+sp_command:     C shell script text
+sp_phot:        C shell script text
+sp_plots:       C shell script text
+sp_sexphot:     C shell script text
Index: /tags/start/Ohana/src/shell/doc/notes.txt
===================================================================
--- /tags/start/Ohana/src/shell/doc/notes.txt	(revision 12606)
+++ /tags/start/Ohana/src/shell/doc/notes.txt	(revision 12606)
@@ -0,0 +1,113 @@
+block			general
+checkdisks		CFHT specific
+dads.cleanup		
+dads.remef		
+dads.split		
+defringe		N CCDs, CFH12K Coord file
+detrend			Not Used?
+detstats		OK (check mana scripts)
+doflips			OK
+dumptape		
+elixir.fork		
+elixir.grab		
+elixir.report		
+fits2jpeg		
+fixdetrend		
+flatten.flips		OK
+flatten.mana		OK	
+focusstats		
+fr.ckfile		Not Used
+fr.defringe		N CCDs (check mana scripts)
+fr.mkimage		OK
+fr.mkrough		OK
+fr.mkstats		(check scripts)
+fr.smooth		Scale is CCD dependent
+fr.stats		OK
+getfocus		
+getseeing		
+gettemps		
+gopsfphot		
+gosexphot		
+gtfringe		(sh) OK
+imstats			CCD size specific -- should use DETSEC
+merge.lists		OK
+mk2d			Not Used
+mkjpeg			(realtime) N CCD specific
+normalize		OK
+normalize.invert	-
+phot.by.night		
+pt.export		(ptolemy export process)
+rm.elixir		(drop & convert to the exit status method)
+setpath			unused?
+sexstats		OK
+skyprobephot		
+split.mef		OK
+spphot			
+
+-
+
+cfht.names		a
+checkconfig		CFHT specific
+ckastrom		
+ckdetrend		
+ckphotom		
+ckrunid			
+ckvalid			
+clear.rawdir		
+create.imlists		nut used
+create.subset		OK
+dads.detrend		
+dads.jpeg		
+dads.keywords		
+darktime.cfht		CFH12K specific -- these curves must be measured for a new device!
+fixlists		
+fl.split2mef		not used?
+fr.detrend		Nccds from gt_names -- more general encapsulation
+fr.gtstats		Nccds
+fr.medbin		Nccds
+fr.medbin.spline	Nccds
+fr.mklists		OK
+fr.select		
+fr.subset		
+get.standards		
+grab.keywords		
+images.names		
+imclean.cfht		
+imselect		
+imstatqso		
+merge.lists		
+mkdetrend		
+mkfringe		
+mkptolemy.names		
+mktrans			
+mktreport		
+mosaic.merge		
+mosaic.stats		
+pt.run			
+seeingstats		
+validate		
+
+shell scripts that use awk -v (convert to perl):
+defringe
+fr.defringe
+fr.smooth
+gtfringe   (convert from sh anyway)
+
+shell scripts which use CFH12K dependent things:
+
+defringe		N CCDs, CFH12K Coord file
+detstats		(check mana scripts)
+fr.ckfile		Nccds
+fr.defringe		N CCDs (check mana scripts)
+fr.mkimage		(check scripts)
+fr.mkstats		(check scripts)
+fr.smooth		Scale is CCD dependent
+fr.stats		(check scripts)
+imstats			CCD size specific -- should use DETSEC
+normalize		OK
+split.mef		CCD size specific
+
+(watch out for header keywords -- make a complete dictionary)
+
+shell -> perl
+split.mef
Index: /tags/start/Ohana/src/shell/doc/programs.txt
===================================================================
--- /tags/start/Ohana/src/shell/doc/programs.txt	(revision 12606)
+++ /tags/start/Ohana/src/shell/doc/programs.txt	(revision 12606)
@@ -0,0 +1,61 @@
+block			: x
+checkdisks		: x
+ckastro			: x
+dads.cleanup		: x
+dads.remef		: x
+dads.split		: +
+doflips			: x
+dumptape		: x
+elixir.fork		: x
+fits2jpeg		: x
+flatten.flips		: +
+flatten.subaru		: x (fake)
+gettemps		: x
+gopsfphot		: x
+gosexphot		: +
+imstats			: +
+merge.lists		: x
+mk2d			: x
+normalize		: x
+normalize.invert	: x
+phot.by.night		: x
+pt.export		: x
+rm.elixir		: x
+setpath			: x
+sexstats		: x
+detstats		: x
+
+getfocus		: [which chips should be camera-dependent]
+getseeing		: [which chip should be camera-dependent]
+mkjpeg			: [scale and ccd list should be camera-dependend]
+
+mk.ptlist		: - [ccds in list need to be ID, not N - add option to imsearch?]
+el_plots		: - (in script mana/elixir)
+
+skyprobe should have its own minimal config file
+
+skyprobephot		: [cleanup up config reference]
+sp_expose		: x
+split.mef		: x
+spphot			: [abstract RAWDIR, etc?]
+sp_plots		: [abstract plot directory?]
+
+mkfringe stuff:
+
+fr.fitstats		: +
+fr.imstats		: +
+fr.mkimage		: 
+fr.mkrough		: 
+fr.mkstats		: 
+fr.smooth		: 
+fr.stats		: 
+getfringe		: 
+defringe		: - (not very clean; might work)
+fr.defringe		: - (some major issues..)
+
+
+already checked:
+
+mode.imstats
+mode.sextract
+mode.flips
Index: /tags/start/Ohana/src/skycalc/Makefile
===================================================================
--- /tags/start/Ohana/src/skycalc/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/skycalc/Makefile	(revision 12606)
@@ -0,0 +1,71 @@
+include ../../Configure
+HOME	=	.
+
+SRC	=	$(HOME)/src
+LIB	=	$(HOME)/lib
+INC	=	$(HOME)/include
+MAN	= 	$(HOME)/doc
+BIN	= 	$(HOME)/bin
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+INCS	=	-I$(INC) -I$(LINC)  -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB)
+CFLAGS	=	-g -o $*.$(ARCH).o $(INCS)
+CCFLAGS	=	$(INCS) $(LIBS)
+
+default: skycalc
+
+skycalc: $(DESTLIB)/libskycalc.a
+
+install: $(DESTINC)/skycalc.h $(DESTLIB)/libskycalc.a
+
+OBJ = 	$(SRC)/time.$(ARCH).o		$(SRC)/geometry.$(ARCH).o \
+	$(SRC)/astro.$(ARCH).o		$(SRC)/sun.$(ARCH).o \
+	$(SRC)/moon.$(ARCH).o		$(SRC)/misc.$(ARCH).o		
+
+$(OBJ): $(INC)/skycalc.h $(INC)/skycalc_internal.h
+
+$(LIB)/libskycalc.$(ARCH).a: $(OBJ)
+	rm -f $(LIB)/libskycalc.$(ARCH).a
+	ar rcv $(LIB)/libskycalc.$(ARCH).a $(OBJ)
+	ranlib $(LIB)/libskycalc.$(ARCH).a
+
+$(DESTLIB)/libskycalc.a: $(LIB)/libskycalc.$(ARCH).a 
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	rm -f  $(DESTLIB)/libskycalc.a
+	cp $(LIB)/libskycalc.$(ARCH).a $(DESTLIB)/libskycalc.a
+
+$(DESTINC)/skycalc.h: $(INC)/skycalc.h
+	@if [ ! -d $(DESTINC) ]; then mkdir -p $(DESTINC); fi
+	rm -f $(DESTINC)/skycalc.h
+	cp $(INC)/skycalc.h $(DESTINC)/
+
+test:
+	$(CC) $(CCFLAGS) -g -o skylib $(SRC)/skylib.c -lskycalc -lm
+
+dusktime: skycalc
+	$(CC) $(CCFLAGS) -g -o $(BIN)/dusktime.$(ARCH) $(SRC)/dusktime.c -lskycalc -lm -lohana
+	cp $(BIN)/dusktime.$(ARCH) $(DESTBIN)/dusktime
+
+moondata: skycalc
+	$(CC) $(CCFLAGS) -g -o $(BIN)/moondata.$(ARCH) $(SRC)/moondata.c -lskycalc -lm -lohana
+	cp $(BIN)/moondata.$(ARCH) $(DESTBIN)/moondata
+
+sundata: skycalc
+	$(CC) $(CCFLAGS) -g -o $(BIN)/sundata.$(ARCH) $(SRC)/sundata.c -lskycalc -lm -lohana
+	cp $(BIN)/sundata.$(ARCH) $(DESTBIN)/sundata
+
+clean:	
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*.a"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
+
Index: /tags/start/Ohana/src/skycalc/doc/skycalc.txt
===================================================================
--- /tags/start/Ohana/src/skycalc/doc/skycalc.txt	(revision 12606)
+++ /tags/start/Ohana/src/skycalc/doc/skycalc.txt	(revision 12606)
@@ -0,0 +1,92 @@
+
+functions in time.c:
+
+int    get_sys_date (struct SC_date_time *date)
+       set SC date & time from system clock
+
+double date_to_jd (struct SC_date_time date)
+       convert JD to SC date & time
+
+void   jd_to_date (double jdin, struct SC_date_time *date)
+       convert SC date & time to JD
+
+double lst (double jd, double longit)
+       convert JD & longitude to LST
+
+double adj_time (double x)
+       force time domain to be -12h and 12h 
+
+
+functions in geometry.c:
+
+void   xyz_cel (double x, double y, double z, double *r, double *d)
+       converts a coordinate triplet back to a standard ra and dec
+
+double atan_circ (double x, double y)
+       returns radian angle 0 to 2pi for coords x, y -- get that quadrant right !! */
+
+double altit (double dec, double ha, double lat, double *az)
+       returns altitude (degrees) for dec, ha, lat (degree)
+       also computes and returns azimuth through pointer argument.
+
+double ha_alt (double dec, double lat, double alt)
+       returns hour angle at which object at dec is at altitude alt.
+       If object is never at this altitude, signals with special
+       return values 1000 (always higher) and -1000 (always lower).
+
+void   min_max_alt (double lat, double dec, double *min, double *max)
+       computes minimum and maximum altitude for a given dec and latitude.
+
+double circulo (double x)
+       force domain to be 0 - 360 degrees
+
+
+functions in astro.c:
+
+void   precrot (double rorig, double dorig, double orig_epoch, double final_epoch, double *rf, double *df) {
+       accurate precession method from rorig, dorig, orig_epoch 
+
+void   geocent (double geolong, double geolat, double height, double x_geo, double y_geo, double z_geo)
+       return geocentric coordinate from geodetic data
+
+void   eclrot(double jd, double x, double y, double z)
+       rotates ecliptic rectangular coords x, y, z to equatorial
+
+double etcorr (double jd)
+       return correction to jd for shifts in ET or TDT
+
+void   set_zenith (struct SC_date_time date, double lat, double longit, double epoch, double *ra, double *dec)
+       return zenith coords for given date, time, epoch, position 
+
+
+functions is sun.c:
+
+void   lpsun (double jd, double ra, double dec)
+       return ra & dec for sun on given JD (low precision)
+
+double jd_sun_alt (double alt, double jdguess, double lat, double longit)
+       return JD for sun at given altitude, start with jdguess
+
+double sunset_tonight (struct SC_date_time date, double lat, double longit, double elev)
+       return JD for sunset before closest midnight to date & time
+
+double sunrise_tonight (struct SC_date_time date, double lat, double longit, double elev)
+       return JD for sunrise after closest midnight to date & time
+
+
+functions in moon.c:
+
+void   accumoon (double jd, double geolat, double lst, double elevsea, 
+       double *geora, double *geodec, double *geodist, 
+       double *topora, double *topodec, double *topodist)
+       calculate position of moon given jd, lat, etc.
+
+double jd_moon_alt (double alt, double jdguess, double lat, double longit, double elevsea)
+       return JD for moon at given altitude, start with jdguess
+
+double moonset_tonight (struct SC_date_time date, double lat, double longit, double elevsea, double elev) {
+       Given site position, return Moonset for closest midnight
+
+double moonrise_tonight (struct SC_date_time date, double lat, double longit, double elevsea, double elev) {
+       Given site position, return Moonrise for closest midnight
+
Index: /tags/start/Ohana/src/skycalc/include/skycalc.h
===================================================================
--- /tags/start/Ohana/src/skycalc/include/skycalc.h	(revision 12606)
+++ /tags/start/Ohana/src/skycalc/include/skycalc.h	(revision 12606)
@@ -0,0 +1,23 @@
+
+/* header for skycalc library function calls */
+
+struct SC_coord {
+     short sign;  /* carry sign explicitly since -0 not neg. */
+     double hh;
+     double mm;
+     double ss;
+}; 
+
+struct SC_date_time {
+  short y;
+  short mo;
+  short d;
+  short h;
+  short mn;
+  float s;
+};
+
+double sunset_tonight (struct SC_date_time date, double lat, double longit, double elev);
+double sunrise_tonight (struct SC_date_time date, double lat, double longit, double elev);
+double moonset_tonight (struct SC_date_time date, double lat, double longit, double elevsea, double elev);
+double moonrise_tonight (struct SC_date_time date, double lat, double longit, double elevsea, double elev);
Index: /tags/start/Ohana/src/skycalc/include/skycalc_internal.h
===================================================================
--- /tags/start/Ohana/src/skycalc/include/skycalc_internal.h	(revision 12606)
+++ /tags/start/Ohana/src/skycalc/include/skycalc_internal.h	(revision 12606)
@@ -0,0 +1,91 @@
+
+/* header for use by the skycalc library files, not needed for external calls */
+
+# include <skycalc.h>
+# include <stdio.h>
+# include <math.h>
+# include <ctype.h>
+# include <stdarg.h>
+# include <string.h>
+# include <time.h>
+
+/* a couple of the system-dependent magic numbers are defined here */
+
+#define SYS_CLOCK_OK 1    /* 1 means ANSI-standard time libraries do work,
+   2 means they don't.  This is used by compiler switches in file 5 and
+   the main program.  */
+
+#define LOG_FILES_OK 1  /* 1 means that log files are enabled.
+			Any other value means they're not.  */
+
+#define MAX_OBJECTS 500
+#define MINSHORT -32767   /* min, max short integers and double precision */
+#define MAXSHORT 32767
+#define MAXDOUBLE 1.0e38
+#define MINDOUBLE -1.0e38
+#define BUFSIZE 150
+
+/* some (not all) physical, mathematical, and astronomical constants
+   used are defined here. */
+
+#define  PI                3.14159265358979
+#define  ARCSEC_IN_RADIAN  206264.8062471
+#define  DEG_IN_RADIAN     57.2957795130823
+#define  HRS_IN_RADIAN     3.819718634205
+#define  KMS_AUDAY         1731.45683633   /* km per sec in 1 AU/day */
+#define  SS_MASS           1.00134198      /* solar system mass in solar units */
+#define  J2000             2451545.        /* Julian date at standard epoch */
+#define  SEC_IN_DAY        86400.
+#define  FLATTEN           0.003352813   /* flattening of earth, 1/298.257 */
+#define  EQUAT_RAD         6378137.    /* equatorial radius of earth, meters */
+#define  ASTRO_UNIT        1.4959787066e11 /* 1 AU in meters */
+#define  RSUN              6.96000e8  /* IAU 1976 recom. solar radius, meters */
+#define  RMOON             1.738e6    /* IAU 1976 recom. lunar radius, meters */
+#define  PLANET_TOL        3.          /* flag if nearer than 3 degrees
+						to a major planet ... */
+#define  KZEN              0.172       /* zenith extinction, mag, for use
+				     in lunar sky brightness calculations. */
+#define FIRSTJD            2415387.  /* 1901 Jan 1 -- calendrical limit */
+#define LASTJD             2488070.  /* 2099 Dec 31 */
+
+/* MAGIC NUMBERS which might depend on how accurately double-
+   precision floating point is handled on your machine ... */
+
+#define  EARTH_DIFF        0.05            /* used in numerical
+   differentiation to find earth velocity -- this value gives
+   about 8 digits of numerical accuracy on the VAX, but is
+   about 3 orders of magnitude larger than the value where roundoff
+   errors become apparent. */
+
+#define  MIDN_TOL          0.00001         /* this is no longer
+   used -- it was formerly
+   how close (in days) a julian date has to be to midnight
+   before a warning flag is printed for the reader.  VAX
+   double precision renders a Julian date considerably
+   more accurately than this.  The day and date are now based
+   on the same rounding of the julian date, so they should
+   always agree. */
+
+/** prototypes **/
+int    get_sys_date (struct SC_date_time *date);
+double date_to_jd (struct SC_date_time date);
+void   jd_to_date (double jdin, struct SC_date_time *date);
+double lst (double jd, double longit);
+double adj_time (double x);
+void   xyz_cel (double x, double y, double z, double *r, double *d);
+double atan_circ (double x, double y);
+double altit (double dec, double ha, double lat, double *az);
+double ha_alt (double dec, double lat, double alt);
+void   min_max_alt (double lat, double dec, double *min, double *max);
+double circulo (double x);
+void   precrot (double rorig, double dorig, double orig_epoch, double final_epoch, double *rf, double *df);
+void   geocent (double geolong, double geolat, double height, double *x_geo, double *y_geo, double *z_geo);
+void   eclrot(double jd, double *x, double *y, double *z);
+double etcorr (double jd);
+void   set_zenith (struct SC_date_time date, double lat, double longit, double epoch, double *ra, double *dec);
+void   lpsun (double jd, double *ra, double *dec);
+double jd_sun_alt (double alt, double jdguess, double lat, double longit);
+void   accumoon (double jd, double geolat, double lst, double elevsea, 
+       double *geora, double *geodec, double *geodist, 
+       double *topora, double *topodec, double *topodist);
+double jd_moon_alt (double alt, double jdguess, double lat, double longit, double elevsea);
Index: /tags/start/Ohana/src/skycalc/src/astro.c
===================================================================
--- /tags/start/Ohana/src/skycalc/src/astro.c	(revision 12606)
+++ /tags/start/Ohana/src/skycalc/src/astro.c	(revision 12606)
@@ -0,0 +1,192 @@
+# include <skycalc_internal.h>
+
+/* Takes a coordinate pair and precesses it using matrix procedures
+   as outlined in Taff's Computational Spherical Astronomy book.
+   This is the so-called 'rigorous' method which should give very
+   accurate answers all over the sky over an interval of several
+   centuries.  Naked eye accuracy holds to ancient times, too.
+   Precession constants used are the new IAU1976 -- the 'J2000'
+   system. Angles in degrees, epochs in years */
+
+void precrot (double rorig, double dorig, double orig_epoch, double final_epoch, double *rf, double *df) {
+  
+  double ti, tf, zeta, z, theta;  /* all as per  Taff */
+  double cosz, coszeta, costheta, sinz, sinzeta, sintheta;  /* ftns */
+  double p11, p12, p13, p21, p22, p23, p31, p32, p33;
+  /* elements of the rotation matrix */
+  double radian_ra, radian_dec;
+  double orig_x, orig_y, orig_z;
+  double fin_x, fin_y, fin_z;   /* original and final unit ectors */
+
+  ti = (orig_epoch - 2000.) / 100.;
+  tf = (final_epoch - 2000. - 100. * ti) / 100.;
+
+  zeta = (2306.2181 + 1.39656 * ti + 0.000139 * ti * ti) * tf +
+    (0.30188 - 0.000344 * ti) * tf * tf + 0.017998 * tf * tf * tf;
+  z = zeta + (0.79280 + 0.000410 * ti) * tf * tf + 0.000205 * tf * tf * tf;
+  theta = (2004.3109 - 0.8533 * ti - 0.000217 * ti * ti) * tf
+    - (0.42665 + 0.000217 * ti) * tf * tf - 0.041833 * tf * tf * tf;
+
+  /* convert to radians */
+
+  zeta = zeta / ARCSEC_IN_RADIAN;
+  z = z / ARCSEC_IN_RADIAN;
+  theta = theta / ARCSEC_IN_RADIAN;
+
+  /* compute the necessary trig functions for speed and simplicity */
+
+  cosz = cos(z);
+  coszeta = cos(zeta);
+  costheta = cos(theta);
+  sinz = sin(z);
+  sinzeta = sin(zeta);
+  sintheta = sin(theta);
+
+  /* compute the elements of the precession matrix */
+
+  p11 = coszeta * cosz * costheta - sinzeta * sinz;
+  p12 = -1. * sinzeta * cosz * costheta - coszeta * sinz;
+  p13 = -1. * cosz * sintheta;
+
+  p21 = coszeta * sinz * costheta + sinzeta * cosz;
+  p22 = -1. * sinzeta * sinz * costheta + coszeta * cosz;
+  p23 = -1. * sinz * sintheta;
+
+  p31 = coszeta * sintheta;
+  p32 = -1. * sinzeta * sintheta;
+  p33 = costheta;
+
+  /* transform original coordinates */
+
+  radian_ra = rorig / HRS_IN_RADIAN;
+  radian_dec = dorig / DEG_IN_RADIAN;
+
+  orig_x = cos(radian_dec) * cos(radian_ra);
+  orig_y = cos(radian_dec) *sin(radian_ra);
+  orig_z = sin(radian_dec);
+  /* (hard coded matrix multiplication ...) */
+  fin_x = p11 * orig_x + p12 * orig_y + p13 * orig_z;
+  fin_y = p21 * orig_x + p22 * orig_y + p23 * orig_z;
+  fin_z = p31 * orig_x + p32 * orig_y + p33 * orig_z;
+
+  /* convert back to spherical polar coords */
+
+  xyz_cel(fin_x, fin_y, fin_z, rf, df);
+
+}
+
+
+/* computes the geocentric coordinates from the geodetic
+   (standard map-type) longitude, latitude, and height.
+   These are assumed to be in decimal hours, decimal degrees, and
+   meters respectively.  Notation generally follows 1992 Astr Almanac,
+   p. K11 */
+
+void geocent (double geolong, double geolat, double height, double *x_geo, double *y_geo, double *z_geo) {
+
+  double denom, C_geo, S_geo;
+
+  geolat = geolat / DEG_IN_RADIAN;
+  geolong = geolong / HRS_IN_RADIAN;
+  denom = (1. - FLATTEN) * sin(geolat);
+  denom = cos(geolat) * cos(geolat) + denom*denom;
+  C_geo = 1. / sqrt(denom);
+  S_geo = (1. - FLATTEN) * (1. - FLATTEN) * C_geo;
+  C_geo = C_geo + height / EQUAT_RAD;  /* deviation from almanac
+					  notation -- include height here. */
+  S_geo = S_geo + height / EQUAT_RAD;
+  *x_geo = C_geo * cos(geolat) * cos(geolong);
+  *y_geo = C_geo * cos(geolat) * sin(geolong);
+  *z_geo = S_geo * sin(geolat);
+}
+
+/* rotates ecliptic rectangular coords x, y, z to
+   equatorial (all assumed of date.) */
+void eclrot(double jd, double *x, double *y, double *z) {
+
+  double incl;
+  double xpr,ypr,zpr;
+  double T;
+
+  T = (jd - J2000) / 36525;  /* centuries since J2000 */
+
+  incl = (23.439291 + T * (-0.0130042 - 0.00000016 * T))/DEG_IN_RADIAN;
+  /* 1992 Astron Almanac, p. B18, dropping the
+     cubic term, which is 2 milli-arcsec! */
+  ypr = cos(incl) * *y - sin(incl) * *z;
+  zpr = sin(incl) * *y + cos(incl) * *z;
+  *y = ypr;
+  *z = zpr;
+  /* x remains the same. */
+}
+
+/* Given a julian date in 1900-2100, returns the correction
+     delta t which is:
+     TDT - UT (after 1983 and before 1993)
+     ET - UT (before 1983)
+     an extrapolated guess  (after 1993).
+
+     For dates in the past (<= 1993) the value is linearly
+     interpolated on 5-year intervals; for dates after the present,
+     an extrapolation is used, because the true value of delta t
+     cannot be predicted precisely.  Note that TDT is essentially the
+     modern version of ephemeris time with a slightly cleaner
+     definition.
+
+     Where the algorithm shifts there is an approximately 0.1 second
+     discontinuity.  Also, the 5-year linear interpolation scheme can
+     lead to errors as large as 0.5 seconds in some cases, though
+     usually rather smaller. */
+
+double etcorr (double jd) {
+
+  double jd1900 = 2415019.5;
+  double dates[20] = {1900,1905,1910,1915,1920,1925,1930,1935,1940,1945,
+		      1950,1955,1960,1965,1970,1975,1980,1985,1990,1993};
+  double delts[20]={-2.72,3.86,10.46,17.20,21.16,23.62,24.02,23.93,24.33,26.77,
+		    29.15,31.07,33.15,35.73,40.18,45.48,50.54,54.34,56.86,59.12};
+  double year, delt;
+  short i;
+
+  year = 1900. + (jd - 2415019.5) / 365.25;
+
+  if(year < 1993.0 && year >= 1900.) {
+    i = (year - 1900) / 5;
+    delt = delts[i] +
+      ((delts[i+1] - delts[i])/(dates[i+1] - dates[i])) * (year - dates[i]);
+  }
+
+  else if (year > 1993. && year < 2100.)
+    delt = 33.15 + (2.164e-3) * (jd - 2436935.4);  /* rough extrapolation */
+
+  else if (year < 1900) {
+    delt = 0.;
+  }
+
+  else if (year >= 2100.) {
+    delt = 180.; /* who knows? */
+  }
+
+  return (delt);
+
+}
+
+/* sets RA and DEC at zenith as defined by given time and date  */
+void set_zenith (struct SC_date_time date, double lat, double longit, double epoch, double *ra, double *dec)
+{
+  double jd, current_epoch;
+
+  jd = date_to_jd (date);
+
+  if (jd < 0.) return;  /* nonexistent time. */
+
+  *ra = lst (jd, longit);
+
+  *dec = lat;
+
+  current_epoch = 2000. + (jd - J2000) / 365.25;
+
+  precrot (*ra,*dec,current_epoch,epoch,ra,dec);
+
+}
+
Index: /tags/start/Ohana/src/skycalc/src/dusktime.c
===================================================================
--- /tags/start/Ohana/src/skycalc/src/dusktime.c	(revision 12606)
+++ /tags/start/Ohana/src/skycalc/src/dusktime.c	(revision 12606)
@@ -0,0 +1,69 @@
+# include <stdio.h>
+# include <math.h>
+# include <skycalc_internal.h>
+
+void set_site (double *longit, double *lat, double *elevsea, double *elev) {
+
+  *longit = 10.36478; /*  W longitude in decimal hours */                     
+  *lat = 19.8267;     /*  N latitude in decimal degrees */                    
+  *elevsea = 4215.;   /* elevation above sea level (for absolute location) */ 
+  *elev = 4215.;      /* observatory elevation above horizon, meters */       
+
+}
+
+main (int argc, char **argv) {
+
+  struct SC_date_time date, tmpdate;
+  double longit, lat, elevsea, elev;
+  double jdnow, jdset, jdrise, d1, d2;
+  unsigned long int tzero;
+  struct tm *stm;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: dusktime (date)\n");
+    exit (1);
+  }
+
+  if (!str_to_time (argv[1], &tzero)) { 
+    fprintf (stderr, "syntax error\n");
+    exit (1);
+  }
+  stm = gmtime (&tzero);
+  date.y  = (short) (stm->tm_year + 1900);
+  date.mo = (short) (stm->tm_mon + 1);
+  date.d  = (short) (stm->tm_mday);
+  date.h  = (short) (stm->tm_hour);
+  date.mn = (short) (stm->tm_min);
+  date.s  = (float) (stm->tm_sec);
+
+  /*
+  fprintf (stderr, "%4d/%02d/%02d %02d:%02d:%02f\n", date.y, date.mo, date.d, date.h, date.mn, date.s);
+  */
+
+  set_site (&longit, &lat, &elevsea, &elev);
+
+  jdnow  = date_to_jd (date);
+  jdset  = sunset_tonight (date, lat, longit, elev);
+  jdrise = sunrise_tonight (date, lat, longit, elev);
+
+
+  d1 = fabs (jdnow - jdset);
+  d2 = fabs (jdnow - jdrise);
+
+  if (d1 < d2) {
+    fprintf (stdout, "set %f  %f\n", jdset, 24*60*(jdnow - jdset));
+    jdnow = jdset;
+  } else {
+    fprintf (stdout, "rise %f  %f\n", jdrise, 24*60*(jdrise - jdnow));
+    jdnow = jdrise;
+  }    
+
+  /*
+  jd_to_date (jdnow, &tmpdate);
+  fprintf (stderr, "%4d/%02d/%02d %02d:%02d:%02f\n", tmpdate.y, tmpdate.mo, tmpdate.d, tmpdate.h, tmpdate.mn, tmpdate.s);
+  */
+  exit (0);
+
+}
+
+  /* set_zenith (date, lat, longit, objepoch, &objra, &objdec); */
Index: /tags/start/Ohana/src/skycalc/src/geometry.c
===================================================================
--- /tags/start/Ohana/src/skycalc/src/geometry.c	(revision 12606)
+++ /tags/start/Ohana/src/skycalc/src/geometry.c	(revision 12606)
@@ -0,0 +1,135 @@
+# include <skycalc_internal.h>
+
+/* converts a coordinate triplet back to a standard ra and dec */
+void xyz_cel (double x, double y, double z, double *r, double *d) {
+
+   /* converts a coordinate triplet back to a standard ra and dec */
+
+   double mod;    /* modulus */
+   double xy;     /* component in xy plane */
+   short sign;    /* for determining quadrant */
+   double radian_ra, radian_dec;
+
+   /* this taken directly from pl1 routine - no acos or asin available there,
+       as it is in c. Easier just to copy, though */
+
+   mod = sqrt(x*x + y*y + z*z);
+   x = x / mod;
+   y = y / mod;
+   z = z / mod;   /* normalize 'em explicitly first. */
+
+   xy = sqrt(x*x + y*y);
+
+   if(xy < 1.0e-10) {
+      radian_ra = 0.;  /* too close to pole */
+      radian_dec = PI / 2.;
+      if(z < 0.) radian_dec = radian_dec * -1.;
+   }
+   else {
+      if(fabs(z/xy) < 3.) radian_dec = atan(z / xy);
+	 else if (z >= 0.) radian_dec = PI / 2. - atan(xy / z);
+	 else radian_dec = -1. * PI / 2. - atan(xy / z);
+      if(fabs(x) > 1.0e-10) {
+	 if(fabs(y / x) < 3.) radian_ra = atan(y / x);
+	 else if ((x * y ) >= 0.) radian_ra = PI / 2. - atan(x/y);
+	 else radian_ra = -1. *  PI / 2. - atan(x / y);
+      }
+      else {
+	 radian_ra = PI / 2.;
+	 if((x * y)<= 0.) radian_ra = radian_ra * -1.;
+      }
+      if(x <0.) radian_ra = radian_ra + PI ;
+      if(radian_ra < 0.) radian_ra = radian_ra + 2. * PI ;
+   }
+
+   *r = radian_ra * HRS_IN_RADIAN;
+   *d = radian_dec * DEG_IN_RADIAN;
+
+}
+
+/* returns radian angle 0 to 2pi for coords x, y -- get that quadrant right !! */
+double atan_circ (double x, double y) {
+  
+  double theta;
+  
+  if(x == 0.) {
+    if(y > 0.) theta = PI / 2.;
+    else if(y < 0.) theta = 3.* PI / 2.;
+    else theta = 0.;   /* x and y zero */
+  }
+  else theta = atan(y/x);
+  if(x < 0.) theta = theta + PI;
+  if(theta < 0.) theta = theta + 2.* PI;
+  return(theta);
+}
+
+/* returns altitude(degr) for dec, ha, lat (decimal degr, hr, degr);
+    also computes and returns azimuth through pointer argument. */
+double altit (double dec, double ha, double lat, double *az) {
+
+  double x,y,z;
+
+  dec = dec / DEG_IN_RADIAN;
+  ha = ha / HRS_IN_RADIAN;
+  lat = lat / DEG_IN_RADIAN;
+  x = DEG_IN_RADIAN * asin(cos(dec)*cos(ha)*cos(lat) + sin(dec)*sin(lat));
+  y =  sin(dec)*cos(lat) - cos(dec)*cos(ha)*sin(lat); /* due N comp. */
+  z =  -1. * cos(dec)*sin(ha); /* due east comp. */
+  *az = atan_circ(y,z) * DEG_IN_RADIAN;
+  return(x);
+}
+
+/* returns hour angle at which object at dec is at altitude alt.
+   If object is never at this altitude, signals with special
+   return values 1000 (always higher) and -1000 (always lower). */
+double ha_alt (double dec, double lat, double alt) {
+
+  double x,coalt,min,max;
+  
+  min_max_alt(lat,dec,&min,&max);
+  if(alt < min)
+    return(1000.);  /* flag value - always higher than asked */
+  if(alt > max)
+    return(-1000.); /* flag for object always lower than asked */
+  dec = (0.5*PI) - dec / DEG_IN_RADIAN;
+  lat = (0.5*PI) - lat / DEG_IN_RADIAN;
+  coalt = (0.5*PI) - alt / DEG_IN_RADIAN;
+  x = (cos(coalt) - cos(dec)*cos(lat)) / (sin(dec)*sin(lat));
+  if (fabs(x) <= 1.) return(acos(x) * HRS_IN_RADIAN);
+  else {
+    printf  ("Error in ha_alt ... acos(>1).\n");
+    return (1000.);
+  }
+}
+
+/* computes minimum and maximum altitude for a given dec and latitude. */
+void min_max_alt (double lat, double dec, double *min, double *max) {
+
+  double x;
+
+  lat = lat / DEG_IN_RADIAN; /* pass by value! */
+  dec = dec / DEG_IN_RADIAN;
+  x = cos(dec)*cos(lat) + sin(dec)*sin(lat);
+  if (fabs(x) <= 1.) {
+    *max = asin(x) * DEG_IN_RADIAN;
+  }
+  else printf ("Error in min_max_alt -- arcsin(>1)\n");
+
+  x = sin(dec)*sin(lat) - cos(dec)*cos(lat);
+  if(fabs(x) <= 1.) {
+    *min = asin(x) * DEG_IN_RADIAN;
+  }
+  else printf ("Error in min_max_alt -- arcsin(>1)\n");
+}
+
+/* force domain to be 0 - 360 degrees */
+double circulo (double x) {
+  
+  /* fails for negative angles! */
+
+  int n;
+  
+  n = (int)(x / 360.);
+  return(x - 360. * n);
+}
+
Index: /tags/start/Ohana/src/skycalc/src/misc.c
===================================================================
--- /tags/start/Ohana/src/skycalc/src/misc.c	(revision 12606)
+++ /tags/start/Ohana/src/skycalc/src/misc.c	(revision 12606)
@@ -0,0 +1,321 @@
+# include <ohana.h>
+
+int dms_to_ddd (double *Value, char *string);
+int str_to_radec (double *ra, double *dec, char *str1, char *str2);
+int chk_time (char *line);
+double sec_to_jd (unsigned long second);
+unsigned long int jd_to_sec (double jd);
+char *sec_to_date (unsigned long second);
+unsigned long date_to_sec (char *date);
+  
+/***** convert [-]00:00:00 to 0.0000 ****/
+int dms_to_ddd (double *Value, char *string) {
+  
+  int valid, neg, status;
+  double tmp, value;
+  char *p1, *p2, *px;
+
+  valid = FALSE; 
+  neg = FALSE;
+  stripwhite (string);
+  p1 = string;
+  px = string + strlen(string);
+
+  if (string[0] == '-') { 
+    valid = TRUE; 
+    neg = TRUE;
+    p1 = &string[1];
+  }
+  if (string[0] == '+') { 
+    valid = TRUE; 
+    neg = FALSE;
+    p1 = &string[1];
+  }
+  if (isdigit(string[0])) { 
+    valid = TRUE;
+    p1 = &string[0];
+  }
+  if (!valid) { return (FALSE); }
+
+  status = 1;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) return (FALSE); /* entry not a number: +fred */
+  value = tmp;
+  if (p2 == px) goto escape;    /* entry only number: +1.0 */ 
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:fred */
+  status = 2;
+  value += tmp / 60.0;
+  if (p2 == px) goto escape;    /* entry only number: +1:1 */
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:1:fred */
+  value += tmp / 3600.0;
+
+ escape:
+  if (neg) {
+    value *= -1;
+  }
+  *Value = value;
+
+  return (status);
+}
+
+/**********/
+int str_to_radec (double *ra, double *dec, char *str1, char *str2) {
+
+  double Ra, Dec;
+
+  *ra = *dec = 0;
+  switch (dms_to_ddd (&Ra, str1)) {
+  case 0:
+    fprintf (stderr, "syntax error in RA\n");
+    return (FALSE);
+  case 1:
+    break;
+  case 2:
+    Ra = Ra * 15;
+    break;
+  }
+  switch (dms_to_ddd (&Dec, str2)) {
+  case 0:
+    fprintf (stderr, "syntax error in DEC\n");
+    return (FALSE);
+  case 1:
+  case 2:
+    break;
+  }
+  *ra = Ra;
+  *dec = Dec;
+  return (TRUE);
+}
+
+# define FORMAT_DAYS    1
+# define FORMAT_HOURS   2
+# define FORMAT_MINUTES 3
+# define FORMAT_SECONDS 4
+# define FORMAT_JD      5
+# define FORMAT_DATE    6
+
+/**********/
+int chk_time (char *line) {
+
+  char *p1, *p2;
+  double tmp;
+  int mode;
+
+  p1 = line;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1 + strlen (p1) - 1) {
+    if (*p2 == 'd') {
+      mode = FORMAT_DAYS;
+    }
+    if (*p2 == 'h') {
+      mode = FORMAT_HOURS;
+    }
+    if (*p2 == 'm') {
+      mode = FORMAT_MINUTES;
+    }
+    if (*p2 == 's') {
+      mode = FORMAT_SECONDS;
+    }
+    if (*p2 == 'j') {
+      mode = FORMAT_JD;
+    }
+  } else { 
+    mode = FORMAT_DATE;
+  }
+  return (mode);
+}
+
+/**********/
+int str_to_time (char *line, unsigned int *second) {
+  
+  struct timeval now;
+  double jd;
+
+  if (!strcasecmp (line, "NOW")) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    *second = now.tv_sec;
+    return (TRUE);
+  }
+    
+  if (!strcasecmp (line, "TODAY")) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    *second = 86400 * ((int)(now.tv_sec / 86400));
+    return (TRUE);
+  }
+    
+  switch (chk_time (line)) {
+  case 0:
+    return (FALSE);
+  case FORMAT_DAYS:
+    *second = strtod (line, 0) * 86400.0;
+    return (TRUE);
+  case FORMAT_HOURS:
+    *second = strtod (line, 0) * 3600.0;
+    return (TRUE);
+  case FORMAT_MINUTES:
+    *second = strtod (line, 0) * 60.0;
+    return (TRUE);
+  case FORMAT_SECONDS:
+    *second = strtod (line, 0);
+    return (TRUE);
+  case FORMAT_JD:
+    jd = strtod (line, 0);
+    *second = jd_to_sec (jd);
+    return (TRUE);
+  case FORMAT_DATE:
+    *second = date_to_sec (line);
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+/**********/
+int str_to_dtime (char *line, double *second) {
+  
+  switch (chk_time (line)) {
+  case 0:
+  case FORMAT_JD:
+  case FORMAT_DATE:
+    return (FALSE);
+  case FORMAT_DAYS:
+    *second = strtod (line, 0) * 86400.0;
+    return (TRUE);
+  case FORMAT_HOURS:
+    *second = strtod (line, 0) * 3600.0;
+    return (TRUE);
+  case FORMAT_MINUTES:
+    *second = strtod (line, 0) * 60.0;
+    return (TRUE);
+  case FORMAT_SECONDS:
+    *second = strtod (line, 0);
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+/**********/
+double sec_to_jd (unsigned long second) {
+
+  double jd;
+  
+  jd = second/86400.0 + 2440587.5;
+  return (jd);
+}
+
+/**********/
+unsigned long int jd_to_sec (double jd) {
+
+  unsigned long int second;
+
+  second = (jd - 2440587.5)*86400;
+  return (second);
+}
+
+/**********/
+char *sec_to_date (unsigned long second) {
+  
+  struct tm *gmt;
+  char *line;
+  
+  ALLOCATE (line, char, 64);
+  gmt   = gmtime (&second);
+  sprintf (line, "%4d/%02d/%02d,%02d:%02d:%02d", 1900+gmt[0].tm_year, gmt[0].tm_mon+1, gmt[0].tm_mday, gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+  return (line);
+
+}
+
+/***** date in format yyyy/mm/dd,hh:mm:ss *****/
+unsigned long date_to_sec (char *date) {
+  
+  unsigned long second;
+  double tmp, jd;
+  struct tm now;
+  char *p1, *p2, *px;
+  
+  p1 = date;
+  px = date + strlen(date);
+  bzero (&now, sizeof(now));
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_year = tmp;
+  if (now.tm_year > 1000) now.tm_year -= 1900;
+  if (now.tm_year <   50) now.tm_year += 100;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mon = tmp - 1; /* mon runs from 0 - 11 */
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mday = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  p1 = p2 + 1;
+  now.tm_hour = tmp;
+  if (p2 == px) goto escape;  
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_min = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_sec = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+ escape:
+  jd = now.tm_mday - 32075 + (int)(1461*(1900 + now.tm_year + 4800 + (int)(((now.tm_mon+1)-14)/12))/4)
+    + (int)(367*((now.tm_mon+1) - 2 - (int)(((now.tm_mon+1) - 14)/12)*12)/12)
+    - (int)(3*(int)((1900 + now.tm_year + 4900 + (int)(((now.tm_mon+1) - 14)/12))/100)/4) - 0.5;
+  
+  second = (jd - 2440587.5)*86400 + 3600.0*now.tm_hour + now.tm_min*60.0 + now.tm_sec;
+
+  return (second);
+}
+
+
+/* times may be in forms as:
+   20040200450s (N seconds since 1970.0)
+   2440900.232j (julian date)
+   99/02/23,03:22:18 (date string)
+   (separators may be anything except space, +, -)
+   99:02:15:12:23:30
+   99:02:15:12h23m30s
+   */
+
+
+/* fseek with timeout - 0.5 sec */
+int Fseek (FILE *f, long offset, int whence) {
+
+  int status, k;
+
+  status = fseek (f, offset, whence);
+  if (status == -1) {
+    int k;
+    /* fprintf (stderr, "problem seeking position: %d\n", errno); */
+    for (k = 0; (k < 10) && ((status = fseek (f, 0, SEEK_SET)) == -1); k++) usleep (50000);
+    if (status == -1) {
+      /* fprintf (stderr, "ERROR: serious problem seeking position: %d\n", errno); */
+      /* clear lock at this point? */
+      return (0);
+    }
+  }
+  return (1);
+}
Index: /tags/start/Ohana/src/skycalc/src/moon.c
===================================================================
--- /tags/start/Ohana/src/skycalc/src/moon.c	(revision 12606)
+++ /tags/start/Ohana/src/skycalc/src/moon.c	(revision 12606)
@@ -0,0 +1,465 @@
+# include <skycalc_internal.h>
+
+void lpmoon(double jd, double lat, double sid,
+       double* ra, double* dec, double* dist) {
+
+
+/* implements "low precision" moon algorithms from
+   Astronomical Almanac (p. D46 in 1992 version).  Does
+   apply the topocentric correction. 
+   Units are as follows
+   jd,lat, sid;   decimal hours 
+   *ra, *dec,   decimal hours, degrees 
+   *dist;      earth radii */
+
+
+    double T, lambda, beta, pie, l, m, n, x, y, z, alpha, delta,
+        rad_lat, rad_lst, distance, topo_dist;
+    char dummy[40];  /* to fix compiler bug on IBM system */
+
+    T = (jd - J2000) / 36525.;  /* jul cent. since J2000.0 */
+
+    lambda = 218.32 + 481267.883 * T 
+        + 6.29 * sin((134.9 + 477198.85 * T) / DEG_IN_RADIAN)
+        - 1.27 * sin((259.2 - 413335.38 * T) / DEG_IN_RADIAN)
+        + 0.66 * sin((235.7 + 890534.23 * T) / DEG_IN_RADIAN)
+        + 0.21 * sin((269.9 + 954397.70 * T) / DEG_IN_RADIAN)
+        - 0.19 * sin((357.5 + 35999.05 * T) / DEG_IN_RADIAN)
+        - 0.11 * sin((186.6 + 966404.05 * T) / DEG_IN_RADIAN);
+    lambda = lambda / DEG_IN_RADIAN;
+    beta = 5.13 * sin((93.3 + 483202.03 * T) / DEG_IN_RADIAN)
+        + 0.28 * sin((228.2 + 960400.87 * T) / DEG_IN_RADIAN)
+        - 0.28 * sin((318.3 + 6003.18 * T) / DEG_IN_RADIAN)
+        - 0.17 * sin((217.6 - 407332.20 * T) / DEG_IN_RADIAN);
+    beta = beta / DEG_IN_RADIAN;
+    pie = 0.9508 
+        + 0.0518 * cos((134.9 + 477198.85 * T) / DEG_IN_RADIAN)
+        + 0.0095 * cos((259.2 - 413335.38 * T) / DEG_IN_RADIAN)
+        + 0.0078 * cos((235.7 + 890534.23 * T) / DEG_IN_RADIAN)
+        + 0.0028 * cos((269.9 + 954397.70 * T) / DEG_IN_RADIAN);
+    pie = pie / DEG_IN_RADIAN;
+    distance = 1 / sin(pie);
+
+    l = cos(beta) * cos(lambda);
+    m = 0.9175 * cos(beta) * sin(lambda) - 0.3978 * sin(beta);
+    n = 0.3978 * cos(beta) * sin(lambda) + 0.9175 * sin(beta);
+
+    x = l * distance; 
+    y = m * distance; 
+    z = n * distance;  /* for topocentric correction */
+
+
+    /* lat isn't passed right on some IBM systems unless you do this
+       or something like it! */
+    sprintf(dummy,"%f",lat);
+
+    rad_lat = lat / DEG_IN_RADIAN;
+    rad_lst = sid / HRS_IN_RADIAN;
+
+    x = x - cos(rad_lat) * cos(rad_lst);
+    y = y - cos(rad_lat) * sin(rad_lst);
+    z = z - sin(rad_lat);
+
+
+    topo_dist = sqrt(x * x + y * y + z * z);
+
+    l = x / topo_dist; 
+    m = y / topo_dist; 
+    n = z / topo_dist;
+
+    alpha = atan_circ(l,m);
+    delta = asin(n);
+
+    *ra = alpha * HRS_IN_RADIAN;
+
+    *dec = delta * DEG_IN_RADIAN;
+    
+    *dist = topo_dist;
+
+}
+
+/* More accurate (but more elaborate and slower) lunar
+   ephemeris, from Jean Meeus' *Astronomical Formulae For Calculators*,
+   pub. Willman-Bell.  Includes all the terms given there. */
+
+void accumoon (jd,geolat,lst,elevsea,geora,geodec,geodist,topora,topodec,topodist)
+     double jd,geolat,lst,elevsea;
+     double *geora,*geodec,*geodist,*topora,*topodec,*topodist;
+{
+  double pie, dist;  /* horiz parallax */
+  double Lpr,M,Mpr,D,F,Om,T,Tsq,Tcb;
+  double e,lambda,B,beta,om1,om2;
+  double sinx, x, y, z, l, m, n;
+  double x_geo, y_geo, z_geo;  /* geocentric position of *observer* */
+
+  jd = jd + etcorr(jd)/SEC_IN_DAY;   /* approximate correction to ephemeris time */
+  T = (jd - 2415020.) / 36525.;   /* this based around 1900 ... */
+  Tsq = T * T;
+  Tcb = Tsq * T;
+
+  Lpr = 270.434164 + 481267.8831 * T - 0.001133 * Tsq
+    + 0.0000019 * Tcb;
+  M = 358.475833 + 35999.0498*T - 0.000150*Tsq
+    - 0.0000033*Tcb;
+  Mpr = 296.104608 + 477198.8491*T + 0.009192*Tsq
+    + 0.0000144*Tcb;
+  D = 350.737486 + 445267.1142*T - 0.001436 * Tsq
+    + 0.0000019*Tcb;
+  F = 11.250889 + 483202.0251*T -0.003211 * Tsq
+    - 0.0000003*Tcb;
+  Om = 259.183275 - 1934.1420*T + 0.002078*Tsq
+    + 0.0000022*Tcb;
+
+  Lpr = circulo(Lpr);
+  Mpr = circulo(Mpr);
+  M = circulo(M);
+  D = circulo(D);
+  F = circulo(F);
+  Om = circulo(Om);
+
+
+  sinx =  sin((51.2 + 20.2 * T)/DEG_IN_RADIAN);
+  Lpr = Lpr + 0.000233 * sinx;
+  M = M - 0.001778 * sinx;
+  Mpr = Mpr + 0.000817 * sinx;
+  D = D + 0.002011 * sinx;
+
+  sinx = 0.003964 * sin((346.560+132.870*T -0.0091731*Tsq)/DEG_IN_RADIAN);
+
+  Lpr = Lpr + sinx;
+  Mpr = Mpr + sinx;
+  D = D + sinx;
+  F = F + sinx;
+
+  sinx = sin(Om/DEG_IN_RADIAN);
+  Lpr = Lpr + 0.001964 * sinx;
+  Mpr = Mpr + 0.002541 * sinx;
+  D = D + 0.001964 * sinx;
+  F = F - 0.024691 * sinx;
+  F = F - 0.004328 * sin((Om + 275.05 -2.30*T)/DEG_IN_RADIAN);
+
+  e = 1 - 0.002495 * T - 0.00000752 * Tsq;
+
+  M = M / DEG_IN_RADIAN;   /* these will all be arguments ... */
+  Mpr = Mpr / DEG_IN_RADIAN;
+  D = D / DEG_IN_RADIAN;
+  F = F / DEG_IN_RADIAN;
+
+  lambda = Lpr + 6.288750 * sin(Mpr)
+    + 1.274018 * sin(2*D - Mpr)
+    + 0.658309 * sin(2*D)
+    + 0.213616 * sin(2*Mpr)
+    - e * 0.185596 * sin(M)
+    - 0.114336 * sin(2*F)
+    + 0.058793 * sin(2*D - 2*Mpr)
+    + e * 0.057212 * sin(2*D - M - Mpr)
+    + 0.053320 * sin(2*D + Mpr)
+    + e * 0.045874 * sin(2*D - M)
+    + e * 0.041024 * sin(Mpr - M)
+    - 0.034718 * sin(D)
+    - e * 0.030465 * sin(M+Mpr)
+    + 0.015326 * sin(2*D - 2*F)
+    - 0.012528 * sin(2*F + Mpr)
+    - 0.010980 * sin(2*F - Mpr)
+    + 0.010674 * sin(4*D - Mpr)
+    + 0.010034 * sin(3*Mpr)
+    + 0.008548 * sin(4*D - 2*Mpr)
+    - e * 0.007910 * sin(M - Mpr + 2*D)
+    - e * 0.006783 * sin(2*D + M)
+    + 0.005162 * sin(Mpr - D);
+
+		/* And furthermore.....*/
+
+  lambda = lambda + e * 0.005000 * sin(M + D)
+    + e * 0.004049 * sin(Mpr - M + 2*D)
+    + 0.003996 * sin(2*Mpr + 2*D)
+    + 0.003862 * sin(4*D)
+    + 0.003665 * sin(2*D - 3*Mpr)
+    + e * 0.002695 * sin(2*Mpr - M)
+    + 0.002602 * sin(Mpr - 2*F - 2*D)
+    + e * 0.002396 * sin(2*D - M - 2*Mpr)
+    - 0.002349 * sin(Mpr + D)
+    + e * e * 0.002249 * sin(2*D - 2*M)
+    - e * 0.002125 * sin(2*Mpr + M)
+    - e * e * 0.002079 * sin(2*M)
+    + e * e * 0.002059 * sin(2*D - Mpr - 2*M)
+    - 0.001773 * sin(Mpr + 2*D - 2*F)
+    - 0.001595 * sin(2*F + 2*D)
+    + e * 0.001220 * sin(4*D - M - Mpr)
+    - 0.001110 * sin(2*Mpr + 2*F)
+    + 0.000892 * sin(Mpr - 3*D)
+    - e * 0.000811 * sin(M + Mpr + 2*D)
+    + e * 0.000761 * sin(4*D - M - 2*Mpr)
+    + e * e * 0.000717 * sin(Mpr - 2*M)
+    + e * e * 0.000704 * sin(Mpr - 2 * M - 2*D)
+    + e * 0.000693 * sin(M - 2*Mpr + 2*D)
+    + e * 0.000598 * sin(2*D - M - 2*F)
+    + 0.000550 * sin(Mpr + 4*D)
+    + 0.000538 * sin(4*Mpr)
+    + e * 0.000521 * sin(4*D - M)
+    + 0.000486 * sin(2*Mpr - D);
+
+/*              *eclongit = lambda;  */
+
+  B = 5.128189 * sin(F)
+    + 0.280606 * sin(Mpr + F)
+    + 0.277693 * sin(Mpr - F)
+    + 0.173238 * sin(2*D - F)
+    + 0.055413 * sin(2*D + F - Mpr)
+    + 0.046272 * sin(2*D - F - Mpr)
+    + 0.032573 * sin(2*D + F)
+    + 0.017198 * sin(2*Mpr + F)
+    + 0.009267 * sin(2*D + Mpr - F)
+    + 0.008823 * sin(2*Mpr - F)
+    + e * 0.008247 * sin(2*D - M - F)
+    + 0.004323 * sin(2*D - F - 2*Mpr)
+    + 0.004200 * sin(2*D + F + Mpr)
+    + e * 0.003372 * sin(F - M - 2*D)
+    + 0.002472 * sin(2*D + F - M - Mpr)
+    + e * 0.002222 * sin(2*D + F - M)
+    + e * 0.002072 * sin(2*D - F - M - Mpr)
+    + e * 0.001877 * sin(F - M + Mpr)
+    + 0.001828 * sin(4*D - F - Mpr)
+    - e * 0.001803 * sin(F + M)
+    - 0.001750 * sin(3*F)
+    + e * 0.001570 * sin(Mpr - M - F)
+    - 0.001487 * sin(F + D)
+    - e * 0.001481 * sin(F + M + Mpr)
+    + e * 0.001417 * sin(F - M - Mpr)
+    + e * 0.001350 * sin(F - M)
+    + 0.001330 * sin(F - D)
+    + 0.001106 * sin(F + 3*Mpr)
+    + 0.001020 * sin(4*D - F)
+    + 0.000833 * sin(F + 4*D - Mpr);
+  /* not only that, but */
+  B = B + 0.000781 * sin(Mpr - 3*F)
+    + 0.000670 * sin(F + 4*D - 2*Mpr)
+    + 0.000606 * sin(2*D - 3*F)
+    + 0.000597 * sin(2*D + 2*Mpr - F)
+    + e * 0.000492 * sin(2*D + Mpr - M - F)
+    + 0.000450 * sin(2*Mpr - F - 2*D)
+    + 0.000439 * sin(3*Mpr - F)
+    + 0.000423 * sin(F + 2*D + 2*Mpr)
+    + 0.000422 * sin(2*D - F - 3*Mpr)
+    - e * 0.000367 * sin(M + F + 2*D - Mpr)
+    - e * 0.000353 * sin(M + F + 2*D)
+    + 0.000331 * sin(F + 4*D)
+    + e * 0.000317 * sin(2*D + F - M + Mpr)
+    + e * e * 0.000306 * sin(2*D - 2*M - F)
+    - 0.000283 * sin(Mpr + 3*F);
+
+  om1 = 0.0004664 * cos(Om/DEG_IN_RADIAN);
+  om2 = 0.0000754 * cos((Om + 275.05 - 2.30*T)/DEG_IN_RADIAN);
+
+  beta = B * (1. - om1 - om2);
+  /*      *eclatit = beta; */
+
+  pie = 0.950724
+    + 0.051818 * cos(Mpr)
+    + 0.009531 * cos(2*D - Mpr)
+    + 0.007843 * cos(2*D)
+    + 0.002824 * cos(2*Mpr)
+    + 0.000857 * cos(2*D + Mpr)
+    + e * 0.000533 * cos(2*D - M)
+    + e * 0.000401 * cos(2*D - M - Mpr)
+    + e * 0.000320 * cos(Mpr - M)
+    - 0.000271 * cos(D)
+    - e * 0.000264 * cos(M + Mpr)
+    - 0.000198 * cos(2*F - Mpr)
+    + 0.000173 * cos(3*Mpr)
+    + 0.000167 * cos(4*D - Mpr)
+    - e * 0.000111 * cos(M)
+    + 0.000103 * cos(4*D - 2*Mpr)
+    - 0.000084 * cos(2*Mpr - 2*D)
+    - e * 0.000083 * cos(2*D + M)
+    + 0.000079 * cos(2*D + 2*Mpr)
+    + 0.000072 * cos(4*D)
+    + e * 0.000064 * cos(2*D - M + Mpr)
+    - e * 0.000063 * cos(2*D + M - Mpr)
+    + e * 0.000041 * cos(M + D)
+    + e * 0.000035 * cos(2*Mpr - M)
+    - 0.000033 * cos(3*Mpr - 2*D)
+    - 0.000030 * cos(Mpr + D)
+    - 0.000029 * cos(2*F - 2*D)
+    - e * 0.000029 * cos(2*Mpr + M)
+    + e * e * 0.000026 * cos(2*D - 2*M)
+    - 0.000023 * cos(2*F - 2*D + Mpr)
+    + e * 0.000019 * cos(4*D - M - Mpr);
+
+  beta = beta/DEG_IN_RADIAN;
+  lambda = lambda/DEG_IN_RADIAN;
+  l = cos(lambda) * cos(beta);
+  m = sin(lambda) * cos(beta);
+  n = sin(beta);
+  eclrot(jd,&l,&m,&n);
+
+  dist = 1/sin((pie)/DEG_IN_RADIAN);
+  x = l * dist;
+  y = m * dist;
+  z = n * dist;
+
+  *geora = atan_circ(l,m) * HRS_IN_RADIAN;
+  *geodec = asin(n) * DEG_IN_RADIAN;
+  *geodist = dist;
+
+  geocent (lst, geolat, elevsea, &x_geo, &y_geo, &z_geo);
+
+  x = x - x_geo;  /* topocentric correction using elliptical earth fig. */
+  y = y - y_geo;
+  z = z - z_geo;
+
+  *topodist = sqrt(x*x + y*y + z*z);
+
+  l = x / (*topodist);
+  m = y / (*topodist);
+  n = z / (*topodist);
+
+  *topora = atan_circ(l,m) * HRS_IN_RADIAN;
+  *topodec = asin(n) * DEG_IN_RADIAN;
+
+}
+
+/* returns jd at which moon is at a given
+   altitude, given jdguess as a starting point. In current version
+   uses high-precision moon -- execution time does not seem to be
+   excessive on modern hardware.  If it's a problem on your machine,
+   you can replace calls to 'accumoon' with 'lpmoon' and remove
+   the 'elevsea' argument. */
+double jd_moon_alt (double alt, double jdguess, double lat, double longit, double elevsea) {
+
+  double jdout;
+  double deriv, err, del = 0.002;
+  double ra,dec,dist,geora,geodec,geodist,sid,ha,alt2,alt3,az;
+  short i = 0;
+
+  /* first guess */
+
+  sid=lst(jdguess,longit);
+  accumoon(jdguess,lat,sid,elevsea,&geora,&geodec,&geodist,
+	   &ra,&dec,&dist);
+  ha = lst(jdguess,longit) - ra;
+  alt2 = altit(dec,ha,lat,&az);
+  jdguess = jdguess + del;
+  sid = lst(jdguess,longit);
+  accumoon(jdguess,lat,sid,elevsea,&geora,&geodec,&geodist,
+	   &ra,&dec,&dist);
+  alt3 = altit(dec,(sid - ra),lat,&az);
+  err = alt3 - alt;
+  deriv = (alt3 - alt2) / del;
+  while((fabs(err) > 0.1) && (i < 10)) {
+    jdguess = jdguess - err/deriv;
+    sid=lst(jdguess,longit);
+    accumoon(jdguess,lat,sid,elevsea,&geora,&geodec,&geodist,
+	     &ra,&dec,&dist);
+    alt3 = altit(dec,(sid - ra),lat,&az);
+    err = alt3 - alt;
+    i++;
+  }
+  if(i >= 9) jdguess = -1000.;
+  jdout = jdguess;
+  return(jdout);
+}
+
+/* Given site position, return Moonset for closest midnight */
+double moonset_tonight (struct SC_date_time date, double lat, double longit, double elevsea, double elev) {
+
+  double jd, jdmid, stmid;
+  double min_alt, max_alt;
+  double geora, geodec, geodist;  /* geocent for moon, not used here.*/
+  double ramoon, decmoon, distmoon;
+  double hamoonrise, hamoonset, tmoonrise, tmoonset, jdmoonrise, jdmoonset;
+  short dow; /* day of week */
+  struct SC_date_time date_midnight, tmpdate;
+  double dt, lst0, lst1, djd, horiz;
+
+  horiz = sqrt (2. * elev / 6378140.) * DEG_IN_RADIAN;
+
+  /* find offset in hours from longit to greenwich */
+  jd = date_to_jd (date);  /* true jd now */
+  lst0 = lst (jd, 0.0);    /* lst at long = 0 */
+  lst1 = lst (jd, longit); /* local lst now */
+  dt = lst0 - lst1;
+  if (dt < 0) dt += 24;
+	
+  /* midnight at greenwich */
+  date_midnight = date;
+  date_midnight.h = 0;
+  date_midnight.mn = 0;
+  date_midnight.s = 0;
+	
+  /* find jd for local midnight, select the *closest* midnight */
+  jdmid = date_to_jd (date_midnight) - dt / 24.0;
+  djd = jd - jdmid;
+  if (djd < -0.5) jdmid -= 1.0;
+  if (djd >  0.5) jdmid += 1.0;
+  stmid = lst (jdmid,longit); 
+
+  accumoon (jdmid,lat,stmid,elevsea,&geora,&geodec,&geodist,&ramoon,&decmoon,&distmoon);
+
+  min_max_alt (lat,decmoon,&min_alt,&max_alt);  /* rough check -- occurs? */
+  if (max_alt < -(0.83+horiz)) return (-1);
+  if (min_alt > -(0.83+horiz)) return (-1);
+
+  /* compute moonrise and set if they're likely to occur */
+
+  hamoonset = ha_alt(decmoon,lat,-(0.83+horiz)); /* rough approx. */
+
+  tmoonset = adj_time(ramoon+hamoonset-stmid);
+  jdmoonset = jdmid + tmoonset / 24.;
+  jdmoonset = jd_moon_alt(-(0.83+horiz),jdmoonset,lat,longit,elevsea);
+
+  return (jdmoonset);
+
+}
+
+/* Given site position, return Moonrise for closest midnight */
+double moonrise_tonight (struct SC_date_time date, double lat, double longit, double elevsea, double elev) {
+
+  double jd, jdmid, stmid;
+  double min_alt, max_alt;
+  double geora, geodec, geodist;  /* geocent for moon, not used here.*/
+  double ramoon, decmoon, distmoon;
+  double hamoonrise, hamoonset, tmoonrise, tmoonset, jdmoonrise, jdmoonset;
+  short dow; /* day of week */
+  struct SC_date_time date_midnight, tmpdate;
+  double dt, lst0, lst1, djd, horiz;
+
+  horiz = sqrt (2. * elev / 6378140.) * DEG_IN_RADIAN;
+
+  /* find offset in hours from longit to greenwich */
+  jd = date_to_jd (date);  /* true jd now */
+  lst0 = lst (jd, 0.0);    /* lst at long = 0 */
+  lst1 = lst (jd, longit); /* local lst now */
+  dt = lst0 - lst1;
+  if (dt < 0) dt += 24;
+	
+  /* midnight at greenwich */
+  date_midnight = date;
+  date_midnight.h = 0;
+  date_midnight.mn = 0;
+  date_midnight.s = 0;
+	
+  /* find jd for local midnight, select the *closest* midnight */
+  jdmid = date_to_jd (date_midnight) - dt / 24.0;
+  djd = jd - jdmid;
+  if (djd < -0.5) jdmid -= 1.0;
+  if (djd >  0.5) jdmid += 1.0;
+  stmid = lst (jdmid,longit); 
+
+  accumoon (jdmid,lat,stmid,elevsea,&geora,&geodec,&geodist,&ramoon,&decmoon,&distmoon);
+
+  min_max_alt (lat,decmoon,&min_alt,&max_alt);  /* rough check -- occurs? */
+  if (max_alt < -(0.83+horiz)) return (-1);
+  if (min_alt > -(0.83+horiz)) return (-1);
+
+  /* compute moonrise and set if they're likely to occur */
+
+  hamoonset = ha_alt(decmoon,lat,-(0.83+horiz)); /* rough approx. */
+
+  tmoonrise = adj_time(ramoon-hamoonset-stmid);
+  jdmoonrise = jdmid + tmoonrise / 24.;
+  jdmoonrise = jd_moon_alt(-(0.83+horiz),jdmoonrise,lat,longit,elevsea);
+
+  return (jdmoonrise);
+
+}
Index: /tags/start/Ohana/src/skycalc/src/moon_interference.c
===================================================================
--- /tags/start/Ohana/src/skycalc/src/moon_interference.c	(revision 12606)
+++ /tags/start/Ohana/src/skycalc/src/moon_interference.c	(revision 12606)
@@ -0,0 +1,875 @@
+/*
+   This program segment is extracted from the skycalc program written
+   by John Thorstensen from Dartmouth College.  For question please
+   contact: John.Thorstensen@Dartmouth.edu
+   This is one long and ugly, but accurate program.  Ideally I should
+   have split this into separate modules, but this may be replaced by
+   Bernt's algorithm anyway... so "let's wait and see what happens"   
+   -Rosemary Alles 04/18/2001
+   */
+
+#include <stdio.h>
+#include <math.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+
+/* some (not all) physical, mathematical, and astronomical constants
+   used are defined here. */
+#define  DEG_IN_RADIAN     57.2957795130823
+#define  HRS_IN_RADIAN     3.819718634205
+#define  EQUAT_RAD         6378137.    /* equatorial radius of earth, meters */
+#define  TWOPI             6.28318530717959
+#define  J2000             2451545.    /* Julian date at standard epoch */
+#define  SEC_IN_DAY        86400.
+
+struct coord {
+    short sign;  /* carry sign explicitly since -0 not neg. */
+    double hh;
+    double mm;
+    double ss;
+};
+
+struct date_time {
+    short y;
+    short mo;
+    short d;
+    short h;
+    short mn;
+    float s;
+};
+
+/* Gloabals */
+int update_on = 0; 
+double update_delta = 0.;
+
+/* Prototypes */
+void load_site(double* longit, double* lat, double* stdz,
+               short* use_dst, char* zone_name, char* zabr,
+               double* elevsea, double* elev, double* horiz,
+               char* site_name);
+double zone(short use_dst, double stdz,
+            double jd, double jdb, double jde);
+void caldat(double jdin, struct date_time* date, short *dow);
+short day_of_week(double jd);
+double day_of_year(double jd);
+void find_dst_bounds(short yr, double stdz, short use_dst,
+                     double *jdb, double* jde);
+int get_sys_date(struct date_time *date, short use_dst, short enter_ut,
+                 short night_date, double stdz, double toffset, double* jd);
+double lst(double jd, double longit);
+double date_to_jd(struct date_time date);
+void lpmoon(double jd, double lat, double sid,
+            double* ra, double* dec, double* dist);
+void put_coords(double deci, int precision, int showsign);
+double get_coord(void);
+void dec_to_bab (double deci, struct coord* bab);
+double atan_circ(double x, double y);
+double adj_time(double x);
+
+    
+void
+load_site(double* longit, double* lat, double* stdz,
+          short* use_dst, char* zone_name, char* zabr,
+          double* elevsea, double* elev, double* horiz,
+          char* site_name) {
+              
+/* sets the site-specific quantities; these are
+   longit     = W longitude in decimal hours
+   lat        = N latitude in decimal degrees
+   stdz       = standard time zone offset, hours
+   elevsea    = elevation above sea level (for absolute location)
+   elev       = observatory elevation above horizon, meters
+   horiz      = (derived) added zenith distance for rise/set due
+                to elevation
+   use_dst    = 0 don't use it
+                1 use USA convention
+                2 use Spanish convention
+                < 0 Southern hemisphere (reserved, unimplimented)
+   zone_name  = name of time zone, e. g. Eastern
+   zabr       = single-character abbreviation of time zone
+   site_name  = name of site.  */
+    
+    strcpy(site_name, "Mauna Kea, Hawaii");
+    strcpy(zone_name, "Hawaiian");
+    *zabr = 'H';
+    *use_dst = 0;
+    *longit = 10.36478;
+    *lat = 19.8267;
+    *elevsea = 4215.;
+    *elev = 4215.;  /* yow! */
+    *stdz = 10.;
+
+    /* now compute derived quantity "horiz" = depression of horizon.*/
+    *horiz = sqrt(2. * *elev / EQUAT_RAD) * DEG_IN_RADIAN;   
+}
+
+double
+zone(short use_dst, double stdz,
+     double jd, double jdb, double jde) {
+    
+    /* Returns zone time offset when standard time zone is stdz,
+       when daylight time begins (for the year) on jdb, and ends
+       (for the year) on jde.  This is parochial to the northern
+       hemisphere.  */
+    /* Extension -- specifying a negative value of use_dst reverses
+       the logic for the Southern hemisphere; then DST is assumed for
+       the Southern hemisphere summer (which is the end and beginning
+       of the year. */
+    
+    if(use_dst == 0) return(stdz);
+    else if((jd > jdb) && (jd < jde) && (use_dst > 0)) return(stdz-1.);
+    /* next line .. use_dst < 0 .. for Southern Hemisphere sites. */
+    else if(((jd < jdb) || (jd > jde)) && (use_dst < 0)) return(stdz-1.);
+    else return(stdz);
+}
+
+void
+caldat(double jdin, struct date_time* date, short *dow) {
+
+    /* from Jean Meeus, Astronomical Formulae for Calculators,
+       published by Willman-Bell Inc.
+       Avoids a copyrighted routine from Numerical Recipes.
+       Tested and works properly from the beginning of the 
+       Gregorian calendar era (1583) to beyond 3000 AD. */
+
+    double jdtmp;
+    long alpha;
+    long Z;
+    long A, B, C, D, E;
+    double F; 
+    double x;   /* for day-of-week calculation */
+
+    jdtmp = jdin + 0.5;
+
+    Z = (long) jdtmp;
+
+    x = Z/7.+0.01;
+    *dow = 7.*(x - (long) x);   /* truncate for day of week */
+
+    F = jdtmp - Z;
+
+    if(Z < 2299161) A = Z;
+    else {
+        alpha = (long) ((Z - 1867216.25) / 36524.25);
+        A = Z + 1 + alpha - (long) (alpha / 4);
+    }
+
+    B = A + 1524;
+    C = ((B - 122.1) / 365.25);
+    D =  (365.25 * C);\
+    E =  ((B - D) / 30.6001);
+
+    date->d = B - D - (long)(30.6001 * E);
+    if(E < 13.5) date->mo = E - 1;
+    else date->mo = E - 13;
+    if(date->mo  > 2.5)  date->y = C - 4716;
+    else date->y = C - 4715;
+	
+    date->h = F * 24.;  /* truncate */
+    date->mn = (F - ((float) date->h)/24.) * 1440.;
+    date->s = (F - ((float) date->h)/24. -
+               ((float) date->mn)/1440.) * 86400;
+	
+}
+
+short
+day_of_week(double jd) { 
+
+    /* returns day of week for a jd, 0 = Mon, 6 = Sun. */
+    
+    double x;
+    long i;
+    short d;
+    
+    jd = jd+0.5;
+    i = jd; /* truncate */
+    x = i/7.+0.01; 
+    d = 7.*(x - (long) x);   /* truncate */
+    return(d);
+}
+
+double
+day_of_year(double jd) {
+    
+    double jdjan0;
+    struct date_time date;
+    short dow;
+    
+    caldat(jd,&date,&dow);
+    /* find jd of "jan 0" = Dec 31 of previous year */
+    date.y = date.y - 1;
+    date.mo = 12;
+    date.d = 31;
+    date.h = 0;
+    date.mn = 0;
+    date.s = 0.;
+    jdjan0 = date_to_jd(date);
+    return(jd - jdjan0);
+}
+
+void
+find_dst_bounds(short yr, double stdz, short use_dst,
+                double *jdb, double* jde) {
+    
+	/* finds jd's at which daylight savings time begins 
+	    and ends.  The parameter use_dst allows for a number
+	    of conventions, namely:
+		0 = don't use it at all (standard time all the time)
+		1 = use USA convention (1st Sun in April to
+		     last Sun in Oct after 1986; last Sun in April before)
+		2 = use Spanish convention (for Canary Islands)
+		-1 = use Chilean convention (CTIO).
+		-2 = Australian convention (for AAT).
+	    Negative numbers denote sites in the southern hemisphere,
+	    where jdb and jde are beginning and end of STANDARD time for
+	    the year. 
+	    It's assumed that the time changes at 2AM local time; so
+	    when clock is set ahead, time jumps suddenly from 2 to 3,
+	    and when time is set back, the hour from 1 to 2 AM local 
+	    time is repeated.  This could be changed in code if need be. */
+
+	struct date_time trial;
+
+	if((use_dst == 1) || (use_dst == 0)) { 
+	    /* USA Convention, and including no DST to be defensive */
+	    /* Note that this ignores various wrinkles such as the
+		brief Nixon administration flirtation with year-round DST,
+		the extended DST of WW II, and so on. */
+		trial.y = yr;
+		trial.mo = 4;
+		if(yr >= 1986) trial.d = 1;
+		else trial.d = 30; 
+		trial.h = 2;
+		trial.mn = 0;
+		trial.s = 0;
+
+		/* Find first Sunday in April for 1986 on ... */
+		if(yr >= 1986) 
+			while(day_of_week(date_to_jd(trial)) != 6) 
+				trial.d++;
+			
+		/* Find last Sunday in April for pre-1986 .... */
+		else while(day_of_week(date_to_jd(trial)) != 6) 
+				trial.d--;
+
+		*jdb = date_to_jd(trial) + stdz/24.;    
+
+		/* Find last Sunday in October ... */
+		trial.mo = 10;
+		trial.d = 31;
+		while(day_of_week(date_to_jd(trial)) != 6) {
+			trial.d--;
+		}
+		*jde = date_to_jd(trial) + (stdz - 1.)/24.;             
+	}
+	else if (use_dst == 2) {  /* Spanish, for Canaries */
+		trial.y = yr;
+		trial.mo = 3;
+		trial.d = 31; 
+		trial.h = 2;
+		trial.mn = 0;
+		trial.s = 0;
+
+		while(day_of_week(date_to_jd(trial)) != 6) {
+			trial.d--;
+		}
+		*jdb = date_to_jd(trial) + stdz/24.;    
+		trial.mo = 9;
+		trial.d = 30;
+		while(day_of_week(date_to_jd(trial)) != 6) {
+			trial.d--;
+		}
+		*jde = date_to_jd(trial) + (stdz - 1.)/24.;             
+	}               
+	else if (use_dst == -1) {  /* Chilean, for CTIO, etc.  */
+	   /* off daylight 2nd Sun in March, onto daylight 2nd Sun in October */
+		trial.y = yr;
+		trial.mo = 3;
+		trial.d = 8;  /* earliest possible 2nd Sunday */
+		trial.h = 2;
+		trial.mn = 0;
+		trial.s = 0;
+
+		while(day_of_week(date_to_jd(trial)) != 6) {
+			trial.d++;
+		}
+		*jdb = date_to_jd(trial) + (stdz - 1.)/24.;
+			/* note jdb is beginning of STANDARD time in south,
+				hence use stdz - 1. */  
+		trial.mo = 10;
+		trial.d = 8;
+		while(day_of_week(date_to_jd(trial)) != 6) {
+			trial.d++;
+		}
+		*jde = date_to_jd(trial) + stdz /24.;           
+	}                       
+	else if (use_dst == -2) {  /* For Anglo-Australian Telescope  */
+	   /* off daylight 1st Sun in March, onto daylight last Sun in October */
+		trial.y = yr;
+		trial.mo = 3;
+		trial.d = 1;  /* earliest possible 1st Sunday */
+		trial.h = 2;
+		trial.mn = 0;
+		trial.s = 0;
+
+		while(day_of_week(date_to_jd(trial)) != 6) {
+			trial.d++;
+		}
+		*jdb = date_to_jd(trial) + (stdz - 1.)/24.;
+			/* note jdb is beginning of STANDARD time in south,
+				hence use stdz - 1. */  
+		trial.mo = 10;
+		trial.d = 31;
+		while(day_of_week(date_to_jd(trial)) != 6) {
+			trial.d--;
+		}
+		*jde = date_to_jd(trial) + stdz /24.;           
+	}               
+}
+
+int
+get_sys_date(struct date_time *date, short use_dst, short enter_ut,
+             short night_date, double stdz, double toffset, double* jd) {
+
+    /* Reads the system clock; loads up the date structure
+       to conform to the prevailing conventions for the interpretation
+       of times.  Optionally adds "toffset" minutes to the system
+       clock, as in x minutes in the future. */
+
+    time_t t, *tp;
+    struct tm *stm;
+    double jdb, jde;
+    short dow;
+
+    tp = &t;  /* have to initialize pointer variable for it to
+                 serve as an argument. */
+
+    t = time(tp);
+    if(t == -1) {
+        printf("error: system time unavailable during calculation of moon interference\n");
+        return(-1);
+    }
+    stm = localtime(&t);
+    date->y = (short) (stm->tm_year + 1900);
+    date->mo = (short) (stm->tm_mon + 1);
+    date->d = (short) (stm->tm_mday);
+    date->h = (short) (stm->tm_hour);
+    date->mn = (short) (stm->tm_min);
+    date->s = (float) (stm->tm_sec);
+
+    if(toffset != 0.) {
+        *jd = date_to_jd(*date);
+        *jd = *jd + toffset / 1440.;
+        caldat(*jd,date,&dow);
+    }
+
+    if(enter_ut == 1)  { /* adjust if needed */
+        find_dst_bounds(date->y,stdz,use_dst,&jdb,&jde);
+        *jd = date_to_jd(*date);
+        *jd = *jd + zone(use_dst,stdz,*jd,jdb,jde)/24.;
+        caldat(*jd,date,&dow);
+    }
+    if((night_date == 1) && (date->h < 12)) {
+        date->d = date->d - 1;
+    }
+
+    return(0); /* success */
+}
+
+double
+lst(double jd, double longit) {
+
+    /* returns the local MEAN sidereal time (dec hrs) at julian date jd
+       at west longitude long (decimal hours).  Follows
+       definitions in 1992 Astronomical Almanac, pp. B7 and L2. 
+       Expression for GMST at 0h ut referenced to Aoki et al, A&A 105,
+       p.359, 1982.  On workstations, accuracy (numerical only!)
+       is about a millisecond in the 1990s. */
+
+    double t, ut, jdmid, jdint, jdfrac, sid_g;
+    long jdin, sid_int;
+
+    jdin = jd;         /* fossil code from earlier package which 
+                          split jd into integer and fractional parts ... */
+    jdint = jdin;
+    jdfrac = jd - jdint;
+    if(jdfrac < 0.5) {
+        jdmid = jdint - 0.5;
+        ut = jdfrac + 0.5;
+    }
+    else {
+        jdmid = jdint + 0.5;
+        ut = jdfrac - 0.5;
+    }
+    t = (jdmid - J2000)/36525;
+    sid_g = (24110.54841+8640184.812866*t+0.093104*t*t-6.2e-6*t*t*t)/SEC_IN_DAY;
+    sid_int = sid_g;
+    sid_g = sid_g - (double) sid_int;
+    sid_g = sid_g + 1.0027379093 * ut - longit/24.;
+    sid_int = sid_g;
+    sid_g = (sid_g - (double) sid_int) * 24.;
+    if(sid_g < 0.) sid_g = sid_g + 24.;
+    return(sid_g);
+}
+
+
+double
+date_to_jd(struct date_time date) {
+    
+/* From Meeus' Astronomical Formulae for Calculators.  The two JD
+   conversion routines routines were replaced 1998 November 29 to
+   avoid inclusion of copyrighted "Numerical Recipes" code.  A test
+   of 1 million random JDs between 1585 and 3200 AD gave the same
+   conversions as the NR routines. */
+
+
+    double jd;
+    int y, m;
+    long A, B;
+
+    if(date.mo <= 2) {
+        y = date.y - 1;
+        m = date.mo + 12;
+    }
+    else {
+        y = date.y;
+        m = date.mo;
+    }
+
+    A = (long) (y / 100.);
+    B = 2 - A + (long) (A / 4.);
+
+    jd = (long) (365.25 * y) + (long) (30.6001 * (m + 1)) + date.d + 
+        1720994.5;
+
+    jd += date.h / 24. + date.mn / 1440. + date.s / 86400.;
+
+    if(date.y > 1583) return(jd + B);  
+    else return(jd);
+    /* Not quite right, since Gregorian calendar first
+       adopted around Oct 1582.  But fine for modern. */
+}
+
+void
+lpmoon(double jd, double lat, double sid,
+       double* ra, double* dec, double* dist) {
+
+
+/* implements "low precision" moon algorithms from
+   Astronomical Almanac (p. D46 in 1992 version).  Does
+   apply the topocentric correction. 
+   Units are as follows
+   jd,lat, sid;   decimal hours 
+   *ra, *dec,   decimal hours, degrees 
+   *dist;      earth radii */
+
+
+    double T, lambda, beta, pie, l, m, n, x, y, z, alpha, delta,
+        rad_lat, rad_lst, distance, topo_dist;
+    char dummy[40];  /* to fix compiler bug on IBM system */
+
+    T = (jd - J2000) / 36525.;  /* jul cent. since J2000.0 */
+
+    lambda = 218.32 + 481267.883 * T 
+        + 6.29 * sin((134.9 + 477198.85 * T) / DEG_IN_RADIAN)
+        - 1.27 * sin((259.2 - 413335.38 * T) / DEG_IN_RADIAN)
+        + 0.66 * sin((235.7 + 890534.23 * T) / DEG_IN_RADIAN)
+        + 0.21 * sin((269.9 + 954397.70 * T) / DEG_IN_RADIAN)
+        - 0.19 * sin((357.5 + 35999.05 * T) / DEG_IN_RADIAN)
+        - 0.11 * sin((186.6 + 966404.05 * T) / DEG_IN_RADIAN);
+    lambda = lambda / DEG_IN_RADIAN;
+    beta = 5.13 * sin((93.3 + 483202.03 * T) / DEG_IN_RADIAN)
+        + 0.28 * sin((228.2 + 960400.87 * T) / DEG_IN_RADIAN)
+        - 0.28 * sin((318.3 + 6003.18 * T) / DEG_IN_RADIAN)
+        - 0.17 * sin((217.6 - 407332.20 * T) / DEG_IN_RADIAN);
+    beta = beta / DEG_IN_RADIAN;
+    pie = 0.9508 
+        + 0.0518 * cos((134.9 + 477198.85 * T) / DEG_IN_RADIAN)
+        + 0.0095 * cos((259.2 - 413335.38 * T) / DEG_IN_RADIAN)
+        + 0.0078 * cos((235.7 + 890534.23 * T) / DEG_IN_RADIAN)
+        + 0.0028 * cos((269.9 + 954397.70 * T) / DEG_IN_RADIAN);
+    pie = pie / DEG_IN_RADIAN;
+    distance = 1 / sin(pie);
+
+    l = cos(beta) * cos(lambda);
+    m = 0.9175 * cos(beta) * sin(lambda) - 0.3978 * sin(beta);
+    n = 0.3978 * cos(beta) * sin(lambda) + 0.9175 * sin(beta);
+
+    x = l * distance; 
+    y = m * distance; 
+    z = n * distance;  /* for topocentric correction */
+
+
+    /* lat isn't passed right on some IBM systems unless you do this
+       or something like it! */
+    sprintf(dummy,"%f",lat);
+
+    rad_lat = lat / DEG_IN_RADIAN;
+    rad_lst = sid / HRS_IN_RADIAN;
+
+    x = x - cos(rad_lat) * cos(rad_lst);
+    y = y - cos(rad_lat) * sin(rad_lst);
+    z = z - sin(rad_lat);
+
+
+    topo_dist = sqrt(x * x + y * y + z * z);
+
+    l = x / topo_dist; 
+    m = y / topo_dist; 
+    n = z / topo_dist;
+
+    alpha = atan_circ(l,m);
+    delta = asin(n);
+
+    *ra = alpha * HRS_IN_RADIAN;
+
+    *dec = delta * DEG_IN_RADIAN;
+    
+    *dist = topo_dist;
+
+}
+
+
+void
+put_coords(double deci, int precision, int showsign) {
+
+
+/* prints out a struct coord in a nice format; precision
+   is a code for how accurate you want it.  The options are:
+     precision = 0;   minutes rounded to the nearest minute
+     precision = 1;   minutes rounded to the nearest tenth.
+     precision = 2;   seconds rounded to the nearest second
+     precision = 3;   seconds given to the tenth
+     precision = 4;   seconds given to the hundredth
+   The program assumes that the line is ready for the coord
+   to be printed and does NOT deliver a new line at the end
+   of the output. */
+
+   
+   double minutes;  /* for rounding off if necess. */
+   struct coord out_coord, coords;
+   char out_string[20];  /* for checking for nasty 60's */
+
+   dec_to_bab(deci,&coords);  /* internally convert to coords*/
+
+   if(coords.sign == -1) printf("-");
+	else printf(" "); /* to preserve alignment */
+
+   if(precision == 0) {   /* round to nearest minute */
+      minutes = coords.mm + coords.ss / 60.;
+           /* check to be sure minutes aren't 60 */
+      sprintf(out_string,"%.0f %02.0f",coords.hh,minutes);
+      sscanf(out_string,"%lf %lf",&out_coord.hh,&out_coord.mm);
+      if(fabs(out_coord.mm - 60.) < 1.0e-7) {
+         out_coord.mm = 0.;
+         out_coord.hh = out_coord.hh + 1.;
+      }
+      printf("%2.0f:%02.0f",out_coord.hh,out_coord.mm);
+   }
+
+   else if(precision == 1) {    /* keep nearest tenth of a minute */
+      minutes = coords.mm + coords.ss / 60.;
+           /* check to be sure minutes are not 60 */
+      sprintf(out_string,"%.0f %04.1f",coords.hh,minutes);
+      sscanf(out_string,"%lf %lf",&out_coord.hh, &out_coord.mm);
+      if(fabs(out_coord.mm - 60.) < 1.0e-7) {
+         out_coord.mm = 0.;
+         out_coord.hh = out_coord.hh + 1.;
+      }
+      printf("%2.0f:%04.1f", out_coord.hh, out_coord.mm);
+   }
+   else if(precision == 2) {
+          /* check to be sure seconds are not 60 */
+      sprintf(out_string,"%.0f %02.0f %02.0f",coords.hh,coords.mm,coords.ss);
+      sscanf(out_string,"%lf %lf %lf",&out_coord.hh,&out_coord.mm,
+           &out_coord.ss);
+      if(fabs(out_coord.ss - 60.) < 1.0e-7) {
+          out_coord.mm = out_coord.mm + 1.;
+          out_coord.ss = 0.;
+          if(fabs(out_coord.mm - 60.) < 1.0e-7) {
+              out_coord.hh = out_coord.hh + 1.;
+              out_coord.mm = 0.;
+          }
+      }
+      printf("%2.0f:%02.0f:%02.0f",out_coord.hh,out_coord.mm,out_coord.ss);
+   }
+   else if(precision == 3) {
+          /* the usual shuffle to check for 60's */
+      sprintf(out_string,"%.0f %02.0f %04.1f",coords.hh, coords.mm, coords.ss);
+      sscanf(out_string,"%lf %lf %lf",&out_coord.hh,&out_coord.mm,
+           &out_coord.ss);
+      if(fabs(out_coord.ss - 60.) < 1.0e-7) {
+          out_coord.mm = out_coord.mm + 1.;
+          out_coord.ss = 0.;
+          if(fabs(out_coord.mm - 60.) < 1.0e-7) {
+             out_coord.hh = out_coord.hh + 1.;
+             out_coord.mm = 0.;
+          }
+      }
+      printf("%2.0f:%02.0f:%04.1f",out_coord.hh,out_coord.mm,out_coord.ss);
+   }
+   else {
+      sprintf(out_string,"%.0f %02.0f %05.2f",coords.hh,coords.mm,coords.ss);
+      sscanf(out_string,"%lf %lf %lf",&out_coord.hh,&out_coord.mm,
+           &out_coord.ss);
+      if(fabs(out_coord.ss - 60.) < 1.0e-6) {
+         out_coord.mm = out_coord.mm + 1.;
+         out_coord.ss = 0.;
+         if(fabs(out_coord.mm - 60.) < 1.0e-6) {
+            out_coord.hh = out_coord.hh + 1.;
+            out_coord.mm = 0.;
+         }
+      }
+      printf("%2.0f:%02.0f:%05.2f",out_coord.hh, out_coord.mm, out_coord.ss);
+   }
+}
+
+
+double
+get_coord(void) {
+
+/* Reads a string from the terminal and converts it into
+   a double-precision coordinate.  This is trickier than 
+   it appeared at first, since a -00 tests as non-negative; 
+   the sign has to be picked out and handled explicitly. */
+/* Prompt for input in the calling routine.*/
+
+   short sign;
+   double hrs, mins, secs;
+   char hh_string[6];  /* string with the first coord (hh) */
+   char hh1[1];
+   short i = 0;
+
+   /* read and handle the hour (or degree) part with sign */
+
+   scanf("%s",hh_string);
+   hh1[0] = hh_string[i];
+
+   while(hh1[0] == ' ') {
+       /* discard leading blanks */
+       i++;
+       hh1[0] = hh_string[i];
+   }
+
+   if(hh1[0] == '-') sign = -1;
+
+     else sign = 1;
+
+   sscanf(hh_string,"%lf", &hrs);
+   if(sign == -1) hrs = -1. * hrs;
+
+   /* read in the minutes and seconds normally */
+   scanf("%lf %lf",&mins,&secs);
+
+   return(sign * (hrs + mins / 60. + secs / 3600.));
+}
+
+void
+dec_to_bab (double deci, struct coord* bab) {
+
+    /* function for converting decimal to babylonian hh mm ss.ss */
+    int hr_int, min_int;
+    
+    if (deci >= 0.) bab->sign = 1; 
+    else {
+        bab->sign = -1;
+        deci = -1. * deci;
+    }
+    hr_int = deci;   /* use conversion conventions to truncate */
+    bab->hh = hr_int;
+    min_int = 60. * (deci - bab->hh);
+    bab->mm = min_int;
+    bab->ss = 3600. * (deci - bab->hh - bab->mm / 60.);
+}
+
+double
+atan_circ(double x, double y) {
+    
+    /* returns radian angle 0 to 2pi for coords x, y --
+       get that quadrant right !! */
+    
+    double theta;
+    
+    if((x == 0.) && (y == 0.)) return(0.);  /* guard ... */
+    
+    theta = atan2(y,x);  /* turns out there is such a thing in math.h */
+    while(theta < 0.) theta += TWOPI;
+    return(theta);
+}
+
+
+double
+adj_time(double x) {
+
+    /* adjusts a time (decimal hours) to be between -12 and 12, 
+       generally used for hour angles.  */
+    
+    if(fabs(x) < 100000.) {  /* too inefficient for this! */
+        while(x > 12.) {
+            x = x - 24.;
+        }
+        while(x < -12.) {
+            x = x + 24.;
+        }
+    }
+
+    else printf("warning: Out of bounds in adj_time in moon interference routine!\n");
+
+    return(x);
+}
+
+double
+altit(double dec, double ha, double lat,
+      double* az, double *parang) {
+            
+/*
+  returns altitude(degr) for dec, ha, lat (decimal degr, hr, degr); 
+  also computes and returns azimuth through pointer argument,
+  and as an extra added bonus returns parallactic angle (decimal degr)
+  through another pointer argument.
+  */
+
+    double x,y,z;
+    double sinp, cosp;  /* sin and cos of parallactic angle */
+    double cosdec, sindec, cosha, sinha, coslat, sinlat;
+    /* time-savers ... */
+    
+    dec = dec / DEG_IN_RADIAN;
+    ha = ha / HRS_IN_RADIAN;
+    lat = lat / DEG_IN_RADIAN;  /* thank heavens for pass-by-value */
+    cosdec = cos(dec); sindec = sin(dec);
+    cosha = cos(ha); sinha = sin(ha);
+    coslat = cos(lat); sinlat = sin(lat);
+    x = DEG_IN_RADIAN * asin(cosdec*cosha*coslat + sindec*sinlat);
+    y =  sindec*coslat - cosdec*cosha*sinlat; /* due N comp. */
+    z =  -1. * cosdec*sinha; /* due east comp. */
+    *az = atan2(z,y);   
+    
+    /* as it turns out, having knowledge of the altitude and 
+       azimuth makes the spherical trig of the parallactic angle
+       less ambiguous ... so do it here!  Method uses the 
+       "astronomical triangle" connecting celestial pole, object,
+       and zenith ... now know all the other sides and angles,
+       so we can crush it ... */
+    
+    if(cosdec != 0.) { /* protect divide by zero ... */ 
+        sinp = -1. * sin(*az) * coslat / cosdec;
+        /* spherical law of sines .. note cosdec = sin of codec,
+           coslat = sin of colat .... */
+        cosp = -1. * cos(*az) * cosha - sin(*az) * sinha * sinlat;
+        /* spherical law of cosines ... also transformed to local
+           available variables. */
+	   *parang = atan2(sinp,cosp) * DEG_IN_RADIAN;
+           /* let the library function find the quadrant ... */
+    }
+    else { /* you're on the pole */
+        if(lat >= 0.) *parang = 180.;
+        else *parang = 0.;
+    }
+    
+    *az *= DEG_IN_RADIAN;  /* done with taking trig functions of it ... */ 
+    while(*az < 0.) *az += 360.;  /* force 0 -> 360 */
+    while(*az >= 360.) *az -= 360.;
+    
+    return(x);
+}
+
+
+int
+main(void) {
+
+    /* Site specific parameters */
+    double longit, lat;
+    double stdz;
+    short use_dst;
+    char zabr;
+    double elevsea;
+    double elev, horiz;
+
+    char site_name[45];  /* initialized later with
+                            strcpy for portability */
+    char zone_name[25];  /* this too */
+
+    struct date_time date;
+    double jd, sid;    
+
+    /* Position of moon */    
+    double ra, dec, dist;    
+    double ha, az, par, alt;    
+    
+    /* Misc stuff */
+    short enter_ut = 1;
+    short night_date = 0;
+    
+    /* Load site specific information */
+    load_site(&longit,&lat,&stdz,&use_dst,zone_name,&zabr,
+          &elevsea,&elev,&horiz,site_name);
+
+    /* Get system date and calculate julian date */
+    if (get_sys_date(&date, use_dst, enter_ut, night_date, stdz,
+                     update_delta, &jd) != 0) { 
+        printf("error: Can't get system date! \n");
+        return(-1);
+    }
+
+    /* Calcualte local sidereal time */
+    sid = lst(jd, longit);
+
+    /* Calculate position of moon */
+    lpmoon(jd, lat, sid, &ra, &dec, &dist);
+
+    ha = adj_time(sid - ra);
+    
+    alt=altit(dec, ha, lat, &az, &par);
+
+    /* Debug section
+      printf("moon ra = ");    
+      put_coords(ra, 2, 1);    
+      printf("\n"); 
+      printf("moon dec = ");  
+      put_coords(dec, 2, 1); 
+      printf("\n");
+      printf("moon ha = "); 
+      put_coords(ha, 2, 1); 
+      printf("\n");
+      printf("moon altitude = %.2f\n", alt); 
+      printf("moon zenith-distance = %.2f\n", 90 - alt);    
+      */
+      
+    /* Calculation of where to move */
+    /* If zenith distance is within 40 degrees then we move.
+       In order to do so the following logic will be applied:
+
+       1) Is zenith distance within 40 degrees (inclusive)
+       2) If so:
+             if dec > 20 then
+                move dec by -40
+             else
+                move dec by +40        
+          
+    */                      
+
+    if (fabs(90.0 - alt) <= 40) {
+        double adj_dec;        
+        /* Zenith distance within 40 degress */        
+        if (dec > lat) {
+            adj_dec = dec - 40.0;                              
+        }
+        else {
+            adj_dec = dec + 40.0;                     
+        }
+        printf("TRUE ");
+        put_coords(adj_dec, 2, 1);
+        printf("\n");    
+    }
+    else {
+        printf("FALSE\n");        
+    }
+    
+    return(0);    
+    
+}
+
+
Index: /tags/start/Ohana/src/skycalc/src/moondata.c
===================================================================
--- /tags/start/Ohana/src/skycalc/src/moondata.c	(revision 12606)
+++ /tags/start/Ohana/src/skycalc/src/moondata.c	(revision 12606)
@@ -0,0 +1,81 @@
+# include <stdio.h>
+# include <math.h>
+# include <skycalc_internal.h>
+
+# define DEG_RAD 57.295779513082322
+# define RAD_DEG  0.017453292519943
+
+double atof();
+
+void set_site (double *longit, double *lat, double *elevsea, double *elev) {
+
+  *longit = 10.36478; /*  W longitude in decimal hours */                     
+  *lat = 19.8267;     /*  N latitude in decimal degrees */                    
+  *elevsea = 4215.;   /* elevation above sea level (for absolute location) */ 
+  *elev = 4215.;      /* observatory elevation above horizon, meters */       
+
+}
+
+main (int argc, char **argv) {
+
+  struct SC_date_time date, tmpdate;
+  double longit, lat, elevsea, elev;
+  double jdnow, ra, dec, sid;
+  double geora, geodec, geodist, dist;
+  double RAo, DECo, abx, aby, abz, cs, theta;
+  double Rsun, Dsun, days;
+  unsigned long int tzero;
+  struct tm *stm;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: moondata (date) (ra) (dec) [ra & dec in dec. deg.]\n");
+    exit (1);
+  }
+
+  RAo = atof (argv[2]);
+  DECo = atof (argv[3]);
+
+  if (!str_to_time (argv[1], &tzero)) { 
+    fprintf (stderr, "syntax error\n");
+    exit (1);
+  }
+  stm = gmtime (&tzero);
+  date.y  = (short) (stm->tm_year + 1900);
+  date.mo = (short) (stm->tm_mon + 1);
+  date.d  = (short) (stm->tm_mday);
+  date.h  = (short) (stm->tm_hour);
+  date.mn = (short) (stm->tm_min);
+  date.s  = (float) (stm->tm_sec);
+
+  /*
+  fprintf (stderr, "%4d/%02d/%02d %02d:%02d:%02f\n", date.y, date.mo, date.d, date.h, date.mn, date.s);
+  */
+
+  set_site (&longit, &lat, &elevsea, &elev);
+  jdnow  = date_to_jd (date);
+  /* Calcualte local sidereal time */
+  sid = lst(jdnow, longit);
+  lpsun (jdnow, &Rsun, &Dsun);
+
+  accumoon(jdnow,lat,sid,elevsea,&geora,&geodec,&geodist,&ra,&dec,&dist);
+
+  /*  fprintf (stdout, "moon @ %f %f\n", 15*ra, dec); */
+
+  abx = cos(RAo*RAD_DEG)*cos(DECo*RAD_DEG)*cos(15*ra*RAD_DEG)*cos(dec*RAD_DEG);
+  aby = sin(RAo*RAD_DEG)*cos(DECo*RAD_DEG)*sin(15*ra*RAD_DEG)*cos(dec*RAD_DEG);
+  abz = sin(DECo*RAD_DEG)*sin(dec*RAD_DEG);
+
+  cs = abx + aby + abz;
+  
+  theta = DEG_RAD * acos (cs);
+
+  days = (Rsun - ra - 12)/24.0;
+  while (days < -0.5) days += 1.0;
+  while (days >  0.5) days -= 1.0;
+  days *= 29.5;
+
+  fprintf (stdout, "moon @ %f %f dist %f %f days from full\n", 15*ra, dec, theta, days);
+  exit (0);
+
+}
+
Index: /tags/start/Ohana/src/skycalc/src/skylib.c
===================================================================
--- /tags/start/Ohana/src/skycalc/src/skylib.c	(revision 12606)
+++ /tags/start/Ohana/src/skycalc/src/skylib.c	(revision 12606)
@@ -0,0 +1,48 @@
+# include <stdio.h>
+# include <math.h>
+# include <skycalc.h>
+
+void set_site (double *longit, double *lat, double *elevsea, double *elev) {
+
+  *longit = 10.36478; /*  W longitude in decimal hours */                     
+  *lat = 19.8267;     /*  N latitude in decimal degrees */                    
+  *elevsea = 4215.;   /* elevation above sea level (for absolute location) */ 
+  *elev = 4215.;      /* observatory elevation above horizon, meters */       
+
+}
+
+main()
+
+{
+
+  struct SC_date_time date, tmpdate;
+  double longit, lat, elevsea, elev;
+  double jd;
+
+  set_site (&longit, &lat, &elevsea, &elev);
+  get_sys_date (&date);
+
+  jd = sunset_tonight (date, lat, longit, elev);
+  fprintf (stderr, "Sunset (%5.0f m horizon): %f\n", elev, jd);
+  jd_to_date (jd, &tmpdate);
+  fprintf (stderr, "%4d/%02d/%02d %02d:%02d:%02f\n", tmpdate.y, tmpdate.mo, tmpdate.d, tmpdate.h, tmpdate.mn, tmpdate.s);
+
+  jd = sunrise_tonight (date, lat, longit, elev);
+  fprintf (stderr, "Sunrise (%5.0f m horizon): %f\n", elev, jd);
+  jd_to_date (jd, &tmpdate);
+  fprintf (stderr, "%4d/%02d/%02d %02d:%02d:%02f\n", tmpdate.y, tmpdate.mo, tmpdate.d, tmpdate.h, tmpdate.mn, tmpdate.s);
+  
+
+  jd = moonset_tonight (date, lat, longit, elevsea, elev);
+  fprintf (stderr, "Moonset (%5.0f m horizon): %f\n", elev, jd);
+  jd_to_date (jd, &tmpdate);
+  fprintf (stderr, "%4d/%02d/%02d %02d:%02d:%02f\n", tmpdate.y, tmpdate.mo, tmpdate.d, tmpdate.h, tmpdate.mn, tmpdate.s);
+
+  jd = moonrise_tonight (date, lat, longit, elevsea, elev);
+  fprintf (stderr, "Moonrise (%5.0f m horizon): %f\n", elev, jd);
+  jd_to_date (jd, &tmpdate);
+  fprintf (stderr, "%4d/%02d/%02d %02d:%02d:%02f\n", tmpdate.y, tmpdate.mo, tmpdate.d, tmpdate.h, tmpdate.mn, tmpdate.s);
+
+}
+
+  /* set_zenith (date, lat, longit, objepoch, &objra, &objdec); */
Index: /tags/start/Ohana/src/skycalc/src/sun.c
===================================================================
--- /tags/start/Ohana/src/skycalc/src/sun.c	(revision 12606)
+++ /tags/start/Ohana/src/skycalc/src/sun.c	(revision 12606)
@@ -0,0 +1,157 @@
+# include <skycalc_internal.h>
+
+/* Low precision formulae for the sun, from Almanac p. C24 (1990) */
+/* ra and dec are returned as decimal hours and decimal degrees. */
+void lpsun (double jd, double *ra, double *dec) {
+
+  double n, L, g, lambda,epsilon,alpha,delta,x,y,z;
+
+  n = jd - J2000;
+  L = 280.460 + 0.9856474 * n;
+  g = (357.528 + 0.9856003 * n)/DEG_IN_RADIAN;
+  lambda = (L + 1.915 * sin(g) + 0.020 * sin(2. * g))/DEG_IN_RADIAN;
+  epsilon = (23.439 - 0.0000004 * n)/DEG_IN_RADIAN;
+
+  x = cos(lambda);
+  y = cos(epsilon) * sin(lambda);
+  z = sin(epsilon)*sin(lambda);
+
+  *ra = (atan_circ(x,y))*HRS_IN_RADIAN;
+  *dec = (asin(z))*DEG_IN_RADIAN;
+}
+
+/* returns jd at which sun is at a given
+   altitude, given jdguess as a starting point. Uses
+   low-precision sun, which is plenty good enough. */
+double jd_sun_alt (double alt, double jdguess, double lat, double longit) {
+
+  double jdout;
+  double deriv, err, del = 0.002;
+  double ra,dec,ha,alt2,alt3,az;
+  short i = 0;
+  
+  /* first guess */
+  
+  lpsun (jdguess, &ra, &dec);
+  ha = lst (jdguess,longit) - ra;
+  alt2 = altit (dec,ha,lat,&az);
+  jdguess = jdguess + del;
+  lpsun (jdguess,&ra,&dec);
+  alt3 = altit(dec,(lst(jdguess,longit) - ra),lat,&az);
+  err = alt3 - alt;
+  deriv = (alt3 - alt2) / del;
+  while((fabs(err) > 0.1) && (i < 10)) {
+    jdguess = jdguess - err/deriv;
+    lpsun(jdguess,&ra,&dec);
+    alt3 = altit(dec,(lst(jdguess,longit) - ra),lat,&az);
+    err = alt3 - alt;
+    i++;
+    if(i == 9) printf ("Sunrise, set, or twilight calculation not converging!\n");
+  }
+  if(i >= 9) jdguess = -1000.;
+  jdout = jdguess;
+  return(jdout);
+}
+
+/* Given site position, prints Sun info for the given night.
+/* dates are all in UT now */
+double sunset_tonight (struct SC_date_time date, double lat, double longit, double elev) {
+
+  double jd, jdmid0, jdmid, stmid;
+  double rasun, decsun, min_alt, max_alt, horiz;
+  double hasunset, jdsunset, jdsunrise, sid;
+  double dt, lst0, lst1, djd;
+  struct SC_date_time date_midnight, tmpdate;
+  short dow;
+
+  horiz = sqrt (2. * elev / 6378140.) * DEG_IN_RADIAN;
+
+  /* find offset in hours from longit to greenwich */
+  jd = date_to_jd (date);  /* true jd now */
+  lst0 = lst (jd, 0.0);    /* lst at long = 0 */
+  lst1 = lst (jd, longit); /* local lst now */
+  dt = lst0 - lst1;
+  if (dt < 0) dt += 24;
+	
+  /* midnight at greenwich */
+  date_midnight = date;
+  date_midnight.h = 0;
+  date_midnight.mn = 0;
+  date_midnight.s = 0;
+	
+  /* find jd for local midnight, select the *closest* midnight */
+  jdmid0 = date_to_jd (date_midnight);
+  jdmid = jdmid0 + dt / 24.0;
+  djd = jd - jdmid;
+  if (djd < -0.5) jdmid -= 1.0;
+  if (djd >  0.5) jdmid += 1.0;
+  stmid = lst (jdmid,longit); 
+
+  /* sunset / sunrise hour angle */
+  lpsun (jdmid, &rasun, &decsun);
+  hasunset = ha_alt (decsun, lat, -(0.83+horiz));
+  if(hasunset > 900.) {  /* flag for never sets */
+    return (-1);
+  }
+  if(hasunset < -900.) {
+    return (-1);
+  }
+
+  /* find sunset time */
+  jdsunset = jdmid + adj_time(rasun+hasunset-stmid)/24.;
+  jdsunset = jd_sun_alt (-(0.83+horiz),jdsunset,lat,longit);
+
+  return (jdsunset);
+
+}
+
+/* Given site position, prints Sun info for the given night.
+/* dates are all in UT now */
+double sunrise_tonight (struct SC_date_time date, double lat, double longit, double elev) {
+
+  double jd, jdmid, stmid;
+  double rasun, decsun, min_alt, max_alt, horiz;
+  double hasunset, jdsunset, jdsunrise, sid;
+  double dt, lst0, lst1, djd;
+  struct SC_date_time date_midnight, tmpdate;
+  short dow;
+
+  horiz = sqrt (2. * elev / 6378140.) * DEG_IN_RADIAN;
+
+  /* find offset in hours from longit to greenwich */
+  jd = date_to_jd (date);  /* true jd now */
+  lst0 = lst (jd, 0.0);    /* lst at long = 0 */
+  lst1 = lst (jd, longit); /* local lst now */
+  dt = lst0 - lst1;
+  if (dt < 0) dt += 24;
+	
+  /* midnight at greenwich */
+  date_midnight = date;
+  date_midnight.h = 0;
+  date_midnight.mn = 0;
+  date_midnight.s = 0;
+	
+  /* find jd for local midnight, select the *closest* midnight */
+  jdmid = date_to_jd (date_midnight) - dt / 24.0;
+  djd = jd - jdmid;
+  if (djd < -0.5) jdmid -= 1.0;
+  if (djd >  0.5) jdmid += 1.0;
+  stmid = lst (jdmid,longit); 
+
+  /* sunset / sunrise hour angle */
+  lpsun (jdmid, &rasun, &decsun);
+  hasunset = ha_alt (decsun, lat, -(0.83+horiz));
+  if(hasunset > 900.) {  /* flag for never sets */
+    return (-1);
+  }
+  if(hasunset < -900.) {
+    fprintf (stderr, "Sun down all day!\n");
+    return (-1);
+  }
+
+  /* find sunrise time */
+  jdsunrise = jdmid + adj_time(rasun-hasunset-stmid)/24.;
+  jdsunrise = jd_sun_alt(-(0.83+horiz),jdsunrise,lat,longit);
+
+  return (jdsunrise);
+}
Index: /tags/start/Ohana/src/skycalc/src/sundata.c
===================================================================
--- /tags/start/Ohana/src/skycalc/src/sundata.c	(revision 12606)
+++ /tags/start/Ohana/src/skycalc/src/sundata.c	(revision 12606)
@@ -0,0 +1,84 @@
+# include <stdio.h>
+# include <math.h>
+# include <skycalc_internal.h>
+
+# define DEG_RAD 57.295779513082322
+# define RAD_DEG  0.017453292519943
+# define dCOS(A)   ((double) cos ((double)RAD_DEG*A))
+# define dSIN(A)   ((double) sin ((double)RAD_DEG*A))
+
+double atof();
+
+void set_site (double *longit, double *lat, double *elevsea, double *elev) {
+
+  *longit = 10.36478; /*  W longitude in decimal hours */                     
+  *lat = 19.8267;     /*  N latitude in decimal degrees */                    
+  *elevsea = 4215.;   /* elevation above sea level (for absolute location) */ 
+  *elev = 4215.;      /* observatory elevation above horizon, meters */       
+
+}
+
+main (int argc, char **argv) {
+
+  struct SC_date_time date, tmpdate;
+  double longit, lat, elevsea, elev;
+  double jdnow, ra, dec, sid, alt, az, sind, sinh, cosh;
+  double geora, geodec, geodist, dist;
+  double RAo, DECo, abx, aby, abz, cs, theta;
+  double Rsun, Dsun, days, Hsun;
+  unsigned long int tzero;
+  struct tm *stm;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: sundata (date) (ra) (dec) [ra & dec in dec. deg.]\n");
+    exit (1);
+  }
+
+  RAo = atof (argv[2]);
+  DECo = atof (argv[3]);
+
+  if (!str_to_time (argv[1], &tzero)) { 
+    fprintf (stderr, "syntax error\n");
+    exit (1);
+  }
+  stm = gmtime (&tzero);
+  date.y  = (short) (stm->tm_year + 1900);
+  date.mo = (short) (stm->tm_mon + 1);
+  date.d  = (short) (stm->tm_mday);
+  date.h  = (short) (stm->tm_hour);
+  date.mn = (short) (stm->tm_min);
+  date.s  = (float) (stm->tm_sec);
+
+  /*
+  fprintf (stderr, "%4d/%02d/%02d %02d:%02d:%02f\n", date.y, date.mo, date.d, date.h, date.mn, date.s);
+  */
+
+  set_site (&longit, &lat, &elevsea, &elev);
+  jdnow  = date_to_jd (date);
+
+  /* Calcualte local sidereal time */
+  sid = lst(jdnow, longit);
+  lpsun (jdnow, &Rsun, &Dsun);
+
+  /* dot product of unit vectors of (RAo,DECo) & (Rsun,Dsun) */
+  abx = dCOS(RAo)*dCOS(DECo)*dCOS(15*Rsun)*dCOS(Dsun);
+  aby = dSIN(RAo)*dCOS(DECo)*dSIN(15*Rsun)*dCOS(Dsun);
+  abz = dSIN(DECo)*dSIN(Dsun);
+  cs = abx + aby + abz;
+  theta = DEG_RAD * acos (cs);
+
+  /***** get sun altitude *****/
+  Hsun = 15.0*(sid - Rsun);
+ 
+  sind = dSIN (Dsun) * dSIN (lat) + dCOS (Dsun) * dCOS (Hsun) * dCOS (lat);
+  alt  = DEG_RAD * asin (sind);
+
+  sinh = - dCOS (Dsun) * dSIN (Hsun);
+  cosh =   dSIN (Dsun) * dCOS (lat) - dCOS (Dsun) * dCOS (Hsun) * dSIN (lat);
+  az = DEG_RAD * atan2 (sinh, cosh);
+
+  fprintf (stdout, "sun @ %f %f dist %f altaz: %f %f\n", 15*Rsun, Dsun, theta, alt, az);
+  exit (0);
+
+}
+
Index: /tags/start/Ohana/src/skycalc/src/time.c
===================================================================
--- /tags/start/Ohana/src/skycalc/src/time.c	(revision 12606)
+++ /tags/start/Ohana/src/skycalc/src/time.c	(revision 12606)
@@ -0,0 +1,148 @@
+# include <skycalc_internal.h>
+
+/* fill date structure with current date & time (UT) */
+int get_sys_date (struct SC_date_time *date) {
+
+  time_t t;
+  struct tm *stm;
+  double jd, jdb, jde;
+  short dow;
+  
+  t = time (0);
+  if (t == -1) return (-1);
+
+  stm = gmtime (&t);
+  date->y = (short) (stm->tm_year + 1900);
+  date->mo = (short) (stm->tm_mon + 1);
+  date->d = (short) (stm->tm_mday);
+  date->h = (short) (stm->tm_hour);
+  date->mn = (short) (stm->tm_min);
+  date->s = (float) (stm->tm_sec);
+
+  return (0); /* success */
+
+}
+
+/* convert a UT date to JD ( 1900 -- 2100?) */
+double date_to_jd (struct SC_date_time date) {
+  
+  short yr1=0, mo1=1;
+  long jdzpt = 1720982, jdint, inter;
+  double jd,jdfrac;
+  
+  if ((date.y <= 1900) | (date.y >= 2100)) return (0.0);
+  
+  if (date.mo <= 2) {
+    yr1 = -1;
+    mo1 = 13;
+  }
+  
+  jdint = 365.25*(date.y+yr1);  /* truncates */
+  inter = 30.6001*(date.mo+mo1);
+  jdint = jdint+inter+date.d+jdzpt;
+  jd = jdint;
+  jdfrac=date.h/24.+date.mn/1440.+date.s/SEC_IN_DAY;
+  if (jdfrac < 0.5) {
+    jdint--;
+    jdfrac=jdfrac+0.5;
+  }
+  else jdfrac=jdfrac-0.5;
+  jd = jdint+jdfrac;
+  return (jd);
+}
+
+/* convert JD to a UT date & time */
+void jd_to_date (double jdin, struct SC_date_time *date) {
+  
+#define IGREG 2299161
+
+  /* Adapted from Press, Flannery, Teukolsky, &
+     Vetterling, Numerical Recipes in C, (Cambridge
+     University Press), 1st edn, p. 12. */
+  
+  int mm, id, iyyy;  /* their notation */
+  long ja, jdint, jalpha, jb, jc, jd, je;
+  float jdfrac;
+  double x;
+
+  jdin = jdin + 0.5;  /* adjust for 1/2 day */
+  jdint = jdin;
+  x = jdint/7.+0.01;
+  jdfrac = jdin - jdint;
+  date->h = jdfrac * 24; /* truncate */
+  date->mn = (jdfrac - ((float) date->h)/24.) * 1440.;
+  date->s = (jdfrac - ((float) date->h)/24. -
+	     ((float) date->mn)/1440.) * SEC_IN_DAY;
+
+  if(jdint > IGREG) {
+    jalpha=((float) (jdint-1867216)-0.25)/36524.25;
+    ja=jdint+1+jalpha-(long)(0.25*jalpha);
+  }
+  else
+    ja=jdint;
+  jb=ja+1524;
+  jc=6680.0+((float) (jb-2439870)-122.1)/365.25;
+  jd=365*jc+(0.25*jc);
+  je=(jb-jd)/30.6001;
+  id=jb-jd-(int) (30.6001*je);
+  mm=je-1;
+  if(mm > 12) mm -= 12;
+  iyyy=jc-4715;
+  if(mm > 2) --iyyy;
+  if (iyyy <= 0) --iyyy;
+  date->y = iyyy;
+  date->mo = mm;
+  date->d = id;
+
+}
+
+
+/* returns the local MEAN sidereal time (dec hrs) at julian date jd
+   at west longitude long (decimal hours).  Follows
+   definitions in 1992 Astronomical Almanac, pp. B7 and L2.
+   Expression for GMST at 0h ut referenced to Aoki et al, A&A 105,
+   p.359, 1982.  On workstations, accuracy (numerical only!)
+   is about a millisecond in the 1990s. */
+double lst (double jd, double longit) {
+  
+  double t, ut, jdmid, jdint, jdfrac, sid_g, sid;
+  long sid_int;
+  
+  jdint = (int) jd;
+  jdfrac = jd - jdint;
+
+  if (jdfrac < 0.5) {
+    jdmid = jdint - 0.5;
+    ut = jdfrac + 0.5;
+  }
+  else {
+    jdmid = jdint + 0.5;
+    ut = jdfrac - 0.5;
+  }
+  t = (jdmid - J2000)/36525;
+  sid_g = (24110.54841+8640184.812866*t+0.093104*t*t-6.2e-6*t*t*t)/SEC_IN_DAY;
+  sid_int = sid_g;
+  sid_g = sid_g - (double) sid_int;
+  sid_g = sid_g + 1.0027379093 * ut - longit/24.;
+  sid_int = sid_g;
+  sid_g = (sid_g - (double) sid_int) * 24.;
+  if (sid_g < 0.) sid_g = sid_g + 24.;
+  return (sid_g);
+}
+
+/* force time domain to be -12h and 12h  */
+double adj_time (double x) {
+  
+  /* ridiculously inefficient - use modulo and fractions.. */
+  if(fabs(x) < 100000.) {  
+    while(x > 12.) {
+      x = x - 24.;
+    }
+    while(x < -12.) {
+      x = x + 24.;
+    }
+  }
+  else printf ("Out of bounds in adj_time!\n");
+  return(x);
+}
+
Index: /tags/start/Ohana/src/skyprobe/skyproberedccd
===================================================================
--- /tags/start/Ohana/src/skyprobe/skyproberedccd	(revision 12606)
+++ /tags/start/Ohana/src/skyprobe/skyproberedccd	(revision 12606)
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+echo " FLIPS - skyproberedccd (imred)"
+if [ $# -ne 2 ] ; then
+  echo " Process: single SkyProbe CCD image reduction with Dark & Flat-Field"
+  echo " Syntax:  skyproberedccd FILE_IN FILE_OUT"
+  exit 1
+fi
+
+# Check if INPUT FITS file exists
+if [ ! -f $1 ]; then
+   echo "FITS file '$1' (FILE_IN = 1st argument) does not exist"
+   exit 1
+fi
+
+# Create temporary parameter file name
+TEMP="/tmp/redccd$$"
+
+# Prepare parameter file
+cat ~skyprobe/.skyprobeimred.param.CCD | sed "s|INFILE|$1|"   | sed "s|OUTFILE|$2|" > $TEMP
+
+# Set a default size for the buffer height
+echo "BUFFER"                       >> $TEMP
+echo "        height          240"  >> $TEMP
+echo "        end"                  >> $TEMP
+# CPU type: for swap or not
+echo "CPU"                          >> $TEMP
+echo "        swap            1"    >> $TEMP
+echo "        end"                  >> $TEMP
+# Timing info flag
+echo "TIMING"                       >> $TEMP
+echo "        timing          1"    >> $TEMP
+echo "        end"                  >> $TEMP
+# End of the parfile
+echo "END"                          >> $TEMP
+
+# Combine files
+imred_lx $TEMP
+
+# Remove temporary file
+rm -f $TEMP
+rm -f imred-stat.dat
+
+exit 0
Index: /tags/start/Ohana/src/tcl/Makefile
===================================================================
--- /tags/start/Ohana/src/tcl/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/tcl/Makefile	(revision 12606)
@@ -0,0 +1,21 @@
+include ../../Configure
+HOME 	=	$(ROOT)/src/tcl
+
+DESTBIN	=	$(LBIN)
+
+tcl:
+
+default: install
+
+CODE =  edisp
+
+install:
+	for file in $(CODE); do \
+	(cd $(DESTBIN); rm -f $$file; ln -s $(HOME)/src/$$file .); \
+	done
+
+# utilities #################################################
+clean:	
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
Index: /tags/start/Ohana/src/tcl/src/edisp
===================================================================
--- /tags/start/Ohana/src/tcl/src/edisp	(revision 12606)
+++ /tags/start/Ohana/src/tcl/src/edisp	(revision 12606)
@@ -0,0 +1,217 @@
+#!/usr/bin/env wish
+
+# define three components to the window:
+
+# text line with data value
+# image region with image
+# quit button
+
+if [catch {exec /apps/elixir/bin/gconfig DATDIR} datdir] { 
+    set picpath "ERROR" 
+} else {
+    set picpath "$datdir/plots"
+}
+
+set imname "(empty)"
+set name "(empty)"
+set pid [pid]
+set index 0
+
+proc mk_layout { } {
+
+    global file lasttime picpath
+
+    set lasttime 0
+    if {$picpath == "ERROR"} {
+	set file "ERROR"
+    } else {
+	set file "$picpath/empty.gif"
+    }
+    wm withdraw .
+
+    set w [toplevel .t]
+    wm title .t "user display"
+    
+    # top level containers
+    frame $w.menubar -relief raised -borderwidth 2
+    frame $w.picture -relief raised -borderwidth 2
+    frame $w.dataline -relief raised -borderwidth 2
+
+    pack $w.menubar -fill x
+    pack $w.picture -fill x
+    pack $w.dataline -fill x
+
+    mk_menubar $w.menubar
+    mk_picture $w.picture
+    mk_dataline $w.dataline
+
+    update
+}
+
+proc do_quit {} {
+    
+    exit 
+
+}
+
+proc mk_picture {w} {
+
+    global file
+
+    if {$file == "ERROR"} {
+	label $w.name -text "Config Error: missing DATDIR"
+	pack  $w.name -side top -fill both
+    } else {
+	image create photo picture -file $file
+	label $w.name -image picture
+	pack  $w.name -side top -fill both
+    }
+}
+
+proc mk_menubar {w} {
+
+    global file picpath cycle
+
+    menubutton $w.file -text "File" -menu $w.file.menu
+    pack $w.file -side left
+
+    menu $w.file.menu -tearoff 0
+    $w.file.menu add command -label "Quit" -command { do_quit }
+    bind all <Alt-q> { do_quit }
+    bind all <Control-q> { do_quit }
+    
+    menubutton $w.plot -text "Plots" -menu $w.plot.menu
+    pack $w.plot -side left
+
+    label $w.label -text "$file"
+    pack $w.label -side right
+
+    menu $w.plot.menu -tearoff 0
+    $w.plot.menu add command -label "Cycle"           -command { set cycle 1 ; cycleImages }
+    $w.plot.menu add command -label "biases"          -command { set cycle 0 ; set file "$picpath/biases.gif"; refresh_now;  }
+    $w.plot.menu add command -label "skyprobe recent" -command { set cycle 0 ; set file "$picpath/skyprobe_recent.gif"; refresh_now;  }
+    $w.plot.menu add command -label "skyprobe night"  -command { set cycle 0 ; set file "$picpath/skyprobe_night.gif"; refresh_now;  }
+    $w.plot.menu add command -label "sky vs time"     -command { set cycle 0 ; set file "$picpath/sky.time.gif"; refresh_now;  }
+    $w.plot.menu add command -label "sky vs airmass"  -command { set cycle 0 ; set file "$picpath/sky.airmass.gif"; refresh_now;  }
+    $w.plot.menu add command -label "Recent Seeing"    -command { set cycle 0 ; set file "$picpath/seeing_recent.gif"; refresh_now;  }
+    $w.plot.menu add command -label "Night Seeing"    -command { set cycle 0 ; set file "$picpath/seeing_night.gif"; refresh_now;  }
+    $w.plot.menu add command -label "FWHM vs airmass" -command { set cycle 0 ; set file "$picpath/fwhm.airmass.gif"; refresh_now;  }
+    $w.plot.menu add command -label "field (small)"   -command { set cycle 0 ; set file "$picpath/field.small.gif"; refresh_now;  }
+    $w.plot.menu add command -label "field (large)"   -command { set cycle 0 ; set file "$picpath/field.large.gif"; refresh_now;  }
+    $w.plot.menu add command -label "temperatures"    -command { set cycle 0 ; set file "$picpath/temps.time.gif"; refresh_now;  }
+    $w.plot.menu add command -label "last image (10x10)"   -command { set cycle 0 ; set file "$picpath/current.b10.gif"; refresh_now;  }
+    $w.plot.menu add command -label "last image (zoom)"     -command { set cycle 0 ; set file "$picpath/current.zoom.gif"; refresh_now;  }
+    $w.plot.menu add command -label "last short image" -command { set cycle 0 ; set file "$picpath/lastshort.zoom.gif"; refresh_now;  }
+    $w.plot.menu add command -label "focus (unit)"     -command { set cycle 0 ; set file "$picpath/focus.unit.gif"; refresh_now;  }
+
+}
+
+proc mk_dataline {w} {
+
+    global fwhm imname name file
+    set time [clock format [clock seconds] -format "%H:%M:%S"]
+
+    label $w.label -text "name: $name  |  FHWM: 0.0  |  FILTER: X  |  time: $time            | image: $imname"
+    pack $w.label -fill x
+
+}
+
+proc cycleImages { } {
+
+    global file cycle picpath index
+
+    set images { skyprobe_recent.gif sky.time.gif seeing_recent.gif biases.gif temps.time.gif current.b10.gif current.zoom.gif lastshort.zoom.gif }
+
+
+    if { $cycle == 0 } { return }
+
+    set file "$picpath/[lindex $images $index]"
+    refresh_now
+
+    incr index
+    if { $index == [llength $images] } {
+	set index 0
+    }
+
+    after 30000 {
+	cycleImages
+    }
+}
+
+proc do_refresh { } {
+
+    global picpath imname name file
+
+    after 1000 {
+	
+	set time [clock format [clock seconds] -format "%H:%M:%S"]
+	set name "(empty)"
+	set fwhm 0.0
+	set filter "X"
+
+	if {! [catch {open $picpath/seeing.dat r} data] } {
+	    gets $data line
+	    close $data
+	    set list [split $line]
+	    if {[llength $list] == 4} {
+		set name [lindex $list 0]
+		catch { set fwhm [format "%5.2f" [lindex $list 1]] } status
+		set filter [lindex $list 3]
+            }
+	}
+	
+	.t.dataline.label configure -text "name: $name  |  FHWM: $fwhm  |  FILTER: $filter  |  time: $time           | image: $imname"
+	.t.menubar.label configure -text "file: $file"
+	update
+	do_refresh 
+    }
+}
+
+proc do_refresh_pic { } {
+
+    global file lasttime imname name pid
+
+    after 2000 {
+	
+	# get file status & time
+	if {! [catch {file stat $file stats}] } {
+	    set newtime $stats(mtime)
+	    if {$newtime > $lasttime} {
+		set tmpfile "$file.$pid"
+		catch { exec ln -f $file $tmpfile }
+		catch { picture read $tmpfile -shrink } 
+		catch { exec rm -f $tmpfile }
+		set imname $name
+		set lasttime $newtime
+		update
+	    }
+	}
+	do_refresh_pic
+    }
+}
+
+proc bgerror {result} {
+	puts "edisp error: $result"
+}
+
+proc refresh_now { } {
+
+    global file lasttime imname name pid
+
+    if {[file exists $file]} {
+	set tmpfile "$file.$pid"
+	catch { exec ln -f $file $tmpfile }
+	catch { picture read $tmpfile -shrink }
+	catch { exec rm -f $tmpfile }
+
+	file stat $file stats
+	set imname $name
+	set lasttime $stats(mtime)
+	update
+	
+    }
+}
+
+mk_layout
+do_refresh
+do_refresh_pic
Index: /tags/start/Ohana/src/tcl/src/edisp-1.0
===================================================================
--- /tags/start/Ohana/src/tcl/src/edisp-1.0	(revision 12606)
+++ /tags/start/Ohana/src/tcl/src/edisp-1.0	(revision 12606)
@@ -0,0 +1,175 @@
+#!/usr/bin/env wish
+
+# define three components to the window:
+
+# text line with data value
+# image region with image
+# quit button
+
+set picpath "/data/milo/elixir/plots"
+set imname "(empty)"
+set name "(empty)"
+set pid [pid]
+
+proc mk_layout { } {
+
+    global file lasttime picpath
+
+    set lasttime 0
+    set file "$picpath/empty.gif"
+    wm withdraw .
+
+    set w [toplevel .t]
+    wm title .t "user display"
+    
+    # top level containers
+    frame $w.menubar -relief raised -borderwidth 2
+    frame $w.picture -relief raised -borderwidth 2
+    frame $w.dataline -relief raised -borderwidth 2
+
+    pack $w.menubar -fill x
+    pack $w.picture -fill x
+    pack $w.dataline -fill x
+
+    mk_menubar $w.menubar
+    mk_picture $w.picture
+    mk_dataline $w.dataline
+
+    update
+}
+
+proc do_quit {} {
+    
+    exit 
+
+}
+
+proc mk_picture {w} {
+
+    global file
+
+    image create photo picture -file $file
+
+    label $w.name -image picture
+    pack  $w.name -side top -fill both
+}
+
+proc mk_menubar {w} {
+
+    global file picpath
+
+    menubutton $w.file -text "File" -menu $w.file.menu
+    pack $w.file -side left
+
+    menu $w.file.menu -tearoff 0
+    $w.file.menu add command -label "Quit" -command { do_quit }
+    bind all <Alt-q> { do_quit }
+    bind all <Control-q> { do_quit }
+    
+    menubutton $w.plot -text "Plots" -menu $w.plot.menu
+    pack $w.plot -side left
+
+    menu $w.plot.menu -tearoff 0
+    $w.plot.menu add command -label "biases"          -command { set file "$picpath/biases.gif"; refresh_now;  }
+    $w.plot.menu add command -label "skyprobe recent" -command { set file "$picpath/skyprobe_recent.gif"; refresh_now;  }
+    $w.plot.menu add command -label "skyprobe night"  -command { set file "$picpath/skyprobe_night.gif"; refresh_now;  }
+    $w.plot.menu add command -label "sky vs time"     -command { set file "$picpath/sky.time.gif"; refresh_now;  }
+    $w.plot.menu add command -label "sky vs airmass"  -command { set file "$picpath/sky.airmass.gif"; refresh_now;  }
+    $w.plot.menu add command -label "FWHM vs time"    -command { set file "$picpath/fwhm.time.gif"; refresh_now;  }
+    $w.plot.menu add command -label "FWHM vs airmass" -command { set file "$picpath/fwhm.airmass.gif"; refresh_now;  }
+    $w.plot.menu add command -label "field (small)"   -command { set file "$picpath/field.small.gif"; refresh_now;  }
+    $w.plot.menu add command -label "field (large)"   -command { set file "$picpath/field.large.gif"; refresh_now;  }
+    $w.plot.menu add command -label "temperatures"    -command { set file "$picpath/temps.time.gif"; refresh_now;  }
+    $w.plot.menu add command -label "last image (10x10)"   -command { set file "$picpath/current.b10.gif"; refresh_now;  }
+    $w.plot.menu add command -label "last image (zoom)"     -command { set file "$picpath/current.zoom.gif"; refresh_now;  }
+    $w.plot.menu add command -label "last short image" -command { set file "$picpath/lastshort.zoom.gif"; refresh_now;  }
+    $w.plot.menu add command -label "focus (unit)"     -command { set file "$picpath/focus.unit.gif"; refresh_now;  }
+
+}
+
+proc mk_dataline {w} {
+
+    global fwhm imname name
+    set time [clock format [clock seconds] -format "%H:%M:%S"]
+
+    label $w.label -text "name: $name  |  FHWM: 0.0  |  FILTER: X  |  time: $time            | image: $imname"
+    pack $w.label -side left
+    
+}
+
+proc do_refresh { } {
+
+    global picpath imname name
+
+    after 1000 {
+	
+	set time [clock format [clock seconds] -format "%H:%M:%S"]
+	set name "(empty)"
+	set fwhm 0.0
+	set filter "X"
+
+	if {! [catch {open $picpath/seeing.dat r} data] } {
+	    gets $data line
+	    close $data
+	    set list [split $line]
+	    if {[llength $list] == 4} {
+		set name [lindex $list 0]
+		catch { set fwhm [format "%5.2f" [lindex $list 1]] } status
+		set filter [lindex $list 3]
+            }
+	}
+	
+	.t.dataline.label configure -text "name: $name  |  FHWM: $fwhm  |  FILTER: $filter  |  time: $time           | image: $imname"
+	update
+	do_refresh 
+    }
+}
+
+proc do_refresh_pic { } {
+
+    global file lasttime imname name pid
+
+    after 2000 {
+	
+	# get file status & time
+	if {! [catch {file stat $file stats}] } {
+	    set newtime $stats(mtime)
+	    if {$newtime > $lasttime} {
+		set tmpfile "$file.$pid"
+		catch { exec ln -f $file $tmpfile }
+		catch { picture read $tmpfile -shrink } 
+		catch { exec rm -f $tmpfile }
+		set imname $name
+		set lasttime $newtime
+		update
+	    }
+	}
+	do_refresh_pic
+    }
+}
+
+proc bgerror {result} {
+	puts "edisp error: $result"
+}
+
+proc refresh_now { } {
+
+    global file lasttime imname name pid
+
+    if {[file exists $file]} {
+	set tmpfile "$file.$pid"
+	catch { exec ln -f $file $tmpfile }
+	catch { picture read $tmpfile -shrink }
+	catch { exec rm -f $tmpfile }
+
+	file stat $file stats
+	set imname $name
+	set lasttime $stats(mtime)
+	update
+	
+    }
+}
+
+mk_layout
+do_refresh
+do_refresh_pic
Index: /tags/start/Ohana/src/tcl/src/edisp.ppm
===================================================================
--- /tags/start/Ohana/src/tcl/src/edisp.ppm	(revision 12606)
+++ /tags/start/Ohana/src/tcl/src/edisp.ppm	(revision 12606)
@@ -0,0 +1,169 @@
+#!/usr/bin/env wish
+
+# define three components to the window:
+
+# text line with data value
+# image region with image
+# quit button
+
+set picpath "/data/milo/cfh12k/plots"
+set imname "(empty)"
+set name "(empty)"
+
+proc mk_layout { } {
+
+    global file lasttime picpath
+
+    set lasttime 0
+    set file "$picpath/empty.gif"
+    wm withdraw .
+
+    set w [toplevel .t]
+    wm title .t "user display"
+    
+    # top level containers
+    frame $w.menubar -relief raised -borderwidth 2
+    frame $w.picture -relief raised -borderwidth 2
+    frame $w.dataline -relief raised -borderwidth 2
+
+    pack $w.menubar -fill x
+    pack $w.picture -fill x
+    pack $w.dataline -fill x
+
+    mk_menubar $w.menubar
+    mk_picture $w.picture
+    mk_dataline $w.dataline
+
+    update
+}
+
+proc do_quit {} {
+    
+    exit 
+
+}
+
+proc mk_picture {w} {
+
+    global file
+
+    image create photo picture -file $file
+
+    label $w.name -image picture
+    pack  $w.name -side top -fill both
+}
+
+proc mk_menubar {w} {
+
+    global file picpath
+
+    menubutton $w.file -text "File" -menu $w.file.menu
+    pack $w.file -side left
+
+    menu $w.file.menu -tearoff 0
+    $w.file.menu add command -label "Quit" -command { do_quit }
+    bind all <Alt-q> { do_quit }
+    
+    menubutton $w.plot -text "Plots" -menu $w.plot.menu
+    pack $w.plot -side left
+
+    menu $w.plot.menu -tearoff 0
+    $w.plot.menu add command -label "biases"          -command { set file "$picpath/biases.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "skyprobe recent" -command { set file "$picpath/skyprobe_recent.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "skyprobe night"  -command { set file "$picpath/skyprobe_night.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "sky vs time"     -command { set file "$picpath/sky.time.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "sky vs airmass"  -command { set file "$picpath/sky.airmass.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "FWHM vs time"    -command { set file "$picpath/fwhm.time.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "FWHM vs airmass" -command { set file "$picpath/fwhm.airmass.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "field (small)"   -command { set file "$picpath/field.small.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "field (large)"   -command { set file "$picpath/field.large.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "temperatures"    -command { set file "$picpath/temps.time.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "image (10x10)"   -command { set file "$picpath/current.b10.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "focus (unit)"    -command { set file "$picpath/focus.unit.ppm"; refresh_now;  }
+
+}
+
+proc mk_dataline {w} {
+
+    global fwhm imname name
+    set time [clock format [clock seconds] -format "%H:%M:%S"]
+
+    label $w.label -text "name: $name  |  FHWM: 0.0  |  FILTER: X  |  time: $time            | image: $imname"
+    pack $w.label -side left
+    
+}
+
+proc do_refresh { } {
+
+    global picpath imname name
+
+    after 1000 {
+	
+	set time [clock format [clock seconds] -format "%H:%M:%S"]
+
+	set name "empty"
+	set fwhm 0.0
+	set filter "X"
+
+	if {! [catch "open $picpath/seeing.dat r" data] } {
+	    gets $data line
+	    close $data
+	    set list [split $line]
+	    set name [lindex $list 0]
+	    set fwhm [format "%5.2f" [lindex $list 1]]
+	    set filter [lindex $list 3]
+	}
+
+	.t.dataline.label configure -text "name: $name  |  FHWM: $fwhm  |  FILTER: $filter  |  time: $time           | image: $imname"
+	update
+	
+	do_refresh 
+    }
+}
+
+proc do_refresh_pic { } {
+
+    global file lasttime imname name
+
+    after 2000 {
+	
+	if {! [catch "file stat $file stats"] } {
+	    set newtime $stats(mtime)
+	    if {$newtime > $lasttime} {
+		set tmpfile "$file.tmp"
+		catch "exec ln -f $file $tmpfile"
+		catch "picture read $tmpfile -shrink"
+		catch "exec rm $tmpfile"
+		set imname $name
+		set lasttime $newtime
+		update
+	    }
+	}
+	do_refresh_pic
+    }
+}
+
+proc refresh_now { } {
+
+    global file lasttime imname name
+
+    picture read $file -shrink;
+
+    if {[file exists $file]} {
+	set tmpfile "$file.tmp"
+	catch "exec ln -f $file $tmpfile"
+	catch "picture read $tmpfile -shrink"
+	catch "exec rm -f $tmpfile"
+
+	file stat $file stats
+	set lasttime $stats(mtime)
+	set imname $name
+	
+	update
+	
+    }
+}
+
+mk_layout
+do_refresh
+do_refresh_pic
Index: /tags/start/Ohana/src/uniphot/Makefile
===================================================================
--- /tags/start/Ohana/src/uniphot/Makefile	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/Makefile	(revision 12606)
@@ -0,0 +1,67 @@
+include ../../Configure
+HOME    =       $(ROOT)/src/uniphot
+CONFIG  =	$(ROOT)/config
+PROGRAM =       uniphot
+
+BIN	=	$(HOME)/bin
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+DESTBIN	=	$(LBIN)
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+#
+INCS	= 	-I$(INC) -I$(LINC) -I$(XINC) -I$(LINC)/$(ARCH)
+LIBS	= 	-L$(LLIB) -lohana -lFITS -lm 
+CFLAGS	=	-o $*.$(ARCH).o $(INCS) -Wall
+CCFLAGS	=	$(INCS) $(LIBS) -Wall
+
+UNIPHOT = \
+$(SRC)/uniphot.$(ARCH).o	 \
+$(SRC)/initialize.$(ARCH).o	 \
+$(SRC)/ConfigInit.$(ARCH).o	 \
+$(SRC)/args.$(ARCH).o		 \
+$(SRC)/liststats.$(ARCH).o	 \
+$(SRC)/load_images.$(ARCH).o	 \
+$(SRC)/find_image_tgroups.$(ARCH).o	 \
+$(SRC)/find_image_sgroups.$(ARCH).o	 \
+$(SRC)/fit_groups.$(ARCH).o	 \
+$(SRC)/update.$(ARCH).o		 \
+$(SRC)/update_catalog.$(ARCH).o		 \
+$(SRC)/wcatalog.$(ARCH).o		 \
+$(SRC)/wimages.$(ARCH).o		 \
+$(SRC)/gcatalog.$(ARCH).o		 \
+$(SRC)/misc.$(ARCH).o		 \
+$(SRC)/time.$(ARCH).o		 
+
+OBJ = $(UNIPHOT)
+
+default: $(PROGRAM)
+
+$(UNIPHOT): $(INC)/uniphot.h
+
+# dependancy rules for binary code ##########################
+$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+
+$(BIN)/$(PROGRAM).$(ARCH): $(OBJ)
+	$(CC) $(OBJ) -o $(BIN)/$(PROGRAM).$(ARCH) $(CCFLAGS)
+
+install: $(DESTBIN)/$(PROGRAM)
+
+$(DESTBIN)/$(PROGRAM): $(BIN)/$(PROGRAM).$(ARCH)
+	rm -f $(DESTBIN)/$(PROGRAM)
+	cp $(BIN)/$(PROGRAM).$(ARCH) $(DESTBIN)/$(PROGRAM)
+
+# utilities #################################################
+clean:	
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
Index: /tags/start/Ohana/src/uniphot/doc/notes.txt
===================================================================
--- /tags/start/Ohana/src/uniphot/doc/notes.txt	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/doc/notes.txt	(revision 12606)
@@ -0,0 +1,14 @@
+
+<h2> uniphot </h2>
+
+<ul>
+<li> load images (select on photcode, time range)
+<li> create time groups
+<li> create space groups
+<li> solve for:
+     tgroup[i].M = ave(image[tgroup].Mcal - image[tgroup].sgroup.Mcal)
+     sgroup[i].M = ave(image[sgroup].Mcal - image[tgroup].tgroup.Mcal)
+
+     image.tgroup -> tgroup
+     group.Nimage, image
+     
Index: /tags/start/Ohana/src/uniphot/include/uniphot.h
===================================================================
--- /tags/start/Ohana/src/uniphot/include/uniphot.h	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/include/uniphot.h	(revision 12606)
@@ -0,0 +1,74 @@
+# include <ohana.h>
+# include <loneos.h>
+
+typedef struct {
+  double median;
+  double mean;
+  double sigma;
+  double error;
+  double chisq;
+  double min;
+  double max;
+  double total;
+  int    Nmeas;
+} StatType;
+
+typedef struct {
+  void *tgroup;
+  void *sgroup;
+} ImageLink;
+
+typedef struct {
+  char label[64];
+  short int M;
+  short int dM;
+  short int dMsub;
+  double v1, v2;
+  Image **image;
+  ImageLink **imlink;
+  int Nimage, Ngood;
+} Group;
+
+/* global variables set in parameter file */
+char         ImageCat[256];
+char         CATDIR[256];
+char         STATMODE[64];
+int          VERBOSE;
+int          NLOOP;
+int          TimeSelect;
+int          VERBOSE;
+int          UPDATE;
+int          IMAGE_BAD;
+double       RADIUS;
+double       TRANGE;
+unsigned int TSTART;
+unsigned int TSTOP;
+PhotCode    *photcode;
+
+enum {black, white, red, orange, yellow, green, blue, indigo, violet};
+
+/***** prototypes ****/
+Group *find_image_tgroups (Image *image, ImageLink *imlink, int Nimage, int *Ntgroup);
+Group *find_image_sgroups (Image *image, ImageLink *imlink, int Nimage, int *Nsgroup);
+Image *load_images (int *nimage);
+char *sec_to_date (unsigned long second);
+double sec_to_jd (unsigned long second);
+int main (int argc, char **argv);
+int args (int argc, char **argv);
+int liststats (double *value, double *dvalue, int N, StatType *stats);
+int dms_to_ddd (double *Value, char *string);
+int str_to_radec (double *ra, double *dec, char *str1, char *str2);
+int chk_time (char *line);
+int str_to_time (char *line, unsigned int *second);
+int str_to_dtime (char *line, double *second);
+int Fseek (FILE *f, long offset, int whence);
+unsigned long int jd_to_sec (double jd);
+unsigned long date_to_sec (char *date);
+void initialize (int argc, char **argv);
+void ConfigInit (int *argc, char **argv);
+void fit_tgroup (Group *tgroup, int Ntgroup);
+void fit_sgroup (Group *sgroup, int Nsgroup);
+void initstats (char *mode);
+void sort (unsigned int *X, int N);
+void sortB (double *X, double *Y, int N);
+void sortD (double *X, double *Y, double *Z, int N);
Index: /tags/start/Ohana/src/uniphot/src/ConfigInit.c
===================================================================
--- /tags/start/Ohana/src/uniphot/src/ConfigInit.c	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/src/ConfigInit.c	(revision 12606)
@@ -0,0 +1,33 @@
+# include "uniphot.h"
+
+void ConfigInit (int *argc, char **argv) {
+
+  double ZERO_POINT;
+  char  *config, *file;
+  char   PhotCodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  ScanConfig (config, "CATDIR",                 "%s",  0, CATDIR);
+  ScanConfig (config, "IMAGE_CATALOG",          "%s",  0, ImageCat);
+  ScanConfig (config, "PHOTCODE_FILE",          "%s",  0, PhotCodeFile);
+  ScanConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
+  SetZeroPoint (ZERO_POINT);
+
+  free (config);
+  free (file);
+
+  if (!LoadPhotcodes (PhotCodeFile)) {
+    fprintf (stderr, "error loading photcodes\n");
+    exit (0);
+  }
+
+}
Index: /tags/start/Ohana/src/uniphot/src/args.c
===================================================================
--- /tags/start/Ohana/src/uniphot/src/args.c	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/src/args.c	(revision 12606)
@@ -0,0 +1,73 @@
+# include "uniphot.h"
+
+int args (int argc, char **argv) {
+
+  int N;
+
+  /* define time */
+  TimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-time"))) {
+    remove_argument (N, &argc, argv);
+    if (!str_to_time (argv[N], &TSTART)) { 
+      fprintf (stderr, "ERROR: syntax error\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    if (!str_to_time (argv[N], &TSTOP)) { 
+      fprintf (stderr, "ERROR: syntax error\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    TimeSelect = TRUE;
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  NLOOP = 8;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    NLOOP = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  strcpy (STATMODE, "MEAN");
+  if ((N = get_argument (argc, argv, "-statmode"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (STATMODE, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  UPDATE = FALSE;
+  if ((N = get_argument (argc, argv, "-update"))) {
+    remove_argument (N, &argc, argv);
+    UPDATE = TRUE;
+  }
+
+  /* max separation for unique space group, in degrees */
+  RADIUS = 2.0;
+  if ((N = get_argument (argc, argv, "-radius"))) {
+    remove_argument (N, &argc, argv);
+    RADIUS = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* max separation for unique time group, in days -> seconds */
+  TRANGE = 86400*7.0;
+  if ((N = get_argument (argc, argv, "-trange"))) {
+    remove_argument (N, &argc, argv);
+    TRANGE = 86400*atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "ERROR: USAGE: uniphot (photcode) [options]\n");
+    exit (2);
+  } 
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/uniphot/src/dumpresult.c
===================================================================
--- /tags/start/Ohana/src/uniphot/src/dumpresult.c	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/src/dumpresult.c	(revision 12606)
@@ -0,0 +1,25 @@
+# include "uniphot.h"
+
+dumpresult () {
+  short Mcal, Mgrp, Mset;
+  FILE *f;
+  char outfile[64];
+  Group *tgrp;
+
+  for (i = 0; i < Nsgroup; i++) {
+    sprintf (outfile, "test.%02d.dat", i);
+    f = fopen (outfile, "w");
+    for (j = 0; j < sgroup[i].Nimage; j++) {
+      if (sgroup[i].image[j][0].code & IMAGE_BAD) continue;
+      tgrp = (Group *) sgroup[i].imlink[j][0].tgroup;
+      Mcal = sgroup[i].image[j][0].Mcal;
+      Mset = sgroup[i].M;
+      Mgrp = tgrp[0].M;
+      fprintf (f, "%7.4f %7.4f %7.4f %7.4f   %10.6f %10.6f  %f %s\n", 
+	       0.001*Mcal, 0.001*Mgrp, 0.001*Mset, 0.001*sgroup[i].image[j][0].dMcal, 
+	       sgroup[i].image[j][0].coords.crval1, sgroup[i].image[j][0].coords.crval2, (sgroup[i].image[j][0].tzero-915148800)/86400.0, tgrp[0].label);
+    }
+    fclose (f);
+  }
+}
+
Index: /tags/start/Ohana/src/uniphot/src/find_image_sgroups.c
===================================================================
--- /tags/start/Ohana/src/uniphot/src/find_image_sgroups.c	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/src/find_image_sgroups.c	(revision 12606)
@@ -0,0 +1,80 @@
+# include "uniphot.h"
+
+Group *find_image_sgroups (Image *image, ImageLink *imlink, int Nimage, int *Nsgroup) {
+
+  int i, j, Ngroup, Nentry, NENTRY;
+  double r, d, x, y, radius;
+  Group *group;
+  Coords coords;
+  
+  coords.crpix1 = coords.crpix2 = 0.0;
+  coords.cdelt1 = coords.cdelt2 = 1.0; /* scale is degrees, radius in degrees */
+  coords.pc1_1 = coords.pc2_2 = 1.0;
+  coords.pc1_2 = coords.pc2_1 = 0.0;
+  strcpy (coords.ctype, "RA---TAN");
+  
+  Ngroup = 0;
+  ALLOCATE (group, Group, Nimage);
+
+  /* set imlink.sgroups = NULL as a marker */
+  for (i = 0; i < Nimage; i++) imlink[i].sgroup = NULL;
+
+  for (i = 0; i < Nimage; i++) {
+    if (imlink[i].sgroup != NULL) continue;
+    if (image[i].code & ID_IMAGE_NOCAL) continue;
+
+    /* new sgroup, set ref coords */
+    XY_to_RD (&r, &d, 0.5*image[i].NX, 0.5*image[i].NX, &image[i].coords);
+    coords.crval1 = r;
+    coords.crval2 = d;
+
+    /* init sgroup structure */
+    Nentry = 0;
+    NENTRY = 100;
+    ALLOCATE (group[Ngroup].image, Image *, NENTRY);
+    ALLOCATE (group[Ngroup].imlink, ImageLink *, NENTRY);
+    group[Ngroup].M = 0;
+    group[Ngroup].dM = 0;
+    snprintf (group[Ngroup].label, 64, "%10.6f - %10.6f", r, d);
+    group[Ngroup].v1 = r;
+    group[Ngroup].v2 = d;
+
+    /* link this image to sgroup */
+    group[Ngroup].image[Nentry] = &image[i];
+    group[Ngroup].imlink[Nentry] = &imlink[i];
+    imlink[i].sgroup = &group[Ngroup];
+    Nentry ++;
+
+    for (j = 0; j < Nimage; j++) {
+      if (image[j].code & ID_IMAGE_NOCAL) continue;
+      if (imlink[j].sgroup != NULL) continue;
+
+      /* project image center to local coords, check radius */
+      XY_to_RD (&r, &d, 0.5*image[j].NX, 0.5*image[j].NX, &image[j].coords);
+      if (!RD_to_XY (&x, &y, r, d, &coords)) continue; 
+      /* RD_to_XY returns FALSE if opposite hemispheres */
+      radius = hypot (x, y);
+
+      if (radius > RADIUS) continue;
+
+      /* image in sgroup, add to entry */
+      group[Ngroup].image[Nentry] = &image[j];
+      group[Ngroup].imlink[Nentry] = &imlink[j];
+      imlink[j].sgroup = &group[Ngroup];
+      Nentry ++;
+      if (Nentry == NENTRY) {
+	NENTRY += 100;
+	REALLOCATE (group[Ngroup].image, Image *, NENTRY);
+	REALLOCATE (group[Ngroup].imlink, ImageLink *, NENTRY);
+      }
+    }
+    group[Ngroup].Nimage = Nentry;
+    Ngroup ++;
+  }
+  *Nsgroup = Ngroup;
+  return (group);
+}
+
+  /* this is a bit weak: since we use pointers, we can't
+     reallocate group after the pointers are assigned.
+     therefore, we allocate the max possible groups */
Index: /tags/start/Ohana/src/uniphot/src/find_image_tgroups.c
===================================================================
--- /tags/start/Ohana/src/uniphot/src/find_image_tgroups.c	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/src/find_image_tgroups.c	(revision 12606)
@@ -0,0 +1,78 @@
+# include "uniphot.h"
+
+Group *find_image_tgroups (Image *image, ImageLink *imlink, int Nimage, int *Ntgroup) {
+
+  char *start, *stop;
+  int i, j, Ngroup, NGROUP, Nentry, NENTRY;
+  unsigned int *time, *tmin, *tmax;
+  Group *group;
+
+  /* sort time list (use only valid images?) */
+  ALLOCATE (time, unsigned int, Nimage);
+  for (i = 0; i < Nimage; i++) {
+    time[i] = image[i].tzero;
+  }
+  sort (time, Nimage);
+
+  /* find groups with dt < TRANGE */
+  Ngroup = 0;
+  NGROUP = 100;
+  ALLOCATE (tmin, unsigned int, NGROUP);
+  ALLOCATE (tmax, unsigned int, NGROUP);
+  tmin[Ngroup] = time[0];
+
+  /* generate tgroups */
+  for (i = 0; i < Nimage - 1; i++) {
+    if (time[i+1] - time[i] < TRANGE) continue;
+    
+    tmax[Ngroup] = time[i];
+    
+    Ngroup ++;
+    if (Ngroup == NGROUP) {
+      NGROUP += 100;
+      REALLOCATE (tmin, unsigned int, NGROUP);
+      REALLOCATE (tmax, unsigned int, NGROUP);
+    }
+    tmin[Ngroup] = time[i + 1];
+  }
+  tmax[Ngroup] = time[Nimage - 1];
+  Ngroup ++;
+  ALLOCATE (group, Group, Ngroup);
+
+  /* assign images to groups */
+  for (i = 0; i < Ngroup; i++) {
+    Nentry = 0;
+    NENTRY = 100;
+    ALLOCATE (group[i].image, Image *, NENTRY);
+    ALLOCATE (group[i].imlink, ImageLink *, NENTRY);
+    group[i].M = 0;
+    group[i].dM = 0;
+
+    start = sec_to_date (tmin[i]);
+    stop = sec_to_date (tmax[i]);
+    snprintf (group[i].label, 64, "%s - %s", start, stop);
+    free (start);
+    free (stop);
+
+    for (j = 0; j < Nimage; j++) {
+      if (image[j].tzero < tmin[i]) continue;
+      if (image[j].tzero > tmax[i]) continue;
+      if (image[j].code & ID_IMAGE_NOCAL) continue;
+      
+      group[i].image[Nentry] = &image[j];
+      group[i].imlink[Nentry] = &imlink[j];
+      imlink[j].tgroup = &group[i];
+      Nentry ++;
+      if (Nentry == NENTRY) {
+	NENTRY += 100;
+	REALLOCATE (group[i].image, Image *, NENTRY);
+	REALLOCATE (group[i].imlink, ImageLink *, NENTRY);
+      }
+    }
+    group[i].Nimage = Nentry;
+  }
+  *Ntgroup = Ngroup;
+  return (group);
+}
+
+
Index: /tags/start/Ohana/src/uniphot/src/fit_groups.c
===================================================================
--- /tags/start/Ohana/src/uniphot/src/fit_groups.c	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/src/fit_groups.c	(revision 12606)
@@ -0,0 +1,76 @@
+# include "uniphot.h"
+
+void fit_tgroup (Group *tgroup, int Ntgroup) {
+
+  int i, j, Nlist;
+  short Mcal, Mgrp;
+  double *mlist, *dlist;
+  StatType stats;
+  Group *sgroup;
+
+  Nlist = tgroup[0].Nimage;
+  for (i = 0; i < Ntgroup; i++) { Nlist = MAX (Nlist, tgroup[i].Nimage); }
+  ALLOCATE (mlist, double, Nlist);
+  ALLOCATE (dlist, double, Nlist);
+
+  for (i = 0; i < Ntgroup; i++) {
+    for (j = Nlist = 0; j < tgroup[i].Nimage; j++) {
+      if (tgroup[i].image[j][0].code & IMAGE_BAD) continue;
+      sgroup = (Group *) tgroup[i].imlink[j][0].sgroup;
+      Mcal = tgroup[i].image[j][0].Mcal;
+      Mgrp = sgroup[0].M;
+      mlist[Nlist] = (Mcal - Mgrp);
+      dlist[Nlist] = tgroup[i].image[j][0].dMcal;
+      Nlist ++;
+    }
+    liststats (mlist, dlist, Nlist, &stats);
+    tgroup[i].M  = stats.mean;
+    tgroup[i].dMsub = stats.sigma;
+    tgroup[i].Ngood = stats.Nmeas;
+    
+    initstats ("MEAN");
+    liststats (mlist, dlist, Nlist, &stats);
+    tgroup[i].dM = stats.sigma;
+    initstats (STATMODE);
+  }
+  free (mlist);
+  free (dlist);
+}
+
+void fit_sgroup (Group *sgroup, int Nsgroup) {
+
+  int i, j, Nlist;
+  short Mcal, Mgrp;
+  double *mlist, *dlist;
+  StatType stats;
+  Group *tgroup;
+  
+  Nlist = sgroup[0].Nimage;
+  for (i = 0; i < Nsgroup; i++) { Nlist = MAX (Nlist, sgroup[i].Nimage); }
+  ALLOCATE (mlist, double, Nlist);
+  ALLOCATE (dlist, double, Nlist);
+  Nlist = 0;
+
+  for (i = 0; i < Nsgroup; i++) {
+    for (j = Nlist = 0; j < sgroup[i].Nimage; j++) {
+      if (sgroup[i].image[j][0].code & IMAGE_BAD) continue;
+      tgroup = (Group *) sgroup[i].imlink[j][0].tgroup;
+      Mcal = sgroup[i].image[j][0].Mcal;
+      Mgrp = tgroup[0].M;
+      mlist[Nlist] = (Mcal - Mgrp);
+      dlist[Nlist] = sgroup[i].image[j][0].dMcal;
+      Nlist ++;
+    }
+    liststats (mlist, dlist, Nlist, &stats);
+    sgroup[i].M  = stats.mean;
+    sgroup[i].dMsub = stats.sigma;
+    sgroup[i].Ngood = stats.Nmeas;
+
+    initstats ("MEAN");
+    liststats (mlist, dlist, Nlist, &stats);
+    sgroup[i].dM = stats.sigma;
+    initstats (STATMODE);
+  }
+  free (mlist);
+  free (dlist);
+}
Index: /tags/start/Ohana/src/uniphot/src/gcatalog.c
===================================================================
--- /tags/start/Ohana/src/uniphot/src/gcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/src/gcatalog.c	(revision 12606)
@@ -0,0 +1,31 @@
+# include "uniphot.h"
+
+int gcatalog (Catalog *catalog) {
+
+  int mode;
+
+  mode = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+
+  switch (lock_catalog (catalog, LCK_SOFT)) {
+  case 0:
+    fprintf (stderr, "ERROR: can't lock file %s\n", catalog[0].filename);
+    exit (1);
+  case 1:
+    if (!load_catalog (catalog, mode, VERBOSE)) {
+      fprintf (stderr, "ERROR: failure loading catalog %s\n", catalog[0].filename);
+      exit (1);
+    }
+    if (VERBOSE) {
+      fprintf (stderr, "read %d stars from catalog file %s (%d measurements)\n", 
+	       catalog[0].Naverage, catalog[0].filename, catalog[0].Nmeasure);
+    }
+    return (TRUE);
+  case 2:
+    if (VERBOSE) fprintf (stderr, "no data in %s, skipping\n", catalog[0].filename);
+    return (FALSE);
+  default:
+    fprintf (stderr, "weird lock_catalog exit state\n");
+    exit (1);
+  }
+  return (FALSE);
+}
Index: /tags/start/Ohana/src/uniphot/src/initialize.c
===================================================================
--- /tags/start/Ohana/src/uniphot/src/initialize.c	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/src/initialize.c	(revision 12606)
@@ -0,0 +1,22 @@
+# include "uniphot.h"
+
+void initialize (int argc, char **argv) {
+
+  /* are these set correctly? */
+  ConfigInit (&argc, argv);
+  args (argc, argv);
+
+  if ((photcode = GetPhotcodebyName (argv[1])) == NULL) {
+    fprintf (stderr, "ERROR: photcode not found in photcode table\n");
+    exit (1);
+  }
+  if ((photcode[0].type == PHOT_DEP) && (photcode[0].type == PHOT_REF)) {
+    fprintf (stderr, "photcode must be primary or secondary type\n");
+    exit (1);
+  }
+
+  IMAGE_BAD = ID_IMAGE_NOCAL | ID_IMAGE_POOR | ID_IMAGE_SKIP | ID_IMAGE_FEW;
+
+  initstats (STATMODE);
+}
+
Index: /tags/start/Ohana/src/uniphot/src/liststats.c
===================================================================
--- /tags/start/Ohana/src/uniphot/src/liststats.c	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/src/liststats.c	(revision 12606)
@@ -0,0 +1,115 @@
+# include "uniphot.h"
+
+enum {M_MEAN, M_MEDIAN, M_WT_MEAN, M_INNER_MEAN, 
+      M_INNER_WTMEAN, M_CHI_INNER_MEAN, M_CHI_INNER_WTMEAN};
+
+static int statmode;
+
+void initstats (char *mode) {
+
+  statmode = -1;
+  if (!strcmp (mode, "MEAN")) statmode = M_MEAN;
+  if (!strcmp (mode, "MEDIAN")) statmode = M_MEDIAN;
+  if (!strcmp (mode, "WT_MEAN")) statmode = M_WT_MEAN;
+  if (!strcmp (mode, "INNER_MEAN")) statmode = M_INNER_MEAN;
+  if (!strcmp (mode, "INNER_WTMEAN")) statmode = M_INNER_WTMEAN;
+  if (!strcmp (mode, "CHI_INNER_MEAN")) statmode = M_CHI_INNER_MEAN;
+  if (!strcmp (mode, "CHI_INNER_WTMEAN")) statmode = M_CHI_INNER_WTMEAN;
+
+  if (statmode == -1) {
+    fprintf (stderr, "ERROR: invalid stats mode: %s\n", mode);
+    exit (1);
+  }
+}
+
+int liststats (double *value, double *dvalue, int N, StatType *stats) {
+  
+  int i, ks, ke, Nm;
+  double Mo, dMo, M, dM, X2, dS, *chi;
+
+  stats[0].Nmeas = N;
+  stats[0].mean  = 0;
+  stats[0].sigma = 0;
+  if (N < 2) return (FALSE);
+
+  sortB (value, dvalue, N);
+  stats[0].median = value[(int)(0.5*N)];
+  stats[0].min    = value[0];
+  stats[0].max    = value[N-1];
+
+  switch (statmode) {
+  case M_MEDIAN:
+    ks = 0;
+    ke = N;
+    Mo = stats[0].median;
+    Nm = N;
+    goto chisq;
+    break;
+  case M_MEAN:
+  case M_WT_MEAN:
+    ks = 0;
+    ke = N;
+    break;
+  case M_INNER_MEAN:
+  case M_INNER_WTMEAN:
+  case M_CHI_INNER_MEAN:
+  case M_CHI_INNER_WTMEAN:
+    ks = 0.25*N + 0.50;
+    ke = 0.75*N + 0.25;
+    if (N <= 3) {
+      ks = 0;
+      ke = N;
+    }
+    break;
+  }    
+
+  if ((statmode == M_CHI_INNER_MEAN) || (statmode == M_CHI_INNER_WTMEAN)) {
+    ALLOCATE (chi, double, N);
+    for (i = 0; i < N; i++) {
+      chi[i] = (value[i] - stats[0].median) / dvalue[i];
+    }
+    sortD (chi, value, dvalue, N);
+    free (chi);
+  }
+
+  /* calculating the per-star offset based on the weighted average */
+  M = dM = Nm = 0;
+  if ((statmode == M_WT_MEAN) || (statmode == M_INNER_WTMEAN) || (statmode == M_CHI_INNER_WTMEAN)) {
+    for (i = ks; i < ke; i++) {
+      M   += value[i] / SQ (dvalue[i]);
+      dM  += 1.0 / SQ (dvalue[i]);
+      Nm  ++;  
+    }	
+    Mo = M / dM;
+    dMo = sqrt (1.0 / dM);
+  } else {
+    for (i = ks; i < ke; i++) {
+      M   += value[i];
+      dM  += SQ (dvalue[i]);
+      Nm  ++;  
+    }	
+    Mo = M / (double) Nm;
+    dMo = sqrt (dM / (double) Nm);
+  }
+
+ chisq:
+  /* find sigma and chisq */
+  X2 = dS = 0;
+  for (i = ks; i < ke; i++) {
+    M  = SQ (value[i] - Mo);
+    dM = SQ (dvalue[i]);
+    X2 += M / dM;
+    dS += M;
+  }
+  X2 = X2 / Nm;
+  dS = sqrt (dS / Nm);
+
+  stats[0].mean  = Mo;
+  stats[0].Nmeas = Nm;
+  stats[0].chisq = X2;
+  stats[0].sigma = dS;
+  stats[0].error = dMo;
+
+  return (TRUE);
+}
+
Index: /tags/start/Ohana/src/uniphot/src/load_images.c
===================================================================
--- /tags/start/Ohana/src/uniphot/src/load_images.c	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/src/load_images.c	(revision 12606)
@@ -0,0 +1,60 @@
+# include "uniphot.h"
+
+Image *load_images (int *nimage) {
+
+  int    i, Nimage, status, equiv;
+  FILE  *f;
+  Image *image;
+  Header header;
+
+  if (VERBOSE) fprintf (stderr, "finding images\n");
+
+  /* open image datafile */
+  if ((f = fopen (ImageCat, "r")) == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't open image table %s\n", ImageCat);
+    exit (1);
+  }
+
+  /* read header */
+  if (!fits_fread_header (f, &header)) {
+    fprintf (stderr, "ERROR: can't read image table header %s\n", ImageCat);
+    exit (1);
+  }
+
+  /* read number of images */
+  Nimage = 0;
+  fits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+  if (Nimage == 0) {
+    fprintf (stderr, "ERROR: No images in catalog %s (1)\n", ImageCat);
+    exit (1);
+  }
+
+  /* load all images */
+  ALLOCATE (image, Image, Nimage);
+  status = Fread (image, sizeof(Image), Nimage, f, "image");
+  if (status != Nimage) {
+    fprintf (stderr, "ERROR: couldn't read all images from image catalog: %s\n", ImageCat);
+    exit (1);
+  }
+  fclose (f);
+
+  /* mark images to be calibrated */
+  for (i = 0; i < Nimage; i++) {
+      
+    image[i].code |= ID_IMAGE_NOCAL;
+
+    /* select images by photcode */
+    equiv = GetPhotcodeEquivCodebyCode (image[i].source);
+    if (equiv != photcode[0].code) continue;
+
+    /* select images by time */
+    if (TimeSelect) {
+      if (image[i].tzero < TSTART) continue;
+      if (image[i].tzero > TSTOP) continue;
+    }
+
+    image[i].code &= ~ID_IMAGE_NOCAL;
+  }
+  *nimage = Nimage;
+  return (image);
+}
Index: /tags/start/Ohana/src/uniphot/src/misc.c
===================================================================
--- /tags/start/Ohana/src/uniphot/src/misc.c	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/src/misc.c	(revision 12606)
@@ -0,0 +1,127 @@
+
+void sort (unsigned int *X, int N) {
+
+  int l,j,ir,i;
+  unsigned tX;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+  }
+}
+
+void sortB (double *X, double *Y, int N) {
+
+  int l,j,ir,i;
+  double tX, tY;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+  }
+}
+
+void sortD (double *X, double *Y, double *Z, int N) {
+
+  int l,j,ir,i;
+  double tX, tY, tZ;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tZ = Z[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tZ = Z[ir];
+      Z[ir] = Z[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	Z[0] = tZ;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	Z[i] = Z[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    Z[i] = tZ;
+  }
+}
+
Index: /tags/start/Ohana/src/uniphot/src/plotstuff.c
===================================================================
--- /tags/start/Ohana/src/uniphot/src/plotstuff.c	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/src/plotstuff.c	(revision 12606)
@@ -0,0 +1,204 @@
+# include "uniphot.h"
+# include <signal.h>
+
+static int Xgraph[5] = {0,0,0,0,0};
+static int active;
+
+void XDead () {
+  signal (SIGPIPE, XDead);
+  fprintf (stderr, "kapa is dead, must restart\n");
+  Xgraph[active] = -1;
+}
+
+typedef struct {
+  double xmin, xmax, ymin, ymax;
+  int style, ptype, ltype, etype, color;
+  double lweight, size;
+} Graphdata;
+
+int open_graph (int N) {
+
+# ifdef ANSI
+#   define F_SETFL      4   
+#   define O_NONBLOCK 0200000  
+#   define       AF_UNIX         1          
+#   define       SOCK_STREAM     1          
+#define ENOENT          2       /* No such file or directory    */
+# endif /* ANSI */
+
+  int i, InitSocket, status, addreslen;
+  struct sockaddr_un Address;
+  char temp[100], *display_name;
+  char socket_name[100];
+  FILE *f;
+  
+  active = N;
+  sprintf (socket_name, "/tmp/kapa%d", N);
+  sprintf (temp, "rm -f %s", socket_name);
+  system (temp);
+    
+  strcpy (Address.sun_path, socket_name); 
+  Address.sun_family = AF_UNIX; 
+  InitSocket = socket (AF_UNIX, SOCK_STREAM, 0); 
+  status = bind (InitSocket, &Address, sizeof (Address));
+  status = listen (InitSocket, 1);
+  
+  sprintf (temp, "kapa %s &", socket_name);
+# ifndef DEBUG
+  system (temp);
+# else  
+  fprintf (stderr, "start kapa, press return: %s\n", temp);
+  fscanf (stdin, "%d", &i);
+# endif
+  
+  addreslen =  sizeof (Address);
+  Xgraph[N] = accept (InitSocket, &Address, &addreslen);
+  if (Xgraph[N] < 0) {
+    fprintf (stderr, "error starting kapa\n");
+    return (FALSE);
+  }
+  else {
+    return (TRUE);
+  }
+  
+}
+
+void DonePlotting (Graphdata *graphmode, int N) {
+  char buffer[65], buffer2[65];
+
+  if (Xgraph[N] == 0) return;
+
+  write (Xgraph[N], "DBOX", 4);
+  sprintf (buffer, "%f %f %f %f", graphmode[0].xmin, graphmode[0].xmax, graphmode[0].ymin, graphmode[0].ymax);
+  sprintf (buffer2, "NBYTES: %6d", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+
+  sprintf (buffer, "%s %s %s", "2222", "2222", "2222");
+  sprintf (buffer2, "NBYTES: %6d", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+}
+
+void JpegPlot (Graphdata *graphmode, int N, char *filename) {
+  char buffer[65], buffer2[65];
+
+  if (Xgraph[N] == 0) return;
+
+  write (Xgraph[N], "PNGF", 4);
+  sprintf (buffer, "LEN: %11d", strlen (filename));
+  write (Xgraph[N], buffer, 16);
+  write (Xgraph[N], filename, strlen (filename));
+  read (Xgraph[N], buffer, 4);
+}
+
+void PSPlot (Graphdata *graphmode, int N, char *filename) {
+  char buffer[65], buffer2[65];
+
+  if (Xgraph[N] == 0) return;
+
+  write (Xgraph[N], "PSIT", 4);
+  sprintf (buffer, "LEN: %11d", strlen (filename));
+  write (Xgraph[N], buffer, 16);
+  write (Xgraph[N], filename, strlen (filename));
+  read (Xgraph[N], buffer, 4);
+}
+
+void PrepPlotting (int Npts, Graphdata *graphmode, int N) {
+
+  int i, status;
+  char buffer[128], buffer2[128];
+
+  active = N;
+  if (Npts < 1) return;
+
+  if (Xgraph[N] < 1) if (!open_graph(N)) return;
+
+  /* test Xgraph[N], flush junk from pipe */
+  signal (SIGPIPE, XDead);
+  fcntl (Xgraph[N], F_SETFL,  O_NONBLOCK); 
+  for (i = 0; (read (Xgraph[N], buffer, 64) > 0) && (i < 20); i++);
+  fcntl (Xgraph[N], F_SETFL, !O_NONBLOCK); 
+  
+  write (Xgraph[N], "ERAS", 4);
+  
+  /* tell kapa to look for the incoming image */
+  status = write (Xgraph[N], "PLOT", 4); 
+
+  /* send Xgraph[N] the plot details */
+  sprintf (buffer, "%8d %8d %d %d %d %d %f %f", 
+	   Npts, graphmode[0].style, 
+	   graphmode[0].ptype, graphmode[0].ltype, 
+	   graphmode[0].etype, graphmode[0].color, 
+	   graphmode[0].lweight, graphmode[0].size);
+  sprintf (buffer2, "NBYTES: %6d", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+  
+  sprintf (buffer, "%f %f %f %f", 
+	   graphmode[0].xmin, graphmode[0].xmax, 
+	   graphmode[0].ymin, graphmode[0].ymax);
+  sprintf (buffer2, "NBYTES: %6d", strlen (buffer));
+  write (Xgraph[N], buffer2, 16);
+  write (Xgraph[N], buffer, strlen (buffer));
+
+}
+
+void PlotLabel (char *string, int N) {
+
+  char buffer[32];
+
+  if (Xgraph[N] == 0) return;
+
+  write (Xgraph[N], "LABL", 4);
+  sprintf (buffer, " %6d %6d", strlen (string), 2);
+  write (Xgraph[N], buffer, 16);
+  write (Xgraph[N], string, strlen (string));
+}
+
+void PlotVector (int Npts, double *vect, int mode, int N) {
+
+  float *values;
+  int i, Nbytes;
+
+  active = N;
+  if (Npts < 1) return;
+
+  ALLOCATE (values, float, Npts);
+  for (i = 0; i < Npts; i++) {
+    values[i] = vect[i];
+  }
+
+  Nbytes = Npts * sizeof (float);
+  write (Xgraph[N], values, Nbytes);
+  free (values);
+
+}
+
+/* include these lines to plot a pair of vectors: 
+
+   typedef struct {
+   double xmin, xmax, ymin, ymax;
+   int style, ptype, ltype, etype, color;
+   double lweight, size;
+   } Graphdata;
+   Graphdata graphdata;
+   
+   graphdata.xmin = -200;
+   graphdata.xmax = 4200;
+   graphdata.ymin = -500;
+   graphdata.ymax = 500;
+   graphdata.style = 2;
+   graphdata.ptype = 2;
+   graphdata.ltype = 0;
+   graphdata.etype = 0;
+   graphdata.color = 0;
+   graphdata.lweight = 0;
+   graphdata.size = 0.5;
+   
+   PrepPlotting (N, &graphdata, n);
+   PlotVector (N, Y, 0, n);
+   PlotVector (N, dM, 1, n);
+   DonePlotting (&graphdata, n);
+   
+ */
Index: /tags/start/Ohana/src/uniphot/src/time.c
===================================================================
--- /tags/start/Ohana/src/uniphot/src/time.c	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/src/time.c	(revision 12606)
@@ -0,0 +1,313 @@
+# include "uniphot.h"
+
+# define FORMAT_DAYS    1
+# define FORMAT_HOURS   2
+# define FORMAT_MINUTES 3
+# define FORMAT_SECONDS 4
+# define FORMAT_JD      5
+# define FORMAT_DATE    6
+
+/***** convert [-]00:00:00 to 0.0000 ****/
+int dms_to_ddd (double *Value, char *string) {
+  
+  int valid, neg, status;
+  double tmp, value;
+  char *p1, *p2, *px;
+
+  valid = FALSE; 
+  neg = FALSE;
+  stripwhite (string);
+  p1 = string;
+  px = string + strlen(string);
+
+  if (string[0] == '-') { 
+    valid = TRUE; 
+    neg = TRUE;
+    p1 = &string[1];
+  }
+  if (string[0] == '+') { 
+    valid = TRUE; 
+    neg = FALSE;
+    p1 = &string[1];
+  }
+  if (isdigit(string[0])) { 
+    valid = TRUE;
+    p1 = &string[0];
+  }
+  if (!valid) { return (FALSE); }
+
+  status = 1;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) return (FALSE); /* entry not a number: +fred */
+  value = tmp;
+  if (p2 == px) goto escape;    /* entry only number: +1.0 */ 
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:fred */
+  status = 2;
+  value += tmp / 60.0;
+  if (p2 == px) goto escape;    /* entry only number: +1:1 */
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:1:fred */
+  value += tmp / 3600.0;
+
+ escape:
+  if (neg) {
+    value *= -1;
+  }
+  *Value = value;
+
+  return (status);
+}
+
+/**********/
+int str_to_radec (double *ra, double *dec, char *str1, char *str2) {
+
+  double Ra, Dec;
+
+  *ra = *dec = 0;
+  switch (dms_to_ddd (&Ra, str1)) {
+  case 0:
+    fprintf (stderr, "syntax error in RA\n");
+    return (FALSE);
+  case 1:
+    break;
+  case 2:
+    Ra = Ra * 15;
+    break;
+  }
+  switch (dms_to_ddd (&Dec, str2)) {
+  case 0:
+    fprintf (stderr, "syntax error in DEC\n");
+    return (FALSE);
+  case 1:
+  case 2:
+    break;
+  }
+  *ra = Ra;
+  *dec = Dec;
+  return (TRUE);
+}
+
+/**********/
+int chk_time (char *line) {
+
+  char *p1, *p2;
+  double tmp;
+  int mode;
+
+  p1 = line;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1 + strlen (p1) - 1) {
+    if (*p2 == 'd') {
+      mode = FORMAT_DAYS;
+    }
+    if (*p2 == 'h') {
+      mode = FORMAT_HOURS;
+    }
+    if (*p2 == 'm') {
+      mode = FORMAT_MINUTES;
+    }
+    if (*p2 == 's') {
+      mode = FORMAT_SECONDS;
+    }
+    if (*p2 == 'j') {
+      mode = FORMAT_JD;
+    }
+  } else { 
+    mode = FORMAT_DATE;
+  }
+  return (mode);
+}
+
+/**********/
+int str_to_time (char *line, unsigned int *second) {
+  
+  struct timeval now;
+  double jd;
+
+  if (!strcasecmp (line, "NOW")) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    *second = now.tv_sec;
+    return (TRUE);
+  }
+    
+  if (!strcasecmp (line, "TODAY")) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    *second = 86400 * ((int)(now.tv_sec / 86400));
+    return (TRUE);
+  }
+    
+  switch (chk_time (line)) {
+  case 0:
+    return (FALSE);
+  case FORMAT_DAYS:
+    *second = strtod (line, 0) * 86400.0;
+    return (TRUE);
+  case FORMAT_HOURS:
+    *second = strtod (line, 0) * 3600.0;
+    return (TRUE);
+  case FORMAT_MINUTES:
+    *second = strtod (line, 0) * 60.0;
+    return (TRUE);
+  case FORMAT_SECONDS:
+    *second = strtod (line, 0);
+    return (TRUE);
+  case FORMAT_JD:
+    jd = strtod (line, 0);
+    *second = jd_to_sec (jd);
+    return (TRUE);
+  case FORMAT_DATE:
+    *second = date_to_sec (line);
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+/**********/
+int str_to_dtime (char *line, double *second) {
+  
+  switch (chk_time (line)) {
+  case 0:
+  case FORMAT_JD:
+  case FORMAT_DATE:
+    return (FALSE);
+  case FORMAT_DAYS:
+    *second = strtod (line, 0) * 86400.0;
+    return (TRUE);
+  case FORMAT_HOURS:
+    *second = strtod (line, 0) * 3600.0;
+    return (TRUE);
+  case FORMAT_MINUTES:
+    *second = strtod (line, 0) * 60.0;
+    return (TRUE);
+  case FORMAT_SECONDS:
+    *second = strtod (line, 0);
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+/**********/
+double sec_to_jd (unsigned long second) {
+
+  double jd;
+  
+  jd = second/86400.0 + 2440587.5;
+  return (jd);
+}
+
+/**********/
+unsigned long int jd_to_sec (double jd) {
+
+  unsigned long int second;
+
+  second = (jd - 2440587.5)*86400;
+  return (second);
+}
+
+/**********/
+char *sec_to_date (unsigned long second) {
+  
+  struct tm *gmt;
+  char *line;
+  
+  ALLOCATE (line, char, 64);
+  gmt   = gmtime (&second);
+  sprintf (line, "%4d/%02d/%02d,%02d:%02d:%02d", 1900+gmt[0].tm_year, gmt[0].tm_mon+1, gmt[0].tm_mday, gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+  return (line);
+
+}
+
+/***** date in format yyyy/mm/dd,hh:mm:ss *****/
+unsigned long date_to_sec (char *date) {
+  
+  unsigned long second;
+  double tmp, jd;
+  struct tm now;
+  char *p1, *p2, *px;
+  
+  p1 = date;
+  px = date + strlen(date);
+  bzero (&now, sizeof(now));
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_year = tmp;
+  if (now.tm_year > 1000) now.tm_year -= 1900;
+  if (now.tm_year <   50) now.tm_year += 100;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mon = tmp - 1; /* mon runs from 0 - 11 */
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mday = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  p1 = p2 + 1;
+  now.tm_hour = tmp;
+  if (p2 == px) goto escape;  
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_min = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_sec = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+ escape:
+  jd = now.tm_mday - 32075 + (int)(1461*(1900 + now.tm_year + 4800 + (int)(((now.tm_mon+1)-14)/12))/4)
+    + (int)(367*((now.tm_mon+1) - 2 - (int)(((now.tm_mon+1) - 14)/12)*12)/12)
+    - (int)(3*(int)((1900 + now.tm_year + 4900 + (int)(((now.tm_mon+1) - 14)/12))/100)/4) - 0.5;
+  
+  second = (jd - 2440587.5)*86400 + 3600.0*now.tm_hour + now.tm_min*60.0 + now.tm_sec;
+
+  return (second);
+}
+
+
+/* times may be in forms as:
+   20040200450s (N seconds since 1970.0)
+   2440900.232j (julian date)
+   99/02/23,03:22:18 (date string)
+   (separators may be anything except space, +, -)
+   99:02:15:12:23:30
+   99:02:15:12h23m30s
+   */
+
+
+/* fseek with timeout - 0.5 sec */
+int Fseek (FILE *f, long offset, int whence) {
+
+  int status;
+
+  status = fseek (f, offset, whence);
+  if (status == -1) {
+    int k;
+    /* fprintf (stderr, "problem seeking position: %d\n", errno); */
+    for (k = 0; (k < 10) && ((status = fseek (f, 0, SEEK_SET)) == -1); k++) usleep (50000);
+    if (status == -1) {
+      /* fprintf (stderr, "ERROR: serious problem seeking position: %d\n", errno); */
+      /* clear lock at this point? */
+      return (0);
+    }
+  }
+  return (1);
+}
Index: /tags/start/Ohana/src/uniphot/src/uniphot.c
===================================================================
--- /tags/start/Ohana/src/uniphot/src/uniphot.c	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/src/uniphot.c	(revision 12606)
@@ -0,0 +1,54 @@
+# include "uniphot.h"
+
+int main (int argc, char **argv) {
+
+  int i, j, Nimage, Ntgroup, Nsgroup;
+  Group *tgroup, *sgroup;
+  Image *image;
+  ImageLink *imlinks;
+
+  /* add a mode to check / force consistency between image.Mcal and
+     measure.Mcal use the method in delstar to match image with measure
+     (gregions (image), etc) 
+  */
+
+  /* get configuration info, args, lockfile */
+  initialize (argc, argv);
+
+  /* load images filtered by selection */
+  image = load_images (&Nimage);
+  ALLOCATE (imlinks, ImageLink, Nimage);
+
+  tgroup = find_image_tgroups (image, imlinks, Nimage, &Ntgroup);
+  sgroup = find_image_sgroups (image, imlinks, Nimage, &Nsgroup);
+
+  /* determine fit values */
+  for (i = 0; i < NLOOP; i++) {
+
+    fit_tgroup (tgroup, Ntgroup);
+    fit_sgroup (sgroup, Nsgroup); 
+
+  }    
+
+  fprintf (stdout, "# uniphot results for filter %s\n", photcode[0].name);
+  fprintf (stdout, "# STATMODE: %s\n", STATMODE);
+  fprintf (stdout, "# NLOOP: %d\n", NLOOP);
+  fprintf (stdout, "# time groups : %d\n", Ntgroup);
+  for (i = 0; i < Ntgroup; i++) {
+    fprintf (stdout, "%s %5d %5d %7.4f  %7.4f %7.4f\n", tgroup[i].label, 
+	     tgroup[i].Nimage, tgroup[i].Ngood, 0.001*tgroup[i].M, 0.001*tgroup[i].dM, 0.001*tgroup[i].dMsub);
+  }
+  fprintf (stdout, "\n");
+
+  fprintf (stdout, "# space groups : %d\n", Nsgroup);
+  for (i = 0; i < Nsgroup; i++) {
+    fprintf (stdout, "%s %5d %5d %7.4f  %7.4f %7.4f\n", sgroup[i].label, 
+	     sgroup[i].Nimage, sgroup[i].Ngood, 0.001*sgroup[i].M, 0.001*sgroup[i].dM, 0.001*sgroup[i].dMsub);
+  }
+
+  if (!UPDATE) exit (0);
+
+  update (image, Nimage, sgroup, Nsgroup);
+  exit (0);
+}
+
Index: /tags/start/Ohana/src/uniphot/src/update.c
===================================================================
--- /tags/start/Ohana/src/uniphot/src/update.c	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/src/update.c	(revision 12606)
@@ -0,0 +1,104 @@
+# include "uniphot.h"
+# include <glob.h>
+
+void update (Image *image, int Nimage, Group *sgroup, int Nsgroup) {
+
+  int i, j, status, Nmin;
+  char line[256];
+  glob_t pglob;
+  double Rmin, Rmax, Dmin, Dmax, x, y, radius;
+  Catalog catalog;
+  Coords coords;
+
+  /* clear the NOCAL flags */
+  for (i = 0; i < Nimage; i++) {
+    image[i].code &= ~ID_IMAGE_NOCAL;
+  }
+
+
+  /* apply calculated space-group offset to image Mcal values */
+  for (i = 0; i < Nsgroup; i++) {
+    for (j = 0; j < sgroup[i].Nimage; j++) {
+      sgroup[i].image[j][0].Mcal -= sgroup[i].M;
+    }
+  }
+
+  /** write image table **/
+  wimages (image, Nimage);
+
+  /** update catalog tables **/
+  pglob.gl_offs = 0;
+  sprintf (line, "%s/*/*.cpt", CATDIR);
+  status = glob (line, 0, NULL, &pglob);
+
+  coords.crpix1 = coords.crpix2 = 0.0;
+  coords.cdelt1 = coords.cdelt2 = 1.0; /* scale is degrees, radius in degrees */
+  coords.pc1_1 = coords.pc2_2 = 1.0;
+  coords.pc1_2 = coords.pc2_1 = 0.0;
+  strcpy (coords.ctype, "RA---TAN");
+  
+  for (i = 0; i < pglob.gl_pathc; i++) {
+    catalog.filename = pglob.gl_pathv[i];
+    if (!gcatalog (&catalog)) continue;
+
+    fits_scan (&catalog.header, "RA0", "%lf",  1, &Rmin);
+    fits_scan (&catalog.header, "RA1", "%lf",  1, &Rmax);
+    fits_scan (&catalog.header, "DEC0", "%lf", 1, &Dmin);
+    fits_scan (&catalog.header, "DEC1", "%lf", 1, &Dmax);
+    while (Rmin <   0.0) { Rmin += 360.0; }
+    while (Rmin > 360.0) { Rmin -= 360.0; }
+    while (Rmax <   0.0) { Rmax += 360.0; }
+    while (Rmax > 360.0) { Rmax -= 360.0; }
+
+    coords.crval1 = 0.5*(Rmin + Rmax);
+    coords.crval2 = 0.5*(Dmin + Dmax);
+
+    Nmin = 0;
+    Rmin = 1000;
+    /* primitive version: match catalog with closest sgroup */
+    for (j = 0; j < Nsgroup; j++) {
+      if (!RD_to_XY (&x, &y, sgroup[j].v1, sgroup[j].v2, &coords)) continue;
+      radius = hypot (x, y);
+      if ((j == 0) || (radius < Rmin)) {
+	Rmin = radius;
+	Nmin = j;
+      }
+    }
+
+    fprintf (stderr, "catalog: %s sgroup: %d %s %f\n", catalog.filename, Nmin, sgroup[Nmin].label, Rmin);
+    update_catalog (&catalog, &sgroup[Nmin], (Rmin > 2*RADIUS)); 
+    wcatalog (&catalog); 
+  }
+}      
+
+/* loop over all average 
+
+   if (source equiv photcode)
+
+   loop over sgroups
+
+   if (radius < RADIUS) 
+      
+   average.M (+/-) source.M
+*/
+
+/* loop over all measure 
+
+   if (source equiv photcode)
+
+   loop over sgroups
+
+   if (radius < RADIUS) 
+      
+   measure.Mcal (+/-) source.M
+*/
+
+/* alternative (slower, more robust)
+
+   loop over all average
+   loop over all average.Nm
+   select measure with source equiv photcode
+   match measure to image, get Mcal & offset
+   if any offset for average[i] is different, give error
+   apply offset to average.M
+*/
Index: /tags/start/Ohana/src/uniphot/src/update_catalog.c
===================================================================
--- /tags/start/Ohana/src/uniphot/src/update_catalog.c	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/src/update_catalog.c	(revision 12606)
@@ -0,0 +1,35 @@
+# include "uniphot.h"
+
+update_catalog (Catalog *catalog, Group *sgroup, int warn) {
+
+  int i, j, m, found;
+  int Primary, Nsec, Nsecfilt;
+  short *Mp;
+  PhotCode *code;
+
+  Primary = (photcode[0].type == PHOT_PRI);
+  Nsec = GetPhotcodeNsec (photcode[0].code);
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  found = 0;    
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    
+    Mp = Primary ? &catalog[0].average[i].M : &catalog[0].secfilt[i*Nsecfilt+Nsec].M;
+    if (*Mp != NO_MAG) *Mp += sgroup[0].M;
+
+    m = catalog[0].average[i].offset;
+    for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+      code = GetPhotcodebyCode (catalog[0].measure[m].source);
+      if (code == NULL) continue;
+      if (code[0].type != PHOT_DEP) continue;
+      if (code[0].equiv != photcode[0].code) continue;
+      catalog[0].measure[m].Mcal -= sgroup[0].M;
+      found ++;
+    }
+  }
+
+  if (found) {
+    fprintf (stderr, "found %d matches\n", found);
+    if (warn) fprintf (stderr, "warning: updated values, perhaps out of range?\n");
+  }
+}
Index: /tags/start/Ohana/src/uniphot/src/wcatalog.c
===================================================================
--- /tags/start/Ohana/src/uniphot/src/wcatalog.c	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/src/wcatalog.c	(revision 12606)
@@ -0,0 +1,25 @@
+# include "uniphot.h"
+
+wcatalog (Catalog *catalog) {
+
+  /** write out catalog, free memory **/
+  save_catalog (catalog, VERBOSE);
+      
+  if (catalog[0].Naverage) {
+    free (catalog[0].average); 
+    catalog[0].Naverage = 0;
+  }
+  if (catalog[0].Nmeasure) {
+    free (catalog[0].measure); 
+    catalog[0].Nmeasure = 0;
+  }
+  if (catalog[0].Nmissing) {
+    free (catalog[0].missing); 
+    catalog[0].Nmissing = 0;
+  }
+  if (catalog[0].Nsecfilt) {
+    free (catalog[0].secfilt); 
+    catalog[0].Nsecfilt = 0;
+  }
+  unlock_catalog (catalog);
+}
Index: /tags/start/Ohana/src/uniphot/src/wimages.c
===================================================================
--- /tags/start/Ohana/src/uniphot/src/wimages.c	(revision 12606)
+++ /tags/start/Ohana/src/uniphot/src/wimages.c	(revision 12606)
@@ -0,0 +1,40 @@
+# include "uniphot.h"
+
+wimages (Image *image, int Nimage) {
+
+  int status, mode;
+  char line[256];
+  FILE *f;
+  Header header;
+
+  /* make backup */
+  sprintf (line, "cp %s %s~", ImageCat, ImageCat);
+  if (system (line)) {
+    fprintf (stderr, "ERROR: failed to make backup copy of image table\n");
+    exit (1);
+  }
+
+  /* load image catalog */
+  f = fopen (ImageCat, "r+");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open image catalog file to append: %s\n", ImageCat);
+    exit (1);
+  }
+  if (!fits_fread_header (f, &header)) {
+    fprintf (stderr, "ERROR: can't read header %s\n", ImageCat);
+    exit (1);
+  }
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  chmod (ImageCat, mode);
+  fseek (f, header.size, SEEK_SET);
+
+  /* write image data */
+  if (VERBOSE) fprintf (stderr, "writing out %d images\n", Nimage);
+  status = Fwrite (image, sizeof(Image), Nimage, f, "image");
+  if (status != Nimage) {
+    fprintf (stderr, "ERROR: failed writing data to image catalog\n");
+    exit (1);
+  }
+  fclose (f);
+
+}
Index: /tags/start/PS-IPP-MetaDB/Build.PL
===================================================================
--- /tags/start/PS-IPP-MetaDB/Build.PL	(revision 12606)
+++ /tags/start/PS-IPP-MetaDB/Build.PL	(revision 12606)
@@ -0,0 +1,9 @@
+use Module::Build;
+# See perldoc Module::Build for details of how this works
+
+Module::Build->new(
+    module_name     => 'PS::IPP::MetaDB',
+    build_requires  => {
+      'Class::DBI::mysql'   => 0,
+    },
+)->create_build_script;
Index: /tags/start/PS-IPP-MetaDB/Changes
===================================================================
--- /tags/start/PS-IPP-MetaDB/Changes	(revision 12606)
+++ /tags/start/PS-IPP-MetaDB/Changes	(revision 12606)
@@ -0,0 +1,6 @@
+Revision history for Perl module PS::IPP::MetaDB
+
+0.01 Tue Sep 20 12:20:39 2005
+    - original version; created by ExtUtils::ModuleMaker 0.41
+
+
Index: /tags/start/PS-IPP-MetaDB/LICENSE
===================================================================
--- /tags/start/PS-IPP-MetaDB/LICENSE	(revision 12606)
+++ /tags/start/PS-IPP-MetaDB/LICENSE	(revision 12606)
@@ -0,0 +1,260 @@
+The General Public License (GPL)
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave,
+Cambridge, MA 02139, USA. Everyone is permitted to copy and distribute
+verbatim copies of this license document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share
+and change it. By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to most of
+the Free Software Foundation's software and to any other program whose
+authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom
+to distribute copies of free software (and charge for this service if you wish), that
+you receive source code or can get it if you want it, that you can change the
+software or use pieces of it in new free programs; and that you know you can do
+these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights. These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for a
+fee, you must give the recipients all the rights that you have. You must make
+sure that they, too, receive or can get the source code. And you must show
+them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer
+you this license which gives you legal permission to copy, distribute and/or
+modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced by
+others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We wish
+to avoid the danger that redistributors of a free program will individually obtain
+patent licenses, in effect making the program proprietary. To prevent this, we
+have made it clear that any patent must be licensed for everyone's free use or
+not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+GNU GENERAL PUBLIC LICENSE
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND
+MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License. The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or translated
+into another language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope. The act of running the Program is not
+restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program). Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as
+you receive it, in any medium, provided that you conspicuously and appropriately
+publish on each copy an appropriate copyright notice and disclaimer of warranty;
+keep intact all the notices that refer to this License and to the absence of any
+warranty; and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may at
+your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus
+forming a work based on the Program, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you also
+meet all of these conditions:
+
+a) You must cause the modified files to carry prominent notices stating that you
+changed the files and the date of any change.
+
+b) You must cause any work that you distribute or publish, that in whole or in
+part contains or is derived from the Program or any part thereof, to be licensed
+as a whole at no charge to all third parties under the terms of this License.
+
+c) If the modified program normally reads commands interactively when run, you
+must cause it, when started running for such interactive use in the most ordinary
+way, to print or display an announcement including an appropriate copyright
+notice and a notice that there is no warranty (or else, saying that you provide a
+warranty) and that users may redistribute the program under these conditions,
+and telling the user how to view a copy of this License. (Exception: if the
+Program itself is interactive but does not normally print such an announcement,
+your work based on the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Program, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to
+work written entirely by you; rather, the intent is to exercise the right to control
+the distribution of derivative or collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and 2
+above provided that you also do one of the following:
+
+a) Accompany it with the complete corresponding machine-readable source
+code, which must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange; or,
+
+b) Accompany it with a written offer, valid for at least three years, to give any
+third party, for a charge no more than your cost of physically performing source
+distribution, a complete machine-readable copy of the corresponding source
+code, to be distributed under the terms of Sections 1 and 2 above on a medium
+customarily used for software interchange; or,
+
+c) Accompany it with the information you received as to the offer to distribute
+corresponding source code. (This alternative is allowed only for noncommercial
+distribution and only if you received the program in object code or executable
+form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it. For an executable work, complete source code means all the
+source code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the
+executable. However, as a special exception, the source code distributed need
+not include anything that is normally distributed (in either source or binary form)
+with the major components (compiler, kernel, and so on) of the operating system
+on which the executable runs, unless that component itself accompanies the
+executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source
+code from the same place counts as distribution of the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License. Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License. However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so long
+as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it.
+However, nothing else grants you permission to modify or distribute the Program
+or its derivative works. These actions are prohibited by law if you do not accept
+this License. Therefore, by modifying or distributing the Program (or any work
+based on the Program), you indicate your acceptance of this License to do so,
+and all its terms and conditions for copying, distributing or modifying the
+Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program),
+the recipient automatically receives a license from the original licensor to copy,
+distribute or modify the Program subject to these terms and conditions. You
+may not impose any further restrictions on the recipients' exercise of the rights
+granted herein. You are not responsible for enforcing compliance by third parties
+to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent infringement
+or for any other reason (not limited to patent issues), conditions are imposed on
+you (whether by court order, agreement or otherwise) that contradict the
+conditions of this License, they do not excuse you from the conditions of this
+License. If you cannot distribute so as to satisfy simultaneously your obligations
+under this License and any other pertinent obligations, then as a consequence
+you may not distribute the Program at all. For example, if a patent license would
+not permit royalty-free redistribution of the Program by all those who receive
+copies directly or indirectly through you, then the only way you could satisfy
+both it and this License would be to refrain entirely from distribution of the
+Program.
+
+If any portion of this section is held invalid or unenforceable under any particular
+circumstance, the balance of the section is intended to apply and the section as
+a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other
+property right claims or to contest validity of any such claims; this section has
+the sole purpose of protecting the integrity of the free software distribution
+system, which is implemented by public license practices. Many people have
+made generous contributions to the wide range of software distributed through
+that system in reliance on consistent application of that system; it is up to the
+author/donor to decide if he or she is willing to distribute software through any
+other system and a licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain countries
+either by patents or by copyrighted interfaces, the original copyright holder who
+places the Program under this License may add an explicit geographical
+distribution limitation excluding those countries, so that distribution is permitted
+only in or among countries not thus excluded. In such case, this License
+incorporates the limitation as if written in the body of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the
+General Public License from time to time. Such new versions will be similar in
+spirit to the present version, but may differ in detail to address new problems or
+concerns.
+
+Each version is given a distinguishing version number. If the Program specifies a
+version number of this License which applies to it and "any later version", you
+have the option of following the terms and conditions either of that version or of
+any later version published by the Free Software Foundation. If the Program does
+not specify a version number of this License, you may choose any version ever
+published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission. For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of all
+derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS
+NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
+COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
+"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR
+IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED
+TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY
+WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS
+PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
+(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
+OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
Index: /tags/start/PS-IPP-MetaDB/MANIFEST
===================================================================
--- /tags/start/PS-IPP-MetaDB/MANIFEST	(revision 12606)
+++ /tags/start/PS-IPP-MetaDB/MANIFEST	(revision 12606)
@@ -0,0 +1,8 @@
+MANIFEST
+README
+LICENSE
+Todo
+Changes
+Build.PL
+lib/PS/IPP/MetaDB.pm
+t/01_load.t
Index: /tags/start/PS-IPP-MetaDB/README
===================================================================
--- /tags/start/PS-IPP-MetaDB/README	(revision 12606)
+++ /tags/start/PS-IPP-MetaDB/README	(revision 12606)
@@ -0,0 +1,15 @@
+pod2text PS::IPP::MetaDB.pm > README
+
+If this is still here it means the programmer was too lazy to create the readme file.
+
+You can create it now by using the command shown above from this directory.
+
+At the very least you should be able to use this set of instructions
+to install the module...
+
+perl Build.PL
+./Build
+./Build test
+./Build install
+
+If you are on a windows box you should use 'nmake' rather than 'make'.
Index: /tags/start/PS-IPP-MetaDB/Todo
===================================================================
--- /tags/start/PS-IPP-MetaDB/Todo	(revision 12606)
+++ /tags/start/PS-IPP-MetaDB/Todo	(revision 12606)
@@ -0,0 +1,5 @@
+TODO list for Perl module PS::IPP::MetaDB
+
+- Nothing yet
+
+
Index: /tags/start/PS-IPP-MetaDB/lib/PS/IPP/MetaDB.pm
===================================================================
--- /tags/start/PS-IPP-MetaDB/lib/PS/IPP/MetaDB.pm	(revision 12606)
+++ /tags/start/PS-IPP-MetaDB/lib/PS/IPP/MetaDB.pm	(revision 12606)
@@ -0,0 +1,376 @@
+# Copyright (C) 2005  Joshua Hoblitt
+#
+# $Id: MetaDB.pm,v 1.1.1.1 2005-09-28 01:21:27 jhoblitt Exp $
+
+package PS::IPP::MetaDB;
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION ); 
+$VERSION = '0.01';
+
+use base qw( Class::DBI::mysql );
+
+__PACKAGE__->set_db('Main', 'dbi:mysql:test', 'test', '');
+
+#package PS::IPP::MetaDB::Image::Prepared;
+#package PS::IPP::MetaDB::Image::Reduced;
+#package PS::IPP::MetaDB::Image::Analyzed;
+#package PS::IPP::MetaDB::Image::Combined;
+
+=pod
+
+=head2 Temporal Queues
+
+These queues all describe work that I<needs> to be performed but hasn't
+happened yet.
+
+=over 4
+
+=item * new
+
+This table contains a list of new data waiting to be downloaded from the
+summit.  The location of fetched data files is written into the C<newed> table.
+
+Table description:
+
+=over 4
+
+=item * url
+
+URL to retrieve data from
+
+=item * exp_id
+
+exposure ID #
+
+=item * camera
+
+Camera that this data was acquired from
+
+=item * class
+
+The 'type' of data this is
+
+=item * class_id
+
+A unique identifier for data of the same class in the same exposure.
+
+=back
+
+=cut
+
+package PS::IPP::MetaDB::Image::New;
+
+use base qw( PS::IPP::MetaDB );
+
+__PACKAGE__->table("new");
+__PACKAGE__->create_table(q{
+    exp_id      BIGINT          NOT NULL PRIMARY KEY,
+    class_id    BIGINT          NOT NULL,
+    camera      VARCHAR(255),
+    class       VARCHAR(255),
+    url         VARCHAR(255)    NOT NULL
+});
+__PACKAGE__->set_up_table;
+
+=item * raw
+
+Phase 0.  A list of exposure IDs to extract metadata from.
+
+=over 4
+
+=item * exp_id
+
+exposure ID #, keyed against the C<newed> table.
+
+=item * class_id
+
+Class ID #, keyed against the C<newed> table.
+
+=back
+
+=cut
+
+package PS::IPP::MetaDB::Image::Raw;
+
+use base qw( PS::IPP::MetaDB );
+
+__PACKAGE__->table("raw");
+__PACKAGE__->create_table(q{
+    exp_id      BIGINT          NOT NULL PRIMARY KEY,
+    class_id    BIGINT          NOT NULL 
+});
+__PACKAGE__->set_up_table;
+
+=item * prepare
+
+Phase 1: A list of exposure IDs to extra metadata from.
+
+=over 4
+
+=item * exp_id
+
+exposure ID #, keyed against the C<newed> table.
+
+=item * exp_config
+
+Class ID #, keyed against the C<exposure_config> table.
+
+=back
+
+=item * reduce
+
+Phase 2: A list of exposure components to reduce.
+
+=over 4
+
+=item * exp_id
+
+exposure ID #, keyed against the C<prepared> table.
+
+=item * class_id
+
+class ID #, keyed against the C<prepared> table.
+
+=item * prepared_ver
+
+version #, keyed against the C<prepared> table.
+
+=item * dest_ver
+
+version # to be written into the C<reduced> table.
+
+=back
+
+=item * mosaic
+
+Phase 3: A list of exposures to process.
+
+=over 4
+
+=item * exp_id
+
+exposure ID #, keyed against the C<reduced> table.
+
+=item * exp_config
+
+Class ID #, keyed against the C<exposure_config> table.
+
+=back
+
+=item * combine
+
+=over 4
+
+=item * run_id???
+
+=back
+
+=back
+
+=head2 Metadata
+
+These tables describe data in other tables.
+
+=over 4
+
+=item * exposure
+
+A list of ALL exposure ID #s.
+
+=over 4
+
+=item * exp_id
+
+exposure ID #.
+
+=item * camera
+
+Name of the camera the generated the exposure.
+
+=item * type
+
+The type of exposure taken.
+
+=item * n_components
+
+The number of file that make of the complete exposure.
+
+=back
+
+=item * exposure_component
+
+A list of the files that together make up a complete exposure.
+
+=over 4
+
+=item * exp_id
+
+exposure ID #, keyed against the C<exposure> table.
+
+=item * class_id
+
+class ID #.
+
+=item * class
+
+The type of component this is
+
+=back
+
+=item * exposure_config
+
+This table provides a way to configure which 'version' of components of an
+'exposure' to use.
+
+=over 4
+
+=item * exp_config
+
+exposure config ID #.
+
+=item * class_id
+
+class ID #, keyed against the C<exposure_component> table.
+
+=item * version
+
+version ID #, keyed against the C<exposure_component> table.
+
+=item * n_components
+
+=back
+
+=item * exposure_reduced
+
+A list of version ID #'s assigned after reducing data.  This table is used to
+make sure that all components of an exposure get the same version ID assigned
+to them.
+
+=over 4
+
+=item * exp_id
+
+exposure ID #, keyed on the C<exposure> table.
+
+=item * reduced_version
+
+Version ID # used.
+
+=back
+
+=back
+
+=head2 File Storage
+
+These tables describe data actually stored on disk.
+
+=over 4
+
+=item * newed
+
+Note that there is only one 'version' of the original data.
+
+=over 4
+
+=item * exp_id
+
+exposure ID #, keyed on the C<exposure_component> table.
+
+=item * class_id
+
+class ID #, keyed on the C<exposure_componet> table.
+
+=item * url
+
+url to the storage location of the file.
+
+=back
+
+=cut
+
+package PS::IPP::MetaDB::Image::Newed;
+
+use base qw( PS::IPP::MetaDB );
+
+__PACKAGE__->table("newed");
+__PACKAGE__->create_table(q{
+    exp_id      BIGINT          NOT NULL PRIMARY KEY,
+    class_id    BIGINT          NOT NULL,
+    url         VARCHAR(255)    NOT NULL
+});
+__PACKAGE__->set_up_table;
+
+=item * prepared
+
+Data that has been through Phase: 0.
+
+=over 4
+
+=item * exp_id
+
+exposure ID #, keyed on the C<exposure_component> table.
+
+=item * class_id
+
+class ID #, keyed on the C<exposure_componet> table.
+
+=item * version
+
+version ID #
+
+=item * recipe
+
+algorithm ID #
+
+=item * url
+
+url to the storage location of the file.
+
+=back
+
+=item * reduced
+
+Data that's been through Phase: 2.
+
+=over 4
+
+=item * exp_id
+
+exposure ID #, keyed on the C<exposure_component> table.
+
+=item * class_id
+
+class ID #, keyed on the C<exposure_componet> table.
+
+=item * version
+
+version ID #
+
+=item * recipe
+
+algorithm ID #
+
+=item * url
+
+url to the storage location of the file.
+
+=back
+
+=item * mosaiced
+
+???
+
+=item * combined
+
+???
+
+=back
+
+=cut
+
+1;
+
+__END__
Index: /tags/start/PS-IPP-MetaDB/t/01_load.t
===================================================================
--- /tags/start/PS-IPP-MetaDB/t/01_load.t	(revision 12606)
+++ /tags/start/PS-IPP-MetaDB/t/01_load.t	(revision 12606)
@@ -0,0 +1,12 @@
+# -*- perl -*-
+
+# t/001_load.t - check module loading and create testing directory
+
+use Test::More tests => 2;
+
+BEGIN { use_ok( 'PS::IPP::MetaDB' ); }
+
+my $object = PS::IPP::MetaDB->new ();
+isa_ok ($object, 'PS::IPP::MetaDB');
+
+
Index: /tags/start/PS-IPP-Metadata-Config/Build.PL
===================================================================
--- /tags/start/PS-IPP-Metadata-Config/Build.PL	(revision 12606)
+++ /tags/start/PS-IPP-Metadata-Config/Build.PL	(revision 12606)
@@ -0,0 +1,14 @@
+use Module::Build;
+# See perldoc Module::Build for details of how this works
+
+Module::Build->new(
+    module_name         => 'PS::IPP::Metadata::Config',
+    dist_version_from   => 'lib/PS/IPP/Metadata/Config.pm',
+    author              => 'Joshua Hoblitt <jhoblitt@cpan.org>',
+    license             => 'gpl',
+    requires            =>  {
+        'Parse::RecDescent'     => '1.94',
+        'Class::Accessor::Fast' => '0.19',
+        'Carp'                  => 0,
+    },   
+)->create_build_script;
Index: /tags/start/PS-IPP-Metadata-Config/Changes
===================================================================
--- /tags/start/PS-IPP-Metadata-Config/Changes	(revision 12606)
+++ /tags/start/PS-IPP-Metadata-Config/Changes	(revision 12606)
@@ -0,0 +1,6 @@
+Revision history for Perl module PS::IPP::Metadata::Config
+
+0.01 Tue Feb 22 15:46:35 2005
+	- original version; created by ExtUtils::ModuleMaker 0.32
+
+
Index: /tags/start/PS-IPP-Metadata-Config/LICENSE
===================================================================
--- /tags/start/PS-IPP-Metadata-Config/LICENSE	(revision 12606)
+++ /tags/start/PS-IPP-Metadata-Config/LICENSE	(revision 12606)
@@ -0,0 +1,260 @@
+The General Public License (GPL)
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave,
+Cambridge, MA 02139, USA. Everyone is permitted to copy and distribute
+verbatim copies of this license document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share
+and change it. By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to most of
+the Free Software Foundation's software and to any other program whose
+authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom
+to distribute copies of free software (and charge for this service if you wish), that
+you receive source code or can get it if you want it, that you can change the
+software or use pieces of it in new free programs; and that you know you can do
+these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights. These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for a
+fee, you must give the recipients all the rights that you have. You must make
+sure that they, too, receive or can get the source code. And you must show
+them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer
+you this license which gives you legal permission to copy, distribute and/or
+modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced by
+others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We wish
+to avoid the danger that redistributors of a free program will individually obtain
+patent licenses, in effect making the program proprietary. To prevent this, we
+have made it clear that any patent must be licensed for everyone's free use or
+not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+GNU GENERAL PUBLIC LICENSE
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND
+MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License. The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or translated
+into another language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope. The act of running the Program is not
+restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program). Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as
+you receive it, in any medium, provided that you conspicuously and appropriately
+publish on each copy an appropriate copyright notice and disclaimer of warranty;
+keep intact all the notices that refer to this License and to the absence of any
+warranty; and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may at
+your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus
+forming a work based on the Program, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you also
+meet all of these conditions:
+
+a) You must cause the modified files to carry prominent notices stating that you
+changed the files and the date of any change.
+
+b) You must cause any work that you distribute or publish, that in whole or in
+part contains or is derived from the Program or any part thereof, to be licensed
+as a whole at no charge to all third parties under the terms of this License.
+
+c) If the modified program normally reads commands interactively when run, you
+must cause it, when started running for such interactive use in the most ordinary
+way, to print or display an announcement including an appropriate copyright
+notice and a notice that there is no warranty (or else, saying that you provide a
+warranty) and that users may redistribute the program under these conditions,
+and telling the user how to view a copy of this License. (Exception: if the
+Program itself is interactive but does not normally print such an announcement,
+your work based on the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Program, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to
+work written entirely by you; rather, the intent is to exercise the right to control
+the distribution of derivative or collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and 2
+above provided that you also do one of the following:
+
+a) Accompany it with the complete corresponding machine-readable source
+code, which must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange; or,
+
+b) Accompany it with a written offer, valid for at least three years, to give any
+third party, for a charge no more than your cost of physically performing source
+distribution, a complete machine-readable copy of the corresponding source
+code, to be distributed under the terms of Sections 1 and 2 above on a medium
+customarily used for software interchange; or,
+
+c) Accompany it with the information you received as to the offer to distribute
+corresponding source code. (This alternative is allowed only for noncommercial
+distribution and only if you received the program in object code or executable
+form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it. For an executable work, complete source code means all the
+source code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the
+executable. However, as a special exception, the source code distributed need
+not include anything that is normally distributed (in either source or binary form)
+with the major components (compiler, kernel, and so on) of the operating system
+on which the executable runs, unless that component itself accompanies the
+executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source
+code from the same place counts as distribution of the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License. Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License. However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so long
+as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it.
+However, nothing else grants you permission to modify or distribute the Program
+or its derivative works. These actions are prohibited by law if you do not accept
+this License. Therefore, by modifying or distributing the Program (or any work
+based on the Program), you indicate your acceptance of this License to do so,
+and all its terms and conditions for copying, distributing or modifying the
+Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program),
+the recipient automatically receives a license from the original licensor to copy,
+distribute or modify the Program subject to these terms and conditions. You
+may not impose any further restrictions on the recipients' exercise of the rights
+granted herein. You are not responsible for enforcing compliance by third parties
+to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent infringement
+or for any other reason (not limited to patent issues), conditions are imposed on
+you (whether by court order, agreement or otherwise) that contradict the
+conditions of this License, they do not excuse you from the conditions of this
+License. If you cannot distribute so as to satisfy simultaneously your obligations
+under this License and any other pertinent obligations, then as a consequence
+you may not distribute the Program at all. For example, if a patent license would
+not permit royalty-free redistribution of the Program by all those who receive
+copies directly or indirectly through you, then the only way you could satisfy
+both it and this License would be to refrain entirely from distribution of the
+Program.
+
+If any portion of this section is held invalid or unenforceable under any particular
+circumstance, the balance of the section is intended to apply and the section as
+a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other
+property right claims or to contest validity of any such claims; this section has
+the sole purpose of protecting the integrity of the free software distribution
+system, which is implemented by public license practices. Many people have
+made generous contributions to the wide range of software distributed through
+that system in reliance on consistent application of that system; it is up to the
+author/donor to decide if he or she is willing to distribute software through any
+other system and a licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain countries
+either by patents or by copyrighted interfaces, the original copyright holder who
+places the Program under this License may add an explicit geographical
+distribution limitation excluding those countries, so that distribution is permitted
+only in or among countries not thus excluded. In such case, this License
+incorporates the limitation as if written in the body of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the
+General Public License from time to time. Such new versions will be similar in
+spirit to the present version, but may differ in detail to address new problems or
+concerns.
+
+Each version is given a distinguishing version number. If the Program specifies a
+version number of this License which applies to it and "any later version", you
+have the option of following the terms and conditions either of that version or of
+any later version published by the Free Software Foundation. If the Program does
+not specify a version number of this License, you may choose any version ever
+published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission. For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of all
+derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS
+NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
+COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
+"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR
+IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED
+TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY
+WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS
+PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
+(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
+OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
Index: /tags/start/PS-IPP-Metadata-Config/MANIFEST
===================================================================
--- /tags/start/PS-IPP-Metadata-Config/MANIFEST	(revision 12606)
+++ /tags/start/PS-IPP-Metadata-Config/MANIFEST	(revision 12606)
@@ -0,0 +1,13 @@
+Build.PL
+Changes
+LICENSE
+MANIFEST
+Makefile.PL
+README
+Todo
+docs/sdrs_grammar.txt
+lib/PS/IPP/Metadata/Config.pm
+lib/PS/IPP/Metadata/Config.pod
+t/01_load.t
+t/02_sdrs_example.t
+t/03_gene_example.t
Index: /tags/start/PS-IPP-Metadata-Config/Makefile.PL
===================================================================
--- /tags/start/PS-IPP-Metadata-Config/Makefile.PL	(revision 12606)
+++ /tags/start/PS-IPP-Metadata-Config/Makefile.PL	(revision 12606)
@@ -0,0 +1,27 @@
+unless (eval "use Module::Build::Compat 0.02; 1" ) {
+  print "This module requires Module::Build to install itself.\n";
+
+  require ExtUtils::MakeMaker;
+  my $yn = ExtUtils::MakeMaker::prompt
+    ('  Install Module::Build from CPAN?', 'y');
+
+  if ($yn =~ /^y/i) {
+    require Cwd;
+    require File::Spec;
+    require CPAN;
+
+    # Save this 'cause CPAN will chdir all over the place.
+    my $cwd = Cwd::cwd();
+    my $makefile = File::Spec->rel2abs($0);
+
+    CPAN::Shell->install('Module::Build::Compat');
+
+    chdir $cwd or die "Cannot chdir() back to $cwd: $!";
+    exec $^X, $makefile, @ARGV;  # Redo now that we have Module::Build
+  } else {
+    warn " *** Cannot install without Module::Build.  Exiting ...\n";
+    exit 1;
+  }
+}
+Module::Build::Compat->run_build_pl(args => \@ARGV);
+Module::Build::Compat->write_makefile();
Index: /tags/start/PS-IPP-Metadata-Config/README
===================================================================
--- /tags/start/PS-IPP-Metadata-Config/README	(revision 12606)
+++ /tags/start/PS-IPP-Metadata-Config/README	(revision 12606)
@@ -0,0 +1,16 @@
+pod2text PS::IPP::Metadata::Config.pm > README
+
+If this is still here it means the programmer was too lazy to create the readme file.
+
+You can create it now by using the command shown above from this directory.
+
+At the very least you should be able to use this set of instructions
+to install the module...
+
+perl Build.PL
+./Build
+./Build test
+./Build install
+
+
+If you are on a windows box you should use 'nmake' rather than 'make'.
Index: /tags/start/PS-IPP-Metadata-Config/Todo
===================================================================
--- /tags/start/PS-IPP-Metadata-Config/Todo	(revision 12606)
+++ /tags/start/PS-IPP-Metadata-Config/Todo	(revision 12606)
@@ -0,0 +1,5 @@
+TODO list for Perl module PS::IPP::Metadata::Config
+
+- Nothing yet
+
+
Index: /tags/start/PS-IPP-Metadata-Config/docs/sdrs_grammar.txt
===================================================================
--- /tags/start/PS-IPP-Metadata-Config/docs/sdrs_grammar.txt	(revision 12606)
+++ /tags/start/PS-IPP-Metadata-Config/docs/sdrs_grammar.txt	(revision 12606)
@@ -0,0 +1,144 @@
+startrule: statement(s) /\z/
+
+statement: scalar | vector | multi_declare | comment
+
+comment: '#' end_of_line
+
+scalar: name type value comment | name type value 
+
+vector: vname vtype vvalue comment | vname vtype vvalue 
+
+multi_declare: name '*' end_of_line
+
+name: /[a-z][.\w]*/i
+
+vname: /\@[a-z][.\w]*/i
+
+type: 
+    vtype | 'STR' | 'STRING'
+
+vtype: 
+    'S8'  |
+    'S16' |
+    'S32' |
+    'S64' |
+    'U8'  |
+    'U16' |
+    'U32' |
+    'U64' |
+    'F32' |
+    'F64' |
+    'C32' |
+    'C64' |
+    'BOOL'
+
+value: vector_value | string
+
+vvalue: vector_value vector_sep vvalue | vector_value vector_sep(?)
+
+vector_sep: ','
+
+vector_value: float | int | bool
+
+int: integer_constant
+
+float: floating_constant
+
+bool: /[tf]\s+?/i
+
+string:
+    /\S[^#\n]*/
+
+end_of_line: /[^\n]*/
+
+### based on syntax found in "C A Reference Manual"
+
+# integer constants
+
+integer_constant:
+    decimal_constant integer_suffix(?) |
+    octal_constant integer_suffix(?) |
+    hexadecimal_constant integer_suffix(?)
+
+decimal_constant:
+    digit(2..) |
+    nonzero_digit
+
+octal_constant:
+    '0' octal_digit(s) |
+    '0'
+   
+hexadecimal_constant:
+    hex_prefix hex_digit_sequence
+
+digit:
+    /[0-9]/
+
+nonzero_digit:
+    /[1-9]/
+
+octal_digit:
+    /[0-7]/
+
+hex_digit:
+    /0_9a-f/i
+
+integer_suffix:
+    long_suffix unsigned_suffix(?) |
+    long_long_suffix unsigned_suffix(?) |
+    unsigned_suffix long_suffix(?) |
+    unsigned_suffix long_long_suffix(?)
+
+long_suffix:
+    /l/i
+
+long_long_suffix:
+    /ll/i
+
+unsigned_suffix:
+    /u/i
+
+# floating-point constants
+
+floating_constant:
+    decimal_floating_constant |
+    hexadecimal_floating_constant
+
+decimal_floating_constant:
+    digit_sequence exponent floating_suffix(?) |
+    dotted_digits exponent(?) floating_suffix(?)
+
+digit_sequence:
+    digit(s)
+
+dotted_digits:
+    digit_sequence '.' digit_sequence  |
+    '.' digit_sequence |
+    digit_sequence '.'
+
+exponent:
+    /e/i sign_part digit_sequence
+
+sign_part:
+    /[+-]/
+
+floating_suffix:
+    /[fl]/i
+
+hexadecimal_floating_constant:
+    hex_prefix dotted_hex_digits binary_exponent floating_suffix(?) |
+    hex_prefix hex_digit_sequence binary_exponent floating_suffix(?)
+
+hex_prefix:
+    /0x/i
+
+dotted_hex_digits:
+    hex_digit_sequence '.' hex_digit_sequence |
+    '.' hex_digit_sequence |
+    hex_digit_sequence '.'
+
+hex_digit_sequence:
+    hex_digit(s) 
+
+binary_exponent:
+    /p/i sign_part(?) digit_sequence
Index: /tags/start/PS-IPP-Metadata-Config/lib/PS/IPP/Metadata/Config.pm
===================================================================
--- /tags/start/PS-IPP-Metadata-Config/lib/PS/IPP/Metadata/Config.pm	(revision 12606)
+++ /tags/start/PS-IPP-Metadata-Config/lib/PS/IPP/Metadata/Config.pm	(revision 12606)
@@ -0,0 +1,288 @@
+# Copyright (c) 2005  Joshua Hoblitt
+#
+# $Id#
+
+package PS::IPP::Metadata::Config;
+
+use strict;
+use warnings FATAL => qw( all );
+
+our $VERSION = '0.01';
+
+use Carp qw( carp );
+use Parse::RecDescent;
+#use Data::Dumper;
+
+use base qw( Class::Accessor::Fast );
+__PACKAGE__->mk_accessors( qw( overwrite ) );
+
+#$::RD_TRACE = 1;
+#$::RD_HINT = 1;
+
+my $grammar = do{ local $/; <DATA> };
+
+sub new {
+    my $class = shift;
+
+    my $myparser = Parse::RecDescent->new( $grammar );
+
+    my $self = { _parser => $myparser };
+
+    bless $self, $class;
+
+    $self->overwrite( undef );
+
+    return $self;
+}
+
+sub parse {
+    my ( $self, $metadata ) = @_;
+
+    my $tree = $self->{_parser}->startrule( $metadata );
+
+    # remove comment only lines
+    $self->_strip_comments( $tree ) or return undef;
+
+    # handle multi-declare lines
+    $self->_merge_multi_declares( $tree ) or return undef;
+
+    # look for duplicate names, there should be none after processing the
+    # multi-declares
+    $self->_merge_duplicates( $tree ) or return undef;
+
+    return $tree;
+}
+
+sub _strip_comments {
+    my ( $self, $tree ) = @_;
+
+    # Iteratate through the AoH structure and remove the hashes that have a
+    # class key equal to "comment_line".
+    for (my $i = 0; $i < @{$tree}; $i++) {
+        my $elem = $tree->[$i];
+
+        if ( $elem->{class} eq "comment_line" ) {
+            # delete element from array
+            splice @$tree, $i, 1;
+
+            # the list just got shorter by one element so we don't want to
+            # increment the cursor
+            redo;
+        }
+    }
+
+    return 1;
+}
+
+sub _merge_multi_declares {
+    my ( $self, $tree ) = @_;
+
+    # list of valid multi-declares
+    my %multis;
+
+    # Iteratate through the AoH structure looking for multi-declare
+    # declarations.  This is done in a single pass so multi-declares must
+    # actually be 'declared' before any member elements appear.  
+    for (my $i = 0; $i < @{$tree}; $i++) {
+        my $elem = $tree->[$i];
+
+        if ( $elem->{class} eq "multi_declare" ) {
+            # construct a valid parse spec
+            my $node = {
+                class   => 'vector',
+                name    => $elem->{name},
+                type    => 'STR',   # only strings are allowed
+                value   => [],
+            };
+
+            # add to list of valid multi-declares
+            $multis{ $elem->{name} } = $node;
+
+            # delete mult-declare hash from the array and replace it with the
+            # valid spec
+            splice @$tree, $i, 1, $node;
+
+            next;
+        }
+
+        if ( my $node = $multis{ $elem->{name} } ) {
+            if ( ! $elem->{type} =~ /STR|STRING/ ) {
+                carp "multi-declare element, ",
+                     $elem->{name},
+                     "has type of ",
+                     $elem->{type},
+                     "instead of STR|STRING\n";
+                return undef;
+            }
+
+            # add element value to the appropriate multi-declare element
+            my $vec = $node->{value};
+            push( @$vec, $elem->{value} );
+
+            # delete element from array
+            splice @$tree, $i, 1;
+
+            # the list just got shorter by one element so we don't want to
+            # increment the cursor
+            redo;
+        }
+    }
+
+    return 1;
+}
+
+sub _merge_duplicates {
+    my ( $self, $tree ) = @_;
+
+    # encountered names
+    my %names;
+
+    for (my $i = 0; $i < @{$tree}; $i++) {
+        my $elem = $tree->[$i];
+
+        if ( exists $names{ $elem->{name} } ) {
+            carp "duplicate element name, ", $elem->{name}, "\n";
+
+            if ( $self->{overwrite} ) {
+                # remove the previous occurance
+                splice @{$tree}, $names{ $elem->{name} }, 1;
+            } else {
+                # remove the current occurance
+                splice @{$tree}, $i, 1;
+            }
+        }
+
+        # add element name and location to record of previously seen names
+        $names{ $elem->{name} } = $i;
+    }
+
+    return 1;
+}
+
+1;
+
+__DATA__
+
+startrule:
+    statement(s) /\z/
+        { $item[1 .. -1] }
+
+statement:
+    scalar
+    | vector
+    | multi_declare
+    | comment_line
+
+comment_line:
+    comment
+        {{
+            class   => 'comment_line',
+            comment => $item{comment}
+        }}
+
+comment:
+    '#' end_of_line
+        { $item{end_of_line} }
+
+scalar:
+    name type value comment
+        {{
+            class   => 'scalar',
+            name    => $item{name},
+            type    => $item{type},
+            value   => $item{value},
+            comment => $item{comment}
+         }}
+    | name type value 
+        {{
+            class   => 'scalar',
+            name    => $item{name},
+            type    => $item{type},
+            value   => $item{value},
+        }}
+
+vector:
+    vname vtype vvalue comment
+        {{
+            class   => 'vector',
+            name    => $item{vname},
+            type    => $item{vtype},
+            value   => $item{vvalue},
+            comment => $item{comment}
+         }}
+    | vname vtype vvalue 
+        {{
+            class   => 'vector',
+            name    => $item{vname},
+            type    => $item{vtype},
+            value   => $item{vvalue},
+         }}
+
+multi_declare:
+    name '*' end_of_line
+        {{
+            class   => 'multi_declare',
+            name    => $item{name}, 
+            comment => $item{end_of_line},
+        }}
+
+name:
+    /[a-z][.\w]*/i
+
+vname:
+    /\@[a-z][.\w]*/i
+
+type: 
+    vtype | 'STR' | 'STRING'
+
+vtype: 
+    'S8'
+    | 'S16'
+    | 'S32'
+    | 'S64'
+    | 'U8' 
+    | 'U16'
+    | 'U32'
+    | 'U64'
+    | 'F32'
+    | 'F64'
+    | 'C32'
+    | 'C64'
+    | 'BOOL'
+
+value:
+    primitive | string
+
+
+vvalue:
+    vvalue_(s)
+        { [ map { @$_ } @{$item[1]} ] }
+
+# backtracking optimization
+vvalue_:
+    primitive vector_sep(?)
+        { [ $item[1] ] }
+
+vector_sep:
+    /,|\s+/
+
+primitive:
+    bool | float | int
+
+int:
+    # $RE{num}{int} from Regexp::Common::number
+    /(?:(?:[+-]?)(?:[0-9]+))/
+
+float:
+    # based on $RE{num}{real} from Regexp::Common::number
+    /(?:(?i)(?:[+-]?)(?:(?=[0-9]|[.])(?:[0-9]*)(?:(?:[.])(?:[0-9]{0,}))?)(?:(?:[Ee])(?:(?:[+-]?)(?:[0-9]+))|))/
+
+bool:
+    /[tf]\s+?/i
+        { $item[1] =~ /t/i ? 1 : 0 }
+
+string:
+    /\S[^#\n]*/
+
+end_of_line:
+    /[^\n]*/
Index: /tags/start/PS-IPP-Metadata-Config/lib/PS/IPP/Metadata/Config.pod
===================================================================
--- /tags/start/PS-IPP-Metadata-Config/lib/PS/IPP/Metadata/Config.pod	(revision 12606)
+++ /tags/start/PS-IPP-Metadata-Config/lib/PS/IPP/Metadata/Config.pod	(revision 12606)
@@ -0,0 +1,128 @@
+=pod
+
+=head1 NAME
+
+PS::IPP::Metadata::Config - Parses the psMetadata config language
+
+=head1 SYNOPSIS
+
+    use PS::IPP::Metadata::Config;
+
+    my $mdparser = PS::IPP::Metadata::Config->new;
+    $mdparser->overwrite( 1 );
+
+    my $config = $mdparser->parse( $example );
+
+=head1 DESCRIPTION
+
+Parses the psMetadata configuration language into an AoH parse tree.
+
+=head1 USAGE
+
+=head2 Import Parameters
+
+This module accepts no arguments to it's C<import> method and exports no
+I<symbols>.
+
+=head2 Methods
+
+=head3 Constructors
+
+=over 4
+
+=item * new
+
+Accepts no parameters and returns a L<PS::IPP::Metadata::Config> object.
+
+=back
+
+=head3 Object Methods
+
+=over 4
+
+=item * overwrite
+
+Controls the behavior of the parser when encountering keys that have been
+defined more then once.  A true value instructs the parser to discard all but
+the latest declaration and a false value will preserve the first key parsed.
+Accepts 0, 1, or undef.
+
+Defaults to undef.
+
+=item * parse
+
+Accepts a string.  Returns an AoH structure on success or undef on failure.
+
+The format of the returned structure is as follows:
+
+    [
+        {
+            'comment'   => 'This is a comment',
+            'value'     => '123456789',
+            'name'      => 'Bob',
+            'type'      => 'U64',
+            'class'     => 'scalar'
+        },
+        {
+            'comment'   => 'These are prime numbers',
+            'value'     => [
+                            '2',
+                            '3'
+                        ],
+            'name'      => '@primes',
+            'type'      => 'U8',
+            'class'     => 'vector'
+        },
+        ...
+    ]
+
+=back
+
+=head1 DEVELOPER NOTES
+
+=head2 REFERENCES
+
+=over 4
+
+=item PSDC-430-007
+
+Pan-STARRS PS-1 IPP Library Supplementary Design Requirements Specification
+(SDRS): Section 5.3.4, "Configuration Files".
+
+=back
+
+=head1 CREDITS
+
+Just me, myself, and I.
+
+=head1 SUPPORT
+
+Please contact the author directly via e-mail.
+
+=head1 AUTHOR
+
+Joshua Hoblitt <jhoblitt@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2005  Joshua Hoblitt.  All rights reserved.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA  02111-1307, USA.
+
+The full text of the license can be found in the LICENSE file included with
+this module, or in the L<perlgpl> Pod as supplied with Perl 5.8.1 and later.
+
+=head1 SEE ALSO
+
+=cut
Index: /tags/start/PS-IPP-Metadata-Config/t/01_load.t
===================================================================
--- /tags/start/PS-IPP-Metadata-Config/t/01_load.t	(revision 12606)
+++ /tags/start/PS-IPP-Metadata-Config/t/01_load.t	(revision 12606)
@@ -0,0 +1,14 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2005  Joshua Hoblitt
+#
+# $Id: 01_load.t,v 1.1.1.1 2005-03-01 03:38:45 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use lib qw( ./lib );
+
+use Test::More tests => 1;
+
+BEGIN { use_ok( 'PS::IPP::Metadata::Config' ); }
Index: /tags/start/PS-IPP-Metadata-Config/t/02_sdrs_example.t
===================================================================
--- /tags/start/PS-IPP-Metadata-Config/t/02_sdrs_example.t	(revision 12606)
+++ /tags/start/PS-IPP-Metadata-Config/t/02_sdrs_example.t	(revision 12606)
@@ -0,0 +1,38 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2005  Joshua Hoblitt
+#
+# $Id: 02_sdrs_example.t,v 1.1.1.1 2005-03-01 03:40:20 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use lib qw( ./lib );
+
+use Test::More tests => 1;
+use PS::IPP::Metadata::Config;
+
+my $example = do { local $/; <DATA> };
+
+my $config_parser = PS::IPP::Metadata::Config->new;
+my $pt = $config_parser->parse( $example );
+
+ok( defined( $pt ), "valid parase tree");
+
+__DATA__
+Double     F64     1.23456789      # This is a comment
+Float    F32 0.98765#This is a comment too
+String  STR This is the string that forms the value #comment
+                                                                                                                                          
+ # This is a comment line and is to be ignored
+boolean     BOOL    T # The value of `boolean' is `true'
+                                                                                                                                          
+@primes U8  2,3 5 7,11,13 17 #   These are prime numbers
+                                                                                                                                          
+comment * The rest of this line is ignored, but `comment' is set to be non-unique
+comment STR This
+comment STR     is
+comment STR       a
+comment STR        non-unique
+comment STR                  key
+Float F64 1.23456 # This generates a warning, and, if `overwrite' is `false', is ignored
Index: /tags/start/PS-IPP-Metadata-Config/t/03_gene_example.t
===================================================================
--- /tags/start/PS-IPP-Metadata-Config/t/03_gene_example.t	(revision 12606)
+++ /tags/start/PS-IPP-Metadata-Config/t/03_gene_example.t	(revision 12606)
@@ -0,0 +1,94 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2005  Joshua Hoblitt
+#
+# $Id: 03_gene_example.t,v 1.1.1.1 2005-03-01 03:41:05 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use lib qw( ./lib );
+
+use Test::More tests => 1;
+use PS::IPP::Metadata::Config;
+
+my $example = do { local $/; <DATA> };
+
+my $config_parser = PS::IPP::Metadata::Config->new;
+my $pt = $config_parser->parse( $example );
+
+ok( defined( $pt ), "valid parase tree");
+
+__DATA__
+# these are examples of camera definition variables:
+# skyprobe
+NCELL       S32    1
+NCHIP       S32    1
+#                  FILENAME    EXTNAME  REGION      CHIP      BIASSEC     
+CELL.00     STR    %f00.%x     PHU      [0,0:0,0]   CHIP.00   [0,0:0,0] 
+                   
+# megacam-raw      
+NCELL       S32    72
+NCHIP       S32    36
+#                  FILENAME    EXTNAME  DATASEC     CHIP      BIASSEC     
+CELL.00     STR    %f.%x       AMP00    [0,0:0,0]   CHIP.00   BIASSEC
+CELL.01     STR    %f.%x       AMP01    [0,0:0,0]   CHIP.00   [2100,2110:0,4096]   
+CELL.02     STR    %f.%x       AMP02    [0,0:0,0]   CHIP.01   [0,0:0,0]   
+CELL.03     STR    %f.%x       AMP03    [0,0:0,0]   CHIP.01   [0,0:0,0]   
+
+# megacam-splice
+NCELL       S32    72
+NCHIP       S32    36
+#                  FILENAME    EXTNAME  REGION      CHIP      BIASSEC   TRIMSEC
+CELL.00     STR    %f.%x       CCD00    ASEC-00     CHIP.00   BSEC-00   DSEC-00
+CELL.01     STR    %f.%x       CCD00    ASEC-01     CHIP.00   BSEC-01   DSEC-01
+CELL.02     STR    %f.%x       CCD01    ASEC-00     CHIP.01   BSEC-00   DSEC-00
+CELL.03     STR    %f.%x       CCD01    ASEC-01     CHIP.01   BSEC-01   DSEC-01
+
+# cfh12k-split
+NCELL       S32    12
+NCHIP       S32    12
+#                  FILENAME    EXTNAME  REGION      CHIP      BIASSEC     
+CELL.00     STR    %f/%f00.%x  PHU      [0,0:0,0]   CHIP.00   [0,0:0,0]   
+CELL.01     STR    %f/%f01.%x  PHU      [0,0:0,0]   CHIP.01   [0,0:0,0]   
+CELL.02     STR    %f/%f02.%x  PHU      [0,0:0,0]   CHIP.02   [0,0:0,0]   
+
+# cfh12k-mef
+NCELL       S32    12
+NCHIP       S32    12
+#                  FILENAME    EXTNAME  REGION      CHIP      BIASSEC     
+CELL.00     STR    %f.%x       CHIP00   [0,0:0,0]   CHIP.00   [0,0:0,0]   
+CELL.01     STR    %f.%x       CHIP01   [0,0:0,0]   CHIP.01   [0,0:0,0]   
+CELL.02     STR    %f.%x       CHIP02   [0,0:0,0]   CHIP.02   [0,0:0,0]   
+
+#- REGION can be defined by a header keyword in IRAF format or by a explicit IRAF format 
+#- what is default for NAXIS1,2 for IRAF format?
+#- Nreadout is always NAXIS3?
+
+# recipe file:
+# this makes the assumption that, for a given camera, all chips &
+# cells have the same recipe.  this is probably a good start, but may
+# not cut it in general. eg, it is already clear that for 
+
+# recipe file must be a function of time and camera.
+# 
+
+# BIAS:
+BIAS.IMAGE                 STR    NONE
+BIAS.IMAGE  		   STR    FILE:bias.fits
+BIAS.IMAGE  		   STR    DB:BEST
+BIAS.IMAGE  		   STR    DB:CLOSE
+
+BIAS.OVERSCAN 		   STR    HEADER:BIASSEC
+BIAS.OVERSCAN 		   STR    RECIPE:[0,0:0,0]
+BIAS.OVERSCAN 		   STR    NONE
+
+BIAS.OVERSCAN.STATS 	   STR    MEDIAN
+BIAS.OVERSCAN.STATS 	   STR    MEAN
+
+BIAS.OVERSCAN.FIT          STR    SPLINE
+BIAS.OVERSCAN.FIT.NPTS     S32    5
+
+BIAS.OVERSCAN.FIT          STR    POLYNOMIAL
+BIAS.OVERSCAN.FIT.ORDER    S32    3
+BIAS.OVERSCAN.FIT.NBIN     S32    5
Index: /tags/start/PS-IPP-PSFTP/.cvsignore
===================================================================
--- /tags/start/PS-IPP-PSFTP/.cvsignore	(revision 12606)
+++ /tags/start/PS-IPP-PSFTP/.cvsignore	(revision 12606)
@@ -0,0 +1,6 @@
+Build
+META.yml
+Makefile
+Makefile.PL
+_build
+blib
Index: /tags/start/PS-IPP-PSFTP/Build.PL
===================================================================
--- /tags/start/PS-IPP-PSFTP/Build.PL	(revision 12606)
+++ /tags/start/PS-IPP-PSFTP/Build.PL	(revision 12606)
@@ -0,0 +1,13 @@
+use Module::Build;
+# See perldoc Module::Build for details of how this works
+
+Module::Build->new(
+    module_name         => 'PS::IPP::PSFTP',
+    dist_version_from   => 'lib/PS/IPP/PSFTP.pm',
+    author              => 'Joshua Hoblitt <jhoblitt@cpan.org>',
+    license             => 'gpl',
+    create_makefile_pl  => 'passthrough',
+    recommends      => {
+        'Test::Distribution' => 0,
+    },
+)->create_build_script;
Index: /tags/start/PS-IPP-PSFTP/Changes
===================================================================
--- /tags/start/PS-IPP-PSFTP/Changes	(revision 12606)
+++ /tags/start/PS-IPP-PSFTP/Changes	(revision 12606)
@@ -0,0 +1,6 @@
+Revision history for Perl module PS::IPP::PSFTP
+
+0.01 Wed Oct  5 14:00:26 2005
+    - original version; created by ExtUtils::ModuleMaker 0.41
+
+
Index: /tags/start/PS-IPP-PSFTP/LICENSE
===================================================================
--- /tags/start/PS-IPP-PSFTP/LICENSE	(revision 12606)
+++ /tags/start/PS-IPP-PSFTP/LICENSE	(revision 12606)
@@ -0,0 +1,260 @@
+The General Public License (GPL)
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave,
+Cambridge, MA 02139, USA. Everyone is permitted to copy and distribute
+verbatim copies of this license document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share
+and change it. By contrast, the GNU General Public License is intended to
+guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to most of
+the Free Software Foundation's software and to any other program whose
+authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom
+to distribute copies of free software (and charge for this service if you wish), that
+you receive source code or can get it if you want it, that you can change the
+software or use pieces of it in new free programs; and that you know you can do
+these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny
+you these rights or to ask you to surrender the rights. These restrictions
+translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for a
+fee, you must give the recipients all the rights that you have. You must make
+sure that they, too, receive or can get the source code. And you must show
+them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer
+you this license which gives you legal permission to copy, distribute and/or
+modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If the
+software is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original, so that any problems introduced by
+others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We wish
+to avoid the danger that redistributors of a free program will individually obtain
+patent licenses, in effect making the program proprietary. To prevent this, we
+have made it clear that any patent must be licensed for everyone's free use or
+not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+GNU GENERAL PUBLIC LICENSE
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND
+MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+placed by the copyright holder saying it may be distributed under the terms of
+this General Public License. The "Program", below, refers to any such program
+or work, and a "work based on the Program" means either the Program or any
+derivative work under copyright law: that is to say, a work containing the
+Program or a portion of it, either verbatim or with modifications and/or translated
+into another language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not covered by
+this License; they are outside its scope. The act of running the Program is not
+restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by
+running the Program). Whether that is true depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as
+you receive it, in any medium, provided that you conspicuously and appropriately
+publish on each copy an appropriate copyright notice and disclaimer of warranty;
+keep intact all the notices that refer to this License and to the absence of any
+warranty; and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may at
+your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus
+forming a work based on the Program, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you also
+meet all of these conditions:
+
+a) You must cause the modified files to carry prominent notices stating that you
+changed the files and the date of any change.
+
+b) You must cause any work that you distribute or publish, that in whole or in
+part contains or is derived from the Program or any part thereof, to be licensed
+as a whole at no charge to all third parties under the terms of this License.
+
+c) If the modified program normally reads commands interactively when run, you
+must cause it, when started running for such interactive use in the most ordinary
+way, to print or display an announcement including an appropriate copyright
+notice and a notice that there is no warranty (or else, saying that you provide a
+warranty) and that users may redistribute the program under these conditions,
+and telling the user how to view a copy of this License. (Exception: if the
+Program itself is interactive but does not normally print such an announcement,
+your work based on the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Program, and can be reasonably
+considered independent and separate works in themselves, then this License,
+and its terms, do not apply to those sections when you distribute them as
+separate works. But when you distribute the same sections as part of a whole
+which is a work based on the Program, the distribution of the whole must be on
+the terms of this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to
+work written entirely by you; rather, the intent is to exercise the right to control
+the distribution of derivative or collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program with the
+Program (or with a work based on the Program) on a volume of a storage or
+distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+Section 2) in object code or executable form under the terms of Sections 1 and 2
+above provided that you also do one of the following:
+
+a) Accompany it with the complete corresponding machine-readable source
+code, which must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange; or,
+
+b) Accompany it with a written offer, valid for at least three years, to give any
+third party, for a charge no more than your cost of physically performing source
+distribution, a complete machine-readable copy of the corresponding source
+code, to be distributed under the terms of Sections 1 and 2 above on a medium
+customarily used for software interchange; or,
+
+c) Accompany it with the information you received as to the offer to distribute
+corresponding source code. (This alternative is allowed only for noncommercial
+distribution and only if you received the program in object code or executable
+form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making
+modifications to it. For an executable work, complete source code means all the
+source code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the
+executable. However, as a special exception, the source code distributed need
+not include anything that is normally distributed (in either source or binary form)
+with the major components (compiler, kernel, and so on) of the operating system
+on which the executable runs, unless that component itself accompanies the
+executable.
+
+If distribution of executable or object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the source
+code from the same place counts as distribution of the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+expressly provided under this License. Any attempt otherwise to copy, modify,
+sublicense or distribute the Program is void, and will automatically terminate
+your rights under this License. However, parties who have received copies, or
+rights, from you under this License will not have their licenses terminated so long
+as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it.
+However, nothing else grants you permission to modify or distribute the Program
+or its derivative works. These actions are prohibited by law if you do not accept
+this License. Therefore, by modifying or distributing the Program (or any work
+based on the Program), you indicate your acceptance of this License to do so,
+and all its terms and conditions for copying, distributing or modifying the
+Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program),
+the recipient automatically receives a license from the original licensor to copy,
+distribute or modify the Program subject to these terms and conditions. You
+may not impose any further restrictions on the recipients' exercise of the rights
+granted herein. You are not responsible for enforcing compliance by third parties
+to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent infringement
+or for any other reason (not limited to patent issues), conditions are imposed on
+you (whether by court order, agreement or otherwise) that contradict the
+conditions of this License, they do not excuse you from the conditions of this
+License. If you cannot distribute so as to satisfy simultaneously your obligations
+under this License and any other pertinent obligations, then as a consequence
+you may not distribute the Program at all. For example, if a patent license would
+not permit royalty-free redistribution of the Program by all those who receive
+copies directly or indirectly through you, then the only way you could satisfy
+both it and this License would be to refrain entirely from distribution of the
+Program.
+
+If any portion of this section is held invalid or unenforceable under any particular
+circumstance, the balance of the section is intended to apply and the section as
+a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other
+property right claims or to contest validity of any such claims; this section has
+the sole purpose of protecting the integrity of the free software distribution
+system, which is implemented by public license practices. Many people have
+made generous contributions to the wide range of software distributed through
+that system in reliance on consistent application of that system; it is up to the
+author/donor to decide if he or she is willing to distribute software through any
+other system and a licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain countries
+either by patents or by copyrighted interfaces, the original copyright holder who
+places the Program under this License may add an explicit geographical
+distribution limitation excluding those countries, so that distribution is permitted
+only in or among countries not thus excluded. In such case, this License
+incorporates the limitation as if written in the body of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the
+General Public License from time to time. Such new versions will be similar in
+spirit to the present version, but may differ in detail to address new problems or
+concerns.
+
+Each version is given a distinguishing version number. If the Program specifies a
+version number of this License which applies to it and "any later version", you
+have the option of following the terms and conditions either of that version or of
+any later version published by the Free Software Foundation. If the Program does
+not specify a version number of this License, you may choose any version ever
+published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask for
+permission. For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this.
+Our decision will be guided by the two goals of preserving the free status of all
+derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS
+NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
+COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
+"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR
+IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
+YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED
+TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY
+WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS
+PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
+(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
+OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
Index: /tags/start/PS-IPP-PSFTP/MANIFEST
===================================================================
--- /tags/start/PS-IPP-PSFTP/MANIFEST	(revision 12606)
+++ /tags/start/PS-IPP-PSFTP/MANIFEST	(revision 12606)
@@ -0,0 +1,10 @@
+Build.PL
+Changes
+LICENSE
+MANIFEST
+META.yml
+README
+Todo
+lib/PS/IPP/PSFTP.pm
+t/00_distribution.t
+t/01_load.t
Index: /tags/start/PS-IPP-PSFTP/README
===================================================================
--- /tags/start/PS-IPP-PSFTP/README	(revision 12606)
+++ /tags/start/PS-IPP-PSFTP/README	(revision 12606)
@@ -0,0 +1,15 @@
+pod2text PS::IPP::PSFTP.pm > README
+
+If this is still here it means the programmer was too lazy to create the readme file.
+
+You can create it now by using the command shown above from this directory.
+
+At the very least you should be able to use this set of instructions
+to install the module...
+
+perl Build.PL
+./Build
+./Build test
+./Build install
+
+If you are on a windows box you should use 'nmake' rather than 'make'.
Index: /tags/start/PS-IPP-PSFTP/Todo
===================================================================
--- /tags/start/PS-IPP-PSFTP/Todo	(revision 12606)
+++ /tags/start/PS-IPP-PSFTP/Todo	(revision 12606)
@@ -0,0 +1,5 @@
+TODO list for Perl module PS::IPP::PSFTP
+
+- Nothing yet
+
+
Index: /tags/start/PS-IPP-PSFTP/lib/PS/IPP/PSFTP.pm
===================================================================
--- /tags/start/PS-IPP-PSFTP/lib/PS/IPP/PSFTP.pm	(revision 12606)
+++ /tags/start/PS-IPP-PSFTP/lib/PS/IPP/PSFTP.pm	(revision 12606)
@@ -0,0 +1,111 @@
+package PS::IPP::PSFTP;
+use strict;
+
+BEGIN {
+    use Exporter ();
+    use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+    $VERSION     = '0.01';
+    @ISA         = qw(Exporter);
+    #Give a hoot don't pollute, do not export more than needed by default
+    @EXPORT      = qw();
+    @EXPORT_OK   = qw();
+    %EXPORT_TAGS = ();
+}
+
+
+#################### subroutine header begin ####################
+
+=head2 sample_function
+
+ Usage     : How to use this function/method
+ Purpose   : What it does
+ Returns   : What it returns
+ Argument  : What it wants to know
+ Throws    : Exceptions and other anomolies
+ Comment   : This is a sample subroutine header.
+           : It is polite to include more pod and fewer comments.
+
+See Also   : 
+
+=cut
+
+#################### subroutine header end ####################
+
+
+sub new
+{
+    my ($class, %parameters) = @_;
+
+    my $self = bless ({}, ref ($class) || $class);
+
+    return $self;
+}
+
+
+#################### main pod documentation begin ###################
+## Below is the stub of documentation for your module. 
+## You better edit it!
+
+
+=head1 NAME
+
+PS::IPP::PSFTP - Module abstract (<= 44 characters) goes here
+
+=head1 SYNOPSIS
+
+  use PS::IPP::PSFTP;
+  blah blah blah
+
+
+=head1 DESCRIPTION
+
+Stub documentation for this module was created by ExtUtils::ModuleMaker.
+It looks like the author of the extension was negligent enough
+to leave the stub unedited.
+
+Blah blah blah.
+
+
+=head1 USAGE
+
+
+
+=head1 BUGS
+
+
+
+=head1 SUPPORT
+
+
+
+=head1 AUTHOR
+
+	A. U. Thor
+	CPAN ID: MODAUTHOR
+	XYZ Corp.
+	a.u.thor@a.galaxy.far.far.away
+	http://a.galaxy.far.far.away/modules
+
+=head1 COPYRIGHT
+
+This program is free software licensed under the...
+
+	The General Public License (GPL)
+	Version 2, June 1991
+
+The full text of the license can be found in the
+LICENSE file included with this module.
+
+
+=head1 SEE ALSO
+
+perl(1).
+
+=cut
+
+#################### main pod documentation end ###################
+
+
+1;
+# The preceding line will help the module return a true value
+
Index: /tags/start/PS-IPP-PSFTP/t/00_distribution.t
===================================================================
--- /tags/start/PS-IPP-PSFTP/t/00_distribution.t	(revision 12606)
+++ /tags/start/PS-IPP-PSFTP/t/00_distribution.t	(revision 12606)
@@ -0,0 +1,27 @@
+#!/usr/bin/env perl
+
+# Copyright (C) 2005  Joshua Hoblitt
+#
+# $Id: 00_distribution.t,v 1.1.1.1 2005-10-06 00:03:10 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use lib qw( ./lib ./t );
+
+use Test::More;
+
+# example taken from Test::Distribution Pod
+
+BEGIN {
+    eval {
+        require Test::Distribution;
+    };
+    if($@) {
+        plan skip_all => 'Test::Distribution not installed';
+    } else {
+        # pod tests have to be disabled because of the Pod test strings in
+        # Test::Pod::Tidy
+        import Test::Distribution not => qw( pod );
+    }
+}
Index: /tags/start/PS-IPP-PSFTP/t/01_load.t
===================================================================
--- /tags/start/PS-IPP-PSFTP/t/01_load.t	(revision 12606)
+++ /tags/start/PS-IPP-PSFTP/t/01_load.t	(revision 12606)
@@ -0,0 +1,12 @@
+# -*- perl -*-
+
+# t/001_load.t - check module loading and create testing directory
+
+use Test::More tests => 2;
+
+BEGIN { use_ok( 'PS::IPP::PSFTP' ); }
+
+my $object = PS::IPP::PSFTP->new ();
+isa_ok ($object, 'PS::IPP::PSFTP');
+
+
Index: /tags/start/archive/pslib/include/psImages.h
===================================================================
--- /tags/start/archive/pslib/include/psImages.h	(revision 12606)
+++ /tags/start/archive/pslib/include/psImages.h	(revision 12606)
@@ -0,0 +1,343 @@
+# ifndef (PS_IMAGES_H)
+# define PS_IMAGES_H
+
+/* General image manipulation functions
+ */
+
+// image data type names 
+typedef enum { 
+    psU8  = 1, 
+    psU16 = 2, 
+    psU32 = 3, 
+    psF32 = 4, 
+    psF64 = 5, 
+} psIMAGE_DEPTH;
+
+// An array of real vectors 
+PS_DECLARE_ARRAY_TYPE(psFloatArray);
+PS_CREATE_ARRAY_TYPE(psFloatArray);
+
+// image depth types 
+typedef unsigned char  psU8;
+typedef unsigned short psU16;
+typedef unsigned long  psU32;
+typedef float          psF32;
+typedef double         psF64;
+
+// overlay operations 
+typedef enum { 
+    psOVERLAY_EQUALS   = '=', 
+    psOVERLAY_ADD      = '+', 
+    psOVERLAY_SUBTRACT = '-', 
+    psOVERLAY_MULTIPLY = '*', 
+    psOVERLAY_DIVIDE   = '/', 
+} psOVERLAY_OP;
+
+// binary operations (image / vector?) 
+typedef enum { 
+    psBINARY_ADD        = '+', 
+    psBINARY_SUBTRACT   = '-', 
+    psBINARY_MULTIPLY   = '*', 
+    psBINARY_DIVIDE     = '/', 
+    psBINARY_POWER      = '^', 
+    psBINARY_MIN, 
+    psBINARY_MAX, 
+    psBINARY_LESSTHAN   = '<', 
+    psBINARY_MORETHAN   = '>', 
+    psBINARY_ISEQUAL    = '==', 
+    psBINARY_NOTEQUAL   = '!=', 
+    psBINARY_LESSOREQ   = '<=', 
+    psBINARY_MOREOREQ   = '>=', 
+    psBINARY_AND        = '&&', 
+    psBINARY_OR         = '||', 
+    psBINARY_BITAND     = '&', 
+    psBINARY_BITOR      = '|', 
+    psBINARY_XOR        = '~', 
+    psBINARY_ATAN2      = 'atan2', 
+} psBINARY_OP;
+
+// unary image operations 
+typedef enum { 
+    psUNARY_IS     = '=', 
+    psUNARY_ABS,
+    psUNARY_INT,
+    psUNARY_EXP,
+    psUNARY_TEN,
+    psUNARY_LOG,
+    psUNARY_LN,
+    psUNARY_SQRT,
+    psUNARY_SIN,
+    psUNARY_COS,
+    psUNARY_TAN,
+    psUNARY_DSIN,
+    psUNARY_DCOS,
+    psUNARY_DTAN,
+    psUNARY_ASIN,
+    psUNARY_ACOS,
+    psUNARY_ATAN,
+    psUNARY_DASIN,
+    psUNARY_DACOS,
+    psUNARY_DATAN,
+    psUNARY_RND,
+    psUNARY_NOT,
+    psUNARY_NEGATE = '-',
+    psUNARY_INCR,
+    psUNARY_DECR,
+    psUNARY_ISINF,
+    psUNARY_ISNAN
+} psUNARY_OP;
+
+// basic image data structure 
+typedef struct psImage {
+    int nx, ny;				// size of image 
+    int x0, y0;				// data region relative to parent 
+    psIMAGE_DEPTH depth;		// type of image 
+    psF32 **rows;		        // == rows_f32 
+    psU8  **rows_u8;			// pointers to psU8 data 
+    psU16 **rows_u16;			// pointers to psU16 data 
+    psU32 **rows_u32;			// pointers to psU32 data 
+    psF32 **rows_f32;			// pointers to psF32 data 
+    psF64 **rows_f64;			// pointers to psF64 data 
+    psImage *parent;			// parent, if a subimage 
+    psImage *children;			// children of this region 
+    int Nchildren;			// number of subimages 
+    psDlist md;				// metadata associated with image
+    psObjectTable objtable;		// objects associated with image
+} psImage;
+
+/*** Image structure manipulation ***/
+// create an image of the specified size and type 
+psImage *
+psAllocImage (int nx,			// image width 
+	      int ny,			// image height 
+	      psIMAGE_DEPTH depth	// image depth 
+    );
+
+// create a subimage of the specified area 
+psImage *
+psSubsetImage (psImage *image,		// parent image 
+	       int nx,			// subimage width (<= image.nx - x0)  
+	       int ny,			// subimage width (<= image.ny - y0)  
+	       int x0,			// subimage x-offset (0 <= x0 < nx)   
+	       int y0			// subimage y-offset (0 <= y0 < ny)   
+    );
+
+// destroy the specified image (destroy children if they exist) 
+void 
+psFreeImage (psImage *image		// free this image
+);
+
+// destroy the children of the specified image 
+int 
+psFreeImageChildren (psImage *image	// free children of this image
+);
+
+// create a copy of the specified image 
+psImage *
+psCopyImage (psImage *output, 		// target structure for output image data
+	     psImage *input		// copy this image 
+);
+
+/*** various image pixel extractions ***/
+// extract pixels from rectlinear region to a vector
+psFloatArray *
+psSliceImage (psImage *input, 		// extract slice from this image
+	      int x, 			// starting x coord of region to slice
+	      int y, 			// starting y coord of region to slice
+	      int nx, 			// width of region in x
+	      int ny, 			// width of region in y
+	      enum direction, 		// direction of vector along slice
+	      enum statmode		// statistic applied to pixel group to find output value
+);
+
+// extract pixels along a line to a vector 
+psFloatArray *
+psCutImage (psImage *input, 		// extract cut from this image
+	    float xs, 			// starting x coord of cut
+	    float ys, 			// starting y coord of cut
+	    float xe, 			// ending x coord of cut
+	    float ye, 			// ending y coord of cut
+	    float dw, 			// width of cut
+	    enum statmode		// statistic applied to pixel group to find output value
+);
+
+// extract radial annulii data to a vector 
+psFloatArray *
+psRadialCutImage (psImage *input, 	// extract profile from this image
+		  float x, 		// center x coord of annulii
+		  float y, 		// center y coord of annulii
+		  float radius, 	// outer radius of annulii
+		  float dr,		// radial step size of annulii
+		  enum statmode		// statistic applied to pixel group to find output value
+);
+
+// extract a 2-d contour from an image at the given threshold
+psFloatArrayArray *
+psContourImage (psImage *input, 	// create contour for this image
+		float threshold,	// contour image at this threshold
+		int binning		// bin image by this value for contour calculation
+);
+
+// extract a 2-d contour from an image at the given threshold
+psSpanArray *
+psContourImage (psImage *input, 	// create contour for this image
+		float threshold		//  image at this threshold
+);
+
+/*** various image geometry manipulation ***/
+// rebin image to new scale
+psImage *
+psRebinImage (psImage *input, 		// rebin this image
+	      float scale, 		// rebinning scale: doutput = scale*dinput
+	      enum statmode		// statistic used in performing interpolation / summing
+);
+
+// rotate image by given angle 
+psImage *
+psRotateImage (psImage *input, 		// rotate this image
+	       float angle		// rotate by this amount (degrees)
+);
+
+// shift image by an arbitrary number of pixels in either direction
+// edge pixels value and newly exposed pixels are set to 'exposed'
+psImage *
+psShiftImage (psImage *input, 		// shift this image
+	      float dx, 		// shift by this amount in x
+	      float dy, 		// shift by this amount in y
+	      float exposed		// set exposed pixels to this value
+);
+
+// roll image by an integer number of pixels in either direction
+// edge pixels wrap to the other side (no values are lost)
+psImage *
+psRollImage (psImage *input, 		// roll this image
+	     int dx, 			// roll this amount in x
+	     int dy			// roll this amount in y
+);
+
+// determine statistics for image (or subimage)
+// should we have one function for all stats, or multiple functions?
+// how to represent the output values?
+void
+psStatImage (psImage *input, enum statmode);
+
+// construct a histogram from an image (or subimage)
+psHistogram *
+psHistogramImage (psHistogram,		// input histogram description & target
+		  psImage *input,	// determine histogram of this image
+);
+
+// fit a 2-D polynomial surface to an image
+psFloatArrayArray *
+psFitPolynomialImage (psImage *input, 	// image to fit
+		      int xorder	// order of polynomial in x-dir
+		      int yorder	// order of polynomial in y-dir
+);
+
+/*** image input/output routines ***/
+// read an image or subimage from a named file
+psImage *
+psReadImageSection (psImage *output, 	// place data in this structure for output 
+		    int x, 		// starting x coord of region
+		    int y, 		// starting y coord of region
+		    int dx, 		// x size of region (-1 for full range)
+		    int dy, 		// y size of region (-1 for full range)
+		    int z, 		// plane of interest
+		    char *extname, 	// MEF extension name ("PHU" for primary header)
+		    char *filename	// file to read data from
+);
+
+// read an image or subimage from file descriptor
+psImage *
+psFReadImageSection (psImage *output,	// place data in this structure for output 
+		     int x,		// starting x coord of region		   
+		     int y,		// starting y coord of region		   
+		     int dx,		// x size of region (-1 for full range)	   
+		     int dy,		// y size of region (-1 for full range)	   
+		     int z,		// plane of interest			   
+		     char *extname,	// MEF extension name ("PHU" for primary header)			   
+		     FILE *f		// file descriptor to read data from		   
+);
+
+// write an image section to named file (which may exist)
+psImage *
+psWriteImageSection (psImage *input,    // image to write out
+		     int x, 		// starting x coord of region		   
+		     int y, 		// starting y coord of region		   
+		     int z, 		// plane of interest			   
+		     char *extname, 	// MEF extension name ("PHU" for primary header)			   
+		     char *filename	// file to write data to		   
+);
+
+// write an image section to named file (which may exist)
+psImage *
+psFWriteImageSection (psImage *input,	// image to write out
+		      int x, 		// starting x coord of region		   
+		      int y, 		// starting y coord of region		   
+		      int z, 		// plane of interest			   
+		      char *extname, 	// MEF extension name			   
+		      FILE *f		// file descriptor to write data to		   
+);
+
+// read only header from image file
+psMetadata *
+psReadImageHeader (psMetadata *output, 	// read data to this structure
+		   char *extname, 	// MEF extension name ("PHU" for primary header)
+		   char *filename	// file to read from
+); 
+
+// read only header from image file descriptor
+psMetadata *
+psReadImageHeader (psMetadata *output, 	// read data to this structure
+		   char *extname, 	// MEF extension name ("PHU" for primary header)
+		   FILE *f		// file descriptor to read from
+); 
+
+/*** image FFT operations ***/
+psImage *
+psFFTImage (psImage *input, 		// image to FFT
+	    enum direction		// FFT direction 
+);
+
+/*** basic pixel manipulations ***/
+// clip image values outside of range to given values 
+int
+psClipImage (psImage *input, 		// clip this image
+	     float min, 		// clip pixels with values < min
+	     float vmin, 		// set min-clipped pixels to vmin
+	     float max, 		// clip pixels with values > max
+	     float vmax			// set max-clipped pixels to vmax
+);
+
+// clip NaN image pixels to given value 
+int
+psClipNaNImage (psImage *input, 	// clip this image
+		float value		// set nan pixels to this value
+);
+
+/*** image arithmetic ***/
+// perform a binary operation on two images 
+psImage *
+psImageBinaryOp (psImage *out,		// destination image (may be NULL) 
+		 psImage *in1,		// first input image 
+		 psImage *in2,		// second input image 
+		 psBINARY_OP OP		// operator 
+    );
+
+// perform a unary operation on an image
+psImage *
+psImageUnaryOp (psImage *out,		// destination image (may be NULL) 
+		psImage *in1,		// input image 
+		psUNARY_OP OP		// operator 
+    );
+
+// overlay subregion of image with another image
+int 
+psOverlayImage (psImage *image,		// input image 
+		psImage *overlay,	// image to overlay 
+		int x0,			// x offset of overlay subimage 
+		int y0,			// y offset of overlay subimage 
+		psOVERLAY_OP op		// overlay operation 
+    );
+
+# endif
Index: /tags/start/doc/design/datasys_cost.tex
===================================================================
--- /tags/start/doc/design/datasys_cost.tex	(revision 12606)
+++ /tags/start/doc/design/datasys_cost.tex	(revision 12606)
@@ -0,0 +1,233 @@
+\documentclass[panstarrs,psreport]{panstarrs}
+%\usepackage{array}
+
+%\documentclass[panstarrs]{panstarrs}
+
+% basic document variables
+\title{Pan-STARRS PS1 Data Systems Cost Estimate}
+\author{Joshua Hoblitt}
+\shorttitle{PS1 Datasys Cost}
+\group{Pan-STARRS Algorithm Group}
+\project{Pan-STARRS Image Processing Pipeline}
+\organization{Institute for Astronomy}
+\version{01}
+\docnumber{PSDC-xxx-xxx}
+% note the use of the docnumber & version number:
+% the complete PSDC document number is given by
+% \thedocnumber-\theversion
+
+\begin{document}
+\maketitle
+
+% -- Revision History --
+% provide explicit values for the old versions
+% use '\theversion' for the current version (set above)
+% use \hline between each table row
+\RevisionsStart
+% version     Date         Description
+01          & 2004.03.08 & First draft \\
+\hline
+\RevisionsEnd
+
+\pagebreak
+\tableofcontents
+
+\pagebreak
+\listoffigures
+
+\pagebreak 
+\pagenumbering{arabic}
+
+\section{Scope}
+
+\subsection{Identification}
+
+This document establishes the estimated cost of the network and computing hardware necessary to support PS1.  Due to the rapid rate of change in the IT industry the part numbers specified in this document may change prior to the actual purchase of equipment but the cost structure is expected to remain stable.
+
+\section{Image Processing Pipeline and Data Storage Equipment}
+
+\subsection{Requirements}
+
+\subsubsection{CPU}
+
+Phase 2 and phase 4 dominate the IPP computational processing needs.  Assuming 3.0GHz CPUs we need 40 CPUs for phase 2 and 30 CPUs for phase 4.
+
+\subsubsection{Storage}
+
+The storage needs for the first year of PS1's operation have been estimated to be between 700-1100TB.  Assuming that 0.5TB SATA disks become available in the next year we will require between 2000-3000 units.
+
+\subsection{Hardware}
+
+A 5u rackmount case has been identified that can support 24 hot-swappable SATA disks, 1 internal disk, and a dual CPU motherboard.  The large data storage capacity requirement is the driver for the number of complete systems we will have to acquire.
+
+We will need between 85 and 132 nodes to support our data requirements.
+
+\begin{center}
+\begin{tabular}{lrrr}
+% \begin{tabular}{>{$}l<{$}>{$}r>{$}r>{$}r}
+Item&Estimated Price&85 nodes&132 nodes\\
+\cline{1-4}
+24 x 0.5TB SATA disks (bulk storage)	&\$7,200 &\$61,200  &\$950,400\\
+1 x 0.5TB SATA disk (OS + software)	&\$300   &\$25,500  &\$39,600\\
+2 x 3.0GHz CPUs				&\$2,000 &\$170,000 &\$264,000\\
+2 x 12-port SATA raid controller	&\$1,500 &\$127,500 &\$198,000\\
+1 x Motherboard				&\$500   &\$42,500  &\$66,000\\
+4 x 1GB RAM DIMM			&\$1,400 &\$119,000 &\$184,800\\
+1 x 5u Rackmount Chassis		&\$2,800 &\$238,000 &\$369,600\\
+\cline{1-4}
+					&$\sim$\$16,000&\$1,360,000&\$2,112,000\\
+\end{tabular}
+\end{center}
+
+\subsubsection{Spares}
+
+\tbd{TBD}
+
+\subsubsection{Maintenance}
+
+\tbd{TBD}
+
+\section{Network Equipment}
+
+\subsection{Requirements}
+
+\subsubsection{Bandwidth}
+
+It has been estimated that we need a throughput of $\sim604Mb/s$ to support PS1 at a 30s cadence.  A OC-12c Packet over SONET connection can provide enough bandwidth.
+
+\subsubsection{Switch ports}
+
+We will needs to support 32 x Summit Pixel Servers and up to 16 x Servers/Workstations at the summit.  The data center switch should be able to support up to 192 computation nodes and control computers.
+
+\subsection{Network Link}
+
+An OC-12c PoS link from the summit of Haleakala to Kihei on Maui will cost \$16,970 per month with a 3-year contract or \$16,460 per month with a 5-year contract.  Setup fees will vary by location and are estimated to be in the range of \$10,000 - \$100,000 per end point (\$20K - \$200K total).  
+
+\subsection{Hardware}
+
+\subsubsection{Data Center Core Switch}
+
+\begin{center}
+Cisco 6513
+\begin{tabular}{lr}
+Item&Estimated Price\\
+\cline{1-2}
+1 x WS-C6513 Cat 6513	&\$15,250\\
+1 x WS-X6K-S720-6408A	&\$33,000\\
+4 x WS-X6548-RJ-45	&\$17,995\\
+1 x WS-C6K-13SLT-FAN2	&\$745\\
+2 x WS-CAC-4000W-US	&\$5,000\\
+\cline{1-2}
+			&$\sim$\$76,990\\
+\end{tabular}
+\end{center}
+
+\subsubsection{Summit Core Switch}
+
+\begin{center}
+Cisco 6513
+\begin{tabular}{lr}
+Item&Estimated Price\\
+\cline{1-2}
+1 x WS-C6513 Cat 6513	&\$15,250\\
+1 x WS-X6K-S720-6408A	&\$33,000\\
+4 x WS-X6548-RJ-45	&\$17,995\\
+1 x WS-C6K-13SLT-FAN2	&\$745\\
+2 x WS-CAC-4000W-US	&\$5,000\\
+\cline{1-2}
+			&$\sim$\$130,975\\
+\end{tabular}
+\end{center}
+
+\subsubsection{Summit Border Router}
+
+\begin{center}
+Cisco 7606
+\begin{tabular}{lr}
+Item&Estimated Price\\
+\cline{1-2}
+7606-SUP720XL-PS	&\$49,500\\
+OSM-2OC12-POS-SI+	&\$60,000\\
+WS-X6548-RJ-45		&\$17,995\\
+\cline{1-2}
+			&$\sim$\$127,495\\
+\end{tabular}
+\end{center}
+
+\subsubsection{Date Center Border Router}
+
+\begin{center}
+Cisco 7606
+\begin{tabular}{lr}
+Item&Estimated Price\\
+\cline{1-2}
+7606-SUP720XL-PS	&\$49,500\\
+OSM-2OC12-POS-SI+	&\$60,000\\
+WS-X6548-RJ-45		&\$17,995\\
+\cline{1-2}
+			&$\sim$\$127,495\\
+\end{tabular}
+\end{center}
+
+\subsubsection{Spares}
+
+\tbd{TBD}
+
+\subsubsection{Maintenance}
+
+\tbd{Cisco SmartNet contracts are typically $\sim5\%$ of the purchase price.}
+
+\section{Moving Object Pipeline Equipment}
+
+\subsection{Requirements}
+
+\tbd{TBD}
+
+\subsection{Hardware}
+
+\tbd{TBD}
+
+\subsubsection{Spares}
+
+\tbd{TBD}
+
+\subsubsection{Maintenance}
+
+\tbd{TBD}
+
+\section{Software}
+
+\subsection{Lustre}
+
+\subsubsection{Maintenance}
+
+\tbd{TBD}
+
+\section{Power Consumption}
+
+\tbd{Total power consumptions is TBD}
+
+\section{Misc}
+
+\subsection{Hardware}
+
+\begin{center}
+\begin{tabular}{lr}
+Item&Estimated Price\\
+\cline{1-2}
+Racks/cabinets	&\$50,000\\
+Cabling		&\$25,000\\
+Tools		&\$10,000\\
+\cline{1-2}
+		&$\sim$\$85,000\\
+\end{tabular}
+\end{center}
+
+\subsection{Electrical Wiring}
+
+Each cabinet will require 4 x 220v/15amp circuits.  \tbd{Material/labor costs are TBD}.
+
+\bibliographystyle{plain}
+\bibliography{panstarrs}
+
+\end{document}
Index: /tags/start/glueforge/glueforge.in
===================================================================
--- /tags/start/glueforge/glueforge.in	(revision 12606)
+++ /tags/start/glueforge/glueforge.in	(revision 12606)
@@ -0,0 +1,159 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2005  Joshua Hoblitt
+#
+# $Id: glueforge.in,v 1.1.1.1 2005-04-01 03:01:18 jhoblitt Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use vars qw( $VERSION );
+$VERSION = '0.01';
+
+use Data::Dumper;
+use PS::IPP::Metadata::Config;
+use Template;
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version );
+use Pod::Usage qw( pod2usage );
+
+my ( $input, $output, $template );
+GetOptions(
+    'input=s'       => \$input,
+    'output=s'      => \$output,
+    'template=s'    => \$template,
+) || pod2usage( 2 );
+
+pod2usage( -msg => "Unknown option: @ARGV", -exitval => 2 ) if @ARGV;
+pod2usage( -msg => "Required option: --input|-i", -exitval => 2 ) unless $input;
+
+$template = "./template" unless $template;
+
+die "file doesn't exist: $input" unless -e $input;
+die "file isn't readable: $input" unless -r $input;
+
+my $config = parse_config( $input );
+
+my %data;
+
+# find table name
+for (my $i = 0; $i < @{$config}; $i++) {
+    my $elem = $config->[$i];
+
+    if ( $elem->{name} eq "table" ) {
+        $data{table_name} = $elem->{value};
+
+        # delete element from array
+        splice @$config, $i, 1;
+
+        last;
+    }
+}
+
+$data{data_type} = $data{table_name} . "Row";
+$data{namespace} = $data{table_name};
+
+my @items;
+
+# setup items
+for (my $i = 0; $i < @{$config}; $i++) {
+    my $elem = $config->[$i];
+
+    my $mdtypes = lookup_type( $elem->{type} );
+    next if ! defined $mdtypes;
+
+    push @items, {
+        name    => $elem->{name},
+        type    => $elem->{type},
+        ctype   => $mdtypes->{ctype},
+        mtype   => $mdtypes->{mtype},
+        comment => $elem->{comment},
+        value   => $elem->{value},
+    };
+}
+
+$data{columns} = \@items;
+
+#my ( $bootstrap, $configure, $m4, $topmake, $srcmake, $makefile, $header, $code );
+
+my %tt = (
+    'bootstrap_sh.tt'   => "$output/bootstrap.sh",
+    'configure_ac.tt'   => "$output/configure.ac",
+    'top_makefile_am.tt'=> "$output/Makefile.am",
+    'src_makefile_am.tt'=> "$output/src/Makefile.am",
+    'header.tt'         => "$output/src/$data{table_name}db.h",
+    'code.tt'           => "$output/src/$data{table_name}db.c",
+);
+
+my $mangler = Template->new({ INCLUDE_PATH => $template });
+
+if ( $output ) {
+    foreach my $t ( keys %tt ) {
+        $mangler->process( $t, \%data, $tt{$t})
+            or die $mangler->error;
+    }
+} else {
+    foreach my $t ( keys %tt ) {
+        $mangler->process( $t, \%data )
+            or die $mangler->error;
+    }
+}
+
+#$mangler->process( "bootstrap_sh.tt", \%data, $bootstrap)
+#    or die $mangler->error;
+#$mangler->process( "configure_ac.tt", \%data, $configure)
+#    or die $mangler->error;
+#$mangler->process( "top_makefile_am.tt", \%data, $topmake)
+#    or die $mangler->error;
+#$mangler->process( "ac_check_mysqlr.tt", \%data, $m4)
+#    or die $mangler->error;
+#$mangler->process( "src_makefile_am.tt", \%data, $srcmake)
+#    or die $mangler->error;
+#$mangler->process( "header.tt", \%data, $header)
+#    or die $mangler->error;
+#$mangler->process( "code.tt", \%data, $code)
+#    or die $mangler->error;
+
+sub parse_config {
+    my $file = shift;
+
+    my $mdparser = PS::IPP::Metadata::Config->new;
+    $mdparser->overwrite( 1 );
+
+    open( my $data, $file ) or die "can't open file: $!";
+    my $example = do { local $/; <$data> };
+    close( $data ) or die "can't close file: $!";
+
+    my $config = $mdparser->parse( $example )
+        or die "error parsing file: $input";
+
+    return $config;
+}
+
+sub lookup_type {
+    my $type = shift;
+
+    my %primitives = map { $_ => 1 } qw( S8 S16 S32 S64 U8 U16 U32 U64 F32 F64 );
+    my %mtypes = map { $_ => "PS_META_$_" } keys %primitives;
+    my %ctypes = map { $_ => "ps$_" } keys %primitives;
+
+    if ( $primitives{$type} ) {
+        return {
+            ctype   => $ctypes{$type},
+            mtype   => $mtypes{$type},
+        };
+    } elsif ( $type =~ /STR|STRING/ ) {
+        return {
+            ctype   => "char*",
+            mtype   => 'PS_META_STR',
+        };
+    } elsif ( $type =~ /BOOL/ ) {
+        return {
+            ctype   => "bool",
+            mtype   => 'PS_META_STR',
+        };
+    } else {
+        return undef;
+    }
+}
+
Index: /tags/start/glueforge/templates/psdb/bootstrap_sh.tt
===================================================================
--- /tags/start/glueforge/templates/psdb/bootstrap_sh.tt	(revision 12606)
+++ /tags/start/glueforge/templates/psdb/bootstrap_sh.tt	(revision 12606)
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+libtoolize --automake --copy \
+&& aclocal \
+&& autoheader \
+&& automake --foreign --add-missing --copy \
+&& autoconf
Index: /tags/start/glueforge/templates/psdb/code.tt
===================================================================
--- /tags/start/glueforge/templates/psdb/code.tt	(revision 12606)
+++ /tags/start/glueforge/templates/psdb/code.tt	(revision 12606)
@@ -0,0 +1,7 @@
+#include "[% table_name %]db.h"
+
+[% INCLUDE init.tt %]
+
+[% INCLUDE create.tt %]
+
+[% INCLUDE insert.tt %]
Index: /tags/start/glueforge/templates/psdb/configure_ac.tt
===================================================================
--- /tags/start/glueforge/templates/psdb/configure_ac.tt	(revision 12606)
+++ /tags/start/glueforge/templates/psdb/configure_ac.tt	(revision 12606)
@@ -0,0 +1,16 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT([[% table_name %]db], [0.0.1], [pan-starrs.ifa.hawaii.edu])
+AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
+AM_CONFIG_HEADER(src/config.h)
+
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_LIBTOOL
+AC_SUBST(LIBTOOL_DEPS)
+
+PKG_CHECK_MODULES(PSLIB, pslib >= 0.5.0) 
+
+dnl AC_CHECK_MYSQLR
+dnl AC_SUBST([MYSQL_CFLAGS MYSQL_LIBS])
+
+AC_OUTPUT(Makefile src/Makefile)
Index: /tags/start/glueforge/templates/psdb/create.tt
===================================================================
--- /tags/start/glueforge/templates/psdb/create.tt	(revision 12606)
+++ /tags/start/glueforge/templates/psdb/create.tt	(revision 12606)
@@ -0,0 +1,26 @@
+bool [% table_name %]CreateTable(psDB *dbh) {
+    psMetadata          *md;
+    bool                status;
+
+    md = psMetadataAlloc();
+    psMetadataAdd(md, 0, "index", PS_META_S32, "Key");
+    [%- SET i = 1 %]
+    [%- FOREACH item = columns %]
+        [%- IF item.comment;
+                SET item.comment = "\"$item.comment\"";
+            ELSE;
+                SET item.comment = 'NULL';
+            END;
+        %]
+        [%- IF item.value %]
+    psMetadataAdd(md, [% i %], "[% item.name %]", [% item.mtype %], [% item.comment %], [% item.value %]);
+        [%- ELSE %]
+    psMetadataAdd(md, [% i %], "[% item.name %]", [% item.mtype %], [% item.comment %]);
+        [%- END %]
+        [%- i = i + 1 %]
+    [%- END %]
+    status = psDBCreateTable(dbh, "[% table_name %]", md);
+    psFree(md);
+
+    return status;
+}
Index: /tags/start/glueforge/templates/psdb/create_h.tt
===================================================================
--- /tags/start/glueforge/templates/psdb/create_h.tt	(revision 12606)
+++ /tags/start/glueforge/templates/psdb/create_h.tt	(revision 12606)
@@ -0,0 +1,7 @@
+/** Creates a new [% table_name %] table
+ *
+ * @return true on success
+ */
+bool [% namespace %]CreateTable(
+    psDB            *dbh                ///< Database handle
+);
Index: /tags/start/glueforge/templates/psdb/datatype.tt
===================================================================
--- /tags/start/glueforge/templates/psdb/datatype.tt	(revision 12606)
+++ /tags/start/glueforge/templates/psdb/datatype.tt	(revision 12606)
@@ -0,0 +1,8 @@
+[% USE format -%]
+[% indented = format('%-15s %s') -%]
+typedef struct {
+[% SET i = 0 -%]
+[% FOREACH item = columns -%]
+    [% indented("$item.ctype", "$item.name") %];
+[% END -%]
+} [% data_type %];
Index: /tags/start/glueforge/templates/psdb/header.tt
===================================================================
--- /tags/start/glueforge/templates/psdb/header.tt	(revision 12606)
+++ /tags/start/glueforge/templates/psdb/header.tt	(revision 12606)
@@ -0,0 +1,25 @@
+#ifndef [% table_name %]_DB_H
+#define [% table_name %]_DB_H 1
+
+#include <pslib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// @addtogroup DataBase
+/// @{
+
+[% INCLUDE datatype.tt %]
+[% INCLUDE init_h.tt %]
+[% INCLUDE create_h.tt %]
+[% INCLUDE insert_h.tt %]
+[% INCLUDE pop_h.tt %]
+
+/// @}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // [% table_name %]_DB_H
Index: /tags/start/glueforge/templates/psdb/init.tt
===================================================================
--- /tags/start/glueforge/templates/psdb/init.tt	(revision 12606)
+++ /tags/start/glueforge/templates/psdb/init.tt	(revision 12606)
@@ -0,0 +1,8 @@
+psDB *[% table_name %]Init(const char *host, const char *user, const char *passwd, const char *dbname) {
+
+    psDB            *dbh;
+
+    dbh = psDBInit(host, user, passwd, dbname);
+
+    return dbh;
+}
Index: /tags/start/glueforge/templates/psdb/init_h.tt
===================================================================
--- /tags/start/glueforge/templates/psdb/init_h.tt	(revision 12606)
+++ /tags/start/glueforge/templates/psdb/init_h.tt	(revision 12606)
@@ -0,0 +1,11 @@
+/** Opens a new database connection
+ *
+ *  @return A new psDB object if the database connection is successful or NULL
+ *  on failure.
+ */
+psDB *[% namespace %]Init(
+    const char      *host,              ///< Database server hostname
+    const char      *user,              ///< Database username
+    const char      *passwd,            ///< Database password
+    const char      *dbname             ///< Database namespace
+);
Index: /tags/start/glueforge/templates/psdb/insert.tt
===================================================================
--- /tags/start/glueforge/templates/psdb/insert.tt	(revision 12606)
+++ /tags/start/glueforge/templates/psdb/insert.tt	(revision 12606)
@@ -0,0 +1,28 @@
+bool [% table_name %]Insert(psDB * dbh,
+    [%- SET i = 0 -%]
+    [%- FOREACH item = columns -%]
+        [%- IF i == 0 -%]
+            [%- i = 1 -%]
+ 
+        [%- ELSE -%]
+, 
+        [%- END -%]
+        [%- item.ctype %] [% item.name %]
+        [%- i = i + 1 -%]
+    [%- END -%]
+)
+{
+    psMetadata      *row;
+    bool            status;
+
+    row = psMetadataAlloc();
+    [%- SET i = 0 %]
+    [%- FOREACH item = columns %]
+    psMetadataAdd(row, [% i %], "[% item.name %]", [% item.mtype %], NULL, [% item.name %]);
+        [%- i = i + 1 %]
+    [%- END %]
+    status = psDBInsertOneRow(dbh, "[% table_name %]", row);
+    psFree(row);
+
+    return status;
+}
Index: /tags/start/glueforge/templates/psdb/insert_h.tt
===================================================================
--- /tags/start/glueforge/templates/psdb/insert_h.tt	(revision 12606)
+++ /tags/start/glueforge/templates/psdb/insert_h.tt	(revision 12606)
@@ -0,0 +1,17 @@
+[% USE format -%]
+[% indented = format('%-15s %s') -%]
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+bool [% namespace %]Insert(
+    psDB            *dbh,               ///< Database handle
+[%- SET i = 0 -%]
+[% FOREACH item = columns -%]
+[% IF i == 0 %][% i = 1 %][% ELSE %],[% END %]
+    [% indented("$item.ctype", "$item.name") -%]
+[% i = i + 1 -%]
+[% END %]
+);
Index: /tags/start/glueforge/templates/psdb/makefile.tt
===================================================================
--- /tags/start/glueforge/templates/psdb/makefile.tt	(revision 12606)
+++ /tags/start/glueforge/templates/psdb/makefile.tt	(revision 12606)
@@ -0,0 +1,19 @@
+SHELL   = /bin/sh
+CFLAGS  = -g -O0 -pipe -fpic -Wall -pedantic -std=c99
+LIBS    = -lpslib
+CFLAGS += `mysql_config --cflags`
+LIBS   += `mysql_config --libs`
+
+
+objects=[% table_name %]db.o
+
+all: lib[% table_name %]db.so
+
+lib[% table_name %]db.so: $(objects)
+	$(CC) $(CFLAGS) -shared -o lib[% table_name %]db.so $(objects) $(LIBS)
+
+$(objects): %.o : %.c
+	$(CC) $(CFLAGS) -o $@ -c $<
+
+clean:
+	$(RM) *.so *.o core test
Index: /tags/start/glueforge/templates/psdb/pop_h.tt
===================================================================
--- /tags/start/glueforge/templates/psdb/pop_h.tt	(revision 12606)
+++ /tags/start/glueforge/templates/psdb/pop_h.tt	(revision 12606)
@@ -0,0 +1,10 @@
+/** Removes the last row from the database and returns it
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+[% data_type %] [% namespace %]Pop(
+    psDB            *dbh                ///< Database handle
+);
Index: /tags/start/glueforge/templates/psdb/src_makefile_am.tt
===================================================================
--- /tags/start/glueforge/templates/psdb/src_makefile_am.tt	(revision 12606)
+++ /tags/start/glueforge/templates/psdb/src_makefile_am.tt	(revision 12606)
@@ -0,0 +1,10 @@
+AM_CFLAGS   = @AM_CFLAGS@
+AM_CFLAGS   += $(PSLIB_CFLAGS)
+AM_LIBS     = $(PSLIB_LIBS)
+
+include_HEADERS=[% table_name %]db.h
+lib_LTLIBRARIES = lib[% table_name %]db.la
+lib[% table_name %]db_la_LDFLAGS = -release @PACKAGE_VERSION@
+lib[% table_name %]db_la_SOURCES =\
+    [% table_name %]db.h\
+    [% table_name %]db.c
Index: /tags/start/glueforge/templates/psdb/top_makefile_am.tt
===================================================================
--- /tags/start/glueforge/templates/psdb/top_makefile_am.tt	(revision 12606)
+++ /tags/start/glueforge/templates/psdb/top_makefile_am.tt	(revision 12606)
@@ -0,0 +1,4 @@
+ACLOCAL_AMFLAGS = -I m4
+
+AM_CFLAGS  = -g -O0 -pipe -fpic -Wall -pedantic -std=c99
+SUBDIRS = src
Index: /tags/start/ippdb/Doxyfile.in
===================================================================
--- /tags/start/ippdb/Doxyfile.in	(revision 12606)
+++ /tags/start/ippdb/Doxyfile.in	(revision 12606)
@@ -0,0 +1,1219 @@
+# Doxyfile 1.4.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = @PACKAGE_NAME@
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = @PACKAGE_VERSION@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+# @top_builddir@ doesn't work for some reason
+OUTPUT_DIRECTORY       = @builddir@/docs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, 
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, 
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, 
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, 
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# This tag can be used to specify the encoding used in the generated output. 
+# The encoding is not always determined by the language that is chosen, 
+# but also whether or not the output is meant for Windows or non-Windows users. 
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
+# forces the Windows encoding (this is the default for the Windows binary), 
+# whereas setting the tag to NO uses a Unix-style encoding (the default for 
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING   = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like the Qt-style comments (thus requiring an 
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
+# only. Doxygen will then generate output that is more tailored for Java. 
+# For instance, namespaces will be presented as packages, qualified scopes 
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation.
+
+SHOW_DIRECTORIES       = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from the 
+# version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the progam writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = @top_srcdir@/src
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS          = *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories.
+
+EXCLUDE_PATTERNS       = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default) 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = YES
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse 
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = @PERL@
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option is superseded by the HAVE_DOT option below. This is only a 
+# fallback. It is recommended to install and use dot, since it yields more 
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
+# generate a call dependency graph for every global function or class method. 
+# Note that enabling this option will significantly increase the time of a run. 
+# So in most cases it will be better to enable call graphs for selected 
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT   = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that a graph may be further truncated if the graph's 
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH 
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), 
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is disabled by default, which results in a white background. 
+# Warning: Depending on the platform used, enabling this option may lead to 
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to 
+# read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
Index: /tags/start/ippdb/Makefile.am
===================================================================
--- /tags/start/ippdb/Makefile.am	(revision 12606)
+++ /tags/start/ippdb/Makefile.am	(revision 12606)
@@ -0,0 +1,51 @@
+SUBDIRS = src tests
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA= ippdb.pc
+
+EXTRA_DIST = ippdb.pc.in Doxyfile.in
+
+if DOXYGEN
+
+man_MANS = \
+    $(top_builddir)/docs/man/man3/ippdb.3 \
+    $(top_builddir)/docs/man/man3/weatherRow.3 \
+    $(top_builddir)/docs/man/man3/skyp_transparencyRow.3 \
+    $(top_builddir)/docs/man/man3/skyp_absorptionRow.3 \
+    $(top_builddir)/docs/man/man3/skyp_emissionRow.3 \
+    $(top_builddir)/docs/man/man3/dimmRow.3 \
+    $(top_builddir)/docs/man/man3/skyp_irRow.3 \
+    $(top_builddir)/docs/man/man3/domeRow.3 \
+    $(top_builddir)/docs/man/man3/telescopeRow.3 \
+    $(top_builddir)/docs/man/man3/summitExpRow.3 \
+    $(top_builddir)/docs/man/man3/pzPendingExpRow.3 \
+    $(top_builddir)/docs/man/man3/pzPendingImfileRow.3 \
+    $(top_builddir)/docs/man/man3/newExpRow.3 \
+    $(top_builddir)/docs/man/man3/newImfileRow.3 \
+    $(top_builddir)/docs/man/man3/rawDetrendExpRow.3 \
+    $(top_builddir)/docs/man/man3/rawScienceExpRow.3 \
+    $(top_builddir)/docs/man/man3/rawImfileRow.3 \
+    $(top_builddir)/docs/man/man3/p1PendingExpRow.3 \
+    $(top_builddir)/docs/man/man3/p2PendingExpRow.3 \
+    $(top_builddir)/docs/man/man3/p2PendingImfileRow.3 \
+    $(top_builddir)/docs/man/man3/p2DoneExpRow.3 \
+    $(top_builddir)/docs/man/man3/p2DoneImfileRow.3 \
+    $(top_builddir)/docs/man/man3/p3PendingExpRow.3 \
+    $(top_builddir)/docs/man/man3/detRunRow.3 \
+    $(top_builddir)/docs/man/man3/detInputExpRow.3 \
+    $(top_builddir)/docs/man/man3/detProcessedImfileRow.3 \
+    $(top_builddir)/docs/man/man3/detStackedImfileRow.3 \
+    $(top_builddir)/docs/man/man3/detNormalizedImfileRow.3 \
+    $(top_builddir)/docs/man/man3/detMasterFrameRow.3 \
+    $(top_builddir)/docs/man/man3/detMasterImfileRow.3 \
+    $(top_builddir)/docs/man/man3/detResidImfileAnalysisRow.3 \
+    $(top_builddir)/docs/man/man3/detResidExpAnalysisRow.3 
+
+
+docs/man/man3/ippdb.3 docs/man/man3/weatherRow.3 docs/man/man3/skyp_transparencyRow.3 docs/man/man3/skyp_absorptionRow.3 docs/man/man3/skyp_emissionRow.3 docs/man/man3/dimmRow.3 docs/man/man3/skyp_irRow.3 docs/man/man3/domeRow.3 docs/man/man3/telescopeRow.3 docs/man/man3/summitExpRow.3 docs/man/man3/pzPendingExpRow.3 docs/man/man3/pzPendingImfileRow.3 docs/man/man3/newExpRow.3 docs/man/man3/newImfileRow.3 docs/man/man3/rawDetrendExpRow.3 docs/man/man3/rawScienceExpRow.3 docs/man/man3/rawImfileRow.3 docs/man/man3/p1PendingExpRow.3 docs/man/man3/p2PendingExpRow.3 docs/man/man3/p2PendingImfileRow.3 docs/man/man3/p2DoneExpRow.3 docs/man/man3/p2DoneImfileRow.3 docs/man/man3/p3PendingExpRow.3 docs/man/man3/detRunRow.3 docs/man/man3/detInputExpRow.3 docs/man/man3/detProcessedImfileRow.3 docs/man/man3/detStackedImfileRow.3 docs/man/man3/detNormalizedImfileRow.3 docs/man/man3/detMasterFrameRow.3 docs/man/man3/detMasterImfileRow.3 docs/man/man3/detResidImfileAnalysisRow.3 docs/man/man3/detResidExpAnalysisRow.3:
+	$(DOXYGEN)
+
+endif
+
+clean-local:
+	-rm -rf docs
Index: /tags/start/ippdb/autogen.sh
===================================================================
--- /tags/start/ippdb/autogen.sh	(revision 12606)
+++ /tags/start/ippdb/autogen.sh	(revision 12606)
@@ -0,0 +1,103 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+PROJECT=ippdb
+TEST_TYPE=-f
+# change this to be a unique filename in the top level dir
+FILE=autogen.sh
+
+DIE=0
+
+LIBTOOLIZE=libtoolize
+ACLOCAL=aclocal
+AUTOHEADER=autoheader
+AUTOMAKE=automake
+AUTOCONF=autoconf
+
+($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $LIBTOOlIZE installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/libtool/"
+        DIE=1
+}
+
+($ACLOCAL --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $ACLOCAL installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/automake/"
+        DIE=1
+}
+
+($AUTOHEADER --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOHEADER installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/"
+        DIE=1
+}
+
+($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOMAKE installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/automake/"
+        DIE=1
+}
+
+($AUTOCONF --version) < /dev/null > /dev/null 2>&1 || {
+        echo
+        echo "You must have $AUTOCONF installed to compile $PROJECT."
+        echo "Download the appropriate package for your distribution,"
+        echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/"
+        DIE=1
+}
+
+if test "$DIE" -eq 1; then
+        exit 1
+fi
+
+test $TEST_TYPE $FILE || {
+        echo "You must run this script in the top-level $PROJECT directory"
+        exit 1
+}
+
+if test -z "$*"; then
+        echo "I am going to run ./configure with no arguments - if you wish "
+        echo "to pass any to it, please specify them on the $0 command line."
+fi
+
+$LIBTOOLIZE --copy --force || echo "$LIBTOOlIZE failed"
+$ACLOCAL || echo "$ACLOCAL failed"
+$AUTOHEADER || echo "$AUTOHEADER failed"
+$AUTOMAKE --add-missing --force-missing --copy || echo "$AUTOMAKE failed"
+$AUTOCONF || echo "$AUTOCONF failed"
+
+cd $ORIGDIR
+
+run_configure=true
+for arg in $*; do
+    case $arg in
+        --no-configure)
+            run_configure=false
+            ;;
+        *)
+            ;;
+    esac
+done
+
+if $run_configure; then
+    $srcdir/configure --enable-maintainer-mode "$@"
+    echo
+    echo "Now type 'make' to compile $PROJECT."
+else
+    echo
+    echo "Now run 'configure' and 'make' to compile $PROJECT."
+fi
Index: /tags/start/ippdb/configure.ac
===================================================================
--- /tags/start/ippdb/configure.ac	(revision 12606)
+++ /tags/start/ippdb/configure.ac	(revision 12606)
@@ -0,0 +1,39 @@
+AC_PREREQ(2.59)
+
+AC_INIT([ippdb], [0.0.1], [pan-starrs.ifa.hawaii.edu])
+AC_CONFIG_SRCDIR([ippdb.pc.in])
+
+AM_INIT_AUTOMAKE([1.6 foreign dist-bzip2])
+AM_CONFIG_HEADER([config.h])
+AM_MAINTAINER_MODE
+
+AC_CONFIG_TESTDIR([tests])
+AC_CONFIG_FILES([tests/Makefile])
+AM_MISSING_PROG([AUTOM4TE], [autom4te])
+
+AC_LANG(C)
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_LIBTOOL
+
+PKG_CHECK_MODULES([PSLIB], [pslib >= 0.9.0]) 
+
+AC_PATH_PROG([PERL], [perl], [missing])
+if test "$PERL" = "missing" ; then
+  AC_MSG_ERROR([perl is required])
+fi
+
+AC_PATH_PROG([doxygen], [doxygen], [missing])
+AM_CONDITIONAL([DOXYGEN], test "x$doxygen" = "xmissing")
+
+dnl is this the best was to setup recursive CFLAGS?
+ippdb_CFLAGS="-Wall -pedantic -std=c99 -fno-strict-aliasing"
+AC_SUBST([ippdb_CFLAGS])
+
+AC_CONFIG_FILES([
+  Makefile
+  src/Makefile
+  ippdb.pc
+  Doxyfile
+])
+AC_OUTPUT
Index: /tags/start/ippdb/ippdb.pc.in
===================================================================
--- /tags/start/ippdb/ippdb.pc.in	(revision 12606)
+++ /tags/start/ippdb/ippdb.pc.in	(revision 12606)
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: @PACKAGE@
+Description: some library
+Version: @VERSION@
+Requires: pslib
+Libs: -L${libdir} -l@PACKAGE@
+Cflags: -I${includedir}
Index: /tags/start/ippdb/src/Makefile.am
===================================================================
--- /tags/start/ippdb/src/Makefile.am	(revision 12606)
+++ /tags/start/ippdb/src/Makefile.am	(revision 12606)
@@ -0,0 +1,10 @@
+AM_CFLAGS = @ippdb_CFLAGS@
+
+include_HEADERS = ippdb.h
+lib_LTLIBRARIES = libippdb.la
+libippdb_la_CFLAGS  = $(PSLIB_CFLAGS) $(AM_CFLAGS)
+libippdb_la_LIBS    = $(PSLIB_LIBS) $(AM_LIBS)
+libippdb_la_LDFLAGS = -release $(PACKAGE_VERSION)
+libippdb_la_SOURCES = \
+    ippdb.h \
+    ippdb.c
Index: /tags/start/ippdb/src/ippdb.c
===================================================================
--- /tags/start/ippdb/src/ippdb.c	(revision 12606)
+++ /tags/start/ippdb/src/ippdb.c	(revision 12606)
@@ -0,0 +1,14463 @@
+#include "ippdb.h"
+
+#define WEATHER_TABLE_NAME "weather"
+#define WEATHER_INDEX_NAME "position"
+#define SKYP_TRANSPARENCY_TABLE_NAME "skyp_transparency"
+#define SKYP_TRANSPARENCY_INDEX_NAME "position"
+#define SKYP_ABSORPTION_TABLE_NAME "skyp_absorption"
+#define SKYP_ABSORPTION_INDEX_NAME "position"
+#define SKYP_EMISSION_TABLE_NAME "skyp_emission"
+#define SKYP_EMISSION_INDEX_NAME "position"
+#define DIMM_TABLE_NAME "dimm"
+#define DIMM_INDEX_NAME "position"
+#define SKYP_IR_TABLE_NAME "skyp_ir"
+#define SKYP_IR_INDEX_NAME "position"
+#define DOME_TABLE_NAME "dome"
+#define DOME_INDEX_NAME "position"
+#define TELESCOPE_TABLE_NAME "telescope"
+#define TELESCOPE_INDEX_NAME "position"
+#define SUMMITEXP_TABLE_NAME "summitExp"
+#define SUMMITEXP_INDEX_NAME "position"
+#define PZPENDINGEXP_TABLE_NAME "pzPendingExp"
+#define PZPENDINGEXP_INDEX_NAME "position"
+#define PZPENDINGIMFILE_TABLE_NAME "pzPendingImfile"
+#define PZPENDINGIMFILE_INDEX_NAME "position"
+#define NEWEXP_TABLE_NAME "newExp"
+#define NEWEXP_INDEX_NAME "position"
+#define NEWIMFILE_TABLE_NAME "newImfile"
+#define NEWIMFILE_INDEX_NAME "position"
+#define RAWDETRENDEXP_TABLE_NAME "rawDetrendExp"
+#define RAWDETRENDEXP_INDEX_NAME "position"
+#define RAWSCIENCEEXP_TABLE_NAME "rawScienceExp"
+#define RAWSCIENCEEXP_INDEX_NAME "position"
+#define RAWIMFILE_TABLE_NAME "rawImfile"
+#define RAWIMFILE_INDEX_NAME "position"
+#define P1PENDINGEXP_TABLE_NAME "p1PendingExp"
+#define P1PENDINGEXP_INDEX_NAME "position"
+#define P2PENDINGEXP_TABLE_NAME "p2PendingExp"
+#define P2PENDINGEXP_INDEX_NAME "position"
+#define P2PENDINGIMFILE_TABLE_NAME "p2PendingImfile"
+#define P2PENDINGIMFILE_INDEX_NAME "position"
+#define P2DONEEXP_TABLE_NAME "p2DoneExp"
+#define P2DONEEXP_INDEX_NAME "position"
+#define P2DONEIMFILE_TABLE_NAME "p2DoneImfile"
+#define P2DONEIMFILE_INDEX_NAME "position"
+#define P3PENDINGEXP_TABLE_NAME "p3PendingExp"
+#define P3PENDINGEXP_INDEX_NAME "position"
+#define DETRUN_TABLE_NAME "detRun"
+#define DETRUN_INDEX_NAME "position"
+#define DETINPUTEXP_TABLE_NAME "detInputExp"
+#define DETINPUTEXP_INDEX_NAME "position"
+#define DETPROCESSEDIMFILE_TABLE_NAME "detProcessedImfile"
+#define DETPROCESSEDIMFILE_INDEX_NAME "position"
+#define DETSTACKEDIMFILE_TABLE_NAME "detStackedImfile"
+#define DETSTACKEDIMFILE_INDEX_NAME "position"
+#define DETNORMALIZEDIMFILE_TABLE_NAME "detNormalizedImfile"
+#define DETNORMALIZEDIMFILE_INDEX_NAME "position"
+#define DETMASTERFRAME_TABLE_NAME "detMasterFrame"
+#define DETMASTERFRAME_INDEX_NAME "position"
+#define DETMASTERIMFILE_TABLE_NAME "detMasterImfile"
+#define DETMASTERIMFILE_INDEX_NAME "position"
+#define DETRESIDIMFILEANALYSIS_TABLE_NAME "detResidImfileAnalysis"
+#define DETRESIDIMFILEANALYSIS_INDEX_NAME "position"
+#define DETRESIDEXPANALYSIS_TABLE_NAME "detResidExpAnalysis"
+#define DETRESIDEXPANALYSIS_INDEX_NAME "position"
+#define MAX_STRING_LENGTH 1024
+
+psDB *ippdbInit(const char *host, const char *user, const char *passwd, const char *dbname)
+{
+    return psDBInit(host, user, passwd, dbname);
+}
+
+void ippdbCleanup(psDB *dbh)
+{
+    psDBCleanup(dbh);
+}
+
+static void weatherRowFree(weatherRow *object);
+
+weatherRow *weatherRowAlloc(psF32 temp01, psF32 humi01, psF32 temp02, psF32 humi02, psF32 temp03, psF32 humi03, psF32 pressure)
+{
+    weatherRow      *object;
+
+    object = psAlloc(sizeof(weatherRow));
+    psMemSetDeallocator(object, (psFreeFunc)weatherRowFree);
+
+    object->temp01 = temp01;
+    object->humi01 = humi01;
+    object->temp02 = temp02;
+    object->humi02 = humi02;
+    object->temp03 = temp03;
+    object->humi03 = humi03;
+    object->pressure = pressure;
+
+    return object;
+}
+
+static void weatherRowFree(weatherRow *object)
+{
+}
+
+bool weatherCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, WEATHER_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", WEATHER_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "temp01", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item temp01");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "humi01", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item humi01");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "temp02", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item temp02");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "humi02", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item humi02");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "temp03", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item temp03");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "humi03", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item humi03");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "pressure", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item pressure");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, WEATHER_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool weatherDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, WEATHER_TABLE_NAME);
+}
+
+bool weatherInsert(psDB * dbh, psF32 temp01, psF32 humi01, psF32 temp02, psF32 humi02, psF32 temp03, psF32 humi03, psF32 pressure)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "temp01", 0, NULL, temp01)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item temp01");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "humi01", 0, NULL, humi01)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item humi01");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "temp02", 0, NULL, temp02)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item temp02");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "humi02", 0, NULL, humi02)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item humi02");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "temp03", 0, NULL, temp03)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item temp03");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "humi03", 0, NULL, humi03)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item humi03");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "pressure", 0, NULL, pressure)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item pressure");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, WEATHER_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool weatherPop(psDB *dbh, psF32 *temp01, psF32 *humi01, psF32 *temp02, psF32 *humi02, psF32 *temp03, psF32 *humi03, psF32 *pressure)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, WEATHER_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", WEATHER_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, WEATHER_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", WEATHER_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, WEATHER_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, WEATHER_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *temp01 = psMetadataLookupF32(&status, row, "temp01");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item temp01");
+        psFree(row);
+        return false;
+    }
+    *humi01 = psMetadataLookupF32(&status, row, "humi01");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item humi01");
+        psFree(row);
+        return false;
+    }
+    *temp02 = psMetadataLookupF32(&status, row, "temp02");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item temp02");
+        psFree(row);
+        return false;
+    }
+    *humi02 = psMetadataLookupF32(&status, row, "humi02");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item humi02");
+        psFree(row);
+        return false;
+    }
+    *temp03 = psMetadataLookupF32(&status, row, "temp03");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item temp03");
+        psFree(row);
+        return false;
+    }
+    *humi03 = psMetadataLookupF32(&status, row, "humi03");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item humi03");
+        psFree(row);
+        return false;
+    }
+    *pressure = psMetadataLookupF32(&status, row, "pressure");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item pressure");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool weatherInsertObject(psDB *dbh, weatherRow *object)
+{
+    return weatherInsert(dbh, object->temp01, object->humi01, object->temp02, object->humi02, object->temp03, object->humi03, object->pressure);
+}
+
+weatherRow *weatherPopObject(psDB *dbh)
+{
+    psF32           temp01;
+    psF32           humi01;
+    psF32           temp02;
+    psF32           humi02;
+    psF32           temp03;
+    psF32           humi03;
+    psF32           pressure;
+
+    if (!weatherPop(dbh, &temp01, &humi01, &temp02, &humi02, &temp03, &humi03, &pressure)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return weatherRowAlloc(temp01, humi01, temp02, humi02, temp03, humi03, pressure);
+}
+
+bool weatherInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  WEATHER_TABLE_NAME
+    if (!psFitsMoveExtName(fits, WEATHER_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", WEATHER_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, WEATHER_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool weatherPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!weatherSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                WEATHER_TABLE_NAME, WEATHER_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool weatherSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, WEATHER_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, WEATHER_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", WEATHER_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, WEATHER_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *weatherMetadataFromObject(const weatherRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "temp01", 0, NULL, object->temp01)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item temp01");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "humi01", 0, NULL, object->humi01)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item humi01");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "temp02", 0, NULL, object->temp02)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item temp02");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "humi02", 0, NULL, object->humi02)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item humi02");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "temp03", 0, NULL, object->temp03)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item temp03");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "humi03", 0, NULL, object->humi03)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item humi03");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "pressure", 0, NULL, object->pressure)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item pressure");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+weatherRow *weatherObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    psF32           temp01;
+    psF32           humi01;
+    psF32           temp02;
+    psF32           humi02;
+    psF32           temp03;
+    psF32           humi03;
+    psF32           pressure;
+
+    temp01 = psMetadataLookupF32(&status, md, "temp01");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item temp01");
+        return false;
+    }
+    humi01 = psMetadataLookupF32(&status, md, "humi01");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item humi01");
+        return false;
+    }
+    temp02 = psMetadataLookupF32(&status, md, "temp02");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item temp02");
+        return false;
+    }
+    humi02 = psMetadataLookupF32(&status, md, "humi02");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item humi02");
+        return false;
+    }
+    temp03 = psMetadataLookupF32(&status, md, "temp03");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item temp03");
+        return false;
+    }
+    humi03 = psMetadataLookupF32(&status, md, "humi03");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item humi03");
+        return false;
+    }
+    pressure = psMetadataLookupF32(&status, md, "pressure");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item pressure");
+        return false;
+    }
+
+    return weatherRowAlloc(temp01, humi01, temp02, humi02, temp03, humi03, pressure);
+}
+psArray *weatherSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, WEATHER_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, WEATHER_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", WEATHER_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, weatherObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long weatherDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        weatherRow *object = objects->data[i];
+        psMetadata *where = weatherMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, WEATHER_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from weather");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void skyp_transparencyRowFree(skyp_transparencyRow *object);
+
+skyp_transparencyRow *skyp_transparencyRowAlloc(const char *filter, psF64 trans, psS32 nstars, psF64 ra, psF64 decl, psF32 exptime, psF64 sky_bright)
+{
+    skyp_transparencyRow *object;
+
+    object = psAlloc(sizeof(skyp_transparencyRow));
+    psMemSetDeallocator(object, (psFreeFunc)skyp_transparencyRowFree);
+
+    object->filter = psStringCopy(filter);
+    object->trans = trans;
+    object->nstars = nstars;
+    object->ra = ra;
+    object->decl = decl;
+    object->exptime = exptime;
+    object->sky_bright = sky_bright;
+
+    return object;
+}
+
+static void skyp_transparencyRowFree(skyp_transparencyRow *object)
+{
+    psFree(object->filter);
+}
+
+bool skyp_transparencyCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, SKYP_TRANSPARENCY_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", SKYP_TRANSPARENCY_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "trans", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item trans");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "nstars", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item nstars");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item ra");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item decl");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "exptime", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exptime");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "sky_bright", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item sky_bright");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, SKYP_TRANSPARENCY_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool skyp_transparencyDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, SKYP_TRANSPARENCY_TABLE_NAME);
+}
+
+bool skyp_transparencyInsert(psDB * dbh, const char *filter, psF64 trans, psS32 nstars, psF64 ra, psF64 decl, psF32 exptime, psF64 sky_bright)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, psStringCopy(filter))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "trans", 0, NULL, trans)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item trans");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "nstars", 0, NULL, nstars)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item nstars");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, ra)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item ra");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, decl)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item decl");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "exptime", 0, NULL, exptime)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exptime");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "sky_bright", 0, NULL, sky_bright)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item sky_bright");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, SKYP_TRANSPARENCY_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool skyp_transparencyPop(psDB *dbh, char **filter, psF64 *trans, psS32 *nstars, psF64 *ra, psF64 *decl, psF32 *exptime, psF64 *sky_bright)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, SKYP_TRANSPARENCY_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", SKYP_TRANSPARENCY_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, SKYP_TRANSPARENCY_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", SKYP_TRANSPARENCY_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, SKYP_TRANSPARENCY_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, SKYP_TRANSPARENCY_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *filter = psMetadataLookupPtr(&status, row, "filter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item filter");
+        psFree(row);
+        return false;
+    }
+    *trans = psMetadataLookupF64(&status, row, "trans");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item trans");
+        psFree(row);
+        return false;
+    }
+    *nstars = psMetadataLookupS32(&status, row, "nstars");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item nstars");
+        psFree(row);
+        return false;
+    }
+    *ra = psMetadataLookupF64(&status, row, "ra");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item ra");
+        psFree(row);
+        return false;
+    }
+    *decl = psMetadataLookupF64(&status, row, "decl");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item decl");
+        psFree(row);
+        return false;
+    }
+    *exptime = psMetadataLookupF32(&status, row, "exptime");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exptime");
+        psFree(row);
+        return false;
+    }
+    *sky_bright = psMetadataLookupF64(&status, row, "sky_bright");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item sky_bright");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool skyp_transparencyInsertObject(psDB *dbh, skyp_transparencyRow *object)
+{
+    return skyp_transparencyInsert(dbh, object->filter, object->trans, object->nstars, object->ra, object->decl, object->exptime, object->sky_bright);
+}
+
+skyp_transparencyRow *skyp_transparencyPopObject(psDB *dbh)
+{
+    char            filter[256];
+    psF64           trans;
+    psS32           nstars;
+    psF64           ra;
+    psF64           decl;
+    psF32           exptime;
+    psF64           sky_bright;
+
+    if (!skyp_transparencyPop(dbh, (char **)&filter, &trans, &nstars, &ra, &decl, &exptime, &sky_bright)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return skyp_transparencyRowAlloc(filter, trans, nstars, ra, decl, exptime, sky_bright);
+}
+
+bool skyp_transparencyInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  SKYP_TRANSPARENCY_TABLE_NAME
+    if (!psFitsMoveExtName(fits, SKYP_TRANSPARENCY_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", SKYP_TRANSPARENCY_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, SKYP_TRANSPARENCY_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool skyp_transparencyPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!skyp_transparencySelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                SKYP_TRANSPARENCY_TABLE_NAME, SKYP_TRANSPARENCY_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool skyp_transparencySelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, SKYP_TRANSPARENCY_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, SKYP_TRANSPARENCY_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", SKYP_TRANSPARENCY_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, SKYP_TRANSPARENCY_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *skyp_transparencyMetadataFromObject(const skyp_transparencyRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, psStringCopy(object->filter))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "trans", 0, NULL, object->trans)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item trans");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "nstars", 0, NULL, object->nstars)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item nstars");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, object->ra)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item ra");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, object->decl)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item decl");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "exptime", 0, NULL, object->exptime)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exptime");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "sky_bright", 0, NULL, object->sky_bright)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item sky_bright");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+skyp_transparencyRow *skyp_transparencyObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *filter;
+    psF64           trans;
+    psS32           nstars;
+    psF64           ra;
+    psF64           decl;
+    psF32           exptime;
+    psF64           sky_bright;
+
+    filter = psMetadataLookupPtr(&status, md, "filter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item filter");
+        return false;
+    }
+    trans = psMetadataLookupF64(&status, md, "trans");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item trans");
+        return false;
+    }
+    nstars = psMetadataLookupS32(&status, md, "nstars");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item nstars");
+        return false;
+    }
+    ra = psMetadataLookupF64(&status, md, "ra");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item ra");
+        return false;
+    }
+    decl = psMetadataLookupF64(&status, md, "decl");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item decl");
+        return false;
+    }
+    exptime = psMetadataLookupF32(&status, md, "exptime");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exptime");
+        return false;
+    }
+    sky_bright = psMetadataLookupF64(&status, md, "sky_bright");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item sky_bright");
+        return false;
+    }
+
+    return skyp_transparencyRowAlloc(filter, trans, nstars, ra, decl, exptime, sky_bright);
+}
+psArray *skyp_transparencySelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, SKYP_TRANSPARENCY_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, SKYP_TRANSPARENCY_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", SKYP_TRANSPARENCY_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, skyp_transparencyObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long skyp_transparencyDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        skyp_transparencyRow *object = objects->data[i];
+        psMetadata *where = skyp_transparencyMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, SKYP_TRANSPARENCY_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from skyp_transparency");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void skyp_absorptionRowFree(skyp_absorptionRow *object);
+
+skyp_absorptionRow *skyp_absorptionRowAlloc(const char *disperser_id, psF32 atmcomp1, psF32 atmcomp2, psF32 atmcomp3, psS32 nstars, psF64 ra, psF64 decl, psF32 exptime, psF64 sky_bright)
+{
+    skyp_absorptionRow *object;
+
+    object = psAlloc(sizeof(skyp_absorptionRow));
+    psMemSetDeallocator(object, (psFreeFunc)skyp_absorptionRowFree);
+
+    object->disperser_id = psStringCopy(disperser_id);
+    object->atmcomp1 = atmcomp1;
+    object->atmcomp2 = atmcomp2;
+    object->atmcomp3 = atmcomp3;
+    object->nstars = nstars;
+    object->ra = ra;
+    object->decl = decl;
+    object->exptime = exptime;
+    object->sky_bright = sky_bright;
+
+    return object;
+}
+
+static void skyp_absorptionRowFree(skyp_absorptionRow *object)
+{
+    psFree(object->disperser_id);
+}
+
+bool skyp_absorptionCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, SKYP_ABSORPTION_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", SKYP_ABSORPTION_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "disperser_id", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item disperser_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp1", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item atmcomp1");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp2", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item atmcomp2");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp3", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item atmcomp3");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "nstars", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item nstars");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item ra");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item decl");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "exptime", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exptime");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "sky_bright", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item sky_bright");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, SKYP_ABSORPTION_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool skyp_absorptionDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, SKYP_ABSORPTION_TABLE_NAME);
+}
+
+bool skyp_absorptionInsert(psDB * dbh, const char *disperser_id, psF32 atmcomp1, psF32 atmcomp2, psF32 atmcomp3, psS32 nstars, psF64 ra, psF64 decl, psF32 exptime, psF64 sky_bright)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "disperser_id", 0, NULL, psStringCopy(disperser_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item disperser_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp1", 0, NULL, atmcomp1)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item atmcomp1");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp2", 0, NULL, atmcomp2)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item atmcomp2");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp3", 0, NULL, atmcomp3)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item atmcomp3");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "nstars", 0, NULL, nstars)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item nstars");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, ra)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item ra");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, decl)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item decl");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "exptime", 0, NULL, exptime)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exptime");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "sky_bright", 0, NULL, sky_bright)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item sky_bright");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, SKYP_ABSORPTION_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool skyp_absorptionPop(psDB *dbh, char **disperser_id, psF32 *atmcomp1, psF32 *atmcomp2, psF32 *atmcomp3, psS32 *nstars, psF64 *ra, psF64 *decl, psF32 *exptime, psF64 *sky_bright)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, SKYP_ABSORPTION_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", SKYP_ABSORPTION_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, SKYP_ABSORPTION_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", SKYP_ABSORPTION_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, SKYP_ABSORPTION_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, SKYP_ABSORPTION_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *disperser_id = psMetadataLookupPtr(&status, row, "disperser_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item disperser_id");
+        psFree(row);
+        return false;
+    }
+    *atmcomp1 = psMetadataLookupF32(&status, row, "atmcomp1");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item atmcomp1");
+        psFree(row);
+        return false;
+    }
+    *atmcomp2 = psMetadataLookupF32(&status, row, "atmcomp2");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item atmcomp2");
+        psFree(row);
+        return false;
+    }
+    *atmcomp3 = psMetadataLookupF32(&status, row, "atmcomp3");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item atmcomp3");
+        psFree(row);
+        return false;
+    }
+    *nstars = psMetadataLookupS32(&status, row, "nstars");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item nstars");
+        psFree(row);
+        return false;
+    }
+    *ra = psMetadataLookupF64(&status, row, "ra");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item ra");
+        psFree(row);
+        return false;
+    }
+    *decl = psMetadataLookupF64(&status, row, "decl");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item decl");
+        psFree(row);
+        return false;
+    }
+    *exptime = psMetadataLookupF32(&status, row, "exptime");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exptime");
+        psFree(row);
+        return false;
+    }
+    *sky_bright = psMetadataLookupF64(&status, row, "sky_bright");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item sky_bright");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool skyp_absorptionInsertObject(psDB *dbh, skyp_absorptionRow *object)
+{
+    return skyp_absorptionInsert(dbh, object->disperser_id, object->atmcomp1, object->atmcomp2, object->atmcomp3, object->nstars, object->ra, object->decl, object->exptime, object->sky_bright);
+}
+
+skyp_absorptionRow *skyp_absorptionPopObject(psDB *dbh)
+{
+    char            disperser_id[256];
+    psF32           atmcomp1;
+    psF32           atmcomp2;
+    psF32           atmcomp3;
+    psS32           nstars;
+    psF64           ra;
+    psF64           decl;
+    psF32           exptime;
+    psF64           sky_bright;
+
+    if (!skyp_absorptionPop(dbh, (char **)&disperser_id, &atmcomp1, &atmcomp2, &atmcomp3, &nstars, &ra, &decl, &exptime, &sky_bright)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return skyp_absorptionRowAlloc(disperser_id, atmcomp1, atmcomp2, atmcomp3, nstars, ra, decl, exptime, sky_bright);
+}
+
+bool skyp_absorptionInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  SKYP_ABSORPTION_TABLE_NAME
+    if (!psFitsMoveExtName(fits, SKYP_ABSORPTION_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", SKYP_ABSORPTION_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, SKYP_ABSORPTION_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool skyp_absorptionPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!skyp_absorptionSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                SKYP_ABSORPTION_TABLE_NAME, SKYP_ABSORPTION_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool skyp_absorptionSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, SKYP_ABSORPTION_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, SKYP_ABSORPTION_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", SKYP_ABSORPTION_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, SKYP_ABSORPTION_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *skyp_absorptionMetadataFromObject(const skyp_absorptionRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "disperser_id", 0, NULL, psStringCopy(object->disperser_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item disperser_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp1", 0, NULL, object->atmcomp1)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item atmcomp1");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp2", 0, NULL, object->atmcomp2)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item atmcomp2");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp3", 0, NULL, object->atmcomp3)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item atmcomp3");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "nstars", 0, NULL, object->nstars)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item nstars");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, object->ra)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item ra");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, object->decl)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item decl");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "exptime", 0, NULL, object->exptime)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exptime");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "sky_bright", 0, NULL, object->sky_bright)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item sky_bright");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+skyp_absorptionRow *skyp_absorptionObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *disperser_id;
+    psF32           atmcomp1;
+    psF32           atmcomp2;
+    psF32           atmcomp3;
+    psS32           nstars;
+    psF64           ra;
+    psF64           decl;
+    psF32           exptime;
+    psF64           sky_bright;
+
+    disperser_id = psMetadataLookupPtr(&status, md, "disperser_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item disperser_id");
+        return false;
+    }
+    atmcomp1 = psMetadataLookupF32(&status, md, "atmcomp1");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item atmcomp1");
+        return false;
+    }
+    atmcomp2 = psMetadataLookupF32(&status, md, "atmcomp2");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item atmcomp2");
+        return false;
+    }
+    atmcomp3 = psMetadataLookupF32(&status, md, "atmcomp3");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item atmcomp3");
+        return false;
+    }
+    nstars = psMetadataLookupS32(&status, md, "nstars");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item nstars");
+        return false;
+    }
+    ra = psMetadataLookupF64(&status, md, "ra");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item ra");
+        return false;
+    }
+    decl = psMetadataLookupF64(&status, md, "decl");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item decl");
+        return false;
+    }
+    exptime = psMetadataLookupF32(&status, md, "exptime");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exptime");
+        return false;
+    }
+    sky_bright = psMetadataLookupF64(&status, md, "sky_bright");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item sky_bright");
+        return false;
+    }
+
+    return skyp_absorptionRowAlloc(disperser_id, atmcomp1, atmcomp2, atmcomp3, nstars, ra, decl, exptime, sky_bright);
+}
+psArray *skyp_absorptionSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, SKYP_ABSORPTION_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, SKYP_ABSORPTION_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", SKYP_ABSORPTION_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, skyp_absorptionObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long skyp_absorptionDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        skyp_absorptionRow *object = objects->data[i];
+        psMetadata *where = skyp_absorptionMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, SKYP_ABSORPTION_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from skyp_absorption");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void skyp_emissionRowFree(skyp_emissionRow *object);
+
+skyp_emissionRow *skyp_emissionRowAlloc(const char *disperser_id, psF32 atmcomp1, psF32 atmcomp2, psF32 atmcomp3, psF32 continuum, psF32 exptime)
+{
+    skyp_emissionRow *object;
+
+    object = psAlloc(sizeof(skyp_emissionRow));
+    psMemSetDeallocator(object, (psFreeFunc)skyp_emissionRowFree);
+
+    object->disperser_id = psStringCopy(disperser_id);
+    object->atmcomp1 = atmcomp1;
+    object->atmcomp2 = atmcomp2;
+    object->atmcomp3 = atmcomp3;
+    object->continuum = continuum;
+    object->exptime = exptime;
+
+    return object;
+}
+
+static void skyp_emissionRowFree(skyp_emissionRow *object)
+{
+    psFree(object->disperser_id);
+}
+
+bool skyp_emissionCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, SKYP_EMISSION_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", SKYP_EMISSION_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "disperser_id", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item disperser_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp1", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item atmcomp1");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp2", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item atmcomp2");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp3", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item atmcomp3");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "continuum", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item continuum");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "exptime", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exptime");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, SKYP_EMISSION_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool skyp_emissionDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, SKYP_EMISSION_TABLE_NAME);
+}
+
+bool skyp_emissionInsert(psDB * dbh, const char *disperser_id, psF32 atmcomp1, psF32 atmcomp2, psF32 atmcomp3, psF32 continuum, psF32 exptime)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "disperser_id", 0, NULL, psStringCopy(disperser_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item disperser_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp1", 0, NULL, atmcomp1)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item atmcomp1");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp2", 0, NULL, atmcomp2)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item atmcomp2");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp3", 0, NULL, atmcomp3)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item atmcomp3");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "continuum", 0, NULL, continuum)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item continuum");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "exptime", 0, NULL, exptime)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exptime");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, SKYP_EMISSION_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool skyp_emissionPop(psDB *dbh, char **disperser_id, psF32 *atmcomp1, psF32 *atmcomp2, psF32 *atmcomp3, psF32 *continuum, psF32 *exptime)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, SKYP_EMISSION_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", SKYP_EMISSION_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, SKYP_EMISSION_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", SKYP_EMISSION_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, SKYP_EMISSION_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, SKYP_EMISSION_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *disperser_id = psMetadataLookupPtr(&status, row, "disperser_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item disperser_id");
+        psFree(row);
+        return false;
+    }
+    *atmcomp1 = psMetadataLookupF32(&status, row, "atmcomp1");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item atmcomp1");
+        psFree(row);
+        return false;
+    }
+    *atmcomp2 = psMetadataLookupF32(&status, row, "atmcomp2");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item atmcomp2");
+        psFree(row);
+        return false;
+    }
+    *atmcomp3 = psMetadataLookupF32(&status, row, "atmcomp3");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item atmcomp3");
+        psFree(row);
+        return false;
+    }
+    *continuum = psMetadataLookupF32(&status, row, "continuum");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item continuum");
+        psFree(row);
+        return false;
+    }
+    *exptime = psMetadataLookupF32(&status, row, "exptime");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exptime");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool skyp_emissionInsertObject(psDB *dbh, skyp_emissionRow *object)
+{
+    return skyp_emissionInsert(dbh, object->disperser_id, object->atmcomp1, object->atmcomp2, object->atmcomp3, object->continuum, object->exptime);
+}
+
+skyp_emissionRow *skyp_emissionPopObject(psDB *dbh)
+{
+    char            disperser_id[256];
+    psF32           atmcomp1;
+    psF32           atmcomp2;
+    psF32           atmcomp3;
+    psF32           continuum;
+    psF32           exptime;
+
+    if (!skyp_emissionPop(dbh, (char **)&disperser_id, &atmcomp1, &atmcomp2, &atmcomp3, &continuum, &exptime)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return skyp_emissionRowAlloc(disperser_id, atmcomp1, atmcomp2, atmcomp3, continuum, exptime);
+}
+
+bool skyp_emissionInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  SKYP_EMISSION_TABLE_NAME
+    if (!psFitsMoveExtName(fits, SKYP_EMISSION_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", SKYP_EMISSION_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, SKYP_EMISSION_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool skyp_emissionPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!skyp_emissionSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                SKYP_EMISSION_TABLE_NAME, SKYP_EMISSION_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool skyp_emissionSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, SKYP_EMISSION_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, SKYP_EMISSION_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", SKYP_EMISSION_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, SKYP_EMISSION_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *skyp_emissionMetadataFromObject(const skyp_emissionRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "disperser_id", 0, NULL, psStringCopy(object->disperser_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item disperser_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp1", 0, NULL, object->atmcomp1)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item atmcomp1");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp2", 0, NULL, object->atmcomp2)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item atmcomp2");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp3", 0, NULL, object->atmcomp3)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item atmcomp3");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "continuum", 0, NULL, object->continuum)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item continuum");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "exptime", 0, NULL, object->exptime)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exptime");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+skyp_emissionRow *skyp_emissionObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *disperser_id;
+    psF32           atmcomp1;
+    psF32           atmcomp2;
+    psF32           atmcomp3;
+    psF32           continuum;
+    psF32           exptime;
+
+    disperser_id = psMetadataLookupPtr(&status, md, "disperser_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item disperser_id");
+        return false;
+    }
+    atmcomp1 = psMetadataLookupF32(&status, md, "atmcomp1");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item atmcomp1");
+        return false;
+    }
+    atmcomp2 = psMetadataLookupF32(&status, md, "atmcomp2");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item atmcomp2");
+        return false;
+    }
+    atmcomp3 = psMetadataLookupF32(&status, md, "atmcomp3");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item atmcomp3");
+        return false;
+    }
+    continuum = psMetadataLookupF32(&status, md, "continuum");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item continuum");
+        return false;
+    }
+    exptime = psMetadataLookupF32(&status, md, "exptime");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exptime");
+        return false;
+    }
+
+    return skyp_emissionRowAlloc(disperser_id, atmcomp1, atmcomp2, atmcomp3, continuum, exptime);
+}
+psArray *skyp_emissionSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, SKYP_EMISSION_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, SKYP_EMISSION_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", SKYP_EMISSION_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, skyp_emissionObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long skyp_emissionDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        skyp_emissionRow *object = objects->data[i];
+        psMetadata *where = skyp_emissionMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, SKYP_EMISSION_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from skyp_emission");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void dimmRowFree(dimmRow *object);
+
+dimmRow *dimmRowAlloc(psF32 sigmax, psF32 sigmay, psF32 fwhm, psF64 ra, psF64 decl, psF32 expttime, const char *telescope_id)
+{
+    dimmRow         *object;
+
+    object = psAlloc(sizeof(dimmRow));
+    psMemSetDeallocator(object, (psFreeFunc)dimmRowFree);
+
+    object->sigmax = sigmax;
+    object->sigmay = sigmay;
+    object->fwhm = fwhm;
+    object->ra = ra;
+    object->decl = decl;
+    object->expttime = expttime;
+    object->telescope_id = psStringCopy(telescope_id);
+
+    return object;
+}
+
+static void dimmRowFree(dimmRow *object)
+{
+    psFree(object->telescope_id);
+}
+
+bool dimmCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, DIMM_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", DIMM_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "sigmax", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item sigmax");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "sigmay", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item sigmay");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "fwhm", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item fwhm");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item ra");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item decl");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "expttime", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item expttime");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope_id", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope_id");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, DIMM_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool dimmDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, DIMM_TABLE_NAME);
+}
+
+bool dimmInsert(psDB * dbh, psF32 sigmax, psF32 sigmay, psF32 fwhm, psF64 ra, psF64 decl, psF32 expttime, const char *telescope_id)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "sigmax", 0, NULL, sigmax)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item sigmax");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "sigmay", 0, NULL, sigmay)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item sigmay");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "fwhm", 0, NULL, fwhm)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item fwhm");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, ra)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item ra");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, decl)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item decl");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "expttime", 0, NULL, expttime)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item expttime");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope_id", 0, NULL, psStringCopy(telescope_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope_id");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, DIMM_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool dimmPop(psDB *dbh, psF32 *sigmax, psF32 *sigmay, psF32 *fwhm, psF64 *ra, psF64 *decl, psF32 *expttime, char **telescope_id)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, DIMM_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DIMM_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, DIMM_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DIMM_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, DIMM_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, DIMM_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *sigmax = psMetadataLookupF32(&status, row, "sigmax");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item sigmax");
+        psFree(row);
+        return false;
+    }
+    *sigmay = psMetadataLookupF32(&status, row, "sigmay");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item sigmay");
+        psFree(row);
+        return false;
+    }
+    *fwhm = psMetadataLookupF32(&status, row, "fwhm");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item fwhm");
+        psFree(row);
+        return false;
+    }
+    *ra = psMetadataLookupF64(&status, row, "ra");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item ra");
+        psFree(row);
+        return false;
+    }
+    *decl = psMetadataLookupF64(&status, row, "decl");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item decl");
+        psFree(row);
+        return false;
+    }
+    *expttime = psMetadataLookupF32(&status, row, "expttime");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item expttime");
+        psFree(row);
+        return false;
+    }
+    *telescope_id = psMetadataLookupPtr(&status, row, "telescope_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope_id");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool dimmInsertObject(psDB *dbh, dimmRow *object)
+{
+    return dimmInsert(dbh, object->sigmax, object->sigmay, object->fwhm, object->ra, object->decl, object->expttime, object->telescope_id);
+}
+
+dimmRow *dimmPopObject(psDB *dbh)
+{
+    psF32           sigmax;
+    psF32           sigmay;
+    psF32           fwhm;
+    psF64           ra;
+    psF64           decl;
+    psF32           expttime;
+    char            telescope_id[256];
+
+    if (!dimmPop(dbh, &sigmax, &sigmay, &fwhm, &ra, &decl, &expttime, (char **)&telescope_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return dimmRowAlloc(sigmax, sigmay, fwhm, ra, decl, expttime, telescope_id);
+}
+
+bool dimmInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  DIMM_TABLE_NAME
+    if (!psFitsMoveExtName(fits, DIMM_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", DIMM_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, DIMM_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool dimmPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!dimmSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                DIMM_TABLE_NAME, DIMM_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool dimmSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DIMM_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, DIMM_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DIMM_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, DIMM_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *dimmMetadataFromObject(const dimmRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "sigmax", 0, NULL, object->sigmax)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item sigmax");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "sigmay", 0, NULL, object->sigmay)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item sigmay");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "fwhm", 0, NULL, object->fwhm)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item fwhm");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, object->ra)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item ra");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, object->decl)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item decl");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "expttime", 0, NULL, object->expttime)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item expttime");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope_id", 0, NULL, psStringCopy(object->telescope_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope_id");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+dimmRow *dimmObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    psF32           sigmax;
+    psF32           sigmay;
+    psF32           fwhm;
+    psF64           ra;
+    psF64           decl;
+    psF32           expttime;
+    char            *telescope_id;
+
+    sigmax = psMetadataLookupF32(&status, md, "sigmax");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item sigmax");
+        return false;
+    }
+    sigmay = psMetadataLookupF32(&status, md, "sigmay");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item sigmay");
+        return false;
+    }
+    fwhm = psMetadataLookupF32(&status, md, "fwhm");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item fwhm");
+        return false;
+    }
+    ra = psMetadataLookupF64(&status, md, "ra");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item ra");
+        return false;
+    }
+    decl = psMetadataLookupF64(&status, md, "decl");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item decl");
+        return false;
+    }
+    expttime = psMetadataLookupF32(&status, md, "expttime");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item expttime");
+        return false;
+    }
+    telescope_id = psMetadataLookupPtr(&status, md, "telescope_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope_id");
+        return false;
+    }
+
+    return dimmRowAlloc(sigmax, sigmay, fwhm, ra, decl, expttime, telescope_id);
+}
+psArray *dimmSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DIMM_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, DIMM_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DIMM_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, dimmObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long dimmDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        dimmRow *object = objects->data[i];
+        psMetadata *where = dimmMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, DIMM_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from dimm");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void skyp_irRowFree(skyp_irRow *object);
+
+skyp_irRow *skyp_irRowAlloc(psF64 sky_bright, psF64 sky_var, psF64 ra, psF64 decl, psF32 fov_x, psF32 fov_y)
+{
+    skyp_irRow      *object;
+
+    object = psAlloc(sizeof(skyp_irRow));
+    psMemSetDeallocator(object, (psFreeFunc)skyp_irRowFree);
+
+    object->sky_bright = sky_bright;
+    object->sky_var = sky_var;
+    object->ra = ra;
+    object->decl = decl;
+    object->fov_x = fov_x;
+    object->fov_y = fov_y;
+
+    return object;
+}
+
+static void skyp_irRowFree(skyp_irRow *object)
+{
+}
+
+bool skyp_irCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, SKYP_IR_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", SKYP_IR_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "sky_bright", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item sky_bright");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "sky_var", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item sky_var");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item ra");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item decl");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "fov_x", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item fov_x");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "fov_y", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item fov_y");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, SKYP_IR_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool skyp_irDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, SKYP_IR_TABLE_NAME);
+}
+
+bool skyp_irInsert(psDB * dbh, psF64 sky_bright, psF64 sky_var, psF64 ra, psF64 decl, psF32 fov_x, psF32 fov_y)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "sky_bright", 0, NULL, sky_bright)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item sky_bright");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "sky_var", 0, NULL, sky_var)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item sky_var");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, ra)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item ra");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, decl)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item decl");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "fov_x", 0, NULL, fov_x)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item fov_x");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "fov_y", 0, NULL, fov_y)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item fov_y");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, SKYP_IR_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool skyp_irPop(psDB *dbh, psF64 *sky_bright, psF64 *sky_var, psF64 *ra, psF64 *decl, psF32 *fov_x, psF32 *fov_y)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, SKYP_IR_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", SKYP_IR_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, SKYP_IR_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", SKYP_IR_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, SKYP_IR_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, SKYP_IR_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *sky_bright = psMetadataLookupF64(&status, row, "sky_bright");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item sky_bright");
+        psFree(row);
+        return false;
+    }
+    *sky_var = psMetadataLookupF64(&status, row, "sky_var");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item sky_var");
+        psFree(row);
+        return false;
+    }
+    *ra = psMetadataLookupF64(&status, row, "ra");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item ra");
+        psFree(row);
+        return false;
+    }
+    *decl = psMetadataLookupF64(&status, row, "decl");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item decl");
+        psFree(row);
+        return false;
+    }
+    *fov_x = psMetadataLookupF32(&status, row, "fov_x");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item fov_x");
+        psFree(row);
+        return false;
+    }
+    *fov_y = psMetadataLookupF32(&status, row, "fov_y");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item fov_y");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool skyp_irInsertObject(psDB *dbh, skyp_irRow *object)
+{
+    return skyp_irInsert(dbh, object->sky_bright, object->sky_var, object->ra, object->decl, object->fov_x, object->fov_y);
+}
+
+skyp_irRow *skyp_irPopObject(psDB *dbh)
+{
+    psF64           sky_bright;
+    psF64           sky_var;
+    psF64           ra;
+    psF64           decl;
+    psF32           fov_x;
+    psF32           fov_y;
+
+    if (!skyp_irPop(dbh, &sky_bright, &sky_var, &ra, &decl, &fov_x, &fov_y)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return skyp_irRowAlloc(sky_bright, sky_var, ra, decl, fov_x, fov_y);
+}
+
+bool skyp_irInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  SKYP_IR_TABLE_NAME
+    if (!psFitsMoveExtName(fits, SKYP_IR_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", SKYP_IR_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, SKYP_IR_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool skyp_irPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!skyp_irSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                SKYP_IR_TABLE_NAME, SKYP_IR_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool skyp_irSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, SKYP_IR_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, SKYP_IR_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", SKYP_IR_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, SKYP_IR_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *skyp_irMetadataFromObject(const skyp_irRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "sky_bright", 0, NULL, object->sky_bright)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item sky_bright");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "sky_var", 0, NULL, object->sky_var)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item sky_var");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, object->ra)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item ra");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, object->decl)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item decl");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "fov_x", 0, NULL, object->fov_x)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item fov_x");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "fov_y", 0, NULL, object->fov_y)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item fov_y");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+skyp_irRow *skyp_irObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    psF64           sky_bright;
+    psF64           sky_var;
+    psF64           ra;
+    psF64           decl;
+    psF32           fov_x;
+    psF32           fov_y;
+
+    sky_bright = psMetadataLookupF64(&status, md, "sky_bright");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item sky_bright");
+        return false;
+    }
+    sky_var = psMetadataLookupF64(&status, md, "sky_var");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item sky_var");
+        return false;
+    }
+    ra = psMetadataLookupF64(&status, md, "ra");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item ra");
+        return false;
+    }
+    decl = psMetadataLookupF64(&status, md, "decl");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item decl");
+        return false;
+    }
+    fov_x = psMetadataLookupF32(&status, md, "fov_x");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item fov_x");
+        return false;
+    }
+    fov_y = psMetadataLookupF32(&status, md, "fov_y");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item fov_y");
+        return false;
+    }
+
+    return skyp_irRowAlloc(sky_bright, sky_var, ra, decl, fov_x, fov_y);
+}
+psArray *skyp_irSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, SKYP_IR_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, SKYP_IR_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", SKYP_IR_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, skyp_irObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long skyp_irDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        skyp_irRow *object = objects->data[i];
+        psMetadata *where = skyp_irMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, SKYP_IR_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from skyp_ir");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void domeRowFree(domeRow *object);
+
+domeRow *domeRowAlloc(psF32 az, bool open, bool light, bool track)
+{
+    domeRow         *object;
+
+    object = psAlloc(sizeof(domeRow));
+    psMemSetDeallocator(object, (psFreeFunc)domeRowFree);
+
+    object->az = az;
+    object->open = open;
+    object->light = light;
+    object->track = track;
+
+    return object;
+}
+
+static void domeRowFree(domeRow *object)
+{
+}
+
+bool domeCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, DOME_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", DOME_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "az", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item az");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "open", PS_DATA_BOOL, NULL, true)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item open");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "light", PS_DATA_BOOL, NULL, true)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item light");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "track", PS_DATA_BOOL, NULL, true)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item track");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, DOME_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool domeDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, DOME_TABLE_NAME);
+}
+
+bool domeInsert(psDB * dbh, psF32 az, bool open, bool light, bool track)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "az", 0, NULL, az)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item az");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "open", PS_DATA_BOOL, NULL, open)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item open");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "light", PS_DATA_BOOL, NULL, light)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item light");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "track", PS_DATA_BOOL, NULL, track)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item track");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, DOME_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool domePop(psDB *dbh, psF32 *az, bool *open, bool *light, bool *track)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, DOME_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DOME_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, DOME_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DOME_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, DOME_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, DOME_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *az = psMetadataLookupF32(&status, row, "az");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item az");
+        psFree(row);
+        return false;
+    }
+    *open = psMetadataLookupBool(&status, row, "open");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item open");
+        psFree(row);
+        return false;
+    }
+    *light = psMetadataLookupBool(&status, row, "light");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item light");
+        psFree(row);
+        return false;
+    }
+    *track = psMetadataLookupBool(&status, row, "track");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item track");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool domeInsertObject(psDB *dbh, domeRow *object)
+{
+    return domeInsert(dbh, object->az, object->open, object->light, object->track);
+}
+
+domeRow *domePopObject(psDB *dbh)
+{
+    psF32           az;
+    bool            open;
+    bool            light;
+    bool            track;
+
+    if (!domePop(dbh, &az, &open, &light, &track)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return domeRowAlloc(az, open, light, track);
+}
+
+bool domeInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  DOME_TABLE_NAME
+    if (!psFitsMoveExtName(fits, DOME_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", DOME_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, DOME_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool domePopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!domeSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                DOME_TABLE_NAME, DOME_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool domeSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DOME_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, DOME_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DOME_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, DOME_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *domeMetadataFromObject(const domeRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "az", 0, NULL, object->az)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item az");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "open", PS_DATA_BOOL, NULL, object->open)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item open");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "light", PS_DATA_BOOL, NULL, object->light)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item light");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "track", PS_DATA_BOOL, NULL, object->track)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item track");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+domeRow *domeObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    psF32           az;
+    bool            open;
+    bool            light;
+    bool            track;
+
+    az = psMetadataLookupF32(&status, md, "az");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item az");
+        return false;
+    }
+    open = psMetadataLookupBool(&status, md, "open");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item open");
+        return false;
+    }
+    light = psMetadataLookupBool(&status, md, "light");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item light");
+        return false;
+    }
+    track = psMetadataLookupBool(&status, md, "track");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item track");
+        return false;
+    }
+
+    return domeRowAlloc(az, open, light, track);
+}
+psArray *domeSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DOME_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, DOME_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DOME_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, domeObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long domeDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        domeRow *object = objects->data[i];
+        psMetadata *where = domeMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, DOME_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from dome");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void telescopeRowFree(telescopeRow *object);
+
+telescopeRow *telescopeRowAlloc(const char *guide, psF32 alt, psF32 az, psF64 ra, psF64 decl)
+{
+    telescopeRow    *object;
+
+    object = psAlloc(sizeof(telescopeRow));
+    psMemSetDeallocator(object, (psFreeFunc)telescopeRowFree);
+
+    object->guide = psStringCopy(guide);
+    object->alt = alt;
+    object->az = az;
+    object->ra = ra;
+    object->decl = decl;
+
+    return object;
+}
+
+static void telescopeRowFree(telescopeRow *object)
+{
+    psFree(object->guide);
+}
+
+bool telescopeCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, TELESCOPE_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", TELESCOPE_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "guide", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item guide");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "alt", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item alt");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "az", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item az");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item ra");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item decl");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, TELESCOPE_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool telescopeDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, TELESCOPE_TABLE_NAME);
+}
+
+bool telescopeInsert(psDB * dbh, const char *guide, psF32 alt, psF32 az, psF64 ra, psF64 decl)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "guide", 0, NULL, psStringCopy(guide))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item guide");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "alt", 0, NULL, alt)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item alt");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "az", 0, NULL, az)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item az");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, ra)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item ra");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, decl)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item decl");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, TELESCOPE_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool telescopePop(psDB *dbh, char **guide, psF32 *alt, psF32 *az, psF64 *ra, psF64 *decl)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, TELESCOPE_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", TELESCOPE_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, TELESCOPE_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", TELESCOPE_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, TELESCOPE_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, TELESCOPE_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *guide = psMetadataLookupPtr(&status, row, "guide");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item guide");
+        psFree(row);
+        return false;
+    }
+    *alt = psMetadataLookupF32(&status, row, "alt");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item alt");
+        psFree(row);
+        return false;
+    }
+    *az = psMetadataLookupF32(&status, row, "az");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item az");
+        psFree(row);
+        return false;
+    }
+    *ra = psMetadataLookupF64(&status, row, "ra");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item ra");
+        psFree(row);
+        return false;
+    }
+    *decl = psMetadataLookupF64(&status, row, "decl");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item decl");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool telescopeInsertObject(psDB *dbh, telescopeRow *object)
+{
+    return telescopeInsert(dbh, object->guide, object->alt, object->az, object->ra, object->decl);
+}
+
+telescopeRow *telescopePopObject(psDB *dbh)
+{
+    char            guide[256];
+    psF32           alt;
+    psF32           az;
+    psF64           ra;
+    psF64           decl;
+
+    if (!telescopePop(dbh, (char **)&guide, &alt, &az, &ra, &decl)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return telescopeRowAlloc(guide, alt, az, ra, decl);
+}
+
+bool telescopeInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  TELESCOPE_TABLE_NAME
+    if (!psFitsMoveExtName(fits, TELESCOPE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", TELESCOPE_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, TELESCOPE_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool telescopePopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!telescopeSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                TELESCOPE_TABLE_NAME, TELESCOPE_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool telescopeSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, TELESCOPE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, TELESCOPE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", TELESCOPE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, TELESCOPE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *telescopeMetadataFromObject(const telescopeRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "guide", 0, NULL, psStringCopy(object->guide))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item guide");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "alt", 0, NULL, object->alt)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item alt");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF32(md, PS_LIST_TAIL, "az", 0, NULL, object->az)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item az");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, object->ra)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item ra");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, object->decl)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item decl");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+telescopeRow *telescopeObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *guide;
+    psF32           alt;
+    psF32           az;
+    psF64           ra;
+    psF64           decl;
+
+    guide = psMetadataLookupPtr(&status, md, "guide");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item guide");
+        return false;
+    }
+    alt = psMetadataLookupF32(&status, md, "alt");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item alt");
+        return false;
+    }
+    az = psMetadataLookupF32(&status, md, "az");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item az");
+        return false;
+    }
+    ra = psMetadataLookupF64(&status, md, "ra");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item ra");
+        return false;
+    }
+    decl = psMetadataLookupF64(&status, md, "decl");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item decl");
+        return false;
+    }
+
+    return telescopeRowAlloc(guide, alt, az, ra, decl);
+}
+psArray *telescopeSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, TELESCOPE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, TELESCOPE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", TELESCOPE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, telescopeObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long telescopeDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        telescopeRow *object = objects->data[i];
+        psMetadata *where = telescopeMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, TELESCOPE_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from telescope");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void summitExpRowFree(summitExpRow *object);
+
+summitExpRow *summitExpRowAlloc(const char *exp_id, const char *camera, const char *telescope, const char *exp_type, const char *uri)
+{
+    summitExpRow    *object;
+
+    object = psAlloc(sizeof(summitExpRow));
+    psMemSetDeallocator(object, (psFreeFunc)summitExpRowFree);
+
+    object->exp_id = psStringCopy(exp_id);
+    object->camera = psStringCopy(camera);
+    object->telescope = psStringCopy(telescope);
+    object->exp_type = psStringCopy(exp_type);
+    object->uri = psStringCopy(uri);
+
+    return object;
+}
+
+static void summitExpRowFree(summitExpRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->camera);
+    psFree(object->telescope);
+    psFree(object->exp_type);
+    psFree(object->uri);
+}
+
+bool summitExpCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, SUMMITEXP_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", SUMMITEXP_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, SUMMITEXP_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool summitExpDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, SUMMITEXP_TABLE_NAME);
+}
+
+bool summitExpInsert(psDB * dbh, const char *exp_id, const char *camera, const char *telescope, const char *exp_type, const char *uri)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, psStringCopy(telescope))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, SUMMITEXP_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool summitExpPop(psDB *dbh, char **exp_id, char **camera, char **telescope, char **exp_type, char **uri)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, SUMMITEXP_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", SUMMITEXP_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, SUMMITEXP_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", SUMMITEXP_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, SUMMITEXP_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, SUMMITEXP_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *exp_id = psMetadataLookupPtr(&status, row, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        psFree(row);
+        return false;
+    }
+    *camera = psMetadataLookupPtr(&status, row, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        psFree(row);
+        return false;
+    }
+    *telescope = psMetadataLookupPtr(&status, row, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        psFree(row);
+        return false;
+    }
+    *exp_type = psMetadataLookupPtr(&status, row, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        psFree(row);
+        return false;
+    }
+    *uri = psMetadataLookupPtr(&status, row, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool summitExpInsertObject(psDB *dbh, summitExpRow *object)
+{
+    return summitExpInsert(dbh, object->exp_id, object->camera, object->telescope, object->exp_type, object->uri);
+}
+
+summitExpRow *summitExpPopObject(psDB *dbh)
+{
+    char            exp_id[256];
+    char            camera[256];
+    char            telescope[256];
+    char            exp_type[256];
+    char            uri[256];
+
+    if (!summitExpPop(dbh, (char **)&exp_id, (char **)&camera, (char **)&telescope, (char **)&exp_type, (char **)&uri)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return summitExpRowAlloc(exp_id, camera, telescope, exp_type, uri);
+}
+
+bool summitExpInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  SUMMITEXP_TABLE_NAME
+    if (!psFitsMoveExtName(fits, SUMMITEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", SUMMITEXP_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, SUMMITEXP_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool summitExpPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!summitExpSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                SUMMITEXP_TABLE_NAME, SUMMITEXP_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool summitExpSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, SUMMITEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, SUMMITEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", SUMMITEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, SUMMITEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *summitExpMetadataFromObject(const summitExpRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(object->exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(object->camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, psStringCopy(object->telescope))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(object->exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(object->uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+summitExpRow *summitExpObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *exp_type;
+    char            *uri;
+
+    exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    camera = psMetadataLookupPtr(&status, md, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        return false;
+    }
+    telescope = psMetadataLookupPtr(&status, md, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        return false;
+    }
+    exp_type = psMetadataLookupPtr(&status, md, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        return false;
+    }
+    uri = psMetadataLookupPtr(&status, md, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        return false;
+    }
+
+    return summitExpRowAlloc(exp_id, camera, telescope, exp_type, uri);
+}
+psArray *summitExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, SUMMITEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, SUMMITEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", SUMMITEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, summitExpObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long summitExpDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        summitExpRow *object = objects->data[i];
+        psMetadata *where = summitExpMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, SUMMITEXP_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from summitExp");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void pzPendingExpRowFree(pzPendingExpRow *object);
+
+pzPendingExpRow *pzPendingExpRowAlloc(const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles)
+{
+    pzPendingExpRow *object;
+
+    object = psAlloc(sizeof(pzPendingExpRow));
+    psMemSetDeallocator(object, (psFreeFunc)pzPendingExpRowFree);
+
+    object->exp_id = psStringCopy(exp_id);
+    object->camera = psStringCopy(camera);
+    object->telescope = psStringCopy(telescope);
+    object->exp_type = psStringCopy(exp_type);
+    object->imfiles = imfiles;
+
+    return object;
+}
+
+static void pzPendingExpRowFree(pzPendingExpRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->camera);
+    psFree(object->telescope);
+    psFree(object->exp_type);
+}
+
+bool pzPendingExpCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, PZPENDINGEXP_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", PZPENDINGEXP_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, PZPENDINGEXP_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool pzPendingExpDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, PZPENDINGEXP_TABLE_NAME);
+}
+
+bool pzPendingExpInsert(psDB * dbh, const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, psStringCopy(telescope))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, PZPENDINGEXP_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool pzPendingExpPop(psDB *dbh, char **exp_id, char **camera, char **telescope, char **exp_type, psS32 *imfiles)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, PZPENDINGEXP_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", PZPENDINGEXP_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, PZPENDINGEXP_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", PZPENDINGEXP_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, PZPENDINGEXP_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, PZPENDINGEXP_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *exp_id = psMetadataLookupPtr(&status, row, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        psFree(row);
+        return false;
+    }
+    *camera = psMetadataLookupPtr(&status, row, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        psFree(row);
+        return false;
+    }
+    *telescope = psMetadataLookupPtr(&status, row, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        psFree(row);
+        return false;
+    }
+    *exp_type = psMetadataLookupPtr(&status, row, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        psFree(row);
+        return false;
+    }
+    *imfiles = psMetadataLookupS32(&status, row, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool pzPendingExpInsertObject(psDB *dbh, pzPendingExpRow *object)
+{
+    return pzPendingExpInsert(dbh, object->exp_id, object->camera, object->telescope, object->exp_type, object->imfiles);
+}
+
+pzPendingExpRow *pzPendingExpPopObject(psDB *dbh)
+{
+    char            exp_id[256];
+    char            camera[256];
+    char            telescope[256];
+    char            exp_type[256];
+    psS32           imfiles;
+
+    if (!pzPendingExpPop(dbh, (char **)&exp_id, (char **)&camera, (char **)&telescope, (char **)&exp_type, &imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return pzPendingExpRowAlloc(exp_id, camera, telescope, exp_type, imfiles);
+}
+
+bool pzPendingExpInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  PZPENDINGEXP_TABLE_NAME
+    if (!psFitsMoveExtName(fits, PZPENDINGEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", PZPENDINGEXP_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, PZPENDINGEXP_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool pzPendingExpPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!pzPendingExpSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                PZPENDINGEXP_TABLE_NAME, PZPENDINGEXP_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool pzPendingExpSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, PZPENDINGEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, PZPENDINGEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", PZPENDINGEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, PZPENDINGEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *pzPendingExpMetadataFromObject(const pzPendingExpRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(object->exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(object->camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, psStringCopy(object->telescope))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(object->exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, object->imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+pzPendingExpRow *pzPendingExpObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *exp_type;
+    psS32           imfiles;
+
+    exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    camera = psMetadataLookupPtr(&status, md, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        return false;
+    }
+    telescope = psMetadataLookupPtr(&status, md, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        return false;
+    }
+    exp_type = psMetadataLookupPtr(&status, md, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        return false;
+    }
+    imfiles = psMetadataLookupS32(&status, md, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        return false;
+    }
+
+    return pzPendingExpRowAlloc(exp_id, camera, telescope, exp_type, imfiles);
+}
+psArray *pzPendingExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, PZPENDINGEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, PZPENDINGEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", PZPENDINGEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, pzPendingExpObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long pzPendingExpDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        pzPendingExpRow *object = objects->data[i];
+        psMetadata *where = pzPendingExpMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, PZPENDINGEXP_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from pzPendingExp");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void pzPendingImfileRowFree(pzPendingImfileRow *object);
+
+pzPendingImfileRow *pzPendingImfileRowAlloc(const char *exp_id, psS32 bytes, const char *md5sum, const char *class, const char *class_id, const char *uri)
+{
+    pzPendingImfileRow *object;
+
+    object = psAlloc(sizeof(pzPendingImfileRow));
+    psMemSetDeallocator(object, (psFreeFunc)pzPendingImfileRowFree);
+
+    object->exp_id = psStringCopy(exp_id);
+    object->bytes = bytes;
+    object->md5sum = psStringCopy(md5sum);
+    object->class = psStringCopy(class);
+    object->class_id = psStringCopy(class_id);
+    object->uri = psStringCopy(uri);
+
+    return object;
+}
+
+static void pzPendingImfileRowFree(pzPendingImfileRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->md5sum);
+    psFree(object->class);
+    psFree(object->class_id);
+    psFree(object->uri);
+}
+
+bool pzPendingImfileCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, PZPENDINGIMFILE_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", PZPENDINGIMFILE_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, "Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "bytes", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bytes");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "md5sum", 0, NULL, "32")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item md5sum");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, PZPENDINGIMFILE_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool pzPendingImfileDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, PZPENDINGIMFILE_TABLE_NAME);
+}
+
+bool pzPendingImfileInsert(psDB * dbh, const char *exp_id, psS32 bytes, const char *md5sum, const char *class, const char *class_id, const char *uri)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "bytes", 0, NULL, bytes)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bytes");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "md5sum", 0, NULL, psStringCopy(md5sum))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item md5sum");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class", 0, NULL, psStringCopy(class))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, PZPENDINGIMFILE_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool pzPendingImfilePop(psDB *dbh, char **exp_id, psS32 *bytes, char **md5sum, char **class, char **class_id, char **uri)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, PZPENDINGIMFILE_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", PZPENDINGIMFILE_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, PZPENDINGIMFILE_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", PZPENDINGIMFILE_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, PZPENDINGIMFILE_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, PZPENDINGIMFILE_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *exp_id = psMetadataLookupPtr(&status, row, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        psFree(row);
+        return false;
+    }
+    *bytes = psMetadataLookupS32(&status, row, "bytes");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bytes");
+        psFree(row);
+        return false;
+    }
+    *md5sum = psMetadataLookupPtr(&status, row, "md5sum");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item md5sum");
+        psFree(row);
+        return false;
+    }
+    *class = psMetadataLookupPtr(&status, row, "class");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class");
+        psFree(row);
+        return false;
+    }
+    *class_id = psMetadataLookupPtr(&status, row, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        psFree(row);
+        return false;
+    }
+    *uri = psMetadataLookupPtr(&status, row, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool pzPendingImfileInsertObject(psDB *dbh, pzPendingImfileRow *object)
+{
+    return pzPendingImfileInsert(dbh, object->exp_id, object->bytes, object->md5sum, object->class, object->class_id, object->uri);
+}
+
+pzPendingImfileRow *pzPendingImfilePopObject(psDB *dbh)
+{
+    char            exp_id[256];
+    psS32           bytes;
+    char            md5sum[256];
+    char            class[256];
+    char            class_id[256];
+    char            uri[256];
+
+    if (!pzPendingImfilePop(dbh, (char **)&exp_id, &bytes, (char **)&md5sum, (char **)&class, (char **)&class_id, (char **)&uri)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return pzPendingImfileRowAlloc(exp_id, bytes, md5sum, class, class_id, uri);
+}
+
+bool pzPendingImfileInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  PZPENDINGIMFILE_TABLE_NAME
+    if (!psFitsMoveExtName(fits, PZPENDINGIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", PZPENDINGIMFILE_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, PZPENDINGIMFILE_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool pzPendingImfilePopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!pzPendingImfileSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                PZPENDINGIMFILE_TABLE_NAME, PZPENDINGIMFILE_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool pzPendingImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, PZPENDINGIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, PZPENDINGIMFILE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", PZPENDINGIMFILE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, PZPENDINGIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *pzPendingImfileMetadataFromObject(const pzPendingImfileRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(object->exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "bytes", 0, NULL, object->bytes)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item bytes");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "md5sum", 0, NULL, psStringCopy(object->md5sum))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item md5sum");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class", 0, NULL, psStringCopy(object->class))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(object->class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(object->uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+pzPendingImfileRow *pzPendingImfileObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *exp_id;
+    psS32           bytes;
+    char            *md5sum;
+    char            *class;
+    char            *class_id;
+    char            *uri;
+
+    exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    bytes = psMetadataLookupS32(&status, md, "bytes");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item bytes");
+        return false;
+    }
+    md5sum = psMetadataLookupPtr(&status, md, "md5sum");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item md5sum");
+        return false;
+    }
+    class = psMetadataLookupPtr(&status, md, "class");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class");
+        return false;
+    }
+    class_id = psMetadataLookupPtr(&status, md, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        return false;
+    }
+    uri = psMetadataLookupPtr(&status, md, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        return false;
+    }
+
+    return pzPendingImfileRowAlloc(exp_id, bytes, md5sum, class, class_id, uri);
+}
+psArray *pzPendingImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, PZPENDINGIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, PZPENDINGIMFILE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", PZPENDINGIMFILE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, pzPendingImfileObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long pzPendingImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        pzPendingImfileRow *object = objects->data[i];
+        psMetadata *where = pzPendingImfileMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, PZPENDINGIMFILE_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from pzPendingImfile");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void newExpRowFree(newExpRow *object);
+
+newExpRow *newExpRowAlloc(const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles)
+{
+    newExpRow       *object;
+
+    object = psAlloc(sizeof(newExpRow));
+    psMemSetDeallocator(object, (psFreeFunc)newExpRowFree);
+
+    object->exp_id = psStringCopy(exp_id);
+    object->camera = psStringCopy(camera);
+    object->telescope = psStringCopy(telescope);
+    object->exp_type = psStringCopy(exp_type);
+    object->imfiles = imfiles;
+
+    return object;
+}
+
+static void newExpRowFree(newExpRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->camera);
+    psFree(object->telescope);
+    psFree(object->exp_type);
+}
+
+bool newExpCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, NEWEXP_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", NEWEXP_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, NEWEXP_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool newExpDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, NEWEXP_TABLE_NAME);
+}
+
+bool newExpInsert(psDB * dbh, const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, psStringCopy(telescope))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, NEWEXP_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool newExpPop(psDB *dbh, char **exp_id, char **camera, char **telescope, char **exp_type, psS32 *imfiles)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, NEWEXP_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", NEWEXP_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, NEWEXP_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", NEWEXP_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, NEWEXP_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, NEWEXP_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *exp_id = psMetadataLookupPtr(&status, row, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        psFree(row);
+        return false;
+    }
+    *camera = psMetadataLookupPtr(&status, row, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        psFree(row);
+        return false;
+    }
+    *telescope = psMetadataLookupPtr(&status, row, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        psFree(row);
+        return false;
+    }
+    *exp_type = psMetadataLookupPtr(&status, row, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        psFree(row);
+        return false;
+    }
+    *imfiles = psMetadataLookupS32(&status, row, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool newExpInsertObject(psDB *dbh, newExpRow *object)
+{
+    return newExpInsert(dbh, object->exp_id, object->camera, object->telescope, object->exp_type, object->imfiles);
+}
+
+newExpRow *newExpPopObject(psDB *dbh)
+{
+    char            exp_id[256];
+    char            camera[256];
+    char            telescope[256];
+    char            exp_type[256];
+    psS32           imfiles;
+
+    if (!newExpPop(dbh, (char **)&exp_id, (char **)&camera, (char **)&telescope, (char **)&exp_type, &imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return newExpRowAlloc(exp_id, camera, telescope, exp_type, imfiles);
+}
+
+bool newExpInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  NEWEXP_TABLE_NAME
+    if (!psFitsMoveExtName(fits, NEWEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", NEWEXP_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, NEWEXP_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool newExpPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!newExpSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                NEWEXP_TABLE_NAME, NEWEXP_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool newExpSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, NEWEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, NEWEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", NEWEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, NEWEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *newExpMetadataFromObject(const newExpRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(object->exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(object->camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, psStringCopy(object->telescope))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(object->exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, object->imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+newExpRow *newExpObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *exp_type;
+    psS32           imfiles;
+
+    exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    camera = psMetadataLookupPtr(&status, md, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        return false;
+    }
+    telescope = psMetadataLookupPtr(&status, md, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        return false;
+    }
+    exp_type = psMetadataLookupPtr(&status, md, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        return false;
+    }
+    imfiles = psMetadataLookupS32(&status, md, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        return false;
+    }
+
+    return newExpRowAlloc(exp_id, camera, telescope, exp_type, imfiles);
+}
+psArray *newExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, NEWEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, NEWEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", NEWEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, newExpObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long newExpDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        newExpRow *object = objects->data[i];
+        psMetadata *where = newExpMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, NEWEXP_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from newExp");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void newImfileRowFree(newImfileRow *object);
+
+newImfileRow *newImfileRowAlloc(const char *exp_id, const char *class, const char *class_id, const char *uri)
+{
+    newImfileRow    *object;
+
+    object = psAlloc(sizeof(newImfileRow));
+    psMemSetDeallocator(object, (psFreeFunc)newImfileRowFree);
+
+    object->exp_id = psStringCopy(exp_id);
+    object->class = psStringCopy(class);
+    object->class_id = psStringCopy(class_id);
+    object->uri = psStringCopy(uri);
+
+    return object;
+}
+
+static void newImfileRowFree(newImfileRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->class);
+    psFree(object->class_id);
+    psFree(object->uri);
+}
+
+bool newImfileCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, NEWIMFILE_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", NEWIMFILE_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, "Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, NEWIMFILE_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool newImfileDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, NEWIMFILE_TABLE_NAME);
+}
+
+bool newImfileInsert(psDB * dbh, const char *exp_id, const char *class, const char *class_id, const char *uri)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class", 0, NULL, psStringCopy(class))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, NEWIMFILE_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool newImfilePop(psDB *dbh, char **exp_id, char **class, char **class_id, char **uri)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, NEWIMFILE_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", NEWIMFILE_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, NEWIMFILE_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", NEWIMFILE_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, NEWIMFILE_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, NEWIMFILE_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *exp_id = psMetadataLookupPtr(&status, row, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        psFree(row);
+        return false;
+    }
+    *class = psMetadataLookupPtr(&status, row, "class");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class");
+        psFree(row);
+        return false;
+    }
+    *class_id = psMetadataLookupPtr(&status, row, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        psFree(row);
+        return false;
+    }
+    *uri = psMetadataLookupPtr(&status, row, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool newImfileInsertObject(psDB *dbh, newImfileRow *object)
+{
+    return newImfileInsert(dbh, object->exp_id, object->class, object->class_id, object->uri);
+}
+
+newImfileRow *newImfilePopObject(psDB *dbh)
+{
+    char            exp_id[256];
+    char            class[256];
+    char            class_id[256];
+    char            uri[256];
+
+    if (!newImfilePop(dbh, (char **)&exp_id, (char **)&class, (char **)&class_id, (char **)&uri)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return newImfileRowAlloc(exp_id, class, class_id, uri);
+}
+
+bool newImfileInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  NEWIMFILE_TABLE_NAME
+    if (!psFitsMoveExtName(fits, NEWIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", NEWIMFILE_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, NEWIMFILE_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool newImfilePopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!newImfileSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                NEWIMFILE_TABLE_NAME, NEWIMFILE_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool newImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, NEWIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, NEWIMFILE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", NEWIMFILE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, NEWIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *newImfileMetadataFromObject(const newImfileRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(object->exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class", 0, NULL, psStringCopy(object->class))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(object->class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(object->uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+newImfileRow *newImfileObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *exp_id;
+    char            *class;
+    char            *class_id;
+    char            *uri;
+
+    exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    class = psMetadataLookupPtr(&status, md, "class");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class");
+        return false;
+    }
+    class_id = psMetadataLookupPtr(&status, md, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        return false;
+    }
+    uri = psMetadataLookupPtr(&status, md, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        return false;
+    }
+
+    return newImfileRowAlloc(exp_id, class, class_id, uri);
+}
+psArray *newImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, NEWIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, NEWIMFILE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", NEWIMFILE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, newImfileObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long newImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        newImfileRow *object = objects->data[i];
+        psMetadata *where = newImfileMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, NEWIMFILE_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from newImfile");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void rawDetrendExpRowFree(rawDetrendExpRow *object);
+
+rawDetrendExpRow *rawDetrendExpRowAlloc(const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles, const char *filter, const char *stats)
+{
+    rawDetrendExpRow *object;
+
+    object = psAlloc(sizeof(rawDetrendExpRow));
+    psMemSetDeallocator(object, (psFreeFunc)rawDetrendExpRowFree);
+
+    object->exp_id = psStringCopy(exp_id);
+    object->camera = psStringCopy(camera);
+    object->telescope = psStringCopy(telescope);
+    object->exp_type = psStringCopy(exp_type);
+    object->imfiles = imfiles;
+    object->filter = psStringCopy(filter);
+    object->stats = psStringCopy(stats);
+
+    return object;
+}
+
+static void rawDetrendExpRowFree(rawDetrendExpRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->camera);
+    psFree(object->telescope);
+    psFree(object->exp_type);
+    psFree(object->filter);
+    psFree(object->stats);
+}
+
+bool rawDetrendExpCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, RAWDETRENDEXP_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", RAWDETRENDEXP_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, RAWDETRENDEXP_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool rawDetrendExpDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, RAWDETRENDEXP_TABLE_NAME);
+}
+
+bool rawDetrendExpInsert(psDB * dbh, const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles, const char *filter, const char *stats)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, psStringCopy(telescope))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, psStringCopy(filter))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, RAWDETRENDEXP_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool rawDetrendExpPop(psDB *dbh, char **exp_id, char **camera, char **telescope, char **exp_type, psS32 *imfiles, char **filter, char **stats)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, RAWDETRENDEXP_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", RAWDETRENDEXP_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, RAWDETRENDEXP_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", RAWDETRENDEXP_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, RAWDETRENDEXP_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, RAWDETRENDEXP_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *exp_id = psMetadataLookupPtr(&status, row, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        psFree(row);
+        return false;
+    }
+    *camera = psMetadataLookupPtr(&status, row, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        psFree(row);
+        return false;
+    }
+    *telescope = psMetadataLookupPtr(&status, row, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        psFree(row);
+        return false;
+    }
+    *exp_type = psMetadataLookupPtr(&status, row, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        psFree(row);
+        return false;
+    }
+    *imfiles = psMetadataLookupS32(&status, row, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        psFree(row);
+        return false;
+    }
+    *filter = psMetadataLookupPtr(&status, row, "filter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item filter");
+        psFree(row);
+        return false;
+    }
+    *stats = psMetadataLookupPtr(&status, row, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool rawDetrendExpInsertObject(psDB *dbh, rawDetrendExpRow *object)
+{
+    return rawDetrendExpInsert(dbh, object->exp_id, object->camera, object->telescope, object->exp_type, object->imfiles, object->filter, object->stats);
+}
+
+rawDetrendExpRow *rawDetrendExpPopObject(psDB *dbh)
+{
+    char            exp_id[256];
+    char            camera[256];
+    char            telescope[256];
+    char            exp_type[256];
+    psS32           imfiles;
+    char            filter[256];
+    char            stats[256];
+
+    if (!rawDetrendExpPop(dbh, (char **)&exp_id, (char **)&camera, (char **)&telescope, (char **)&exp_type, &imfiles, (char **)&filter, (char **)&stats)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return rawDetrendExpRowAlloc(exp_id, camera, telescope, exp_type, imfiles, filter, stats);
+}
+
+bool rawDetrendExpInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  RAWDETRENDEXP_TABLE_NAME
+    if (!psFitsMoveExtName(fits, RAWDETRENDEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", RAWDETRENDEXP_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, RAWDETRENDEXP_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool rawDetrendExpPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!rawDetrendExpSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                RAWDETRENDEXP_TABLE_NAME, RAWDETRENDEXP_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool rawDetrendExpSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, RAWDETRENDEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, RAWDETRENDEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", RAWDETRENDEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, RAWDETRENDEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *rawDetrendExpMetadataFromObject(const rawDetrendExpRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(object->exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(object->camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, psStringCopy(object->telescope))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(object->exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, object->imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, psStringCopy(object->filter))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(object->stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+rawDetrendExpRow *rawDetrendExpObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *exp_type;
+    psS32           imfiles;
+    char            *filter;
+    char            *stats;
+
+    exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    camera = psMetadataLookupPtr(&status, md, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        return false;
+    }
+    telescope = psMetadataLookupPtr(&status, md, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        return false;
+    }
+    exp_type = psMetadataLookupPtr(&status, md, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        return false;
+    }
+    imfiles = psMetadataLookupS32(&status, md, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        return false;
+    }
+    filter = psMetadataLookupPtr(&status, md, "filter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item filter");
+        return false;
+    }
+    stats = psMetadataLookupPtr(&status, md, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        return false;
+    }
+
+    return rawDetrendExpRowAlloc(exp_id, camera, telescope, exp_type, imfiles, filter, stats);
+}
+psArray *rawDetrendExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, RAWDETRENDEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, RAWDETRENDEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", RAWDETRENDEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, rawDetrendExpObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long rawDetrendExpDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        rawDetrendExpRow *object = objects->data[i];
+        psMetadata *where = rawDetrendExpMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, RAWDETRENDEXP_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from rawDetrendExp");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void rawScienceExpRowFree(rawScienceExpRow *object);
+
+rawScienceExpRow *rawScienceExpRowAlloc(const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles, const char *filter, const char *stats)
+{
+    rawScienceExpRow *object;
+
+    object = psAlloc(sizeof(rawScienceExpRow));
+    psMemSetDeallocator(object, (psFreeFunc)rawScienceExpRowFree);
+
+    object->exp_id = psStringCopy(exp_id);
+    object->camera = psStringCopy(camera);
+    object->telescope = psStringCopy(telescope);
+    object->exp_type = psStringCopy(exp_type);
+    object->imfiles = imfiles;
+    object->filter = psStringCopy(filter);
+    object->stats = psStringCopy(stats);
+
+    return object;
+}
+
+static void rawScienceExpRowFree(rawScienceExpRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->camera);
+    psFree(object->telescope);
+    psFree(object->exp_type);
+    psFree(object->filter);
+    psFree(object->stats);
+}
+
+bool rawScienceExpCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, RAWSCIENCEEXP_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", RAWSCIENCEEXP_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, RAWSCIENCEEXP_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool rawScienceExpDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, RAWSCIENCEEXP_TABLE_NAME);
+}
+
+bool rawScienceExpInsert(psDB * dbh, const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles, const char *filter, const char *stats)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, psStringCopy(telescope))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, psStringCopy(filter))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, RAWSCIENCEEXP_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool rawScienceExpPop(psDB *dbh, char **exp_id, char **camera, char **telescope, char **exp_type, psS32 *imfiles, char **filter, char **stats)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, RAWSCIENCEEXP_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", RAWSCIENCEEXP_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, RAWSCIENCEEXP_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", RAWSCIENCEEXP_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, RAWSCIENCEEXP_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, RAWSCIENCEEXP_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *exp_id = psMetadataLookupPtr(&status, row, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        psFree(row);
+        return false;
+    }
+    *camera = psMetadataLookupPtr(&status, row, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        psFree(row);
+        return false;
+    }
+    *telescope = psMetadataLookupPtr(&status, row, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        psFree(row);
+        return false;
+    }
+    *exp_type = psMetadataLookupPtr(&status, row, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        psFree(row);
+        return false;
+    }
+    *imfiles = psMetadataLookupS32(&status, row, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        psFree(row);
+        return false;
+    }
+    *filter = psMetadataLookupPtr(&status, row, "filter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item filter");
+        psFree(row);
+        return false;
+    }
+    *stats = psMetadataLookupPtr(&status, row, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool rawScienceExpInsertObject(psDB *dbh, rawScienceExpRow *object)
+{
+    return rawScienceExpInsert(dbh, object->exp_id, object->camera, object->telescope, object->exp_type, object->imfiles, object->filter, object->stats);
+}
+
+rawScienceExpRow *rawScienceExpPopObject(psDB *dbh)
+{
+    char            exp_id[256];
+    char            camera[256];
+    char            telescope[256];
+    char            exp_type[256];
+    psS32           imfiles;
+    char            filter[256];
+    char            stats[256];
+
+    if (!rawScienceExpPop(dbh, (char **)&exp_id, (char **)&camera, (char **)&telescope, (char **)&exp_type, &imfiles, (char **)&filter, (char **)&stats)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return rawScienceExpRowAlloc(exp_id, camera, telescope, exp_type, imfiles, filter, stats);
+}
+
+bool rawScienceExpInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  RAWSCIENCEEXP_TABLE_NAME
+    if (!psFitsMoveExtName(fits, RAWSCIENCEEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", RAWSCIENCEEXP_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, RAWSCIENCEEXP_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool rawScienceExpPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!rawScienceExpSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                RAWSCIENCEEXP_TABLE_NAME, RAWSCIENCEEXP_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool rawScienceExpSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, RAWSCIENCEEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, RAWSCIENCEEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", RAWSCIENCEEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, RAWSCIENCEEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *rawScienceExpMetadataFromObject(const rawScienceExpRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(object->exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(object->camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, psStringCopy(object->telescope))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(object->exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, object->imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, psStringCopy(object->filter))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(object->stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+rawScienceExpRow *rawScienceExpObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *exp_type;
+    psS32           imfiles;
+    char            *filter;
+    char            *stats;
+
+    exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    camera = psMetadataLookupPtr(&status, md, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        return false;
+    }
+    telescope = psMetadataLookupPtr(&status, md, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        return false;
+    }
+    exp_type = psMetadataLookupPtr(&status, md, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        return false;
+    }
+    imfiles = psMetadataLookupS32(&status, md, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        return false;
+    }
+    filter = psMetadataLookupPtr(&status, md, "filter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item filter");
+        return false;
+    }
+    stats = psMetadataLookupPtr(&status, md, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        return false;
+    }
+
+    return rawScienceExpRowAlloc(exp_id, camera, telescope, exp_type, imfiles, filter, stats);
+}
+psArray *rawScienceExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, RAWSCIENCEEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, RAWSCIENCEEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", RAWSCIENCEEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, rawScienceExpObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long rawScienceExpDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        rawScienceExpRow *object = objects->data[i];
+        psMetadata *where = rawScienceExpMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, RAWSCIENCEEXP_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from rawScienceExp");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void rawImfileRowFree(rawImfileRow *object);
+
+rawImfileRow *rawImfileRowAlloc(const char *exp_id, const char *class_id, const char *uri, const char *stats)
+{
+    rawImfileRow    *object;
+
+    object = psAlloc(sizeof(rawImfileRow));
+    psMemSetDeallocator(object, (psFreeFunc)rawImfileRowFree);
+
+    object->exp_id = psStringCopy(exp_id);
+    object->class_id = psStringCopy(class_id);
+    object->uri = psStringCopy(uri);
+    object->stats = psStringCopy(stats);
+
+    return object;
+}
+
+static void rawImfileRowFree(rawImfileRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->class_id);
+    psFree(object->uri);
+    psFree(object->stats);
+}
+
+bool rawImfileCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, RAWIMFILE_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", RAWIMFILE_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, "Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, RAWIMFILE_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool rawImfileDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, RAWIMFILE_TABLE_NAME);
+}
+
+bool rawImfileInsert(psDB * dbh, const char *exp_id, const char *class_id, const char *uri, const char *stats)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, RAWIMFILE_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool rawImfilePop(psDB *dbh, char **exp_id, char **class_id, char **uri, char **stats)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, RAWIMFILE_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", RAWIMFILE_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, RAWIMFILE_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", RAWIMFILE_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, RAWIMFILE_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, RAWIMFILE_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *exp_id = psMetadataLookupPtr(&status, row, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        psFree(row);
+        return false;
+    }
+    *class_id = psMetadataLookupPtr(&status, row, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        psFree(row);
+        return false;
+    }
+    *uri = psMetadataLookupPtr(&status, row, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        psFree(row);
+        return false;
+    }
+    *stats = psMetadataLookupPtr(&status, row, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool rawImfileInsertObject(psDB *dbh, rawImfileRow *object)
+{
+    return rawImfileInsert(dbh, object->exp_id, object->class_id, object->uri, object->stats);
+}
+
+rawImfileRow *rawImfilePopObject(psDB *dbh)
+{
+    char            exp_id[256];
+    char            class_id[256];
+    char            uri[256];
+    char            stats[256];
+
+    if (!rawImfilePop(dbh, (char **)&exp_id, (char **)&class_id, (char **)&uri, (char **)&stats)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return rawImfileRowAlloc(exp_id, class_id, uri, stats);
+}
+
+bool rawImfileInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  RAWIMFILE_TABLE_NAME
+    if (!psFitsMoveExtName(fits, RAWIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", RAWIMFILE_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, RAWIMFILE_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool rawImfilePopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!rawImfileSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                RAWIMFILE_TABLE_NAME, RAWIMFILE_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool rawImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, RAWIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, RAWIMFILE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", RAWIMFILE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, RAWIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *rawImfileMetadataFromObject(const rawImfileRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(object->exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(object->class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(object->uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(object->stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+rawImfileRow *rawImfileObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *exp_id;
+    char            *class_id;
+    char            *uri;
+    char            *stats;
+
+    exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    class_id = psMetadataLookupPtr(&status, md, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        return false;
+    }
+    uri = psMetadataLookupPtr(&status, md, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        return false;
+    }
+    stats = psMetadataLookupPtr(&status, md, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        return false;
+    }
+
+    return rawImfileRowAlloc(exp_id, class_id, uri, stats);
+}
+psArray *rawImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, RAWIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, RAWIMFILE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", RAWIMFILE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, rawImfileObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long rawImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        rawImfileRow *object = objects->data[i];
+        psMetadata *where = rawImfileMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, RAWIMFILE_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from rawImfile");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void p1PendingExpRowFree(p1PendingExpRow *object);
+
+p1PendingExpRow *p1PendingExpRowAlloc(const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles, const char *filter, const char *stats, const char *recipe, psS32 p1_version)
+{
+    p1PendingExpRow *object;
+
+    object = psAlloc(sizeof(p1PendingExpRow));
+    psMemSetDeallocator(object, (psFreeFunc)p1PendingExpRowFree);
+
+    object->exp_id = psStringCopy(exp_id);
+    object->camera = psStringCopy(camera);
+    object->telescope = psStringCopy(telescope);
+    object->exp_type = psStringCopy(exp_type);
+    object->imfiles = imfiles;
+    object->filter = psStringCopy(filter);
+    object->stats = psStringCopy(stats);
+    object->recipe = psStringCopy(recipe);
+    object->p1_version = p1_version;
+
+    return object;
+}
+
+static void p1PendingExpRowFree(p1PendingExpRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->camera);
+    psFree(object->telescope);
+    psFree(object->exp_type);
+    psFree(object->filter);
+    psFree(object->stats);
+    psFree(object->recipe);
+}
+
+bool p1PendingExpCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, P1PENDINGEXP_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", P1PENDINGEXP_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p1_version");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, P1PENDINGEXP_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool p1PendingExpDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, P1PENDINGEXP_TABLE_NAME);
+}
+
+bool p1PendingExpInsert(psDB * dbh, const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles, const char *filter, const char *stats, const char *recipe, psS32 p1_version)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, psStringCopy(telescope))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, psStringCopy(filter))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, p1_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p1_version");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, P1PENDINGEXP_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool p1PendingExpPop(psDB *dbh, char **exp_id, char **camera, char **telescope, char **exp_type, psS32 *imfiles, char **filter, char **stats, char **recipe, psS32 *p1_version)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, P1PENDINGEXP_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", P1PENDINGEXP_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, P1PENDINGEXP_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", P1PENDINGEXP_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, P1PENDINGEXP_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, P1PENDINGEXP_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *exp_id = psMetadataLookupPtr(&status, row, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        psFree(row);
+        return false;
+    }
+    *camera = psMetadataLookupPtr(&status, row, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        psFree(row);
+        return false;
+    }
+    *telescope = psMetadataLookupPtr(&status, row, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        psFree(row);
+        return false;
+    }
+    *exp_type = psMetadataLookupPtr(&status, row, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        psFree(row);
+        return false;
+    }
+    *imfiles = psMetadataLookupS32(&status, row, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        psFree(row);
+        return false;
+    }
+    *filter = psMetadataLookupPtr(&status, row, "filter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item filter");
+        psFree(row);
+        return false;
+    }
+    *stats = psMetadataLookupPtr(&status, row, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        psFree(row);
+        return false;
+    }
+    *recipe = psMetadataLookupPtr(&status, row, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        psFree(row);
+        return false;
+    }
+    *p1_version = psMetadataLookupS32(&status, row, "p1_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p1_version");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool p1PendingExpInsertObject(psDB *dbh, p1PendingExpRow *object)
+{
+    return p1PendingExpInsert(dbh, object->exp_id, object->camera, object->telescope, object->exp_type, object->imfiles, object->filter, object->stats, object->recipe, object->p1_version);
+}
+
+p1PendingExpRow *p1PendingExpPopObject(psDB *dbh)
+{
+    char            exp_id[256];
+    char            camera[256];
+    char            telescope[256];
+    char            exp_type[256];
+    psS32           imfiles;
+    char            filter[256];
+    char            stats[256];
+    char            recipe[256];
+    psS32           p1_version;
+
+    if (!p1PendingExpPop(dbh, (char **)&exp_id, (char **)&camera, (char **)&telescope, (char **)&exp_type, &imfiles, (char **)&filter, (char **)&stats, (char **)&recipe, &p1_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return p1PendingExpRowAlloc(exp_id, camera, telescope, exp_type, imfiles, filter, stats, recipe, p1_version);
+}
+
+bool p1PendingExpInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  P1PENDINGEXP_TABLE_NAME
+    if (!psFitsMoveExtName(fits, P1PENDINGEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", P1PENDINGEXP_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, P1PENDINGEXP_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool p1PendingExpPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!p1PendingExpSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                P1PENDINGEXP_TABLE_NAME, P1PENDINGEXP_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool p1PendingExpSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, P1PENDINGEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, P1PENDINGEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", P1PENDINGEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, P1PENDINGEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *p1PendingExpMetadataFromObject(const p1PendingExpRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(object->exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(object->camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, psStringCopy(object->telescope))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(object->exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, object->imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, psStringCopy(object->filter))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(object->stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(object->recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, object->p1_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p1_version");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+p1PendingExpRow *p1PendingExpObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *exp_type;
+    psS32           imfiles;
+    char            *filter;
+    char            *stats;
+    char            *recipe;
+    psS32           p1_version;
+
+    exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    camera = psMetadataLookupPtr(&status, md, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        return false;
+    }
+    telescope = psMetadataLookupPtr(&status, md, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        return false;
+    }
+    exp_type = psMetadataLookupPtr(&status, md, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        return false;
+    }
+    imfiles = psMetadataLookupS32(&status, md, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        return false;
+    }
+    filter = psMetadataLookupPtr(&status, md, "filter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item filter");
+        return false;
+    }
+    stats = psMetadataLookupPtr(&status, md, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        return false;
+    }
+    recipe = psMetadataLookupPtr(&status, md, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        return false;
+    }
+    p1_version = psMetadataLookupS32(&status, md, "p1_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p1_version");
+        return false;
+    }
+
+    return p1PendingExpRowAlloc(exp_id, camera, telescope, exp_type, imfiles, filter, stats, recipe, p1_version);
+}
+psArray *p1PendingExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, P1PENDINGEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, P1PENDINGEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", P1PENDINGEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, p1PendingExpObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long p1PendingExpDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        p1PendingExpRow *object = objects->data[i];
+        psMetadata *where = p1PendingExpMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, P1PENDINGEXP_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from p1PendingExp");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void p2PendingExpRowFree(p2PendingExpRow *object);
+
+p2PendingExpRow *p2PendingExpRowAlloc(const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles, const char *filter, const char *stats, const char *recipe, psS32 p1_version, psS32 p2_version)
+{
+    p2PendingExpRow *object;
+
+    object = psAlloc(sizeof(p2PendingExpRow));
+    psMemSetDeallocator(object, (psFreeFunc)p2PendingExpRowFree);
+
+    object->exp_id = psStringCopy(exp_id);
+    object->camera = psStringCopy(camera);
+    object->telescope = psStringCopy(telescope);
+    object->exp_type = psStringCopy(exp_type);
+    object->imfiles = imfiles;
+    object->filter = psStringCopy(filter);
+    object->stats = psStringCopy(stats);
+    object->recipe = psStringCopy(recipe);
+    object->p1_version = p1_version;
+    object->p2_version = p2_version;
+
+    return object;
+}
+
+static void p2PendingExpRowFree(p2PendingExpRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->camera);
+    psFree(object->telescope);
+    psFree(object->exp_type);
+    psFree(object->filter);
+    psFree(object->stats);
+    psFree(object->recipe);
+}
+
+bool p2PendingExpCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, P2PENDINGEXP_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", P2PENDINGEXP_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p1_version");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p2_version");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, P2PENDINGEXP_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool p2PendingExpDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, P2PENDINGEXP_TABLE_NAME);
+}
+
+bool p2PendingExpInsert(psDB * dbh, const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles, const char *filter, const char *stats, const char *recipe, psS32 p1_version, psS32 p2_version)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, psStringCopy(telescope))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, psStringCopy(filter))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, p1_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p1_version");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, p2_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p2_version");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, P2PENDINGEXP_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool p2PendingExpPop(psDB *dbh, char **exp_id, char **camera, char **telescope, char **exp_type, psS32 *imfiles, char **filter, char **stats, char **recipe, psS32 *p1_version, psS32 *p2_version)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, P2PENDINGEXP_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", P2PENDINGEXP_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, P2PENDINGEXP_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", P2PENDINGEXP_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, P2PENDINGEXP_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, P2PENDINGEXP_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *exp_id = psMetadataLookupPtr(&status, row, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        psFree(row);
+        return false;
+    }
+    *camera = psMetadataLookupPtr(&status, row, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        psFree(row);
+        return false;
+    }
+    *telescope = psMetadataLookupPtr(&status, row, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        psFree(row);
+        return false;
+    }
+    *exp_type = psMetadataLookupPtr(&status, row, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        psFree(row);
+        return false;
+    }
+    *imfiles = psMetadataLookupS32(&status, row, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        psFree(row);
+        return false;
+    }
+    *filter = psMetadataLookupPtr(&status, row, "filter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item filter");
+        psFree(row);
+        return false;
+    }
+    *stats = psMetadataLookupPtr(&status, row, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        psFree(row);
+        return false;
+    }
+    *recipe = psMetadataLookupPtr(&status, row, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        psFree(row);
+        return false;
+    }
+    *p1_version = psMetadataLookupS32(&status, row, "p1_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p1_version");
+        psFree(row);
+        return false;
+    }
+    *p2_version = psMetadataLookupS32(&status, row, "p2_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p2_version");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool p2PendingExpInsertObject(psDB *dbh, p2PendingExpRow *object)
+{
+    return p2PendingExpInsert(dbh, object->exp_id, object->camera, object->telescope, object->exp_type, object->imfiles, object->filter, object->stats, object->recipe, object->p1_version, object->p2_version);
+}
+
+p2PendingExpRow *p2PendingExpPopObject(psDB *dbh)
+{
+    char            exp_id[256];
+    char            camera[256];
+    char            telescope[256];
+    char            exp_type[256];
+    psS32           imfiles;
+    char            filter[256];
+    char            stats[256];
+    char            recipe[256];
+    psS32           p1_version;
+    psS32           p2_version;
+
+    if (!p2PendingExpPop(dbh, (char **)&exp_id, (char **)&camera, (char **)&telescope, (char **)&exp_type, &imfiles, (char **)&filter, (char **)&stats, (char **)&recipe, &p1_version, &p2_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return p2PendingExpRowAlloc(exp_id, camera, telescope, exp_type, imfiles, filter, stats, recipe, p1_version, p2_version);
+}
+
+bool p2PendingExpInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  P2PENDINGEXP_TABLE_NAME
+    if (!psFitsMoveExtName(fits, P2PENDINGEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", P2PENDINGEXP_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, P2PENDINGEXP_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool p2PendingExpPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!p2PendingExpSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                P2PENDINGEXP_TABLE_NAME, P2PENDINGEXP_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool p2PendingExpSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, P2PENDINGEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, P2PENDINGEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", P2PENDINGEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, P2PENDINGEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *p2PendingExpMetadataFromObject(const p2PendingExpRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(object->exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(object->camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, psStringCopy(object->telescope))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(object->exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, object->imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, psStringCopy(object->filter))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(object->stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(object->recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, object->p1_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p1_version");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, object->p2_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p2_version");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+p2PendingExpRow *p2PendingExpObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *exp_type;
+    psS32           imfiles;
+    char            *filter;
+    char            *stats;
+    char            *recipe;
+    psS32           p1_version;
+    psS32           p2_version;
+
+    exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    camera = psMetadataLookupPtr(&status, md, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        return false;
+    }
+    telescope = psMetadataLookupPtr(&status, md, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        return false;
+    }
+    exp_type = psMetadataLookupPtr(&status, md, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        return false;
+    }
+    imfiles = psMetadataLookupS32(&status, md, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        return false;
+    }
+    filter = psMetadataLookupPtr(&status, md, "filter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item filter");
+        return false;
+    }
+    stats = psMetadataLookupPtr(&status, md, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        return false;
+    }
+    recipe = psMetadataLookupPtr(&status, md, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        return false;
+    }
+    p1_version = psMetadataLookupS32(&status, md, "p1_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p1_version");
+        return false;
+    }
+    p2_version = psMetadataLookupS32(&status, md, "p2_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p2_version");
+        return false;
+    }
+
+    return p2PendingExpRowAlloc(exp_id, camera, telescope, exp_type, imfiles, filter, stats, recipe, p1_version, p2_version);
+}
+psArray *p2PendingExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, P2PENDINGEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, P2PENDINGEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", P2PENDINGEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, p2PendingExpObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long p2PendingExpDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        p2PendingExpRow *object = objects->data[i];
+        psMetadata *where = p2PendingExpMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, P2PENDINGEXP_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from p2PendingExp");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void p2PendingImfileRowFree(p2PendingImfileRow *object);
+
+p2PendingImfileRow *p2PendingImfileRowAlloc(const char *exp_id, const char *class_id, const char *uri, const char *stats, const char *recipe, psS32 p1_version, psS32 p2_version)
+{
+    p2PendingImfileRow *object;
+
+    object = psAlloc(sizeof(p2PendingImfileRow));
+    psMemSetDeallocator(object, (psFreeFunc)p2PendingImfileRowFree);
+
+    object->exp_id = psStringCopy(exp_id);
+    object->class_id = psStringCopy(class_id);
+    object->uri = psStringCopy(uri);
+    object->stats = psStringCopy(stats);
+    object->recipe = psStringCopy(recipe);
+    object->p1_version = p1_version;
+    object->p2_version = p2_version;
+
+    return object;
+}
+
+static void p2PendingImfileRowFree(p2PendingImfileRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->class_id);
+    psFree(object->uri);
+    psFree(object->stats);
+    psFree(object->recipe);
+}
+
+bool p2PendingImfileCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, P2PENDINGIMFILE_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", P2PENDINGIMFILE_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, "Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p1_version");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p2_version");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, P2PENDINGIMFILE_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool p2PendingImfileDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, P2PENDINGIMFILE_TABLE_NAME);
+}
+
+bool p2PendingImfileInsert(psDB * dbh, const char *exp_id, const char *class_id, const char *uri, const char *stats, const char *recipe, psS32 p1_version, psS32 p2_version)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, p1_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p1_version");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, p2_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p2_version");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, P2PENDINGIMFILE_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool p2PendingImfilePop(psDB *dbh, char **exp_id, char **class_id, char **uri, char **stats, char **recipe, psS32 *p1_version, psS32 *p2_version)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, P2PENDINGIMFILE_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", P2PENDINGIMFILE_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, P2PENDINGIMFILE_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", P2PENDINGIMFILE_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, P2PENDINGIMFILE_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, P2PENDINGIMFILE_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *exp_id = psMetadataLookupPtr(&status, row, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        psFree(row);
+        return false;
+    }
+    *class_id = psMetadataLookupPtr(&status, row, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        psFree(row);
+        return false;
+    }
+    *uri = psMetadataLookupPtr(&status, row, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        psFree(row);
+        return false;
+    }
+    *stats = psMetadataLookupPtr(&status, row, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        psFree(row);
+        return false;
+    }
+    *recipe = psMetadataLookupPtr(&status, row, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        psFree(row);
+        return false;
+    }
+    *p1_version = psMetadataLookupS32(&status, row, "p1_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p1_version");
+        psFree(row);
+        return false;
+    }
+    *p2_version = psMetadataLookupS32(&status, row, "p2_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p2_version");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool p2PendingImfileInsertObject(psDB *dbh, p2PendingImfileRow *object)
+{
+    return p2PendingImfileInsert(dbh, object->exp_id, object->class_id, object->uri, object->stats, object->recipe, object->p1_version, object->p2_version);
+}
+
+p2PendingImfileRow *p2PendingImfilePopObject(psDB *dbh)
+{
+    char            exp_id[256];
+    char            class_id[256];
+    char            uri[256];
+    char            stats[256];
+    char            recipe[256];
+    psS32           p1_version;
+    psS32           p2_version;
+
+    if (!p2PendingImfilePop(dbh, (char **)&exp_id, (char **)&class_id, (char **)&uri, (char **)&stats, (char **)&recipe, &p1_version, &p2_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return p2PendingImfileRowAlloc(exp_id, class_id, uri, stats, recipe, p1_version, p2_version);
+}
+
+bool p2PendingImfileInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  P2PENDINGIMFILE_TABLE_NAME
+    if (!psFitsMoveExtName(fits, P2PENDINGIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", P2PENDINGIMFILE_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, P2PENDINGIMFILE_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool p2PendingImfilePopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!p2PendingImfileSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                P2PENDINGIMFILE_TABLE_NAME, P2PENDINGIMFILE_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool p2PendingImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, P2PENDINGIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, P2PENDINGIMFILE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", P2PENDINGIMFILE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, P2PENDINGIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *p2PendingImfileMetadataFromObject(const p2PendingImfileRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(object->exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(object->class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(object->uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(object->stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(object->recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, object->p1_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p1_version");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, object->p2_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p2_version");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+p2PendingImfileRow *p2PendingImfileObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *exp_id;
+    char            *class_id;
+    char            *uri;
+    char            *stats;
+    char            *recipe;
+    psS32           p1_version;
+    psS32           p2_version;
+
+    exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    class_id = psMetadataLookupPtr(&status, md, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        return false;
+    }
+    uri = psMetadataLookupPtr(&status, md, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        return false;
+    }
+    stats = psMetadataLookupPtr(&status, md, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        return false;
+    }
+    recipe = psMetadataLookupPtr(&status, md, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        return false;
+    }
+    p1_version = psMetadataLookupS32(&status, md, "p1_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p1_version");
+        return false;
+    }
+    p2_version = psMetadataLookupS32(&status, md, "p2_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p2_version");
+        return false;
+    }
+
+    return p2PendingImfileRowAlloc(exp_id, class_id, uri, stats, recipe, p1_version, p2_version);
+}
+psArray *p2PendingImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, P2PENDINGIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, P2PENDINGIMFILE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", P2PENDINGIMFILE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, p2PendingImfileObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long p2PendingImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        p2PendingImfileRow *object = objects->data[i];
+        psMetadata *where = p2PendingImfileMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, P2PENDINGIMFILE_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from p2PendingImfile");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void p2DoneExpRowFree(p2DoneExpRow *object);
+
+p2DoneExpRow *p2DoneExpRowAlloc(const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles, const char *filter, const char *stats, const char *recipe, psS32 p1_version, psS32 p2_version)
+{
+    p2DoneExpRow    *object;
+
+    object = psAlloc(sizeof(p2DoneExpRow));
+    psMemSetDeallocator(object, (psFreeFunc)p2DoneExpRowFree);
+
+    object->exp_id = psStringCopy(exp_id);
+    object->camera = psStringCopy(camera);
+    object->telescope = psStringCopy(telescope);
+    object->exp_type = psStringCopy(exp_type);
+    object->imfiles = imfiles;
+    object->filter = psStringCopy(filter);
+    object->stats = psStringCopy(stats);
+    object->recipe = psStringCopy(recipe);
+    object->p1_version = p1_version;
+    object->p2_version = p2_version;
+
+    return object;
+}
+
+static void p2DoneExpRowFree(p2DoneExpRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->camera);
+    psFree(object->telescope);
+    psFree(object->exp_type);
+    psFree(object->filter);
+    psFree(object->stats);
+    psFree(object->recipe);
+}
+
+bool p2DoneExpCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, P2DONEEXP_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", P2DONEEXP_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p1_version");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p2_version");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, P2DONEEXP_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool p2DoneExpDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, P2DONEEXP_TABLE_NAME);
+}
+
+bool p2DoneExpInsert(psDB * dbh, const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles, const char *filter, const char *stats, const char *recipe, psS32 p1_version, psS32 p2_version)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, psStringCopy(telescope))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, psStringCopy(filter))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, p1_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p1_version");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, p2_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p2_version");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, P2DONEEXP_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool p2DoneExpPop(psDB *dbh, char **exp_id, char **camera, char **telescope, char **exp_type, psS32 *imfiles, char **filter, char **stats, char **recipe, psS32 *p1_version, psS32 *p2_version)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, P2DONEEXP_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", P2DONEEXP_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, P2DONEEXP_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", P2DONEEXP_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, P2DONEEXP_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, P2DONEEXP_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *exp_id = psMetadataLookupPtr(&status, row, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        psFree(row);
+        return false;
+    }
+    *camera = psMetadataLookupPtr(&status, row, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        psFree(row);
+        return false;
+    }
+    *telescope = psMetadataLookupPtr(&status, row, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        psFree(row);
+        return false;
+    }
+    *exp_type = psMetadataLookupPtr(&status, row, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        psFree(row);
+        return false;
+    }
+    *imfiles = psMetadataLookupS32(&status, row, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        psFree(row);
+        return false;
+    }
+    *filter = psMetadataLookupPtr(&status, row, "filter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item filter");
+        psFree(row);
+        return false;
+    }
+    *stats = psMetadataLookupPtr(&status, row, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        psFree(row);
+        return false;
+    }
+    *recipe = psMetadataLookupPtr(&status, row, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        psFree(row);
+        return false;
+    }
+    *p1_version = psMetadataLookupS32(&status, row, "p1_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p1_version");
+        psFree(row);
+        return false;
+    }
+    *p2_version = psMetadataLookupS32(&status, row, "p2_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p2_version");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool p2DoneExpInsertObject(psDB *dbh, p2DoneExpRow *object)
+{
+    return p2DoneExpInsert(dbh, object->exp_id, object->camera, object->telescope, object->exp_type, object->imfiles, object->filter, object->stats, object->recipe, object->p1_version, object->p2_version);
+}
+
+p2DoneExpRow *p2DoneExpPopObject(psDB *dbh)
+{
+    char            exp_id[256];
+    char            camera[256];
+    char            telescope[256];
+    char            exp_type[256];
+    psS32           imfiles;
+    char            filter[256];
+    char            stats[256];
+    char            recipe[256];
+    psS32           p1_version;
+    psS32           p2_version;
+
+    if (!p2DoneExpPop(dbh, (char **)&exp_id, (char **)&camera, (char **)&telescope, (char **)&exp_type, &imfiles, (char **)&filter, (char **)&stats, (char **)&recipe, &p1_version, &p2_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return p2DoneExpRowAlloc(exp_id, camera, telescope, exp_type, imfiles, filter, stats, recipe, p1_version, p2_version);
+}
+
+bool p2DoneExpInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  P2DONEEXP_TABLE_NAME
+    if (!psFitsMoveExtName(fits, P2DONEEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", P2DONEEXP_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, P2DONEEXP_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool p2DoneExpPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!p2DoneExpSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                P2DONEEXP_TABLE_NAME, P2DONEEXP_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool p2DoneExpSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, P2DONEEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, P2DONEEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", P2DONEEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, P2DONEEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *p2DoneExpMetadataFromObject(const p2DoneExpRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(object->exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(object->camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, psStringCopy(object->telescope))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(object->exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, object->imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, psStringCopy(object->filter))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(object->stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(object->recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, object->p1_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p1_version");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, object->p2_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p2_version");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+p2DoneExpRow *p2DoneExpObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *exp_type;
+    psS32           imfiles;
+    char            *filter;
+    char            *stats;
+    char            *recipe;
+    psS32           p1_version;
+    psS32           p2_version;
+
+    exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    camera = psMetadataLookupPtr(&status, md, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        return false;
+    }
+    telescope = psMetadataLookupPtr(&status, md, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        return false;
+    }
+    exp_type = psMetadataLookupPtr(&status, md, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        return false;
+    }
+    imfiles = psMetadataLookupS32(&status, md, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        return false;
+    }
+    filter = psMetadataLookupPtr(&status, md, "filter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item filter");
+        return false;
+    }
+    stats = psMetadataLookupPtr(&status, md, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        return false;
+    }
+    recipe = psMetadataLookupPtr(&status, md, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        return false;
+    }
+    p1_version = psMetadataLookupS32(&status, md, "p1_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p1_version");
+        return false;
+    }
+    p2_version = psMetadataLookupS32(&status, md, "p2_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p2_version");
+        return false;
+    }
+
+    return p2DoneExpRowAlloc(exp_id, camera, telescope, exp_type, imfiles, filter, stats, recipe, p1_version, p2_version);
+}
+psArray *p2DoneExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, P2DONEEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, P2DONEEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", P2DONEEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, p2DoneExpObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long p2DoneExpDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        p2DoneExpRow *object = objects->data[i];
+        psMetadata *where = p2DoneExpMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, P2DONEEXP_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from p2DoneExp");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void p2DoneImfileRowFree(p2DoneImfileRow *object);
+
+p2DoneImfileRow *p2DoneImfileRowAlloc(const char *exp_id, const char *class_id, const char *uri, const char *stats, const char *recipe, psS32 p1_version, psS32 p2_version)
+{
+    p2DoneImfileRow *object;
+
+    object = psAlloc(sizeof(p2DoneImfileRow));
+    psMemSetDeallocator(object, (psFreeFunc)p2DoneImfileRowFree);
+
+    object->exp_id = psStringCopy(exp_id);
+    object->class_id = psStringCopy(class_id);
+    object->uri = psStringCopy(uri);
+    object->stats = psStringCopy(stats);
+    object->recipe = psStringCopy(recipe);
+    object->p1_version = p1_version;
+    object->p2_version = p2_version;
+
+    return object;
+}
+
+static void p2DoneImfileRowFree(p2DoneImfileRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->class_id);
+    psFree(object->uri);
+    psFree(object->stats);
+    psFree(object->recipe);
+}
+
+bool p2DoneImfileCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, P2DONEIMFILE_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", P2DONEIMFILE_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, "Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p1_version");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p2_version");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, P2DONEIMFILE_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool p2DoneImfileDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, P2DONEIMFILE_TABLE_NAME);
+}
+
+bool p2DoneImfileInsert(psDB * dbh, const char *exp_id, const char *class_id, const char *uri, const char *stats, const char *recipe, psS32 p1_version, psS32 p2_version)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, p1_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p1_version");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, p2_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p2_version");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, P2DONEIMFILE_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool p2DoneImfilePop(psDB *dbh, char **exp_id, char **class_id, char **uri, char **stats, char **recipe, psS32 *p1_version, psS32 *p2_version)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, P2DONEIMFILE_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", P2DONEIMFILE_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, P2DONEIMFILE_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", P2DONEIMFILE_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, P2DONEIMFILE_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, P2DONEIMFILE_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *exp_id = psMetadataLookupPtr(&status, row, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        psFree(row);
+        return false;
+    }
+    *class_id = psMetadataLookupPtr(&status, row, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        psFree(row);
+        return false;
+    }
+    *uri = psMetadataLookupPtr(&status, row, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        psFree(row);
+        return false;
+    }
+    *stats = psMetadataLookupPtr(&status, row, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        psFree(row);
+        return false;
+    }
+    *recipe = psMetadataLookupPtr(&status, row, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        psFree(row);
+        return false;
+    }
+    *p1_version = psMetadataLookupS32(&status, row, "p1_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p1_version");
+        psFree(row);
+        return false;
+    }
+    *p2_version = psMetadataLookupS32(&status, row, "p2_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p2_version");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool p2DoneImfileInsertObject(psDB *dbh, p2DoneImfileRow *object)
+{
+    return p2DoneImfileInsert(dbh, object->exp_id, object->class_id, object->uri, object->stats, object->recipe, object->p1_version, object->p2_version);
+}
+
+p2DoneImfileRow *p2DoneImfilePopObject(psDB *dbh)
+{
+    char            exp_id[256];
+    char            class_id[256];
+    char            uri[256];
+    char            stats[256];
+    char            recipe[256];
+    psS32           p1_version;
+    psS32           p2_version;
+
+    if (!p2DoneImfilePop(dbh, (char **)&exp_id, (char **)&class_id, (char **)&uri, (char **)&stats, (char **)&recipe, &p1_version, &p2_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return p2DoneImfileRowAlloc(exp_id, class_id, uri, stats, recipe, p1_version, p2_version);
+}
+
+bool p2DoneImfileInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  P2DONEIMFILE_TABLE_NAME
+    if (!psFitsMoveExtName(fits, P2DONEIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", P2DONEIMFILE_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, P2DONEIMFILE_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool p2DoneImfilePopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!p2DoneImfileSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                P2DONEIMFILE_TABLE_NAME, P2DONEIMFILE_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool p2DoneImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, P2DONEIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, P2DONEIMFILE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", P2DONEIMFILE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, P2DONEIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *p2DoneImfileMetadataFromObject(const p2DoneImfileRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(object->exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(object->class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(object->uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(object->stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(object->recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, object->p1_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p1_version");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, object->p2_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p2_version");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+p2DoneImfileRow *p2DoneImfileObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *exp_id;
+    char            *class_id;
+    char            *uri;
+    char            *stats;
+    char            *recipe;
+    psS32           p1_version;
+    psS32           p2_version;
+
+    exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    class_id = psMetadataLookupPtr(&status, md, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        return false;
+    }
+    uri = psMetadataLookupPtr(&status, md, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        return false;
+    }
+    stats = psMetadataLookupPtr(&status, md, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        return false;
+    }
+    recipe = psMetadataLookupPtr(&status, md, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        return false;
+    }
+    p1_version = psMetadataLookupS32(&status, md, "p1_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p1_version");
+        return false;
+    }
+    p2_version = psMetadataLookupS32(&status, md, "p2_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p2_version");
+        return false;
+    }
+
+    return p2DoneImfileRowAlloc(exp_id, class_id, uri, stats, recipe, p1_version, p2_version);
+}
+psArray *p2DoneImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, P2DONEIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, P2DONEIMFILE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", P2DONEIMFILE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, p2DoneImfileObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long p2DoneImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        p2DoneImfileRow *object = objects->data[i];
+        psMetadata *where = p2DoneImfileMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, P2DONEIMFILE_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from p2DoneImfile");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void p3PendingExpRowFree(p3PendingExpRow *object);
+
+p3PendingExpRow *p3PendingExpRowAlloc(const char *exp_id, const char *camera, const char *exp_type, psS32 imfiles, const char *filter, const char *stats, const char *recipe, psS32 p2_version, psS32 p3_version)
+{
+    p3PendingExpRow *object;
+
+    object = psAlloc(sizeof(p3PendingExpRow));
+    psMemSetDeallocator(object, (psFreeFunc)p3PendingExpRowFree);
+
+    object->exp_id = psStringCopy(exp_id);
+    object->camera = psStringCopy(camera);
+    object->exp_type = psStringCopy(exp_type);
+    object->imfiles = imfiles;
+    object->filter = psStringCopy(filter);
+    object->stats = psStringCopy(stats);
+    object->recipe = psStringCopy(recipe);
+    object->p2_version = p2_version;
+    object->p3_version = p3_version;
+
+    return object;
+}
+
+static void p3PendingExpRowFree(p3PendingExpRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->camera);
+    psFree(object->exp_type);
+    psFree(object->filter);
+    psFree(object->stats);
+    psFree(object->recipe);
+}
+
+bool p3PendingExpCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, P3PENDINGEXP_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", P3PENDINGEXP_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p2_version");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p3_version", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p3_version");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, P3PENDINGEXP_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool p3PendingExpDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, P3PENDINGEXP_TABLE_NAME);
+}
+
+bool p3PendingExpInsert(psDB * dbh, const char *exp_id, const char *camera, const char *exp_type, psS32 imfiles, const char *filter, const char *stats, const char *recipe, psS32 p2_version, psS32 p3_version)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, psStringCopy(filter))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, p2_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p2_version");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p3_version", 0, NULL, p3_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p3_version");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, P3PENDINGEXP_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool p3PendingExpPop(psDB *dbh, char **exp_id, char **camera, char **exp_type, psS32 *imfiles, char **filter, char **stats, char **recipe, psS32 *p2_version, psS32 *p3_version)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, P3PENDINGEXP_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", P3PENDINGEXP_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, P3PENDINGEXP_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", P3PENDINGEXP_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, P3PENDINGEXP_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, P3PENDINGEXP_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *exp_id = psMetadataLookupPtr(&status, row, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        psFree(row);
+        return false;
+    }
+    *camera = psMetadataLookupPtr(&status, row, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        psFree(row);
+        return false;
+    }
+    *exp_type = psMetadataLookupPtr(&status, row, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        psFree(row);
+        return false;
+    }
+    *imfiles = psMetadataLookupS32(&status, row, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        psFree(row);
+        return false;
+    }
+    *filter = psMetadataLookupPtr(&status, row, "filter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item filter");
+        psFree(row);
+        return false;
+    }
+    *stats = psMetadataLookupPtr(&status, row, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        psFree(row);
+        return false;
+    }
+    *recipe = psMetadataLookupPtr(&status, row, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        psFree(row);
+        return false;
+    }
+    *p2_version = psMetadataLookupS32(&status, row, "p2_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p2_version");
+        psFree(row);
+        return false;
+    }
+    *p3_version = psMetadataLookupS32(&status, row, "p3_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p3_version");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool p3PendingExpInsertObject(psDB *dbh, p3PendingExpRow *object)
+{
+    return p3PendingExpInsert(dbh, object->exp_id, object->camera, object->exp_type, object->imfiles, object->filter, object->stats, object->recipe, object->p2_version, object->p3_version);
+}
+
+p3PendingExpRow *p3PendingExpPopObject(psDB *dbh)
+{
+    char            exp_id[256];
+    char            camera[256];
+    char            exp_type[256];
+    psS32           imfiles;
+    char            filter[256];
+    char            stats[256];
+    char            recipe[256];
+    psS32           p2_version;
+    psS32           p3_version;
+
+    if (!p3PendingExpPop(dbh, (char **)&exp_id, (char **)&camera, (char **)&exp_type, &imfiles, (char **)&filter, (char **)&stats, (char **)&recipe, &p2_version, &p3_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return p3PendingExpRowAlloc(exp_id, camera, exp_type, imfiles, filter, stats, recipe, p2_version, p3_version);
+}
+
+bool p3PendingExpInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  P3PENDINGEXP_TABLE_NAME
+    if (!psFitsMoveExtName(fits, P3PENDINGEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", P3PENDINGEXP_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, P3PENDINGEXP_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool p3PendingExpPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!p3PendingExpSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                P3PENDINGEXP_TABLE_NAME, P3PENDINGEXP_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool p3PendingExpSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, P3PENDINGEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, P3PENDINGEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", P3PENDINGEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, P3PENDINGEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *p3PendingExpMetadataFromObject(const p3PendingExpRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(object->exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(object->camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(object->exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, object->imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, psStringCopy(object->filter))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(object->stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(object->recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, object->p2_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p2_version");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "p3_version", 0, NULL, object->p3_version)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item p3_version");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+p3PendingExpRow *p3PendingExpObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *exp_id;
+    char            *camera;
+    char            *exp_type;
+    psS32           imfiles;
+    char            *filter;
+    char            *stats;
+    char            *recipe;
+    psS32           p2_version;
+    psS32           p3_version;
+
+    exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    camera = psMetadataLookupPtr(&status, md, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        return false;
+    }
+    exp_type = psMetadataLookupPtr(&status, md, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        return false;
+    }
+    imfiles = psMetadataLookupS32(&status, md, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        return false;
+    }
+    filter = psMetadataLookupPtr(&status, md, "filter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item filter");
+        return false;
+    }
+    stats = psMetadataLookupPtr(&status, md, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        return false;
+    }
+    recipe = psMetadataLookupPtr(&status, md, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        return false;
+    }
+    p2_version = psMetadataLookupS32(&status, md, "p2_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p2_version");
+        return false;
+    }
+    p3_version = psMetadataLookupS32(&status, md, "p3_version");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item p3_version");
+        return false;
+    }
+
+    return p3PendingExpRowAlloc(exp_id, camera, exp_type, imfiles, filter, stats, recipe, p2_version, p3_version);
+}
+psArray *p3PendingExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, P3PENDINGEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, P3PENDINGEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", P3PENDINGEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, p3PendingExpObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long p3PendingExpDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        p3PendingExpRow *object = objects->data[i];
+        psMetadata *where = p3PendingExpMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, P3PENDINGEXP_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from p3PendingExp");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void detRunRowFree(detRunRow *object);
+
+detRunRow *detRunRowAlloc(const char *det_type)
+{
+    detRunRow       *object;
+
+    object = psAlloc(sizeof(detRunRow));
+    psMemSetDeallocator(object, (psFreeFunc)detRunRowFree);
+
+    object->det_type = psStringCopy(det_type);
+
+    return object;
+}
+
+static void detRunRowFree(detRunRow *object)
+{
+    psFree(object->det_type);
+}
+
+bool detRunCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, DETRUN_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", DETRUN_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "det_type", 0, "Key", "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_type");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, DETRUN_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool detRunDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, DETRUN_TABLE_NAME);
+}
+
+bool detRunInsert(psDB * dbh, const char *det_type)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "det_type", 0, NULL, psStringCopy(det_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_type");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, DETRUN_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool detRunPop(psDB *dbh, char **det_type)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, DETRUN_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETRUN_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, DETRUN_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETRUN_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, DETRUN_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, DETRUN_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *det_type = psMetadataLookupPtr(&status, row, "det_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_type");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool detRunInsertObject(psDB *dbh, detRunRow *object)
+{
+    return detRunInsert(dbh, object->det_type);
+}
+
+detRunRow *detRunPopObject(psDB *dbh)
+{
+    char            det_type[256];
+
+    if (!detRunPop(dbh, (char **)&det_type)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return detRunRowAlloc(det_type);
+}
+
+bool detRunInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  DETRUN_TABLE_NAME
+    if (!psFitsMoveExtName(fits, DETRUN_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", DETRUN_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, DETRUN_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool detRunPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!detRunSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                DETRUN_TABLE_NAME, DETRUN_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool detRunSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETRUN_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, DETRUN_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETRUN_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, DETRUN_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *detRunMetadataFromObject(const detRunRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "det_type", 0, NULL, psStringCopy(object->det_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_type");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+detRunRow *detRunObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    char            *det_type;
+
+    det_type = psMetadataLookupPtr(&status, md, "det_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_type");
+        return false;
+    }
+
+    return detRunRowAlloc(det_type);
+}
+psArray *detRunSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETRUN_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, DETRUN_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETRUN_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, detRunObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long detRunDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        detRunRow *object = objects->data[i];
+        psMetadata *where = detRunMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, DETRUN_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from detRun");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void detInputExpRowFree(detInputExpRow *object);
+
+detInputExpRow *detInputExpRowAlloc(psS32 det_id, psS32 iteration, const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles, const char *filter, const char *stats)
+{
+    detInputExpRow  *object;
+
+    object = psAlloc(sizeof(detInputExpRow));
+    psMemSetDeallocator(object, (psFreeFunc)detInputExpRowFree);
+
+    object->det_id = det_id;
+    object->iteration = iteration;
+    object->exp_id = psStringCopy(exp_id);
+    object->camera = psStringCopy(camera);
+    object->telescope = psStringCopy(telescope);
+    object->exp_type = psStringCopy(exp_type);
+    object->imfiles = imfiles;
+    object->filter = psStringCopy(filter);
+    object->stats = psStringCopy(stats);
+
+    return object;
+}
+
+static void detInputExpRowFree(detInputExpRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->camera);
+    psFree(object->telescope);
+    psFree(object->exp_type);
+    psFree(object->filter);
+    psFree(object->stats);
+}
+
+bool detInputExpCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, DETINPUTEXP_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", DETINPUTEXP_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, "Primary Key", 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, "Primary Key", 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, DETINPUTEXP_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool detInputExpDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, DETINPUTEXP_TABLE_NAME);
+}
+
+bool detInputExpInsert(psDB * dbh, psS32 det_id, psS32 iteration, const char *exp_id, const char *camera, const char *telescope, const char *exp_type, psS32 imfiles, const char *filter, const char *stats)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, iteration)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, psStringCopy(telescope))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, psStringCopy(filter))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, DETINPUTEXP_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool detInputExpPop(psDB *dbh, psS32 *det_id, psS32 *iteration, char **exp_id, char **camera, char **telescope, char **exp_type, psS32 *imfiles, char **filter, char **stats)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, DETINPUTEXP_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETINPUTEXP_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, DETINPUTEXP_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETINPUTEXP_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, DETINPUTEXP_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, DETINPUTEXP_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *det_id = psMetadataLookupS32(&status, row, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
+        psFree(row);
+        return false;
+    }
+    *iteration = psMetadataLookupS32(&status, row, "iteration");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item iteration");
+        psFree(row);
+        return false;
+    }
+    *exp_id = psMetadataLookupPtr(&status, row, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        psFree(row);
+        return false;
+    }
+    *camera = psMetadataLookupPtr(&status, row, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        psFree(row);
+        return false;
+    }
+    *telescope = psMetadataLookupPtr(&status, row, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        psFree(row);
+        return false;
+    }
+    *exp_type = psMetadataLookupPtr(&status, row, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        psFree(row);
+        return false;
+    }
+    *imfiles = psMetadataLookupS32(&status, row, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        psFree(row);
+        return false;
+    }
+    *filter = psMetadataLookupPtr(&status, row, "filter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item filter");
+        psFree(row);
+        return false;
+    }
+    *stats = psMetadataLookupPtr(&status, row, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool detInputExpInsertObject(psDB *dbh, detInputExpRow *object)
+{
+    return detInputExpInsert(dbh, object->det_id, object->iteration, object->exp_id, object->camera, object->telescope, object->exp_type, object->imfiles, object->filter, object->stats);
+}
+
+detInputExpRow *detInputExpPopObject(psDB *dbh)
+{
+    psS32           det_id;
+    psS32           iteration;
+    char            exp_id[256];
+    char            camera[256];
+    char            telescope[256];
+    char            exp_type[256];
+    psS32           imfiles;
+    char            filter[256];
+    char            stats[256];
+
+    if (!detInputExpPop(dbh, &det_id, &iteration, (char **)&exp_id, (char **)&camera, (char **)&telescope, (char **)&exp_type, &imfiles, (char **)&filter, (char **)&stats)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return detInputExpRowAlloc(det_id, iteration, exp_id, camera, telescope, exp_type, imfiles, filter, stats);
+}
+
+bool detInputExpInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  DETINPUTEXP_TABLE_NAME
+    if (!psFitsMoveExtName(fits, DETINPUTEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", DETINPUTEXP_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, DETINPUTEXP_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool detInputExpPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!detInputExpSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                DETINPUTEXP_TABLE_NAME, DETINPUTEXP_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool detInputExpSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETINPUTEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, DETINPUTEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETINPUTEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, DETINPUTEXP_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *detInputExpMetadataFromObject(const detInputExpRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, object->det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, object->iteration)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(object->exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, psStringCopy(object->camera))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item camera");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, psStringCopy(object->telescope))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item telescope");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, psStringCopy(object->exp_type))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_type");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, object->imfiles)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item imfiles");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, psStringCopy(object->filter))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item filter");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(object->stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+detInputExpRow *detInputExpObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    psS32           det_id;
+    psS32           iteration;
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *exp_type;
+    psS32           imfiles;
+    char            *filter;
+    char            *stats;
+
+    det_id = psMetadataLookupS32(&status, md, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
+        return false;
+    }
+    iteration = psMetadataLookupS32(&status, md, "iteration");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item iteration");
+        return false;
+    }
+    exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    camera = psMetadataLookupPtr(&status, md, "camera");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item camera");
+        return false;
+    }
+    telescope = psMetadataLookupPtr(&status, md, "telescope");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item telescope");
+        return false;
+    }
+    exp_type = psMetadataLookupPtr(&status, md, "exp_type");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_type");
+        return false;
+    }
+    imfiles = psMetadataLookupS32(&status, md, "imfiles");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item imfiles");
+        return false;
+    }
+    filter = psMetadataLookupPtr(&status, md, "filter");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item filter");
+        return false;
+    }
+    stats = psMetadataLookupPtr(&status, md, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        return false;
+    }
+
+    return detInputExpRowAlloc(det_id, iteration, exp_id, camera, telescope, exp_type, imfiles, filter, stats);
+}
+psArray *detInputExpSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETINPUTEXP_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, DETINPUTEXP_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETINPUTEXP_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, detInputExpObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long detInputExpDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        detInputExpRow *object = objects->data[i];
+        psMetadata *where = detInputExpMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, DETINPUTEXP_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from detInputExp");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void detProcessedImfileRowFree(detProcessedImfileRow *object);
+
+detProcessedImfileRow *detProcessedImfileRowAlloc(psS32 det_id, const char *exp_id, const char *class_id, const char *uri, const char *stats, const char *recipe)
+{
+    detProcessedImfileRow *object;
+
+    object = psAlloc(sizeof(detProcessedImfileRow));
+    psMemSetDeallocator(object, (psFreeFunc)detProcessedImfileRowFree);
+
+    object->det_id = det_id;
+    object->exp_id = psStringCopy(exp_id);
+    object->class_id = psStringCopy(class_id);
+    object->uri = psStringCopy(uri);
+    object->stats = psStringCopy(stats);
+    object->recipe = psStringCopy(recipe);
+
+    return object;
+}
+
+static void detProcessedImfileRowFree(detProcessedImfileRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->class_id);
+    psFree(object->uri);
+    psFree(object->stats);
+    psFree(object->recipe);
+}
+
+bool detProcessedImfileCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, DETPROCESSEDIMFILE_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", DETPROCESSEDIMFILE_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, "Primary Key", 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, DETPROCESSEDIMFILE_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool detProcessedImfileDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, DETPROCESSEDIMFILE_TABLE_NAME);
+}
+
+bool detProcessedImfileInsert(psDB * dbh, psS32 det_id, const char *exp_id, const char *class_id, const char *uri, const char *stats, const char *recipe)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, DETPROCESSEDIMFILE_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool detProcessedImfilePop(psDB *dbh, psS32 *det_id, char **exp_id, char **class_id, char **uri, char **stats, char **recipe)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, DETPROCESSEDIMFILE_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETPROCESSEDIMFILE_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, DETPROCESSEDIMFILE_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETPROCESSEDIMFILE_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, DETPROCESSEDIMFILE_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, DETPROCESSEDIMFILE_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *det_id = psMetadataLookupS32(&status, row, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
+        psFree(row);
+        return false;
+    }
+    *exp_id = psMetadataLookupPtr(&status, row, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        psFree(row);
+        return false;
+    }
+    *class_id = psMetadataLookupPtr(&status, row, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        psFree(row);
+        return false;
+    }
+    *uri = psMetadataLookupPtr(&status, row, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        psFree(row);
+        return false;
+    }
+    *stats = psMetadataLookupPtr(&status, row, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        psFree(row);
+        return false;
+    }
+    *recipe = psMetadataLookupPtr(&status, row, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool detProcessedImfileInsertObject(psDB *dbh, detProcessedImfileRow *object)
+{
+    return detProcessedImfileInsert(dbh, object->det_id, object->exp_id, object->class_id, object->uri, object->stats, object->recipe);
+}
+
+detProcessedImfileRow *detProcessedImfilePopObject(psDB *dbh)
+{
+    psS32           det_id;
+    char            exp_id[256];
+    char            class_id[256];
+    char            uri[256];
+    char            stats[256];
+    char            recipe[256];
+
+    if (!detProcessedImfilePop(dbh, &det_id, (char **)&exp_id, (char **)&class_id, (char **)&uri, (char **)&stats, (char **)&recipe)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return detProcessedImfileRowAlloc(det_id, exp_id, class_id, uri, stats, recipe);
+}
+
+bool detProcessedImfileInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  DETPROCESSEDIMFILE_TABLE_NAME
+    if (!psFitsMoveExtName(fits, DETPROCESSEDIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", DETPROCESSEDIMFILE_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, DETPROCESSEDIMFILE_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool detProcessedImfilePopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!detProcessedImfileSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                DETPROCESSEDIMFILE_TABLE_NAME, DETPROCESSEDIMFILE_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool detProcessedImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETPROCESSEDIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, DETPROCESSEDIMFILE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETPROCESSEDIMFILE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, DETPROCESSEDIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *detProcessedImfileMetadataFromObject(const detProcessedImfileRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, object->det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(object->exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(object->class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(object->uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(object->stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(object->recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+detProcessedImfileRow *detProcessedImfileObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    psS32           det_id;
+    char            *exp_id;
+    char            *class_id;
+    char            *uri;
+    char            *stats;
+    char            *recipe;
+
+    det_id = psMetadataLookupS32(&status, md, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
+        return false;
+    }
+    exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    class_id = psMetadataLookupPtr(&status, md, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        return false;
+    }
+    uri = psMetadataLookupPtr(&status, md, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        return false;
+    }
+    stats = psMetadataLookupPtr(&status, md, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        return false;
+    }
+    recipe = psMetadataLookupPtr(&status, md, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        return false;
+    }
+
+    return detProcessedImfileRowAlloc(det_id, exp_id, class_id, uri, stats, recipe);
+}
+psArray *detProcessedImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETPROCESSEDIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, DETPROCESSEDIMFILE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETPROCESSEDIMFILE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, detProcessedImfileObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long detProcessedImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        detProcessedImfileRow *object = objects->data[i];
+        psMetadata *where = detProcessedImfileMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, DETPROCESSEDIMFILE_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from detProcessedImfile");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void detStackedImfileRowFree(detStackedImfileRow *object);
+
+detStackedImfileRow *detStackedImfileRowAlloc(psS32 det_id, psS32 iteration, const char *class_id, const char *uri, const char *stats, const char *recipe)
+{
+    detStackedImfileRow *object;
+
+    object = psAlloc(sizeof(detStackedImfileRow));
+    psMemSetDeallocator(object, (psFreeFunc)detStackedImfileRowFree);
+
+    object->det_id = det_id;
+    object->iteration = iteration;
+    object->class_id = psStringCopy(class_id);
+    object->uri = psStringCopy(uri);
+    object->stats = psStringCopy(stats);
+    object->recipe = psStringCopy(recipe);
+
+    return object;
+}
+
+static void detStackedImfileRowFree(detStackedImfileRow *object)
+{
+    psFree(object->class_id);
+    psFree(object->uri);
+    psFree(object->stats);
+    psFree(object->recipe);
+}
+
+bool detStackedImfileCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, DETSTACKEDIMFILE_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", DETSTACKEDIMFILE_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, "Primary Key", 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, "Primary Key", 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, DETSTACKEDIMFILE_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool detStackedImfileDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, DETSTACKEDIMFILE_TABLE_NAME);
+}
+
+bool detStackedImfileInsert(psDB * dbh, psS32 det_id, psS32 iteration, const char *class_id, const char *uri, const char *stats, const char *recipe)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, iteration)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, DETSTACKEDIMFILE_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool detStackedImfilePop(psDB *dbh, psS32 *det_id, psS32 *iteration, char **class_id, char **uri, char **stats, char **recipe)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, DETSTACKEDIMFILE_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETSTACKEDIMFILE_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, DETSTACKEDIMFILE_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETSTACKEDIMFILE_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, DETSTACKEDIMFILE_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, DETSTACKEDIMFILE_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *det_id = psMetadataLookupS32(&status, row, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
+        psFree(row);
+        return false;
+    }
+    *iteration = psMetadataLookupS32(&status, row, "iteration");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item iteration");
+        psFree(row);
+        return false;
+    }
+    *class_id = psMetadataLookupPtr(&status, row, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        psFree(row);
+        return false;
+    }
+    *uri = psMetadataLookupPtr(&status, row, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        psFree(row);
+        return false;
+    }
+    *stats = psMetadataLookupPtr(&status, row, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        psFree(row);
+        return false;
+    }
+    *recipe = psMetadataLookupPtr(&status, row, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool detStackedImfileInsertObject(psDB *dbh, detStackedImfileRow *object)
+{
+    return detStackedImfileInsert(dbh, object->det_id, object->iteration, object->class_id, object->uri, object->stats, object->recipe);
+}
+
+detStackedImfileRow *detStackedImfilePopObject(psDB *dbh)
+{
+    psS32           det_id;
+    psS32           iteration;
+    char            class_id[256];
+    char            uri[256];
+    char            stats[256];
+    char            recipe[256];
+
+    if (!detStackedImfilePop(dbh, &det_id, &iteration, (char **)&class_id, (char **)&uri, (char **)&stats, (char **)&recipe)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return detStackedImfileRowAlloc(det_id, iteration, class_id, uri, stats, recipe);
+}
+
+bool detStackedImfileInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  DETSTACKEDIMFILE_TABLE_NAME
+    if (!psFitsMoveExtName(fits, DETSTACKEDIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", DETSTACKEDIMFILE_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, DETSTACKEDIMFILE_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool detStackedImfilePopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!detStackedImfileSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                DETSTACKEDIMFILE_TABLE_NAME, DETSTACKEDIMFILE_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool detStackedImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETSTACKEDIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, DETSTACKEDIMFILE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETSTACKEDIMFILE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, DETSTACKEDIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *detStackedImfileMetadataFromObject(const detStackedImfileRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, object->det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, object->iteration)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(object->class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(object->uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(object->stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(object->recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+detStackedImfileRow *detStackedImfileObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    psS32           det_id;
+    psS32           iteration;
+    char            *class_id;
+    char            *uri;
+    char            *stats;
+    char            *recipe;
+
+    det_id = psMetadataLookupS32(&status, md, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
+        return false;
+    }
+    iteration = psMetadataLookupS32(&status, md, "iteration");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item iteration");
+        return false;
+    }
+    class_id = psMetadataLookupPtr(&status, md, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        return false;
+    }
+    uri = psMetadataLookupPtr(&status, md, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        return false;
+    }
+    stats = psMetadataLookupPtr(&status, md, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        return false;
+    }
+    recipe = psMetadataLookupPtr(&status, md, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        return false;
+    }
+
+    return detStackedImfileRowAlloc(det_id, iteration, class_id, uri, stats, recipe);
+}
+psArray *detStackedImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETSTACKEDIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, DETSTACKEDIMFILE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETSTACKEDIMFILE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, detStackedImfileObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long detStackedImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        detStackedImfileRow *object = objects->data[i];
+        psMetadata *where = detStackedImfileMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, DETSTACKEDIMFILE_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from detStackedImfile");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void detNormalizedImfileRowFree(detNormalizedImfileRow *object);
+
+detNormalizedImfileRow *detNormalizedImfileRowAlloc(psS32 det_id, psS32 iteration, const char *class_id, const char *uri, const char *stats, const char *recipe)
+{
+    detNormalizedImfileRow *object;
+
+    object = psAlloc(sizeof(detNormalizedImfileRow));
+    psMemSetDeallocator(object, (psFreeFunc)detNormalizedImfileRowFree);
+
+    object->det_id = det_id;
+    object->iteration = iteration;
+    object->class_id = psStringCopy(class_id);
+    object->uri = psStringCopy(uri);
+    object->stats = psStringCopy(stats);
+    object->recipe = psStringCopy(recipe);
+
+    return object;
+}
+
+static void detNormalizedImfileRowFree(detNormalizedImfileRow *object)
+{
+    psFree(object->class_id);
+    psFree(object->uri);
+    psFree(object->stats);
+    psFree(object->recipe);
+}
+
+bool detNormalizedImfileCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, DETNORMALIZEDIMFILE_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", DETNORMALIZEDIMFILE_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, "Primary Key", 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, "Primary Key", 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, DETNORMALIZEDIMFILE_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool detNormalizedImfileDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, DETNORMALIZEDIMFILE_TABLE_NAME);
+}
+
+bool detNormalizedImfileInsert(psDB * dbh, psS32 det_id, psS32 iteration, const char *class_id, const char *uri, const char *stats, const char *recipe)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, iteration)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, DETNORMALIZEDIMFILE_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool detNormalizedImfilePop(psDB *dbh, psS32 *det_id, psS32 *iteration, char **class_id, char **uri, char **stats, char **recipe)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, DETNORMALIZEDIMFILE_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETNORMALIZEDIMFILE_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, DETNORMALIZEDIMFILE_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETNORMALIZEDIMFILE_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, DETNORMALIZEDIMFILE_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, DETNORMALIZEDIMFILE_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *det_id = psMetadataLookupS32(&status, row, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
+        psFree(row);
+        return false;
+    }
+    *iteration = psMetadataLookupS32(&status, row, "iteration");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item iteration");
+        psFree(row);
+        return false;
+    }
+    *class_id = psMetadataLookupPtr(&status, row, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        psFree(row);
+        return false;
+    }
+    *uri = psMetadataLookupPtr(&status, row, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        psFree(row);
+        return false;
+    }
+    *stats = psMetadataLookupPtr(&status, row, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        psFree(row);
+        return false;
+    }
+    *recipe = psMetadataLookupPtr(&status, row, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool detNormalizedImfileInsertObject(psDB *dbh, detNormalizedImfileRow *object)
+{
+    return detNormalizedImfileInsert(dbh, object->det_id, object->iteration, object->class_id, object->uri, object->stats, object->recipe);
+}
+
+detNormalizedImfileRow *detNormalizedImfilePopObject(psDB *dbh)
+{
+    psS32           det_id;
+    psS32           iteration;
+    char            class_id[256];
+    char            uri[256];
+    char            stats[256];
+    char            recipe[256];
+
+    if (!detNormalizedImfilePop(dbh, &det_id, &iteration, (char **)&class_id, (char **)&uri, (char **)&stats, (char **)&recipe)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return detNormalizedImfileRowAlloc(det_id, iteration, class_id, uri, stats, recipe);
+}
+
+bool detNormalizedImfileInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  DETNORMALIZEDIMFILE_TABLE_NAME
+    if (!psFitsMoveExtName(fits, DETNORMALIZEDIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", DETNORMALIZEDIMFILE_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, DETNORMALIZEDIMFILE_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool detNormalizedImfilePopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!detNormalizedImfileSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                DETNORMALIZEDIMFILE_TABLE_NAME, DETNORMALIZEDIMFILE_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool detNormalizedImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETNORMALIZEDIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, DETNORMALIZEDIMFILE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETNORMALIZEDIMFILE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, DETNORMALIZEDIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *detNormalizedImfileMetadataFromObject(const detNormalizedImfileRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, object->det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, object->iteration)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(object->class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(object->uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(object->stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(object->recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+detNormalizedImfileRow *detNormalizedImfileObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    psS32           det_id;
+    psS32           iteration;
+    char            *class_id;
+    char            *uri;
+    char            *stats;
+    char            *recipe;
+
+    det_id = psMetadataLookupS32(&status, md, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
+        return false;
+    }
+    iteration = psMetadataLookupS32(&status, md, "iteration");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item iteration");
+        return false;
+    }
+    class_id = psMetadataLookupPtr(&status, md, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        return false;
+    }
+    uri = psMetadataLookupPtr(&status, md, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        return false;
+    }
+    stats = psMetadataLookupPtr(&status, md, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        return false;
+    }
+    recipe = psMetadataLookupPtr(&status, md, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        return false;
+    }
+
+    return detNormalizedImfileRowAlloc(det_id, iteration, class_id, uri, stats, recipe);
+}
+psArray *detNormalizedImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETNORMALIZEDIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, DETNORMALIZEDIMFILE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETNORMALIZEDIMFILE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, detNormalizedImfileObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long detNormalizedImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        detNormalizedImfileRow *object = objects->data[i];
+        psMetadata *where = detNormalizedImfileMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, DETNORMALIZEDIMFILE_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from detNormalizedImfile");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void detMasterFrameRowFree(detMasterFrameRow *object);
+
+detMasterFrameRow *detMasterFrameRowAlloc(psS32 det_id, psS32 iteration, const char *comment)
+{
+    detMasterFrameRow *object;
+
+    object = psAlloc(sizeof(detMasterFrameRow));
+    psMemSetDeallocator(object, (psFreeFunc)detMasterFrameRowFree);
+
+    object->det_id = det_id;
+    object->iteration = iteration;
+    object->comment = psStringCopy(comment);
+
+    return object;
+}
+
+static void detMasterFrameRowFree(detMasterFrameRow *object)
+{
+    psFree(object->comment);
+}
+
+bool detMasterFrameCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, DETMASTERFRAME_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", DETMASTERFRAME_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, "Primary Key", 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, "Primary Key", 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "comment", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item comment");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, DETMASTERFRAME_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool detMasterFrameDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, DETMASTERFRAME_TABLE_NAME);
+}
+
+bool detMasterFrameInsert(psDB * dbh, psS32 det_id, psS32 iteration, const char *comment)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, iteration)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "comment", 0, NULL, psStringCopy(comment))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item comment");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, DETMASTERFRAME_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool detMasterFramePop(psDB *dbh, psS32 *det_id, psS32 *iteration, char **comment)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, DETMASTERFRAME_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETMASTERFRAME_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, DETMASTERFRAME_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETMASTERFRAME_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, DETMASTERFRAME_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, DETMASTERFRAME_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *det_id = psMetadataLookupS32(&status, row, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
+        psFree(row);
+        return false;
+    }
+    *iteration = psMetadataLookupS32(&status, row, "iteration");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item iteration");
+        psFree(row);
+        return false;
+    }
+    *comment = psMetadataLookupPtr(&status, row, "comment");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item comment");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool detMasterFrameInsertObject(psDB *dbh, detMasterFrameRow *object)
+{
+    return detMasterFrameInsert(dbh, object->det_id, object->iteration, object->comment);
+}
+
+detMasterFrameRow *detMasterFramePopObject(psDB *dbh)
+{
+    psS32           det_id;
+    psS32           iteration;
+    char            comment[256];
+
+    if (!detMasterFramePop(dbh, &det_id, &iteration, (char **)&comment)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return detMasterFrameRowAlloc(det_id, iteration, comment);
+}
+
+bool detMasterFrameInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  DETMASTERFRAME_TABLE_NAME
+    if (!psFitsMoveExtName(fits, DETMASTERFRAME_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", DETMASTERFRAME_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, DETMASTERFRAME_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool detMasterFramePopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!detMasterFrameSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                DETMASTERFRAME_TABLE_NAME, DETMASTERFRAME_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool detMasterFrameSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETMASTERFRAME_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, DETMASTERFRAME_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETMASTERFRAME_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, DETMASTERFRAME_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *detMasterFrameMetadataFromObject(const detMasterFrameRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, object->det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, object->iteration)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "comment", 0, NULL, psStringCopy(object->comment))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item comment");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+detMasterFrameRow *detMasterFrameObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    psS32           det_id;
+    psS32           iteration;
+    char            *comment;
+
+    det_id = psMetadataLookupS32(&status, md, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
+        return false;
+    }
+    iteration = psMetadataLookupS32(&status, md, "iteration");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item iteration");
+        return false;
+    }
+    comment = psMetadataLookupPtr(&status, md, "comment");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item comment");
+        return false;
+    }
+
+    return detMasterFrameRowAlloc(det_id, iteration, comment);
+}
+psArray *detMasterFrameSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETMASTERFRAME_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, DETMASTERFRAME_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETMASTERFRAME_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, detMasterFrameObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long detMasterFrameDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        detMasterFrameRow *object = objects->data[i];
+        psMetadata *where = detMasterFrameMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, DETMASTERFRAME_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from detMasterFrame");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void detMasterImfileRowFree(detMasterImfileRow *object);
+
+detMasterImfileRow *detMasterImfileRowAlloc(psS32 det_id, const char *class_id, const char *uri, const char *stats, const char *recipe)
+{
+    detMasterImfileRow *object;
+
+    object = psAlloc(sizeof(detMasterImfileRow));
+    psMemSetDeallocator(object, (psFreeFunc)detMasterImfileRowFree);
+
+    object->det_id = det_id;
+    object->class_id = psStringCopy(class_id);
+    object->uri = psStringCopy(uri);
+    object->stats = psStringCopy(stats);
+    object->recipe = psStringCopy(recipe);
+
+    return object;
+}
+
+static void detMasterImfileRowFree(detMasterImfileRow *object)
+{
+    psFree(object->class_id);
+    psFree(object->uri);
+    psFree(object->stats);
+    psFree(object->recipe);
+}
+
+bool detMasterImfileCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, DETMASTERIMFILE_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", DETMASTERIMFILE_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, "Primary Key", 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, DETMASTERIMFILE_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool detMasterImfileDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, DETMASTERIMFILE_TABLE_NAME);
+}
+
+bool detMasterImfileInsert(psDB * dbh, psS32 det_id, const char *class_id, const char *uri, const char *stats, const char *recipe)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, DETMASTERIMFILE_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool detMasterImfilePop(psDB *dbh, psS32 *det_id, char **class_id, char **uri, char **stats, char **recipe)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, DETMASTERIMFILE_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETMASTERIMFILE_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, DETMASTERIMFILE_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETMASTERIMFILE_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, DETMASTERIMFILE_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, DETMASTERIMFILE_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *det_id = psMetadataLookupS32(&status, row, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
+        psFree(row);
+        return false;
+    }
+    *class_id = psMetadataLookupPtr(&status, row, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        psFree(row);
+        return false;
+    }
+    *uri = psMetadataLookupPtr(&status, row, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        psFree(row);
+        return false;
+    }
+    *stats = psMetadataLookupPtr(&status, row, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        psFree(row);
+        return false;
+    }
+    *recipe = psMetadataLookupPtr(&status, row, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool detMasterImfileInsertObject(psDB *dbh, detMasterImfileRow *object)
+{
+    return detMasterImfileInsert(dbh, object->det_id, object->class_id, object->uri, object->stats, object->recipe);
+}
+
+detMasterImfileRow *detMasterImfilePopObject(psDB *dbh)
+{
+    psS32           det_id;
+    char            class_id[256];
+    char            uri[256];
+    char            stats[256];
+    char            recipe[256];
+
+    if (!detMasterImfilePop(dbh, &det_id, (char **)&class_id, (char **)&uri, (char **)&stats, (char **)&recipe)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return detMasterImfileRowAlloc(det_id, class_id, uri, stats, recipe);
+}
+
+bool detMasterImfileInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  DETMASTERIMFILE_TABLE_NAME
+    if (!psFitsMoveExtName(fits, DETMASTERIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", DETMASTERIMFILE_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, DETMASTERIMFILE_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool detMasterImfilePopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!detMasterImfileSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                DETMASTERIMFILE_TABLE_NAME, DETMASTERIMFILE_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool detMasterImfileSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETMASTERIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, DETMASTERIMFILE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETMASTERIMFILE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, DETMASTERIMFILE_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *detMasterImfileMetadataFromObject(const detMasterImfileRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, object->det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(object->class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, psStringCopy(object->uri))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item uri");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(object->stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(object->recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+detMasterImfileRow *detMasterImfileObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    psS32           det_id;
+    char            *class_id;
+    char            *uri;
+    char            *stats;
+    char            *recipe;
+
+    det_id = psMetadataLookupS32(&status, md, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
+        return false;
+    }
+    class_id = psMetadataLookupPtr(&status, md, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        return false;
+    }
+    uri = psMetadataLookupPtr(&status, md, "uri");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item uri");
+        return false;
+    }
+    stats = psMetadataLookupPtr(&status, md, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        return false;
+    }
+    recipe = psMetadataLookupPtr(&status, md, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        return false;
+    }
+
+    return detMasterImfileRowAlloc(det_id, class_id, uri, stats, recipe);
+}
+psArray *detMasterImfileSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETMASTERIMFILE_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, DETMASTERIMFILE_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETMASTERIMFILE_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, detMasterImfileObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long detMasterImfileDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        detMasterImfileRow *object = objects->data[i];
+        psMetadata *where = detMasterImfileMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, DETMASTERIMFILE_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from detMasterImfile");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void detResidImfileAnalysisRowFree(detResidImfileAnalysisRow *object);
+
+detResidImfileAnalysisRow *detResidImfileAnalysisRowAlloc(psS32 det_id, psS32 iteration, const char *exp_id, const char *class_id, const char *stats, const char *recipe)
+{
+    detResidImfileAnalysisRow *object;
+
+    object = psAlloc(sizeof(detResidImfileAnalysisRow));
+    psMemSetDeallocator(object, (psFreeFunc)detResidImfileAnalysisRowFree);
+
+    object->det_id = det_id;
+    object->iteration = iteration;
+    object->exp_id = psStringCopy(exp_id);
+    object->class_id = psStringCopy(class_id);
+    object->stats = psStringCopy(stats);
+    object->recipe = psStringCopy(recipe);
+
+    return object;
+}
+
+static void detResidImfileAnalysisRowFree(detResidImfileAnalysisRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->class_id);
+    psFree(object->stats);
+    psFree(object->recipe);
+}
+
+bool detResidImfileAnalysisCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, DETRESIDIMFILEANALYSIS_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", DETRESIDIMFILEANALYSIS_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, "Primary Key", 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, "Primary Key", 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, DETRESIDIMFILEANALYSIS_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool detResidImfileAnalysisDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, DETRESIDIMFILEANALYSIS_TABLE_NAME);
+}
+
+bool detResidImfileAnalysisInsert(psDB * dbh, psS32 det_id, psS32 iteration, const char *exp_id, const char *class_id, const char *stats, const char *recipe)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, iteration)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, DETRESIDIMFILEANALYSIS_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool detResidImfileAnalysisPop(psDB *dbh, psS32 *det_id, psS32 *iteration, char **exp_id, char **class_id, char **stats, char **recipe)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, DETRESIDIMFILEANALYSIS_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETRESIDIMFILEANALYSIS_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, DETRESIDIMFILEANALYSIS_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETRESIDIMFILEANALYSIS_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, DETRESIDIMFILEANALYSIS_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, DETRESIDIMFILEANALYSIS_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *det_id = psMetadataLookupS32(&status, row, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
+        psFree(row);
+        return false;
+    }
+    *iteration = psMetadataLookupS32(&status, row, "iteration");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item iteration");
+        psFree(row);
+        return false;
+    }
+    *exp_id = psMetadataLookupPtr(&status, row, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        psFree(row);
+        return false;
+    }
+    *class_id = psMetadataLookupPtr(&status, row, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        psFree(row);
+        return false;
+    }
+    *stats = psMetadataLookupPtr(&status, row, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        psFree(row);
+        return false;
+    }
+    *recipe = psMetadataLookupPtr(&status, row, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool detResidImfileAnalysisInsertObject(psDB *dbh, detResidImfileAnalysisRow *object)
+{
+    return detResidImfileAnalysisInsert(dbh, object->det_id, object->iteration, object->exp_id, object->class_id, object->stats, object->recipe);
+}
+
+detResidImfileAnalysisRow *detResidImfileAnalysisPopObject(psDB *dbh)
+{
+    psS32           det_id;
+    psS32           iteration;
+    char            exp_id[256];
+    char            class_id[256];
+    char            stats[256];
+    char            recipe[256];
+
+    if (!detResidImfileAnalysisPop(dbh, &det_id, &iteration, (char **)&exp_id, (char **)&class_id, (char **)&stats, (char **)&recipe)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return detResidImfileAnalysisRowAlloc(det_id, iteration, exp_id, class_id, stats, recipe);
+}
+
+bool detResidImfileAnalysisInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  DETRESIDIMFILEANALYSIS_TABLE_NAME
+    if (!psFitsMoveExtName(fits, DETRESIDIMFILEANALYSIS_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", DETRESIDIMFILEANALYSIS_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, DETRESIDIMFILEANALYSIS_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool detResidImfileAnalysisPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!detResidImfileAnalysisSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                DETRESIDIMFILEANALYSIS_TABLE_NAME, DETRESIDIMFILEANALYSIS_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool detResidImfileAnalysisSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETRESIDIMFILEANALYSIS_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, DETRESIDIMFILEANALYSIS_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETRESIDIMFILEANALYSIS_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, DETRESIDIMFILEANALYSIS_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *detResidImfileAnalysisMetadataFromObject(const detResidImfileAnalysisRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, object->det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, object->iteration)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(object->exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, psStringCopy(object->class_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(object->stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(object->recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+detResidImfileAnalysisRow *detResidImfileAnalysisObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    psS32           det_id;
+    psS32           iteration;
+    char            *exp_id;
+    char            *class_id;
+    char            *stats;
+    char            *recipe;
+
+    det_id = psMetadataLookupS32(&status, md, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
+        return false;
+    }
+    iteration = psMetadataLookupS32(&status, md, "iteration");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item iteration");
+        return false;
+    }
+    exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    class_id = psMetadataLookupPtr(&status, md, "class_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item class_id");
+        return false;
+    }
+    stats = psMetadataLookupPtr(&status, md, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        return false;
+    }
+    recipe = psMetadataLookupPtr(&status, md, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        return false;
+    }
+
+    return detResidImfileAnalysisRowAlloc(det_id, iteration, exp_id, class_id, stats, recipe);
+}
+psArray *detResidImfileAnalysisSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETRESIDIMFILEANALYSIS_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, DETRESIDIMFILEANALYSIS_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETRESIDIMFILEANALYSIS_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, detResidImfileAnalysisObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long detResidImfileAnalysisDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        detResidImfileAnalysisRow *object = objects->data[i];
+        psMetadata *where = detResidImfileAnalysisMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, DETRESIDIMFILEANALYSIS_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from detResidImfileAnalysis");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
+static void detResidExpAnalysisRowFree(detResidExpAnalysisRow *object);
+
+detResidExpAnalysisRow *detResidExpAnalysisRowAlloc(psS32 det_id, psS32 iteration, const char *exp_id, const char *stats, const char *recipe, bool accept)
+{
+    detResidExpAnalysisRow *object;
+
+    object = psAlloc(sizeof(detResidExpAnalysisRow));
+    psMemSetDeallocator(object, (psFreeFunc)detResidExpAnalysisRowFree);
+
+    object->det_id = det_id;
+    object->iteration = iteration;
+    object->exp_id = psStringCopy(exp_id);
+    object->stats = psStringCopy(stats);
+    object->recipe = psStringCopy(recipe);
+    object->accept = accept;
+
+    return object;
+}
+
+static void detResidExpAnalysisRowFree(detResidExpAnalysisRow *object)
+{
+    psFree(object->exp_id);
+    psFree(object->stats);
+    psFree(object->recipe);
+}
+
+bool detResidExpAnalysisCreateTable(psDB *dbh)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAdd(md, PS_LIST_TAIL, DETRESIDEXPANALYSIS_INDEX_NAME, PS_DATA_S32, "AUTO_INCREMENT", 0.0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item %s", DETRESIDEXPANALYSIS_INDEX_NAME);
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, "Primary Key", 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, "Primary Key", 0)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, "Primary Key", "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "255")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "64")) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "accept", PS_DATA_BOOL, NULL, false)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item accept");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBCreateTable(dbh, DETRESIDEXPANALYSIS_TABLE_NAME, md);
+
+    psFree(md);
+
+    return status;
+}
+
+bool detResidExpAnalysisDropTable(psDB *dbh)
+{
+    return psDBDropTable(dbh, DETRESIDEXPANALYSIS_TABLE_NAME);
+}
+
+bool detResidExpAnalysisInsert(psDB * dbh, psS32 det_id, psS32 iteration, const char *exp_id, const char *stats, const char *recipe, bool accept)
+{
+    psMetadata      *md;
+    bool            status;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, iteration)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return false;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "accept", PS_DATA_BOOL, NULL, accept)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item accept");
+        psFree(md);
+        return false;
+    }
+
+    status = psDBInsertOneRow(dbh, DETRESIDEXPANALYSIS_TABLE_NAME, md);
+    psFree(md);
+
+    return status;
+}
+
+bool detResidExpAnalysisPop(psDB *dbh, psS32 *det_id, psS32 *iteration, char **exp_id, char **stats, char **recipe, bool *accept)
+{
+    psArray         *rowSet;
+    psMetadata      *row;
+    psMetadata      *popped;
+    long            deleted;
+    bool            status;
+    int             rowID;
+
+    rowSet = psDBSelectRows(dbh, DETRESIDEXPANALYSIS_TABLE_NAME, NULL, 1);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETRESIDEXPANALYSIS_INDEX_NAME);
+        psFree(rowSet);
+        return NULL;
+    }
+
+    row = psArrayGet(rowSet, 0);
+    psMemIncrRefCounter(row);
+    if (!row) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return NULL;
+    }
+    psFree(rowSet);
+
+    rowID = psMetadataLookupS32(&status, row, DETRESIDEXPANALYSIS_INDEX_NAME);
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item %s", DETRESIDEXPANALYSIS_INDEX_NAME);
+        psFree(row);
+        return NULL;
+    }
+
+    popped = psMetadataAlloc();
+    psMetadataAddS32(popped, PS_LIST_TAIL, DETRESIDEXPANALYSIS_INDEX_NAME, 0, NULL, rowID);
+
+    deleted = psDBDeleteRows(dbh, DETRESIDEXPANALYSIS_TABLE_NAME, popped, 0);
+    if (deleted != 1) {
+        psError(PS_ERR_UNKNOWN, false, "database failed to delete row");
+        psFree(popped);
+        psFree(row);
+        return NULL;
+    }
+
+    psFree(popped);
+
+    *det_id = psMetadataLookupS32(&status, row, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
+        psFree(row);
+        return false;
+    }
+    *iteration = psMetadataLookupS32(&status, row, "iteration");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item iteration");
+        psFree(row);
+        return false;
+    }
+    *exp_id = psMetadataLookupPtr(&status, row, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        psFree(row);
+        return false;
+    }
+    *stats = psMetadataLookupPtr(&status, row, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        psFree(row);
+        return false;
+    }
+    *recipe = psMetadataLookupPtr(&status, row, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        psFree(row);
+        return false;
+    }
+    *accept = psMetadataLookupBool(&status, row, "accept");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item accept");
+        psFree(row);
+        return false;
+    }
+
+    psFree(row);
+
+    return true;
+}
+
+bool detResidExpAnalysisInsertObject(psDB *dbh, detResidExpAnalysisRow *object)
+{
+    return detResidExpAnalysisInsert(dbh, object->det_id, object->iteration, object->exp_id, object->stats, object->recipe, object->accept);
+}
+
+detResidExpAnalysisRow *detResidExpAnalysisPopObject(psDB *dbh)
+{
+    psS32           det_id;
+    psS32           iteration;
+    char            exp_id[256];
+    char            stats[256];
+    char            recipe[256];
+    bool            accept;
+
+    if (!detResidExpAnalysisPop(dbh, &det_id, &iteration, (char **)&exp_id, (char **)&stats, (char **)&recipe, &accept)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to pop a database row");
+        return NULL;
+    }
+
+    return detResidExpAnalysisRowAlloc(det_id, iteration, exp_id, stats, recipe, accept);
+}
+
+bool detResidExpAnalysisInsertFits(psDB *dbh, const psFits *fits)
+{
+    psArray         *rowSet;
+
+    // move to (the first?) extension named  DETRESIDEXPANALYSIS_TABLE_NAME
+    if (!psFitsMoveExtName(fits, DETRESIDEXPANALYSIS_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, true, "failed to find FITS extension %s", DETRESIDEXPANALYSIS_TABLE_NAME);
+        return false;
+    }
+
+    // check HDU type
+    if (psFitsGetExtType(fits) != PS_FITS_TYPE_BINARY_TABLE)  {
+        psError(PS_ERR_UNKNOWN, true, "FITS HDU type is not PS_FITS_TYPE_BINARY_TABLE");
+        return false;
+    }
+
+    // read fits table
+    rowSet = psFitsReadTable(fits);
+    if (!rowSet) {
+        psError(PS_ERR_UNKNOWN, true, "FITS read error or FITS table is empty");
+        psFree(rowSet);
+        return false;
+    }
+
+    if (!psDBInsertRows(dbh, DETRESIDEXPANALYSIS_TABLE_NAME, rowSet)) {
+        psError(PS_ERR_UNKNOWN, false, "databse insert failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+bool detResidExpAnalysisPopFits(psDB *dbh, psFits *fits, unsigned long long limit)
+{
+    char            query[MAX_STRING_LENGTH];
+
+    if (!detResidExpAnalysisSelectRowsFits(dbh, fits, NULL, limit)) {
+        psError(PS_ERR_UNKNOWN, true, "database error or table is empty");
+        return false;
+    }
+
+    // remove limit rows from the end of the database
+    if (snprintf(query, MAX_STRING_LENGTH,
+                "DELETE FROM %s ORDER BY %s DESC LIMIT %lld",
+                DETRESIDEXPANALYSIS_TABLE_NAME, DETRESIDEXPANALYSIS_INDEX_NAME, limit) < 0) {
+        psError(PS_ERR_UNKNOWN, true, "query value attempted to exceed %s bytes", MAX_STRING_LENGTH);
+        return false;
+    }
+            
+    if (!p_psDBRunQuery(dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database query failed");
+        return false;
+    }
+
+    return true;
+}
+
+bool detResidExpAnalysisSelectRowsFits(psDB *dbh, psFits *fits, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETRESIDEXPANALYSIS_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return false;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)rowSet->data[i], 0, DETRESIDEXPANALYSIS_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETRESIDEXPANALYSIS_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // output to fits
+    if (!psFitsWriteTable(fits, NULL, rowSet, DETRESIDEXPANALYSIS_TABLE_NAME)) {
+        psError(PS_ERR_UNKNOWN, false, "FITS table write failed");
+        psFree(rowSet);
+        return false;
+    }
+
+    psFree(rowSet);
+
+    return true;
+}
+
+psMetadata *detResidExpAnalysisMetadataFromObject(const detResidExpAnalysisRow *object)
+{
+    psMetadata      *md;
+
+    md = psMetadataAlloc();
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, object->det_id)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item det_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, object->iteration)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item iteration");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, psStringCopy(object->exp_id))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, psStringCopy(object->stats))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item stats");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, psStringCopy(object->recipe))) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item recipe");
+        psFree(md);
+        return NULL;
+    }
+    if (!psMetadataAdd(md, PS_LIST_TAIL, "accept", PS_DATA_BOOL, NULL, object->accept)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to add item accept");
+        psFree(md);
+        return NULL;
+    }
+
+    return md;
+}
+
+detResidExpAnalysisRow *detResidExpAnalysisObjectFromMetadata(psMetadata *md)
+{
+    bool            status;
+    psS32           det_id;
+    psS32           iteration;
+    char            *exp_id;
+    char            *stats;
+    char            *recipe;
+    bool            accept;
+
+    det_id = psMetadataLookupS32(&status, md, "det_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item det_id");
+        return false;
+    }
+    iteration = psMetadataLookupS32(&status, md, "iteration");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item iteration");
+        return false;
+    }
+    exp_id = psMetadataLookupPtr(&status, md, "exp_id");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item exp_id");
+        return false;
+    }
+    stats = psMetadataLookupPtr(&status, md, "stats");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item stats");
+        return false;
+    }
+    recipe = psMetadataLookupPtr(&status, md, "recipe");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item recipe");
+        return false;
+    }
+    accept = psMetadataLookupBool(&status, md, "accept");
+    if (!status) {
+        psError(PS_ERR_UNKNOWN, true, "failed to lookup value for item accept");
+        return false;
+    }
+
+    return detResidExpAnalysisRowAlloc(det_id, iteration, exp_id, stats, recipe, accept);
+}
+psArray *detResidExpAnalysisSelectRowObjects(psDB *dbh, const psMetadata *where, unsigned long long limit)
+{
+    psArray         *rowSet;
+    psArray         *returnSet;
+    psU64           i;
+
+    rowSet = psDBSelectRows(dbh, DETRESIDEXPANALYSIS_TABLE_NAME, where, limit);
+    if (!rowSet) {
+        return NULL;
+    }
+
+    // strip index column
+    for (i = 0; i < rowSet->n; i++) {
+        if (!psMetadataRemove((psMetadata *)(rowSet->data[i]), 0, DETRESIDEXPANALYSIS_INDEX_NAME)) {
+            psError(PS_ERR_UNKNOWN, true, "failed to remove item %s", DETRESIDEXPANALYSIS_INDEX_NAME);
+            psFree(rowSet);
+            return false;
+        }
+    }
+
+    // convert psMetadata rows to row objects
+
+    returnSet = psArrayAlloc(rowSet->n);
+    returnSet->n = 0;
+
+    for (i = 0; i < rowSet->n; i++) {
+        psArrayAdd(returnSet, 0, detResidExpAnalysisObjectFromMetadata(rowSet->data[i]));
+    }
+
+    psFree(rowSet);
+
+    return returnSet;
+}
+long long detResidExpAnalysisDeleteRowObjects(psDB *dbh, const psArray *objects, unsigned long long limit)
+{
+    long long       deleted = 0;
+
+    for (long long i = 0; i < objects->n; i++) {
+        detResidExpAnalysisRow *object = objects->data[i];
+        psMetadata *where = detResidExpAnalysisMetadataFromObject(object);
+        long long count = psDBDeleteRows(dbh, DETRESIDEXPANALYSIS_TABLE_NAME, where, limit);
+        psFree(where)
+        if (count < 0) {
+            psError(PS_ERR_UNKNOWN, true, "failed to delete row from detResidExpAnalysis");
+            return count;
+        }
+
+        deleted += count;
+    }
+
+    return deleted;
+}
Index: /tags/start/ippdb/src/ippdb.h
===================================================================
--- /tags/start/ippdb/src/ippdb.h	(revision 12606)
+++ /tags/start/ippdb/src/ippdb.h	(revision 12606)
@@ -0,0 +1,5869 @@
+#ifndef IPPDB_H
+#define IPPDB_H 1
+
+#include <pslib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// @addtogroup ippdb
+/// @{
+
+/** Opens a new database connection
+ *
+ *  @return A new psDB object if the database connection is successful or NULL
+ *  on failure.
+ */
+
+psDB *ippdbInit(
+    const char      *host,              ///< Database server hostname
+    const char      *user,              ///< Database username
+    const char      *passwd,            ///< Database password
+    const char      *dbname             ///< Database table.namespace
+);
+
+/** Closes a database connection
+ */
+
+void ippdbCleanup(
+    psDB            *dbh                ///< Database handle
+);
+
+/** weatherRow data structure
+ *
+ * Structure for representing a single row of weather table data.
+ */
+
+typedef struct {
+    psF32           temp01;
+    psF32           humi01;
+    psF32           temp02;
+    psF32           humi02;
+    psF32           temp03;
+    psF32           humi03;
+    psF32           pressure;
+} weatherRow;
+
+/** Creates a new weatherRow object
+ *
+ *  @return A new weatherRow object or NULL on failure.
+ */
+
+weatherRow *weatherRowAlloc(
+    psF32           temp01,
+    psF32           humi01,
+    psF32           temp02,
+    psF32           humi02,
+    psF32           temp03,
+    psF32           humi03,
+    psF32           pressure
+);
+
+/** Creates a new weather table
+ *
+ * @return true on success
+ */
+
+bool weatherCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a weather table
+ *
+ * @return true on success
+ */
+
+bool weatherDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool weatherInsert(
+    psDB            *dbh,               ///< Database handle
+    psF32           temp01,
+    psF32           humi01,
+    psF32           temp02,
+    psF32           humi02,
+    psF32           temp03,
+    psF32           humi03,
+    psF32           pressure
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool weatherPop(
+    psDB            *dbh,               ///< Database handle
+    psF32           *temp01,
+    psF32           *humi01,
+    psF32           *temp02,
+    psF32           *humi02,
+    psF32           *temp03,
+    psF32           *humi03,
+    psF32           *pressure
+);
+
+/** Insert a single weatherRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool weatherInsertObject(
+    psDB            *dbh,               ///< Database handle
+    weatherRow      *object             ///< weatherRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new weatherRow on success or NULL on failure.
+ */
+
+weatherRow *weatherPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table weatherRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool weatherInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool weatherPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool weatherSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a weatherRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *weatherMetadataFromObject(
+    const weatherRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A weatherRow pointer or NULL on error
+ */
+
+weatherRow *weatherObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as weatherRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *weatherSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long weatherDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** skyp_transparencyRow data structure
+ *
+ * Structure for representing a single row of skyp_transparency table data.
+ */
+
+typedef struct {
+    char            *filter;
+    psF64           trans;
+    psS32           nstars;
+    psF64           ra;
+    psF64           decl;
+    psF32           exptime;
+    psF64           sky_bright;
+} skyp_transparencyRow;
+
+/** Creates a new skyp_transparencyRow object
+ *
+ *  @return A new skyp_transparencyRow object or NULL on failure.
+ */
+
+skyp_transparencyRow *skyp_transparencyRowAlloc(
+    const char      *filter,
+    psF64           trans,
+    psS32           nstars,
+    psF64           ra,
+    psF64           decl,
+    psF32           exptime,
+    psF64           sky_bright
+);
+
+/** Creates a new skyp_transparency table
+ *
+ * @return true on success
+ */
+
+bool skyp_transparencyCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a skyp_transparency table
+ *
+ * @return true on success
+ */
+
+bool skyp_transparencyDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool skyp_transparencyInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *filter,
+    psF64           trans,
+    psS32           nstars,
+    psF64           ra,
+    psF64           decl,
+    psF32           exptime,
+    psF64           sky_bright
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool skyp_transparencyPop(
+    psDB            *dbh,               ///< Database handle
+    char            **filter,
+    psF64           *trans,
+    psS32           *nstars,
+    psF64           *ra,
+    psF64           *decl,
+    psF32           *exptime,
+    psF64           *sky_bright
+);
+
+/** Insert a single skyp_transparencyRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool skyp_transparencyInsertObject(
+    psDB            *dbh,               ///< Database handle
+    skyp_transparencyRow *object             ///< skyp_transparencyRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new skyp_transparencyRow on success or NULL on failure.
+ */
+
+skyp_transparencyRow *skyp_transparencyPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table skyp_transparencyRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool skyp_transparencyInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool skyp_transparencyPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool skyp_transparencySelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a skyp_transparencyRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *skyp_transparencyMetadataFromObject(
+    const skyp_transparencyRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A skyp_transparencyRow pointer or NULL on error
+ */
+
+skyp_transparencyRow *skyp_transparencyObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as skyp_transparencyRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *skyp_transparencySelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long skyp_transparencyDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** skyp_absorptionRow data structure
+ *
+ * Structure for representing a single row of skyp_absorption table data.
+ */
+
+typedef struct {
+    char            *disperser_id;
+    psF32           atmcomp1;
+    psF32           atmcomp2;
+    psF32           atmcomp3;
+    psS32           nstars;
+    psF64           ra;
+    psF64           decl;
+    psF32           exptime;
+    psF64           sky_bright;
+} skyp_absorptionRow;
+
+/** Creates a new skyp_absorptionRow object
+ *
+ *  @return A new skyp_absorptionRow object or NULL on failure.
+ */
+
+skyp_absorptionRow *skyp_absorptionRowAlloc(
+    const char      *disperser_id,
+    psF32           atmcomp1,
+    psF32           atmcomp2,
+    psF32           atmcomp3,
+    psS32           nstars,
+    psF64           ra,
+    psF64           decl,
+    psF32           exptime,
+    psF64           sky_bright
+);
+
+/** Creates a new skyp_absorption table
+ *
+ * @return true on success
+ */
+
+bool skyp_absorptionCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a skyp_absorption table
+ *
+ * @return true on success
+ */
+
+bool skyp_absorptionDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool skyp_absorptionInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *disperser_id,
+    psF32           atmcomp1,
+    psF32           atmcomp2,
+    psF32           atmcomp3,
+    psS32           nstars,
+    psF64           ra,
+    psF64           decl,
+    psF32           exptime,
+    psF64           sky_bright
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool skyp_absorptionPop(
+    psDB            *dbh,               ///< Database handle
+    char            **disperser_id,
+    psF32           *atmcomp1,
+    psF32           *atmcomp2,
+    psF32           *atmcomp3,
+    psS32           *nstars,
+    psF64           *ra,
+    psF64           *decl,
+    psF32           *exptime,
+    psF64           *sky_bright
+);
+
+/** Insert a single skyp_absorptionRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool skyp_absorptionInsertObject(
+    psDB            *dbh,               ///< Database handle
+    skyp_absorptionRow *object             ///< skyp_absorptionRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new skyp_absorptionRow on success or NULL on failure.
+ */
+
+skyp_absorptionRow *skyp_absorptionPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table skyp_absorptionRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool skyp_absorptionInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool skyp_absorptionPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool skyp_absorptionSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a skyp_absorptionRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *skyp_absorptionMetadataFromObject(
+    const skyp_absorptionRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A skyp_absorptionRow pointer or NULL on error
+ */
+
+skyp_absorptionRow *skyp_absorptionObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as skyp_absorptionRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *skyp_absorptionSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long skyp_absorptionDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** skyp_emissionRow data structure
+ *
+ * Structure for representing a single row of skyp_emission table data.
+ */
+
+typedef struct {
+    char            *disperser_id;
+    psF32           atmcomp1;
+    psF32           atmcomp2;
+    psF32           atmcomp3;
+    psF32           continuum;
+    psF32           exptime;
+} skyp_emissionRow;
+
+/** Creates a new skyp_emissionRow object
+ *
+ *  @return A new skyp_emissionRow object or NULL on failure.
+ */
+
+skyp_emissionRow *skyp_emissionRowAlloc(
+    const char      *disperser_id,
+    psF32           atmcomp1,
+    psF32           atmcomp2,
+    psF32           atmcomp3,
+    psF32           continuum,
+    psF32           exptime
+);
+
+/** Creates a new skyp_emission table
+ *
+ * @return true on success
+ */
+
+bool skyp_emissionCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a skyp_emission table
+ *
+ * @return true on success
+ */
+
+bool skyp_emissionDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool skyp_emissionInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *disperser_id,
+    psF32           atmcomp1,
+    psF32           atmcomp2,
+    psF32           atmcomp3,
+    psF32           continuum,
+    psF32           exptime
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool skyp_emissionPop(
+    psDB            *dbh,               ///< Database handle
+    char            **disperser_id,
+    psF32           *atmcomp1,
+    psF32           *atmcomp2,
+    psF32           *atmcomp3,
+    psF32           *continuum,
+    psF32           *exptime
+);
+
+/** Insert a single skyp_emissionRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool skyp_emissionInsertObject(
+    psDB            *dbh,               ///< Database handle
+    skyp_emissionRow *object             ///< skyp_emissionRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new skyp_emissionRow on success or NULL on failure.
+ */
+
+skyp_emissionRow *skyp_emissionPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table skyp_emissionRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool skyp_emissionInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool skyp_emissionPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool skyp_emissionSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a skyp_emissionRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *skyp_emissionMetadataFromObject(
+    const skyp_emissionRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A skyp_emissionRow pointer or NULL on error
+ */
+
+skyp_emissionRow *skyp_emissionObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as skyp_emissionRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *skyp_emissionSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long skyp_emissionDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** dimmRow data structure
+ *
+ * Structure for representing a single row of dimm table data.
+ */
+
+typedef struct {
+    psF32           sigmax;
+    psF32           sigmay;
+    psF32           fwhm;
+    psF64           ra;
+    psF64           decl;
+    psF32           expttime;
+    char            *telescope_id;
+} dimmRow;
+
+/** Creates a new dimmRow object
+ *
+ *  @return A new dimmRow object or NULL on failure.
+ */
+
+dimmRow *dimmRowAlloc(
+    psF32           sigmax,
+    psF32           sigmay,
+    psF32           fwhm,
+    psF64           ra,
+    psF64           decl,
+    psF32           expttime,
+    const char      *telescope_id
+);
+
+/** Creates a new dimm table
+ *
+ * @return true on success
+ */
+
+bool dimmCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a dimm table
+ *
+ * @return true on success
+ */
+
+bool dimmDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool dimmInsert(
+    psDB            *dbh,               ///< Database handle
+    psF32           sigmax,
+    psF32           sigmay,
+    psF32           fwhm,
+    psF64           ra,
+    psF64           decl,
+    psF32           expttime,
+    const char      *telescope_id
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool dimmPop(
+    psDB            *dbh,               ///< Database handle
+    psF32           *sigmax,
+    psF32           *sigmay,
+    psF32           *fwhm,
+    psF64           *ra,
+    psF64           *decl,
+    psF32           *expttime,
+    char            **telescope_id
+);
+
+/** Insert a single dimmRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool dimmInsertObject(
+    psDB            *dbh,               ///< Database handle
+    dimmRow         *object             ///< dimmRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new dimmRow on success or NULL on failure.
+ */
+
+dimmRow *dimmPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table dimmRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool dimmInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool dimmPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool dimmSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a dimmRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *dimmMetadataFromObject(
+    const dimmRow   *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A dimmRow pointer or NULL on error
+ */
+
+dimmRow *dimmObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as dimmRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *dimmSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long dimmDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** skyp_irRow data structure
+ *
+ * Structure for representing a single row of skyp_ir table data.
+ */
+
+typedef struct {
+    psF64           sky_bright;
+    psF64           sky_var;
+    psF64           ra;
+    psF64           decl;
+    psF32           fov_x;
+    psF32           fov_y;
+} skyp_irRow;
+
+/** Creates a new skyp_irRow object
+ *
+ *  @return A new skyp_irRow object or NULL on failure.
+ */
+
+skyp_irRow *skyp_irRowAlloc(
+    psF64           sky_bright,
+    psF64           sky_var,
+    psF64           ra,
+    psF64           decl,
+    psF32           fov_x,
+    psF32           fov_y
+);
+
+/** Creates a new skyp_ir table
+ *
+ * @return true on success
+ */
+
+bool skyp_irCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a skyp_ir table
+ *
+ * @return true on success
+ */
+
+bool skyp_irDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool skyp_irInsert(
+    psDB            *dbh,               ///< Database handle
+    psF64           sky_bright,
+    psF64           sky_var,
+    psF64           ra,
+    psF64           decl,
+    psF32           fov_x,
+    psF32           fov_y
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool skyp_irPop(
+    psDB            *dbh,               ///< Database handle
+    psF64           *sky_bright,
+    psF64           *sky_var,
+    psF64           *ra,
+    psF64           *decl,
+    psF32           *fov_x,
+    psF32           *fov_y
+);
+
+/** Insert a single skyp_irRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool skyp_irInsertObject(
+    psDB            *dbh,               ///< Database handle
+    skyp_irRow      *object             ///< skyp_irRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new skyp_irRow on success or NULL on failure.
+ */
+
+skyp_irRow *skyp_irPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table skyp_irRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool skyp_irInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool skyp_irPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool skyp_irSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a skyp_irRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *skyp_irMetadataFromObject(
+    const skyp_irRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A skyp_irRow pointer or NULL on error
+ */
+
+skyp_irRow *skyp_irObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as skyp_irRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *skyp_irSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long skyp_irDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** domeRow data structure
+ *
+ * Structure for representing a single row of dome table data.
+ */
+
+typedef struct {
+    psF32           az;
+    bool            open;
+    bool            light;
+    bool            track;
+} domeRow;
+
+/** Creates a new domeRow object
+ *
+ *  @return A new domeRow object or NULL on failure.
+ */
+
+domeRow *domeRowAlloc(
+    psF32           az,
+    bool            open,
+    bool            light,
+    bool            track
+);
+
+/** Creates a new dome table
+ *
+ * @return true on success
+ */
+
+bool domeCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a dome table
+ *
+ * @return true on success
+ */
+
+bool domeDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool domeInsert(
+    psDB            *dbh,               ///< Database handle
+    psF32           az,
+    bool            open,
+    bool            light,
+    bool            track
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool domePop(
+    psDB            *dbh,               ///< Database handle
+    psF32           *az,
+    bool            *open,
+    bool            *light,
+    bool            *track
+);
+
+/** Insert a single domeRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool domeInsertObject(
+    psDB            *dbh,               ///< Database handle
+    domeRow         *object             ///< domeRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new domeRow on success or NULL on failure.
+ */
+
+domeRow *domePopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table domeRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool domeInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool domePopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool domeSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a domeRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *domeMetadataFromObject(
+    const domeRow   *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A domeRow pointer or NULL on error
+ */
+
+domeRow *domeObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as domeRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *domeSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long domeDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** telescopeRow data structure
+ *
+ * Structure for representing a single row of telescope table data.
+ */
+
+typedef struct {
+    char            *guide;
+    psF32           alt;
+    psF32           az;
+    psF64           ra;
+    psF64           decl;
+} telescopeRow;
+
+/** Creates a new telescopeRow object
+ *
+ *  @return A new telescopeRow object or NULL on failure.
+ */
+
+telescopeRow *telescopeRowAlloc(
+    const char      *guide,
+    psF32           alt,
+    psF32           az,
+    psF64           ra,
+    psF64           decl
+);
+
+/** Creates a new telescope table
+ *
+ * @return true on success
+ */
+
+bool telescopeCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a telescope table
+ *
+ * @return true on success
+ */
+
+bool telescopeDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool telescopeInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *guide,
+    psF32           alt,
+    psF32           az,
+    psF64           ra,
+    psF64           decl
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool telescopePop(
+    psDB            *dbh,               ///< Database handle
+    char            **guide,
+    psF32           *alt,
+    psF32           *az,
+    psF64           *ra,
+    psF64           *decl
+);
+
+/** Insert a single telescopeRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool telescopeInsertObject(
+    psDB            *dbh,               ///< Database handle
+    telescopeRow    *object             ///< telescopeRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new telescopeRow on success or NULL on failure.
+ */
+
+telescopeRow *telescopePopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table telescopeRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool telescopeInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool telescopePopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool telescopeSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a telescopeRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *telescopeMetadataFromObject(
+    const telescopeRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A telescopeRow pointer or NULL on error
+ */
+
+telescopeRow *telescopeObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as telescopeRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *telescopeSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long telescopeDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** summitExpRow data structure
+ *
+ * Structure for representing a single row of summitExp table data.
+ */
+
+typedef struct {
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *exp_type;
+    char            *uri;
+} summitExpRow;
+
+/** Creates a new summitExpRow object
+ *
+ *  @return A new summitExpRow object or NULL on failure.
+ */
+
+summitExpRow *summitExpRowAlloc(
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *exp_type,
+    const char      *uri
+);
+
+/** Creates a new summitExp table
+ *
+ * @return true on success
+ */
+
+bool summitExpCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a summitExp table
+ *
+ * @return true on success
+ */
+
+bool summitExpDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool summitExpInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *exp_type,
+    const char      *uri
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool summitExpPop(
+    psDB            *dbh,               ///< Database handle
+    char            **exp_id,
+    char            **camera,
+    char            **telescope,
+    char            **exp_type,
+    char            **uri
+);
+
+/** Insert a single summitExpRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool summitExpInsertObject(
+    psDB            *dbh,               ///< Database handle
+    summitExpRow    *object             ///< summitExpRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new summitExpRow on success or NULL on failure.
+ */
+
+summitExpRow *summitExpPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table summitExpRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool summitExpInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool summitExpPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool summitExpSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a summitExpRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *summitExpMetadataFromObject(
+    const summitExpRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A summitExpRow pointer or NULL on error
+ */
+
+summitExpRow *summitExpObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as summitExpRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *summitExpSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long summitExpDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** pzPendingExpRow data structure
+ *
+ * Structure for representing a single row of pzPendingExp table data.
+ */
+
+typedef struct {
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *exp_type;
+    psS32           imfiles;
+} pzPendingExpRow;
+
+/** Creates a new pzPendingExpRow object
+ *
+ *  @return A new pzPendingExpRow object or NULL on failure.
+ */
+
+pzPendingExpRow *pzPendingExpRowAlloc(
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *exp_type,
+    psS32           imfiles
+);
+
+/** Creates a new pzPendingExp table
+ *
+ * @return true on success
+ */
+
+bool pzPendingExpCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a pzPendingExp table
+ *
+ * @return true on success
+ */
+
+bool pzPendingExpDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool pzPendingExpInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *exp_type,
+    psS32           imfiles
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool pzPendingExpPop(
+    psDB            *dbh,               ///< Database handle
+    char            **exp_id,
+    char            **camera,
+    char            **telescope,
+    char            **exp_type,
+    psS32           *imfiles
+);
+
+/** Insert a single pzPendingExpRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool pzPendingExpInsertObject(
+    psDB            *dbh,               ///< Database handle
+    pzPendingExpRow *object             ///< pzPendingExpRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new pzPendingExpRow on success or NULL on failure.
+ */
+
+pzPendingExpRow *pzPendingExpPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table pzPendingExpRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool pzPendingExpInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool pzPendingExpPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool pzPendingExpSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a pzPendingExpRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *pzPendingExpMetadataFromObject(
+    const pzPendingExpRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A pzPendingExpRow pointer or NULL on error
+ */
+
+pzPendingExpRow *pzPendingExpObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as pzPendingExpRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *pzPendingExpSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long pzPendingExpDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** pzPendingImfileRow data structure
+ *
+ * Structure for representing a single row of pzPendingImfile table data.
+ */
+
+typedef struct {
+    char            *exp_id;
+    psS32           bytes;
+    char            *md5sum;
+    char            *class;
+    char            *class_id;
+    char            *uri;
+} pzPendingImfileRow;
+
+/** Creates a new pzPendingImfileRow object
+ *
+ *  @return A new pzPendingImfileRow object or NULL on failure.
+ */
+
+pzPendingImfileRow *pzPendingImfileRowAlloc(
+    const char      *exp_id,
+    psS32           bytes,
+    const char      *md5sum,
+    const char      *class,
+    const char      *class_id,
+    const char      *uri
+);
+
+/** Creates a new pzPendingImfile table
+ *
+ * @return true on success
+ */
+
+bool pzPendingImfileCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a pzPendingImfile table
+ *
+ * @return true on success
+ */
+
+bool pzPendingImfileDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool pzPendingImfileInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *exp_id,
+    psS32           bytes,
+    const char      *md5sum,
+    const char      *class,
+    const char      *class_id,
+    const char      *uri
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool pzPendingImfilePop(
+    psDB            *dbh,               ///< Database handle
+    char            **exp_id,
+    psS32           *bytes,
+    char            **md5sum,
+    char            **class,
+    char            **class_id,
+    char            **uri
+);
+
+/** Insert a single pzPendingImfileRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool pzPendingImfileInsertObject(
+    psDB            *dbh,               ///< Database handle
+    pzPendingImfileRow *object             ///< pzPendingImfileRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new pzPendingImfileRow on success or NULL on failure.
+ */
+
+pzPendingImfileRow *pzPendingImfilePopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table pzPendingImfileRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool pzPendingImfileInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool pzPendingImfilePopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool pzPendingImfileSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a pzPendingImfileRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *pzPendingImfileMetadataFromObject(
+    const pzPendingImfileRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A pzPendingImfileRow pointer or NULL on error
+ */
+
+pzPendingImfileRow *pzPendingImfileObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as pzPendingImfileRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *pzPendingImfileSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long pzPendingImfileDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** newExpRow data structure
+ *
+ * Structure for representing a single row of newExp table data.
+ */
+
+typedef struct {
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *exp_type;
+    psS32           imfiles;
+} newExpRow;
+
+/** Creates a new newExpRow object
+ *
+ *  @return A new newExpRow object or NULL on failure.
+ */
+
+newExpRow *newExpRowAlloc(
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *exp_type,
+    psS32           imfiles
+);
+
+/** Creates a new newExp table
+ *
+ * @return true on success
+ */
+
+bool newExpCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a newExp table
+ *
+ * @return true on success
+ */
+
+bool newExpDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool newExpInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *exp_type,
+    psS32           imfiles
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool newExpPop(
+    psDB            *dbh,               ///< Database handle
+    char            **exp_id,
+    char            **camera,
+    char            **telescope,
+    char            **exp_type,
+    psS32           *imfiles
+);
+
+/** Insert a single newExpRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool newExpInsertObject(
+    psDB            *dbh,               ///< Database handle
+    newExpRow       *object             ///< newExpRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new newExpRow on success or NULL on failure.
+ */
+
+newExpRow *newExpPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table newExpRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool newExpInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool newExpPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool newExpSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a newExpRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *newExpMetadataFromObject(
+    const newExpRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A newExpRow pointer or NULL on error
+ */
+
+newExpRow *newExpObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as newExpRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *newExpSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long newExpDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** newImfileRow data structure
+ *
+ * Structure for representing a single row of newImfile table data.
+ */
+
+typedef struct {
+    char            *exp_id;
+    char            *class;
+    char            *class_id;
+    char            *uri;
+} newImfileRow;
+
+/** Creates a new newImfileRow object
+ *
+ *  @return A new newImfileRow object or NULL on failure.
+ */
+
+newImfileRow *newImfileRowAlloc(
+    const char      *exp_id,
+    const char      *class,
+    const char      *class_id,
+    const char      *uri
+);
+
+/** Creates a new newImfile table
+ *
+ * @return true on success
+ */
+
+bool newImfileCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a newImfile table
+ *
+ * @return true on success
+ */
+
+bool newImfileDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool newImfileInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *exp_id,
+    const char      *class,
+    const char      *class_id,
+    const char      *uri
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool newImfilePop(
+    psDB            *dbh,               ///< Database handle
+    char            **exp_id,
+    char            **class,
+    char            **class_id,
+    char            **uri
+);
+
+/** Insert a single newImfileRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool newImfileInsertObject(
+    psDB            *dbh,               ///< Database handle
+    newImfileRow    *object             ///< newImfileRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new newImfileRow on success or NULL on failure.
+ */
+
+newImfileRow *newImfilePopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table newImfileRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool newImfileInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool newImfilePopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool newImfileSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a newImfileRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *newImfileMetadataFromObject(
+    const newImfileRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A newImfileRow pointer or NULL on error
+ */
+
+newImfileRow *newImfileObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as newImfileRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *newImfileSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long newImfileDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** rawDetrendExpRow data structure
+ *
+ * Structure for representing a single row of rawDetrendExp table data.
+ */
+
+typedef struct {
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *exp_type;
+    psS32           imfiles;
+    char            *filter;
+    char            *stats;
+} rawDetrendExpRow;
+
+/** Creates a new rawDetrendExpRow object
+ *
+ *  @return A new rawDetrendExpRow object or NULL on failure.
+ */
+
+rawDetrendExpRow *rawDetrendExpRowAlloc(
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *exp_type,
+    psS32           imfiles,
+    const char      *filter,
+    const char      *stats
+);
+
+/** Creates a new rawDetrendExp table
+ *
+ * @return true on success
+ */
+
+bool rawDetrendExpCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a rawDetrendExp table
+ *
+ * @return true on success
+ */
+
+bool rawDetrendExpDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool rawDetrendExpInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *exp_type,
+    psS32           imfiles,
+    const char      *filter,
+    const char      *stats
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool rawDetrendExpPop(
+    psDB            *dbh,               ///< Database handle
+    char            **exp_id,
+    char            **camera,
+    char            **telescope,
+    char            **exp_type,
+    psS32           *imfiles,
+    char            **filter,
+    char            **stats
+);
+
+/** Insert a single rawDetrendExpRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool rawDetrendExpInsertObject(
+    psDB            *dbh,               ///< Database handle
+    rawDetrendExpRow *object             ///< rawDetrendExpRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new rawDetrendExpRow on success or NULL on failure.
+ */
+
+rawDetrendExpRow *rawDetrendExpPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table rawDetrendExpRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool rawDetrendExpInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool rawDetrendExpPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool rawDetrendExpSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a rawDetrendExpRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *rawDetrendExpMetadataFromObject(
+    const rawDetrendExpRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A rawDetrendExpRow pointer or NULL on error
+ */
+
+rawDetrendExpRow *rawDetrendExpObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as rawDetrendExpRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *rawDetrendExpSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long rawDetrendExpDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** rawScienceExpRow data structure
+ *
+ * Structure for representing a single row of rawScienceExp table data.
+ */
+
+typedef struct {
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *exp_type;
+    psS32           imfiles;
+    char            *filter;
+    char            *stats;
+} rawScienceExpRow;
+
+/** Creates a new rawScienceExpRow object
+ *
+ *  @return A new rawScienceExpRow object or NULL on failure.
+ */
+
+rawScienceExpRow *rawScienceExpRowAlloc(
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *exp_type,
+    psS32           imfiles,
+    const char      *filter,
+    const char      *stats
+);
+
+/** Creates a new rawScienceExp table
+ *
+ * @return true on success
+ */
+
+bool rawScienceExpCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a rawScienceExp table
+ *
+ * @return true on success
+ */
+
+bool rawScienceExpDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool rawScienceExpInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *exp_type,
+    psS32           imfiles,
+    const char      *filter,
+    const char      *stats
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool rawScienceExpPop(
+    psDB            *dbh,               ///< Database handle
+    char            **exp_id,
+    char            **camera,
+    char            **telescope,
+    char            **exp_type,
+    psS32           *imfiles,
+    char            **filter,
+    char            **stats
+);
+
+/** Insert a single rawScienceExpRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool rawScienceExpInsertObject(
+    psDB            *dbh,               ///< Database handle
+    rawScienceExpRow *object             ///< rawScienceExpRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new rawScienceExpRow on success or NULL on failure.
+ */
+
+rawScienceExpRow *rawScienceExpPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table rawScienceExpRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool rawScienceExpInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool rawScienceExpPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool rawScienceExpSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a rawScienceExpRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *rawScienceExpMetadataFromObject(
+    const rawScienceExpRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A rawScienceExpRow pointer or NULL on error
+ */
+
+rawScienceExpRow *rawScienceExpObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as rawScienceExpRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *rawScienceExpSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long rawScienceExpDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** rawImfileRow data structure
+ *
+ * Structure for representing a single row of rawImfile table data.
+ */
+
+typedef struct {
+    char            *exp_id;
+    char            *class_id;
+    char            *uri;
+    char            *stats;
+} rawImfileRow;
+
+/** Creates a new rawImfileRow object
+ *
+ *  @return A new rawImfileRow object or NULL on failure.
+ */
+
+rawImfileRow *rawImfileRowAlloc(
+    const char      *exp_id,
+    const char      *class_id,
+    const char      *uri,
+    const char      *stats
+);
+
+/** Creates a new rawImfile table
+ *
+ * @return true on success
+ */
+
+bool rawImfileCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a rawImfile table
+ *
+ * @return true on success
+ */
+
+bool rawImfileDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool rawImfileInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *exp_id,
+    const char      *class_id,
+    const char      *uri,
+    const char      *stats
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool rawImfilePop(
+    psDB            *dbh,               ///< Database handle
+    char            **exp_id,
+    char            **class_id,
+    char            **uri,
+    char            **stats
+);
+
+/** Insert a single rawImfileRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool rawImfileInsertObject(
+    psDB            *dbh,               ///< Database handle
+    rawImfileRow    *object             ///< rawImfileRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new rawImfileRow on success or NULL on failure.
+ */
+
+rawImfileRow *rawImfilePopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table rawImfileRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool rawImfileInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool rawImfilePopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool rawImfileSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a rawImfileRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *rawImfileMetadataFromObject(
+    const rawImfileRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A rawImfileRow pointer or NULL on error
+ */
+
+rawImfileRow *rawImfileObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as rawImfileRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *rawImfileSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long rawImfileDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** p1PendingExpRow data structure
+ *
+ * Structure for representing a single row of p1PendingExp table data.
+ */
+
+typedef struct {
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *exp_type;
+    psS32           imfiles;
+    char            *filter;
+    char            *stats;
+    char            *recipe;
+    psS32           p1_version;
+} p1PendingExpRow;
+
+/** Creates a new p1PendingExpRow object
+ *
+ *  @return A new p1PendingExpRow object or NULL on failure.
+ */
+
+p1PendingExpRow *p1PendingExpRowAlloc(
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *exp_type,
+    psS32           imfiles,
+    const char      *filter,
+    const char      *stats,
+    const char      *recipe,
+    psS32           p1_version
+);
+
+/** Creates a new p1PendingExp table
+ *
+ * @return true on success
+ */
+
+bool p1PendingExpCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a p1PendingExp table
+ *
+ * @return true on success
+ */
+
+bool p1PendingExpDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool p1PendingExpInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *exp_type,
+    psS32           imfiles,
+    const char      *filter,
+    const char      *stats,
+    const char      *recipe,
+    psS32           p1_version
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool p1PendingExpPop(
+    psDB            *dbh,               ///< Database handle
+    char            **exp_id,
+    char            **camera,
+    char            **telescope,
+    char            **exp_type,
+    psS32           *imfiles,
+    char            **filter,
+    char            **stats,
+    char            **recipe,
+    psS32           *p1_version
+);
+
+/** Insert a single p1PendingExpRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool p1PendingExpInsertObject(
+    psDB            *dbh,               ///< Database handle
+    p1PendingExpRow *object             ///< p1PendingExpRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new p1PendingExpRow on success or NULL on failure.
+ */
+
+p1PendingExpRow *p1PendingExpPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table p1PendingExpRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool p1PendingExpInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool p1PendingExpPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool p1PendingExpSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a p1PendingExpRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *p1PendingExpMetadataFromObject(
+    const p1PendingExpRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A p1PendingExpRow pointer or NULL on error
+ */
+
+p1PendingExpRow *p1PendingExpObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as p1PendingExpRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *p1PendingExpSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long p1PendingExpDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** p2PendingExpRow data structure
+ *
+ * Structure for representing a single row of p2PendingExp table data.
+ */
+
+typedef struct {
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *exp_type;
+    psS32           imfiles;
+    char            *filter;
+    char            *stats;
+    char            *recipe;
+    psS32           p1_version;
+    psS32           p2_version;
+} p2PendingExpRow;
+
+/** Creates a new p2PendingExpRow object
+ *
+ *  @return A new p2PendingExpRow object or NULL on failure.
+ */
+
+p2PendingExpRow *p2PendingExpRowAlloc(
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *exp_type,
+    psS32           imfiles,
+    const char      *filter,
+    const char      *stats,
+    const char      *recipe,
+    psS32           p1_version,
+    psS32           p2_version
+);
+
+/** Creates a new p2PendingExp table
+ *
+ * @return true on success
+ */
+
+bool p2PendingExpCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a p2PendingExp table
+ *
+ * @return true on success
+ */
+
+bool p2PendingExpDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool p2PendingExpInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *exp_type,
+    psS32           imfiles,
+    const char      *filter,
+    const char      *stats,
+    const char      *recipe,
+    psS32           p1_version,
+    psS32           p2_version
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool p2PendingExpPop(
+    psDB            *dbh,               ///< Database handle
+    char            **exp_id,
+    char            **camera,
+    char            **telescope,
+    char            **exp_type,
+    psS32           *imfiles,
+    char            **filter,
+    char            **stats,
+    char            **recipe,
+    psS32           *p1_version,
+    psS32           *p2_version
+);
+
+/** Insert a single p2PendingExpRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool p2PendingExpInsertObject(
+    psDB            *dbh,               ///< Database handle
+    p2PendingExpRow *object             ///< p2PendingExpRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new p2PendingExpRow on success or NULL on failure.
+ */
+
+p2PendingExpRow *p2PendingExpPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table p2PendingExpRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool p2PendingExpInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool p2PendingExpPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool p2PendingExpSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a p2PendingExpRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *p2PendingExpMetadataFromObject(
+    const p2PendingExpRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A p2PendingExpRow pointer or NULL on error
+ */
+
+p2PendingExpRow *p2PendingExpObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as p2PendingExpRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *p2PendingExpSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long p2PendingExpDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** p2PendingImfileRow data structure
+ *
+ * Structure for representing a single row of p2PendingImfile table data.
+ */
+
+typedef struct {
+    char            *exp_id;
+    char            *class_id;
+    char            *uri;
+    char            *stats;
+    char            *recipe;
+    psS32           p1_version;
+    psS32           p2_version;
+} p2PendingImfileRow;
+
+/** Creates a new p2PendingImfileRow object
+ *
+ *  @return A new p2PendingImfileRow object or NULL on failure.
+ */
+
+p2PendingImfileRow *p2PendingImfileRowAlloc(
+    const char      *exp_id,
+    const char      *class_id,
+    const char      *uri,
+    const char      *stats,
+    const char      *recipe,
+    psS32           p1_version,
+    psS32           p2_version
+);
+
+/** Creates a new p2PendingImfile table
+ *
+ * @return true on success
+ */
+
+bool p2PendingImfileCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a p2PendingImfile table
+ *
+ * @return true on success
+ */
+
+bool p2PendingImfileDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool p2PendingImfileInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *exp_id,
+    const char      *class_id,
+    const char      *uri,
+    const char      *stats,
+    const char      *recipe,
+    psS32           p1_version,
+    psS32           p2_version
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool p2PendingImfilePop(
+    psDB            *dbh,               ///< Database handle
+    char            **exp_id,
+    char            **class_id,
+    char            **uri,
+    char            **stats,
+    char            **recipe,
+    psS32           *p1_version,
+    psS32           *p2_version
+);
+
+/** Insert a single p2PendingImfileRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool p2PendingImfileInsertObject(
+    psDB            *dbh,               ///< Database handle
+    p2PendingImfileRow *object             ///< p2PendingImfileRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new p2PendingImfileRow on success or NULL on failure.
+ */
+
+p2PendingImfileRow *p2PendingImfilePopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table p2PendingImfileRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool p2PendingImfileInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool p2PendingImfilePopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool p2PendingImfileSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a p2PendingImfileRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *p2PendingImfileMetadataFromObject(
+    const p2PendingImfileRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A p2PendingImfileRow pointer or NULL on error
+ */
+
+p2PendingImfileRow *p2PendingImfileObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as p2PendingImfileRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *p2PendingImfileSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long p2PendingImfileDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** p2DoneExpRow data structure
+ *
+ * Structure for representing a single row of p2DoneExp table data.
+ */
+
+typedef struct {
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *exp_type;
+    psS32           imfiles;
+    char            *filter;
+    char            *stats;
+    char            *recipe;
+    psS32           p1_version;
+    psS32           p2_version;
+} p2DoneExpRow;
+
+/** Creates a new p2DoneExpRow object
+ *
+ *  @return A new p2DoneExpRow object or NULL on failure.
+ */
+
+p2DoneExpRow *p2DoneExpRowAlloc(
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *exp_type,
+    psS32           imfiles,
+    const char      *filter,
+    const char      *stats,
+    const char      *recipe,
+    psS32           p1_version,
+    psS32           p2_version
+);
+
+/** Creates a new p2DoneExp table
+ *
+ * @return true on success
+ */
+
+bool p2DoneExpCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a p2DoneExp table
+ *
+ * @return true on success
+ */
+
+bool p2DoneExpDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool p2DoneExpInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *exp_type,
+    psS32           imfiles,
+    const char      *filter,
+    const char      *stats,
+    const char      *recipe,
+    psS32           p1_version,
+    psS32           p2_version
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool p2DoneExpPop(
+    psDB            *dbh,               ///< Database handle
+    char            **exp_id,
+    char            **camera,
+    char            **telescope,
+    char            **exp_type,
+    psS32           *imfiles,
+    char            **filter,
+    char            **stats,
+    char            **recipe,
+    psS32           *p1_version,
+    psS32           *p2_version
+);
+
+/** Insert a single p2DoneExpRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool p2DoneExpInsertObject(
+    psDB            *dbh,               ///< Database handle
+    p2DoneExpRow    *object             ///< p2DoneExpRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new p2DoneExpRow on success or NULL on failure.
+ */
+
+p2DoneExpRow *p2DoneExpPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table p2DoneExpRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool p2DoneExpInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool p2DoneExpPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool p2DoneExpSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a p2DoneExpRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *p2DoneExpMetadataFromObject(
+    const p2DoneExpRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A p2DoneExpRow pointer or NULL on error
+ */
+
+p2DoneExpRow *p2DoneExpObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as p2DoneExpRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *p2DoneExpSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long p2DoneExpDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** p2DoneImfileRow data structure
+ *
+ * Structure for representing a single row of p2DoneImfile table data.
+ */
+
+typedef struct {
+    char            *exp_id;
+    char            *class_id;
+    char            *uri;
+    char            *stats;
+    char            *recipe;
+    psS32           p1_version;
+    psS32           p2_version;
+} p2DoneImfileRow;
+
+/** Creates a new p2DoneImfileRow object
+ *
+ *  @return A new p2DoneImfileRow object or NULL on failure.
+ */
+
+p2DoneImfileRow *p2DoneImfileRowAlloc(
+    const char      *exp_id,
+    const char      *class_id,
+    const char      *uri,
+    const char      *stats,
+    const char      *recipe,
+    psS32           p1_version,
+    psS32           p2_version
+);
+
+/** Creates a new p2DoneImfile table
+ *
+ * @return true on success
+ */
+
+bool p2DoneImfileCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a p2DoneImfile table
+ *
+ * @return true on success
+ */
+
+bool p2DoneImfileDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool p2DoneImfileInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *exp_id,
+    const char      *class_id,
+    const char      *uri,
+    const char      *stats,
+    const char      *recipe,
+    psS32           p1_version,
+    psS32           p2_version
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool p2DoneImfilePop(
+    psDB            *dbh,               ///< Database handle
+    char            **exp_id,
+    char            **class_id,
+    char            **uri,
+    char            **stats,
+    char            **recipe,
+    psS32           *p1_version,
+    psS32           *p2_version
+);
+
+/** Insert a single p2DoneImfileRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool p2DoneImfileInsertObject(
+    psDB            *dbh,               ///< Database handle
+    p2DoneImfileRow *object             ///< p2DoneImfileRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new p2DoneImfileRow on success or NULL on failure.
+ */
+
+p2DoneImfileRow *p2DoneImfilePopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table p2DoneImfileRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool p2DoneImfileInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool p2DoneImfilePopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool p2DoneImfileSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a p2DoneImfileRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *p2DoneImfileMetadataFromObject(
+    const p2DoneImfileRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A p2DoneImfileRow pointer or NULL on error
+ */
+
+p2DoneImfileRow *p2DoneImfileObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as p2DoneImfileRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *p2DoneImfileSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long p2DoneImfileDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** p3PendingExpRow data structure
+ *
+ * Structure for representing a single row of p3PendingExp table data.
+ */
+
+typedef struct {
+    char            *exp_id;
+    char            *camera;
+    char            *exp_type;
+    psS32           imfiles;
+    char            *filter;
+    char            *stats;
+    char            *recipe;
+    psS32           p2_version;
+    psS32           p3_version;
+} p3PendingExpRow;
+
+/** Creates a new p3PendingExpRow object
+ *
+ *  @return A new p3PendingExpRow object or NULL on failure.
+ */
+
+p3PendingExpRow *p3PendingExpRowAlloc(
+    const char      *exp_id,
+    const char      *camera,
+    const char      *exp_type,
+    psS32           imfiles,
+    const char      *filter,
+    const char      *stats,
+    const char      *recipe,
+    psS32           p2_version,
+    psS32           p3_version
+);
+
+/** Creates a new p3PendingExp table
+ *
+ * @return true on success
+ */
+
+bool p3PendingExpCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a p3PendingExp table
+ *
+ * @return true on success
+ */
+
+bool p3PendingExpDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool p3PendingExpInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *exp_id,
+    const char      *camera,
+    const char      *exp_type,
+    psS32           imfiles,
+    const char      *filter,
+    const char      *stats,
+    const char      *recipe,
+    psS32           p2_version,
+    psS32           p3_version
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool p3PendingExpPop(
+    psDB            *dbh,               ///< Database handle
+    char            **exp_id,
+    char            **camera,
+    char            **exp_type,
+    psS32           *imfiles,
+    char            **filter,
+    char            **stats,
+    char            **recipe,
+    psS32           *p2_version,
+    psS32           *p3_version
+);
+
+/** Insert a single p3PendingExpRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool p3PendingExpInsertObject(
+    psDB            *dbh,               ///< Database handle
+    p3PendingExpRow *object             ///< p3PendingExpRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new p3PendingExpRow on success or NULL on failure.
+ */
+
+p3PendingExpRow *p3PendingExpPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table p3PendingExpRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool p3PendingExpInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool p3PendingExpPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool p3PendingExpSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a p3PendingExpRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *p3PendingExpMetadataFromObject(
+    const p3PendingExpRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A p3PendingExpRow pointer or NULL on error
+ */
+
+p3PendingExpRow *p3PendingExpObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as p3PendingExpRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *p3PendingExpSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long p3PendingExpDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** detRunRow data structure
+ *
+ * Structure for representing a single row of detRun table data.
+ */
+
+typedef struct {
+    char            *det_type;
+} detRunRow;
+
+/** Creates a new detRunRow object
+ *
+ *  @return A new detRunRow object or NULL on failure.
+ */
+
+detRunRow *detRunRowAlloc(
+    const char      *det_type
+);
+
+/** Creates a new detRun table
+ *
+ * @return true on success
+ */
+
+bool detRunCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a detRun table
+ *
+ * @return true on success
+ */
+
+bool detRunDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool detRunInsert(
+    psDB            *dbh,               ///< Database handle
+    const char      *det_type
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool detRunPop(
+    psDB            *dbh,               ///< Database handle
+    char            **det_type
+);
+
+/** Insert a single detRunRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool detRunInsertObject(
+    psDB            *dbh,               ///< Database handle
+    detRunRow       *object             ///< detRunRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new detRunRow on success or NULL on failure.
+ */
+
+detRunRow *detRunPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table detRunRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool detRunInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool detRunPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool detRunSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a detRunRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *detRunMetadataFromObject(
+    const detRunRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A detRunRow pointer or NULL on error
+ */
+
+detRunRow *detRunObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as detRunRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *detRunSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long detRunDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** detInputExpRow data structure
+ *
+ * Structure for representing a single row of detInputExp table data.
+ */
+
+typedef struct {
+    psS32           det_id;
+    psS32           iteration;
+    char            *exp_id;
+    char            *camera;
+    char            *telescope;
+    char            *exp_type;
+    psS32           imfiles;
+    char            *filter;
+    char            *stats;
+} detInputExpRow;
+
+/** Creates a new detInputExpRow object
+ *
+ *  @return A new detInputExpRow object or NULL on failure.
+ */
+
+detInputExpRow *detInputExpRowAlloc(
+    psS32           det_id,
+    psS32           iteration,
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *exp_type,
+    psS32           imfiles,
+    const char      *filter,
+    const char      *stats
+);
+
+/** Creates a new detInputExp table
+ *
+ * @return true on success
+ */
+
+bool detInputExpCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a detInputExp table
+ *
+ * @return true on success
+ */
+
+bool detInputExpDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool detInputExpInsert(
+    psDB            *dbh,               ///< Database handle
+    psS32           det_id,
+    psS32           iteration,
+    const char      *exp_id,
+    const char      *camera,
+    const char      *telescope,
+    const char      *exp_type,
+    psS32           imfiles,
+    const char      *filter,
+    const char      *stats
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool detInputExpPop(
+    psDB            *dbh,               ///< Database handle
+    psS32           *det_id,
+    psS32           *iteration,
+    char            **exp_id,
+    char            **camera,
+    char            **telescope,
+    char            **exp_type,
+    psS32           *imfiles,
+    char            **filter,
+    char            **stats
+);
+
+/** Insert a single detInputExpRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool detInputExpInsertObject(
+    psDB            *dbh,               ///< Database handle
+    detInputExpRow  *object             ///< detInputExpRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new detInputExpRow on success or NULL on failure.
+ */
+
+detInputExpRow *detInputExpPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table detInputExpRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool detInputExpInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool detInputExpPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool detInputExpSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a detInputExpRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *detInputExpMetadataFromObject(
+    const detInputExpRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A detInputExpRow pointer or NULL on error
+ */
+
+detInputExpRow *detInputExpObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as detInputExpRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *detInputExpSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long detInputExpDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** detProcessedImfileRow data structure
+ *
+ * Structure for representing a single row of detProcessedImfile table data.
+ */
+
+typedef struct {
+    psS32           det_id;
+    char            *exp_id;
+    char            *class_id;
+    char            *uri;
+    char            *stats;
+    char            *recipe;
+} detProcessedImfileRow;
+
+/** Creates a new detProcessedImfileRow object
+ *
+ *  @return A new detProcessedImfileRow object or NULL on failure.
+ */
+
+detProcessedImfileRow *detProcessedImfileRowAlloc(
+    psS32           det_id,
+    const char      *exp_id,
+    const char      *class_id,
+    const char      *uri,
+    const char      *stats,
+    const char      *recipe
+);
+
+/** Creates a new detProcessedImfile table
+ *
+ * @return true on success
+ */
+
+bool detProcessedImfileCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a detProcessedImfile table
+ *
+ * @return true on success
+ */
+
+bool detProcessedImfileDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool detProcessedImfileInsert(
+    psDB            *dbh,               ///< Database handle
+    psS32           det_id,
+    const char      *exp_id,
+    const char      *class_id,
+    const char      *uri,
+    const char      *stats,
+    const char      *recipe
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool detProcessedImfilePop(
+    psDB            *dbh,               ///< Database handle
+    psS32           *det_id,
+    char            **exp_id,
+    char            **class_id,
+    char            **uri,
+    char            **stats,
+    char            **recipe
+);
+
+/** Insert a single detProcessedImfileRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool detProcessedImfileInsertObject(
+    psDB            *dbh,               ///< Database handle
+    detProcessedImfileRow *object             ///< detProcessedImfileRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new detProcessedImfileRow on success or NULL on failure.
+ */
+
+detProcessedImfileRow *detProcessedImfilePopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table detProcessedImfileRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool detProcessedImfileInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool detProcessedImfilePopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool detProcessedImfileSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a detProcessedImfileRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *detProcessedImfileMetadataFromObject(
+    const detProcessedImfileRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A detProcessedImfileRow pointer or NULL on error
+ */
+
+detProcessedImfileRow *detProcessedImfileObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as detProcessedImfileRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *detProcessedImfileSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long detProcessedImfileDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** detStackedImfileRow data structure
+ *
+ * Structure for representing a single row of detStackedImfile table data.
+ */
+
+typedef struct {
+    psS32           det_id;
+    psS32           iteration;
+    char            *class_id;
+    char            *uri;
+    char            *stats;
+    char            *recipe;
+} detStackedImfileRow;
+
+/** Creates a new detStackedImfileRow object
+ *
+ *  @return A new detStackedImfileRow object or NULL on failure.
+ */
+
+detStackedImfileRow *detStackedImfileRowAlloc(
+    psS32           det_id,
+    psS32           iteration,
+    const char      *class_id,
+    const char      *uri,
+    const char      *stats,
+    const char      *recipe
+);
+
+/** Creates a new detStackedImfile table
+ *
+ * @return true on success
+ */
+
+bool detStackedImfileCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a detStackedImfile table
+ *
+ * @return true on success
+ */
+
+bool detStackedImfileDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool detStackedImfileInsert(
+    psDB            *dbh,               ///< Database handle
+    psS32           det_id,
+    psS32           iteration,
+    const char      *class_id,
+    const char      *uri,
+    const char      *stats,
+    const char      *recipe
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool detStackedImfilePop(
+    psDB            *dbh,               ///< Database handle
+    psS32           *det_id,
+    psS32           *iteration,
+    char            **class_id,
+    char            **uri,
+    char            **stats,
+    char            **recipe
+);
+
+/** Insert a single detStackedImfileRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool detStackedImfileInsertObject(
+    psDB            *dbh,               ///< Database handle
+    detStackedImfileRow *object             ///< detStackedImfileRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new detStackedImfileRow on success or NULL on failure.
+ */
+
+detStackedImfileRow *detStackedImfilePopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table detStackedImfileRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool detStackedImfileInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool detStackedImfilePopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool detStackedImfileSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a detStackedImfileRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *detStackedImfileMetadataFromObject(
+    const detStackedImfileRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A detStackedImfileRow pointer or NULL on error
+ */
+
+detStackedImfileRow *detStackedImfileObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as detStackedImfileRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *detStackedImfileSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long detStackedImfileDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** detNormalizedImfileRow data structure
+ *
+ * Structure for representing a single row of detNormalizedImfile table data.
+ */
+
+typedef struct {
+    psS32           det_id;
+    psS32           iteration;
+    char            *class_id;
+    char            *uri;
+    char            *stats;
+    char            *recipe;
+} detNormalizedImfileRow;
+
+/** Creates a new detNormalizedImfileRow object
+ *
+ *  @return A new detNormalizedImfileRow object or NULL on failure.
+ */
+
+detNormalizedImfileRow *detNormalizedImfileRowAlloc(
+    psS32           det_id,
+    psS32           iteration,
+    const char      *class_id,
+    const char      *uri,
+    const char      *stats,
+    const char      *recipe
+);
+
+/** Creates a new detNormalizedImfile table
+ *
+ * @return true on success
+ */
+
+bool detNormalizedImfileCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a detNormalizedImfile table
+ *
+ * @return true on success
+ */
+
+bool detNormalizedImfileDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool detNormalizedImfileInsert(
+    psDB            *dbh,               ///< Database handle
+    psS32           det_id,
+    psS32           iteration,
+    const char      *class_id,
+    const char      *uri,
+    const char      *stats,
+    const char      *recipe
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool detNormalizedImfilePop(
+    psDB            *dbh,               ///< Database handle
+    psS32           *det_id,
+    psS32           *iteration,
+    char            **class_id,
+    char            **uri,
+    char            **stats,
+    char            **recipe
+);
+
+/** Insert a single detNormalizedImfileRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool detNormalizedImfileInsertObject(
+    psDB            *dbh,               ///< Database handle
+    detNormalizedImfileRow *object             ///< detNormalizedImfileRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new detNormalizedImfileRow on success or NULL on failure.
+ */
+
+detNormalizedImfileRow *detNormalizedImfilePopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table detNormalizedImfileRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool detNormalizedImfileInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool detNormalizedImfilePopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool detNormalizedImfileSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a detNormalizedImfileRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *detNormalizedImfileMetadataFromObject(
+    const detNormalizedImfileRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A detNormalizedImfileRow pointer or NULL on error
+ */
+
+detNormalizedImfileRow *detNormalizedImfileObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as detNormalizedImfileRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *detNormalizedImfileSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long detNormalizedImfileDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** detMasterFrameRow data structure
+ *
+ * Structure for representing a single row of detMasterFrame table data.
+ */
+
+typedef struct {
+    psS32           det_id;
+    psS32           iteration;
+    char            *comment;
+} detMasterFrameRow;
+
+/** Creates a new detMasterFrameRow object
+ *
+ *  @return A new detMasterFrameRow object or NULL on failure.
+ */
+
+detMasterFrameRow *detMasterFrameRowAlloc(
+    psS32           det_id,
+    psS32           iteration,
+    const char      *comment
+);
+
+/** Creates a new detMasterFrame table
+ *
+ * @return true on success
+ */
+
+bool detMasterFrameCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a detMasterFrame table
+ *
+ * @return true on success
+ */
+
+bool detMasterFrameDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool detMasterFrameInsert(
+    psDB            *dbh,               ///< Database handle
+    psS32           det_id,
+    psS32           iteration,
+    const char      *comment
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool detMasterFramePop(
+    psDB            *dbh,               ///< Database handle
+    psS32           *det_id,
+    psS32           *iteration,
+    char            **comment
+);
+
+/** Insert a single detMasterFrameRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool detMasterFrameInsertObject(
+    psDB            *dbh,               ///< Database handle
+    detMasterFrameRow *object             ///< detMasterFrameRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new detMasterFrameRow on success or NULL on failure.
+ */
+
+detMasterFrameRow *detMasterFramePopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table detMasterFrameRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool detMasterFrameInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool detMasterFramePopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool detMasterFrameSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a detMasterFrameRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *detMasterFrameMetadataFromObject(
+    const detMasterFrameRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A detMasterFrameRow pointer or NULL on error
+ */
+
+detMasterFrameRow *detMasterFrameObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as detMasterFrameRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *detMasterFrameSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long detMasterFrameDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** detMasterImfileRow data structure
+ *
+ * Structure for representing a single row of detMasterImfile table data.
+ */
+
+typedef struct {
+    psS32           det_id;
+    char            *class_id;
+    char            *uri;
+    char            *stats;
+    char            *recipe;
+} detMasterImfileRow;
+
+/** Creates a new detMasterImfileRow object
+ *
+ *  @return A new detMasterImfileRow object or NULL on failure.
+ */
+
+detMasterImfileRow *detMasterImfileRowAlloc(
+    psS32           det_id,
+    const char      *class_id,
+    const char      *uri,
+    const char      *stats,
+    const char      *recipe
+);
+
+/** Creates a new detMasterImfile table
+ *
+ * @return true on success
+ */
+
+bool detMasterImfileCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a detMasterImfile table
+ *
+ * @return true on success
+ */
+
+bool detMasterImfileDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool detMasterImfileInsert(
+    psDB            *dbh,               ///< Database handle
+    psS32           det_id,
+    const char      *class_id,
+    const char      *uri,
+    const char      *stats,
+    const char      *recipe
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool detMasterImfilePop(
+    psDB            *dbh,               ///< Database handle
+    psS32           *det_id,
+    char            **class_id,
+    char            **uri,
+    char            **stats,
+    char            **recipe
+);
+
+/** Insert a single detMasterImfileRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool detMasterImfileInsertObject(
+    psDB            *dbh,               ///< Database handle
+    detMasterImfileRow *object             ///< detMasterImfileRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new detMasterImfileRow on success or NULL on failure.
+ */
+
+detMasterImfileRow *detMasterImfilePopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table detMasterImfileRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool detMasterImfileInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool detMasterImfilePopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool detMasterImfileSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a detMasterImfileRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *detMasterImfileMetadataFromObject(
+    const detMasterImfileRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A detMasterImfileRow pointer or NULL on error
+ */
+
+detMasterImfileRow *detMasterImfileObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as detMasterImfileRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *detMasterImfileSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long detMasterImfileDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** detResidImfileAnalysisRow data structure
+ *
+ * Structure for representing a single row of detResidImfileAnalysis table data.
+ */
+
+typedef struct {
+    psS32           det_id;
+    psS32           iteration;
+    char            *exp_id;
+    char            *class_id;
+    char            *stats;
+    char            *recipe;
+} detResidImfileAnalysisRow;
+
+/** Creates a new detResidImfileAnalysisRow object
+ *
+ *  @return A new detResidImfileAnalysisRow object or NULL on failure.
+ */
+
+detResidImfileAnalysisRow *detResidImfileAnalysisRowAlloc(
+    psS32           det_id,
+    psS32           iteration,
+    const char      *exp_id,
+    const char      *class_id,
+    const char      *stats,
+    const char      *recipe
+);
+
+/** Creates a new detResidImfileAnalysis table
+ *
+ * @return true on success
+ */
+
+bool detResidImfileAnalysisCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a detResidImfileAnalysis table
+ *
+ * @return true on success
+ */
+
+bool detResidImfileAnalysisDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool detResidImfileAnalysisInsert(
+    psDB            *dbh,               ///< Database handle
+    psS32           det_id,
+    psS32           iteration,
+    const char      *exp_id,
+    const char      *class_id,
+    const char      *stats,
+    const char      *recipe
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool detResidImfileAnalysisPop(
+    psDB            *dbh,               ///< Database handle
+    psS32           *det_id,
+    psS32           *iteration,
+    char            **exp_id,
+    char            **class_id,
+    char            **stats,
+    char            **recipe
+);
+
+/** Insert a single detResidImfileAnalysisRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool detResidImfileAnalysisInsertObject(
+    psDB            *dbh,               ///< Database handle
+    detResidImfileAnalysisRow *object             ///< detResidImfileAnalysisRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new detResidImfileAnalysisRow on success or NULL on failure.
+ */
+
+detResidImfileAnalysisRow *detResidImfileAnalysisPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table detResidImfileAnalysisRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool detResidImfileAnalysisInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool detResidImfileAnalysisPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool detResidImfileAnalysisSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a detResidImfileAnalysisRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *detResidImfileAnalysisMetadataFromObject(
+    const detResidImfileAnalysisRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A detResidImfileAnalysisRow pointer or NULL on error
+ */
+
+detResidImfileAnalysisRow *detResidImfileAnalysisObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as detResidImfileAnalysisRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *detResidImfileAnalysisSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long detResidImfileAnalysisDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+/** detResidExpAnalysisRow data structure
+ *
+ * Structure for representing a single row of detResidExpAnalysis table data.
+ */
+
+typedef struct {
+    psS32           det_id;
+    psS32           iteration;
+    char            *exp_id;
+    char            *stats;
+    char            *recipe;
+    bool            accept;
+} detResidExpAnalysisRow;
+
+/** Creates a new detResidExpAnalysisRow object
+ *
+ *  @return A new detResidExpAnalysisRow object or NULL on failure.
+ */
+
+detResidExpAnalysisRow *detResidExpAnalysisRowAlloc(
+    psS32           det_id,
+    psS32           iteration,
+    const char      *exp_id,
+    const char      *stats,
+    const char      *recipe,
+    bool            accept
+);
+
+/** Creates a new detResidExpAnalysis table
+ *
+ * @return true on success
+ */
+
+bool detResidExpAnalysisCreateTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Deletes a detResidExpAnalysis table
+ *
+ * @return true on success
+ */
+
+bool detResidExpAnalysisDropTable(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert a single row into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool detResidExpAnalysisInsert(
+    psDB            *dbh,               ///< Database handle
+    psS32           det_id,
+    psS32           iteration,
+    const char      *exp_id,
+    const char      *stats,
+    const char      *recipe,
+    bool            accept
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return true on success
+ */
+
+bool detResidExpAnalysisPop(
+    psDB            *dbh,               ///< Database handle
+    psS32           *det_id,
+    psS32           *iteration,
+    char            **exp_id,
+    char            **stats,
+    char            **recipe,
+    bool            *accept
+);
+
+/** Insert a single detResidExpAnalysisRow object into a table
+ *
+ * This function constructs and inserts a single row based on it's parameters.
+ *
+ * @return true on success
+ */
+
+bool detResidExpAnalysisInsertObject(
+    psDB            *dbh,               ///< Database handle
+    detResidExpAnalysisRow *object             ///< detResidExpAnalysisRow object
+);
+
+/** Removes the last row from the database and returns it
+ *
+ * @return A new detResidExpAnalysisRow on success or NULL on failure.
+ */
+
+detResidExpAnalysisRow *detResidExpAnalysisPopObject(
+    psDB            *dbh                ///< Database handle
+);
+
+/** Insert data from a binary FITS table detResidExpAnalysisRow into the database
+ *
+ * This function expects a psFits object with a FITS table as the first
+ * extension.  The table must have at least one row of data in it, that is of
+ * the appropriate format (number of columns and their type).  All other
+ * extensions are ignored.
+ *
+ * @return true on success
+ */
+
+bool detResidExpAnalysisInsertFits(
+    psDB            *dbh,               ///< Database handle
+    const psFits    *fits               ///< psFits object
+);
+
+/** Removes the last limit row from the database and returns them in a binary FITS table.
+ *
+ * This function assumes an empty psFits object and will create a FITS table as
+ * the first extension. 
+ *
+ * @return true on success
+ */
+
+bool detResidExpAnalysisPopFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Selects up to limit from the database and returns them in a binary FITS table
+ *
+ * This function assumes an empty psFits object and will create a FITS table
+ * as the first extension.
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return true on success
+ */
+
+bool detResidExpAnalysisSelectRowsFits(
+    psDB            *dbh,               ///< Database handle
+    psFits          *fits,              ///< psFits object
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+
+/** Convert a detResidExpAnalysisRow into an equivalent psMetadata
+ *
+ * @return A psMetadata pointer or NULL on error
+ */
+
+psMetadata *detResidExpAnalysisMetadataFromObject(
+    const detResidExpAnalysisRow *object             ///< fooRow to convert into a psMetadata
+);
+
+/** Convert a psMetadata into an equivalent fooRow
+ *
+ * @return A detResidExpAnalysisRow pointer or NULL on error
+ */
+
+detResidExpAnalysisRow *detResidExpAnalysisObjectFromMetadata(
+    psMetadata      *md                 ///< psMetadata to convert into a fooRow
+);
+/** Selects up to limit rows from the database and returns as detResidExpAnalysisRow objects in a psArray
+ *
+ *  See psDBSelectRows() for documentation on the format of where.
+ *
+ * @return A psArray pointer or NULL on error
+ */
+
+psArray *detResidExpAnalysisSelectRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psMetadata *where,            ///< Row match criteria
+    unsigned long long limit            ///< Maximum number of elements to return
+);
+/** Deletes up to limit rows from the database and returns the number of rows actually deleted. 
+ *
+ *  Note that a 'where' search psMetadata is constructed from each object and
+ *  used to find rows to delete.
+ *
+ * @return A The number of rows removed or a negative value on error
+ */
+
+long long detResidExpAnalysisDeleteRowObjects(
+    psDB            *dbh,               ///< Database handle
+    const psArray   *objects,           ///< Array of objects to delete
+    unsigned long long limit            ///< Maximum number of elements to delete 
+);
+
+/// @}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // DETRESIDEXPANALYSIS_DB_H
Index: /tags/start/ippdb/tests/Makefile.am
===================================================================
--- /tags/start/ippdb/tests/Makefile.am	(revision 12606)
+++ /tags/start/ippdb/tests/Makefile.am	(revision 12606)
@@ -0,0 +1,67 @@
+# copied from bison-1.875d
+
+EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4
+
+DISTCLEANFILES       = atconfig $(check_SCRIPTS)
+MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE)
+
+## ------------ ##
+## package.m4.  ##
+## ------------ ##
+
+$(srcdir)/package.m4: $(top_srcdir)/configure.ac
+	{					\
+	  echo '# Signature of the current package.'; \
+	  echo 'm4_define([AT_PACKAGE_NAME],      [@PACKAGE_NAME@])'; \
+	  echo 'm4_define([AT_PACKAGE_TARNAME],   [@PACKAGE_TARNAME@])'; \
+	  echo 'm4_define([AT_PACKAGE_VERSION],   [@PACKAGE_VERSION@])'; \
+	  echo 'm4_define([AT_PACKAGE_STRING],    [@PACKAGE_STRING@])'; \
+	  echo 'm4_define([AT_PACKAGE_BUGREPORT], [@PACKAGE_BUGREPORT@])'; \
+	} >$(srcdir)/package.m4
+
+## ------------ ##
+## Test suite.  ##
+## ------------ ##
+
+TESTSUITE = $(srcdir)/testsuite
+
+AUTOTEST = $(AUTOM4TE) --language=autotest
+$(TESTSUITE): package.m4 $(TESTSUITE_AT)
+	$(AUTOTEST) -I $(srcdir) testsuite.at -o $@.tmp
+	mv $@.tmp $@
+
+atconfig: $(top_builddir)/config.status
+	cd $(top_builddir) && ./config.status tests/$@
+
+clean-local:
+	test ! -f $(TESTSUITE) || $(SHELL) $(TESTSUITE) --clean
+
+check-local: atconfig $(TESTSUITE)
+	$(SHELL) $(TESTSUITE)
+
+#
+# END BISON
+#
+
+UNITS = \
+	alloc \
+	init \
+	cleanup \
+	createtable \
+    droptable \
+    insert \
+    pop \
+    insertobject \
+    popobject \
+    insertfits \
+    popfits \
+    selectrowsfits \
+    metadatafromobject \
+    objectfrommetadata
+
+AM_CPPFLAGS = -I$(top_srcdir)/src$
+AM_CFLAGS   = @ippdb_CFLAGS@ $(PSLIB_CFLAGS)$
+AM_LDFLAGS  = $(PSLIB_LIBS)$
+LDADD       = $(top_builddir)/src/libippdb.la$
+
+check_PROGRAMS = dbsetup dbcleanup $(UNITS)
Index: /tags/start/ippdb/tests/alloc.c
===================================================================
--- /tags/start/ippdb/tests/alloc.c	(revision 12606)
+++ /tags/start/ippdb/tests/alloc.c	(revision 12606)
@@ -0,0 +1,1189 @@
+#include <pslib.h>
+#include <ippdb.h>
+#include <stdlib.h>
+
+#define MAX_STRING_LENGTH 1024
+
+int main ()
+{
+    {
+        weatherRow      *object;
+
+        object = weatherRowAlloc(32.32, 32.32, 32.32, 32.32, 32.32, 32.32, 32.32    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!object->temp01 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->humi01 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->temp02 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->humi02 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->temp03 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->humi03 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->pressure == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        skyp_transparencyRow *object;
+
+        object = skyp_transparencyRowAlloc("a string", 64.64, -32, 64.64, 64.64, 32.32, 64.64    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->filter, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->trans == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->nstars == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->ra == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->decl == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->exptime == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->sky_bright == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        skyp_absorptionRow *object;
+
+        object = skyp_absorptionRowAlloc("a string", 32.32, 32.32, 32.32, -32, 64.64, 64.64, 32.32, 64.64    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->disperser_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->atmcomp1 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->atmcomp2 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->atmcomp3 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->nstars == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->ra == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->decl == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->exptime == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->sky_bright == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        skyp_emissionRow *object;
+
+        object = skyp_emissionRowAlloc("a string", 32.32, 32.32, 32.32, 32.32, 32.32    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->disperser_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->atmcomp1 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->atmcomp2 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->atmcomp3 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->continuum == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->exptime == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        dimmRow         *object;
+
+        object = dimmRowAlloc(32.32, 32.32, 32.32, 64.64, 64.64, 32.32, "a string"    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!object->sigmax == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->sigmay == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->fwhm == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->ra == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->decl == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->expttime == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        skyp_irRow      *object;
+
+        object = skyp_irRowAlloc(64.64, 64.64, 64.64, 64.64, 32.32, 32.32    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!object->sky_bright == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->sky_var == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->ra == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->decl == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->fov_x == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->fov_y == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        domeRow         *object;
+
+        object = domeRowAlloc(32.32, true, true, true    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!object->az == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->open == true) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->light == true) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->track == true) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        telescopeRow    *object;
+
+        object = telescopeRowAlloc("a string", 32.32, 32.32, 64.64, 64.64    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->guide, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->alt == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->az == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->ra == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->decl == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        summitExpRow    *object;
+
+        object = summitExpRowAlloc("a string", "a string", "a string", "a string", "a string"    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        pzPendingExpRow *object;
+
+        object = pzPendingExpRowAlloc("a string", "a string", "a string", "a string", -32    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        pzPendingImfileRow *object;
+
+        object = pzPendingImfileRowAlloc("a string", -32, "a string", "a string", "a string", "a string"    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->bytes == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->md5sum, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        newExpRow       *object;
+
+        object = newExpRowAlloc("a string", "a string", "a string", "a string", -32    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        newImfileRow    *object;
+
+        object = newImfileRowAlloc("a string", "a string", "a string", "a string"    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        rawDetrendExpRow *object;
+
+        object = rawDetrendExpRowAlloc("a string", "a string", "a string", "a string", -32, "a string", "a string"    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->filter, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        rawScienceExpRow *object;
+
+        object = rawScienceExpRowAlloc("a string", "a string", "a string", "a string", -32, "a string", "a string"    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->filter, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        rawImfileRow    *object;
+
+        object = rawImfileRowAlloc("a string", "a string", "a string", "a string"    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        p1PendingExpRow *object;
+
+        object = p1PendingExpRowAlloc("a string", "a string", "a string", "a string", -32, "a string", "a string", "a string", -32    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->filter, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p1_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        p2PendingExpRow *object;
+
+        object = p2PendingExpRowAlloc("a string", "a string", "a string", "a string", -32, "a string", "a string", "a string", -32, -32    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->filter, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p1_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p2_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        p2PendingImfileRow *object;
+
+        object = p2PendingImfileRowAlloc("a string", "a string", "a string", "a string", "a string", -32, -32    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p1_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p2_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        p2DoneExpRow    *object;
+
+        object = p2DoneExpRowAlloc("a string", "a string", "a string", "a string", -32, "a string", "a string", "a string", -32, -32    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->filter, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p1_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p2_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        p2DoneImfileRow *object;
+
+        object = p2DoneImfileRowAlloc("a string", "a string", "a string", "a string", "a string", -32, -32    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p1_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p2_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        p3PendingExpRow *object;
+
+        object = p3PendingExpRowAlloc("a string", "a string", "a string", -32, "a string", "a string", "a string", -32, -32    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->filter, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p2_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p3_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        detRunRow       *object;
+
+        object = detRunRowAlloc("a string"    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (strncmp(object->det_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        detInputExpRow  *object;
+
+        object = detInputExpRowAlloc(-32, -32, "a string", "a string", "a string", "a string", -32, "a string", "a string"    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!object->det_id == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->iteration == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->filter, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        detProcessedImfileRow *object;
+
+        object = detProcessedImfileRowAlloc(-32, "a string", "a string", "a string", "a string", "a string"    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!object->det_id == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        detStackedImfileRow *object;
+
+        object = detStackedImfileRowAlloc(-32, -32, "a string", "a string", "a string", "a string"    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!object->det_id == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->iteration == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        detNormalizedImfileRow *object;
+
+        object = detNormalizedImfileRowAlloc(-32, -32, "a string", "a string", "a string", "a string"    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!object->det_id == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->iteration == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        detMasterFrameRow *object;
+
+        object = detMasterFrameRowAlloc(-32, -32, "a string"    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!object->det_id == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->iteration == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->comment, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        detMasterImfileRow *object;
+
+        object = detMasterImfileRowAlloc(-32, "a string", "a string", "a string", "a string"    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!object->det_id == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        detResidImfileAnalysisRow *object;
+
+        object = detResidImfileAnalysisRowAlloc(-32, -32, "a string", "a string", "a string", "a string"    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!object->det_id == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->iteration == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        detResidExpAnalysisRow *object;
+
+        object = detResidExpAnalysisRowAlloc(-32, -32, "a string", "a string", "a string", true    );
+
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!object->det_id == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->iteration == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->accept == true) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/start/ippdb/tests/cleanup.c
===================================================================
--- /tags/start/ippdb/tests/cleanup.c	(revision 12606)
+++ /tags/start/ippdb/tests/cleanup.c	(revision 12606)
@@ -0,0 +1,17 @@
+#include <pslib.h>
+#include <ippdb.h>
+#include <stdlib.h>
+
+int main ()
+{
+    psDB            *dbh;
+
+    dbh = psDBInit("localhost", "test", NULL, "test");
+    if (!dbh) {
+        exit(EXIT_FAILURE);
+    }
+
+    ippdbCleanup(dbh);
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/start/ippdb/tests/createtable.c
===================================================================
--- /tags/start/ippdb/tests/createtable.c	(revision 12606)
+++ /tags/start/ippdb/tests/createtable.c	(revision 12606)
@@ -0,0 +1,473 @@
+#include <pslib.h>
+#include <ippdb.h>
+#include <stdlib.h>
+
+int main ()
+{
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!weatherCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!skyp_transparencyCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!skyp_absorptionCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!skyp_emissionCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!dimmCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!skyp_irCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!domeCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!telescopeCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!summitExpCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!pzPendingExpCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!pzPendingImfileCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!newExpCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!newImfileCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!rawDetrendExpCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!rawScienceExpCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!rawImfileCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!p1PendingExpCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!p2PendingExpCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!p2PendingImfileCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!p2DoneExpCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!p2DoneImfileCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!p3PendingExpCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!detRunCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!detInputExpCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!detProcessedImfileCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!detStackedImfileCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!detNormalizedImfileCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!detMasterFrameCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!detMasterImfileCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!detResidImfileAnalysisCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if(!detResidExpAnalysisCreateTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/start/ippdb/tests/dbcleanup.c
===================================================================
--- /tags/start/ippdb/tests/dbcleanup.c	(revision 12606)
+++ /tags/start/ippdb/tests/dbcleanup.c	(revision 12606)
@@ -0,0 +1,48 @@
+#include <pslib.h>
+#include <stdlib.h>
+
+int main ()
+{
+    psDB            *dbh;
+
+    dbh = psDBInit("localhost", "test", NULL, "test");
+    if (!dbh) {
+        exit(EXIT_FAILURE);
+    }
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS weather");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS skyp_transparency");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS skyp_absorption");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS skyp_emission");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS dimm");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS skyp_ir");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS dome");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS telescope");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS summitExp");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS pzPendingExp");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS pzPendingImfile");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS newExp");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS newImfile");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS rawDetrendExp");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS rawScienceExp");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS rawImfile");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS p1PendingExp");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS p2PendingExp");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS p2PendingImfile");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS p2DoneExp");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS p2DoneImfile");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS p3PendingExp");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS detRun");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS detInputExp");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS detProcessedImfile");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS detStackedImfile");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS detNormalizedImfile");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS detMasterFrame");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS detMasterImfile");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS detResidImfileAnalysis");
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS detResidExpAnalysis");
+
+    psDBCleanup(dbh);
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/start/ippdb/tests/dbsetup.c
===================================================================
--- /tags/start/ippdb/tests/dbsetup.c	(revision 12606)
+++ /tags/start/ippdb/tests/dbsetup.c	(revision 12606)
@@ -0,0 +1,111 @@
+#include <pslib.h>
+#include <ippdb.h>
+#include <stdlib.h>
+
+int main ()
+{
+    psDB            *dbh;
+
+    dbh = psDBInit("localhost", "test", NULL, "test");
+    if (!dbh) {
+        exit(EXIT_FAILURE);
+    }
+
+    // remove the table if it already exists
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS weather");
+    weatherCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS skyp_transparency");
+    skyp_transparencyCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS skyp_absorption");
+    skyp_absorptionCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS skyp_emission");
+    skyp_emissionCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS dimm");
+    dimmCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS skyp_ir");
+    skyp_irCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS dome");
+    domeCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS telescope");
+    telescopeCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS summitExp");
+    summitExpCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS pzPendingExp");
+    pzPendingExpCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS pzPendingImfile");
+    pzPendingImfileCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS newExp");
+    newExpCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS newImfile");
+    newImfileCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS rawDetrendExp");
+    rawDetrendExpCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS rawScienceExp");
+    rawScienceExpCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS rawImfile");
+    rawImfileCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS p1PendingExp");
+    p1PendingExpCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS p2PendingExp");
+    p2PendingExpCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS p2PendingImfile");
+    p2PendingImfileCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS p2DoneExp");
+    p2DoneExpCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS p2DoneImfile");
+    p2DoneImfileCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS p3PendingExp");
+    p3PendingExpCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS detRun");
+    detRunCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS detInputExp");
+    detInputExpCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS detProcessedImfile");
+    detProcessedImfileCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS detStackedImfile");
+    detStackedImfileCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS detNormalizedImfile");
+    detNormalizedImfileCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS detMasterFrame");
+    detMasterFrameCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS detMasterImfile");
+    detMasterImfileCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS detResidImfileAnalysis");
+    detResidImfileAnalysisCreateTable(dbh);
+
+    p_psDBRunQuery(dbh, "DROP TABLE IF EXISTS detResidExpAnalysis");
+    detResidExpAnalysisCreateTable(dbh);
+
+    psDBCleanup(dbh);
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/start/ippdb/tests/droptable.c
===================================================================
--- /tags/start/ippdb/tests/droptable.c	(revision 12606)
+++ /tags/start/ippdb/tests/droptable.c	(revision 12606)
@@ -0,0 +1,473 @@
+#include <pslib.h>
+#include <ippdb.h>
+#include <stdlib.h>
+
+int main ()
+{
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!weatherDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_transparencyDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_absorptionDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_emissionDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!dimmDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_irDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!domeDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!telescopeDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!summitExpDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzPendingExpDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzPendingImfileDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!newExpDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!newImfileDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawDetrendExpDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawScienceExpDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawImfileDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p1PendingExpDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2PendingExpDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2PendingImfileDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2DoneExpDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2DoneImfileDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p3PendingExpDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detRunDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detInputExpDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detProcessedImfileDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detStackedImfileDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detNormalizedImfileDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detMasterFrameDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detMasterImfileDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detResidImfileAnalysisDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detResidExpAnalysisDropTable(dbh)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/start/ippdb/tests/init.c
===================================================================
--- /tags/start/ippdb/tests/init.c	(revision 12606)
+++ /tags/start/ippdb/tests/init.c	(revision 12606)
@@ -0,0 +1,17 @@
+#include <pslib.h>
+#include <ippdb.h>
+#include <stdlib.h>
+
+int main ()
+{
+    psDB            *dbh;
+
+    dbh = ippdbInit("localhost", "test", NULL, "test");
+    if (!dbh) {
+        exit(EXIT_FAILURE);
+    }
+
+    psDBCleanup(dbh);
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/start/ippdb/tests/insert.c
===================================================================
--- /tags/start/ippdb/tests/insert.c	(revision 12606)
+++ /tags/start/ippdb/tests/insert.c	(revision 12606)
@@ -0,0 +1,473 @@
+#include <pslib.h>
+#include <ippdb.h>
+#include <stdlib.h>
+
+int main ()
+{
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!weatherInsert(dbh, 32.32, 32.32, 32.32, 32.32, 32.32, 32.32, 32.32)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_transparencyInsert(dbh, "a string", 64.64, -32, 64.64, 64.64, 32.32, 64.64)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_absorptionInsert(dbh, "a string", 32.32, 32.32, 32.32, -32, 64.64, 64.64, 32.32, 64.64)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_emissionInsert(dbh, "a string", 32.32, 32.32, 32.32, 32.32, 32.32)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!dimmInsert(dbh, 32.32, 32.32, 32.32, 64.64, 64.64, 32.32, "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_irInsert(dbh, 64.64, 64.64, 64.64, 64.64, 32.32, 32.32)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!domeInsert(dbh, 32.32, true, true, true)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!telescopeInsert(dbh, "a string", 32.32, 32.32, 64.64, 64.64)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!summitExpInsert(dbh, "a string", "a string", "a string", "a string", "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzPendingExpInsert(dbh, "a string", "a string", "a string", "a string", -32)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzPendingImfileInsert(dbh, "a string", -32, "a string", "a string", "a string", "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!newExpInsert(dbh, "a string", "a string", "a string", "a string", -32)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!newImfileInsert(dbh, "a string", "a string", "a string", "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawDetrendExpInsert(dbh, "a string", "a string", "a string", "a string", -32, "a string", "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawScienceExpInsert(dbh, "a string", "a string", "a string", "a string", -32, "a string", "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawImfileInsert(dbh, "a string", "a string", "a string", "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p1PendingExpInsert(dbh, "a string", "a string", "a string", "a string", -32, "a string", "a string", "a string", -32)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2PendingExpInsert(dbh, "a string", "a string", "a string", "a string", -32, "a string", "a string", "a string", -32, -32)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2PendingImfileInsert(dbh, "a string", "a string", "a string", "a string", "a string", -32, -32)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2DoneExpInsert(dbh, "a string", "a string", "a string", "a string", -32, "a string", "a string", "a string", -32, -32)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2DoneImfileInsert(dbh, "a string", "a string", "a string", "a string", "a string", -32, -32)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p3PendingExpInsert(dbh, "a string", "a string", "a string", -32, "a string", "a string", "a string", -32, -32)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detRunInsert(dbh, "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detInputExpInsert(dbh, -32, -32, "a string", "a string", "a string", "a string", -32, "a string", "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detProcessedImfileInsert(dbh, -32, "a string", "a string", "a string", "a string", "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detStackedImfileInsert(dbh, -32, -32, "a string", "a string", "a string", "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detNormalizedImfileInsert(dbh, -32, -32, "a string", "a string", "a string", "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detMasterFrameInsert(dbh, -32, -32, "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detMasterImfileInsert(dbh, -32, "a string", "a string", "a string", "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detResidImfileAnalysisInsert(dbh, -32, -32, "a string", "a string", "a string", "a string")) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detResidExpAnalysisInsert(dbh, -32, -32, "a string", "a string", "a string", true)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/start/ippdb/tests/insertfits.c
===================================================================
--- /tags/start/ippdb/tests/insertfits.c	(revision 12606)
+++ /tags/start/ippdb/tests/insertfits.c	(revision 12606)
@@ -0,0 +1,818 @@
+#include <pslib.h>
+#include <ippdb.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#define TMP_FILENAME "./blargh"
+
+int main ()
+{
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!weatherInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_transparencyInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_absorptionInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_emissionInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!dimmInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_irInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!domeInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!telescopeInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!summitExpInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzPendingExpInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzPendingImfileInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!newExpInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!newImfileInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawDetrendExpInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawScienceExpInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawImfileInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p1PendingExpInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2PendingExpInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2PendingImfileInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2DoneExpInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2DoneImfileInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p3PendingExpInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detRunInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detInputExpInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detProcessedImfileInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detStackedImfileInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detNormalizedImfileInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detMasterFrameInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detMasterImfileInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detResidImfileAnalysisInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // open a temp
+        fits = psFitsOpen(TMP_FILENAME, "r");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detResidExpAnalysisInsertFits(dbh, fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/start/ippdb/tests/insertobject.c
===================================================================
--- /tags/start/ippdb/tests/insertobject.c	(revision 12606)
+++ /tags/start/ippdb/tests/insertobject.c	(revision 12606)
@@ -0,0 +1,690 @@
+#include <pslib.h>
+#include <ippdb.h>
+#include <stdlib.h>
+
+int main ()
+{
+    {
+        psDB            *dbh;
+        weatherRow      *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = weatherRowAlloc(32.32, 32.32, 32.32, 32.32, 32.32, 32.32, 32.32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!weatherInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        skyp_transparencyRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = skyp_transparencyRowAlloc("a string", 64.64, -32, 64.64, 64.64, 32.32, 64.64);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_transparencyInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        skyp_absorptionRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = skyp_absorptionRowAlloc("a string", 32.32, 32.32, 32.32, -32, 64.64, 64.64, 32.32, 64.64);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_absorptionInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        skyp_emissionRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = skyp_emissionRowAlloc("a string", 32.32, 32.32, 32.32, 32.32, 32.32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_emissionInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        dimmRow         *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = dimmRowAlloc(32.32, 32.32, 32.32, 64.64, 64.64, 32.32, "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!dimmInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        skyp_irRow      *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = skyp_irRowAlloc(64.64, 64.64, 64.64, 64.64, 32.32, 32.32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_irInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        domeRow         *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = domeRowAlloc(32.32, true, true, true);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!domeInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        telescopeRow    *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = telescopeRowAlloc("a string", 32.32, 32.32, 64.64, 64.64);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!telescopeInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        summitExpRow    *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = summitExpRowAlloc("a string", "a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!summitExpInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        pzPendingExpRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = pzPendingExpRowAlloc("a string", "a string", "a string", "a string", -32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzPendingExpInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        pzPendingImfileRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = pzPendingImfileRowAlloc("a string", -32, "a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzPendingImfileInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        newExpRow       *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = newExpRowAlloc("a string", "a string", "a string", "a string", -32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!newExpInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        newImfileRow    *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = newImfileRowAlloc("a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!newImfileInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        rawDetrendExpRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = rawDetrendExpRowAlloc("a string", "a string", "a string", "a string", -32, "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawDetrendExpInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        rawScienceExpRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = rawScienceExpRowAlloc("a string", "a string", "a string", "a string", -32, "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawScienceExpInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        rawImfileRow    *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = rawImfileRowAlloc("a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawImfileInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        p1PendingExpRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = p1PendingExpRowAlloc("a string", "a string", "a string", "a string", -32, "a string", "a string", "a string", -32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p1PendingExpInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        p2PendingExpRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = p2PendingExpRowAlloc("a string", "a string", "a string", "a string", -32, "a string", "a string", "a string", -32, -32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2PendingExpInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        p2PendingImfileRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = p2PendingImfileRowAlloc("a string", "a string", "a string", "a string", "a string", -32, -32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2PendingImfileInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        p2DoneExpRow    *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = p2DoneExpRowAlloc("a string", "a string", "a string", "a string", -32, "a string", "a string", "a string", -32, -32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2DoneExpInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        p2DoneImfileRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = p2DoneImfileRowAlloc("a string", "a string", "a string", "a string", "a string", -32, -32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2DoneImfileInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        p3PendingExpRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = p3PendingExpRowAlloc("a string", "a string", "a string", -32, "a string", "a string", "a string", -32, -32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p3PendingExpInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        detRunRow       *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = detRunRowAlloc("a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detRunInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        detInputExpRow  *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = detInputExpRowAlloc(-32, -32, "a string", "a string", "a string", "a string", -32, "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detInputExpInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        detProcessedImfileRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = detProcessedImfileRowAlloc(-32, "a string", "a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detProcessedImfileInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        detStackedImfileRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = detStackedImfileRowAlloc(-32, -32, "a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detStackedImfileInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        detNormalizedImfileRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = detNormalizedImfileRowAlloc(-32, -32, "a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detNormalizedImfileInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        detMasterFrameRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = detMasterFrameRowAlloc(-32, -32, "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detMasterFrameInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        detMasterImfileRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = detMasterImfileRowAlloc(-32, "a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detMasterImfileInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        detResidImfileAnalysisRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = detResidImfileAnalysisRowAlloc(-32, -32, "a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detResidImfileAnalysisInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        detResidExpAnalysisRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = detResidExpAnalysisRowAlloc(-32, -32, "a string", "a string", "a string", true);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detResidExpAnalysisInsertObject(dbh, object)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/start/ippdb/tests/metadatafromobject.c
===================================================================
--- /tags/start/ippdb/tests/metadatafromobject.c	(revision 12606)
+++ /tags/start/ippdb/tests/metadatafromobject.c	(revision 12606)
@@ -0,0 +1,1438 @@
+#include <pslib.h>
+#include <ippdb.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAX_STRING_LENGTH 1024
+
+int main ()
+{
+    {
+        psMetadata      *md;
+        weatherRow      *object;
+        bool            status;
+
+        object = weatherRowAlloc(32.32, 32.32, 32.32, 32.32, 32.32, 32.32, 32.32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = weatherMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (!psMetadataLookupF32(&status, md, "temp01") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "humi01") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "temp02") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "humi02") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "temp03") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "humi03") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "pressure") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        skyp_transparencyRow *object;
+        bool            status;
+
+        object = skyp_transparencyRowAlloc("a string", 64.64, -32, 64.64, 64.64, 32.32, 64.64);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = skyp_transparencyMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "filter"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF64(&status, md, "trans") == 64.64) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "nstars") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF64(&status, md, "ra") == 64.64) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF64(&status, md, "decl") == 64.64) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "exptime") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF64(&status, md, "sky_bright") == 64.64) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        skyp_absorptionRow *object;
+        bool            status;
+
+        object = skyp_absorptionRowAlloc("a string", 32.32, 32.32, 32.32, -32, 64.64, 64.64, 32.32, 64.64);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = skyp_absorptionMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "disperser_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "atmcomp1") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "atmcomp2") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "atmcomp3") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "nstars") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF64(&status, md, "ra") == 64.64) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF64(&status, md, "decl") == 64.64) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "exptime") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF64(&status, md, "sky_bright") == 64.64) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        skyp_emissionRow *object;
+        bool            status;
+
+        object = skyp_emissionRowAlloc("a string", 32.32, 32.32, 32.32, 32.32, 32.32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = skyp_emissionMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "disperser_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "atmcomp1") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "atmcomp2") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "atmcomp3") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "continuum") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "exptime") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        dimmRow         *object;
+        bool            status;
+
+        object = dimmRowAlloc(32.32, 32.32, 32.32, 64.64, 64.64, 32.32, "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = dimmMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (!psMetadataLookupF32(&status, md, "sigmax") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "sigmay") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "fwhm") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF64(&status, md, "ra") == 64.64) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF64(&status, md, "decl") == 64.64) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "expttime") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "telescope_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        skyp_irRow      *object;
+        bool            status;
+
+        object = skyp_irRowAlloc(64.64, 64.64, 64.64, 64.64, 32.32, 32.32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = skyp_irMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (!psMetadataLookupF64(&status, md, "sky_bright") == 64.64) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF64(&status, md, "sky_var") == 64.64) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF64(&status, md, "ra") == 64.64) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF64(&status, md, "decl") == 64.64) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "fov_x") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "fov_y") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        domeRow         *object;
+        bool            status;
+
+        object = domeRowAlloc(32.32, true, true, true);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = domeMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (!psMetadataLookupF32(&status, md, "az") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupBool(&status, md, "open") == true) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupBool(&status, md, "light") == true) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupBool(&status, md, "track") == true) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        telescopeRow    *object;
+        bool            status;
+
+        object = telescopeRowAlloc("a string", 32.32, 32.32, 64.64, 64.64);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = telescopeMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "guide"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "alt") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF32(&status, md, "az") == 32.32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF64(&status, md, "ra") == 64.64) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupF64(&status, md, "decl") == 64.64) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        summitExpRow    *object;
+        bool            status;
+
+        object = summitExpRowAlloc("a string", "a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = summitExpMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "camera"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "telescope"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_type"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "uri"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        pzPendingExpRow *object;
+        bool            status;
+
+        object = pzPendingExpRowAlloc("a string", "a string", "a string", "a string", -32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = pzPendingExpMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "camera"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "telescope"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_type"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "imfiles") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        pzPendingImfileRow *object;
+        bool            status;
+
+        object = pzPendingImfileRowAlloc("a string", -32, "a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = pzPendingImfileMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "bytes") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "md5sum"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "class"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "class_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "uri"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        newExpRow       *object;
+        bool            status;
+
+        object = newExpRowAlloc("a string", "a string", "a string", "a string", -32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = newExpMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "camera"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "telescope"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_type"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "imfiles") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        newImfileRow    *object;
+        bool            status;
+
+        object = newImfileRowAlloc("a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = newImfileMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "class"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "class_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "uri"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        rawDetrendExpRow *object;
+        bool            status;
+
+        object = rawDetrendExpRowAlloc("a string", "a string", "a string", "a string", -32, "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = rawDetrendExpMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "camera"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "telescope"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_type"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "imfiles") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "filter"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "stats"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        rawScienceExpRow *object;
+        bool            status;
+
+        object = rawScienceExpRowAlloc("a string", "a string", "a string", "a string", -32, "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = rawScienceExpMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "camera"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "telescope"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_type"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "imfiles") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "filter"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "stats"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        rawImfileRow    *object;
+        bool            status;
+
+        object = rawImfileRowAlloc("a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = rawImfileMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "class_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "uri"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "stats"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        p1PendingExpRow *object;
+        bool            status;
+
+        object = p1PendingExpRowAlloc("a string", "a string", "a string", "a string", -32, "a string", "a string", "a string", -32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = p1PendingExpMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "camera"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "telescope"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_type"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "imfiles") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "filter"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "stats"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "recipe"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "p1_version") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        p2PendingExpRow *object;
+        bool            status;
+
+        object = p2PendingExpRowAlloc("a string", "a string", "a string", "a string", -32, "a string", "a string", "a string", -32, -32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = p2PendingExpMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "camera"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "telescope"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_type"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "imfiles") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "filter"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "stats"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "recipe"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "p1_version") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "p2_version") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        p2PendingImfileRow *object;
+        bool            status;
+
+        object = p2PendingImfileRowAlloc("a string", "a string", "a string", "a string", "a string", -32, -32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = p2PendingImfileMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "class_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "uri"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "stats"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "recipe"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "p1_version") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "p2_version") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        p2DoneExpRow    *object;
+        bool            status;
+
+        object = p2DoneExpRowAlloc("a string", "a string", "a string", "a string", -32, "a string", "a string", "a string", -32, -32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = p2DoneExpMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "camera"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "telescope"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_type"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "imfiles") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "filter"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "stats"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "recipe"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "p1_version") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "p2_version") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        p2DoneImfileRow *object;
+        bool            status;
+
+        object = p2DoneImfileRowAlloc("a string", "a string", "a string", "a string", "a string", -32, -32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = p2DoneImfileMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "class_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "uri"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "stats"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "recipe"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "p1_version") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "p2_version") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        p3PendingExpRow *object;
+        bool            status;
+
+        object = p3PendingExpRowAlloc("a string", "a string", "a string", -32, "a string", "a string", "a string", -32, -32);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = p3PendingExpMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "camera"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_type"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "imfiles") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "filter"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "stats"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "recipe"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "p2_version") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "p3_version") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        detRunRow       *object;
+        bool            status;
+
+        object = detRunRowAlloc("a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = detRunMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (strncmp(psMetadataLookupPtr(&status, md, "det_type"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        detInputExpRow  *object;
+        bool            status;
+
+        object = detInputExpRowAlloc(-32, -32, "a string", "a string", "a string", "a string", -32, "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = detInputExpMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (!psMetadataLookupS32(&status, md, "det_id") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "iteration") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "camera"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "telescope"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_type"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "imfiles") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "filter"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "stats"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        detProcessedImfileRow *object;
+        bool            status;
+
+        object = detProcessedImfileRowAlloc(-32, "a string", "a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = detProcessedImfileMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (!psMetadataLookupS32(&status, md, "det_id") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "class_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "uri"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "stats"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "recipe"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        detStackedImfileRow *object;
+        bool            status;
+
+        object = detStackedImfileRowAlloc(-32, -32, "a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = detStackedImfileMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (!psMetadataLookupS32(&status, md, "det_id") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "iteration") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "class_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "uri"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "stats"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "recipe"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        detNormalizedImfileRow *object;
+        bool            status;
+
+        object = detNormalizedImfileRowAlloc(-32, -32, "a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = detNormalizedImfileMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (!psMetadataLookupS32(&status, md, "det_id") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "iteration") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "class_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "uri"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "stats"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "recipe"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        detMasterFrameRow *object;
+        bool            status;
+
+        object = detMasterFrameRowAlloc(-32, -32, "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = detMasterFrameMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (!psMetadataLookupS32(&status, md, "det_id") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "iteration") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "comment"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        detMasterImfileRow *object;
+        bool            status;
+
+        object = detMasterImfileRowAlloc(-32, "a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = detMasterImfileMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (!psMetadataLookupS32(&status, md, "det_id") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "class_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "uri"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "stats"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "recipe"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        detResidImfileAnalysisRow *object;
+        bool            status;
+
+        object = detResidImfileAnalysisRowAlloc(-32, -32, "a string", "a string", "a string", "a string");
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = detResidImfileAnalysisMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (!psMetadataLookupS32(&status, md, "det_id") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "iteration") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "class_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "stats"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "recipe"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    {
+        psMetadata      *md;
+        detResidExpAnalysisRow *object;
+        bool            status;
+
+        object = detResidExpAnalysisRowAlloc(-32, -32, "a string", "a string", "a string", true);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        md = detResidExpAnalysisMetadataFromObject(object);
+        if (!md) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+
+        if (!psMetadataLookupS32(&status, md, "det_id") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupS32(&status, md, "iteration") == -32) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "exp_id"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "stats"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(psMetadataLookupPtr(&status, md, "recipe"), "a string", MAX_STRING_LENGTH)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataLookupBool(&status, md, "accept") == true) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+    }
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/start/ippdb/tests/objectfrommetadata.c
===================================================================
--- /tags/start/ippdb/tests/objectfrommetadata.c	(revision 12606)
+++ /tags/start/ippdb/tests/objectfrommetadata.c	(revision 12606)
@@ -0,0 +1,2121 @@
+#include <pslib.h>
+#include <ippdb.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAX_STRING_LENGTH 1024
+
+int main ()
+{
+    {
+        psMetadata      *md;
+        weatherRow      *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "temp01", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "humi01", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "temp02", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "humi02", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "temp03", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "humi03", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "pressure", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = weatherObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (!object->temp01 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->humi01 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->temp02 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->humi02 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->temp03 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->humi03 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->pressure == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        skyp_transparencyRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF64(md, PS_LIST_TAIL, "trans", 0, NULL, 64.64)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "nstars", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, 64.64)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, 64.64)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "exptime", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF64(md, PS_LIST_TAIL, "sky_bright", 0, NULL, 64.64)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = skyp_transparencyObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->filter, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->trans == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->nstars == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->ra == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->decl == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->exptime == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->sky_bright == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        skyp_absorptionRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "disperser_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp1", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp2", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp3", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "nstars", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, 64.64)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, 64.64)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "exptime", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF64(md, PS_LIST_TAIL, "sky_bright", 0, NULL, 64.64)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = skyp_absorptionObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->disperser_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->atmcomp1 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->atmcomp2 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->atmcomp3 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->nstars == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->ra == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->decl == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->exptime == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->sky_bright == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        skyp_emissionRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "disperser_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp1", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp2", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "atmcomp3", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "continuum", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "exptime", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = skyp_emissionObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->disperser_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->atmcomp1 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->atmcomp2 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->atmcomp3 == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->continuum == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->exptime == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        dimmRow         *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "sigmax", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "sigmay", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "fwhm", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, 64.64)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, 64.64)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "expttime", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = dimmObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (!object->sigmax == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->sigmay == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->fwhm == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->ra == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->decl == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->expttime == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        skyp_irRow      *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddF64(md, PS_LIST_TAIL, "sky_bright", 0, NULL, 64.64)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF64(md, PS_LIST_TAIL, "sky_var", 0, NULL, 64.64)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, 64.64)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, 64.64)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "fov_x", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "fov_y", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = skyp_irObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (!object->sky_bright == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->sky_var == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->ra == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->decl == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->fov_x == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->fov_y == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        domeRow         *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "az", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAdd(md, PS_LIST_TAIL, "open", PS_DATA_BOOL, NULL, true)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAdd(md, PS_LIST_TAIL, "light", PS_DATA_BOOL, NULL, true)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAdd(md, PS_LIST_TAIL, "track", PS_DATA_BOOL, NULL, true)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = domeObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (!object->az == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->open == true) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->light == true) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->track == true) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        telescopeRow    *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "guide", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "alt", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF32(md, PS_LIST_TAIL, "az", 0, NULL, 32.32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF64(md, PS_LIST_TAIL, "ra", 0, NULL, 64.64)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddF64(md, PS_LIST_TAIL, "decl", 0, NULL, 64.64)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = telescopeObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->guide, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->alt == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->az == 32.32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->ra == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->decl == 64.64) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        summitExpRow    *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = summitExpObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        pzPendingExpRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = pzPendingExpObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        pzPendingImfileRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "bytes", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "md5sum", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = pzPendingImfileObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->bytes == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->md5sum, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        newExpRow       *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = newExpObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        newImfileRow    *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = newImfileObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        rawDetrendExpRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = rawDetrendExpObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->filter, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        rawScienceExpRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = rawScienceExpObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->filter, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        rawImfileRow    *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = rawImfileObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        p1PendingExpRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = p1PendingExpObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->filter, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p1_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        p2PendingExpRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = p2PendingExpObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->filter, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p1_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p2_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        p2PendingImfileRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = p2PendingImfileObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p1_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p2_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        p2DoneExpRow    *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = p2DoneExpObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->filter, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p1_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p2_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        p2DoneImfileRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "p1_version", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = p2DoneImfileObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p1_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p2_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        p3PendingExpRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "p2_version", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "p3_version", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = p3PendingExpObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->filter, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p2_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->p3_version == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        detRunRow       *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "det_type", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = detRunObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (strncmp(object->det_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        detInputExpRow  *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "camera", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "telescope", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_type", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "imfiles", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "filter", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = detInputExpObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (!object->det_id == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->iteration == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->camera, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->telescope, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_type, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->imfiles == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->filter, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        detProcessedImfileRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = detProcessedImfileObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (!object->det_id == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        detStackedImfileRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = detStackedImfileObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (!object->det_id == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->iteration == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        detNormalizedImfileRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = detNormalizedImfileObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (!object->det_id == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->iteration == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        detMasterFrameRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "comment", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = detMasterFrameObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (!object->det_id == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->iteration == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->comment, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        detMasterImfileRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "uri", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = detMasterImfileObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (!object->det_id == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->uri, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        detResidImfileAnalysisRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "class_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = detResidImfileAnalysisObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (!object->det_id == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->iteration == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->class_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    {
+        psMetadata      *md;
+        detResidExpAnalysisRow *object;
+
+        md = psMetadataAlloc();
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "det_id", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddS32(md, PS_LIST_TAIL, "iteration", 0, NULL, -32)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "exp_id", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "stats", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAddStr(md, PS_LIST_TAIL, "recipe", 0, NULL, "a string")) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+        if (!psMetadataAdd(md, PS_LIST_TAIL, "accept", PS_DATA_BOOL, NULL, true)) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        object = detResidExpAnalysisObjectFromMetadata(md);
+        if (!object) {
+            psFree(md);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(md);
+
+        if (!object->det_id == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->iteration == -32) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->exp_id, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->stats, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (strncmp(object->recipe, "a string", MAX_STRING_LENGTH)) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+        if (!object->accept == true) {
+            psFree(object);
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+    }
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/start/ippdb/tests/pop.c
===================================================================
--- /tags/start/ippdb/tests/pop.c	(revision 12606)
+++ /tags/start/ippdb/tests/pop.c	(revision 12606)
@@ -0,0 +1,667 @@
+#include <pslib.h>
+#include <ippdb.h>
+#include <stdlib.h>
+
+int main ()
+{
+    {
+        psDB            *dbh;
+        psF32           temp01;
+        psF32           humi01;
+        psF32           temp02;
+        psF32           humi02;
+        psF32           temp03;
+        psF32           humi03;
+        psF32           pressure;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!weatherPop(dbh, &temp01, &humi01, &temp02, &humi02, &temp03, &humi03, &pressure)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            filter[256];
+        psF64           trans;
+        psS32           nstars;
+        psF64           ra;
+        psF64           decl;
+        psF32           exptime;
+        psF64           sky_bright;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_transparencyPop(dbh, (char **)&filter, &trans, &nstars, &ra, &decl, &exptime, &sky_bright)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            disperser_id[256];
+        psF32           atmcomp1;
+        psF32           atmcomp2;
+        psF32           atmcomp3;
+        psS32           nstars;
+        psF64           ra;
+        psF64           decl;
+        psF32           exptime;
+        psF64           sky_bright;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_absorptionPop(dbh, (char **)&disperser_id, &atmcomp1, &atmcomp2, &atmcomp3, &nstars, &ra, &decl, &exptime, &sky_bright)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            disperser_id[256];
+        psF32           atmcomp1;
+        psF32           atmcomp2;
+        psF32           atmcomp3;
+        psF32           continuum;
+        psF32           exptime;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_emissionPop(dbh, (char **)&disperser_id, &atmcomp1, &atmcomp2, &atmcomp3, &continuum, &exptime)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psF32           sigmax;
+        psF32           sigmay;
+        psF32           fwhm;
+        psF64           ra;
+        psF64           decl;
+        psF32           expttime;
+        char            telescope_id[256];
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!dimmPop(dbh, &sigmax, &sigmay, &fwhm, &ra, &decl, &expttime, (char **)&telescope_id)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psF64           sky_bright;
+        psF64           sky_var;
+        psF64           ra;
+        psF64           decl;
+        psF32           fov_x;
+        psF32           fov_y;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_irPop(dbh, &sky_bright, &sky_var, &ra, &decl, &fov_x, &fov_y)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psF32           az;
+        bool            open;
+        bool            light;
+        bool            track;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!domePop(dbh, &az, &open, &light, &track)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            guide[256];
+        psF32           alt;
+        psF32           az;
+        psF64           ra;
+        psF64           decl;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!telescopePop(dbh, (char **)&guide, &alt, &az, &ra, &decl)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            exp_id[256];
+        char            camera[256];
+        char            telescope[256];
+        char            exp_type[256];
+        char            uri[256];
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!summitExpPop(dbh, (char **)&exp_id, (char **)&camera, (char **)&telescope, (char **)&exp_type, (char **)&uri)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            exp_id[256];
+        char            camera[256];
+        char            telescope[256];
+        char            exp_type[256];
+        psS32           imfiles;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzPendingExpPop(dbh, (char **)&exp_id, (char **)&camera, (char **)&telescope, (char **)&exp_type, &imfiles)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            exp_id[256];
+        psS32           bytes;
+        char            md5sum[256];
+        char            class[256];
+        char            class_id[256];
+        char            uri[256];
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzPendingImfilePop(dbh, (char **)&exp_id, &bytes, (char **)&md5sum, (char **)&class, (char **)&class_id, (char **)&uri)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            exp_id[256];
+        char            camera[256];
+        char            telescope[256];
+        char            exp_type[256];
+        psS32           imfiles;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!newExpPop(dbh, (char **)&exp_id, (char **)&camera, (char **)&telescope, (char **)&exp_type, &imfiles)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            exp_id[256];
+        char            class[256];
+        char            class_id[256];
+        char            uri[256];
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!newImfilePop(dbh, (char **)&exp_id, (char **)&class, (char **)&class_id, (char **)&uri)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            exp_id[256];
+        char            camera[256];
+        char            telescope[256];
+        char            exp_type[256];
+        psS32           imfiles;
+        char            filter[256];
+        char            stats[256];
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawDetrendExpPop(dbh, (char **)&exp_id, (char **)&camera, (char **)&telescope, (char **)&exp_type, &imfiles, (char **)&filter, (char **)&stats)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            exp_id[256];
+        char            camera[256];
+        char            telescope[256];
+        char            exp_type[256];
+        psS32           imfiles;
+        char            filter[256];
+        char            stats[256];
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawScienceExpPop(dbh, (char **)&exp_id, (char **)&camera, (char **)&telescope, (char **)&exp_type, &imfiles, (char **)&filter, (char **)&stats)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            exp_id[256];
+        char            class_id[256];
+        char            uri[256];
+        char            stats[256];
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawImfilePop(dbh, (char **)&exp_id, (char **)&class_id, (char **)&uri, (char **)&stats)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            exp_id[256];
+        char            camera[256];
+        char            telescope[256];
+        char            exp_type[256];
+        psS32           imfiles;
+        char            filter[256];
+        char            stats[256];
+        char            recipe[256];
+        psS32           p1_version;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p1PendingExpPop(dbh, (char **)&exp_id, (char **)&camera, (char **)&telescope, (char **)&exp_type, &imfiles, (char **)&filter, (char **)&stats, (char **)&recipe, &p1_version)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            exp_id[256];
+        char            camera[256];
+        char            telescope[256];
+        char            exp_type[256];
+        psS32           imfiles;
+        char            filter[256];
+        char            stats[256];
+        char            recipe[256];
+        psS32           p1_version;
+        psS32           p2_version;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2PendingExpPop(dbh, (char **)&exp_id, (char **)&camera, (char **)&telescope, (char **)&exp_type, &imfiles, (char **)&filter, (char **)&stats, (char **)&recipe, &p1_version, &p2_version)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            exp_id[256];
+        char            class_id[256];
+        char            uri[256];
+        char            stats[256];
+        char            recipe[256];
+        psS32           p1_version;
+        psS32           p2_version;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2PendingImfilePop(dbh, (char **)&exp_id, (char **)&class_id, (char **)&uri, (char **)&stats, (char **)&recipe, &p1_version, &p2_version)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            exp_id[256];
+        char            camera[256];
+        char            telescope[256];
+        char            exp_type[256];
+        psS32           imfiles;
+        char            filter[256];
+        char            stats[256];
+        char            recipe[256];
+        psS32           p1_version;
+        psS32           p2_version;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2DoneExpPop(dbh, (char **)&exp_id, (char **)&camera, (char **)&telescope, (char **)&exp_type, &imfiles, (char **)&filter, (char **)&stats, (char **)&recipe, &p1_version, &p2_version)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            exp_id[256];
+        char            class_id[256];
+        char            uri[256];
+        char            stats[256];
+        char            recipe[256];
+        psS32           p1_version;
+        psS32           p2_version;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2DoneImfilePop(dbh, (char **)&exp_id, (char **)&class_id, (char **)&uri, (char **)&stats, (char **)&recipe, &p1_version, &p2_version)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            exp_id[256];
+        char            camera[256];
+        char            exp_type[256];
+        psS32           imfiles;
+        char            filter[256];
+        char            stats[256];
+        char            recipe[256];
+        psS32           p2_version;
+        psS32           p3_version;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p3PendingExpPop(dbh, (char **)&exp_id, (char **)&camera, (char **)&exp_type, &imfiles, (char **)&filter, (char **)&stats, (char **)&recipe, &p2_version, &p3_version)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        char            det_type[256];
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detRunPop(dbh, (char **)&det_type)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psS32           det_id;
+        psS32           iteration;
+        char            exp_id[256];
+        char            camera[256];
+        char            telescope[256];
+        char            exp_type[256];
+        psS32           imfiles;
+        char            filter[256];
+        char            stats[256];
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detInputExpPop(dbh, &det_id, &iteration, (char **)&exp_id, (char **)&camera, (char **)&telescope, (char **)&exp_type, &imfiles, (char **)&filter, (char **)&stats)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psS32           det_id;
+        char            exp_id[256];
+        char            class_id[256];
+        char            uri[256];
+        char            stats[256];
+        char            recipe[256];
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detProcessedImfilePop(dbh, &det_id, (char **)&exp_id, (char **)&class_id, (char **)&uri, (char **)&stats, (char **)&recipe)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psS32           det_id;
+        psS32           iteration;
+        char            class_id[256];
+        char            uri[256];
+        char            stats[256];
+        char            recipe[256];
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detStackedImfilePop(dbh, &det_id, &iteration, (char **)&class_id, (char **)&uri, (char **)&stats, (char **)&recipe)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psS32           det_id;
+        psS32           iteration;
+        char            class_id[256];
+        char            uri[256];
+        char            stats[256];
+        char            recipe[256];
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detNormalizedImfilePop(dbh, &det_id, &iteration, (char **)&class_id, (char **)&uri, (char **)&stats, (char **)&recipe)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psS32           det_id;
+        psS32           iteration;
+        char            comment[256];
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detMasterFramePop(dbh, &det_id, &iteration, (char **)&comment)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psS32           det_id;
+        char            class_id[256];
+        char            uri[256];
+        char            stats[256];
+        char            recipe[256];
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detMasterImfilePop(dbh, &det_id, (char **)&class_id, (char **)&uri, (char **)&stats, (char **)&recipe)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psS32           det_id;
+        psS32           iteration;
+        char            exp_id[256];
+        char            class_id[256];
+        char            stats[256];
+        char            recipe[256];
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detResidImfileAnalysisPop(dbh, &det_id, &iteration, (char **)&exp_id, (char **)&class_id, (char **)&stats, (char **)&recipe)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psS32           det_id;
+        psS32           iteration;
+        char            exp_id[256];
+        char            stats[256];
+        char            recipe[256];
+        bool            accept;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detResidExpAnalysisPop(dbh, &det_id, &iteration, (char **)&exp_id, (char **)&stats, (char **)&recipe, &accept)) { 
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/start/ippdb/tests/popfits.c
===================================================================
--- /tags/start/ippdb/tests/popfits.c	(revision 12606)
+++ /tags/start/ippdb/tests/popfits.c	(revision 12606)
@@ -0,0 +1,818 @@
+#include <pslib.h>
+#include <ippdb.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#define TMP_FILENAME "./blargh"
+
+int main ()
+{
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!weatherPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_transparencyPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_absorptionPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_emissionPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!dimmPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_irPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!domePopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!telescopePopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!summitExpPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzPendingExpPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzPendingImfilePopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!newExpPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!newImfilePopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawDetrendExpPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawScienceExpPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawImfilePopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p1PendingExpPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2PendingExpPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2PendingImfilePopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2DoneExpPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2DoneImfilePopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p3PendingExpPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detRunPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detInputExpPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detProcessedImfilePopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detStackedImfilePopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detNormalizedImfilePopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detMasterFramePopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detMasterImfilePopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detResidImfileAnalysisPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        // allocate a temp
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detResidExpAnalysisPopFits(dbh, fits, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!psFitsClose(fits)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psDBCleanup(dbh);
+    }
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/start/ippdb/tests/popobject.c
===================================================================
--- /tags/start/ippdb/tests/popobject.c	(revision 12606)
+++ /tags/start/ippdb/tests/popobject.c	(revision 12606)
@@ -0,0 +1,566 @@
+#include <pslib.h>
+#include <ippdb.h>
+#include <stdlib.h>
+
+int main ()
+{
+    {
+        psDB            *dbh;
+        weatherRow      *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = weatherPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        skyp_transparencyRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = skyp_transparencyPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        skyp_absorptionRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = skyp_absorptionPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        skyp_emissionRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = skyp_emissionPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        dimmRow         *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = dimmPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        skyp_irRow      *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = skyp_irPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        domeRow         *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = domePopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        telescopeRow    *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = telescopePopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        summitExpRow    *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = summitExpPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        pzPendingExpRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = pzPendingExpPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        pzPendingImfileRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = pzPendingImfilePopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        newExpRow       *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = newExpPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        newImfileRow    *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = newImfilePopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        rawDetrendExpRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = rawDetrendExpPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        rawScienceExpRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = rawScienceExpPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        rawImfileRow    *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = rawImfilePopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        p1PendingExpRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = p1PendingExpPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        p2PendingExpRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = p2PendingExpPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        p2PendingImfileRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = p2PendingImfilePopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        p2DoneExpRow    *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = p2DoneExpPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        p2DoneImfileRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = p2DoneImfilePopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        p3PendingExpRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = p3PendingExpPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        detRunRow       *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = detRunPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        detInputExpRow  *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = detInputExpPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        detProcessedImfileRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = detProcessedImfilePopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        detStackedImfileRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = detStackedImfilePopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        detNormalizedImfileRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = detNormalizedImfilePopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        detMasterFrameRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = detMasterFramePopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        detMasterImfileRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = detMasterImfilePopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        detResidImfileAnalysisRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = detResidImfileAnalysisPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        detResidExpAnalysisRow *object;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        object = detResidExpAnalysisPopObject(dbh);
+        if (!object) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(object);
+        psDBCleanup(dbh);
+    }
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/start/ippdb/tests/selectrowsfits.c
===================================================================
--- /tags/start/ippdb/tests/selectrowsfits.c	(revision 12606)
+++ /tags/start/ippdb/tests/selectrowsfits.c	(revision 12606)
@@ -0,0 +1,692 @@
+#include <pslib.h>
+#include <ippdb.h>
+#include <stdlib.h>
+
+#define TMP_FILENAME "./blargh"
+
+int main ()
+{
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!weatherSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_transparencySelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_absorptionSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_emissionSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!dimmSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!skyp_irSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!domeSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!telescopeSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!summitExpSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzPendingExpSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!pzPendingImfileSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!newExpSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!newImfileSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawDetrendExpSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawScienceExpSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!rawImfileSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p1PendingExpSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2PendingExpSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2PendingImfileSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2DoneExpSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p2DoneImfileSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!p3PendingExpSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detRunSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detInputExpSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detProcessedImfileSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detStackedImfileSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detNormalizedImfileSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detMasterFrameSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detMasterImfileSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detResidImfileAnalysisSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    {
+        psDB            *dbh;
+        psFits          *fits;
+
+        dbh = psDBInit("localhost", "test", NULL, "test");
+        if (!dbh) {
+            exit(EXIT_FAILURE);
+        }
+
+        fits = psFitsOpen(TMP_FILENAME, "w");
+        if (!fits) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!detResidExpAnalysisSelectRowsFits(dbh, fits, NULL, 1)) {
+            exit(EXIT_FAILURE);
+        }
+
+        psFree(fits);
+        psDBCleanup(dbh);
+    }
+
+    exit(EXIT_SUCCESS);
+}
Index: /tags/start/ippdb/tests/testsuite.at
===================================================================
--- /tags/start/ippdb/tests/testsuite.at	(revision 12606)
+++ /tags/start/ippdb/tests/testsuite.at	(revision 12606)
@@ -0,0 +1,158 @@
+m4_version_prereq([2.59])
+
+AT_INIT
+
+###
+AT_SETUP([Alloc()])
+AT_KEYWORDS([Alloc])
+
+AT_CHECK([alloc])
+
+AT_CLEANUP
+
+###
+AT_SETUP([Init()])
+AT_KEYWORDS([Init])
+
+AT_CHECK([init])
+
+AT_CLEANUP
+
+###
+AT_SETUP([Cleanup()])
+AT_KEYWORDS([Cleanup])
+
+AT_CHECK([cleanup])
+
+AT_CLEANUP
+
+###
+AT_SETUP([CreateTable()])
+AT_KEYWORDS([CreateTable])
+
+# make sure the table is not there.
+AT_CHECK([dbcleanup])
+AT_CHECK([createtable])
+AT_CHECK([dbcleanup])
+
+AT_CLEANUP
+
+###
+AT_SETUP([DropTable()])
+AT_KEYWORDS([DropTable])
+
+# make sure the table is not there.
+AT_CHECK([dbsetup])
+AT_CHECK([droptable])
+AT_CHECK([dbcleanup])
+
+AT_CLEANUP
+
+###
+AT_SETUP([Insert()])
+AT_KEYWORDS([Insert])
+
+AT_CHECK([dbsetup])
+AT_CHECK([insert])
+AT_CHECK([dbcleanup])
+
+AT_CLEANUP
+
+###
+AT_SETUP([Pop()])
+AT_KEYWORDS([Pop])
+
+AT_CHECK([dbsetup])
+# run insert so there is a row in the table
+AT_CHECK([insert])
+AT_CHECK([pop])
+AT_CHECK([dbcleanup])
+
+AT_CLEANUP
+
+###
+AT_SETUP([InsertObject()])
+AT_KEYWORDS([InsertObject])
+
+AT_CHECK([dbsetup])
+AT_CHECK([insertobject])
+AT_CHECK([dbcleanup])
+
+AT_CLEANUP
+
+###
+AT_SETUP([PopObject()])
+AT_KEYWORDS([PopObject])
+
+AT_CHECK([dbsetup])
+# run insert so there is a row in the table
+AT_CHECK([insert])
+AT_CHECK([popobject])
+AT_CHECK([dbcleanup])
+
+AT_CLEANUP
+
+###
+AT_SETUP([InsertFits()])
+AT_KEYWORDS([InsertFits])
+
+AT_CHECK([dbsetup])
+# run insert so there is a row in the table
+AT_CHECK([insert])
+# run popfis so there is afits file to read
+AT_CHECK([popfits])
+AT_CHECK([insertfits])
+AT_CHECK([dbcleanup])
+if [ test -f "blargh" ] ; then
+    rm -f "blargh"
+fi
+
+AT_CLEANUP
+
+###
+AT_SETUP([PopFits()])
+AT_KEYWORDS([PopFits])
+
+AT_CHECK([dbsetup])
+# run insert so there is a row in the table
+AT_CHECK([insert])
+AT_CHECK([popfits])
+AT_CHECK([dbcleanup])
+if [ test -f "blargh" ] ; then
+    rm -f "blargh"
+fi
+
+AT_CLEANUP
+
+###
+AT_SETUP([SelectRowsFits()])
+AT_KEYWORDS([SelectRowsFits])
+
+AT_CHECK([dbsetup])
+# run insert so there is a row in the table
+AT_CHECK([insert])
+AT_CHECK([selectrowsfits])
+AT_CHECK([dbcleanup])
+if [ test -f "blargh" ] ; then
+    rm -f "blargh"
+fi
+
+AT_CLEANUP
+
+###
+AT_SETUP([MetadataFromObject()])
+AT_KEYWORDS([MetadataFromObject])
+
+AT_CHECK([metadatafromobject])
+
+AT_CLEANUP
+
+###
+AT_SETUP([ObjectFromMetadata()])
+AT_KEYWORDS([ObjectFromMetadata])
+
+AT_CHECK([objectfrommetadata])
+
+AT_CLEANUP
+
+###
Index: /tags/start/psModules/AUTHORS
===================================================================
--- /tags/start/psModules/AUTHORS	(revision 12606)
+++ /tags/start/psModules/AUTHORS	(revision 12606)
@@ -0,0 +1,1 @@
+Maui High Performance Computing Center, University of Hawai'i
Index: /tags/start/psModules/COPYING
===================================================================
--- /tags/start/psModules/COPYING	(revision 12606)
+++ /tags/start/psModules/COPYING	(revision 12606)
@@ -0,0 +1,6 @@
+(C) 2004 University of Hawai'i
+
+Permission to copy/distribute to be governed by:
+    Institute for Astronomy
+    2680 Woodlawn Drive
+    Honolulu, HI 96822-1897
Index: /tags/start/psModules/ChangeLog
===================================================================
--- /tags/start/psModules/ChangeLog	(revision 12606)
+++ /tags/start/psModules/ChangeLog	(revision 12606)
@@ -0,0 +1,1 @@
+ 
Index: /tags/start/psModules/INSTALL
===================================================================
--- /tags/start/psModules/INSTALL	(revision 12606)
+++ /tags/start/psModules/INSTALL	(revision 12606)
@@ -0,0 +1,167 @@
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+   The file `configure.in' is used to create `configure' by a program
+called `autoconf'.  You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes a while.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Type `make install' to install the programs and any data files and
+     documentation.
+
+  4. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  You can give `configure'
+initial values for variables by setting them in the environment.  Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+     CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory.  After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+   By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on.  Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+     CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+   If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+     Use and save the results of the tests in FILE instead of
+     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
+     debugging `configure'.
+
+`--help'
+     Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--version'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
+
Index: /tags/start/psModules/Makefile.am
===================================================================
--- /tags/start/psModules/Makefile.am	(revision 12606)
+++ /tags/start/psModules/Makefile.am	(revision 12606)
@@ -0,0 +1,3 @@
+AUTOMAKE_OPTIONS = foreign 1.4
+
+SUBDIRS = src
Index: /tags/start/psModules/Makefile.cvs
===================================================================
--- /tags/start/psModules/Makefile.cvs	(revision 12606)
+++ /tags/start/psModules/Makefile.cvs	(revision 12606)
@@ -0,0 +1,8 @@
+default: all
+
+all:
+	aclocal
+	autoheader
+	automake
+	autoconf
+
Index: /tags/start/psModules/NEWS
===================================================================
--- /tags/start/psModules/NEWS	(revision 12606)
+++ /tags/start/psModules/NEWS	(revision 12606)
@@ -0,0 +1,1 @@
+ 
Index: /tags/start/psModules/README
===================================================================
--- /tags/start/psModules/README	(revision 12606)
+++ /tags/start/psModules/README	(revision 12606)
@@ -0,0 +1,1 @@
+
Index: /tags/start/psModules/TODO
===================================================================
--- /tags/start/psModules/TODO	(revision 12606)
+++ /tags/start/psModules/TODO	(revision 12606)
@@ -0,0 +1,1 @@
+ 
Index: /tags/start/psModules/config.guess
===================================================================
--- /tags/start/psModules/config.guess	(revision 12606)
+++ /tags/start/psModules/config.guess	(revision 12606)
@@ -0,0 +1,1411 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2003-06-17'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+## for Red Hat Linux
+if test -f /etc/redhat-release ; then
+    VENDOR=redhat ;
+else
+    VENDOR= ;
+fi
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE_ARCH}" in
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep __ELF__ >/dev/null
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+	        os=netbsd
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit 0 ;;
+    amiga:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    arc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    hp300:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mac68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    macppc:OpenBSD:*:*)
+	echo powerpc-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme88k:OpenBSD:*:*)
+	echo m88k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvmeppc:OpenBSD:*:*)
+	echo powerpc-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    pmax:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    sgi:OpenBSD:*:*)
+	echo mipseb-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    sun3:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    wgrisc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    *:OpenBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    alpha:OSF1:*:*)
+	if test $UNAME_RELEASE = "V4.0"; then
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+	fi
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	exit 0 ;;
+    Alpha*:OpenVMS:*:*)
+	echo alpha-hp-vms
+	exit 0 ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit 0 ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit 0 ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit 0;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit 0 ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit 0 ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit 0 ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit 0;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit 0;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit 0 ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit 0 ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit 0 ;;
+    DRS?6000:UNIX_SV:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7 && exit 0 ;;
+	esac ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    i86pc:SunOS:5.*:*)
+	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit 0 ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit 0 ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit 0 ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit 0 ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit 0 ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit 0 ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit 0 ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit 0 ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit 0 ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c \
+	  && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+	  && exit 0
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit 0 ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit 0 ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit 0 ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit 0 ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit 0 ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit 0 ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit 0 ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+ 	exit 0 ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit 0 ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit 0 ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit 0 ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit 0 ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
+	exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit 0 ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit 0 ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		$CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+		echo rs6000-ibm-aix3.2.5
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit 0 ;;
+    *:AIX:*:[45])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit 0 ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit 0 ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit 0 ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit 0 ;;                           # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit 0 ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit 0 ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit 0 ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit 0 ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+              	{
+              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+              	case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+              	    switch (bits)
+              		{
+              		case 64: puts ("hppa2.0w"); break;
+              		case 32: puts ("hppa2.0n"); break;
+              		default: puts ("hppa2.0"); break;
+              		} break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+              	    puts ("hppa2.0"); break;
+              #endif
+              	default: puts ("hppa1.0"); break;
+              	}
+                  exit (0);
+              }
+EOF
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    # avoid double evaluation of $set_cc_for_build
+	    test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+	echo unknown-hitachi-hiuxwe2
+	exit 0 ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit 0 ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit 0 ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit 0 ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit 0 ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit 0 ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit 0 ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit 0 ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+        exit 0 ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+        exit 0 ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+        exit 0 ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+        exit 0 ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+        exit 0 ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    *:UNICOS/mp:*:*)
+	echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' 
+	exit 0 ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit 0 ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:FreeBSD:*:*|*:GNU/FreeBSD:*:*)
+	# Determine whether the default compiler uses glibc.
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <features.h>
+	#if __GLIBC__ >= 2
+	LIBC=gnu
+	#else
+	LIBC=
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+	echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+	exit 0 ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit 0 ;;
+    i*:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit 0 ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit 0 ;;
+    x86:Interix*:[34]*)
+	echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+	exit 0 ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit 0 ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i586-pc-interix
+	exit 0 ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit 0 ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit 0 ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    *:GNU:*:*)
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit 0 ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit 0 ;;
+    arm*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    cris:Linux:*:*)
+	echo cris-axis-linux-gnu
+	exit 0 ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-${VENDOR:-unknown}-linux-gnu
+	exit 0 ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    mips:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips
+	#undef mipsel
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mipsel
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+	test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+	;;
+    mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips64
+	#undef mips64el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mips64el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips64
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+	test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+	;;
+    ppc:Linux:*:*)
+	echo powerpc-${VENDOR:-unknown}-linux-gnu
+	exit 0 ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-${VENDOR:-unknown}-linux-gnu
+	exit 0 ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+	objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	exit 0 ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
+	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
+	  *)    echo hppa-unknown-linux-gnu ;;
+	esac
+	exit 0 ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit 0 ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-${VENDOR:-ibm}-linux-gnu
+	exit 0 ;;
+    sh64*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    x86_64:Linux:*:*)
+	echo x86_64-${VENDOR:-unknown}-linux-gnu
+	exit 0 ;;
+    i*86:Linux:*:*)
+	# The BFD linker knows what the default object file format is, so
+	# first see if it will tell us. cd to the root directory to prevent
+	# problems with other programs or directories called `ld' in the path.
+	# Set LC_ALL=C to ensure ld outputs messages in English.
+	ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+			 | sed -ne '/supported targets:/!d
+				    s/[ 	][ 	]*/ /g
+				    s/.*supported targets: *//
+				    s/ .*//
+				    p'`
+        case "$ld_supported_targets" in
+	  elf32-i386)
+		TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+		;;
+	  a.out-i386-linux)
+		echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+		exit 0 ;;
+	  coff-i386)
+		echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+		exit 0 ;;
+	  "")
+		# Either a pre-BFD a.out linker (linux-gnuoldld) or
+		# one that does not give us useful --help.
+		echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+		exit 0 ;;
+	esac
+	# Determine whether the default compiler is a.out or elf
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <features.h>
+	#ifdef __ELF__
+	# ifdef __GLIBC__
+	#  if __GLIBC__ >= 2
+	LIBC=gnu
+	#  else
+	LIBC=gnulibc1
+	#  endif
+	# else
+	LIBC=gnulibc1
+	# endif
+	#else
+	#ifdef __INTEL_COMPILER
+	LIBC=gnu
+	#else
+	LIBC=gnuaout
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+	test x"${LIBC}" != x && echo "${UNAME_MACHINE}-${VENDOR:-pc}-linux-${LIBC}" && exit 0
+	test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+	;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit 0 ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit 0 ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit 0 ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit 0 ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit 0 ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit 0 ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit 0 ;;
+    i*86:*:5:[78]*)
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit 0 ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit 0 ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+	echo i386-pc-msdosdjgpp
+        exit 0 ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit 0 ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit 0 ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit 0 ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit 0 ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit 0 ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit 0 ;;
+    M68*:*:R3V[567]*:*)
+	test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4 && exit 0 ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit 0 ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit 0 ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit 0 ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit 0 ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit 0 ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit 0 ;;
+    *:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo hppa1.1-stratus-vos
+	exit 0 ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit 0 ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit 0 ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+	        echo mips-nec-sysv${UNAME_RELEASE}
+	else
+	        echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+        exit 0 ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit 0 ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit 0 ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit 0 ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit 0 ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit 0 ;;
+    *:Darwin:*:*)
+	case `uname -p` in
+	    *86) UNAME_PROCESSOR=i686 ;;
+	    powerpc) UNAME_PROCESSOR=powerpc ;;
+	esac
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit 0 ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = "x86"; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit 0 ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit 0 ;;
+    NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit 0 ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit 0 ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit 0 ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit 0 ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit 0 ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit 0 ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit 0 ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit 0 ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit 0 ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit 0 ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit 0 ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+	exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+	  ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit 0 ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit 0 ;;
+    c34*)
+	echo c34-convex-bsd
+	exit 0 ;;
+    c38*)
+	echo c38-convex-bsd
+	exit 0 ;;
+    c4*)
+	echo c4-convex-bsd
+	exit 0 ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+    ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: /tags/start/psModules/config.sub
===================================================================
--- /tags/start/psModules/config.sub	(revision 12606)
+++ /tags/start/psModules/config.sub	(revision 12606)
@@ -0,0 +1,1500 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2003-06-18'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit 0;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis)
+		os=
+		basic_machine=$1
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+ 	-chorusrdb)
+ 		os=-chorusrdb
+		basic_machine=$1
+ 		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	1750a | 580 \
+	| a29k \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+	| c4x | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| fr30 | frv \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| i370 | i860 | i960 | ia64 \
+	| ip2k \
+	| m32r | m68000 | m68k | m88k | mcore \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64vr | mips64vrel \
+	| mips64orion | mips64orionel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| msp430 \
+	| ns16k | ns32k \
+	| openrisc | or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+	| pyramid \
+	| s390 | s390x \
+	| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
+	| strongarm \
+	| tahoe | thumb | tic4x | tic80 | tron \
+	| v850 | v850e \
+	| we32k \
+	| x86 | xscale | xstormy16 | xtensa \
+	| z8k)
+		basic_machine=$basic_machine-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12)
+		# Motorola 68HC11/12.
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* \
+	| bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+	| clipper-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| i*86-* | i860-* | i960-* | ia64-* \
+	| ip2k-* \
+	| m32r-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | mcore-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipstx39-* | mipstx39el-* \
+	| msp430-* \
+	| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+	| pyramid-* \
+	| romp-* | rs6000-* \
+	| s390-* | s390x-* \
+	| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+	| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+	| tahoe-* | thumb-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tron-* \
+	| v850-* | v850e-* | vax-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+	| xtensa-* \
+	| ymp-* \
+	| z8k-*)
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	mmix*)
+		basic_machine=mmix-knuth
+		os=-mmixware
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	nv1)
+		basic_machine=nv1-cray
+		os=-unicosmp
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	or32 | or32-*)
+		basic_machine=or32-unknown
+		os=-coff
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc)	basic_machine=powerpc-unknown
+		;;
+	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+		;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparclite-wrs | simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tic54x | c54x*)
+		basic_machine=tic54x-unknown
+		os=-coff
+		;;
+	tic55x | c55x*)
+		basic_machine=tic55x-unknown
+		os=-coff
+		;;
+	tic6x | c6x*)
+		basic_machine=tic6x-unknown
+		os=-coff
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparc | sparcv9 | sparcv9b)
+		basic_machine=sparc-sun
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+	      | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* \
+	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2 )
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-kaos*)
+		os=-kaos
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+	c4x-* | tic4x-*)
+		os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-ibm)
+		os=-aix
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+			-vos*)
+				vendor=stratus
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: /tags/start/psModules/configure.in
===================================================================
--- /tags/start/psModules/configure.in	(revision 12606)
+++ /tags/start/psModules/configure.in	(revision 12606)
@@ -0,0 +1,37 @@
+AC_INIT(configure.in)
+
+AM_CONFIG_HEADER(src/config.h)
+AM_INIT_AUTOMAKE(psModule, 0.1)
+
+AC_LANG_C
+AC_PROG_CC
+
+CFLAGS="${CFLAGS=} -g2 -Wall -std=c99 -D_GNU_SOURCE"
+
+AC_ARG_WITH(psLib,
+[  --with-psLib            Specify location of psLib files],[
+CFLAGS="$CFLAGS -I$withval/include" 
+LDFLAGS="$LDFLAGS -L$withval/lib"
+psLib_prefix=$withval 
+])
+
+AC_ARG_WITH(sla,
+[  --with-sla              Specify location of SLA.],[
+CFLAGS="$CFLAGS -I$withval/include" 
+SLA_LINK = `$withval/bin/sla_link`
+LDFLAGS="$LDFLAGS $SLA_LINK"
+psLib_prefix=$withval 
+])
+
+AC_ARG_WITH(psLib-includes, [  --with-psLib-includes   Specify location of psLib header files], \
+    CFLAGS="$CFLAGS -I$withval")
+
+AC_ARG_WITH(psLib-lib, [  --with-psLib-lib        Specify location of psLib library file], \
+    LDFLAGS="$LDFLAGS -L$withval")
+
+
+AC_PROG_INSTALL
+
+AM_PROG_LIBTOOL
+
+AC_OUTPUT(Makefile src/Makefile)
Index: /tags/start/psModules/depcomp
===================================================================
--- /tags/start/psModules/depcomp	(revision 12606)
+++ /tags/start/psModules/depcomp	(revision 12606)
@@ -0,0 +1,441 @@
+#! /bin/sh
+
+# depcomp - compile a program generating dependencies as side-effects
+# Copyright 1999, 2000 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+  echo "depcomp: Variables source, object and depmode must be set" 1>&2
+  exit 1
+fi
+# `libtool' can also be set to `yes' or `no'.
+
+depfile=${depfile-`echo "$object" | sed 's,\([^/]*\)$,.deps/\1,;s/\.\([^.]*\)$/.P\1/'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags.  We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write.  Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+  # HP compiler uses -M and no extra arg.
+  gccflag=-M
+  depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+   # This is just like dashmstdout with a different argument.
+   dashmflag=-xM
+   depmode=dashmstdout
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff.  Hmm.
+  "$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  mv "$tmpdepfile" "$depfile"
+  ;;
+
+gcc)
+## There are various ways to get dependency output from gcc.  Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+##   up in a subdir.  Having to rename by hand is ugly.
+##   (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+##   -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+##   than renaming).
+  if test -z "$gccflag"; then
+    gccflag=-MD,
+  fi
+  "$@" -Wp,"$gccflag$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+  sed -e 's/^[^:]*: / /' \
+      -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header).  We avoid this by adding
+## dummy dependencies for each header file.  Too bad gcc doesn't do
+## this for us directly.
+  tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'.  On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+sgi)
+  if test "$libtool" = yes; then
+    "$@" "-Wp,-MDupdate,$tmpdepfile"
+  else
+    "$@" -MDupdate "$tmpdepfile"
+  fi
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+
+  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
+    echo "$object : \\" > "$depfile"
+
+    # Clip off the initial element (the dependent).  Don't try to be
+    # clever and replace this with sed code, as IRIX sed won't handle
+    # lines with more than a fixed number of characters (4096 in
+    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
+    # the IRIX cc adds comments like `#:fec' to the end of the
+    # dependency line.
+    tr ' ' '
+' < "$tmpdepfile" \
+    | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+    tr '
+' ' ' >> $depfile
+    echo >> $depfile
+
+    # The second pass generates a dummy entry for each header file.
+    tr ' ' '
+' < "$tmpdepfile" \
+   | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+   >> $depfile
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+aix)
+  # The C for AIX Compiler uses -M and outputs the dependencies
+  # in a .u file.  This file always lives in the current directory.
+  # Also, the AIX compiler puts `$object:' at the start of each line;
+  # $object doesn't have directory information.
+  stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'`
+  tmpdepfile="$stripped.u"
+  outname="$stripped.o"
+  if test "$libtool" = yes; then
+    "$@" -Wc,-M
+  else
+    "$@" -M
+  fi
+
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+
+  if test -f "$tmpdepfile"; then
+    # Each line is of the form `foo.o: dependent.h'.
+    # Do two passes, one to just change these to
+    # `$object: dependent.h' and one to simply `dependent.h:'.
+    sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
+    sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+icc)
+  # Must come before tru64.
+
+  # Intel's C compiler understands `-MD -MF file'.  However
+  #    icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+  # will fill foo.d with something like
+  #    foo.o: sub/foo.c
+  #    foo.o: sub/foo.h
+  # which is wrong.  We want:
+  #    sub/foo.o: sub/foo.c
+  #    sub/foo.o: sub/foo.h
+  #    sub/foo.c:
+  #    sub/foo.h:
+
+  "$@" -MD -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each line is of the form `foo.o: dependent.h'.
+  # Do two passes, one to just change these to
+  # `$object: dependent.h' and one to simply `dependent.h:'.
+  sed -e "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+  sed -e "s,^[^:]*: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+tru64)
+   # The Tru64 AIX compiler uses -MD to generate dependencies as a side
+   # effect.  `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+   # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put 
+   # dependencies in `foo.d' instead, so we check for that too.
+   # Subdirectories are respected.
+
+   tmpdepfile1="$object.d"
+   tmpdepfile2=`echo "$object" | sed -e 's/.o$/.d/'` 
+   if test "$libtool" = yes; then
+      "$@" -Wc,-MD
+   else
+      "$@" -MD
+   fi
+
+   stat=$?
+   if test $stat -eq 0; then :
+   else
+      rm -f "$tmpdepfile1" "$tmpdepfile2"
+      exit $stat
+   fi
+
+   if test -f "$tmpdepfile1"; then
+      tmpdepfile="$tmpdepfile1"
+   else
+      tmpdepfile="$tmpdepfile2"
+   fi
+   if test -f "$tmpdepfile"; then
+      sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+      # That's a space and a tab in the [].
+      sed -e 's,^.*\.[a-z]*:[ 	]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+   else
+      echo "#dummy" > "$depfile"
+   fi
+   rm -f "$tmpdepfile"
+   ;;
+
+#nosideeffect)
+  # This comment above is used by automake to tell side-effect
+  # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the proprocessed file to stdout, regardless of -o,
+  # because we must use -o when running libtool.
+  test -z "$dashmflag" && dashmflag=-M
+  ( IFS=" "
+    case " $* " in
+    *" --mode=compile "*) # this is libtool, let us make it quiet
+      for arg
+      do # cycle over the arguments
+        case "$arg" in
+	"--mode=compile")
+	  # insert --quiet before "--mode=compile"
+	  set fnord "$@" --quiet
+	  shift # fnord
+	  ;;
+	esac
+	set fnord "$@" "$arg"
+	shift # fnord
+	shift # "$arg"
+      done
+      ;;
+    esac
+    "$@" $dashmflag | sed 's:^[^:]*\:[ 	]*:'"$object"'\: :' > "$tmpdepfile"
+  ) &
+  proc=$!
+  "$@"
+  stat=$?
+  wait "$proc"
+  if test "$stat" != 0; then exit $stat; fi
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+dashXmstdout)
+  # This case only exists to satisfy depend.m4.  It is never actually
+  # run, as this mode is specially recognized in the preamble.
+  exit 1
+  ;;
+
+makedepend)
+  # X makedepend
+  (
+    shift
+    cleared=no
+    for arg in "$@"; do
+      case $cleared in no)
+        set ""; shift
+	cleared=yes
+      esac
+      case "$arg" in
+        -D*|-I*)
+	  set fnord "$@" "$arg"; shift;;
+	-*)
+	  ;;
+	*)
+	  set fnord "$@" "$arg"; shift;;
+      esac
+    done
+    obj_suffix="`echo $object | sed 's/^.*\././'`"
+    touch "$tmpdepfile"
+    ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@"
+  ) &
+  proc=$!
+  "$@"
+  stat=$?
+  wait "$proc"
+  if test "$stat" != 0; then exit $stat; fi
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  tail +3 "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile" "$tmpdepfile".bak
+  ;;
+
+cpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the proprocessed file to stdout, regardless of -o,
+  # because we must use -o when running libtool.
+  ( IFS=" "
+    case " $* " in
+    *" --mode=compile "*)
+      for arg
+      do # cycle over the arguments
+        case $arg in
+	"--mode=compile")
+	  # insert --quiet before "--mode=compile"
+	  set fnord "$@" --quiet
+	  shift # fnord
+	  ;;
+	esac
+	set fnord "$@" "$arg"
+	shift # fnord
+	shift # "$arg"
+      done
+      ;;
+    esac
+    "$@" -E |
+    sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+    sed '$ s: \\$::' > "$tmpdepfile"
+  ) &
+  proc=$!
+  "$@"
+  stat=$?
+  wait "$proc"
+  if test "$stat" != 0; then exit $stat; fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  cat < "$tmpdepfile" >> "$depfile"
+  sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvisualcpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the proprocessed file to stdout, regardless of -o,
+  # because we must use -o when running libtool.
+  ( IFS=" "
+    case " $* " in
+    *" --mode=compile "*)
+      for arg
+      do # cycle over the arguments
+        case $arg in
+	"--mode=compile")
+	  # insert --quiet before "--mode=compile"
+	  set fnord "$@" --quiet
+	  shift # fnord
+	  ;;
+	esac
+	set fnord "$@" "$arg"
+	shift # fnord
+	shift # "$arg"
+      done
+      ;;
+    esac
+    "$@" -E |
+    sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
+  ) &
+  proc=$!
+  "$@"
+  stat=$?
+  wait "$proc"
+  if test "$stat" != 0; then exit $stat; fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::	\1 \\:p' >> "$depfile"
+  echo "	" >> "$depfile"
+  . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+none)
+  exec "$@"
+  ;;
+
+*)
+  echo "Unknown depmode $depmode" 1>&2
+  exit 1
+  ;;
+esac
+
+exit 0
Index: /tags/start/psModules/install-sh
===================================================================
--- /tags/start/psModules/install-sh	(revision 12606)
+++ /tags/start/psModules/install-sh	(revision 12606)
@@ -0,0 +1,276 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd=$cpprog
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd=$stripprog
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "$0: no input file specified" >&2
+	exit 1
+else
+	:
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+
+	if [ -d "$dst" ]; then
+		instcmd=:
+		chmodcmd=""
+	else
+		instcmd=$mkdirprog
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+	if [ -f "$src" ] || [ -d "$src" ]
+	then
+		:
+	else
+		echo "$0: $src does not exist" >&2
+		exit 1
+	fi
+
+	if [ x"$dst" = x ]
+	then
+		echo "$0: no destination specified" >&2
+		exit 1
+	else
+		:
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d "$dst" ]
+	then
+		dst=$dst/`basename "$src"`
+	else
+		:
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+	'
+IFS="${IFS-$defaultIFS}"
+
+oIFS=$IFS
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS=$oIFS
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp=$pathcomp$1
+	shift
+
+	if [ ! -d "$pathcomp" ] ;
+        then
+		$mkdirprog "$pathcomp"
+	else
+		:
+	fi
+
+	pathcomp=$pathcomp/
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd "$dst" &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ]
+	then
+		dstfile=`basename "$dst"`
+	else
+		dstfile=`basename "$dst" $transformbasename |
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ]
+	then
+		dstfile=`basename "$dst"`
+	else
+		:
+	fi
+
+# Make a couple of temp file names in the proper directory.
+
+	dsttmp=$dstdir/#inst.$$#
+	rmtmp=$dstdir/#rm.$$#
+
+# Trap to clean up temp files at exit.
+
+	trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
+	trap '(exit $?); exit' 1 2 13 15
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd "$src" "$dsttmp" &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
+
+# Now remove or move aside any old file at destination location.  We try this
+# two ways since rm can't unlink itself on some systems and the destination
+# file might be busy for other reasons.  In this case, the final cleanup
+# might fail but the new file should still install successfully.
+
+{
+	if [ -f "$dstdir/$dstfile" ]
+	then
+		$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
+		$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
+		{
+		  echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
+		  (exit 1); exit
+		}
+	else
+		:
+	fi
+} &&
+
+# Now rename the file to the real destination.
+
+	$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
+
+fi &&
+
+# The final little trick to "correctly" pass the exit status to the exit trap.
+
+{
+	(exit 0); exit
+}
Index: /tags/start/psModules/ltmain.sh
===================================================================
--- /tags/start/psModules/ltmain.sh	(revision 12606)
+++ /tags/start/psModules/ltmain.sh	(revision 12606)
@@ -0,0 +1,6343 @@
+# ltmain.sh - Provide generalized library-building support services.
+# NOTE: Changing this file will not affect anything until you rerun configure.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003
+# Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Check that we have a working $echo.
+if test "X$1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X$1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+  # Yippee, $echo works!
+  :
+else
+  # Restart under the correct shell, and then maybe $echo will work.
+  exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+$*
+EOF
+  exit 0
+fi
+
+# The name of this program.
+progname=`$echo "$0" | ${SED} 's%^.*/%%'`
+modename="$progname"
+
+# Constants.
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.5a
+TIMESTAMP=" (1.1240 2003/06/26 06:55:19)"
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+# test EBCDIC or ASCII
+case `echo A|tr A '\301'` in
+ A) # EBCDIC based system
+  SP2NL="tr '\100' '\n'"
+  NL2SP="tr '\r\n' '\100\100'"
+  ;;
+ *) # Assume ASCII based system
+  SP2NL="tr '\040' '\012'"
+  NL2SP="tr '\015\012' '\040\040'"
+  ;;
+esac
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+# We save the old values to restore during execute mode.
+if test "${LC_ALL+set}" = set; then
+  save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
+fi
+if test "${LANG+set}" = set; then
+  save_LANG="$LANG"; LANG=C; export LANG
+fi
+
+# Make sure IFS has a sensible default
+: ${IFS=" 	"}
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+  $echo "$modename: not configured to build any kind of library" 1>&2
+  $echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
+  exit 1
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+
+#####################################
+# Shell function definitions:
+# This seems to be the best place for them
+
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+win32_libid () {
+  win32_libid_type="unknown"
+  win32_fileres=`file -L $1 2>/dev/null`
+  case $win32_fileres in
+  *ar\ archive\ import\ library*) # definitely import
+    win32_libid_type="x86 archive import"
+    ;;
+  *ar\ archive*) # could be an import, or static
+    if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \
+      grep -E 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
+      win32_nmres=`eval $NM -f posix -A $1 | \
+	sed -n -e '1,100{/ I /{x;/import/!{s/^/import/;h;p;};x;};}'`
+      if test "X$win32_nmres" = "Ximport" ; then
+        win32_libid_type="x86 archive import"
+      else
+        win32_libid_type="x86 archive static"
+      fi
+    fi
+    ;;
+  *DLL*) 
+    win32_libid_type="x86 DLL"
+    ;;
+  *executable*) # but shell scripts are "executable" too...
+    case $win32_fileres in
+    *MS\ Windows\ PE\ Intel*)
+      win32_libid_type="x86 DLL"
+      ;;
+    esac
+    ;;
+  esac
+  $echo $win32_libid_type
+}
+
+# End of Shell function definitions
+#####################################
+
+# Parse our command line options once, thoroughly.
+while test "$#" -gt 0
+do
+  arg="$1"
+  shift
+
+  case $arg in
+  -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) optarg= ;;
+  esac
+
+  # If the previous option needs an argument, assign it.
+  if test -n "$prev"; then
+    case $prev in
+    execute_dlfiles)
+      execute_dlfiles="$execute_dlfiles $arg"
+      ;;
+    tag)
+      tagname="$arg"
+
+      # Check whether tagname contains only valid characters
+      case $tagname in
+      *[!-_A-Za-z0-9,/]*)
+	$echo "$progname: invalid tag name: $tagname" 1>&2
+	exit 1
+	;;
+      esac
+
+      case $tagname in
+      CC)
+	# Don't test for the "default" C tag, as we know, it's there, but
+	# not specially marked.
+	;;
+      *)
+	if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$0" > /dev/null; then
+	  taglist="$taglist $tagname"
+	  # Evaluate the configuration.
+	  eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $0`"
+	else
+	  $echo "$progname: ignoring unknown tag $tagname" 1>&2
+	fi
+	;;
+      esac
+      ;;
+    *)
+      eval "$prev=\$arg"
+      ;;
+    esac
+
+    prev=
+    prevopt=
+    continue
+  fi
+
+  # Have we seen a non-optional argument yet?
+  case $arg in
+  --help)
+    show_help=yes
+    ;;
+
+  --version)
+    $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
+    $echo
+    $echo "Copyright (C) 2003  Free Software Foundation, Inc."
+    $echo "This is free software; see the source for copying conditions.  There is NO"
+    $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+    exit 0
+    ;;
+
+  --config)
+    ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0
+    # Now print the configurations for the tags.
+    for tagname in $taglist; do
+      ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$0"
+    done
+    exit 0
+    ;;
+
+  --debug)
+    $echo "$progname: enabling shell trace mode"
+    set -x
+    ;;
+
+  --dry-run | -n)
+    run=:
+    ;;
+
+  --features)
+    $echo "host: $host"
+    if test "$build_libtool_libs" = yes; then
+      $echo "enable shared libraries"
+    else
+      $echo "disable shared libraries"
+    fi
+    if test "$build_old_libs" = yes; then
+      $echo "enable static libraries"
+    else
+      $echo "disable static libraries"
+    fi
+    exit 0
+    ;;
+
+  --finish) mode="finish" ;;
+
+  --mode) prevopt="--mode" prev=mode ;;
+  --mode=*) mode="$optarg" ;;
+
+  --preserve-dup-deps) duplicate_deps="yes" ;;
+
+  --quiet | --silent)
+    show=:
+    ;;
+
+  --tag) prevopt="--tag" prev=tag ;;
+  --tag=*)
+    set tag "$optarg" ${1+"$@"}
+    shift
+    prev=tag
+    ;;
+
+  -dlopen)
+    prevopt="-dlopen"
+    prev=execute_dlfiles
+    ;;
+
+  -*)
+    $echo "$modename: unrecognized option \`$arg'" 1>&2
+    $echo "$help" 1>&2
+    exit 1
+    ;;
+
+  *)
+    nonopt="$arg"
+    break
+    ;;
+  esac
+done
+
+if test -n "$prevopt"; then
+  $echo "$modename: option \`$prevopt' requires an argument" 1>&2
+  $echo "$help" 1>&2
+  exit 1
+fi
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end.  This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+if test -z "$show_help"; then
+
+  # Infer the operation mode.
+  if test -z "$mode"; then
+    $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2
+    $echo "*** Future versions of Libtool will require -mode=MODE be specified." 1>&2
+    case $nonopt in
+    *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*)
+      mode=link
+      for arg
+      do
+	case $arg in
+	-c)
+	   mode=compile
+	   break
+	   ;;
+	esac
+      done
+      ;;
+    *db | *dbx | *strace | *truss)
+      mode=execute
+      ;;
+    *install*|cp|mv)
+      mode=install
+      ;;
+    *rm)
+      mode=uninstall
+      ;;
+    *)
+      # If we have no mode, but dlfiles were specified, then do execute mode.
+      test -n "$execute_dlfiles" && mode=execute
+
+      # Just use the default operation mode.
+      if test -z "$mode"; then
+	if test -n "$nonopt"; then
+	  $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+	else
+	  $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+	fi
+      fi
+      ;;
+    esac
+  fi
+
+  # Only execute mode is allowed to have -dlopen flags.
+  if test -n "$execute_dlfiles" && test "$mode" != execute; then
+    $echo "$modename: unrecognized option \`-dlopen'" 1>&2
+    $echo "$help" 1>&2
+    exit 1
+  fi
+
+  # Change the help message to a mode-specific one.
+  generic_help="$help"
+  help="Try \`$modename --help --mode=$mode' for more information."
+
+  # These modes are in order of execution frequency so that they run quickly.
+  case $mode in
+  # libtool compile mode
+  compile)
+    modename="$modename: compile"
+    # Get the compilation command and the source file.
+    base_compile=
+    srcfile="$nonopt"  #  always keep a non-empty value in "srcfile"
+    suppress_output=
+    arg_mode=normal
+    libobj=
+
+    for arg
+    do
+      case "$arg_mode" in
+      arg  )
+	# do not "continue".  Instead, add this to base_compile
+	lastarg="$arg"
+	arg_mode=normal
+	;;
+
+      target )
+	libobj="$arg"
+	arg_mode=normal
+	continue
+	;;
+
+      normal )
+	# Accept any command-line options.
+	case $arg in
+	-o)
+	  if test -n "$libobj" ; then
+	    $echo "$modename: you cannot specify \`-o' more than once" 1>&2
+	    exit 1
+	  fi
+	  arg_mode=target
+	  continue
+	  ;;
+
+	-static)
+	  build_old_libs=yes
+	  continue
+	  ;;
+
+	-prefer-pic)
+	  pic_mode=yes
+	  continue
+	  ;;
+
+	-prefer-non-pic)
+	  pic_mode=no
+	  continue
+	  ;;
+
+	-Xcompiler)
+	  arg_mode=arg  #  the next one goes into the "base_compile" arg list
+	  continue      #  The current "srcfile" will either be retained or
+	  ;;            #  replaced later.  I would guess that would be a bug.
+
+	-Wc,*)
+	  args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
+	  lastarg=
+	  save_ifs="$IFS"; IFS=','
+	  for arg in $args; do
+	    IFS="$save_ifs"
+
+	    # Double-quote args containing other shell metacharacters.
+	    # Many Bourne shells cannot handle close brackets correctly
+	    # in scan sets, so we specify it separately.
+	    case $arg in
+	      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	      arg="\"$arg\""
+	      ;;
+	    esac
+	    lastarg="$lastarg $arg"
+	  done
+	  IFS="$save_ifs"
+	  lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
+
+	  # Add the arguments to base_compile.
+	  base_compile="$base_compile $lastarg"
+	  continue
+	  ;;
+
+	* )
+	  # Accept the current argument as the source file.
+	  # The previous "srcfile" becomes the current argument.
+	  #
+	  lastarg="$srcfile"
+	  srcfile="$arg"
+	  ;;
+	esac  #  case $arg
+	;;
+      esac    #  case $arg_mode
+
+      # Aesthetically quote the previous argument.
+      lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
+
+      case $lastarg in
+      # Double-quote args containing other shell metacharacters.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	lastarg="\"$lastarg\""
+	;;
+      esac
+
+      base_compile="$base_compile $lastarg"
+    done # for arg
+
+    case $arg_mode in
+    arg)
+      $echo "$modename: you must specify an argument for -Xcompile"
+      exit 1
+      ;;
+    target)
+      $echo "$modename: you must specify a target with \`-o'" 1>&2
+      exit 1
+      ;;
+    *)
+      # Get the name of the library object.
+      [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
+      ;;
+    esac
+
+    # Recognize several different file suffixes.
+    # If the user specifies -o file.o, it is replaced with file.lo
+    xform='[cCFSifmso]'
+    case $libobj in
+    *.ada) xform=ada ;;
+    *.adb) xform=adb ;;
+    *.ads) xform=ads ;;
+    *.asm) xform=asm ;;
+    *.c++) xform=c++ ;;
+    *.cc) xform=cc ;;
+    *.ii) xform=ii ;;
+    *.class) xform=class ;;
+    *.cpp) xform=cpp ;;
+    *.cxx) xform=cxx ;;
+    *.f90) xform=f90 ;;
+    *.for) xform=for ;;
+    *.java) xform=java ;;
+    esac
+
+    libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
+
+    case $libobj in
+    *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
+    *)
+      $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
+      exit 1
+      ;;
+    esac
+
+    # Infer tagged configuration to use if any are available and
+    # if one wasn't chosen via the "--tag" command line option.
+    # Only attempt this if the compiler in the base compile
+    # command doesn't match the default compiler.
+    if test -n "$available_tags" && test -z "$tagname"; then
+      case $base_compile in
+      # Blanks in the command may have been stripped by the calling shell,
+      # but not from the CC environment variable when configure was run.
+      " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "*) ;;
+      # Blanks at the start of $base_compile will cause this to fail
+      # if we don't check for them as well.
+      *)
+	for z in $available_tags; do
+	  if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$0" > /dev/null; then
+	    # Evaluate the configuration.
+	    eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $0`"
+	    case "$base_compile " in
+	    "$CC "* | " $CC "* | "`$echo $CC` "* | " `$echo $CC` "*)
+	      # The compiler in the base compile command matches
+	      # the one in the tagged configuration.
+	      # Assume this is the tagged configuration we want.
+	      tagname=$z
+	      break
+	      ;;
+	    esac
+	  fi
+	done
+	# If $tagname still isn't set, then no tagged configuration
+	# was found and let the user know that the "--tag" command
+	# line option must be used.
+	if test -z "$tagname"; then
+	  $echo "$modename: unable to infer tagged configuration"
+	  $echo "$modename: specify a tag with \`--tag'" 1>&2
+	  exit 1
+#        else
+#          $echo "$modename: using $tagname tagged configuration"
+	fi
+	;;
+      esac
+    fi
+
+    objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+    xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+    if test "X$xdir" = "X$obj"; then
+      xdir=
+    else
+      xdir=$xdir/
+    fi
+    lobj=${xdir}$objdir/$objname
+
+    if test -z "$base_compile"; then
+      $echo "$modename: you must specify a compilation command" 1>&2
+      $echo "$help" 1>&2
+      exit 1
+    fi
+
+    # Delete any leftover library objects.
+    if test "$build_old_libs" = yes; then
+      removelist="$obj $lobj $libobj ${libobj}T"
+    else
+      removelist="$lobj $libobj ${libobj}T"
+    fi
+
+    $run $rm $removelist
+    trap "$run $rm $removelist; exit 1" 1 2 15
+
+    # On Cygwin there's no "real" PIC flag so we must build both object types
+    case $host_os in
+    cygwin* | mingw* | pw32* | os2*)
+      pic_mode=default
+      ;;
+    esac
+    if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+      # non-PIC code in shared libraries is not supported
+      pic_mode=default
+    fi
+
+    # Calculate the filename of the output object if compiler does
+    # not support -o with -c
+    if test "$compiler_c_o" = no; then
+      output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
+      lockfile="$output_obj.lock"
+      removelist="$removelist $output_obj $lockfile"
+      trap "$run $rm $removelist; exit 1" 1 2 15
+    else
+      output_obj=
+      need_locks=no
+      lockfile=
+    fi
+
+    # Lock this critical section if it is needed
+    # We use this script file to make the link, it avoids creating a new file
+    if test "$need_locks" = yes; then
+      until $run ln "$0" "$lockfile" 2>/dev/null; do
+	$show "Waiting for $lockfile to be removed"
+	sleep 2
+      done
+    elif test "$need_locks" = warn; then
+      if test -f "$lockfile"; then
+	$echo "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$run $rm $removelist
+	exit 1
+      fi
+      $echo $srcfile > "$lockfile"
+    fi
+
+    if test -n "$fix_srcfile_path"; then
+      eval srcfile=\"$fix_srcfile_path\"
+    fi
+
+    $run $rm "$libobj" "${libobj}T"
+
+    # Create a libtool object file (analogous to a ".la" file),
+    # but don't create it if we're doing a dry run.
+    test -z "$run" && cat > ${libobj}T <<EOF
+# $libobj - a libtool object file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+EOF
+
+    # Only build a PIC object if we are building libtool libraries.
+    if test "$build_libtool_libs" = yes; then
+      # Without this assignment, base_compile gets emptied.
+      fbsd_hideous_sh_bug=$base_compile
+
+      if test "$pic_mode" != no; then
+	command="$base_compile $srcfile $pic_flag"
+      else
+	# Don't build PIC code
+	command="$base_compile $srcfile"
+      fi
+
+      if test ! -d "${xdir}$objdir"; then
+	$show "$mkdir ${xdir}$objdir"
+	$run $mkdir ${xdir}$objdir
+	status=$?
+	if test "$status" -ne 0 && test ! -d "${xdir}$objdir"; then
+	  exit $status
+	fi
+      fi
+
+      if test -z "$output_obj"; then
+	# Place PIC objects in $objdir
+	command="$command -o $lobj"
+      fi
+
+      $run $rm "$lobj" "$output_obj"
+
+      $show "$command"
+      if $run eval "$command"; then :
+      else
+	test -n "$output_obj" && $run $rm $removelist
+	exit 1
+      fi
+
+      if test "$need_locks" = warn &&
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$run $rm $removelist
+	exit 1
+      fi
+
+      # Just move the object if needed, then go on to compile the next one
+      if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+	$show "$mv $output_obj $lobj"
+	if $run $mv $output_obj $lobj; then :
+	else
+	  error=$?
+	  $run $rm $removelist
+	  exit $error
+	fi
+      fi
+
+      # Append the name of the PIC object to the libtool object file.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object='$objdir/$objname'
+
+EOF
+
+      # Allow error messages only from the first compilation.
+      suppress_output=' >/dev/null 2>&1'
+    else
+      # No PIC object so indicate it doesn't exist in the libtool
+      # object file.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object=none
+
+EOF
+    fi
+
+    # Only build a position-dependent object if we build old libraries.
+    if test "$build_old_libs" = yes; then
+      if test "$pic_mode" != yes; then
+	# Don't build PIC code
+	command="$base_compile $srcfile"
+      else
+	command="$base_compile $srcfile $pic_flag"
+      fi
+      if test "$compiler_c_o" = yes; then
+	command="$command -o $obj"
+      fi
+
+      # Suppress compiler output if we already did a PIC compilation.
+      command="$command$suppress_output"
+      $run $rm "$obj" "$output_obj"
+      $show "$command"
+      if $run eval "$command"; then :
+      else
+	$run $rm $removelist
+	exit 1
+      fi
+
+      if test "$need_locks" = warn &&
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$run $rm $removelist
+	exit 1
+      fi
+
+      # Just move the object if needed
+      if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+	$show "$mv $output_obj $obj"
+	if $run $mv $output_obj $obj; then :
+	else
+	  error=$?
+	  $run $rm $removelist
+	  exit $error
+	fi
+      fi
+
+      # Append the name of the non-PIC object the libtool object file.
+      # Only append if the libtool object file exists.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object='$objname'
+
+EOF
+    else
+      # Append the name of the non-PIC object the libtool object file.
+      # Only append if the libtool object file exists.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object=none
+
+EOF
+    fi
+
+    $run $mv "${libobj}T" "${libobj}"
+
+    # Unlock the critical section if it was locked
+    if test "$need_locks" != no; then
+      $run $rm "$lockfile"
+    fi
+
+    exit 0
+    ;;
+
+  # libtool link mode
+  link | relink)
+    modename="$modename: link"
+    case $host in
+    *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+      # It is impossible to link a dll without this setting, and
+      # we shouldn't force the makefile maintainer to figure out
+      # which system we are compiling for in order to pass an extra
+      # flag for every libtool invocation.
+      # allow_undefined=no
+
+      # FIXME: Unfortunately, there are problems with the above when trying
+      # to make a dll which has undefined symbols, in which case not
+      # even a static library is built.  For now, we need to specify
+      # -no-undefined on the libtool link line when we can be certain
+      # that all symbols are satisfied, otherwise we get a static library.
+      allow_undefined=yes
+      ;;
+    *)
+      allow_undefined=yes
+      ;;
+    esac
+    libtool_args="$nonopt"
+    base_compile="$nonopt"
+    compile_command="$nonopt"
+    finalize_command="$nonopt"
+
+    compile_rpath=
+    finalize_rpath=
+    compile_shlibpath=
+    finalize_shlibpath=
+    convenience=
+    old_convenience=
+    deplibs=
+    old_deplibs=
+    add_flags=
+    compiler_flags=
+    linker_flags=
+    dllsearchpath=
+    lib_search_path=`pwd`
+    inst_prefix_dir=
+
+    avoid_version=no
+    dlfiles=
+    dlprefiles=
+    dlself=no
+    export_dynamic=no
+    export_symbols=
+    export_symbols_regex=
+    generated=
+    libobjs=
+    ltlibs=
+    module=no
+    no_install=no
+    objs=
+    non_pic_objects=
+    prefer_static_libs=no
+    preload=no
+    prev=
+    prevarg=
+    release=
+    rpath=
+    xrpath=
+    perm_rpath=
+    temp_rpath=
+    thread_safe=no
+    vinfo=
+    vinfo_number=no
+
+    # We need to know -static, to get the right output filenames.
+    for arg
+    do
+      case $arg in
+      -all-static | -static)
+	if test "X$arg" = "X-all-static"; then
+	  if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+	    $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
+	  fi
+	  if test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	else
+	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	fi
+	build_libtool_libs=no
+	build_old_libs=yes
+	prefer_static_libs=yes
+	break
+	;;
+      esac
+    done
+
+    # See if our shared archives depend on static archives.
+    test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+    # Go through the arguments, transforming them on the way.
+    while test "$#" -gt 0; do
+      arg="$1"
+      base_compile="$base_compile $arg"
+      shift
+      case $arg in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test
+	;;
+      *) qarg=$arg ;;
+      esac
+      libtool_args="$libtool_args $qarg"
+
+      # If the previous option needs an argument, assign it.
+      if test -n "$prev"; then
+	case $prev in
+	output)
+	  compile_command="$compile_command @OUTPUT@"
+	  finalize_command="$finalize_command @OUTPUT@"
+	  ;;
+	esac
+
+	case $prev in
+	dlfiles|dlprefiles)
+	  if test "$preload" = no; then
+	    # Add the symbol object into the linking commands.
+	    compile_command="$compile_command @SYMFILE@"
+	    finalize_command="$finalize_command @SYMFILE@"
+	    preload=yes
+	  fi
+	  case $arg in
+	  *.la | *.lo) ;;  # We handle these cases below.
+	  force)
+	    if test "$dlself" = no; then
+	      dlself=needless
+	      export_dynamic=yes
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  self)
+	    if test "$prev" = dlprefiles; then
+	      dlself=yes
+	    elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+	      dlself=yes
+	    else
+	      dlself=needless
+	      export_dynamic=yes
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  *)
+	    if test "$prev" = dlfiles; then
+	      dlfiles="$dlfiles $arg"
+	    else
+	      dlprefiles="$dlprefiles $arg"
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  esac
+	  ;;
+	expsyms)
+	  export_symbols="$arg"
+	  if test ! -f "$arg"; then
+	    $echo "$modename: symbol file \`$arg' does not exist"
+	    exit 1
+	  fi
+	  prev=
+	  continue
+	  ;;
+	expsyms_regex)
+	  export_symbols_regex="$arg"
+	  prev=
+	  continue
+	  ;;
+	inst_prefix)
+	  inst_prefix_dir="$arg"
+	  prev=
+	  continue
+	  ;;
+	release)
+	  release="-$arg"
+	  prev=
+	  continue
+	  ;;
+	objectlist)
+	  if test -f "$arg"; then
+	    save_arg=$arg
+	    moreargs=
+	    for fil in `cat $save_arg`
+	    do
+#	      moreargs="$moreargs $fil"
+	      arg=$fil
+	      # A libtool-controlled object.
+
+	      # Check to see that this really is a libtool object.
+	      if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+		pic_object=
+		non_pic_object=
+
+		# Read the .lo file
+		# If there is no directory component, then add one.
+		case $arg in
+		*/* | *\\*) . $arg ;;
+		*) . ./$arg ;;
+		esac
+
+		if test -z "$pic_object" || \
+		   test -z "$non_pic_object" ||
+		   test "$pic_object" = none && \
+		   test "$non_pic_object" = none; then
+		  $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+		  exit 1
+		fi
+
+		# Extract subdirectory from the argument.
+		xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+		if test "X$xdir" = "X$arg"; then
+		  xdir=
+		else
+		  xdir="$xdir/"
+		fi
+
+		if test "$pic_object" != none; then
+		  # Prepend the subdirectory the object is found in.
+		  pic_object="$xdir$pic_object"
+
+		  if test "$prev" = dlfiles; then
+		    if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+		      dlfiles="$dlfiles $pic_object"
+		      prev=
+		      continue
+		    else
+		      # If libtool objects are unsupported, then we need to preload.
+		      prev=dlprefiles
+		    fi
+		  fi
+
+		  # CHECK ME:  I think I busted this.  -Ossama
+		  if test "$prev" = dlprefiles; then
+		    # Preload the old-style object.
+		    dlprefiles="$dlprefiles $pic_object"
+		    prev=
+		  fi
+
+		  # A PIC object.
+		  libobjs="$libobjs $pic_object"
+		  arg="$pic_object"
+		fi
+
+		# Non-PIC object.
+		if test "$non_pic_object" != none; then
+		  # Prepend the subdirectory the object is found in.
+		  non_pic_object="$xdir$non_pic_object"
+
+		  # A standard non-PIC object
+		  non_pic_objects="$non_pic_objects $non_pic_object"
+		  if test -z "$pic_object" || test "$pic_object" = none ; then
+		    arg="$non_pic_object"
+		  fi
+		fi
+	      else
+		# Only an error if not doing a dry-run.
+		if test -z "$run"; then
+		  $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+		  exit 1
+		else
+		  # Dry-run case.
+
+		  # Extract subdirectory from the argument.
+		  xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+		  if test "X$xdir" = "X$arg"; then
+		    xdir=
+		  else
+		    xdir="$xdir/"
+		  fi
+
+		  pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+		  non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+		  libobjs="$libobjs $pic_object"
+		  non_pic_objects="$non_pic_objects $non_pic_object"
+		fi
+	      fi
+	    done
+	  else
+	    $echo "$modename: link input file \`$save_arg' does not exist"
+	    exit 1
+	  fi
+	  arg=$save_arg
+	  prev=
+	  continue
+	  ;;
+	rpath | xrpath)
+	  # We need an absolute path.
+	  case $arg in
+	  [\\/]* | [A-Za-z]:[\\/]*) ;;
+	  *)
+	    $echo "$modename: only absolute run-paths are allowed" 1>&2
+	    exit 1
+	    ;;
+	  esac
+	  if test "$prev" = rpath; then
+	    case "$rpath " in
+	    *" $arg "*) ;;
+	    *) rpath="$rpath $arg" ;;
+	    esac
+	  else
+	    case "$xrpath " in
+	    *" $arg "*) ;;
+	    *) xrpath="$xrpath $arg" ;;
+	    esac
+	  fi
+	  prev=
+	  continue
+	  ;;
+	xcompiler)
+	  compiler_flags="$compiler_flags $qarg"
+	  prev=
+	  compile_command="$compile_command $qarg"
+	  finalize_command="$finalize_command $qarg"
+	  continue
+	  ;;
+	xlinker)
+	  linker_flags="$linker_flags $qarg"
+	  compiler_flags="$compiler_flags $wl$qarg"
+	  prev=
+	  compile_command="$compile_command $wl$qarg"
+	  finalize_command="$finalize_command $wl$qarg"
+	  continue
+	  ;;
+	xcclinker)
+	  linker_flags="$linker_flags $qarg"
+	  compiler_flags="$compiler_flags $qarg"
+	  prev=
+	  compile_command="$compile_command $qarg"
+	  finalize_command="$finalize_command $qarg"
+	  continue
+	  ;;
+	*)
+	  eval "$prev=\"\$arg\""
+	  prev=
+	  continue
+	  ;;
+	esac
+      fi # test -n "$prev"
+
+      prevarg="$arg"
+
+      case $arg in
+      -all-static)
+	if test -n "$link_static_flag"; then
+	  compile_command="$compile_command $link_static_flag"
+	  finalize_command="$finalize_command $link_static_flag"
+	fi
+	continue
+	;;
+
+      -allow-undefined)
+	# FIXME: remove this flag sometime in the future.
+	$echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
+	continue
+	;;
+
+      -avoid-version)
+	avoid_version=yes
+	continue
+	;;
+
+      -dlopen)
+	prev=dlfiles
+	continue
+	;;
+
+      -dlpreopen)
+	prev=dlprefiles
+	continue
+	;;
+
+      -export-dynamic)
+	export_dynamic=yes
+	continue
+	;;
+
+      -export-symbols | -export-symbols-regex)
+	if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+	  $echo "$modename: more than one -exported-symbols argument is not allowed"
+	  exit 1
+	fi
+	if test "X$arg" = "X-export-symbols"; then
+	  prev=expsyms
+	else
+	  prev=expsyms_regex
+	fi
+	continue
+	;;
+
+      -inst-prefix-dir)
+	prev=inst_prefix
+	continue
+	;;
+
+      # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+      # so, if we see these flags be careful not to treat them like -L
+      -L[A-Z][A-Z]*:*)
+	case $with_gcc/$host in
+	no/*-*-irix* | /*-*-irix*)
+	  compile_command="$compile_command $arg"
+	  finalize_command="$finalize_command $arg"
+	  ;;
+	esac
+	continue
+	;;
+
+      -L*)
+	dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
+	# We need an absolute path.
+	case $dir in
+	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	*)
+	  absdir=`cd "$dir" && pwd`
+	  if test -z "$absdir"; then
+	    $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
+	    exit 1
+	  fi
+	  dir="$absdir"
+	  ;;
+	esac
+	case "$deplibs " in
+	*" -L$dir "*) ;;
+	*)
+	  deplibs="$deplibs -L$dir"
+	  lib_search_path="$lib_search_path $dir"
+	  ;;
+	esac
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+	  case :$dllsearchpath: in
+	  *":$dir:"*) ;;
+	  *) dllsearchpath="$dllsearchpath:$dir";;
+	  esac
+	  ;;
+	esac
+	continue
+	;;
+
+      -l*)
+	if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+	  case $host in
+	  *-*-cygwin* | *-*-pw32* | *-*-beos*)
+	    # These systems don't actually have a C or math library (as such)
+	    continue
+	    ;;
+	  *-*-freebsd*-gnu*)
+	    # prevent being parsed by the freebsd regexp below
+	    ;;
+	  *-*-mingw* | *-*-os2*)
+	    # These systems don't actually have a C library (as such)
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-openbsd* | *-*-freebsd*)
+	    # Do not include libc due to us having libc/libc_r.
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C and math libraries are in the System framework
+	    deplibs="$deplibs -framework System"
+	    continue
+	  esac
+	elif test "X$arg" = "X-lc_r"; then
+	 case $host in
+	 *-*-freebsd*-gnu*)
+	   # prevent being parsed by the freebsd regexp below
+	   ;;
+	 *-*-openbsd*)
+	   # Do not include libc_r directly, use -pthread flag.
+	   continue
+	   ;;
+	 esac
+	fi
+	deplibs="$deplibs $arg"
+	continue
+	;;
+
+      -module)
+	module=yes
+	continue
+	;;
+
+      # gcc -m* arguments should be passed to the linker via $compiler_flags
+      # in order to pass architecture information to the linker
+      # (e.g. 32 vs 64-bit).  This may also be accomplished via -Wl,-mfoo
+      # but this is not reliable with gcc because gcc may use -mfoo to
+      # select a different linker, different libraries, etc, while
+      # -Wl,-mfoo simply passes -mfoo to the linker.
+      -m*)
+	# Unknown arguments in both finalize_command and compile_command need
+	# to be aesthetically quoted because they are evaled later.
+	arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+	case $arg in
+	*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	  arg="\"$arg\""
+	  ;;
+	esac
+        compile_command="$compile_command $arg"
+        finalize_command="$finalize_command $arg"
+        if test "$with_gcc" = "yes" ; then
+          compiler_flags="$compiler_flags $arg"
+        fi
+        continue
+        ;;
+
+      -shrext)
+	prev=shrext
+	continue
+	;;
+
+      -no-fast-install)
+	fast_install=no
+	continue
+	;;
+
+      -no-install)
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+	  # The PATH hackery in wrapper scripts is required on Windows
+	  # in order for the loader to find any dlls it needs.
+	  $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2
+	  $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2
+	  fast_install=no
+	  ;;
+	*) no_install=yes ;;
+	esac
+	continue
+	;;
+
+      -no-undefined)
+	allow_undefined=no
+	continue
+	;;
+
+      -objectlist)
+	prev=objectlist
+	continue
+	;;
+
+      -o) prev=output ;;
+
+      -release)
+	prev=release
+	continue
+	;;
+
+      -rpath)
+	prev=rpath
+	continue
+	;;
+
+      -R)
+	prev=xrpath
+	continue
+	;;
+
+      -R*)
+	dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
+	# We need an absolute path.
+	case $dir in
+	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	*)
+	  $echo "$modename: only absolute run-paths are allowed" 1>&2
+	  exit 1
+	  ;;
+	esac
+	case "$xrpath " in
+	*" $dir "*) ;;
+	*) xrpath="$xrpath $dir" ;;
+	esac
+	continue
+	;;
+
+      -static)
+	# The effects of -static are defined in a previous loop.
+	# We used to do the same as -all-static on platforms that
+	# didn't have a PIC flag, but the assumption that the effects
+	# would be equivalent was wrong.  It would break on at least
+	# Digital Unix and AIX.
+	continue
+	;;
+
+      -thread-safe)
+	thread_safe=yes
+	continue
+	;;
+
+      -version-info)
+	prev=vinfo
+	continue
+	;;
+      -version-number)
+	prev=vinfo
+	vinfo_number=yes
+	continue
+	;;
+
+      -Wc,*)
+	args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
+	arg=
+	save_ifs="$IFS"; IFS=','
+	for flag in $args; do
+	  IFS="$save_ifs"
+	  case $flag in
+	    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	    flag="\"$flag\""
+	    ;;
+	  esac
+	  arg="$arg $wl$flag"
+	  compiler_flags="$compiler_flags $flag"
+	done
+	IFS="$save_ifs"
+	arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+	;;
+
+      -Wl,*)
+	args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'`
+	arg=
+	save_ifs="$IFS"; IFS=','
+	for flag in $args; do
+	  IFS="$save_ifs"
+	  case $flag in
+	    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	    flag="\"$flag\""
+	    ;;
+	  esac
+	  arg="$arg $wl$flag"
+	  compiler_flags="$compiler_flags $wl$flag"
+	  linker_flags="$linker_flags $flag"
+	done
+	IFS="$save_ifs"
+	arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+	;;
+
+      -Xcompiler)
+	prev=xcompiler
+	continue
+	;;
+
+      -Xlinker)
+	prev=xlinker
+	continue
+	;;
+
+      -XCClinker)
+	prev=xcclinker
+	continue
+	;;
+
+      # Some other compiler flag.
+      -* | +*)
+	# Unknown arguments in both finalize_command and compile_command need
+	# to be aesthetically quoted because they are evaled later.
+	arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+	case $arg in
+	*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	  arg="\"$arg\""
+	  ;;
+	esac
+	add_flags="$add_flags $arg"
+	;;
+
+      *.$objext)
+	# A standard object.
+	objs="$objs $arg"
+	;;
+
+      *.lo)
+	# A libtool-controlled object.
+
+	# Check to see that this really is a libtool object.
+	if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+	  pic_object=
+	  non_pic_object=
+
+	  # Read the .lo file
+	  # If there is no directory component, then add one.
+	  case $arg in
+	  */* | *\\*) . $arg ;;
+	  *) . ./$arg ;;
+	  esac
+
+	  if test -z "$pic_object" || \
+	     test -z "$non_pic_object" ||
+	     test "$pic_object" = none && \
+	     test "$non_pic_object" = none; then
+	    $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+	    exit 1
+	  fi
+
+	  # Extract subdirectory from the argument.
+	  xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+	  if test "X$xdir" = "X$arg"; then
+	    xdir=
+ 	  else
+	    xdir="$xdir/"
+	  fi
+
+	  if test "$pic_object" != none; then
+	    # Prepend the subdirectory the object is found in.
+	    pic_object="$xdir$pic_object"
+
+	    if test "$prev" = dlfiles; then
+	      if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+		dlfiles="$dlfiles $pic_object"
+		prev=
+		continue
+	      else
+		# If libtool objects are unsupported, then we need to preload.
+		prev=dlprefiles
+	      fi
+	    fi
+
+	    # CHECK ME:  I think I busted this.  -Ossama
+	    if test "$prev" = dlprefiles; then
+	      # Preload the old-style object.
+	      dlprefiles="$dlprefiles $pic_object"
+	      prev=
+	    fi
+
+	    # A PIC object.
+	    libobjs="$libobjs $pic_object"
+	    arg="$pic_object"
+	  fi
+
+	  # Non-PIC object.
+	  if test "$non_pic_object" != none; then
+	    # Prepend the subdirectory the object is found in.
+	    non_pic_object="$xdir$non_pic_object"
+
+	    # A standard non-PIC object
+	    non_pic_objects="$non_pic_objects $non_pic_object"
+	    if test -z "$pic_object" || test "$pic_object" = none ; then
+	      arg="$non_pic_object"
+	    fi
+	  fi
+	else
+	  # Only an error if not doing a dry-run.
+	  if test -z "$run"; then
+	    $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+	    exit 1
+	  else
+	    # Dry-run case.
+
+	    # Extract subdirectory from the argument.
+	    xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+	    if test "X$xdir" = "X$arg"; then
+	      xdir=
+	    else
+	      xdir="$xdir/"
+	    fi
+
+	    pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+	    non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+	    libobjs="$libobjs $pic_object"
+	    non_pic_objects="$non_pic_objects $non_pic_object"
+	  fi
+	fi
+	;;
+
+      *.$libext)
+	# An archive.
+	deplibs="$deplibs $arg"
+	old_deplibs="$old_deplibs $arg"
+	continue
+	;;
+
+      *.la)
+	# A libtool-controlled library.
+
+	if test "$prev" = dlfiles; then
+	  # This library was specified with -dlopen.
+	  dlfiles="$dlfiles $arg"
+	  prev=
+	elif test "$prev" = dlprefiles; then
+	  # The library was specified with -dlpreopen.
+	  dlprefiles="$dlprefiles $arg"
+	  prev=
+	else
+	  deplibs="$deplibs $arg"
+	fi
+	continue
+	;;
+
+      # Some other compiler argument.
+      *)
+	# Unknown arguments in both finalize_command and compile_command need
+	# to be aesthetically quoted because they are evaled later.
+	arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+	case $arg in
+	*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	  arg="\"$arg\""
+	  ;;
+	esac
+	add_flags="$add_flags $arg"
+	;;
+      esac # arg
+
+      # Now actually substitute the argument into the commands.
+      if test -n "$arg"; then
+	compile_command="$compile_command $arg"
+	finalize_command="$finalize_command $arg"
+      fi
+    done # argument parsing loop
+
+    if test -n "$prev"; then
+      $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
+      $echo "$help" 1>&2
+      exit 1
+    fi
+
+    # Infer tagged configuration to use if any are available and
+    # if one wasn't chosen via the "--tag" command line option.
+    # Only attempt this if the compiler in the base link
+    # command doesn't match the default compiler.
+    if test -n "$available_tags" && test -z "$tagname"; then
+      case $base_compile in
+      # Blanks in the command may have been stripped by the calling shell,
+      # but not from the CC environment variable when configure was run.
+      "$CC "* | " $CC "* | "`$echo $CC` "* | " `$echo $CC` "*) ;;
+      # Blanks at the start of $base_compile will cause this to fail
+      # if we don't check for them as well.
+      *)
+	for z in $available_tags; do
+	  if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$0" > /dev/null; then
+	    # Evaluate the configuration.
+	    eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $0`"
+	    case $base_compile in
+	    "$CC "* | " $CC "* | "`$echo $CC` "* | " `$echo $CC` "*)
+	      # The compiler in $compile_command matches
+	      # the one in the tagged configuration.
+	      # Assume this is the tagged configuration we want.
+	      tagname=$z
+	      break
+	      ;;
+	    esac
+	  fi
+	done
+	# If $tagname still isn't set, then no tagged configuration
+	# was found and let the user know that the "--tag" command
+	# line option must be used.
+	if test -z "$tagname"; then
+	  $echo "$modename: unable to infer tagged configuration"
+	  $echo "$modename: specify a tag with \`--tag'" 1>&2
+	  exit 1
+#       else
+#         $echo "$modename: using $tagname tagged configuration"
+	fi
+	;;
+      esac
+    fi
+
+    if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+      eval arg=\"$export_dynamic_flag_spec\"
+      compile_command="$compile_command $arg"
+      finalize_command="$finalize_command $arg"
+    fi
+
+    oldlibs=
+    # calculate the name of the file, without its directory
+    outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
+    libobjs_save="$libobjs"
+
+    if test -n "$shlibpath_var"; then
+      # get the directories listed in $shlibpath_var
+      eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+    else
+      shlib_search_path=
+    fi
+    eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+    eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+    output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+    if test "X$output_objdir" = "X$output"; then
+      output_objdir="$objdir"
+    else
+      output_objdir="$output_objdir/$objdir"
+    fi
+    # Create the object directory.
+    if test ! -d "$output_objdir"; then
+      $show "$mkdir $output_objdir"
+      $run $mkdir $output_objdir
+      status=$?
+      if test "$status" -ne 0 && test ! -d "$output_objdir"; then
+	exit $status
+      fi
+    fi
+
+    # Determine the type of output
+    case $output in
+    "")
+      $echo "$modename: you must specify an output file" 1>&2
+      $echo "$help" 1>&2
+      exit 1
+      ;;
+    *.$libext) linkmode=oldlib ;;
+    *.lo | *.$objext) linkmode=obj ;;
+    *.la) linkmode=lib ;;
+    *) linkmode=prog ;; # Anything else should be a program.
+    esac
+
+    case $host in
+    *cygwin* | *mingw* | *pw32*)
+      # don't eliminate duplcations in $postdeps and $predeps
+      duplicate_compiler_generated_deps=yes
+      ;;
+    *)
+      duplicate_compiler_generated_deps=$duplicate_deps
+      ;;
+    esac
+    specialdeplibs=
+
+    libs=
+    # Find all interdependent deplibs by searching for libraries
+    # that are linked more than once (e.g. -la -lb -la)
+    for deplib in $deplibs; do
+      if test "X$duplicate_deps" = "Xyes" ; then
+	case "$libs " in
+	*" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	esac
+      fi
+      libs="$libs $deplib"
+    done
+
+    if test "$linkmode" = lib; then
+      libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+      # Compute libraries that are listed more than once in $predeps
+      # $postdeps and mark them as special (i.e., whose duplicates are
+      # not to be eliminated).
+      pre_post_deps=
+      if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then
+	for pre_post_dep in $predeps $postdeps; do
+	  case "$pre_post_deps " in
+	  *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+	  esac
+	  pre_post_deps="$pre_post_deps $pre_post_dep"
+	done
+      fi
+      pre_post_deps=
+    fi
+
+    deplibs=
+    newdependency_libs=
+    newlib_search_path=
+    need_relink=no # whether we're linking any uninstalled libtool libraries
+    notinst_deplibs= # not-installed libtool libraries
+    notinst_path= # paths that contain not-installed libtool libraries
+    case $linkmode in
+    lib)
+	passes="conv link"
+	for file in $dlfiles $dlprefiles; do
+	  case $file in
+	  *.la) ;;
+	  *)
+	    $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2
+	    exit 1
+	    ;;
+	  esac
+	done
+	;;
+    prog)
+	compile_deplibs=
+	finalize_deplibs=
+	alldeplibs=no
+	newdlfiles=
+	newdlprefiles=
+	passes="conv scan dlopen dlpreopen link"
+	;;
+    *)  passes="conv"
+	;;
+    esac
+    for pass in $passes; do
+      if test "$linkmode,$pass" = "lib,link" ||
+	 test "$linkmode,$pass" = "prog,scan"; then
+	libs="$deplibs"
+	deplibs=
+      fi
+      if test "$linkmode" = prog; then
+	case $pass in
+	dlopen) libs="$dlfiles" ;;
+	dlpreopen) libs="$dlprefiles" ;;
+	link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+	esac
+      fi
+      if test "$pass" = dlopen; then
+	# Collect dlpreopened libraries
+	save_deplibs="$deplibs"
+	deplibs=
+      fi
+      for deplib in $libs; do
+	lib=
+	found=no
+	case $deplib in
+	-l*)
+	  if test "$linkmode" != lib && test "$linkmode" != prog; then
+	    $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2
+	    continue
+	  fi
+	  if test "$pass" = conv && test "$allow_undefined" = yes; then
+	    deplibs="$deplib $deplibs"
+	    continue
+	  fi
+	  name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
+	  for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
+	    for search_ext in .la $shrext .so .a; do
+	      # Search the libtool library
+	      lib="$searchdir/lib${name}${search_ext}"
+	      if test -f "$lib"; then
+		if test "$search_ext" = ".la"; then
+		  found=yes
+		else
+		  found=no
+		fi
+		break 2
+	      fi
+	    done
+	  done
+	  if test "$found" != yes; then
+	    # deplib doesn't seem to be a libtool library
+	    if test "$linkmode,$pass" = "prog,link"; then
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      deplibs="$deplib $deplibs"
+	      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+	    fi
+	    continue
+	  else # deplib is a libtool library
+	    # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+	    # We need to do some special things here, and not later.
+	    if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+	      case " $predeps $postdeps " in
+	      *" $deplib "*)
+		if (${SED} -e '2q' $lib |
+                    grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+		  library_names=
+		  old_library=
+		  case $lib in
+		  */* | *\\*) . $lib ;;
+		  *) . ./$lib ;;
+		  esac
+		  for l in $old_library $library_names; do
+		    ll="$l"
+		  done
+		  if test "X$ll" = "X$old_library" ; then # only static version available
+		    found=no
+		    ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+		    test "X$ladir" = "X$lib" && ladir="."
+		    lib=$ladir/$old_library
+		    if test "$linkmode,$pass" = "prog,link"; then
+		      compile_deplibs="$deplib $compile_deplibs"
+		      finalize_deplibs="$deplib $finalize_deplibs"
+		    else
+		      deplibs="$deplib $deplibs"
+		      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+		    fi
+		    continue
+		  fi
+		fi
+	        ;;
+	      *) ;;
+	      esac
+	    fi
+	  fi
+	  ;; # -l
+	-L*)
+	  case $linkmode in
+	  lib)
+	    deplibs="$deplib $deplibs"
+	    test "$pass" = conv && continue
+	    newdependency_libs="$deplib $newdependency_libs"
+	    newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+	    ;;
+	  prog)
+	    if test "$pass" = conv; then
+	      deplibs="$deplib $deplibs"
+	      continue
+	    fi
+	    if test "$pass" = scan; then
+	      deplibs="$deplib $deplibs"
+	      newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+	    else
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    fi
+	    ;;
+	  *)
+	    $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2
+	    ;;
+	  esac # linkmode
+	  continue
+	  ;; # -L
+	-R*)
+	  if test "$pass" = link; then
+	    dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+	    # Make sure the xrpath contains only unique directories.
+	    case "$xrpath " in
+	    *" $dir "*) ;;
+	    *) xrpath="$xrpath $dir" ;;
+	    esac
+	  fi
+	  deplibs="$deplib $deplibs"
+	  continue
+	  ;;
+	*.la) lib="$deplib" ;;
+	*.$libext)
+	  if test "$pass" = conv; then
+	    deplibs="$deplib $deplibs"
+	    continue
+	  fi
+	  case $linkmode in
+	  lib)
+	    if test "$deplibs_check_method" != pass_all; then
+	      $echo
+	      $echo "*** Warning: Trying to link with static lib archive $deplib."
+	      $echo "*** I have the capability to make that library automatically link in when"
+	      $echo "*** you link to this library.  But I can only do this if you have a"
+	      $echo "*** shared version of the library, which you do not appear to have"
+	      $echo "*** because the file extensions .$libext of this argument makes me believe"
+	      $echo "*** that it is just a static archive that I should not used here."
+	    else
+	      $echo
+	      $echo "*** Warning: Linking the shared library $output against the"
+	      $echo "*** static library $deplib is not portable!"
+	      deplibs="$deplib $deplibs"
+	    fi
+	    continue
+	    ;;
+	  prog)
+	    if test "$pass" != link; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    fi
+	    continue
+	    ;;
+	  esac # linkmode
+	  ;; # *.$libext
+	*.lo | *.$objext)
+	  if test "$pass" = conv; then
+	    deplibs="$deplib $deplibs"
+	  elif test "$linkmode" = prog; then
+	    if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+	      # If there is no dlopen support or we're linking statically,
+	      # we need to preload.
+	      newdlprefiles="$newdlprefiles $deplib"
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      newdlfiles="$newdlfiles $deplib"
+	    fi
+	  fi
+	  continue
+	  ;;
+	%DEPLIBS%)
+	  alldeplibs=yes
+	  continue
+	  ;;
+	esac # case $deplib
+	if test "$found" = yes || test -f "$lib"; then :
+	else
+	  $echo "$modename: cannot find the library \`$lib'" 1>&2
+	  exit 1
+	fi
+
+	# Check to see that this really is a libtool archive.
+	if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+	else
+	  $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+	  exit 1
+	fi
+
+	ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+	test "X$ladir" = "X$lib" && ladir="."
+
+	dlname=
+	dlopen=
+	dlpreopen=
+	libdir=
+	library_names=
+	old_library=
+	# If the library was installed with an old release of libtool,
+	# it will not redefine variables installed, or shouldnotlink
+	installed=yes
+	shouldnotlink=no
+
+	# Read the .la file
+	case $lib in
+	*/* | *\\*) . $lib ;;
+	*) . ./$lib ;;
+	esac
+
+	if test "$linkmode,$pass" = "lib,link" ||
+	   test "$linkmode,$pass" = "prog,scan" ||
+	   { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+	  test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+	  test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+	fi
+
+	if test "$pass" = conv; then
+	  # Only check for convenience libraries
+	  deplibs="$lib $deplibs"
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    #echo "Adding $deplib to \$deplibs"
+	    deplibs="$deplib $deplibs"
+            if test "X$duplicate_deps" = "Xyes" ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+            fi
+	    tmp_libs="$tmp_libs $deplib"
+	  done
+	  if test -z "$libdir"; then
+	    if test -z "$old_library"; then
+	      $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+	      exit 1
+	    fi
+	    # It is a libtool convenience library, so add in its objects.
+	    convenience="$convenience $ladir/$objdir/$old_library"
+	    old_convenience="$old_convenience $ladir/$objdir/$old_library"
+	  elif test "$linkmode" != prog && test "$linkmode" != lib; then
+	    $echo "$modename: \`$lib' is not a convenience library" 1>&2
+	    exit 1
+	  fi
+	  continue
+	fi # $pass = conv
+
+    
+	# Get the name of the library we link against.
+	linklib=
+	for l in $old_library $library_names; do
+	  linklib="$l"
+	done
+	if test -z "$linklib"; then
+	  $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+	  exit 1
+	fi
+
+	# This library was specified with -dlopen.
+	if test "$pass" = dlopen; then
+	  if test -z "$libdir"; then
+	    $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
+	    exit 1
+	  fi
+	  if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+	    # If there is no dlname, no dlopen support or we're linking
+	    # statically, we need to preload.  We also need to preload any
+	    # dependent libraries so libltdl's deplib preloader doesn't
+	    # bomb out in the load deplibs phase.
+	    dlprefiles="$dlprefiles $lib $dependency_libs"
+	  else
+	    newdlfiles="$newdlfiles $lib"
+	  fi
+	  continue
+	fi # $pass = dlopen
+
+	# We need an absolute path.
+	case $ladir in
+	[\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+	*)
+	  abs_ladir=`cd "$ladir" && pwd`
+	  if test -z "$abs_ladir"; then
+	    $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2
+	    $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+	    abs_ladir="$ladir"
+	  fi
+	  ;;
+	esac
+	laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+
+	# Find the relevant object directory and library name.
+	if test "X$installed" = Xyes; then
+	  if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    $echo "$modename: warning: library \`$lib' was moved." 1>&2
+	    dir="$ladir"
+	    absdir="$abs_ladir"
+	    libdir="$abs_ladir"
+	  else
+	    dir="$libdir"
+	    absdir="$libdir"
+	  fi
+	else
+	  dir="$ladir/$objdir"
+	  absdir="$abs_ladir/$objdir"
+	  # Remove this search path later
+	  notinst_path="$notinst_path $abs_ladir"
+	fi # $installed = yes
+	name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+
+	# This library was specified with -dlpreopen.
+	if test "$pass" = dlpreopen; then
+	  if test -z "$libdir"; then
+	    $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
+	    exit 1
+	  fi
+	  # Prefer using a static library (so that no silly _DYNAMIC symbols
+	  # are required to link).
+	  if test -n "$old_library"; then
+	    newdlprefiles="$newdlprefiles $dir/$old_library"
+	  # Otherwise, use the dlname, so that lt_dlopen finds it.
+	  elif test -n "$dlname"; then
+	    newdlprefiles="$newdlprefiles $dir/$dlname"
+	  else
+	    newdlprefiles="$newdlprefiles $dir/$linklib"
+	  fi
+	fi # $pass = dlpreopen
+
+	if test -z "$libdir"; then
+	  # Link the convenience library
+	  if test "$linkmode" = lib; then
+	    deplibs="$dir/$old_library $deplibs"
+	  elif test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$dir/$old_library $compile_deplibs"
+	    finalize_deplibs="$dir/$old_library $finalize_deplibs"
+	  else
+	    deplibs="$lib $deplibs" # used for prog,scan pass
+	  fi
+	  continue
+	fi
+
+    
+	if test "$linkmode" = prog && test "$pass" != link; then
+	  newlib_search_path="$newlib_search_path $ladir"
+	  deplibs="$lib $deplibs"
+
+	  linkalldeplibs=no
+	  if test "$link_all_deplibs" != no || test -z "$library_names" ||
+	     test "$build_libtool_libs" = no; then
+	    linkalldeplibs=yes
+	  fi
+
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    case $deplib in
+	    -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test
+	    esac
+	    # Need to link against all dependency_libs?
+	    if test "$linkalldeplibs" = yes; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      # Need to hardcode shared library paths
+	      # or/and link against static libraries
+	      newdependency_libs="$deplib $newdependency_libs"
+	    fi
+	    if test "X$duplicate_deps" = "Xyes" ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs="$tmp_libs $deplib"
+	  done # for deplib
+	  continue
+	fi # $linkmode = prog...
+
+	if test "$linkmode,$pass" = "prog,link"; then
+	  if test -n "$library_names" &&
+	     { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+	    # We need to hardcode the library path
+	    if test -n "$shlibpath_var"; then
+	      # Make sure the rpath contains only unique directories.
+	      case "$temp_rpath " in
+	      *" $dir "*) ;;
+	      *" $absdir "*) ;;
+	      *) temp_rpath="$temp_rpath $dir" ;;
+	      esac
+	    fi
+
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) compile_rpath="$compile_rpath $absdir"
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) finalize_rpath="$finalize_rpath $libdir"
+	      esac
+	      ;;
+	    esac
+	  fi # $linkmode,$pass = prog,link...
+
+	  if test "$alldeplibs" = yes &&
+	     { test "$deplibs_check_method" = pass_all ||
+	       { test "$build_libtool_libs" = yes &&
+		 test -n "$library_names"; }; }; then
+	    # We only need to search for static libraries
+	    continue
+	  fi
+	fi
+
+	link_static=no # Whether the deplib will be linked statically
+	if test -n "$library_names" &&
+	   { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+	  if test "$installed" = no; then
+	    notinst_deplibs="$notinst_deplibs $lib"
+	    need_relink=yes
+	  fi
+	  # This is a shared library
+	
+      # Warn about portability, can't link against -module's on some systems (darwin)
+      if test "$shouldnotlink" = yes && test "$pass" = link ; then
+	    $echo
+	    if test "$linkmode" = prog; then
+	      $echo "*** Warning: Linking the executable $output against the loadable module"
+	    else
+	      $echo "*** Warning: Linking the shared library $output against the loadable module"
+	    fi
+	    $echo "*** $linklib is not portable!"    
+      fi	  
+	  if test "$linkmode" = lib &&
+	     test "$hardcode_into_libs" = yes; then
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) compile_rpath="$compile_rpath $absdir"
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) finalize_rpath="$finalize_rpath $libdir"
+	      esac
+	      ;;
+	    esac
+	  fi
+
+	  if test -n "$old_archive_from_expsyms_cmds"; then
+	    # figure out the soname
+	    set dummy $library_names
+	    realname="$2"
+	    shift; shift
+	    libname=`eval \\$echo \"$libname_spec\"`
+	    # use dlname if we got it. it's perfectly good, no?
+	    if test -n "$dlname"; then
+	      soname="$dlname"
+	    elif test -n "$soname_spec"; then
+	      # bleh windows
+	      case $host in
+	      *cygwin* | mingw*)
+		major=`expr $current - $age`
+		versuffix="-$major"
+		;;
+	      esac
+	      eval soname=\"$soname_spec\"
+	    else
+	      soname="$realname"
+	    fi
+
+	    # Make a new name for the extract_expsyms_cmds to use
+	    soroot="$soname"
+	    soname=`$echo $soroot | ${SED} -e 's/^.*\///'`
+	    newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a"
+
+	    # If the library has no export list, then create one now
+	    if test -f "$output_objdir/$soname-def"; then :
+	    else
+	      $show "extracting exported symbol list from \`$soname'"
+	      save_ifs="$IFS"; IFS='~'
+	      eval cmds=\"$extract_expsyms_cmds\"
+	      for cmd in $cmds; do
+		IFS="$save_ifs"
+		$show "$cmd"
+		$run eval "$cmd" || exit $?
+	      done
+	      IFS="$save_ifs"
+	    fi
+
+	    # Create $newlib
+	    if test -f "$output_objdir/$newlib"; then :; else
+	      $show "generating import library for \`$soname'"
+	      save_ifs="$IFS"; IFS='~'
+	      eval cmds=\"$old_archive_from_expsyms_cmds\"
+	      for cmd in $cmds; do
+		IFS="$save_ifs"
+		$show "$cmd"
+		$run eval "$cmd" || exit $?
+	      done
+	      IFS="$save_ifs"
+	    fi
+	    # make sure the library variables are pointing to the new library
+	    dir=$output_objdir
+	    linklib=$newlib
+	  fi # test -n "$old_archive_from_expsyms_cmds"
+
+	  if test "$linkmode" = prog || test "$mode" != relink; then
+	    add_shlibpath=
+	    add_dir=
+	    add=
+	    lib_linked=yes
+	    case $hardcode_action in
+	    immediate | unsupported)
+	      if test "$hardcode_direct" = no; then
+		add="$dir/$linklib"
+		case $host in
+		  *-*-sco3.2v5* ) add_dir="-L$dir" ;;
+		  *-*-darwin* )
+		    # if the lib is a module then we can not link against it, someone
+		    # is ignoring the new warnings I added
+		    if /usr/bin/file -L $add 2> /dev/null | grep "bundle" >/dev/null ; then
+		      $echo "** Warning, lib $linklib is a module, not a shared library"
+		      if test -z "$old_library" ; then
+		        $echo
+		        $echo "** And there doesn't seem to be a static archive available"
+		        $echo "** The link will probably fail, sorry"
+		      else
+		        add="$dir/$old_library"
+		      fi 
+		    fi
+		esac
+	      elif test "$hardcode_minus_L" = no; then
+		case $host in
+		*-*-sunos*) add_shlibpath="$dir" ;;
+		esac
+		add_dir="-L$dir"
+		add="-l$name"
+	      elif test "$hardcode_shlibpath_var" = no; then
+		add_shlibpath="$dir"
+		add="-l$name"
+	      else
+		lib_linked=no
+	      fi
+	      ;;
+	    relink)
+	      if test "$hardcode_direct" = yes; then
+		add="$dir/$linklib"
+	      elif test "$hardcode_minus_L" = yes; then
+		add_dir="-L$dir"
+		# Try looking first in the location we're being installed to.
+		if test -n "$inst_prefix_dir"; then
+		  case "$libdir" in
+		    [\\/]*)
+		      add_dir="-L$inst_prefix_dir$libdir $add_dir"
+		      ;;
+		  esac
+		fi
+		add="-l$name"
+	      elif test "$hardcode_shlibpath_var" = yes; then
+		add_shlibpath="$dir"
+		add="-l$name"
+	      else
+		lib_linked=no
+	      fi
+	      ;;
+	    *) lib_linked=no ;;
+	    esac
+
+	    if test "$lib_linked" != yes; then
+	      $echo "$modename: configuration error: unsupported hardcode properties"
+	      exit 1
+	    fi
+
+	    if test -n "$add_shlibpath"; then
+	      case :$compile_shlibpath: in
+	      *":$add_shlibpath:"*) ;;
+	      *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+	      esac
+	    fi
+	    if test "$linkmode" = prog; then
+	      test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+	      test -n "$add" && compile_deplibs="$add $compile_deplibs"
+	    else
+	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
+	      test -n "$add" && deplibs="$add $deplibs"
+	      if test "$hardcode_direct" != yes && \
+		 test "$hardcode_minus_L" != yes && \
+		 test "$hardcode_shlibpath_var" = yes; then
+		case :$finalize_shlibpath: in
+		*":$libdir:"*) ;;
+		*) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+		esac
+	      fi
+	    fi
+	  fi
+
+	  if test "$linkmode" = prog || test "$mode" = relink; then
+	    add_shlibpath=
+	    add_dir=
+	    add=
+	    # Finalize command for both is simple: just hardcode it.
+	    if test "$hardcode_direct" = yes; then
+	      add="$libdir/$linklib"
+	    elif test "$hardcode_minus_L" = yes; then
+	      add_dir="-L$libdir"
+	      add="-l$name"
+	    elif test "$hardcode_shlibpath_var" = yes; then
+	      case :$finalize_shlibpath: in
+	      *":$libdir:"*) ;;
+	      *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+	      esac
+	      add="-l$name"
+	    elif test "$hardcode_automatic" = yes; then
+	      if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then
+	        add="$inst_prefix_dir$libdir/$linklib"
+	      else
+	        add="$libdir/$linklib"
+	      fi
+	    else
+	      # We cannot seem to hardcode it, guess we'll fake it.
+	      add_dir="-L$libdir"
+	      # Try looking first in the location we're being installed to.
+	      if test -n "$inst_prefix_dir"; then
+		case "$libdir" in
+		  [\\/]*)
+		    add_dir="-L$inst_prefix_dir$libdir $add_dir"
+		    ;;
+		esac
+	      fi
+	      add="-l$name"
+	    fi
+
+	    if test "$linkmode" = prog; then
+	      test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+	      test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+	    else
+	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
+	      test -n "$add" && deplibs="$add $deplibs"
+	    fi
+	  fi
+	elif test "$linkmode" = prog; then
+	  # Here we assume that one of hardcode_direct or hardcode_minus_L
+	  # is not unsupported.  This is valid on all known static and
+	  # shared platforms.
+	  if test "$hardcode_direct" != unsupported; then
+	    test -n "$old_library" && linklib="$old_library"
+	    compile_deplibs="$dir/$linklib $compile_deplibs"
+	    finalize_deplibs="$dir/$linklib $finalize_deplibs"
+	  else
+	    compile_deplibs="-l$name -L$dir $compile_deplibs"
+	    finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+	  fi
+	elif test "$build_libtool_libs" = yes; then
+	  # Not a shared library
+	  if test "$deplibs_check_method" != pass_all; then
+	    # We're trying link a shared library against a static one
+	    # but the system doesn't support it.
+
+	    # Just print a warning and add the library to dependency_libs so
+	    # that the program can be linked against the static library.
+	    $echo
+	    $echo "*** Warning: This system can not link to static lib archive $lib."
+	    $echo "*** I have the capability to make that library automatically link in when"
+	    $echo "*** you link to this library.  But I can only do this if you have a"
+	    $echo "*** shared version of the library, which you do not appear to have."
+	    if test "$module" = yes; then
+	      $echo "*** But as you try to build a module library, libtool will still create "
+	      $echo "*** a static module, that should work as long as the dlopening application"
+	      $echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+	      if test -z "$global_symbol_pipe"; then
+		$echo
+		$echo "*** However, this would only work if libtool was able to extract symbol"
+		$echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+		$echo "*** not find such a program.  So, this module is probably useless."
+		$echo "*** \`nm' from GNU binutils and a full rebuild may help."
+	      fi
+	      if test "$build_old_libs" = no; then
+		build_libtool_libs=module
+		build_old_libs=yes
+	      else
+		build_libtool_libs=no
+	      fi
+	    fi
+	  else
+	    convenience="$convenience $dir/$old_library"
+	    old_convenience="$old_convenience $dir/$old_library"
+	    deplibs="$dir/$old_library $deplibs"
+	    link_static=yes
+	  fi
+	fi # link shared/static library?
+
+	if test "$linkmode" = lib; then
+	  #if test -n "$dependency_libs" &&
+	  #   { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes ||
+	  #     test "$link_static" = yes; }; then
+	    # Extract -R from dependency_libs
+	    temp_deplibs=
+	    for libdir in $dependency_libs; do
+	      case $libdir in
+	      -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'`
+		   case " $xrpath " in
+		   *" $temp_xrpath "*) ;;
+		   *) xrpath="$xrpath $temp_xrpath";;
+		   esac;;
+	      *) temp_deplibs="$temp_deplibs $libdir";;
+	      esac
+	    done
+	    dependency_libs="$temp_deplibs"
+	  #fi
+
+	  newlib_search_path="$newlib_search_path $absdir"
+	  # Link against this library
+	  test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+	  # ... and its dependency_libs
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    newdependency_libs="$deplib $newdependency_libs"
+	    if test "X$duplicate_deps" = "Xyes" ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs="$tmp_libs $deplib"
+	  done
+
+	  if test "$link_all_deplibs" != no; then
+	    # Add the search paths of all dependency libraries
+	    for deplib in $dependency_libs; do
+	      case $deplib in
+	      -L*) path="$deplib" ;;
+	      *.la)
+		dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'`
+		test "X$dir" = "X$deplib" && dir="."
+		# We need an absolute path.
+		case $dir in
+		[\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+		*)
+		  absdir=`cd "$dir" && pwd`
+		  if test -z "$absdir"; then
+		    $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+		    absdir="$dir"
+		  fi
+		  ;;
+		esac
+		if grep "^installed=no" $deplib > /dev/null; then
+		  path="$absdir/$objdir"
+		else
+		  eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+		  if test -z "$libdir"; then
+		    $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+		    exit 1
+		  fi
+		  if test "$absdir" != "$libdir"; then
+		    # Sure, some shells/systems don't implement the -ef.
+		    # Those will have to live with the warning.
+		    test "$absdir" -ef "$libdir" > /dev/null 2>&1 ||
+		      $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
+		  fi
+		  path="$absdir"
+		fi
+		depdepl=
+		case $host in
+		*-*-darwin*)
+		  # we do not want to link against static libs, but need to link against shared
+		  eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+		  if test -n "$deplibrary_names" ; then
+		    for tmp in $deplibrary_names ; do
+		      depdepl=$tmp
+		    done
+		    if test -f "$path/$depdepl" ; then
+		      depdepl="$path/$depdepl"
+		   fi
+		    # do not add paths which are already there
+		    case " $newlib_search_path " in
+		    *" $path "*) ;;
+		    *) newlib_search_path="$newlib_search_path $path";;
+		    esac
+		    path=""
+		  fi
+		  ;;
+		*)
+		path="-L$path"
+		;;
+		esac 
+		
+		;;
+		  -l*)
+		case $host in
+		*-*-darwin*)
+		 # Again, we only want to link against shared libraries
+		 eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"`
+		 for tmp in $newlib_search_path ; do
+		     if test -f "$tmp/lib$tmp_libs.dylib" ; then
+		       eval depdepl="$tmp/lib$tmp_libs.dylib"
+		       break
+		     fi  
+         done
+         path=""
+		  ;;
+		*) continue ;;
+		esac  		  
+		;;
+	      *) continue ;;
+	      esac
+	      case " $deplibs " in
+	      *" $depdepl "*) ;;
+	      *) deplibs="$deplibs $depdepl" ;;
+	      esac	      
+	      case " $deplibs " in
+	      *" $path "*) ;;
+	      *) deplibs="$deplibs $path" ;;
+	      esac
+	    done
+	  fi # link_all_deplibs != no
+	fi # linkmode = lib
+      done # for deplib in $libs
+      dependency_libs="$newdependency_libs"
+      if test "$pass" = dlpreopen; then
+	# Link the dlpreopened libraries before other libraries
+	for deplib in $save_deplibs; do
+	  deplibs="$deplib $deplibs"
+	done
+      fi
+      if test "$pass" != dlopen; then
+	if test "$pass" != conv; then
+	  # Make sure lib_search_path contains only unique directories.
+	  lib_search_path=
+	  for dir in $newlib_search_path; do
+	    case "$lib_search_path " in
+	    *" $dir "*) ;;
+	    *) lib_search_path="$lib_search_path $dir" ;;
+	    esac
+	  done
+	  newlib_search_path=
+	fi
+
+	if test "$linkmode,$pass" != "prog,link"; then
+	  vars="deplibs"
+	else
+	  vars="compile_deplibs finalize_deplibs"
+	fi
+	for var in $vars dependency_libs; do
+	  # Add libraries to $var in reverse order
+	  eval tmp_libs=\"\$$var\"
+	  new_libs=
+	  for deplib in $tmp_libs; do
+	    # FIXME: Pedantically, this is the right thing to do, so
+	    #        that some nasty dependency loop isn't accidentally
+	    #        broken:
+	    #new_libs="$deplib $new_libs"
+	    # Pragmatically, this seems to cause very few problems in
+	    # practice:
+	    case $deplib in
+	    -L*) new_libs="$deplib $new_libs" ;;
+	    -R*) ;;
+	    *)
+	      # And here is the reason: when a library appears more
+	      # than once as an explicit dependence of a library, or
+	      # is implicitly linked in more than once by the
+	      # compiler, it is considered special, and multiple
+	      # occurrences thereof are not removed.  Compare this
+	      # with having the same library being listed as a
+	      # dependency of multiple other libraries: in this case,
+	      # we know (pedantically, we assume) the library does not
+	      # need to be listed more than once, so we keep only the
+	      # last copy.  This is not always right, but it is rare
+	      # enough that we require users that really mean to play
+	      # such unportable linking tricks to link the library
+	      # using -Wl,-lname, so that libtool does not consider it
+	      # for duplicate removal.
+	      case " $specialdeplibs " in
+	      *" $deplib "*) new_libs="$deplib $new_libs" ;;
+	      *)
+		case " $new_libs " in
+		*" $deplib "*) ;;
+		*) new_libs="$deplib $new_libs" ;;
+		esac
+		;;
+	      esac
+	      ;;
+	    esac
+	  done
+	  tmp_libs=
+	  for deplib in $new_libs; do
+	    case $deplib in
+	    -L*)
+	      case " $tmp_libs " in
+	      *" $deplib "*) ;;
+	      *) tmp_libs="$tmp_libs $deplib" ;;
+	      esac
+	      ;;
+	    *) tmp_libs="$tmp_libs $deplib" ;;
+	    esac
+	  done
+	  eval $var=\"$tmp_libs\"
+	done # for var
+      fi
+      # Last step: remove runtime libs from dependency_libs (they stay in deplibs)
+      tmp_libs=
+      for i in $dependency_libs ; do
+	case " $predeps $postdeps $compiler_lib_search_path " in
+	*" $i "*)
+	  i=""
+	  ;;
+	esac
+	if test -n "$i" ; then
+	  tmp_libs="$tmp_libs $i"
+	fi
+      done
+      dependency_libs=$tmp_libs
+    done # for pass
+    if test "$linkmode" = prog; then
+      dlfiles="$newdlfiles"
+      dlprefiles="$newdlprefiles"
+    fi
+
+    case $linkmode in
+    oldlib)
+      if test -n "$deplibs"; then
+	$echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
+      fi
+
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+	$echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$rpath"; then
+	$echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$xrpath"; then
+	$echo "$modename: warning: \`-R' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$vinfo"; then
+	$echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$release"; then
+	$echo "$modename: warning: \`-release' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+	$echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
+      fi
+
+      # Now set the variables for building old libraries.
+      build_libtool_libs=no
+      oldlibs="$output"
+      objs="$objs$old_deplibs"
+      ;;
+
+    lib)
+      # Make sure we only generate libraries of the form `libNAME.la'.
+      case $outputname in
+      lib*)
+	name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+	eval shared_ext=\"$shrext\"
+	eval libname=\"$libname_spec\"
+	;;
+      *)
+	if test "$module" = no; then
+	  $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
+	  $echo "$help" 1>&2
+	  exit 1
+	fi
+	if test "$need_lib_prefix" != no; then
+	  # Add the "lib" prefix for modules if required
+	  name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+	  eval shared_ext=\"$shrext\"
+	  eval libname=\"$libname_spec\"
+	else
+	  libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+	fi
+	;;
+      esac
+
+      if test -n "$objs"; then
+	if test "$deplibs_check_method" != pass_all; then
+	  $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
+	  exit 1
+	else
+	  $echo
+	  $echo "*** Warning: Linking the shared library $output against the non-libtool"
+	  $echo "*** objects $objs is not portable!"
+	  libobjs="$libobjs $objs"
+	fi
+      fi
+
+      if test "$dlself" != no; then
+	$echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2
+      fi
+
+      set dummy $rpath
+      if test "$#" -gt 2; then
+	$echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+      fi
+      install_libdir="$2"
+
+      oldlibs=
+      if test -z "$rpath"; then
+	if test "$build_libtool_libs" = yes; then
+	  # Building a libtool convenience library.
+	  # Some compilers have problems with a `.al' extension so
+	  # convenience libraries should have the same extension an
+	  # archive normally would.
+	  oldlibs="$output_objdir/$libname.$libext $oldlibs"
+	  build_libtool_libs=convenience
+	  build_old_libs=yes
+	fi
+
+	if test -n "$vinfo"; then
+	  $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2
+	fi
+
+	if test -n "$release"; then
+	  $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
+	fi
+      else
+
+	# Parse the version information argument.
+	save_ifs="$IFS"; IFS=':'
+	set dummy $vinfo 0 0 0
+	IFS="$save_ifs"
+
+	if test -n "$8"; then
+	  $echo "$modename: too many parameters to \`-version-info'" 1>&2
+	  $echo "$help" 1>&2
+	  exit 1
+	fi
+
+	# convert absolute version numbers to libtool ages
+	# this retains compatibility with .la files and attempts
+	# to make the code below a bit more comprehensible
+	
+	case $vinfo_number in
+	yes)
+	  number_major="$2"
+	  number_minor="$3"
+	  number_revision="$4"
+	  #
+	  # There are really only two kinds -- those that
+	  # use the current revision as the major version
+	  # and those that subtract age and use age as
+	  # a minor version.  But, then there is irix
+	  # which has an extra 1 added just for fun
+	  #
+	  case $version_type in
+	  darwin|linux|osf|windows)
+	    current=`expr $number_major + $number_minor`
+	    age="$number_minor"
+	    revision="$number_revision"
+	    ;;
+	  freebsd-aout|freebsd-elf|sunos)
+	    current="$number_major"
+	    revision="$number_minor"
+	    age="0"
+	    ;;
+	  irix|nonstopux)
+	    current=`expr $number_major + $number_minor - 1`
+	    age="$number_minor"
+	    revision="$number_minor"
+	    ;;
+	  esac
+	  ;;
+	no)
+	  current="$2"
+	  revision="$3"
+	  age="$4"
+	  ;;
+	esac
+
+	# Check that each of the things are valid numbers.
+	case $current in
+	0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
+	*)
+	  $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
+	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+	  exit 1
+	  ;;
+	esac
+
+	case $revision in
+	0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
+	*)
+	  $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
+	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+	  exit 1
+	  ;;
+	esac
+
+	case $age in
+	0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
+	*)
+	  $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
+	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+	  exit 1
+	  ;;
+	esac
+
+	if test "$age" -gt "$current"; then
+	  $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+	  exit 1
+	fi
+
+	# Calculate the version variables.
+	major=
+	versuffix=
+	verstring=
+	case $version_type in
+	none) ;;
+
+	darwin)
+	  # Like Linux, but with the current version available in
+	  # verstring for coding it into the library header
+	  major=.`expr $current - $age`
+	  versuffix="$major.$age.$revision"
+	  # Darwin ld doesn't like 0 for these options...
+	  minor_current=`expr $current + 1`
+	  verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+	  ;;
+
+	freebsd-aout)
+	  major=".$current"
+	  versuffix=".$current.$revision";
+	  ;;
+
+	freebsd-elf)
+	  major=".$current"
+	  versuffix=".$current";
+	  ;;
+
+	irix | nonstopux)
+	  major=`expr $current - $age + 1`
+
+	  case $version_type in
+	    nonstopux) verstring_prefix=nonstopux ;;
+	    *)         verstring_prefix=sgi ;;
+	  esac
+	  verstring="$verstring_prefix$major.$revision"
+
+	  # Add in all the interfaces that we are compatible with.
+	  loop=$revision
+	  while test "$loop" -ne 0; do
+	    iface=`expr $revision - $loop`
+	    loop=`expr $loop - 1`
+	    verstring="$verstring_prefix$major.$iface:$verstring"
+	  done
+
+	  # Before this point, $major must not contain `.'.
+	  major=.$major
+	  versuffix="$major.$revision"
+	  ;;
+
+	linux)
+	  major=.`expr $current - $age`
+	  versuffix="$major.$age.$revision"
+	  ;;
+
+	osf)
+	  major=.`expr $current - $age`
+	  versuffix=".$current.$age.$revision"
+	  verstring="$current.$age.$revision"
+
+	  # Add in all the interfaces that we are compatible with.
+	  loop=$age
+	  while test "$loop" -ne 0; do
+	    iface=`expr $current - $loop`
+	    loop=`expr $loop - 1`
+	    verstring="$verstring:${iface}.0"
+	  done
+
+	  # Make executables depend on our current version.
+	  verstring="$verstring:${current}.0"
+	  ;;
+
+	sunos)
+	  major=".$current"
+	  versuffix=".$current.$revision"
+	  ;;
+
+	windows)
+	  # Use '-' rather than '.', since we only want one
+	  # extension on DOS 8.3 filesystems.
+	  major=`expr $current - $age`
+	  versuffix="-$major"
+	  ;;
+
+	*)
+	  $echo "$modename: unknown library version type \`$version_type'" 1>&2
+	  $echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
+	  exit 1
+	  ;;
+	esac
+
+	# Clear the version info if we defaulted, and they specified a release.
+	if test -z "$vinfo" && test -n "$release"; then
+	  major=
+	  case $version_type in
+	  darwin)
+	    # we can't check for "0.0" in archive_cmds due to quoting
+	    # problems, so we reset it completely
+	    verstring=
+	    ;;
+	  *)
+	    verstring="0.0"
+	    ;;
+	  esac
+	  if test "$need_version" = no; then
+	    versuffix=
+	  else
+	    versuffix=".0.0"
+	  fi
+	fi
+
+	# Remove version info from name if versioning should be avoided
+	if test "$avoid_version" = yes && test "$need_version" = no; then
+	  major=
+	  versuffix=
+	  verstring=""
+	fi
+
+	# Check to see if the archive will have undefined symbols.
+	if test "$allow_undefined" = yes; then
+	  if test "$allow_undefined_flag" = unsupported; then
+	    $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+	    build_libtool_libs=no
+	    build_old_libs=yes
+	  fi
+	else
+	  # Don't allow undefined symbols.
+	  allow_undefined_flag="$no_undefined_flag"
+	fi
+      fi
+
+      if test "$mode" != relink; then
+	# Remove our outputs, but don't remove object files since they
+	# may have been created when compiling PIC objects.
+	removelist=
+	tempremovelist=`$echo "$output_objdir/*"`
+	for p in $tempremovelist; do
+	  case $p in
+	    *.$objext)
+	       ;;
+	    $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+	       removelist="$removelist $p"
+	       ;;
+	    *) ;;
+	  esac
+	done
+	if test -n "$removelist"; then
+	  $show "${rm}r $removelist"
+	  $run ${rm}r $removelist
+	fi
+      fi
+
+      # Now set the variables for building old libraries.
+      if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+	oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+	# Transform .lo files to .o files.
+	oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+      fi
+
+      # Eliminate all temporary directories.
+      for path in $notinst_path; do
+	lib_search_path=`$echo "$lib_search_path " | ${SED} -e 's% $path % %g'`
+	deplibs=`$echo "$deplibs " | ${SED} -e 's% -L$path % %g'`
+	dependency_libs=`$echo "$dependency_libs " | ${SED} -e 's% -L$path % %g'`
+      done
+
+      if test -n "$xrpath"; then
+	# If the user specified any rpath flags, then add them.
+	temp_xrpath=
+	for libdir in $xrpath; do
+	  temp_xrpath="$temp_xrpath -R$libdir"
+	  case "$finalize_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_rpath="$finalize_rpath $libdir" ;;
+	  esac
+	done
+	if true || test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+	  dependency_libs="$temp_xrpath $dependency_libs"
+	fi
+      fi
+
+      # Make sure dlfiles contains only unique files that won't be dlpreopened
+      old_dlfiles="$dlfiles"
+      dlfiles=
+      for lib in $old_dlfiles; do
+	case " $dlprefiles $dlfiles " in
+	*" $lib "*) ;;
+	*) dlfiles="$dlfiles $lib" ;;
+	esac
+      done
+
+      # Make sure dlprefiles contains only unique files
+      old_dlprefiles="$dlprefiles"
+      dlprefiles=
+      for lib in $old_dlprefiles; do
+	case "$dlprefiles " in
+	*" $lib "*) ;;
+	*) dlprefiles="$dlprefiles $lib" ;;
+	esac
+      done
+
+      if test "$build_libtool_libs" = yes; then
+	if test -n "$rpath"; then
+	  case $host in
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*)
+	    # these systems don't actually have a c library (as such)!
+	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C library is in the System framework
+	    deplibs="$deplibs -framework System"
+	    ;;
+	  *-*-netbsd*)
+	    # Don't link with libc until the a.out ld.so is fixed.
+	    ;;
+	  *-*-freebsd*-gnu*)
+	    # Prevent $arg from being parsed by the freebsd regexp below.
+	    if test "$build_libtool_need_lc" = "yes"; then
+	      deplibs="$deplibs -lc"
+	    fi
+	    ;;
+	  *-*-openbsd* | *-*-freebsd*)
+	    # Do not include libc due to us having libc/libc_r.
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+ 	  *)
+	    # Add libc to deplibs on all other systems if necessary.
+	    if test "$build_libtool_need_lc" = "yes"; then
+	      deplibs="$deplibs -lc"
+	    fi
+	    ;;
+	  esac
+	fi
+
+	# Transform deplibs into only deplibs that can be linked in shared.
+	name_save=$name
+	libname_save=$libname
+	release_save=$release
+	versuffix_save=$versuffix
+	major_save=$major
+	# I'm not sure if I'm treating the release correctly.  I think
+	# release should show up in the -l (ie -lgmp5) so we don't want to
+	# add it in twice.  Is that correct?
+	release=""
+	versuffix=""
+	major=""
+	newdeplibs=
+	droppeddeps=no
+	case $deplibs_check_method in
+	pass_all)
+	  # Don't check for shared/static.  Everything works.
+	  # This might be a little naive.  We might want to check
+	  # whether the library exists or not.  But this is on
+	  # osf3 & osf4 and I'm not really sure... Just
+	  # implementing what was already the behavior.
+	  newdeplibs=$deplibs
+	  ;;
+	test_compile)
+	  # This code stresses the "libraries are programs" paradigm to its
+	  # limits. Maybe even breaks it.  We compile a program, linking it
+	  # against the deplibs as a proxy for the library.  Then we can check
+	  # whether they linked in statically or dynamically with ldd.
+	  $rm conftest.c
+	  cat > conftest.c <<EOF
+	  int main() { return 0; }
+EOF
+	  $rm conftest
+	  $LTCC -o conftest conftest.c $deplibs
+	  if test "$?" -eq 0 ; then
+	    ldd_output=`ldd conftest`
+	    for i in $deplibs; do
+	      name="`expr $i : '-l\(.*\)'`"
+	      # If $name is empty we are operating on a -L argument.
+              if test "$name" != "" && test "$name" -ne "0"; then
+		if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		  case " $predeps $postdeps " in
+		  *" $i "*)
+		    newdeplibs="$newdeplibs $i"
+		    i=""
+		    ;;
+		  esac
+	        fi
+		if test -n "$i" ; then
+		  libname=`eval \\$echo \"$libname_spec\"`
+		  deplib_matches=`eval \\$echo \"$library_names_spec\"`
+		  set dummy $deplib_matches
+		  deplib_match=$2
+		  if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+		    newdeplibs="$newdeplibs $i"
+		  else
+		    droppeddeps=yes
+		    $echo
+		    $echo "*** Warning: dynamic linker does not accept needed library $i."
+		    $echo "*** I have the capability to make that library automatically link in when"
+		    $echo "*** you link to this library.  But I can only do this if you have a"
+		    $echo "*** shared version of the library, which I believe you do not have"
+		    $echo "*** because a test_compile did reveal that the linker did not use it for"
+		    $echo "*** its dynamic dependency list that programs get resolved with at runtime."
+		  fi
+		fi
+	      else
+		newdeplibs="$newdeplibs $i"
+	      fi
+	    done
+	  else
+	    # Error occurred in the first compile.  Let's try to salvage
+	    # the situation: Compile a separate program for each library.
+	    for i in $deplibs; do
+	      name="`expr $i : '-l\(.*\)'`"
+	      # If $name is empty we are operating on a -L argument.
+              if test "$name" != "" && test "$name" != "0"; then
+		$rm conftest
+		$LTCC -o conftest conftest.c $i
+		# Did it work?
+		if test "$?" -eq 0 ; then
+		  ldd_output=`ldd conftest`
+		  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		    case " $predeps $postdeps " in
+		    *" $i "*)
+		      newdeplibs="$newdeplibs $i"
+		      i=""
+		      ;;
+		    esac
+		  fi
+		  if test -n "$i" ; then
+		    libname=`eval \\$echo \"$libname_spec\"`
+		    deplib_matches=`eval \\$echo \"$library_names_spec\"`
+		    set dummy $deplib_matches
+		    deplib_match=$2
+		    if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+		      newdeplibs="$newdeplibs $i"
+		    else
+		      droppeddeps=yes
+		      $echo
+		      $echo "*** Warning: dynamic linker does not accept needed library $i."
+		      $echo "*** I have the capability to make that library automatically link in when"
+		      $echo "*** you link to this library.  But I can only do this if you have a"
+		      $echo "*** shared version of the library, which you do not appear to have"
+		      $echo "*** because a test_compile did reveal that the linker did not use this one"
+		      $echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+		    fi
+		  fi
+		else
+		  droppeddeps=yes
+		  $echo
+		  $echo "*** Warning!  Library $i is needed by this library but I was not able to"
+		  $echo "***  make it link in!  You will probably need to install it or some"
+		  $echo "*** library that it depends on before this library will be fully"
+		  $echo "*** functional.  Installing it before continuing would be even better."
+		fi
+	      else
+		newdeplibs="$newdeplibs $i"
+	      fi
+	    done
+	  fi
+	  ;;
+	file_magic*)
+	  set dummy $deplibs_check_method
+	  file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+	  for a_deplib in $deplibs; do
+	    name="`expr $a_deplib : '-l\(.*\)'`"
+	    # If $name is empty we are operating on a -L argument.
+            if test "$name" != "" && test  "$name" != "0"; then
+	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  newdeplibs="$newdeplibs $a_deplib"
+		  a_deplib=""
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib" ; then
+		libname=`eval \\$echo \"$libname_spec\"`
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+		  for potent_lib in $potential_libs; do
+		      # Follow soft links.
+		      if ls -lLd "$potent_lib" 2>/dev/null \
+			 | grep " -> " >/dev/null; then
+			continue
+		      fi
+		      # The statement above tries to avoid entering an
+		      # endless loop below, in case of cyclic links.
+		      # We might still enter an endless loop, since a link
+		      # loop can be closed while we follow links,
+		      # but so what?
+		      potlib="$potent_lib"
+		      while test -h "$potlib" 2>/dev/null; do
+			potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+			case $potliblink in
+			[\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+			*) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+			esac
+		      done
+		      if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
+			 | ${SED} 10q \
+			 | $EGREP "$file_magic_regex" > /dev/null; then
+			newdeplibs="$newdeplibs $a_deplib"
+			a_deplib=""
+			break 2
+		      fi
+		  done
+		done
+	      fi
+	      if test -n "$a_deplib" ; then
+		droppeddeps=yes
+		$echo
+		$echo "*** Warning: linker path does not have real file for library $a_deplib."
+		$echo "*** I have the capability to make that library automatically link in when"
+		$echo "*** you link to this library.  But I can only do this if you have a"
+		$echo "*** shared version of the library, which you do not appear to have"
+		$echo "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib" ; then
+		  $echo "*** with $libname but no candidates were found. (...for file magic test)"
+		else
+		  $echo "*** with $libname and none of the candidates passed a file format test"
+		  $echo "*** using a file magic. Last file checked: $potlib"
+		fi
+	      fi
+	    else
+	      # Add a -L argument.
+	      newdeplibs="$newdeplibs $a_deplib"
+	    fi
+	  done # Gone through all deplibs.
+	  ;;
+	match_pattern*)
+	  set dummy $deplibs_check_method
+	  match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+	  for a_deplib in $deplibs; do
+	    name="`expr $a_deplib : '-l\(.*\)'`"
+	    # If $name is empty we are operating on a -L argument.
+	    if test -n "$name" && test "$name" != "0"; then
+	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  newdeplibs="$newdeplibs $a_deplib"
+		  a_deplib=""
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib" ; then
+		libname=`eval \\$echo \"$libname_spec\"`
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+		  for potent_lib in $potential_libs; do
+		    potlib="$potent_lib" # see symlink-check above in file_magic test
+		    if eval $echo \"$potent_lib\" 2>/dev/null \
+		        | ${SED} 10q \
+		        | $EGREP "$match_pattern_regex" > /dev/null; then
+		      newdeplibs="$newdeplibs $a_deplib"
+		      a_deplib=""
+		      break 2
+		    fi
+		  done
+		done
+	      fi
+	      if test -n "$a_deplib" ; then
+		droppeddeps=yes
+		$echo
+		$echo "*** Warning: linker path does not have real file for library $a_deplib."
+		$echo "*** I have the capability to make that library automatically link in when"
+		$echo "*** you link to this library.  But I can only do this if you have a"
+		$echo "*** shared version of the library, which you do not appear to have"
+		$echo "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib" ; then
+		  $echo "*** with $libname but no candidates were found. (...for regex pattern test)"
+		else
+		  $echo "*** with $libname and none of the candidates passed a file format test"
+		  $echo "*** using a regex pattern. Last file checked: $potlib"
+		fi
+	      fi
+	    else
+	      # Add a -L argument.
+	      newdeplibs="$newdeplibs $a_deplib"
+	    fi
+	  done # Gone through all deplibs.
+	  ;;
+	none | unknown | *)
+	  newdeplibs=""
+	  tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
+	    -e 's/ -[LR][^ ]*//g'`
+	  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+	    for i in $predeps $postdeps ; do
+	      # can't use Xsed below, because $i might contain '/'
+	      tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"`
+	    done
+	  fi
+	  if $echo "X $tmp_deplibs" | $Xsed -e 's/[ 	]//g' \
+	    | grep . >/dev/null; then
+	    $echo
+	    if test "X$deplibs_check_method" = "Xnone"; then
+	      $echo "*** Warning: inter-library dependencies are not supported in this platform."
+	    else
+	      $echo "*** Warning: inter-library dependencies are not known to be supported."
+	    fi
+	    $echo "*** All declared inter-library dependencies are being dropped."
+	    droppeddeps=yes
+	  fi
+	  ;;
+	esac
+	versuffix=$versuffix_save
+	major=$major_save
+	release=$release_save
+	libname=$libname_save
+	name=$name_save
+
+	case $host in
+	*-*-rhapsody* | *-*-darwin1.[012])
+	  # On Rhapsody replace the C library is the System framework
+	  newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'`
+	  ;;
+	esac
+
+	if test "$droppeddeps" = yes; then
+	  if test "$module" = yes; then
+	    $echo
+	    $echo "*** Warning: libtool could not satisfy all declared inter-library"
+	    $echo "*** dependencies of module $libname.  Therefore, libtool will create"
+	    $echo "*** a static module, that should work as long as the dlopening"
+	    $echo "*** application is linked with the -dlopen flag."
+	    if test -z "$global_symbol_pipe"; then
+	      $echo
+	      $echo "*** However, this would only work if libtool was able to extract symbol"
+	      $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+	      $echo "*** not find such a program.  So, this module is probably useless."
+	      $echo "*** \`nm' from GNU binutils and a full rebuild may help."
+	    fi
+	    if test "$build_old_libs" = no; then
+	      oldlibs="$output_objdir/$libname.$libext"
+	      build_libtool_libs=module
+	      build_old_libs=yes
+	    else
+	      build_libtool_libs=no
+	    fi
+	  else
+	    $echo "*** The inter-library dependencies that have been dropped here will be"
+	    $echo "*** automatically added whenever a program is linked with this library"
+	    $echo "*** or is declared to -dlopen it."
+
+	    if test "$allow_undefined" = no; then
+	      $echo
+	      $echo "*** Since this library must not contain undefined symbols,"
+	      $echo "*** because either the platform does not support them or"
+	      $echo "*** it was explicitly requested with -no-undefined,"
+	      $echo "*** libtool will only create a static version of it."
+	      if test "$build_old_libs" = no; then
+		oldlibs="$output_objdir/$libname.$libext"
+		build_libtool_libs=module
+		build_old_libs=yes
+	      else
+		build_libtool_libs=no
+	      fi
+	    fi
+	  fi
+	fi
+	# Done checking deplibs!
+	deplibs=$newdeplibs
+      fi
+
+      # All the library-specific variables (install_libdir is set above).
+      library_names=
+      old_library=
+      dlname=
+
+      # Test again, we may have decided not to build it any more
+      if test "$build_libtool_libs" = yes; then
+	if test "$hardcode_into_libs" = yes; then
+	  # Hardcode the library paths
+	  hardcode_libdirs=
+	  dep_rpath=
+	  rpath="$finalize_rpath"
+	  test "$mode" != relink && test "$fast_install" = no && rpath="$compile_rpath$rpath"
+	  for libdir in $rpath; do
+	    if test -n "$hardcode_libdir_flag_spec"; then
+	      if test -n "$hardcode_libdir_separator"; then
+		if test -z "$hardcode_libdirs"; then
+		  hardcode_libdirs="$libdir"
+		else
+		  # Just accumulate the unique libdirs.
+		  case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+		  *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		    ;;
+		  *)
+		    hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		    ;;
+		  esac
+		fi
+	      else
+		eval flag=\"$hardcode_libdir_flag_spec\"
+		dep_rpath="$dep_rpath $flag"
+	      fi
+	    elif test -n "$runpath_var"; then
+	      case "$perm_rpath " in
+	      *" $libdir "*) ;;
+	      *) perm_rpath="$perm_rpath $libdir" ;;
+	      esac
+	    fi
+	  done
+	  # Substitute the hardcoded libdirs into the rpath.
+	  if test -n "$hardcode_libdir_separator" &&
+	     test -n "$hardcode_libdirs"; then
+	    libdir="$hardcode_libdirs"
+	    if test -n "$hardcode_libdir_flag_spec_ld"; then
+	      eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
+	    else
+	      eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+	    fi
+	  fi
+	  if test -n "$runpath_var" && test -n "$perm_rpath"; then
+	    # We should set the runpath_var.
+	    rpath=
+	    for dir in $perm_rpath; do
+	      rpath="$rpath$dir:"
+	    done
+	    eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+	  fi
+	  test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+	fi
+
+	shlibpath="$finalize_shlibpath"
+	test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+	if test -n "$shlibpath"; then
+	  eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+	fi
+
+	# Get the real and link names of the library.
+	eval shared_ext=\"$shrext\"
+	eval library_names=\"$library_names_spec\"
+	set dummy $library_names
+	realname="$2"
+	shift; shift
+
+	if test -n "$soname_spec"; then
+	  eval soname=\"$soname_spec\"
+	else
+	  soname="$realname"
+	fi
+	if test -z "$dlname"; then
+	  dlname=$soname
+	fi
+
+	lib="$output_objdir/$realname"
+	for link
+	do
+	  linknames="$linknames $link"
+	done
+
+	# Use standard objects if they are pic
+	test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+
+	# Prepare the list of exported symbols
+	if test -z "$export_symbols"; then
+	  if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+	    $show "generating symbol list for \`$libname.la'"
+	    export_symbols="$output_objdir/$libname.exp"
+	    $run $rm $export_symbols
+	    eval cmds=\"$export_symbols_cmds\"
+	    save_ifs="$IFS"; IFS='~'
+	    for cmd in $cmds; do
+	      IFS="$save_ifs"
+	      if len=`expr "X$cmd" : ".*"` &&
+	       test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	        $show "$cmd"
+	        $run eval "$cmd" || exit $?
+	        skipped_export=false
+	      else
+	        # The command line is too long to execute in one step.
+	        $show "using reloadable object file for export list..."
+	        skipped_export=:
+	      fi
+	    done
+	    IFS="$save_ifs"
+	    if test -n "$export_symbols_regex"; then
+	      $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
+	      $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+	      $show "$mv \"${export_symbols}T\" \"$export_symbols\""
+	      $run eval '$mv "${export_symbols}T" "$export_symbols"'
+	    fi
+	  fi
+	fi
+
+	if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	  $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
+	fi
+
+	tmp_deplibs=
+	for test_deplib in $deplibs; do
+		case " $convenience " in
+		*" $test_deplib "*) ;;
+		*) 
+			tmp_deplibs="$tmp_deplibs $test_deplib"
+			;;
+		esac
+	done
+	deplibs="$tmp_deplibs" 
+
+	if test -n "$convenience"; then
+	  if test -n "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+	  else
+	    gentop="$output_objdir/${outputname}x"
+	    $show "${rm}r $gentop"
+	    $run ${rm}r "$gentop"
+	    $show "$mkdir $gentop"
+	    $run $mkdir "$gentop"
+	    status=$?
+	    if test "$status" -ne 0 && test ! -d "$gentop"; then
+	      exit $status
+	    fi
+	    generated="$generated $gentop"
+
+	    for xlib in $convenience; do
+	      # Extract the objects.
+	      case $xlib in
+	      [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+	      *) xabs=`pwd`"/$xlib" ;;
+	      esac
+	      xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+	      xdir="$gentop/$xlib"
+
+	      $show "${rm}r $xdir"
+	      $run ${rm}r "$xdir"
+	      $show "$mkdir $xdir"
+	      $run $mkdir "$xdir"
+	      status=$?
+	      if test "$status" -ne 0 && test ! -d "$xdir"; then
+		exit $status
+	      fi
+	      # We will extract separately just the conflicting names and we will no
+	      # longer touch any unique names. It is faster to leave these extract
+	      # automatically by $AR in one run.
+	      $show "(cd $xdir && $AR x $xabs)"
+	      $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+	      if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then
+		:
+	      else
+		$echo "$modename: warning: object name conflicts; renaming object files" 1>&2
+		$echo "$modename: warning: to ensure that they will not overwrite" 1>&2
+		$AR t "$xabs" | sort | uniq -cd | while read -r count name
+		do
+		  i=1
+		  while test "$i" -le "$count"
+		  do
+		   # Put our $i before any first dot (extension)
+		   # Never overwrite any file
+		   name_to="$name"
+		   while test "X$name_to" = "X$name" || test -f "$xdir/$name_to"
+		   do
+		     name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
+		   done
+		   $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')"
+		   $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $?
+		   i=`expr $i + 1`
+		  done
+		done
+	      fi
+
+	      libobjs="$libobjs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+	    done
+	  fi
+	fi
+
+	if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+	  eval flag=\"$thread_safe_flag_spec\"
+	  linker_flags="$linker_flags $flag"
+	fi
+
+	# Make a backup of the uninstalled library when relinking
+	if test "$mode" = relink; then
+	  $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $?
+	fi
+
+	# Add all flags from the command line.  We here create a library,
+	# but those flags were only added to compile_command and
+	# finalize_command, which are only used when creating executables.
+	# So do it by hand here.
+	compiler_flags="$compiler_flags $add_flags"
+	# Only add it to commands which use CC, instead of LD, i.e.
+	# only to $compiler_flags
+	#linker_flags="$linker_flags $add_flags"
+
+	# Do each of the archive commands.
+	if test "$module" = yes && test -n "$module_cmds" ; then
+	  if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	    eval cmds=\"$module_expsym_cmds\"
+	  else
+	    eval cmds=\"$module_cmds\"
+	  fi
+	else
+	if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	  eval cmds=\"$archive_expsym_cmds\"
+	else
+	  eval cmds=\"$archive_cmds\"
+	  fi
+	fi
+
+	if test "X$skipped_export" != "X:" && len=`expr "X$cmds" : ".*"` &&
+	   test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  :
+	else
+	  # The command line is too long to link in one step, link piecewise.
+	  $echo "creating reloadable object files..."
+
+	  # Save the value of $output and $libobjs because we want to
+	  # use them later.  If we have whole_archive_flag_spec, we
+	  # want to use save_libobjs as it was before
+	  # whole_archive_flag_spec was expanded, because we can't
+	  # assume the linker understands whole_archive_flag_spec.
+	  # This may have to be revisited, in case too many
+	  # convenience libraries get linked in and end up exceeding
+	  # the spec.
+	  if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	  fi
+	  save_output=$output
+
+	  # Clear the reloadable object creation command queue and
+	  # initialize k to one.
+	  test_cmds=
+	  concat_cmds=
+	  objlist=
+	  delfiles=
+	  last_robj=
+	  k=1
+	  output=$output_objdir/$save_output-${k}.$objext
+	  # Loop over the list of objects to be linked.
+	  for obj in $save_libobjs
+	  do
+	    eval test_cmds=\"$reload_cmds $objlist $last_robj\"
+	    if test "X$objlist" = X ||
+	       { len=`expr "X$test_cmds" : ".*"` &&
+		 test "$len" -le "$max_cmd_len"; }; then
+	      objlist="$objlist $obj"
+	    else
+	      # The command $test_cmds is almost too long, add a
+	      # command to the queue.
+	      if test "$k" -eq 1 ; then
+		# The first file doesn't have a previous command to add.
+		eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
+	      else
+		# All subsequent reloadable object files will link in
+		# the last one created.
+		eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
+	      fi
+	      last_robj=$output_objdir/$save_output-${k}.$objext
+	      k=`expr $k + 1`
+	      output=$output_objdir/$save_output-${k}.$objext
+	      objlist=$obj
+	      len=1
+	    fi
+	  done
+	  # Handle the remaining objects by creating one last
+	  # reloadable object file.  All subsequent reloadable object
+	  # files will link in the last one created.
+	  test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	  eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
+
+	  if ${skipped_export-false}; then
+	    $show "generating symbol list for \`$libname.la'"
+	    export_symbols="$output_objdir/$libname.exp"
+	    $run $rm $export_symbols
+	    libobjs=$output
+	    # Append the command to create the export file.
+	    eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
+          fi
+
+	  # Set up a command to remove the reloadale object files
+	  # after they are used.
+	  i=0
+	  while test "$i" -lt "$k"
+	  do
+	    i=`expr $i + 1`
+	    delfiles="$delfiles $output_objdir/$save_output-${i}.$objext"
+	  done
+
+	  $echo "creating a temporary reloadable object file: $output"
+
+	  # Loop through the commands generated above and execute them.
+	  save_ifs="$IFS"; IFS='~'
+	  for cmd in $concat_cmds; do
+	    IFS="$save_ifs"
+	    $show "$cmd"
+	    $run eval "$cmd" || exit $?
+	  done
+	  IFS="$save_ifs"
+
+	  libobjs=$output
+	  # Restore the value of output.
+	  output=$save_output
+
+	  if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+	  fi
+	  # Expand the library linking commands again to reset the
+	  # value of $libobjs for piecewise linking.
+
+	  # Do each of the archive commands.
+	  if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	    eval cmds=\"$archive_expsym_cmds\"
+	  else
+	    eval cmds=\"$archive_cmds\"
+	  fi
+
+	  # Append the command to remove the reloadable object files
+	  # to the just-reset $cmds.
+	  eval cmds=\"\$cmds~$rm $delfiles\"
+	fi
+	save_ifs="$IFS"; IFS='~'
+	for cmd in $cmds; do
+	  IFS="$save_ifs"
+	  $show "$cmd"
+	  $run eval "$cmd" || exit $?
+	done
+	IFS="$save_ifs"
+
+	# Restore the uninstalled library and exit
+	if test "$mode" = relink; then
+	  $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
+	  exit 0
+	fi
+
+	# Create links to the real library.
+	for linkname in $linknames; do
+	  if test "$realname" != "$linkname"; then
+	    $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
+	    $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
+	  fi
+	done
+
+	# If -module or -export-dynamic was specified, set the dlname.
+	if test "$module" = yes || test "$export_dynamic" = yes; then
+	  # On all known operating systems, these are identical.
+	  dlname="$soname"
+	fi
+      fi
+      ;;
+
+    obj)
+      if test -n "$deplibs"; then
+	$echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
+      fi
+
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+	$echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$rpath"; then
+	$echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$xrpath"; then
+	$echo "$modename: warning: \`-R' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$vinfo"; then
+	$echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$release"; then
+	$echo "$modename: warning: \`-release' is ignored for objects" 1>&2
+      fi
+
+      case $output in
+      *.lo)
+	if test -n "$objs$old_deplibs"; then
+	  $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
+	  exit 1
+	fi
+	libobj="$output"
+	obj=`$echo "X$output" | $Xsed -e "$lo2o"`
+	;;
+      *)
+	libobj=
+	obj="$output"
+	;;
+      esac
+
+      # Delete the old objects.
+      $run $rm $obj $libobj
+
+      # Objects from convenience libraries.  This assumes
+      # single-version convenience libraries.  Whenever we create
+      # different ones for PIC/non-PIC, this we'll have to duplicate
+      # the extraction.
+      reload_conv_objs=
+      gentop=
+      # reload_cmds runs $LD directly, so let us get rid of
+      # -Wl from whole_archive_flag_spec
+      wl=
+
+      if test -n "$convenience"; then
+	if test -n "$whole_archive_flag_spec"; then
+	  eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
+	else
+	  gentop="$output_objdir/${obj}x"
+	  $show "${rm}r $gentop"
+	  $run ${rm}r "$gentop"
+	  $show "$mkdir $gentop"
+	  $run $mkdir "$gentop"
+	  status=$?
+	  if test "$status" -ne 0 && test ! -d "$gentop"; then
+	    exit $status
+	  fi
+	  generated="$generated $gentop"
+
+	  for xlib in $convenience; do
+	    # Extract the objects.
+	    case $xlib in
+	    [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+	    *) xabs=`pwd`"/$xlib" ;;
+	    esac
+	    xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+	    xdir="$gentop/$xlib"
+
+	    $show "${rm}r $xdir"
+	    $run ${rm}r "$xdir"
+	    $show "$mkdir $xdir"
+	    $run $mkdir "$xdir"
+	    status=$?
+	    if test "$status" -ne 0 && test ! -d "$xdir"; then
+	      exit $status
+	    fi
+	    # We will extract separately just the conflicting names and we will no
+	    # longer touch any unique names. It is faster to leave these extract
+	    # automatically by $AR in one run.
+	    $show "(cd $xdir && $AR x $xabs)"
+	    $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+	    if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then
+	      :
+	    else
+	      $echo "$modename: warning: object name conflicts; renaming object files" 1>&2
+	      $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
+	      $AR t "$xabs" | sort | uniq -cd | while read -r count name
+	      do
+		i=1
+		while test "$i" -le "$count"
+		do
+		 # Put our $i before any first dot (extension)
+		 # Never overwrite any file
+		 name_to="$name"
+		 while test "X$name_to" = "X$name" || test -f "$xdir/$name_to"
+		 do
+		   name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
+		 done
+		 $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')"
+		 $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $?
+		 i=`expr $i + 1`
+		done
+	      done
+	    fi
+
+	    reload_conv_objs="$reload_objs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+	  done
+	fi
+      fi
+
+      # Create the old-style object.
+      reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+      output="$obj"
+      eval cmds=\"$reload_cmds\"
+      save_ifs="$IFS"; IFS='~'
+      for cmd in $cmds; do
+	IFS="$save_ifs"
+	$show "$cmd"
+	$run eval "$cmd" || exit $?
+      done
+      IFS="$save_ifs"
+
+      # Exit if we aren't doing a library object file.
+      if test -z "$libobj"; then
+	if test -n "$gentop"; then
+	  $show "${rm}r $gentop"
+	  $run ${rm}r $gentop
+	fi
+
+	exit 0
+      fi
+
+      if test "$build_libtool_libs" != yes; then
+	if test -n "$gentop"; then
+	  $show "${rm}r $gentop"
+	  $run ${rm}r $gentop
+	fi
+
+	# Create an invalid libtool object if no PIC, so that we don't
+	# accidentally link it into a program.
+	# $show "echo timestamp > $libobj"
+	# $run eval "echo timestamp > $libobj" || exit $?
+	exit 0
+      fi
+
+      if test -n "$pic_flag" || test "$pic_mode" != default; then
+	# Only do commands if we really have different PIC objects.
+	reload_objs="$libobjs $reload_conv_objs"
+	output="$libobj"
+	eval cmds=\"$reload_cmds\"
+	save_ifs="$IFS"; IFS='~'
+	for cmd in $cmds; do
+	  IFS="$save_ifs"
+	  $show "$cmd"
+	  $run eval "$cmd" || exit $?
+	done
+	IFS="$save_ifs"
+      fi
+
+      if test -n "$gentop"; then
+	$show "${rm}r $gentop"
+	$run ${rm}r $gentop
+      fi
+
+      exit 0
+      ;;
+
+    prog)
+      case $host in
+	*cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
+      esac
+      if test -n "$vinfo"; then
+	$echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
+      fi
+
+      if test -n "$release"; then
+	$echo "$modename: warning: \`-release' is ignored for programs" 1>&2
+      fi
+
+      if test "$preload" = yes; then
+	if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown &&
+	   test "$dlopen_self_static" = unknown; then
+	  $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
+	fi
+      fi
+
+      case $host in
+      *-*-rhapsody* | *-*-darwin1.[012])
+	# On Rhapsody replace the C library is the System framework
+	compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+	finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+	;;
+      esac
+
+      case $host in
+      *darwin*)
+        # Don't allow lazy linking, it breaks C++ global constructors
+        if test "$tagname" = CXX ; then
+        compile_command="$compile_command ${wl}-bind_at_load"
+        finalize_command="$finalize_command ${wl}-bind_at_load"
+        fi
+        ;;
+      esac
+
+      compile_command="$compile_command $compile_deplibs"
+      finalize_command="$finalize_command $finalize_deplibs"
+
+      if test -n "$rpath$xrpath"; then
+	# If the user specified any rpath flags, then add them.
+	for libdir in $rpath $xrpath; do
+	  # This is the magic to use -rpath.
+	  case "$finalize_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_rpath="$finalize_rpath $libdir" ;;
+	  esac
+	done
+      fi
+
+      # Now hardcode the library paths
+      rpath=
+      hardcode_libdirs=
+      for libdir in $compile_rpath $finalize_rpath; do
+	if test -n "$hardcode_libdir_flag_spec"; then
+	  if test -n "$hardcode_libdir_separator"; then
+	    if test -z "$hardcode_libdirs"; then
+	      hardcode_libdirs="$libdir"
+	    else
+	      # Just accumulate the unique libdirs.
+	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		;;
+	      *)
+		hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		;;
+	      esac
+	    fi
+	  else
+	    eval flag=\"$hardcode_libdir_flag_spec\"
+	    rpath="$rpath $flag"
+	  fi
+	elif test -n "$runpath_var"; then
+	  case "$perm_rpath " in
+	  *" $libdir "*) ;;
+	  *) perm_rpath="$perm_rpath $libdir" ;;
+	  esac
+	fi
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+	  case :$dllsearchpath: in
+	  *":$libdir:"*) ;;
+	  *) dllsearchpath="$dllsearchpath:$libdir";;
+	  esac
+	  ;;
+	esac
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+	 test -n "$hardcode_libdirs"; then
+	libdir="$hardcode_libdirs"
+	eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      compile_rpath="$rpath"
+
+      rpath=
+      hardcode_libdirs=
+      for libdir in $finalize_rpath; do
+	if test -n "$hardcode_libdir_flag_spec"; then
+	  if test -n "$hardcode_libdir_separator"; then
+	    if test -z "$hardcode_libdirs"; then
+	      hardcode_libdirs="$libdir"
+	    else
+	      # Just accumulate the unique libdirs.
+	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		;;
+	      *)
+		hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		;;
+	      esac
+	    fi
+	  else
+	    eval flag=\"$hardcode_libdir_flag_spec\"
+	    rpath="$rpath $flag"
+	  fi
+	elif test -n "$runpath_var"; then
+	  case "$finalize_perm_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+	  esac
+	fi
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+	 test -n "$hardcode_libdirs"; then
+	libdir="$hardcode_libdirs"
+	eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      finalize_rpath="$rpath"
+
+      if test -n "$libobjs" && test "$build_old_libs" = yes; then
+	# Transform all the library objects into standard objects.
+	compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+	finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+      fi
+
+      dlsyms=
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+	if test -n "$NM" && test -n "$global_symbol_pipe"; then
+	  dlsyms="${outputname}S.c"
+	else
+	  $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
+	fi
+      fi
+
+      if test -n "$dlsyms"; then
+	case $dlsyms in
+	"") ;;
+	*.c)
+	  # Discover the nlist of each of the dlfiles.
+	  nlist="$output_objdir/${outputname}.nm"
+
+	  $show "$rm $nlist ${nlist}S ${nlist}T"
+	  $run $rm "$nlist" "${nlist}S" "${nlist}T"
+
+	  # Parse the name list into a source file.
+	  $show "creating $output_objdir/$dlsyms"
+
+	  test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
+/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define lt_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */\
+"
+
+	  if test "$dlself" = yes; then
+	    $show "generating symbol list for \`$output'"
+
+	    test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
+
+	    # Add our own program objects to the symbol list.
+	    progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+	    for arg in $progfiles; do
+	      $show "extracting global C symbols from \`$arg'"
+	      $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+	    done
+
+	    if test -n "$exclude_expsyms"; then
+	      $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+	      $run eval '$mv "$nlist"T "$nlist"'
+	    fi
+
+	    if test -n "$export_symbols_regex"; then
+	      $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+	      $run eval '$mv "$nlist"T "$nlist"'
+	    fi
+
+	    # Prepare the list of exported symbols
+	    if test -z "$export_symbols"; then
+	      export_symbols="$output_objdir/$output.exp"
+	      $run $rm $export_symbols
+	      $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+	    else
+	      $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
+	      $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
+	      $run eval 'mv "$nlist"T "$nlist"'
+	    fi
+	  fi
+
+	  for arg in $dlprefiles; do
+	    $show "extracting global C symbols from \`$arg'"
+	    name=`$echo "$arg" | ${SED} -e 's%^.*/%%'`
+	    $run eval '$echo ": $name " >> "$nlist"'
+	    $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+	  done
+
+	  if test -z "$run"; then
+	    # Make sure we have at least an empty file.
+	    test -f "$nlist" || : > "$nlist"
+
+	    if test -n "$exclude_expsyms"; then
+	      $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+	      $mv "$nlist"T "$nlist"
+	    fi
+
+	    # Try sorting and uniquifying the output.
+	    if grep -v "^: " < "$nlist" |
+		if sort -k 3 </dev/null >/dev/null 2>&1; then
+		  sort -k 3
+		else
+		  sort +2
+		fi |
+		uniq > "$nlist"S; then
+	      :
+	    else
+	      grep -v "^: " < "$nlist" > "$nlist"S
+	    fi
+
+	    if test -f "$nlist"S; then
+	      eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
+	    else
+	      $echo '/* NONE */' >> "$output_objdir/$dlsyms"
+	    fi
+
+	    $echo >> "$output_objdir/$dlsyms" "\
+
+#undef lt_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define lt_ptr void *
+#else
+# define lt_ptr char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr address;
+}
+lt_preloaded_symbols[] =
+{\
+"
+
+	    eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms"
+
+	    $echo >> "$output_objdir/$dlsyms" "\
+  {0, (lt_ptr) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+	  fi
+
+	  pic_flag_for_symtable=
+	  case $host in
+	  # compiling the symbol table file with pic_flag works around
+	  # a FreeBSD bug that causes programs to crash when -lm is
+	  # linked before any other PIC object.  But we must not use
+	  # pic_flag when linking with -static.  The problem exists in
+	  # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+	  *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+	    case "$compile_command " in
+	    *" -static "*) ;;
+	    *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";;
+	    esac;;
+	  *-*-hpux*)
+	    case "$compile_command " in
+	    *" -static "*) ;;
+	    *) pic_flag_for_symtable=" $pic_flag";;
+	    esac
+	  esac
+
+	  # Now compile the dynamic symbol file.
+	  $show "(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+	  $run eval '(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+
+	  # Clean up the generated files.
+	  $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
+	  $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
+
+	  # Transform the symbol file into the correct name.
+	  compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+	  finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+	  ;;
+	*)
+	  $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
+	  exit 1
+	  ;;
+	esac
+      else
+	# We keep going just in case the user didn't refer to
+	# lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
+	# really was required.
+
+	# Nullify the symbol file.
+	compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
+	finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+      fi
+
+      # AIX runtime linking requires linking programs with -Wl,-brtl and libs with -Wl,-G
+      # Also add -bnolibpath to the beginning of the link line, to clear the hardcoded runpath.
+      # Otherwise, things like the -L path to libgcc.a are accidentally hardcoded by ld.
+      # This does not apply on AIX for ia64, which uses a SysV linker.
+      case "$host" in
+        ia64-*-aix5*) ;;
+        *-*-aix4* | *-*-aix5*)
+                   compile_command=`$echo "X$compile_command $wl-brtl" | $Xsed -e "s/\$CC/\$CC $wl-bnolibpath/1"`
+                   finalize_command=`$echo "X$finalize_command $wl-brtl" | $Xsed -e "s/\$CC/\$CC $wl-bnolibpath/1"` ;;
+      esac
+
+      if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+	# Replace the output file specification.
+	compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+	link_command="$compile_command$compile_rpath"
+
+	# We have no uninstalled library dependencies, so finalize right now.
+	$show "$link_command"
+	$run eval "$link_command"
+	status=$?
+
+	# Delete the generated files.
+	if test -n "$dlsyms"; then
+	  $show "$rm $output_objdir/${outputname}S.${objext}"
+	  $run $rm "$output_objdir/${outputname}S.${objext}"
+	fi
+
+	exit $status
+      fi
+
+      if test -n "$shlibpath_var"; then
+	# We should set the shlibpath_var
+	rpath=
+	for dir in $temp_rpath; do
+	  case $dir in
+	  [\\/]* | [A-Za-z]:[\\/]*)
+	    # Absolute path.
+	    rpath="$rpath$dir:"
+	    ;;
+	  *)
+	    # Relative path: add a thisdir entry.
+	    rpath="$rpath\$thisdir/$dir:"
+	    ;;
+	  esac
+	done
+	temp_rpath="$rpath"
+      fi
+
+      if test -n "$compile_shlibpath$finalize_shlibpath"; then
+	compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+      fi
+      if test -n "$finalize_shlibpath"; then
+	finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+      fi
+
+      compile_var=
+      finalize_var=
+      if test -n "$runpath_var"; then
+	if test -n "$perm_rpath"; then
+	  # We should set the runpath_var.
+	  rpath=
+	  for dir in $perm_rpath; do
+	    rpath="$rpath$dir:"
+	  done
+	  compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+	fi
+	if test -n "$finalize_perm_rpath"; then
+	  # We should set the runpath_var.
+	  rpath=
+	  for dir in $finalize_perm_rpath; do
+	    rpath="$rpath$dir:"
+	  done
+	  finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+	fi
+      fi
+
+      if test "$no_install" = yes; then
+	# We don't need to create a wrapper script.
+	link_command="$compile_var$compile_command$compile_rpath"
+	# Replace the output file specification.
+	link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+	# Delete the old output file.
+	$run $rm $output
+	# Link the executable and exit
+	$show "$link_command"
+	$run eval "$link_command" || exit $?
+	exit 0
+      fi
+
+      if test "$hardcode_action" = relink; then
+	# Fast installation is not supported
+	link_command="$compile_var$compile_command$compile_rpath"
+	relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+	$echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
+	$echo "$modename: \`$output' will be relinked during installation" 1>&2
+      else
+	if test "$fast_install" != no; then
+	  link_command="$finalize_var$compile_command$finalize_rpath"
+	  if test "$fast_install" = yes; then
+	    relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+	  else
+	    # fast_install is set to needless
+	    relink_command=
+	  fi
+	else
+	  link_command="$compile_var$compile_command$compile_rpath"
+	  relink_command="$finalize_var$finalize_command$finalize_rpath"
+	fi
+      fi
+
+      # Replace the output file specification.
+      link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+      # Delete the old output files.
+      $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+      $show "$link_command"
+      $run eval "$link_command" || exit $?
+
+      # Now create the wrapper script.
+      $show "creating $output"
+
+      # Quote the relink command for shipping.
+      if test -n "$relink_command"; then
+	# Preserve any variables that may affect compiler behavior
+	for var in $variables_saved_for_relink; do
+	  if eval test -z \"\${$var+set}\"; then
+	    relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+	  elif eval var_value=\$$var; test -z "$var_value"; then
+	    relink_command="$var=; export $var; $relink_command"
+	  else
+	    var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+	    relink_command="$var=\"$var_value\"; export $var; $relink_command"
+	  fi
+	done
+	relink_command="(cd `pwd`; $relink_command)"
+	relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+      fi
+
+      # Quote $echo for shipping.
+      if test "X$echo" = "X$SHELL $0 --fallback-echo"; then
+	case $0 in
+	[\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";;
+	*) qecho="$SHELL `pwd`/$0 --fallback-echo";;
+	esac
+	qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
+      else
+	qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
+      fi
+
+      # Only actually do things if our run command is non-null.
+      if test -z "$run"; then
+	# win32 will think the script is a binary if it has
+	# a .exe suffix, so we strip it off here.
+	case $output in
+	  *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;;
+	esac
+	# test for cygwin because mv fails w/o .exe extensions
+	case $host in
+	  *cygwin*)
+	    exeext=.exe
+	    outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;;
+	  *) exeext= ;;
+	esac
+	case $host in
+	  *cygwin* | *mingw* )
+	    cwrappersource=`$echo ${objdir}/lt-${output}.c`
+	    cwrapper=`$echo ${output}.exe`
+	    $rm $cwrappersource $cwrapper
+	    trap "$rm $cwrappersource $cwrapper; exit 1" 1 2 15
+
+	    cat > $cwrappersource <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+   Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+
+   The $output program cannot be directly executed until all the libtool
+   libraries that it depends on are installed.
+   
+   This wrapper executable should never be moved out of the build directory.
+   If it is, it will not operate correctly.
+
+   Currently, it simply execs the wrapper *script* "/bin/sh $output",
+   but could eventually absorb all of the scripts functionality and
+   exec $objdir/$outputname directly.
+*/
+EOF
+	    cat >> $cwrappersource<<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef DIR_SEPARATOR
+#define DIR_SEPARATOR '/'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+  defined (__OS2__)
+#define HAVE_DOS_BASED_FILE_SYSTEM
+#ifndef DIR_SEPARATOR_2 
+#define DIR_SEPARATOR_2 '\\'
+#endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+        (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+  if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+const char *program_name = NULL;
+
+void * xmalloc (size_t num);
+char * xstrdup (const char *string);
+char * basename (const char *name);
+char * fnqualify(const char *path);
+char * strendzap(char *str, const char *pat);
+void lt_fatal (const char *message, ...);
+
+int
+main (int argc, char *argv[])
+{
+  char **newargz;
+  int i;
+  
+  program_name = (char *) xstrdup ((char *) basename (argv[0]));
+  newargz = XMALLOC(char *, argc+2);
+EOF
+
+	    cat >> $cwrappersource <<EOF
+  newargz[0] = "$SHELL";
+EOF
+
+	    cat >> $cwrappersource <<"EOF"
+  newargz[1] = fnqualify(argv[0]);
+  /* we know the script has the same name, without the .exe */
+  /* so make sure newargz[1] doesn't end in .exe */
+  strendzap(newargz[1],".exe"); 
+  for (i = 1; i < argc; i++)
+    newargz[i+1] = xstrdup(argv[i]);
+  newargz[argc+1] = NULL;
+EOF
+
+	    cat >> $cwrappersource <<EOF
+  execv("$SHELL",newargz);
+EOF
+
+	    cat >> $cwrappersource <<"EOF"
+}
+
+void *
+xmalloc (size_t num)
+{
+  void * p = (void *) malloc (num);
+  if (!p)
+    lt_fatal ("Memory exhausted");
+
+  return p;
+}
+
+char * 
+xstrdup (const char *string)
+{
+  return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL
+;
+}
+
+char *
+basename (const char *name)
+{
+  const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  /* Skip over the disk name in MSDOS pathnames. */
+  if (isalpha (name[0]) && name[1] == ':') 
+    name += 2;
+#endif
+
+  for (base = name; *name; name++)
+    if (IS_DIR_SEPARATOR (*name))
+      base = name + 1;
+  return (char *) base;
+}
+
+char * 
+fnqualify(const char *path)
+{
+  size_t size;
+  char *p;
+  char tmp[LT_PATHMAX + 1];
+
+  assert(path != NULL);
+
+  /* Is it qualified already? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if (isalpha (path[0]) && path[1] == ':')
+    return xstrdup (path);
+#endif
+  if (IS_DIR_SEPARATOR (path[0]))
+    return xstrdup (path);
+
+  /* prepend the current directory */
+  /* doesn't handle '~' */
+  if (getcwd (tmp, LT_PATHMAX) == NULL)
+    lt_fatal ("getcwd failed");
+  size = strlen(tmp) + 1 + strlen(path) + 1; /* +2 for '/' and '\0' */
+  p = XMALLOC(char, size);
+  sprintf(p, "%s%c%s", tmp, DIR_SEPARATOR, path);
+  return p;
+}
+
+char *
+strendzap(char *str, const char *pat) 
+{
+  size_t len, patlen;
+
+  assert(str != NULL);
+  assert(pat != NULL);
+
+  len = strlen(str);
+  patlen = strlen(pat);
+
+  if (patlen <= len)
+  {
+    str += len - patlen;
+    if (strcmp(str, pat) == 0)
+      *str = '\0';
+  }
+  return str;
+}
+
+static void
+lt_error_core (int exit_status, const char * mode, 
+          const char * message, va_list ap)
+{
+  fprintf (stderr, "%s: %s: ", program_name, mode);
+  vfprintf (stderr, message, ap);
+  fprintf (stderr, ".\n");
+
+  if (exit_status >= 0)
+    exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+  va_list ap;
+  va_start (ap, message);
+  lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+  va_end (ap);
+}
+EOF
+	  # we should really use a build-platform specific compiler
+	  # here, but OTOH, the wrappers (shell script and this C one)
+	  # are only useful if you want to execute the "real" binary.
+	  # Since the "real" binary is built for $host, then this
+	  # wrapper might as well be built for $host, too.
+	  $run $LTCC -s -o $cwrapper $cwrappersource
+	  ;;
+	esac
+	$rm $output
+	trap "$rm $output; exit 1" 1 2 15
+
+	$echo > $output "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='${SED} -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+  # install mode needs the following variable:
+  notinst_deplibs='$notinst_deplibs'
+else
+  # When we are sourced in execute mode, \$file and \$echo are already set.
+  if test \"\$libtool_execute_magic\" != \"$magic\"; then
+    echo=\"$qecho\"
+    file=\"\$0\"
+    # Make sure echo works.
+    if test \"X\$1\" = X--no-reexec; then
+      # Discard the --no-reexec flag, and continue.
+      shift
+    elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
+      # Yippee, \$echo works!
+      :
+    else
+      # Restart under the correct shell, and then maybe \$echo will work.
+      exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+    fi
+  fi\
+"
+	$echo >> $output "\
+
+  # Find the directory that this script lives in.
+  thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+  test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
+  while test -n \"\$file\"; do
+    destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+    # If there was a directory component, then change thisdir.
+    if test \"x\$destdir\" != \"x\$file\"; then
+      case \"\$destdir\" in
+      [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+      *) thisdir=\"\$thisdir/\$destdir\" ;;
+      esac
+    fi
+
+    file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+    file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
+  done
+
+  # Try to get the absolute directory name.
+  absdir=\`cd \"\$thisdir\" && pwd\`
+  test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+	if test "$fast_install" = yes; then
+	  $echo >> $output "\
+  program=lt-'$outputname'$exeext
+  progdir=\"\$thisdir/$objdir\"
+
+  if test ! -f \"\$progdir/\$program\" || \\
+     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+       test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+    file=\"\$\$-\$program\"
+
+    if test ! -d \"\$progdir\"; then
+      $mkdir \"\$progdir\"
+    else
+      $rm \"\$progdir/\$file\"
+    fi"
+
+	  $echo >> $output "\
+
+    # relink executable if necessary
+    if test -n \"\$relink_command\"; then
+      if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+      else
+	$echo \"\$relink_command_output\" >&2
+	$rm \"\$progdir/\$file\"
+	exit 1
+      fi
+    fi
+
+    $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+    { $rm \"\$progdir/\$program\";
+      $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+    $rm \"\$progdir/\$file\"
+  fi"
+	else
+	  $echo >> $output "\
+  program='$outputname'
+  progdir=\"\$thisdir/$objdir\"
+"
+	fi
+
+	$echo >> $output "\
+
+  if test -f \"\$progdir/\$program\"; then"
+
+	# Export our shlibpath_var if we have one.
+	if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+	  $echo >> $output "\
+    # Add our own library path to $shlibpath_var
+    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+    # Some systems cannot cope with colon-terminated $shlibpath_var
+    # The second colon is a workaround for a bug in BeOS R4 sed
+    $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+    export $shlibpath_var
+"
+	fi
+
+	# fixup the dll searchpath if we need to.
+	if test -n "$dllsearchpath"; then
+	  $echo >> $output "\
+    # Add the dll search path components to the executable PATH
+    PATH=$dllsearchpath:\$PATH
+"
+	fi
+
+	$echo >> $output "\
+    if test \"\$libtool_execute_magic\" != \"$magic\"; then
+      # Run the actual program with our arguments.
+"
+	case $host in
+	# Backslashes separate directories on plain windows
+	*-*-mingw | *-*-os2*)
+	  $echo >> $output "\
+      exec \$progdir\\\\\$program \${1+\"\$@\"}
+"
+	  ;;
+
+	*)
+	  $echo >> $output "\
+      exec \$progdir/\$program \${1+\"\$@\"}
+"
+	  ;;
+	esac
+	$echo >> $output "\
+      \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
+      exit 1
+    fi
+  else
+    # The program doesn't exist.
+    \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2
+    \$echo \"This script is just a wrapper for \$program.\" 1>&2
+    $echo \"See the $PACKAGE documentation for more information.\" 1>&2
+    exit 1
+  fi
+fi\
+"
+	chmod +x $output
+      fi
+      exit 0
+      ;;
+    esac
+
+    # See if we need to build an old-fashioned archive.
+    for oldlib in $oldlibs; do
+
+      if test "$build_libtool_libs" = convenience; then
+	oldobjs="$libobjs_save"
+	addlibs="$convenience"
+	build_libtool_libs=no
+      else
+	if test "$build_libtool_libs" = module; then
+	  oldobjs="$libobjs_save"
+	  build_libtool_libs=no
+	else
+	  oldobjs="$old_deplibs $non_pic_objects"
+	fi
+	addlibs="$old_convenience"
+      fi
+
+      if test -n "$addlibs"; then
+	gentop="$output_objdir/${outputname}x"
+	$show "${rm}r $gentop"
+	$run ${rm}r "$gentop"
+	$show "$mkdir $gentop"
+	$run $mkdir "$gentop"
+	status=$?
+	if test "$status" -ne 0 && test ! -d "$gentop"; then
+	  exit $status
+	fi
+	generated="$generated $gentop"
+
+	# Add in members from convenience archives.
+	for xlib in $addlibs; do
+	  # Extract the objects.
+	  case $xlib in
+	  [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+	  *) xabs=`pwd`"/$xlib" ;;
+	  esac
+	  xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+	  xdir="$gentop/$xlib"
+
+	  $show "${rm}r $xdir"
+	  $run ${rm}r "$xdir"
+	  $show "$mkdir $xdir"
+	  $run $mkdir "$xdir"
+	  status=$?
+	  if test "$status" -ne 0 && test ! -d "$xdir"; then
+	    exit $status
+	  fi
+	  # We will extract separately just the conflicting names and we will no
+	  # longer touch any unique names. It is faster to leave these extract
+	  # automatically by $AR in one run.
+	  $show "(cd $xdir && $AR x $xabs)"
+	  $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+	  if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then
+	    :
+	  else
+	    $echo "$modename: warning: object name conflicts; renaming object files" 1>&2
+	    $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
+	    $AR t "$xabs" | sort | uniq -cd | while read -r count name
+	    do
+	      i=1
+	      while test "$i" -le "$count"
+	      do
+	       # Put our $i before any first dot (extension)
+	       # Never overwrite any file
+	       name_to="$name"
+	       while test "X$name_to" = "X$name" || test -f "$xdir/$name_to"
+	       do
+		 name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
+	       done
+	       $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')"
+	       $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $?
+	       i=`expr $i + 1`
+	      done
+	    done
+	  fi
+
+	  oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP`
+	done
+      fi
+
+      compiler_flags="$compiler_flags $add_flags"
+
+      # Do each command in the archive commands.
+      if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+	eval cmds=\"$old_archive_from_new_cmds\"
+      else
+	eval cmds=\"$old_archive_cmds\"
+
+	if len=`expr "X$cmds" : ".*"` &&
+	     test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  :
+	else
+	  # the command line is too long to link in one step, link in parts
+	  $echo "using piecewise archive linking..."
+	  save_RANLIB=$RANLIB
+	  RANLIB=:
+	  objlist=
+	  concat_cmds=
+	  save_oldobjs=$oldobjs
+	  # GNU ar 2.10+ was changed to match POSIX; thus no paths are
+	  # encoded into archives.  This makes 'ar r' malfunction in
+	  # this piecewise linking case whenever conflicting object
+	  # names appear in distinct ar calls; check, warn and compensate.
+	    if (for obj in $save_oldobjs
+	    do
+	      $echo "X$obj" | $Xsed -e 's%^.*/%%'
+	    done | sort | sort -uc >/dev/null 2>&1); then
+	    :
+	  else
+	    $echo "$modename: warning: object name conflicts; overriding AR_FLAGS to 'cq'" 1>&2
+	    $echo "$modename: warning: to ensure that POSIX-compatible ar will work" 1>&2
+	    AR_FLAGS=cq
+	  fi
+	  # Is there a better way of finding the last object in the list?
+	  for obj in $save_oldobjs
+	  do
+	    last_oldobj=$obj
+	  done  
+	  for obj in $save_oldobjs
+	  do
+	    oldobjs="$objlist $obj"
+	    objlist="$objlist $obj"
+	    eval test_cmds=\"$old_archive_cmds\"
+	    if len=`expr "X$test_cmds" : ".*"` &&
+	       test "$len" -le "$max_cmd_len"; then
+	      :
+	    else
+	      # the above command should be used before it gets too long
+	      oldobjs=$objlist
+	      if test "$obj" = "$last_oldobj" ; then
+	        RANLIB=$save_RANLIB
+	      fi  
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
+	      objlist=
+	    fi
+	  done
+	  RANLIB=$save_RANLIB
+	  oldobjs=$objlist
+	  if test "X$oldobjs" = "X" ; then
+	    eval cmds=\"\$concat_cmds\"
+	  else
+	    eval cmds=\"\$concat_cmds~$old_archive_cmds\"
+	  fi
+	fi
+      fi
+      save_ifs="$IFS"; IFS='~'
+      for cmd in $cmds; do
+	IFS="$save_ifs"
+	$show "$cmd"
+	$run eval "$cmd" || exit $?
+      done
+      IFS="$save_ifs"
+    done
+
+    if test -n "$generated"; then
+      $show "${rm}r$generated"
+      $run ${rm}r$generated
+    fi
+
+    # Now create the libtool archive.
+    case $output in
+    *.la)
+      old_library=
+      test "$build_old_libs" = yes && old_library="$libname.$libext"
+      $show "creating $output"
+
+      # Preserve any variables that may affect compiler behavior
+      for var in $variables_saved_for_relink; do
+	if eval test -z \"\${$var+set}\"; then
+	  relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+	elif eval var_value=\$$var; test -z "$var_value"; then
+	  relink_command="$var=; export $var; $relink_command"
+	else
+	  var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+	  relink_command="$var=\"$var_value\"; export $var; $relink_command"
+	fi
+      done
+      # Quote the link command for shipping.
+      relink_command="(cd `pwd`; $SHELL $0 --mode=relink $libtool_args @inst_prefix_dir@)"
+      relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+      if test "$hardcode_automatic" = yes ; then
+        relink_command=
+      fi  
+      # Only create the output if not a dry run.
+      if test -z "$run"; then
+	for installed in no yes; do
+	  if test "$installed" = yes; then
+	    if test -z "$install_libdir"; then
+	      break
+	    fi
+	    output="$output_objdir/$outputname"i
+	    # Replace all uninstalled libtool libraries with the installed ones
+	    newdependency_libs=
+	    for deplib in $dependency_libs; do
+	      case $deplib in
+	      *.la)
+		name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
+		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+		if test -z "$libdir"; then
+		  $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+		  exit 1
+		fi
+		newdependency_libs="$newdependency_libs $libdir/$name"
+		;;
+	      *) newdependency_libs="$newdependency_libs $deplib" ;;
+	      esac
+	    done
+	    dependency_libs="$newdependency_libs"
+	    newdlfiles=
+	    for lib in $dlfiles; do
+	      name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+	      eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+	      if test -z "$libdir"; then
+		$echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+		exit 1
+	      fi
+	      newdlfiles="$newdlfiles $libdir/$name"
+	    done
+	    dlfiles="$newdlfiles"
+	    newdlprefiles=
+	    for lib in $dlprefiles; do
+	      name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+	      eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+	      if test -z "$libdir"; then
+		$echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+		exit 1
+	      fi
+	      newdlprefiles="$newdlprefiles $libdir/$name"
+	    done
+	    dlprefiles="$newdlprefiles"
+	  fi
+	  $rm $output
+	  # place dlname in correct position for cygwin
+	  tdlname=$dlname
+	  case $host,$output,$installed,$module,$dlname in
+	    *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+	  esac
+	  $echo > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+	  if test "$installed" = no && test "$need_relink" = yes && test "$fast_install" = no; then
+	    $echo >> $output "\
+relink_command=\"$relink_command\""
+	  fi
+	done
+      fi
+
+      # Do a symbolic link so that the libtool archive can be found in
+      # LD_LIBRARY_PATH before the program is installed.
+      $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
+      $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
+      ;;
+    esac
+    exit 0
+    ;;
+
+  # libtool install mode
+  install)
+    modename="$modename: install"
+
+    # There may be an optional sh(1) argument at the beginning of
+    # install_prog (especially on Windows NT).
+    if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+       # Allow the use of GNU shtool's install command.
+       $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then
+      # Aesthetically quote it.
+      arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
+      case $arg in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*)
+	arg="\"$arg\""
+	;;
+      esac
+      install_prog="$arg "
+      arg="$1"
+      shift
+    else
+      install_prog=
+      arg="$nonopt"
+    fi
+
+    # The real first argument should be the name of the installation program.
+    # Aesthetically quote it.
+    arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+    case $arg in
+    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*)
+      arg="\"$arg\""
+      ;;
+    esac
+    install_prog="$install_prog$arg"
+
+    # We need to accept at least all the BSD install flags.
+    dest=
+    files=
+    opts=
+    prev=
+    install_type=
+    isdir=no
+    stripme=
+    for arg
+    do
+      if test -n "$dest"; then
+	files="$files $dest"
+	dest="$arg"
+	continue
+      fi
+
+      case $arg in
+      -d) isdir=yes ;;
+      -f) prev="-f" ;;
+      -g) prev="-g" ;;
+      -m) prev="-m" ;;
+      -o) prev="-o" ;;
+      -s)
+	stripme=" -s"
+	continue
+	;;
+      -*) ;;
+
+      *)
+	# If the previous option needed an argument, then skip it.
+	if test -n "$prev"; then
+	  prev=
+	else
+	  dest="$arg"
+	  continue
+	fi
+	;;
+      esac
+
+      # Aesthetically quote the argument.
+      arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+      case $arg in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*)
+	arg="\"$arg\""
+	;;
+      esac
+      install_prog="$install_prog $arg"
+    done
+
+    if test -z "$install_prog"; then
+      $echo "$modename: you must specify an install program" 1>&2
+      $echo "$help" 1>&2
+      exit 1
+    fi
+
+    if test -n "$prev"; then
+      $echo "$modename: the \`$prev' option requires an argument" 1>&2
+      $echo "$help" 1>&2
+      exit 1
+    fi
+
+    if test -z "$files"; then
+      if test -z "$dest"; then
+	$echo "$modename: no file or destination specified" 1>&2
+      else
+	$echo "$modename: you must specify a destination" 1>&2
+      fi
+      $echo "$help" 1>&2
+      exit 1
+    fi
+
+    # Strip any trailing slash from the destination.
+    dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
+
+    # Check to see that the destination is a directory.
+    test -d "$dest" && isdir=yes
+    if test "$isdir" = yes; then
+      destdir="$dest"
+      destname=
+    else
+      destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
+      test "X$destdir" = "X$dest" && destdir=.
+      destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
+
+      # Not a directory, so check to see that there is only one file specified.
+      set dummy $files
+      if test "$#" -gt 2; then
+	$echo "$modename: \`$dest' is not a directory" 1>&2
+	$echo "$help" 1>&2
+	exit 1
+      fi
+    fi
+    case $destdir in
+    [\\/]* | [A-Za-z]:[\\/]*) ;;
+    *)
+      for file in $files; do
+	case $file in
+	*.lo) ;;
+	*)
+	  $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
+	  $echo "$help" 1>&2
+	  exit 1
+	  ;;
+	esac
+      done
+      ;;
+    esac
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    staticlibs=
+    future_libdirs=
+    current_libdirs=
+    for file in $files; do
+
+      # Do each installation.
+      case $file in
+      *.$libext)
+	# Do the static libraries later.
+	staticlibs="$staticlibs $file"
+	;;
+
+      *.la)
+	# Check to see that this really is a libtool archive.
+	if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+	else
+	  $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
+	  $echo "$help" 1>&2
+	  exit 1
+	fi
+
+	library_names=
+	old_library=
+	relink_command=
+	# If there is no directory component, then add one.
+	case $file in
+	*/* | *\\*) . $file ;;
+	*) . ./$file ;;
+	esac
+
+	# Add the libdir to current_libdirs if it is the destination.
+	if test "X$destdir" = "X$libdir"; then
+	  case "$current_libdirs " in
+	  *" $libdir "*) ;;
+	  *) current_libdirs="$current_libdirs $libdir" ;;
+	  esac
+	else
+	  # Note the libdir as a future libdir.
+	  case "$future_libdirs " in
+	  *" $libdir "*) ;;
+	  *) future_libdirs="$future_libdirs $libdir" ;;
+	  esac
+	fi
+
+	dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/
+	test "X$dir" = "X$file/" && dir=
+	dir="$dir$objdir"
+
+	if test -n "$relink_command"; then
+	  # Determine the prefix the user has applied to our future dir.
+	  inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"`
+
+	  # Don't allow the user to place us outside of our expected
+	  # location b/c this prevents finding dependent libraries that
+	  # are installed to the same prefix.
+	  # At present, this check doesn't affect windows .dll's that
+	  # are installed into $libdir/../bin (currently, that works fine)
+	  # but it's something to keep an eye on.
+	  if test "$inst_prefix_dir" = "$destdir"; then
+	    $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
+	    exit 1
+	  fi
+
+	  if test -n "$inst_prefix_dir"; then
+	    # Stick the inst_prefix_dir data into the link command.
+	    relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+	  else
+	    relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+	  fi
+
+	  $echo "$modename: warning: relinking \`$file'" 1>&2
+	  $show "$relink_command"
+	  if $run eval "$relink_command"; then :
+	  else
+	    $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+	    exit 1
+	  fi
+	fi
+
+	# See the names of the shared library.
+	set dummy $library_names
+	if test -n "$2"; then
+	  realname="$2"
+	  shift
+	  shift
+
+	  srcname="$realname"
+	  test -n "$relink_command" && srcname="$realname"T
+
+	  # Install the shared library and build the symlinks.
+	  $show "$install_prog $dir/$srcname $destdir/$realname"
+	  $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $?
+	  if test -n "$stripme" && test -n "$striplib"; then
+	    $show "$striplib $destdir/$realname"
+	    $run eval "$striplib $destdir/$realname" || exit $?
+	  fi
+
+	  if test "$#" -gt 0; then
+	    # Delete the old symlinks, and create new ones.
+	    for linkname
+	    do
+	      if test "$linkname" != "$realname"; then
+		$show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+		$run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+	      fi
+	    done
+	  fi
+
+	  # Do each command in the postinstall commands.
+	  lib="$destdir/$realname"
+	  eval cmds=\"$postinstall_cmds\"
+	  save_ifs="$IFS"; IFS='~'
+	  for cmd in $cmds; do
+	    IFS="$save_ifs"
+	    $show "$cmd"
+	    $run eval "$cmd" || exit $?
+	  done
+	  IFS="$save_ifs"
+	fi
+
+	# Install the pseudo-library for information purposes.
+	name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+	instname="$dir/$name"i
+	$show "$install_prog $instname $destdir/$name"
+	$run eval "$install_prog $instname $destdir/$name" || exit $?
+
+	# Maybe install the static library, too.
+	test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+	;;
+
+      *.lo)
+	# Install (i.e. copy) a libtool object.
+
+	# Figure out destination file name, if it wasn't already specified.
+	if test -n "$destname"; then
+	  destfile="$destdir/$destname"
+	else
+	  destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+	  destfile="$destdir/$destfile"
+	fi
+
+	# Deduce the name of the destination old-style object file.
+	case $destfile in
+	*.lo)
+	  staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
+	  ;;
+	*.$objext)
+	  staticdest="$destfile"
+	  destfile=
+	  ;;
+	*)
+	  $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
+	  $echo "$help" 1>&2
+	  exit 1
+	  ;;
+	esac
+
+	# Install the libtool object if requested.
+	if test -n "$destfile"; then
+	  $show "$install_prog $file $destfile"
+	  $run eval "$install_prog $file $destfile" || exit $?
+	fi
+
+	# Install the old object if enabled.
+	if test "$build_old_libs" = yes; then
+	  # Deduce the name of the old-style object file.
+	  staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
+
+	  $show "$install_prog $staticobj $staticdest"
+	  $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+	fi
+	exit 0
+	;;
+
+      *)
+	# Figure out destination file name, if it wasn't already specified.
+	if test -n "$destname"; then
+	  destfile="$destdir/$destname"
+	else
+	  destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+	  destfile="$destdir/$destfile"
+	fi
+
+	# If the file is missing, and there is a .exe on the end, strip it
+	# because it is most likely a libtool script we actually want to
+	# install
+	stripped_ext=""
+	case $file in
+	  *.exe)
+	    if test ! -f "$file"; then
+	      file=`$echo $file|${SED} 's,.exe$,,'`
+	      stripped_ext=".exe"
+	    fi
+	    ;;
+	esac
+
+	# Do a test to see if this is really a libtool program.
+	case $host in
+	*cygwin*|*mingw*)
+	    wrapper=`$echo $file | ${SED} -e 's,.exe$,,'`
+	    ;;
+	*)
+	    wrapper=$file
+	    ;;
+	esac
+	if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
+	  notinst_deplibs=
+	  relink_command=
+
+	  # To insure that "foo" is sourced, and not "foo.exe",
+	  # finese the cygwin/MSYS system by explicitly sourcing "foo."
+	  # which disallows the automatic-append-.exe behavior.
+	  case $build in
+	  *cygwin* | *mingw*) wrapperdot=${wrapper}. ;;
+	  *) wrapperdot=${wrapper} ;;
+	  esac
+	  # If there is no directory component, then add one.
+	  case $file in
+	  */* | *\\*) . ${wrapperdot} ;;
+	  *) . ./${wrapperdot} ;;
+	  esac
+
+	  # Check the variables that should have been set.
+	  if test -z "$notinst_deplibs"; then
+	    $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
+	    exit 1
+	  fi
+
+	  finalize=yes
+	  for lib in $notinst_deplibs; do
+	    # Check to see that each library is installed.
+	    libdir=
+	    if test -f "$lib"; then
+	      # If there is no directory component, then add one.
+	      case $lib in
+	      */* | *\\*) . $lib ;;
+	      *) . ./$lib ;;
+	      esac
+	    fi
+	    libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
+	    if test -n "$libdir" && test ! -f "$libfile"; then
+	      $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+	      finalize=no
+	    fi
+	  done
+
+	  relink_command=
+	  # To insure that "foo" is sourced, and not "foo.exe",
+	  # finese the cygwin/MSYS system by explicitly sourcing "foo."
+	  # which disallows the automatic-append-.exe behavior.
+	  case $build in
+	  *cygwin* | *mingw*) wrapperdot=${wrapper}. ;;
+	  *) wrapperdot=${wrapper} ;;
+	  esac
+	  # If there is no directory component, then add one.
+	  case $file in
+	  */* | *\\*) . ${wrapperdot} ;;
+	  *) . ./${wrapperdot} ;;
+	  esac
+
+	  outputname=
+	  if test "$fast_install" = no && test -n "$relink_command"; then
+	    if test "$finalize" = yes && test -z "$run"; then
+	      tmpdir="/tmp"
+	      test -n "$TMPDIR" && tmpdir="$TMPDIR"
+	      tmpdir="$tmpdir/libtool-$$"
+	      if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then :
+	      else
+		$echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
+		continue
+	      fi
+	      file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'`
+	      outputname="$tmpdir/$file"
+	      # Replace the output file specification.
+	      relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+
+	      $show "$relink_command"
+	      if $run eval "$relink_command"; then :
+	      else
+		$echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+		${rm}r "$tmpdir"
+		continue
+	      fi
+	      file="$outputname"
+	    else
+	      $echo "$modename: warning: cannot relink \`$file'" 1>&2
+	    fi
+	  else
+	    # Install the binary that we compiled earlier.
+	    file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+	  fi
+	fi
+
+	# remove .exe since cygwin /usr/bin/install will append another
+	# one anyways
+	case $install_prog,$host in
+	*/usr/bin/install*,*cygwin*)
+	  case $file:$destfile in
+	  *.exe:*.exe)
+	    # this is ok
+	    ;;
+	  *.exe:*)
+	    destfile=$destfile.exe
+	    ;;
+	  *:*.exe)
+	    destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'`
+	    ;;
+	  esac
+	  ;;
+	esac
+	$show "$install_prog$stripme $file $destfile"
+	$run eval "$install_prog\$stripme \$file \$destfile" || exit $?
+	test -n "$outputname" && ${rm}r "$tmpdir"
+	;;
+      esac
+    done
+
+    for file in $staticlibs; do
+      name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+      # Set up the ranlib parameters.
+      oldlib="$destdir/$name"
+
+      $show "$install_prog $file $oldlib"
+      $run eval "$install_prog \$file \$oldlib" || exit $?
+
+      if test -n "$stripme" && test -n "$striplib"; then
+	$show "$old_striplib $oldlib"
+	$run eval "$old_striplib $oldlib" || exit $?
+      fi
+
+      # Do each command in the postinstall commands.
+      eval cmds=\"$old_postinstall_cmds\"
+      save_ifs="$IFS"; IFS='~'
+      for cmd in $cmds; do
+	IFS="$save_ifs"
+	$show "$cmd"
+	$run eval "$cmd" || exit $?
+      done
+      IFS="$save_ifs"
+    done
+
+    if test -n "$future_libdirs"; then
+      $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+    fi
+
+    if test -n "$current_libdirs"; then
+      # Maybe just do a dry run.
+      test -n "$run" && current_libdirs=" -n$current_libdirs"
+      exec_cmd='$SHELL $0 --finish$current_libdirs'
+    else
+      exit 0
+    fi
+    ;;
+
+  # libtool finish mode
+  finish)
+    modename="$modename: finish"
+    libdirs="$nonopt"
+    admincmds=
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      for dir
+      do
+	libdirs="$libdirs $dir"
+      done
+
+      for libdir in $libdirs; do
+	if test -n "$finish_cmds"; then
+	  # Do each command in the finish commands.
+	  eval cmds=\"$finish_cmds\"
+	  save_ifs="$IFS"; IFS='~'
+	  for cmd in $cmds; do
+	    IFS="$save_ifs"
+	    $show "$cmd"
+	    $run eval "$cmd" || admincmds="$admincmds
+       $cmd"
+	  done
+	  IFS="$save_ifs"
+	fi
+	if test -n "$finish_eval"; then
+	  # Do the single finish_eval.
+	  eval cmds=\"$finish_eval\"
+	  $run eval "$cmds" || admincmds="$admincmds
+       $cmds"
+	fi
+      done
+    fi
+
+    # Exit here if they wanted silent mode.
+    exit 0
+
+    $echo "----------------------------------------------------------------------"
+    $echo "Libraries have been installed in:"
+    for libdir in $libdirs; do
+      $echo "   $libdir"
+    done
+    $echo
+    $echo "If you ever happen to want to link against installed libraries"
+    $echo "in a given directory, LIBDIR, you must either use libtool, and"
+    $echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+    $echo "flag during linking and do at least one of the following:"
+    if test -n "$shlibpath_var"; then
+      $echo "   - add LIBDIR to the \`$shlibpath_var' environment variable"
+      $echo "     during execution"
+    fi
+    if test -n "$runpath_var"; then
+      $echo "   - add LIBDIR to the \`$runpath_var' environment variable"
+      $echo "     during linking"
+    fi
+    if test -n "$hardcode_libdir_flag_spec"; then
+      libdir=LIBDIR
+      eval flag=\"$hardcode_libdir_flag_spec\"
+
+      $echo "   - use the \`$flag' linker flag"
+    fi
+    if test -n "$admincmds"; then
+      $echo "   - have your system administrator run these commands:$admincmds"
+    fi
+    if test -f /etc/ld.so.conf; then
+      $echo "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+    fi
+    $echo
+    $echo "See any operating system documentation about shared libraries for"
+    $echo "more information, such as the ld(1) and ld.so(8) manual pages."
+    $echo "----------------------------------------------------------------------"
+    exit 0
+    ;;
+
+  # libtool execute mode
+  execute)
+    modename="$modename: execute"
+
+    # The first argument is the command name.
+    cmd="$nonopt"
+    if test -z "$cmd"; then
+      $echo "$modename: you must specify a COMMAND" 1>&2
+      $echo "$help"
+      exit 1
+    fi
+
+    # Handle -dlopen flags immediately.
+    for file in $execute_dlfiles; do
+      if test ! -f "$file"; then
+	$echo "$modename: \`$file' is not a file" 1>&2
+	$echo "$help" 1>&2
+	exit 1
+      fi
+
+      dir=
+      case $file in
+      *.la)
+	# Check to see that this really is a libtool archive.
+	if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+	else
+	  $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+	  $echo "$help" 1>&2
+	  exit 1
+	fi
+
+	# Read the libtool library.
+	dlname=
+	library_names=
+
+	# If there is no directory component, then add one.
+	case $file in
+	*/* | *\\*) . $file ;;
+	*) . ./$file ;;
+	esac
+
+	# Skip this library if it cannot be dlopened.
+	if test -z "$dlname"; then
+	  # Warn if it was a shared library.
+	  test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
+	  continue
+	fi
+
+	dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+	test "X$dir" = "X$file" && dir=.
+
+	if test -f "$dir/$objdir/$dlname"; then
+	  dir="$dir/$objdir"
+	else
+	  $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+	  exit 1
+	fi
+	;;
+
+      *.lo)
+	# Just add the directory containing the .lo file.
+	dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+	test "X$dir" = "X$file" && dir=.
+	;;
+
+      *)
+	$echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+	continue
+	;;
+      esac
+
+      # Get the absolute pathname.
+      absdir=`cd "$dir" && pwd`
+      test -n "$absdir" && dir="$absdir"
+
+      # Now add the directory to shlibpath_var.
+      if eval "test -z \"\$$shlibpath_var\""; then
+	eval "$shlibpath_var=\"\$dir\""
+      else
+	eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+      fi
+    done
+
+    # This variable tells wrapper scripts just to set shlibpath_var
+    # rather than running their programs.
+    libtool_execute_magic="$magic"
+
+    # Check if any of the arguments is a wrapper script.
+    args=
+    for file
+    do
+      case $file in
+      -*) ;;
+      *)
+	# Do a test to see if this is really a libtool program.
+	if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+	  # If there is no directory component, then add one.
+	  case $file in
+	  */* | *\\*) . $file ;;
+	  *) . ./$file ;;
+	  esac
+
+	  # Transform arg to wrapped name.
+	  file="$progdir/$program"
+	fi
+	;;
+      esac
+      # Quote arguments (to preserve shell metacharacters).
+      file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
+      args="$args \"$file\""
+    done
+
+    if test -z "$run"; then
+      if test -n "$shlibpath_var"; then
+	# Export the shlibpath_var.
+	eval "export $shlibpath_var"
+      fi
+
+      # Restore saved environment variables
+      if test "${save_LC_ALL+set}" = set; then
+	LC_ALL="$save_LC_ALL"; export LC_ALL
+      fi
+      if test "${save_LANG+set}" = set; then
+	LANG="$save_LANG"; export LANG
+      fi
+
+      # Now prepare to actually exec the command.
+      exec_cmd="\$cmd$args"
+    else
+      # Display what would be done.
+      if test -n "$shlibpath_var"; then
+	eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+	$echo "export $shlibpath_var"
+      fi
+      $echo "$cmd$args"
+      exit 0
+    fi
+    ;;
+
+  # libtool clean and uninstall mode
+  clean | uninstall)
+    modename="$modename: $mode"
+    rm="$nonopt"
+    files=
+    rmforce=
+    exit_status=0
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    for arg
+    do
+      case $arg in
+      -f) rm="$rm $arg"; rmforce=yes ;;
+      -*) rm="$rm $arg" ;;
+      *) files="$files $arg" ;;
+      esac
+    done
+
+    if test -z "$rm"; then
+      $echo "$modename: you must specify an RM program" 1>&2
+      $echo "$help" 1>&2
+      exit 1
+    fi
+
+    rmdirs=
+
+    origobjdir="$objdir"
+    for file in $files; do
+      dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+      if test "X$dir" = "X$file"; then
+	dir=.
+	objdir="$origobjdir"
+      else
+	objdir="$dir/$origobjdir"
+      fi
+      name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+      test "$mode" = uninstall && objdir="$dir"
+
+      # Remember objdir for removal later, being careful to avoid duplicates
+      if test "$mode" = clean; then
+	case " $rmdirs " in
+	  *" $objdir "*) ;;
+	  *) rmdirs="$rmdirs $objdir" ;;
+	esac
+      fi
+
+      # Don't error if the file doesn't exist and rm -f was used.
+      if (test -L "$file") >/dev/null 2>&1 \
+	|| (test -h "$file") >/dev/null 2>&1 \
+	|| test -f "$file"; then
+	:
+      elif test -d "$file"; then
+	exit_status=1
+	continue
+      elif test "$rmforce" = yes; then
+	continue
+      fi
+
+      rmfiles="$file"
+
+      case $name in
+      *.la)
+	# Possibly a libtool archive, so verify it.
+	if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+	  . $dir/$name
+
+	  # Delete the libtool libraries and symlinks.
+	  for n in $library_names; do
+	    rmfiles="$rmfiles $objdir/$n"
+	  done
+	  test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+	  test "$mode" = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+
+	  if test "$mode" = uninstall; then
+	    if test -n "$library_names"; then
+	      # Do each command in the postuninstall commands.
+	      eval cmds=\"$postuninstall_cmds\"
+	      save_ifs="$IFS"; IFS='~'
+	      for cmd in $cmds; do
+		IFS="$save_ifs"
+		$show "$cmd"
+		$run eval "$cmd"
+		if test "$?" -ne 0 && test "$rmforce" != yes; then
+		  exit_status=1
+		fi
+	      done
+	      IFS="$save_ifs"
+	    fi
+
+	    if test -n "$old_library"; then
+	      # Do each command in the old_postuninstall commands.
+	      eval cmds=\"$old_postuninstall_cmds\"
+	      save_ifs="$IFS"; IFS='~'
+	      for cmd in $cmds; do
+		IFS="$save_ifs"
+		$show "$cmd"
+		$run eval "$cmd"
+		if test "$?" -ne 0 && test "$rmforce" != yes; then
+		  exit_status=1
+		fi
+	      done
+	      IFS="$save_ifs"
+	    fi
+	    # FIXME: should reinstall the best remaining shared library.
+	  fi
+	fi
+	;;
+
+      *.lo)
+	# Possibly a libtool object, so verify it.
+	if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+
+	  # Read the .lo file
+	  . $dir/$name
+
+	  # Add PIC object to the list of files to remove.
+	  if test -n "$pic_object" \
+	     && test "$pic_object" != none; then
+	    rmfiles="$rmfiles $dir/$pic_object"
+	  fi
+
+	  # Add non-PIC object to the list of files to remove.
+	  if test -n "$non_pic_object" \
+	     && test "$non_pic_object" != none; then
+	    rmfiles="$rmfiles $dir/$non_pic_object"
+	  fi
+	fi
+	;;
+
+      *)
+	if test "$mode" = clean ; then
+	  noexename=$name
+	  case $file in
+	  *.exe) 
+	    file=`$echo $file|${SED} 's,.exe$,,'`
+	    noexename=`$echo $name|${SED} 's,.exe$,,'`
+	    # $file with .exe has already been added to rmfiles,
+	    # add $file without .exe
+	    rmfiles="$rmfiles $file"
+	    ;;
+	  esac
+	  # Do a test to see if this is a libtool program.
+	  if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+	    relink_command=
+	    . $dir/$noexename
+
+	    # note $name still contains .exe if it was in $file originally
+	    # as does the version of $file that was added into $rmfiles
+	    rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+	    if test "$fast_install" = yes && test -n "$relink_command"; then
+	      rmfiles="$rmfiles $objdir/lt-$name"
+	    fi
+	    if test "X$noexename" != "X$name" ; then
+	      rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+	    fi
+	  fi
+	fi
+	;;
+      esac
+      $show "$rm $rmfiles"
+      $run $rm $rmfiles || exit_status=1
+    done
+    objdir="$origobjdir"
+
+    # Try to remove the ${objdir}s in the directories where we deleted files
+    for dir in $rmdirs; do
+      if test -d "$dir"; then
+	$show "rmdir $dir"
+	$run rmdir $dir >/dev/null 2>&1
+      fi
+    done
+
+    exit $exit_status
+    ;;
+
+  "")
+    $echo "$modename: you must specify a MODE" 1>&2
+    $echo "$generic_help" 1>&2
+    exit 1
+    ;;
+  esac
+
+  if test -z "$exec_cmd"; then
+    $echo "$modename: invalid operation mode \`$mode'" 1>&2
+    $echo "$generic_help" 1>&2
+    exit 1
+  fi
+fi # test -z "$show_help"
+
+if test -n "$exec_cmd"; then
+  eval exec $exec_cmd
+  exit 1
+fi
+
+# We need to display help for each of the modes.
+case $mode in
+"") $echo \
+"Usage: $modename [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+    --config          show all configuration variables
+    --debug           enable verbose shell tracing
+-n, --dry-run         display commands without modifying any files
+    --features        display basic configuration information and exit
+    --finish          same as \`--mode=finish'
+    --help            display this help message and exit
+    --mode=MODE       use operation mode MODE [default=inferred from MODE-ARGS]
+    --quiet           same as \`--silent'
+    --silent          don't print informational messages
+    --tag=TAG         use configuration variables from tag TAG
+    --version         print version information
+
+MODE must be one of the following:
+
+      clean           remove files from the build directory
+      compile         compile a source file into a libtool object
+      execute         automatically set library path, then run a program
+      finish          complete the installation of libtool libraries
+      install         install libraries or executables
+      link            create a library or an executable
+      uninstall       remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE.  Try \`$modename --help --mode=MODE' for
+a more detailed description of MODE.
+
+Report bugs to <bug-libtool@gnu.org>."
+  exit 0
+  ;;
+
+clean)
+  $echo \
+"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+  ;;
+
+compile)
+  $echo \
+"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
+  -prefer-pic       try to building PIC objects only
+  -prefer-non-pic   try to building non-PIC objects only
+  -static           always build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+  ;;
+
+execute)
+  $echo \
+"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+  -dlopen FILE      add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+  ;;
+
+finish)
+  $echo \
+"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges.  Use
+the \`--dry-run' option if you just want to see what would be executed."
+  ;;
+
+install)
+  $echo \
+"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command.  The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+  ;;
+
+link)
+  $echo \
+"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+  -all-static       do not do any dynamic linking at all
+  -avoid-version    do not add a version suffix if possible
+  -dlopen FILE      \`-dlpreopen' FILE if it cannot be dlopened at runtime
+  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
+  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+  -export-symbols SYMFILE
+		    try to export only the symbols listed in SYMFILE
+  -export-symbols-regex REGEX
+		    try to export only the symbols matching REGEX
+  -LLIBDIR          search LIBDIR for required installed libraries
+  -lNAME            OUTPUT-FILE requires the installed library libNAME
+  -module           build a library that can dlopened
+  -no-fast-install  disable the fast-install mode
+  -no-install       link a not-installable executable
+  -no-undefined     declare that a library does not refer to external symbols
+  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
+  -objectlist FILE  Use a list of object files found in FILE to specify objects
+  -release RELEASE  specify package release information
+  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
+  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
+  -static           do not do any dynamic linking of libtool libraries
+  -version-info CURRENT[:REVISION[:AGE]]
+		    specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename.  Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+  ;;
+
+uninstall)
+  $echo \
+"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+  ;;
+
+*)
+  $echo "$modename: invalid operation mode \`$mode'" 1>&2
+  $echo "$help" 1>&2
+  exit 1
+  ;;
+esac
+
+$echo
+$echo "Try \`$modename --help' for more information about other modes."
+
+exit 0
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries.  Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them.  This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration.  But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+build_libtool_libs=no
+build_old_libs=yes
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+build_old_libs=`case $build_libtool_libs in yes) $echo no;; *) $echo yes;; esac`
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
Index: /tags/start/psModules/missing
===================================================================
--- /tags/start/psModules/missing	(revision 12606)
+++ /tags/start/psModules/missing	(revision 12606)
@@ -0,0 +1,336 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try \`$0 --help' for more information"
+  exit 1
+fi
+
+run=:
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+  configure_ac=configure.ac
+else
+  configure_ac=configure.in
+fi
+
+case "$1" in
+--run)
+  # Try to run requested program, and just exit if it succeeds.
+  run=
+  shift
+  "$@" && exit 0
+  ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case "$1" in
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+  --run           try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+  aclocal      touch file \`aclocal.m4'
+  autoconf     touch file \`configure'
+  autoheader   touch file \`config.h.in'
+  automake     touch all \`Makefile.in' files
+  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
+  flex         create \`lex.yy.c', if possible, from existing .c
+  help2man     touch the output file
+  lex          create \`lex.yy.c', if possible, from existing .c
+  makeinfo     touch the output file
+  tar          try tar, gnutar, gtar, then tar without non-portable flags
+  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]"
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing 0.4 - GNU automake"
+    ;;
+
+  -*)
+    echo 1>&2 "$0: Unknown \`$1' option"
+    echo 1>&2 "Try \`$0 --help' for more information"
+    exit 1
+    ;;
+
+  aclocal*)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`acinclude.m4' or \`${configure_ac}'.  You might want
+         to install the \`Automake' and \`Perl' packages.  Grab them from
+         any GNU archive site."
+    touch aclocal.m4
+    ;;
+
+  autoconf)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`${configure_ac}'.  You might want to install the
+         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
+         archive site."
+    touch configure
+    ;;
+
+  autoheader)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`acconfig.h' or \`${configure_ac}'.  You might want
+         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
+         from any GNU archive site."
+    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+    test -z "$files" && files="config.h"
+    touch_files=
+    for f in $files; do
+      case "$f" in
+      *:*) touch_files="$touch_files "`echo "$f" |
+				       sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+      *) touch_files="$touch_files $f.in";;
+      esac
+    done
+    touch $touch_files
+    ;;
+
+  automake*)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+         You might want to install the \`Automake' and \`Perl' packages.
+         Grab them from any GNU archive site."
+    find . -type f -name Makefile.am -print |
+	   sed 's/\.am$/.in/' |
+	   while read f; do touch "$f"; done
+    ;;
+
+  autom4te)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+         system.  You might have modified some files without having the
+         proper tools for further handling them.
+         You can get \`$1Help2man' as part of \`Autoconf' from any GNU
+         archive site."
+
+    file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
+    test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
+    if test -f "$file"; then
+	touch $file
+    else
+	test -z "$file" || exec >$file
+	echo "#! /bin/sh"
+	echo "# Created by GNU Automake missing as a replacement of"
+	echo "#  $ $@"
+	echo "exit 0"
+	chmod +x $file
+	exit 1
+    fi
+    ;;
+
+  bison|yacc)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.y' file.  You may need the \`Bison' package
+         in order for those modifications to take effect.  You can get
+         \`Bison' from any GNU archive site."
+    rm -f y.tab.c y.tab.h
+    if [ $# -ne 1 ]; then
+        eval LASTARG="\${$#}"
+	case "$LASTARG" in
+	*.y)
+	    SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+	    if [ -f "$SRCFILE" ]; then
+	         cp "$SRCFILE" y.tab.c
+	    fi
+	    SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+	    if [ -f "$SRCFILE" ]; then
+	         cp "$SRCFILE" y.tab.h
+	    fi
+	  ;;
+	esac
+    fi
+    if [ ! -f y.tab.h ]; then
+	echo >y.tab.h
+    fi
+    if [ ! -f y.tab.c ]; then
+	echo 'main() { return 0; }' >y.tab.c
+    fi
+    ;;
+
+  lex|flex)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.l' file.  You may need the \`Flex' package
+         in order for those modifications to take effect.  You can get
+         \`Flex' from any GNU archive site."
+    rm -f lex.yy.c
+    if [ $# -ne 1 ]; then
+        eval LASTARG="\${$#}"
+	case "$LASTARG" in
+	*.l)
+	    SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+	    if [ -f "$SRCFILE" ]; then
+	         cp "$SRCFILE" lex.yy.c
+	    fi
+	  ;;
+	esac
+    fi
+    if [ ! -f lex.yy.c ]; then
+	echo 'main() { return 0; }' >lex.yy.c
+    fi
+    ;;
+
+  help2man)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+	 you modified a dependency of a manual page.  You may need the
+	 \`Help2man' package in order for those modifications to take
+	 effect.  You can get \`Help2man' from any GNU archive site."
+
+    file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+    if test -z "$file"; then
+	file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
+    fi
+    if [ -f "$file" ]; then
+	touch $file
+    else
+	test -z "$file" || exec >$file
+	echo ".ab help2man is required to generate this page"
+	exit 1
+    fi
+    ;;
+
+  makeinfo)
+    if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then
+       # We have makeinfo, but it failed.
+       exit 1
+    fi
+
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.texi' or \`.texinfo' file, or any other file
+         indirectly affecting the aspect of the manual.  The spurious
+         call might also be the consequence of using a buggy \`make' (AIX,
+         DU, IRIX).  You might want to install the \`Texinfo' package or
+         the \`GNU make' package.  Grab either from any GNU archive site."
+    file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+    if test -z "$file"; then
+      file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+      file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+    fi
+    touch $file
+    ;;
+
+  tar)
+    shift
+    if test -n "$run"; then
+      echo 1>&2 "ERROR: \`tar' requires --run"
+      exit 1
+    fi
+
+    # We have already tried tar in the generic part.
+    # Look for gnutar/gtar before invocation to avoid ugly error
+    # messages.
+    if (gnutar --version > /dev/null 2>&1); then
+       gnutar "$@" && exit 0
+    fi
+    if (gtar --version > /dev/null 2>&1); then
+       gtar "$@" && exit 0
+    fi
+    firstarg="$1"
+    if shift; then
+	case "$firstarg" in
+	*o*)
+	    firstarg=`echo "$firstarg" | sed s/o//`
+	    tar "$firstarg" "$@" && exit 0
+	    ;;
+	esac
+	case "$firstarg" in
+	*h*)
+	    firstarg=`echo "$firstarg" | sed s/h//`
+	    tar "$firstarg" "$@" && exit 0
+	    ;;
+	esac
+    fi
+
+    echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+         You may want to install GNU tar or Free paxutils, or check the
+         command line arguments."
+    exit 1
+    ;;
+
+  *)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+         system.  You might have modified some files without having the
+         proper tools for further handling them.  Check the \`README' file,
+         it often tells you about the needed prerequirements for installing
+         this package.  You may also peek at any GNU archive site, in case
+         some other package would contain this missing \`$1' program."
+    exit 1
+    ;;
+esac
+
+exit 0
Index: /tags/start/psModules/mkinstalldirs
===================================================================
--- /tags/start/psModules/mkinstalldirs	(revision 12606)
+++ /tags/start/psModules/mkinstalldirs	(revision 12606)
@@ -0,0 +1,111 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+errstatus=0
+dirmode=""
+
+usage="\
+Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
+
+# process command line arguments
+while test $# -gt 0 ; do
+  case $1 in
+    -h | --help | --h*)         # -h for help
+      echo "$usage" 1>&2
+      exit 0
+      ;;
+    -m)                         # -m PERM arg
+      shift
+      test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
+      dirmode=$1
+      shift
+      ;;
+    --)                         # stop option processing
+      shift
+      break
+      ;;
+    -*)                         # unknown option
+      echo "$usage" 1>&2
+      exit 1
+      ;;
+    *)                          # first non-opt arg
+      break
+      ;;
+  esac
+done
+
+for file
+do
+  if test -d "$file"; then
+    shift
+  else
+    break
+  fi
+done
+
+case $# in
+  0) exit 0 ;;
+esac
+
+case $dirmode in
+  '')
+    if mkdir -p -- . 2>/dev/null; then
+      echo "mkdir -p -- $*"
+      exec mkdir -p -- "$@"
+    fi
+    ;;
+  *)
+    if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
+      echo "mkdir -m $dirmode -p -- $*"
+      exec mkdir -m "$dirmode" -p -- "$@"
+    fi
+    ;;
+esac
+
+for file
+do
+  set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+  shift
+
+  pathcomp=
+  for d
+  do
+    pathcomp="$pathcomp$d"
+    case $pathcomp in
+      -*) pathcomp=./$pathcomp ;;
+    esac
+
+    if test ! -d "$pathcomp"; then
+      echo "mkdir $pathcomp"
+
+      mkdir "$pathcomp" || lasterr=$?
+
+      if test ! -d "$pathcomp"; then
+  	errstatus=$lasterr
+      else
+  	if test ! -z "$dirmode"; then
+	  echo "chmod $dirmode $pathcomp"
+    	  lasterr=""
+  	  chmod "$dirmode" "$pathcomp" || lasterr=$?
+
+  	  if test ! -z "$lasterr"; then
+  	    errstatus=$lasterr
+  	  fi
+  	fi
+      fi
+    fi
+
+    pathcomp="$pathcomp/"
+  done
+done
+
+exit $errstatus
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# End:
+# mkinstalldirs ends here
Index: /tags/start/psModules/psmodule.kdevelop
===================================================================
--- /tags/start/psModules/psmodule.kdevelop	(revision 12606)
+++ /tags/start/psModules/psmodule.kdevelop	(revision 12606)
@@ -0,0 +1,129 @@
+<?xml version = '1.0'?>
+<kdevelop>
+  <general>
+    <author>Robert Daniel DeSonia</author>
+    <email>desonia@mhpcc.hawaii.edu</email>
+    <version>0.1</version>
+    <projectmanagement>KDevAutoProject</projectmanagement>
+    <primarylanguage>C</primarylanguage>
+    <keywords>
+      <keyword>C</keyword>
+      <keyword>Code</keyword>
+    </keywords>
+  </general>
+  <kdevautoproject>
+    <general>
+      <activetarget>src/psmodule</activetarget>
+      <useconfiguration>debug</useconfiguration>
+    </general>
+    <run>
+      <mainprogram>src/psmodule</mainprogram>
+      <terminal>true</terminal>
+      <directoryradio>executable</directoryradio>
+    </run>
+    <configurations>
+      <optimized>
+        <builddir>optimized</builddir>
+        <ccompiler>kdevgccoptions</ccompiler>
+        <cxxcompiler>kdevgppoptions</cxxcompiler>
+        <f77compiler>kdevg77options</f77compiler>
+        <cflags>-O2 -g0</cflags>
+      </optimized>
+      <debug>
+        <configargs>--enable-debug=full</configargs>
+        <builddir>debug</builddir>
+        <ccompiler>kdevgccoptions</ccompiler>
+        <cxxcompiler>kdevgppoptions</cxxcompiler>
+        <f77compiler>kdevg77options</f77compiler>
+        <cflags>-O0 -g3</cflags>
+      </debug>
+    </configurations>
+    <make>
+      <envvars>
+        <envvar value="1" name="WANT_AUTOCONF_2_5" />
+        <envvar value="1" name="WANT_AUTOMAKE_1_6" />
+      </envvars>
+    </make>
+  </kdevautoproject>
+  <kdevdoctreeview>
+    <ignoretocs>
+      <toc>ada</toc>
+      <toc>ada_bugs_gcc</toc>
+      <toc>bash</toc>
+      <toc>bash_bugs</toc>
+      <toc>clanlib</toc>
+      <toc>w3c-dom-level2-html</toc>
+      <toc>fortran_bugs_gcc</toc>
+      <toc>gnome1</toc>
+      <toc>gnustep</toc>
+      <toc>gtk</toc>
+      <toc>gtk_bugs</toc>
+      <toc>haskell</toc>
+      <toc>haskell_bugs_ghc</toc>
+      <toc>java_bugs_gcc</toc>
+      <toc>java_bugs_sun</toc>
+      <toc>kde2book</toc>
+      <toc>libstdc++</toc>
+      <toc>opengl</toc>
+      <toc>pascal_bugs_fp</toc>
+      <toc>php</toc>
+      <toc>php_bugs</toc>
+      <toc>perl</toc>
+      <toc>perl_bugs</toc>
+      <toc>python</toc>
+      <toc>python_bugs</toc>
+      <toc>qt-kdev3</toc>
+      <toc>ruby</toc>
+      <toc>ruby_bugs</toc>
+      <toc>sdl</toc>
+      <toc>stl</toc>
+      <toc>w3c-svg</toc>
+      <toc>sw</toc>
+      <toc>w3c-uaag10</toc>
+      <toc>wxwidgets_bugs</toc>
+    </ignoretocs>
+    <ignoreqt_xml>
+      <toc>Guide to the Qt Translation Tools</toc>
+      <toc>Qt Assistant Manual</toc>
+      <toc>Qt Designer Manual</toc>
+      <toc>Qt Reference Documentation</toc>
+      <toc>qmake User Guide</toc>
+    </ignoreqt_xml>
+    <ignoredoxygen>
+      <toc>KDE Libraries (Doxygen)</toc>
+    </ignoredoxygen>
+  </kdevdoctreeview>
+  <kdevfilecreate>
+    <useglobaltypes>
+      <type ext="c" />
+      <type ext="h" />
+    </useglobaltypes>
+  </kdevfilecreate>
+  <kdevfileview>
+    <groups>
+      <group pattern="*.h" name="Header files" />
+      <group pattern="*.c" name="Source files" />
+      <hidenonprojectfiles>false</hidenonprojectfiles>
+      <hidenonlocation>false</hidenonlocation>
+    </groups>
+    <tree>
+      <hidepatterns>*.o,*.lo,CVS</hidepatterns>
+      <hidenonprojectfiles>false</hidenonprojectfiles>
+    </tree>
+  </kdevfileview>
+  <kdevcppsupport>
+    <references/>
+    <codecompletion>
+      <includeGlobalFunctions>true</includeGlobalFunctions>
+      <includeTypes>true</includeTypes>
+      <includeEnums>true</includeEnums>
+      <includeTypedefs>false</includeTypedefs>
+      <automaticCodeCompletion>true</automaticCodeCompletion>
+      <automaticArgumentsHint>true</automaticArgumentsHint>
+      <automaticHeaderCompletion>true</automaticHeaderCompletion>
+      <codeCompletionDelay>250</codeCompletionDelay>
+      <argumentsHintDelay>400</argumentsHintDelay>
+      <headerCompletionDelay>250</headerCompletionDelay>
+    </codecompletion>
+  </kdevcppsupport>
+</kdevelop>
Index: /tags/start/psModules/src/Makefile.am
===================================================================
--- /tags/start/psModules/src/Makefile.am	(revision 12606)
+++ /tags/start/psModules/src/Makefile.am	(revision 12606)
@@ -0,0 +1,10 @@
+lib_LTLIBRARIES = libpsmodule.la
+bin_PROGRAMS = tst_pmFlatField
+
+libpsmodule_la_SOURCES = pmFlatField.c
+libpsmodule_la_HEADERS =  pmFlatField.h
+libpsmodule_ladir = .
+
+
+tst_pmFlatField_SOURCES = tst_pmFlatField.c
+tst_pmFlatField_LDFLAGS = -lpsmodule -lpslib -lcfitsio -lgsl -lgslcblas -lfftw3f -lsla
Index: /tags/start/psModules/src/pmFlatField.c
===================================================================
--- /tags/start/psModules/src/pmFlatField.c	(revision 12606)
+++ /tags/start/psModules/src/pmFlatField.c	(revision 12606)
@@ -0,0 +1,34 @@
+/** @file  pmFlatField.c
+ *
+ *  @brief Contains the definitions for ...
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.1.1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-10 19:01:33 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include<stdio.h>
+
+#include "pmFlatField.h"
+
+void pmFlatField(psVector* vector) 
+{
+    if (vector == NULL) {
+        printf("Nothing to see here... move along.\n");
+        return;
+    }
+    
+    for (int lcv=0;lcv<vector->n;lcv++) {
+        printf("%f\n",vector->data.F32[lcv]);
+    }
+    
+    return;
+    
+}
Index: /tags/start/psModules/src/pmFlatField.h
===================================================================
--- /tags/start/psModules/src/pmFlatField.h	(revision 12606)
+++ /tags/start/psModules/src/pmFlatField.h	(revision 12606)
@@ -0,0 +1,17 @@
+/** @file  pmFlatField.h
+ *
+ *  @brief Contains the definitions for ...
+ *
+ *  Detailed Description goes here.
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.1.1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-10 19:01:33 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include "pslib.h"
+
+void pmFlatField(psVector* test);
Index: /tags/start/psModules/src/tst_pmFlatField.c
===================================================================
--- /tags/start/psModules/src/tst_pmFlatField.c	(revision 12606)
+++ /tags/start/psModules/src/tst_pmFlatField.c	(revision 12606)
@@ -0,0 +1,24 @@
+/** @file  filename.h
+ *
+ *  @brief Contains the definitions for ...
+ *
+ *  Detailed Description goes here.
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.1.1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-10 19:01:33 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include "pmFlatField.h"
+
+int main(void)
+{
+    psVector* vec = psVectorAlloc(10,PS_TYPE_F32);
+    for (int i=0;i<10;i++) {
+        vec->data.F32[i] = i/9.0f;
+    }
+    pmFlatField(vec);
+}
Index: /tags/start/psModules/templates/c
===================================================================
--- /tags/start/psModules/templates/c	(revision 12606)
+++ /tags/start/psModules/templates/c	(revision 12606)
@@ -0,0 +1,11 @@
+/** @file  filename.c
+ *
+ *  @brief Contains the definitions for ...
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.1.1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-10 19:01:33 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
Index: /tags/start/psModules/templates/h
===================================================================
--- /tags/start/psModules/templates/h	(revision 12606)
+++ /tags/start/psModules/templates/h	(revision 12606)
@@ -0,0 +1,13 @@
+/** @file  filename.h
+ *
+ *  @brief Contains the definitions for ...
+ *
+ *  Detailed Description goes here.
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.1.1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-09-10 19:01:33 $
+ *
+ *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+ */
Index: /tags/start/stac/scripts/Makefile
===================================================================
--- /tags/start/stac/scripts/Makefile	(revision 12606)
+++ /tags/start/stac/scripts/Makefile	(revision 12606)
@@ -0,0 +1,45 @@
+# $Id: Makefile,v 1.1.1.1 2004-05-19 22:55:27 price Exp $
+#
+# make file
+#
+# Paul A. Price
+#
+
+CC = gcc
+FITSFLAGS = -lcfitsio -lm
+GSLFLAGS = -lgslcblas -lgsl
+
+### SUN:
+#FITSFLAGS = -lcfitsio -lm -L../cfitsio/ -lsocket -lnsl
+
+### RH Linux:
+CFLAGS = -Wall -O3 -g -march=i686
+
+# Destination directory
+DESTDIR = .
+
+# Inputs
+FAKEIMAGE = fakeimage.o memory.o
+CONVERTFITS = convertFITS.o memory.o
+
+.PHONY:	all clean
+
+all: fakeimage convertFITS
+
+.c.o:
+	$(CC) -c $(CFLAGS) $<
+
+fakeimage: $(FAKEIMAGE)
+	$(CC) $(FAKEIMAGE) -o $(DESTDIR)/fakeimage $(FITSFLAGS) $(GSLFLAGS)
+
+convertFITS: $(CONVERTFITS)
+	$(CC) $(CFLAGS) $(CONVERTFITS) -o $(DESTDIR)/convertFITS $(FITSFLAGS)
+
+clean:
+	-$(RM) *.o
+
+# Tags for emacs
+.PHONY : tags
+tags :
+	etags `find . \( -name \*.[ch] -o -name \*.cpp \) -print`
+
Index: /tags/start/stac/scripts/convertFITS.c
===================================================================
--- /tags/start/stac/scripts/convertFITS.c	(revision 12606)
+++ /tags/start/stac/scripts/convertFITS.c	(revision 12606)
@@ -0,0 +1,192 @@
+/*
+**
+** $Id: convertFITS.c,v 1.1.1.1 2004-05-19 22:55:27 price Exp $
+**
+** Program to convert BITPIX of FITS images.
+**
+**
+** Paul A. Price
+** 2004 January 28
+** INDNJC.
+**
+**
+** LEGAL STUFF:
+**
+** Copyright 2003, Paul A. Price.
+**
+** This program is free software; you can redistribute it and/or
+** modify it under the terms of the GNU General Public License as
+** published by the Free Software Foundation; either version 2 of the
+** License, or (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+** General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+** USA
+**
+*/
+
+
+/* Included standard header files */
+#include <stdio.h>
+#include <math.h>
+/* For getopt */
+#include <unistd.h>
+#include <getopt.h>
+/* For cfitsio */
+#include <fitsio.h>
+
+/* Included header files for components */
+#include "memory.h"
+
+/* Handy definitions */
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#define min(a,b) (((a) > (b)) ? (b) : (a))
+#define abs(a) (((a) > 0) ? (a) : (-a))
+
+
+/* Global variables */
+int verbose = 0;   /* Verbose output? */
+
+int main(int argc, char **argv)
+{
+    /* Input variables */
+    char *inputName = NULL;   /* Name of input image */
+    char *outputName = NULL;   /* Name of output image */
+    int bitpix = -32;   /* BITPIX for output image */
+
+    /* Calculation variables */
+    float *inputData;   /* The input pixels */
+    long int inputDims[2];   /* Dimensions of the input image */
+    int i;   /* Counter */
+
+    /* Variables for cfitsio */
+    int status = 0;   /* fitsio status */
+    fitsfile *infp, *outfp;   /* File pointers to FITS file */
+    int nkeys, keypos;   /* Keyword-handling variables */
+    char card[FLEN_CARD];   /* Keyword-handling variable */
+
+    /* Help function */
+    void help(void);
+    /* cfitsio error handler */
+    void ckstatus(int status);
+
+    if (argc < 3)
+    {
+        help();
+        exit(EXIT_FAILURE);
+    }
+    inputName = argv[1];
+    outputName = argv[2];
+    if (sscanf(argv[3], "%d", &bitpix) != 1)
+    {
+	help ();
+	exit (EXIT_FAILURE);
+    }
+
+
+    /* Read the input file */
+    if (verbose) printf ("Opening %s.... ", inputName);
+    if (fits_open_file(&infp,inputName,READONLY,&status)) ckstatus(status);
+    /* Get dimensions */
+    if (fits_get_img_size(infp,2,inputDims,&status)) ckstatus(status);
+    if (verbose) printf ("%ldx%ld\n",inputDims[0],inputDims[1]);
+    /* Allocate storage */
+    inputData = farray(inputDims[0]*inputDims[1]);
+    /* Read the pixels */
+    if (fits_read_img(infp, TFLOAT, 1, inputDims[0]*inputDims[1], 0, inputData, NULL, &status)) ckstatus(status);
+
+    /* Create output file */
+    if (verbose) printf ("Writing %ldx%ld output image...\n",inputDims[0],inputDims[1]);
+    if (fits_create_file(&outfp, outputName, &status)) ckstatus(status);
+
+#if 0
+    /* Write bare header */
+    if (fits_write_imghdr (outfp, bitpix, 2, inputDims, &status)) ckstatus(status);
+#endif
+
+    /* Copy FITS headers */
+    if (fits_get_hdrpos(infp, &nkeys, &keypos, &status))
+        ckstatus(status);
+    for (i=1; i <= nkeys; i++)
+    {
+        fits_read_record(infp, i, card, &status);
+        fits_write_record(outfp, card, &status);
+    }
+    ckstatus(status);
+
+    /* Write new BITPIX */
+    if (fits_update_key (outfp, TINT, "BITPIX", &bitpix, NULL, &status)) ckstatus(status);
+
+    /* Get correct BITPIX for cfitsio */
+    switch (bitpix)
+    {
+    case 8:
+    {
+	char *charData;   /* Short version of the pixels */
+	charData = carray(inputDims[0]*inputDims[1]);
+	for (i = 0; i < inputDims[0]*inputDims[1]; i++) charData[i] = (char)inputData[i];
+	/* Write pixels */
+	if (fits_write_img(outfp, TBYTE, 1, inputDims[0]*inputDims[1], charData, &status)) ckstatus(status);
+	free (charData);
+
+	break;
+    }
+    case 16:
+    {
+	short int *intData;   /* Integer version of the pixels */
+
+	intData = sarray(inputDims[0]*inputDims[1]);
+	for (i = 0; i < inputDims[0]*inputDims[1]; i++) intData[i] = (short int) inputData[i];
+	/* Write pixels */
+	if (fits_write_img(outfp, TSHORT, 1, inputDims[0]*inputDims[1], intData, &status)) ckstatus(status);
+	free (intData);
+	break;
+    }
+    default:
+	fprintf (stderr, "BITPIX must be 8 or 16\n");
+	exit (EXIT_FAILURE);
+    }
+
+    /* Close files and clean up */
+    if (fits_close_file(infp, &status)) ckstatus(status);
+    if (fits_close_file(outfp, &status)) ckstatus(status);
+    free (inputData);
+
+
+    exit (EXIT_SUCCESS);
+}
+
+
+void help(void)
+{
+    fprintf (stderr,
+	     "convertFITS [-hv] INPUT OUTPUT BITPIX\n"
+	     "\n"
+	     "\t-h      Help\n"
+	     "\t-v      Verbose\n"
+	     "\tINPUT   Input FITS file\n"
+	     "\tOUTPUT  Output FITS file\n"
+	     "\tBITPIX  BITPIX for output FITS file\n"
+	     "\n"
+	);
+}
+
+
+void ckstatus(int status)
+{
+    char msg[FLEN_ERRMSG];   /* Error message */
+
+    if (!status)
+        return;
+    fprintf (stderr,"CFITSIO returned an error code of %d\n",status);
+    while (fits_read_errmsg(msg))
+        fprintf(stderr, "CFITSIO: %s\n", msg);
+    fprintf (stderr, "Exiting....\n");
+    exit(EXIT_FAILURE);
+}
Index: /tags/start/stac/scripts/fakeimage.c
===================================================================
--- /tags/start/stac/scripts/fakeimage.c	(revision 12606)
+++ /tags/start/stac/scripts/fakeimage.c	(revision 12606)
@@ -0,0 +1,566 @@
+/*
+** $Id: fakeimage.c,v 1.1.1.1 2004-05-19 22:55:27 price Exp $
+** Program to make some fake images.
+**
+** Paul A. Price
+** 2003 September 3
+** INDNJC.
+**
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <fitsio.h>
+#include <math.h>
+
+/* For seeding the RNG */
+#include <sys/timeb.h>
+
+/* Memory allocation routines */
+#include "memory.h"
+
+/* GSL */
+#include <gsl/gsl_sf_erf.h>		// For error functions
+
+
+/* Conversion factor by which to multiply sigma to get FWHM.  Roughly 2.35 */
+#define SIGMAtoFWHM (2.0*sqrt((double)2.0*(log((double)2.0))))
+
+/* Errors - range of sigma to use */
+#define MAXSIGMA 4.5
+#define NUMSIGMA 100
+
+
+/* Handy functions */
+#define abs(a) (((a) > 0) ? (a) : (-a))
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#define min(a,b) (((a) > (b)) ? (b) : (a))
+
+/* Function declarations */
+void help(void);
+void ckstatus(int status);
+void addstar (float *data, int nx, int ny, int nxos, float x, float y, float flux, float seeing);
+float linint(double x[], double y[], int num, double val);   /* Linear interpolation */
+float gauss (float val);   /* Gaussian-type function */
+float fringe (int x, int y, float periodx, float periody, float phasex, float phasey);
+
+/* Global variables */
+int verbose=0;   /* Verbosity switch */
+long dims[2];   /* Dimensions of images */
+
+int main(int argc, char **argv)
+{
+    /* Input variables */
+    const char *noisefile, *outfile;   /* Input and output filenames */
+    double background;   /* Sky background, ADU */
+    double gain;   /* Detector gain, units e-/ADU */
+    double readnoise;   /* Detector read noise, units e- */
+    long overscan;   /* Number of overscan columns */
+    double zero;   /* Bias/Zero level for image */
+    double zeroslope;   /* Bias/Zero slope for image */
+    int numcrs;   /* Number of CRs */
+    int numstars;   /* Number of stars */
+    double seeing;   /* Seeing FWHM (pixels) */
+    char *starfile;   /* Name of file to use for stars */
+    int debug;   /* Output debug information?  (ie CR position and flux) */
+    int numbadpix;   /* Number of bad pixels */
+
+    /* Calculation variables */
+    fitsfile *fitsfp;   /* FITS files: input, output */
+    int status = 0;   /* fitsio status */
+    int i,x,y;   /* Counters */
+    float *outdata;   /* Output pixels */
+    float *noisedata;   /* Noise - Sigma to add to ideal image */
+    int *mask;   /* Mask of CRs */
+    float starx,stary;   /* Star centre */
+    float flux;   /* (peak) flux of star */
+    FILE *starfilefp;   /* File pointer for star file */
+    int usestarfile;   /* Boolean indicating whether we get the star data from the file or not */
+    int usenoisefile;   /* Boolean indicating whether we apply the noise or not */
+    long noisedims[2];   /* Dimensions of noise map */
+    double *gint, *gsigma;   /* Gaussian */
+    char datasec[FLEN_KEYWORD],biassec[FLEN_KEYWORD]; // Data section and bias section for FITS
+    struct timeb thetime;   /* For seeding the random number generator */
+    float fringeamp, fringeperiod, fringephase;	// Fringe amplitude, period and phase
+
+    /* Variables for getopt */
+    int opt;   /* Option, from getopt */
+    extern char *optarg;   /* Argument accompanying switch */
+    extern int optind;   /* getopt variables */
+
+    /* Seed the random number generator */
+    ftime(&thetime);
+    srand((unsigned int)thetime.millitm);
+
+    /* Set defaults for variables */
+    debug = 0;
+    gain = 1.0;
+    readnoise = 10.0;
+    background = 10000.0;
+    dims[0] = dims[1] = 1024;
+    numcrs = 0;
+    numbadpix = 0;
+    seeing = 2.5;
+    numstars = 0;
+    usestarfile=0;
+    noisefile=NULL;
+    usenoisefile = 0;
+    starfile=NULL;
+    overscan = 0;
+    zero = 0.;
+    zeroslope=0.;
+    fringeamp = 0.0;
+    fringeperiod = (float)dims[0] / 20.0;
+
+    while ((opt = getopt(argc, argv, "hvdkg:r:n:m:c:s:f:b:x:y:z:Z:o:p:F:")) != -1)
+	switch (opt)
+	{
+	  case 'h':
+	    help();
+	    exit(0);
+	  case 'v':
+	    verbose = 1;
+	    break;
+	  case 'd':
+	    debug = 1;
+	    verbose = 0;
+	    break;
+	  case 'k':
+	    usenoisefile = -1;
+	    break;
+	  case 'g':
+	    if (sscanf(optarg, "%lf", &gain) != 1)
+	    {
+		help();
+		exit(1);
+	    }
+	    break;
+	  case 'r':
+	    if (sscanf(optarg, "%lf", &readnoise) != 1)
+	    {
+		help();
+		exit(1);
+	    }
+	    break;
+	  case 'x':
+	    if (sscanf(optarg, "%ld", &dims[0]) != 1)
+	    {
+		help();
+		exit(1);
+	    }
+	    break;
+	  case 'y':
+	    if (sscanf(optarg, "%ld", &dims[1]) != 1)
+	    {
+		help();
+		exit(1);
+	    }
+	    break;
+	  case 'z':
+	    if (sscanf(optarg, "%lf", &zero) != 1)
+	    {
+		help();
+		exit(1);
+	    }
+	    break;
+	  case 'Z':
+	    if (sscanf(optarg, "%lf", &zeroslope) != 1)
+	    {
+		help();
+		exit(1);
+	    }
+	    break;
+	  case 'o':
+	    if (sscanf(optarg, "%ld", &overscan) != 1)
+	    {
+		help();
+		exit(1);
+	    }
+	    break;
+	  case 'c':
+	    if (sscanf(optarg, "%d", &numcrs) != 1)
+	    {
+		help();
+		exit(1);
+	    }
+	    break;
+	  case 's':
+	    if (sscanf(optarg, "%d", &numstars) != 1)
+	    {
+		help();
+		exit(1);
+	    }
+	    usestarfile=0;
+	    break;
+	  case 'p':
+	    if (sscanf(optarg, "%d", &numbadpix) != 1)
+	    {
+		help();
+		exit(1);
+	    }
+	    break;
+	  case 'n':
+	    noisefile = optarg;
+	    usenoisefile = 1;
+	    break;
+	  case 'b':
+	    if (sscanf(optarg, "%lf", &background) != 1)
+	    {
+		help();
+		exit(1);
+	    }
+	    break;
+	  case 'm':
+	    starfile = optarg;
+	    usestarfile=1;
+	    break;
+	  case 'f':
+	    if (sscanf(optarg, "%lf", &seeing) != 1)
+	    {
+		help();
+		exit(1);
+	    }
+	    break;
+	  case 'F':
+	    /*
+	      Note: incrementing optind, so I can read more than
+	      one parameter.
+	    */
+	    
+	    if ((sscanf(argv[optind-1], "%f", &fringeamp) != 1) ||
+		(sscanf(argv[optind++], "%f", &fringeperiod) != 1) ||
+		(sscanf(argv[optind++], "%f", &fringephase) != 1 ))
+	    {
+		help();
+		exit(EXIT_FAILURE);
+	    }
+	    break;
+	  default:
+	    help();
+	    exit(1);
+	}
+
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 1)
+    {
+	help();
+	exit(1);
+    }
+    
+    outfile = argv[0];
+
+
+    /* Now, the program proper... */
+
+    /* Do we read an input, or create an empty image? */
+    if (usenoisefile == 1)
+    {
+	/* Open input file */
+	if (verbose) printf ("Opening %s.... ", noisefile);
+	if (fits_open_file(&fitsfp,noisefile,READONLY,&status)) ckstatus(status);
+
+	/* Get dimensions */
+	if (fits_get_img_size(fitsfp,2,noisedims,&status)) ckstatus(status);
+	if (verbose) printf ("%ldx%ld\n",noisedims[0],noisedims[1]);
+
+	if ((noisedims[0] != dims[0] + overscan) || (noisedims[1] != dims[1]))
+	{
+	    fprintf (stderr, "Noise map must have same dimensions as output image!\n");
+	    fprintf (stderr, "Altering output image dimensions to %ldx%ld\n",noisedims[0],noisedims[1]);
+	    dims[0] = noisedims[0];
+	    dims[1] = noisedims[1];
+	}
+
+	/* Allocate storage */
+	noisedata = farray((dims[0]+overscan)*dims[1]);
+
+	/* Read the pixels */
+	if (fits_read_img(fitsfp, TFLOAT, 1, (dims[0]+overscan)*dims[1], 0, noisedata, NULL, &status)) ckstatus(status);
+
+	/* Close the file */
+	if (fits_close_file(fitsfp, &status)) ckstatus(status);
+
+    }
+    else
+    {
+	/* Integrate gaussian so we can have a nice distribution */
+	if (verbose) printf ("Creating noise map.....\n");
+	gsigma = darray(NUMSIGMA);
+	gint = darray(NUMSIGMA);
+	for (i = 0; i < NUMSIGMA; i++)
+	{
+	    gsigma[i] = 2.0*(double)(MAXSIGMA*i)/(double)NUMSIGMA - MAXSIGMA;
+	    gint[i] = gsl_sf_erf((double)gsigma[i]);
+	    printf ("%f %f\n",gsigma[i],gint[i]);
+	}
+
+	/* Allocate memory for output */
+	noisedata = farray((dims[0]+overscan)*dims[1]);   /* Output Image */
+
+	/* Create noise map */
+	for (i=0;i<(dims[0]+overscan)*dims[1];i++) noisedata[i] = (float)linint(gint,gsigma,NUMSIGMA,(double)rand()/(double)RAND_MAX*(gint[NUMSIGMA-1]-gint[0])+gint[0]);
+    }
+
+
+    /* Create empty output file */
+    if (verbose) printf ("Creating %ldx%ld output image, %s\n",dims[0]+overscan,dims[1],outfile);
+    if (fits_create_file(&fitsfp, outfile, &status)) ckstatus(status);
+
+
+    /* Initialise the output buffer to the background */
+    outdata = farray((dims[0]+overscan)*dims[1]);
+    mask = iarray((dims[0]+overscan)*dims[1]);
+    if (verbose) printf("Initialising output buffer\n");
+    for (y=0;y<dims[1];y++)
+	for (x=0;x<dims[0]+overscan;x++)
+	{
+	    /* Bias */
+	    outdata[(dims[0]+overscan)*y+x] = zero + zeroslope*(float)y;
+	    /* CR pixel mask */
+	    mask[(dims[0]+overscan)*y+x] = 0;
+	    /* Add background to the true pixels */
+	    if (x < dims[0]) outdata[(dims[0]+overscan)*y+x] += background;
+	}
+    
+    /* Add stars */
+    if (verbose) printf("Adding stars\n");
+
+    if (usestarfile)
+    {
+	if ((starfilefp = fopen(starfile,"r")) == NULL)
+	{
+	    fprintf(stderr,"Can't open %s\n",starfile);
+	    exit(1);
+	}
+
+	while (fscanf(starfilefp,"%f %f %f",&starx,&stary,&flux) == 3)
+	    addstar(&outdata[0],dims[0],dims[1],overscan,starx,stary,flux,seeing);
+	fclose(starfilefp);
+    }
+    else
+    {
+	/* Random distribution of Stars */
+	for (i=1;i<=numstars;i++)
+	{
+	    starx = (rand()/(RAND_MAX+1.0)*dims[0]);
+	    stary = (rand()/(RAND_MAX+1.0)*dims[1]);
+	    flux = rand()/(RAND_MAX+1.0)*(32768.0-background);
+
+	    addstar(&outdata[0],dims[0],dims[1],overscan,starx,stary,flux,seeing);
+	    if (verbose) printf ("%f %f %f\n",starx,stary,flux);
+	}
+    }
+
+    /* Add fringes */
+    if (fringeamp != 0.0) {
+	for (y = 0; y < dims[1]; y++)
+	    for (x = 0; x < dims[0]; x++)
+		outdata[(dims[0]+overscan)*y+x] += fringeamp * fringe(x,y,fringeperiod,fringeperiod,fringephase,fringephase);
+    }
+    
+    /* Add Poisson noise */
+    if (usenoisefile != -1)
+    {
+	if (verbose) printf ("Adding noise\n");
+	for (y=0;y<dims[1];y++)
+	    for (x=0;x<(dims[0]+overscan);x++)
+		outdata[(dims[0]+overscan)*y+x] += noisedata[(dims[0]+overscan)*y+x]*sqrt((double)(gain*(outdata[(dims[0]+overscan)*y+x]-(zero + zeroslope*y)) + readnoise*readnoise))/gain;
+    }
+
+    /* Random distribution of bad pixels */
+    if (verbose) printf ("Adding bad pixels\n");
+    for (i = 1; i <= numbadpix; i++)
+    {
+	x = (int)(rand()/(RAND_MAX+1.0)*dims[0]);
+	y = (int)(rand()/(RAND_MAX+1.0)*dims[1]);
+	outdata[(dims[0]+overscan)*y+x] = 0.0;
+    }
+
+    /* Random distribution of CRs */
+    if (verbose) printf ("Adding CRs\n");
+    if (numcrs > dims[0]*dims[1]/2) fprintf (stderr,"Image too small (%ldx%ld) for %d CRs --- no CRs added.\n",dims[0],dims[1],numcrs);
+    else
+    {
+	for (i=1;i<=numcrs;i++)
+	{
+	    x = (int)(rand()/(RAND_MAX+1.0)*dims[0]);
+	    y = (int)(rand()/(RAND_MAX+1.0)*dims[1]);
+	    if (mask[(dims[0]+overscan)*y+x]) i--;   /* Get another one */
+	    else
+	    {
+		flux = rand()/(RAND_MAX+1.0)*(32768.0-background);
+		outdata[(dims[0]+overscan)*y+x] += flux;
+		mask[(dims[0]+overscan)*y+x] = 1;
+		if (debug) printf ("%d %d %f\n",x,y,flux);
+	    }
+	}
+    }
+
+    /* Write output */
+    if (verbose) printf ("Writing %ldx%ld output image...\n",dims[0]+overscan,dims[1]);
+    dims[0] += overscan;
+    if (fits_write_imghdr (fitsfp, -32, 2, dims, &status)) ckstatus(status);
+
+    /* Write DATASEC, BIASSEC */
+    (void)sprintf (datasec,"[%ld:%ld,%ld:%ld]",1L,dims[0]-overscan,1L,dims[1]);
+    (void)sprintf (biassec,"[%ld:%ld,%ld:%ld]",dims[0]-overscan+1,dims[0],1L,dims[1]);
+    if (fits_write_key(fitsfp, TSTRING, "DATASEC", datasec,"Data section",&status)) ckstatus(status);
+    if (fits_write_key(fitsfp, TSTRING, "BIASSEC", biassec,"Bias section",&status)) ckstatus(status);
+
+    /* Write the FITS file */
+    if (fits_write_img(fitsfp, TFLOAT, 1, dims[0]*dims[1], outdata, &status)) ckstatus(status);
+
+    /* Close files and clean up */
+    if(fits_close_file(fitsfp, &status)) ckstatus(status);
+    free ((float*)outdata);
+    free ((int*)mask);
+
+    if (verbose) printf ("Done!\n");
+
+    exit(0);
+}
+
+
+/* Functions follow */
+
+void help(void)
+{
+    fprintf(stderr,
+	    "fakeimage [-hvd] [-x NX] [-y NY] [-g GAIN] [-r READNOISE] [-b BACKGROUND] [-s NUM_STARS] [-f FWHM] [-c NUM_CRS] [-p NUM_BADPIX] [-z ZERO_LEVEL] [-o OVERSCAN] [-n NOISE_MAP] OUTPUT_IMAGE\n"
+	    "\n"
+	    "\tOUTPUT_IMAGE:   Output file (FITS file)\n"
+	    "\t-i INPUT_IMAGE: Use input image (FITS file)\n"
+	    "\t-x NX; -y NY:   Size of the created image\n"
+	    "\t-g GAIN:        Detector gain (e-/ADU)\n"
+	    "\t-r READNOISE:   Detector read noise (e-)\n"
+	    "\t-b BACKGROUND:  Sky background (ADU)\n"
+	    "\t-s NUM_STARS:   Number of stars on the image\n"
+	    "\t-m STARFILE:    Use file (x,y,flux) for stars\n"
+	    "\t-f FWHM:        Seeing FWHM\n"
+            "\t-c NUM_CRS:     Number of CRs on the image\n"
+	    "\t-p NUM_BADPIX:  Number of bad pixels on image\n"
+	    "\t-n NOISE_MAP:   Name of an image to use for the noise\n"
+	    "\t-z ZERO_LEVEL:  Bias/Zero level to add to image\n"
+	    "\t-Z ZERO_SLOPE:  Bias/Zero slope as a function of row\n"
+	    "\t-o OVERSCAN:    Number of overscan columns to add\n"
+	    "\t-k:             Klean --- no noise added\n"
+	    "\t-h:             Help\n"
+	    "\t-v:             Verbose\n"
+	    "\t-d:             Debug (ie output CR flux, position)\n"
+	    "\n"
+	);
+}
+
+void ckstatus(int status)
+{
+    char msg[81];
+    
+    if (!status)
+	return;
+    while (fits_read_errmsg(msg))
+	fprintf(stderr, "CFITSIO: %s\n", msg);
+    exit(1);
+}
+
+
+/* Finds a value in an array --- note: zero-indexed */
+int find(double value,			// Value to find
+	 double *array,			// Array to find in
+	 int n				// Number of values in array
+    )
+{
+    int low = 0;			// Low-end bracket index
+    int high = n - 1;			// High-end bracket index
+    int index;				// Index to check
+
+    /* Test the ends */
+    if (array[high] < value) {
+	return high - 1;
+    }
+    if (array[low] > value) {
+	return low;
+    }
+
+    /* Bisect */
+    do {
+	index = (high - low) / 2 + low;
+	if (array[index] > value) {
+	    high = index;
+	} else {
+	    low = index;
+	}
+    } while (high > low + 1);
+
+    return low;
+}
+
+
+
+
+float linint(double x[], double y[], int num, double val)
+{
+    /*
+      Returns the value of the function y = f(x) at val,
+      calculated by linear interpolation.
+      There are num values in arrays x and y.
+    */
+
+    int index = find(val, x, num);	// Index of position in x
+    double ans = y[index] + (y[index+1] - y[index]) * (val - x[index]) / (x[index+1] - x[index]);
+
+    return (ans);
+}
+
+float gauss (float val)
+{
+    /*
+      Returns a normal-shaped curve evaulated at val.
+    */
+    return (exp((double)(-0.5*val*val)));
+}
+
+
+void addstar (float *data, int nx, int ny, int nxos, float x, float y, float flux, float seeing)
+/*
+  Adds a Gaussian to the data
+
+  data: The pixels
+  nx, ny: Dimensions
+  nxos: Size of overscan (don't put star here)
+  x, y: Centre of the star
+  flux: peak flux of the star
+  seeing: FWHM of the star
+*/
+{
+    int j,k;   /* Counters */
+    int minj,maxj,mink,maxk;   /* Ranges */
+
+    /* Get range for star */
+    minj = max(0,(int) (x-seeing/SIGMAtoFWHM*MAXSIGMA));
+    maxj = min(nx-1,(int) (x+seeing/SIGMAtoFWHM*MAXSIGMA));
+    mink = max(0,(int) (y-seeing/SIGMAtoFWHM*MAXSIGMA));
+    maxk = min(ny-1,(int) (y+seeing/SIGMAtoFWHM*MAXSIGMA));
+
+    /* Put the star in. */
+    for (j=minj;j<=maxj;j++)
+	for (k=mink;k<=maxk;k++)
+	    data[(nx+nxos)*k+j] += flux*exp(-1.0 * ((x-j)*(x-j) + (y-k)*(y-k))/2.0/(seeing/SIGMAtoFWHM)/(seeing/SIGMAtoFWHM));
+    
+}
+
+/* Return a "fringe" value for a pixel */
+float fringe (int x, int y,		// Pixel coordinates
+	      float periodx, float periody, // Period in x and y
+	      float phasex, float phasey// Phase for x and y
+    )
+{
+    float xval = 2.0*M_PI/periodx * (float)x + phasex;
+    float yval = 2.0*M_PI/periody * (float)y + phasey;
+
+    return cos(xval)*cos(yval);
+}
+
+
Index: /tags/start/stac/scripts/memory.c
===================================================================
--- /tags/start/stac/scripts/memory.c	(revision 12606)
+++ /tags/start/stac/scripts/memory.c	(revision 12606)
@@ -0,0 +1,238 @@
+/*
+** memory.c
+**
+** Handy little functions to allocate memory for arrays etc.
+**
+**
+** CVS: $Id: memory.c,v 1.1.1.1 2004-05-19 22:55:27 price Exp $
+**
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include "memory.h"
+
+/*
+  Function to return a pointer to a generic object, such as a struct.
+*/
+
+void *papalloc (size_t size)
+{
+    void *newobject = malloc(size);
+    if (! newobject)
+    {
+	fprintf (stderr, "Error allocating memory for array: %s\n",strerror(errno));
+	abort();
+    }
+    
+    return (newobject);
+}
+	
+
+
+/*
+  Subroutine to allocate memory for an array of doubles of the
+  indicated size.  Array is zero-offset (pass size+1 for unit-offset
+  array).
+*/
+double *darray (size_t size)
+{
+    double *thearray = malloc(size*sizeof(double));
+    if (!thearray)
+    {
+	fprintf (stderr, "Error allocating memory for array: %s\n",strerror(errno));
+	abort();
+    }
+    
+    return (thearray);
+}
+			     
+
+/*
+  Subroutine to allocate memory for an array of floats of the
+  indicated size.  Array is zero-offset (pass size+1 for unit-offset
+  array).
+*/
+float *farray (size_t size)
+{
+    float *thearray = malloc(size*sizeof(float));
+    if (!thearray)
+    {
+	fprintf (stderr, "Error allocating memory for array: %s\n",strerror(errno));
+	abort();
+    }
+
+    return (thearray);
+}
+
+
+/*
+  Subroutine to allocate memory for an array of integers of the
+  indicated size.  Array is zero-offset (pass size+1 for unit-offset
+  array).
+*/
+int *iarray (size_t size)
+{
+    int *thearray = malloc(size*sizeof(int));
+    if (!thearray)
+    {
+	fprintf (stderr, "Error allocating memory for array: %s\n", strerror(errno));
+	abort();
+    }
+    
+    return (thearray);
+}
+
+/*
+  Subroutine to allocate memory for an array of chars of the indicated
+  size.  Array is zero-offset (pass size+1 for unit-offset array).
+*/
+char *carray (size_t size)
+{
+    char *thearray = malloc(size);   /* Since sizeof(char) == 1 by definition */
+    if (!thearray)
+    {
+	fprintf (stderr, "Error allocating memory for array: %s\n", strerror(errno));
+	abort();
+    }
+    
+    return (thearray);
+}
+
+/*
+  Subroutine to allocate memory for an array of short ints of the
+  indicated size.  Array is zero-offset (pass size+1 for unit-offset
+  array).
+*/
+short int *sarray (size_t size)
+{
+    short int *thearray = malloc(size*sizeof(short int));
+    if (!thearray)
+    {
+	fprintf (stderr, "Error allocating memory for array: %s\n", strerror(errno));
+	abort();
+    }
+    
+    return (thearray);
+}
+
+/*
+  Subroutine to allocate memory for an m x n rectangular matrix of
+  floats.  Matrix is zero-offset (pass size+1 for unit-offset matrix).
+*/
+float **fmatrix (size_t m, size_t n)
+{
+    int i;
+    float **thematrix = (float**)malloc(m*sizeof(float*));
+    if (!thematrix)
+    {
+	fprintf (stderr, "Error allocating memory for matrix: %s\n", strerror(errno));
+	abort();
+    }
+
+    for(i=0;i<m;i++)
+    {
+	thematrix[i] = malloc(n*sizeof(float));
+	if (!thematrix[i])
+	{
+	    fprintf (stderr, "Error allocating memory for matrix: %s\n", strerror(errno));
+	    abort();
+	}
+    }
+
+    return thematrix;
+}
+
+
+
+
+
+/*
+  Subroutine to allocate memory for a square matrix of doubles of the
+  indicated size.  Matrix is zero-offset (pass size+1 for unit-offset
+  matrix).
+*/
+double **squarematrix (size_t size)
+{
+    int i;
+    double **thematrix = (double**)malloc(size*sizeof(double*));
+    if (!thematrix)
+    {
+	fprintf (stderr, "Error allocating memory for matrix: %s\n", strerror(errno));
+	abort();
+    }
+    
+    for(i=0;i<size;i++)
+    {
+	thematrix[i] = malloc(size*sizeof(double));
+	if (!thematrix[i])
+	{
+	    fprintf (stderr, "Error allocating memory for matrix: %s\n", strerror(errno));
+	    abort();
+	}
+    }
+  
+    return thematrix;
+}
+
+
+/*
+  Subroutine to allocate memory for an m x n rectangular matrix of
+  doubles.  Matrix is zero-offset (pass size+1 for unit-offset matrix).
+*/
+double **rectmatrix (size_t m, size_t n)
+{
+    int i;
+    double **thematrix = (double**)malloc(m*sizeof(double*));
+    if (!thematrix)
+    {
+	fprintf (stderr, "Error allocating memory for matrix: %s\n", strerror(errno));
+	abort();
+    }
+
+    for(i=0;i<m;i++)
+    {
+	thematrix[i] = malloc(n*sizeof(double));
+	if (!thematrix[i])
+	{
+	    fprintf (stderr, "Error allocating memory for matrix: %s\n", strerror(errno));
+	    abort();
+	}
+    }
+
+    return thematrix;
+}
+
+
+/*
+  Subroutine to allocate memory for an m x n rectangular matrix.
+  Matrix is zero-offset (pass size+1 for unit-offset matrix).  This
+  function adds a buffer of 1 pixel around the edge (i.e. it runs from
+  -1 to m instead of 0 to m-1) --- provided by Nick Kaiser.
+*/
+double **padrectmatrix(size_t m, size_t n)
+{
+
+    int i;
+    double **thematrix = (double **)malloc((m+2)*sizeof(double*)) + 1;
+    if (!thematrix)
+    {
+	fprintf (stderr, "Error allocating memory for matrix: %s\n", strerror(errno));
+	abort();
+    }
+
+    for(i=-1;i<=m;i++)
+    {
+	thematrix[i] = malloc((n+2)*sizeof(double)) + 1;
+	if (!thematrix[i])
+	{
+	    fprintf (stderr, "Error allocating memory for matrix: %s\n", strerror(errno));
+	    abort();
+	}
+    }
+
+    return thematrix;
+}
+
Index: /tags/start/stac/scripts/memory.h
===================================================================
--- /tags/start/stac/scripts/memory.h	(revision 12606)
+++ /tags/start/stac/scripts/memory.h	(revision 12606)
@@ -0,0 +1,83 @@
+/*
+** memory.h
+**
+** Header file for memory.c
+**
+** CVS: $Id: memory.h,v 1.1.1.1 2004-05-19 22:55:27 price Exp $
+**
+*/
+
+#ifndef _MEMORY_H
+#define _MEMORY_H
+
+
+void *papalloc (size_t size);
+/*
+  Function to return a pointer to a generic object, such as a struct.
+*/
+
+double *darray (size_t size);
+/*
+  Subroutine to allocate memory for an array of doubles of the
+  indicated size.  Array is zero-offset (pass size+1 for unit-offset
+  array).
+*/
+
+float *farray (size_t size);
+/*
+  Subroutine to allocate memory for an array of floats of the
+  indicated size.  Array is zero-offset (pass size+1 for unit-offset
+  array).
+*/
+
+int *iarray (size_t size);
+/*
+  Subroutine to allocate memory for an array of integers of the
+  indicated size.  Array is zero-offset (pass size+1 for unit-offset
+  array).
+*/
+
+short int *sarray (size_t size);
+/*
+  Subroutine to allocate memory for an array of short ints of the
+  indicated size.  Array is zero-offset (pass size+1 for unit-offset
+  array).
+*/
+
+char *carray (size_t size);
+/*
+  Subroutine to allocate memory for an array of chars of the indicated
+  size.  Array is zero-offset (pass size+1 for unit-offset array).
+*/
+
+float **fmatrix (size_t m, size_t n);
+/*
+  Subroutine to allocate memory for an m x n rectangular matrix of
+  floats.  Matrix is zero-offset (pass size+1 for unit-offset matrix).
+*/
+
+double **squarematrix (size_t size);
+/*
+  Subroutine to allocate memory for a square matrix of doubles of the
+  indicated size.  Matrix is zero-offset (pass size+1 for unit-offset
+  matrix).
+*/
+
+double **rectmatrix (size_t m, size_t n);
+/*
+  Subroutine to allocate memory for an m x n rectangular matrix of
+  doubles.  Matrix is zero-offset (pass size+1 for unit-offset matrix).
+*/
+
+double **padrectmatrix(size_t m, size_t n);
+/*
+  Subroutine to allocate memory for an m x n rectangular matrix.
+  Matrix is zero-offset (pass size+1 for unit-offset matrix).  This
+  function adds a buffer of 1 pixel around the edge (i.e. it runs from
+  -1 to m instead of 0 to m-1) --- provided by Nick Kaiser.
+*/
+
+
+
+
+#endif
Index: /tags/start/stac/src/Makefile
===================================================================
--- /tags/start/stac/src/Makefile	(revision 12606)
+++ /tags/start/stac/src/Makefile	(revision 12606)
@@ -0,0 +1,60 @@
+SHELL = /bin/sh
+CC = gcc
+CFLAGS = -O2 -g -std=c99 -I/home/mithrandir/price/psLib3/psLib/include # -DTESTING
+PSLIB = -L/home/mithrandir/price/psLib3/psLib/lib/ -lpslib -lgsl -lgslcblas -lfftw3f -lsla -lcfitsio -lm
+LDFLAGS = $(PSLIB)
+
+OBJECTS = stac.o stacConfig.o stacRead.o stacErrorImages.o stacTransform.o stacCheckMemory.o \
+	stacCombine.o stacInvertMaps.o stacRejection.o psPlaneTransform.o
+
+TARGET = stac
+
+.PHONY: tags clean empty test profile optimise
+
+.c.o:
+		$(CC) -c $(CFLAGS) $(OPTFLAGS) $<
+
+$(TARGET):	$(OBJECTS)
+		$(CC) $(CFLAGS) -o $@ $(OBJECTS) $(LDFLAGS) $(OPTFLAGS)
+
+clean:
+		-$(RM) *.o gmon.* profile.txt
+
+empty:		clean
+		-$(RM) $(TARGET) TAGS
+
+test:		stac test_0.fits test_1.fits test_2.fits test_3.fits
+		-$(RM) testout.fits
+		-$(RM) testout.fits.pre
+		-$(RM) test_[0-3].fits.err
+		-$(RM) test_[0-3].fits.mask
+		-$(RM) test_[0-3].fits.shift.?
+		-$(RM) test_[0-3].fits.shiftrej
+		-$(RM) test_[0-3].fits.shifterr.*
+		-$(RM) leaks.dat
+		./stac -v testout.fits test_0.fits test_1.fits test_2.fits test_3.fits
+
+# Run profiling.
+profile:	CFLAGS += -pg
+profile:	empty $(TARGET)
+		$(RM) gmon.*
+		for ((i = 0; i < 10; i++)) \
+		do \
+			$(MAKE) test; \
+			mv -f gmon.out gmon.$$i; \
+		done
+		gprof -p -q -l $(TARGET) gmon.* > profile.txt
+
+# Do gcc optimisation
+optimise:	clean
+		-$(RM) $(TARGET)
+		export OPTFLAGS=-fprofile-arcs ; $(MAKE) test
+		-$(RM) $(TARGET)
+		$(MAKE) clean
+		export OPTFLAGS=-fbranch-probabilities ; $(MAKE) $(TARGET)
+		-$(RM) *.da
+
+# Tags for emacs
+tags:
+		etags `find . -name \*.[ch] -print`
+
Index: /tags/start/stac/src/psPlaneTransform.c
===================================================================
--- /tags/start/stac/src/psPlaneTransform.c	(revision 12606)
+++ /tags/start/stac/src/psPlaneTransform.c	(revision 12606)
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include "pslib.h"
+#include "stac.h"
+
+#define PS_INT_CHECK_NON_NEGATIVE(NAME, RVAL) \
+if (NAME < 0) { \
+    psError("pslib.badValue", \
+            "Error: %s is less than 0.", #NAME); \
+    return(RVAL); \
+}
+
+static void planeTransformFree(psPlaneTransform *pt)
+{
+    psFree(pt->x);
+    psFree(pt->y);
+}
+
+psPlaneTransform* psPlaneTransformAlloc(psS32 n1, psS32 n2)
+{
+    PS_INT_CHECK_NON_NEGATIVE(n1, NULL);
+    PS_INT_CHECK_NON_NEGATIVE(n2, NULL);
+
+    psPlaneTransform *pt = psAlloc(sizeof(psPlaneTransform));
+    pt->x = psDPolynomial2DAlloc(n1, n2, PS_POLYNOMIAL_ORD);
+    pt->y = psDPolynomial2DAlloc(n1, n2, PS_POLYNOMIAL_ORD);
+
+    p_psMemSetDeallocator(pt, (psFreeFcn) planeTransformFree);
+    return(pt);
+}
+
Index: /tags/start/stac/src/stac.c
===================================================================
--- /tags/start/stac/src/stac.c	(revision 12606)
+++ /tags/start/stac/src/stac.c	(revision 12606)
@@ -0,0 +1,91 @@
+#include <stdio.h>
+#include "pslib.h"
+#include "stac.h"
+
+
+int main(int argc, char **argv)
+{
+
+#if 0
+    psMemAllocateCallbackSet(stacMemPrint);
+    psMemAllocateCallbackSetID(185);
+    psMemFreeCallbackSet(stacMemPrint);
+    psMemFreeCallbackSetID(185);
+#endif
+
+    // Set trace levels
+    psTraceSetLevel(".",0);
+    psTraceSetLevel("stac.checkMemory",10);
+    psTraceSetLevel("stac.config",10);
+    psTraceSetLevel("stac.read",10);
+    psTraceSetLevel("stac.invertMaps",10);
+    psTraceSetLevel("stac.errors",10);
+    psTraceSetLevel("stac.transform",10);
+    psTraceSetLevel("stac.combine",10);
+    psTraceSetLevel("stac.rejection",10);
+
+    // Set logging level
+    psLogSetLevel(9);
+
+    // Parse command line
+    stacConfig *config = stacParseConfig(argc, argv);
+
+    // Read input files
+    psArray *inputs = stacReadImages(config);
+
+    // Read maps
+    psArray *maps = stacReadMaps(config);
+
+    // Invert maps
+    psArray *inverseMaps = stacInvertMaps(maps);
+
+    // Generate errors
+    psArray *errors = stacErrorImages(inputs, config);
+
+    // Transform inputs and errors
+    psArray *transformedErrors = NULL;
+    psArray *transformed = stacTransform(inputs, inverseMaps, errors, &transformedErrors, NULL, config);
+
+    // Combine with rejection
+    psArray *rejected = NULL;
+    psImage *combined = stacCombine(transformed, transformedErrors, 1,  &rejected, config);
+
+#ifdef TESTING
+    char prefile[MAXCHAR];		// Filename of precombined image
+    sprintf(prefile,"%s.pre",config->output);
+    psImageWriteSection(combined,0,0,0,NULL,0,prefile);
+#endif
+
+    // Transform rejected pixels to source frame
+    psArray *rejectedSource = stacRejection(inputs, transformed, combined, maps, rejected, config);
+
+    // Redo transformation with the mask
+    psFree(transformed);
+    psFree(transformedErrors);
+    psArray *transformedErrorsNew = NULL;
+    psArray *transformedNew = stacTransform(inputs, inverseMaps, errors, &transformedErrorsNew,
+					    rejectedSource, config);
+
+    // Combine the newly-transformed CR-free images, no rejection
+    psFree(combined);
+    psFree(rejected);
+    rejected = NULL;
+    combined = stacCombine(transformedNew, transformedErrorsNew, 0,  &rejected, config);
+
+    // Write output image
+    psImageWriteSection(combined,0,0,0,NULL,0,config->output);
+
+    // Free everything I've used
+    stacConfigFree(config);
+    psFree(inputs);
+    psFree(maps);
+    psFree(inverseMaps);
+    psFree(errors);
+    psFree(transformedErrors);
+    psFree(transformedNew);
+    psFree(rejectedSource);
+    psFree(combined);
+
+    // Check memory for leaks, corruption
+    stacCheckMemory();
+}
Index: /tags/start/stac/src/stac.h
===================================================================
--- /tags/start/stac/src/stac.h	(revision 12606)
+++ /tags/start/stac/src/stac.h	(revision 12606)
@@ -0,0 +1,141 @@
+#ifndef STAC_H
+#define STAC_H
+
+#include "pslib.h"
+
+#define abs(x) ((x) >= 0 ? (x) : (-(x)))
+
+#define MAXCHAR 80
+
+// Temporary implementation
+psPlaneTransform *psPlaneTransformAlloc(psS32 n1, psS32 n2);
+
+/************************************************************************************************************/
+
+// stacConfig.c
+
+// Configuration options
+typedef struct {
+    int verbose;			// Verbosity level
+    float gain, readnoise;		// Gain and readnoise for detectors
+    psArray *inputs;			// Input file names
+    const char *output;			// Output file name
+    int outnx, outny;			// Size of output image
+    float saturated;			// Saturation level
+    float bad;				// Bad level
+    float reject;			// Rejection level
+    float frac;				// Fraction of input pixel that must be masked before the pixel is
+					// considered bad
+} stacConfig;
+
+// Allocator
+stacConfig *stacConfigAlloc(void);
+// Deallocator
+void stacConfigFree(stacConfig *config);
+
+// Help message
+void help(const char *name);
+
+// Parse the command line and return config
+stacConfig *stacParseConfig(int argc,	// Number of command-line arguments
+			    char **argv // Command-line arguments
+    );
+
+
+/************************************************************************************************************/
+
+// stacRead.c
+
+// Read the input files and return an array of images
+psArray *stacReadImages(stacConfig *config);
+
+// Read the map files and return an array of transformations
+psArray *stacReadMaps(stacConfig *config);
+
+/************************************************************************************************************/
+
+// stacErrorImages.c
+
+// Calculate the error images
+psArray *stacErrorImages(psArray *inputs, // Array of input images
+			 stacConfig *config // Configuration details
+    );
+
+/************************************************************************************************************/
+
+// stacTransform.c
+
+// Transform input images
+psArray *stacTransform(const psArray *images, // Array of images to be transformed
+		       const psArray *maps, // Array of polynomials that do the transformation
+		       const psArray *errors, // Array of error images
+		       psArray **outErrors, // Array of output errors
+		       const psArray *masks, // Masks of input images
+		       const stacConfig *config	// Configuration
+    );
+
+/************************************************************************************************************/
+
+// stacCheckMemory.c
+
+// Check memory
+void stacCheckMemory(void);
+
+// Print out the problem
+void stacMemoryProblem(const psMemBlock* ptr, ///< the pointer to the problematic memory block.
+		       const char *file, ///< the file in which the problem originated
+		       psS32 lineno	///< the line number in which the problem originated
+    );
+
+// Print out a memblock when it's allocated --- this function used as a callback
+psMemoryId stacMemPrint(const psMemBlock *ptr);
+
+
+/************************************************************************************************************/
+
+// stacCombine.c
+
+// Get the mean for a bunch of values
+float stacCombineMean(psVector *values,	// Values for which to take the mean
+		      psVector *errors,	// Errors in the values
+		      psVector *masks	// Masks for the values, 0 = don't use, 1 = use
+    );
+
+// Get the median for a bunch of values
+float stacCombineMedian(psVector *values, // Values for which to take the median
+			psVector *errors, // Errors in the values
+			psVector *masks	// Masks for the values, 0 = don't use, 1 = use
+    );
+
+// Combine the transformed images
+psImage *stacCombine(psArray *images,	// Array of transformed images
+		     psArray *errors,	// Array of transformed error images
+		     int nReject,	// Number of rejection iterations
+		     psArray **rejected, // Array of rejection masks
+		     stacConfig *config	// Configuration
+    );
+
+/************************************************************************************************************/
+
+// stacInvertMaps.c
+
+// Invert an array of maps
+psArray *stacInvertMaps(const psArray *maps // Array of maps to invert
+    );
+
+
+/************************************************************************************************************/
+
+// stacRejection.c
+
+// Transform the rejection masks back to the source frame
+psArray *stacRejection(psArray *inputs,	// Input images
+		       psArray *transformed, // Transformed images
+		       psImage *combined, // Combined image
+		       psArray *maps,	// Maps from input to transformed image
+		       psArray *rejected, // Rejected images
+		       stacConfig *config // Configuration
+    );
+
+
+#endif
Index: /tags/start/stac/src/stacCheckMemory.c
===================================================================
--- /tags/start/stac/src/stacCheckMemory.c	(revision 12606)
+++ /tags/start/stac/src/stacCheckMemory.c	(revision 12606)
@@ -0,0 +1,62 @@
+#include <stdio.h>
+#include "pslib.h"
+#include "stac.h"
+
+
+#define LEAKS "leaks.dat"		// File to which to write leaks data
+
+
+psMemoryId stacMemPrint(const psMemBlock *ptr)
+{
+    psLogMsg("stac.memoryPrint", PS_LOG_INFO,
+	     "Memory block %d:\n"
+	     "\tFile %s, line %d, size %d\n"
+	     "\tPosts: %x %x %x\n",
+	     ptr->id, ptr->file, ptr->lineno, ptr->userMemorySize, ptr->startblock, ptr->endblock,
+	     *(void**)((int8_t *)(ptr + 1) + ptr->userMemorySize));
+    return 0;
+}
+
+
+void stacMemoryProblem(const psMemBlock* ptr, ///< the pointer to the problematic memory block.
+		       const char *file, ///< the file in which the problem originated
+		       psS32 lineno	///< the line number in which the problem originated
+    )
+{
+    psLogMsg("stac.checkMemory.corruption", PS_LOG_WARN,
+	     "Memory corruption detected in memBlock %d\n"
+	     "\tFile %s, line %d, size %d\n"
+	     "\tPosts: %x %x %x\n",
+	     ptr->id, file, lineno, ptr->userMemorySize, ptr->startblock, ptr->endblock,
+	     (ptr + 1 + ptr->userMemorySize));
+}
+
+
+
+void stacCheckMemory(void)
+{
+    psMemBlock **leaks = NULL;		// List of leaks
+    FILE *leakFile;			// File to write leaks to
+
+    psTrace("stac.checkMemory", 1, "Checking for memory problems....\n");
+
+    (void)psMemProblemCallbackSet(stacMemoryProblem); // Set callback for corruption
+
+    if ((leakFile = fopen(LEAKS, "w")) == NULL) {
+	psError("stac.checkMemory", "Unable to open leaks file, %s\n",LEAKS);
+	return;
+    }
+
+    int nLeaks = psMemCheckLeaks(0, &leaks, leakFile); // Number of leaks
+    psTrace("stac.checkMemory", 1, "%d leaks found.\n", nLeaks);
+    for (int i = 0; i < nLeaks; i++) {
+	psLogMsg("stac.checkMemory.leaks", PS_LOG_WARN,
+		 "Memory leak detection: memBlock %d\n"
+		 "\tFile %s, line %d, size %d\n",
+		 leaks[i]->id, leaks[i]->file, leaks[i]->lineno, leaks[i]->userMemorySize);
+    }
+
+    int nCorrupted = psMemCheckCorruption(false); // Number of corrupted
+    psTrace("stac.checkMemory", 1, "%d memory blocks corrupted.\n", nCorrupted);
+
+}
Index: /tags/start/stac/src/stacCombine.c
===================================================================
--- /tags/start/stac/src/stacCombine.c	(revision 12606)
+++ /tags/start/stac/src/stacCombine.c	(revision 12606)
@@ -0,0 +1,176 @@
+#include <stdio.h>
+#include <math.h>
+#include "pslib.h"
+#include "stac.h"
+
+#define SQUARE(x) ((x)*(x))
+#define ABS(x) ((x) >= 0 ? (x) : -(x))
+
+float stacCombineMean(psVector *values,	// Values for which to take the mean
+		      psVector *errors,	// Errors in the values
+		      psVector *masks	// Masks for the values, 0 = don't use, 1 = use
+    )
+{
+#if 0
+    // Would like to use psVectorStats, but it doesn't have errors built in yet
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
+    (void)psVectorStats(stats, values, masks, 1);
+    psFree(stats);
+    return stats->sampleMean;
+#else
+    // Instead, do it ourselves
+    double sum = 0.0;
+    double weights = 0.0;
+    int num = values->n;
+    for (int i = 0; i < num; i++) {
+	if (masks->data.U8[i]) {
+	    sum += values->data.F32[i] / SQUARE(errors->data.F32[i]);
+	    weights += 1.0 / SQUARE(errors->data.F32[i]);
+	}
+    }
+    if (weights > 0.0) {
+	return (float)(sum/weights);
+    } else {
+	return NAN;
+    }
+#endif
+
+}
+
+
+float stacCombineMedian(psVector *values, // Values for which to take the median
+			psVector *errors, // Errors in the values
+			psVector *masks	// Masks for the values, 0 = don't use, 1 = use
+    )
+{
+    psStats *stats = psStatsAlloc(PS_STAT_SAMPLE_MEDIAN);
+    (void)psVectorStats(stats, values, masks, 1);
+    psFree(stats);
+    return stats->sampleMedian;
+}
+
+
+psImage *stacCombine(psArray *images,	// Array of transformed images
+		     psArray *errors,	// Array of transformed error images
+		     int nReject,	// Number of rejection iterations
+		     psArray **rejected, // Array of rejection masks
+		     stacConfig *config	// Configuration
+    )
+{
+    int nImages = images->n;		// Number of images
+    int numRows = ((psImage*)images->data[0])->numRows;	// Image size
+    int numCols = ((psImage*)images->data[0])->numCols; // Image size
+    float saturated = config->saturated;// Saturation limit
+    float bad = config->bad;		// Bad pixel limit
+    float reject = config->reject;	// Rejection (k-sigma)
+    
+    // Check dimensions for consistency
+    for (int i = 0; i < nImages; i++) {
+	psImage *image = (psImage *)images->data[i]; // The image
+	psImage *error = (psImage *)errors->data[i]; // The error image
+
+	if ((image->numCols != numCols) || (image->numRows != numRows)) {
+	    psError("stac.combine",
+		    "Image size mismatch on error image %d\nExpected %dx%d, got %dx%d\n",
+		    i, numCols, numRows, image->numCols, image->numRows);
+	    return NULL;
+	}
+	if ((error->numCols != numCols) || (error->numRows != numRows)) {
+	    psError("stac.combine",
+		    "Image size mismatch on error image %d\nExpected %dx%d, got %dx%d\n",
+		    i, numCols, numRows, error->numCols, error->numRows);
+	    return NULL;
+	}
+    }
+
+    psTrace("stac.combine", 1, "Combining images....\n");
+    psTrace("stac.combine", 3, "Saturation: %f Bad: %f\n", saturated, bad);
+
+    psVector *pixels = psVectorAlloc(nImages, PS_TYPE_F32); // Will hold the pixels in the statistics step
+    psVector *deltas = psVectorAlloc(nImages, PS_TYPE_F32); // Will hold the errors in the statistics step
+    psVector *mask = psVectorAlloc(nImages, PS_TYPE_U8); // Mask bad pixels
+    psImage *combined = psImageAlloc(numCols, numRows, PS_TYPE_F32); // Combined image
+
+
+    // Set up rejection masks
+    if (nReject > 0) {
+	if (*rejected == NULL) {
+	    // Allocate the rejection masks, if required
+	    *rejected = psArrayAlloc(nImages);
+	} else if ((*rejected)->n != nImages) {
+	    psError("stac.combine", "Number of rejection masks (%d) does not match number of input"
+		    "images (%d).\n", (*rejected)->n, nImages);
+	    return NULL;
+	}
+	for (int i = 0; i < nImages; i++) {
+	    (*rejected)->data[i] = psImageAlloc(numCols, numRows, PS_TYPE_F32); // Create rejection mask
+	    // Zero out the mask
+	    for (int r = 0; r < numRows; r++) {
+		for (int c = 0; c < numCols; c++) {
+		    ((psImage*)((*rejected)->data[i]))->data.F32[r][c] = 0.0;
+		}
+	    }
+	}
+    }
+    
+    
+    for (int y = 0; y < numRows; y++) {
+	for (int x = 0; x < numCols; x++) {
+	    
+	    // Export pixels into the vector and get stats
+	    for (int i = 0; i < nImages; i++) {
+		float pixel = ((psImage*)images->data[i])->data.F32[y][x];
+		float delta = ((psImage*)errors->data[i])->data.F32[y][x];
+		pixels->data.F32[i] = pixel;
+		deltas->data.F32[i] = delta;
+		if ((pixel >= saturated) || (pixel <= bad) || (! isfinite(pixel)) || (! isfinite(delta))) {
+		    mask->data.U8[i] = (psU8)0; // Don't use!
+		} else {
+		    mask->data.U8[i] = (psU8)1; // Use.
+		}
+	    }
+	    
+	    float average = stacCombineMean(pixels, deltas, mask); // Combined value
+	    
+	    // Rejection iterations
+	    for (int rejNum = 0; rejNum < nReject; rejNum++) {
+		float max = 0.0;
+		int maxIndex = 0;
+		for (int i = 0; i < nImages; i++) {
+		    if (mask->data.U8[i] && (ABS(pixels->data.F32[i] - average) / deltas->data.F32[i] > max)) {
+			max = ABS(pixels->data.F32[i] - average) / deltas->data.F32[i];
+			maxIndex = i;
+		    }
+		}
+		// Reject the pixel with the maximum deviation
+		if (max > reject) {    
+		    mask->data.U8[maxIndex] = 0;
+		    ((psImage*)((*rejected)->data[maxIndex]))->data.F32[y][x] += 1.0;
+		    // Re-do combination following rejection
+		    average = stacCombineMean(pixels, deltas, mask);
+		}
+	    } // Rejection iterations
+	    
+	    combined->data.F32[y][x] = average;
+	}
+    } // Iterating over output pixels
+
+#ifdef TESTING
+    // Write rejection images out to check
+    if (nReject > 0) {
+	for (int i = 0; i < nImages; i++) {
+	    char rejfile[MAXCHAR];		// Filename of rejection image
+	    sprintf(rejfile,"%s.shiftrej",config->inputs->data[i]);
+	    psImageWriteSection((psImage*)((*rejected)->data[i]),0,0,0,NULL,0,rejfile);
+	}
+    }
+#endif
+
+
+    // Clean up
+    psFree(pixels);
+    psFree(deltas);
+    psFree(mask);
+
+    return combined;
+}
Index: /tags/start/stac/src/stacConfig.c
===================================================================
--- /tags/start/stac/src/stacConfig.c	(revision 12606)
+++ /tags/start/stac/src/stacConfig.c	(revision 12606)
@@ -0,0 +1,156 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include "stac.h"
+
+void help(const char *name)
+{
+    fprintf (stderr, "STAC: Simultaneous Telescope Array Combination\n"
+	     "Usage: %s [-h] [-v] [-g GAIN] [-r RN] [-o NX NY] [-s SAT] [-b BAD] [-k REJ] [-k FRAC] OUT IN1 IN2...\n"
+	     "where\n"
+	     "\t-h           Help (this info)\n"
+	     "\t-v           Increase verbosity level\n"
+	     "\t-g           Gain (e/ADU) for detectors\n"
+	     "\t-r           Read noise (e) for detectors\n"
+	     "\t-o NX NY     Size of output image (512, 512)\n"
+	     "\t-s SAT       Saturation level (65536)\n"
+	     "\t-b BAD       Bad level (0)\n"
+	     "\t-k REJ       Rejection level (k-sigma; 3.5)\n"
+	     "\t-f FRAC      Fraction of pixel to be marked before considered bad (0.8)\n"
+	     "\tOUT          Output image\n"
+	     "\tIN1, IN2...  Input images, which have associated .map files.\n",
+	     name
+	);
+}
+
+
+stacConfig *stacConfigAlloc(void)
+{
+    // Allocate memory
+    stacConfig *config = (stacConfig*) psAlloc(sizeof(stacConfig));
+    // Set defaults
+    config->verbose = 0;
+    config->gain = 1.0;
+    config->readnoise = 0.0;
+    config->inputs = NULL;
+    config->output = NULL;
+    config->outnx = 512;
+    config->outny = 512;
+    config->saturated = 65536.0;
+    config->bad = 0.0;
+    config->reject = 2.75;
+    config->frac = 0.5;
+
+    return config;
+}
+
+
+void stacConfigFree(stacConfig *config)
+{
+    // Free the vector, if necessary
+    if (config->inputs) {
+	psFree(config->inputs);
+    }
+    // Free everything
+    psFree(config);
+}
+
+
+stacConfig *stacParseConfig(int argc,	// Number of command-line arguments
+			    char **argv // Command-line arguments
+    )
+{
+    stacConfig *config = stacConfigAlloc(); // Configuration values
+    const char *programName = argv[0];	// Program name
+
+    /* Variables for getopt */
+    int opt;   /* Option, from getopt */
+    extern char *optarg;   /* Argument accompanying switch */
+    extern int optind;   /* getopt variables */
+
+    /* Parse command-line arguments using getopt */
+    while ((opt = getopt(argc, argv, "hvg:r:o:s:b:k:f:")) != -1) {
+        switch (opt) {
+	  case 'h':
+	    help(programName);
+	    exit(EXIT_SUCCESS);
+	  case 'v':
+            config->verbose++;
+            break;
+	  case 'g':
+	    if (sscanf(optarg, "%f", &config->gain) != 1) {
+		help(programName);
+	    }
+	    break;
+	  case 'r':
+	    if (sscanf(optarg, "%f", &config->readnoise) != 1) {
+		help(programName);
+	    }
+	    break;
+	  case 'o':
+            if ((sscanf(argv[optind-1], "%d", &config->outnx) != 1) ||
+                (sscanf(argv[optind++], "%d", &config->outny) != 1)) {
+                /*
+                  Note: incrementing optind, so I can read more than
+                  one parameter.
+                */
+                help(programName);
+                exit(EXIT_FAILURE);
+            }
+	    break;
+	  case 's':
+	    if (sscanf(optarg, "%f", &config->saturated) != 1) {
+		help(programName);
+	    }
+	    break;
+	  case 'b':
+	    if (sscanf(optarg, "%f", &config->bad) != 1) {
+		help(programName);
+	    }
+	    break;
+	  case 'k':
+	    if (sscanf(optarg, "%f", &config->reject) != 1) {
+		help(programName);
+	    }
+	    break;
+	  case 'f':
+	    if (sscanf(optarg, "%f", &config->frac) != 1) {
+		help(programName);
+	    }
+	    break;
+	  default:
+	    help(programName);
+	}
+    }
+
+    /* Get the remaining, mandatory values */
+    argc -= optind;
+    argv += optind;
+    if (argc < 2) {
+        help(programName);
+        exit(EXIT_FAILURE);
+    }
+
+    config->output = argv[0];		// Output file
+    // Get the input files
+    config->inputs = psArrayAlloc(argc-1);
+    for (int i = 1; i < argc; i++) {
+	config->inputs->data[i-1] = psAlloc(strlen(argv[i]));
+	strncpy(config->inputs->data[i-1], argv[i], strlen(argv[i]));
+    }
+
+    // Debugging output
+    psTrace("stac.config", 8, "Parsed command line for configuration\n");
+    psTrace("stac.config", 9, "Verbosity level: %d\n",config->verbose);
+    psTrace("stac.config", 9, "%d inputs:\n",config->inputs->n);
+    for (int i = 0; i < config->inputs->n; i++) {
+	psTrace("stac.config", 9, "\t%s\n", config->inputs->data[i]);
+    }
+    psTrace("stac.config", 9, "Output file is %s\n",config->output);
+    psTrace("stac.config", 9, "Output file size is %dx%d\n", config->outnx, config->outny);
+
+    return config;
+}
+
Index: /tags/start/stac/src/stacErrorImages.c
===================================================================
--- /tags/start/stac/src/stacErrorImages.c	(revision 12606)
+++ /tags/start/stac/src/stacErrorImages.c	(revision 12606)
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include "pslib.h"
+#include "stac.h"
+
+psArray *stacErrorImages(psArray *inputs, // Array of input images
+			 stacConfig *config // Configuration details
+    )
+{
+    float invGain = 1.0/config->gain;	// Inverse square root of gain
+    float rn = config->readnoise/config->gain; // Read noise in ADU
+    psArray *errors = psArrayAlloc(inputs->n);
+
+    psTrace("stac.errors", 1, "Calculating error images....\n");
+
+    // Iterate over the input images
+    for (int i = 0; i < inputs->n; i++) {
+	psTrace("stac.errors",5,"Working on image #%d\n",i);
+
+	psImage *image = inputs->data[i]; // Pull out the image of interest
+	int numRows = image->numRows;	// Number of rows
+	int numCols = image->numCols;	// Number of columns	
+	psImage *error = psImageAlloc(numCols, numRows, PS_TYPE_F32); // The error image
+
+	// Iterate over the pixels
+	for (int r = 0; r < numRows; r++) {
+	    for (int c = 0; c < numCols; c++) {
+		// We actually calculate the variance
+		error->data.F32[r][c] = image->data.F32[r][c]*invGain + rn*rn;
+	    }
+	}
+
+	// Put image onto the array
+	errors->data[i] = error;
+ 
+#ifdef TESTING
+	// Write error image out to check
+	char errfile[MAXCHAR];		// Filename of error image
+	sprintf(errfile,"%s.err",config->inputs->data[i]);
+	psImageWriteSection(error,0,0,0,NULL,0,errfile);
+#endif
+
+    }
+
+    return errors;
+}
Index: /tags/start/stac/src/stacInvertMaps.c
===================================================================
--- /tags/start/stac/src/stacInvertMaps.c	(revision 12606)
+++ /tags/start/stac/src/stacInvertMaps.c	(revision 12606)
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include "pslib.h"
+#include "stac.h"
+
+
+#define MAX(x,y) ((x) > (y) ? (x) : (y))
+
+psArray *stacInvertMaps(const psArray *maps // Array of maps to invert
+    )
+{
+    int nMaps = maps->n;		// Number of maps
+    psArray *inverted = psArrayAlloc(nMaps); // Array of inverted maps for output
+
+    psTrace("stac.invertMaps", 1, "Inverting maps....\n");
+
+    for (int i = 0; i < nMaps; i++) {
+	// Can't handle higher order than linear yet
+	if (((psPlaneTransform*)maps->data[i])->x->nX != 2 ||
+	    ((psPlaneTransform*)maps->data[i])->x->nY != 2 ||
+	    ((psPlaneTransform*)maps->data[i])->y->nX != 2 ||
+	    ((psPlaneTransform*)maps->data[i])->y->nY != 2) {
+	    psError("stac.invertMaps",
+		    "STAC cannot currently support orders other than linear.\n");
+	    psFree(inverted);
+	    return NULL;
+	}
+
+	psPlaneTransform *newMap = psPlaneTransformAlloc(2, 2); // Inverted map
+	psPlaneTransform *oldMap = (psPlaneTransform*)maps->data[i]; // Uninverted map
+
+	// Now, simply do a 2x2 matrix inversion
+
+	double a = oldMap->x->coeff[1][0];
+	double b = oldMap->x->coeff[0][1];
+	double c = oldMap->y->coeff[1][0];
+	double d = oldMap->y->coeff[0][1];
+	double e = oldMap->x->coeff[0][0];
+	double f = oldMap->y->coeff[0][0];
+
+	double invDet = 1.0 / (a * d - b * c); // Inverse of the determinant
+
+	// Not entirely sure why this works, but it appears to do so.......................................
+	newMap->x->coeff[1][0] = invDet * a;
+	newMap->x->coeff[0][1] = - invDet * b;
+	newMap->y->coeff[1][0] = - invDet * c;
+	newMap->y->coeff[0][1] = invDet * d;
+
+	newMap->x->coeff[0][0] = - invDet * (d * e + c * f);
+	newMap->y->coeff[0][0] = - invDet * (b * e + a * f);
+
+#ifdef TESTING
+	// Go forward then backward
+	double x = 123.4;
+	double y = 432.1;
+	psPlane *oldCoords = psAlloc(sizeof(psPlane));
+	oldCoords->x = x;
+	oldCoords->y = y;
+	psPlane *newCoords = psPlaneTransformApply(NULL, oldMap, oldCoords);
+	psTrace("stac.invertMaps.test", 5, "%f,%f --> %f,%f\n", x, y, newCoords->x, newCoords->y);
+	(void)psPlaneTransformApply(oldCoords, newMap, newCoords);
+	psTrace("stac.invertMaps.test", 5, "--------> %f,%f\n", oldCoords->x, oldCoords->y);
+	psFree(newCoords);
+	psFree(oldCoords);
+#endif
+
+	inverted->data[i] = newMap;	// Stuff into the array
+    }
+
+    return inverted;
+}
+
+
Index: /tags/start/stac/src/stacRead.c
===================================================================
--- /tags/start/stac/src/stacRead.c	(revision 12606)
+++ /tags/start/stac/src/stacRead.c	(revision 12606)
@@ -0,0 +1,114 @@
+#include <stdio.h>
+#include <string.h>
+#include "pslib.h"
+#include "stac.h"
+
+#define ORDER 2
+
+psArray *stacReadImages(stacConfig *config)
+{
+    psArray *filenames = config->inputs;// The file names
+    int nFiles = filenames->n;		// The number of input files
+    psArray *files = psArrayAlloc(nFiles); // The input files, to be returned
+
+    psTrace("stac.read.images",1,"Reading input images....\n");
+    for (int i = 0; i < nFiles; i++) {
+	// We only read PHUs --- not mucking around with extensions for now
+	psTrace("stac.read.images",2,"Reading input image %s....\n",filenames->data[i]);
+	files->data[i] = psImageReadSection(NULL, 0, 0, 0, 0, 0, NULL, 0, filenames->data[i]);
+	if (files->data[i] == NULL) {
+	    psErrorStackPrint(stderr,"Fatal error: Unable to read %s\n",filenames->data[i]);
+	    exit(EXIT_FAILURE);
+	}
+	// Big assumption: input images are 32-bit.
+	if (((psImage*)(files->data[i]))->type.type != PS_TYPE_F32) {
+	    psError("stac.read.images", "Image %d is not 32-bit\n",i);
+	}
+    }
+    psTrace("stac.read.images",1,"%d input images read.\n",nFiles);
+
+    return files;
+}
+
+
+psArray *stacReadMaps(stacConfig *config)
+{
+    psArray *filenames = config->inputs;// The file names
+    int nFiles = filenames->n;		// The number of input files
+    psArray *maps = psArrayAlloc(nFiles); // The maps, to be returned
+    char mapfile[MAXCHAR];		// Filename of map
+    
+    psTrace("stac.read.maps",1,"Reading maps....\n");
+    for (int i = 0; i < nFiles; i++) {
+	if (strlen(filenames->data[i]) > MAXCHAR - 4) {
+	    psLogMsg("stac.read.maps",PS_LOG_ERROR,"Filename %s is too long.\n",filenames->data[i]);
+	    exit(EXIT_FAILURE);
+	}
+	// Open the file
+	sprintf(mapfile,"%s.map",filenames->data[i]);
+	FILE *mapfp = fopen(mapfile,"r");
+	if (mapfp == NULL) {
+	    psLogMsg("stac.read.maps", PS_LOG_ERROR, "Cannot open map file, %s\n",mapfile);
+	    exit(EXIT_FAILURE);
+	}
+	// Read the file
+	psTrace("stac.read.maps",5,"Reading map file %s....\n",mapfile);
+	psPlaneTransform *map = psPlaneTransformAlloc(ORDER,ORDER);
+
+	// Format is as following:
+	// A0  A1
+	// B00 B01
+	// B10 B11
+	//
+	// where:
+	// x_sky = A0 + B00*x + B10*y
+	// y_sky = A1 + B01*x + B11*y
+
+	double a0, a1, b00, b10, b01, b11;
+
+	if (fscanf(mapfp,"%lf %lf %lf %lf %lf %lf", &a0, &a1, &b00, &b01, &b10, &b11) != 6) {
+	    psLogMsg("stac.read.maps", PS_LOG_ERROR, "Couldn't read all 6 transformation values from %s\n",
+		     mapfile);
+	    exit(EXIT_FAILURE);
+	}
+	fclose(mapfp);
+	map->x->coeff[0][0] = a0;
+	map->x->coeff[1][0] = b00;
+	map->x->coeff[0][1] = b10;
+	map->y->coeff[0][0] = a1;
+	map->y->coeff[1][0] = b01;
+	map->y->coeff[0][1] = b11;
+
+	// Mask out the cross-terms
+	map->x->mask[1][1] = 0;
+	map->y->coeff[1][1] = 0;
+	// Set the cross-terms to zero, just in case...
+	map->x->coeff[1][1] = 0.0;
+	map->y->coeff[1][1] = 0.0;
+
+	// Plug it into the array
+	maps->data[i] = map;
+
+#ifdef TESTING
+	// Check psLib's answer is the same as I would get with old version
+	double detx = 256.0, dety = 256.0;
+	// My code
+	double myx = a0 + b00*detx + b10*dety;
+	double myy = a1 + b01*detx + b11*dety;
+	// psLib
+	psPlane *det = psAlloc(sizeof(psPlane));
+	det->x = 256.0;
+	det->y = 256.0;
+	psPlane *pslib = psPlaneTransformApply(NULL, map, det);
+
+	psTrace("stac.read.maps.test",0,"me: %lf,%lf\n",myx,myy);
+	psTrace("stac.read.maps.test",0,"ps: %lf,%lf\n",pslib->x,pslib->y);
+	psFree(det);
+	psFree(pslib);
+#endif
+
+    }
+    psTrace("stac.read.maps",1,"%d maps read.\n",nFiles);
+
+    return maps;
+}
Index: /tags/start/stac/src/stacRejection.c
===================================================================
--- /tags/start/stac/src/stacRejection.c	(revision 12606)
+++ /tags/start/stac/src/stacRejection.c	(revision 12606)
@@ -0,0 +1,99 @@
+#include <stdio.h>
+#include "pslib.h"
+#include "stac.h"
+
+
+psArray *stacRejection(psArray *inputs,	// Input images
+		       psArray *transformed, // Transformed images
+		       psImage *combined, // Combined image
+		       psArray *maps,	// Maps from input to transformed image
+		       psArray *rejected, // Rejected images
+		       stacConfig *config // Configuration
+    )
+{
+    int nImages = inputs->n;		// Number of input images
+
+    // Check inputs
+    if (inputs->n != transformed->n) {
+	psError("stac.rejection", "Number of input (%d) and transformed (%d) images does not match.\n",
+		inputs->n, transformed->n);
+	return NULL;
+    }
+    for (int i = 0; i < nImages; i++) {
+	if ((((psImage*)(transformed->data[i]))->numRows != combined->numRows) ||
+	    (((psImage*)(transformed->data[i]))->numCols != combined->numCols)) {
+	    psError("stac.rejection",
+		    "Sizes of transformed (%dx%d) and combined (%dx%d) images do not match.\n",
+		    ((psImage*)(transformed->data[i]))->numCols, ((psImage*)(transformed->data[i]))->numRows,
+		    combined->numCols, combined->numRows);
+	    return NULL;
+	}
+	if ((((psImage*)(transformed->data[i]))->numRows != ((psImage*)(rejected->data[i]))->numRows) ||
+	    (((psImage*)(transformed->data[i]))->numCols != ((psImage*)(rejected->data[i]))->numCols)) {
+	    psError("stac.rejection",
+		    "Sizes of transformed (%dx%d) and rejected (%dx%d) images do not match.\n",
+		    ((psImage*)(transformed->data[i]))->numCols, ((psImage*)(transformed->data[i]))->numRows,
+		    ((psImage*)(rejected->data[i]))->numCols, ((psImage*)(rejected->data[i]))->numRows);
+	    return NULL;
+	}
+    }
+
+    // Size of output images
+    int nxOutput = combined->numCols;
+    int nyOutput = combined->numRows;
+
+    // Stuff for the transformations
+    psPlane *inCoords = psAlloc(sizeof(psPlane)); // Coordinates on the input
+    psPlane *outCoords = psAlloc(sizeof(psPlane)); // Coordinates on the output
+
+    psTrace("stac.rejection", 1, "Mapping rejection masks back to source....\n");
+
+    // Transform rejection masks back to source
+    psArray *inputRej = psArrayAlloc(nImages);
+    for (int i = 0; i < nImages; i++) {
+	// Size of input image
+	int nxInput = ((psImage*)(inputs->data[i]))->numCols;
+	int nyInput = ((psImage*)(inputs->data[i]))->numRows;
+	psImage *mask = psImageAlloc(nxInput, nyInput, PS_TYPE_F32); // The mask in the source frame
+	psImage *reject = rejected->data[i]; // Pull out the mask in the output frame
+	psPlaneTransform *map = maps->data[i]; // The map from input to output
+
+	psTrace("stac.rejection", 3, "Transforming rejection mask %d....\n", i);
+
+	// Transform the mask
+	// Optimisation option is to only transform the pixels that have been rejected in the output,
+	// calculate derivatives of the map, and use that as a buffer around the transformed position
+	// in the input image.
+	for (int y = 0; y < nyInput; y++) {
+	    for (int x = 0; x < nxInput; x++) {
+    		inCoords->x = (double)x + 0.5;
+		inCoords->y = (double)y + 0.5;
+		(void)psPlaneTransformApply(outCoords, map, inCoords);
+		mask->data.F32[y][x] = psImagePixelInterpolate(reject, outCoords->x, outCoords->y,
+							       NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR);
+
+	    }
+	}
+
+#ifdef TESTING
+	// Write error image out to check
+	char maskfile[MAXCHAR];	// Filename of mask image
+	sprintf(maskfile,"%s.mask",config->inputs->data[i]);
+	psImageWriteSection(mask,0,0,0,NULL,0,maskfile);
+#endif
+
+	// Clip the image, and convert to suitable mask format
+	(void)psImageClip(mask, config->frac, 0.0, config->frac, 1.0);
+	psImage *maskU8 = psImageCopy(NULL, mask, PS_TYPE_U8);
+	psFree(mask);
+    
+	// Stuff into the array
+	inputRej->data[i] = maskU8;
+
+    }
+
+    psFree(inCoords);
+    psFree(outCoords);
+
+    return inputRej;
+}
Index: /tags/start/stac/src/stacTransform.c
===================================================================
--- /tags/start/stac/src/stacTransform.c	(revision 12606)
+++ /tags/start/stac/src/stacTransform.c	(revision 12606)
@@ -0,0 +1,242 @@
+#include <stdio.h>
+#include "pslib.h"
+#include "stac.h"
+
+#define SQUARE(x) ((x)*(x))
+#define MIN(x,y) (((x) > (y)) ? (y) : (x))
+#define MAX(x,y) (((x) > (y)) ? (x) : (y))
+
+#define MAXCHAR 80
+
+static int numTransforms = 0;		// Number of transformations performed
+
+
+// Hacked the original ps_ImagePixelInterpolateBILINEAR_F32 to add variances
+// i.e., to square the fractions when combining.
+inline psF64 p_psImageErrorInterpolateBILINEAR_F32(const psImage* input, 
+						   float x, 
+						   float y, 
+						   const psImage* mask, 
+						   unsigned int maskVal,
+						   psF64 unexposedValue)
+{ 
+    double floorX = floor((psF64)(x) - 0.5); 
+    double floorY = floor((psF64)(y) - 0.5); 
+    psF64 fracX = x - 0.5 - floorX; 
+    psF64 fracY = y - 0.5 - floorY; 
+    int intFloorX = (int) floorX; 
+    int intFloorY = (int) floorY; 
+    int lastX = input->numCols - 1; 
+    int lastY = input->numRows - 1; 
+    psF32 V00; 
+    psF32 V01; 
+    psF32 V10; 
+    psF32 V11; 
+    bool valid00 = false; 
+    bool valid01 = false; 
+    bool valid10 = false; 
+    bool valid11 = false; 
+    
+    if (intFloorY >= 0 && intFloorY <= lastY) { 
+        if (intFloorX >= 0 && intFloorX <= lastX) { 
+            V00 = input->data.F32[intFloorY][intFloorX]; 
+	    valid00 = true;
+        } 
+        if (intFloorX >= -1 && intFloorX < lastX) { 
+            V10 = input->data.F32[intFloorY][intFloorX+1]; 
+	    valid10 = true;
+        } 
+    } 
+    if (intFloorY >= -1 && intFloorY < lastY) { 
+        if (intFloorX >= 0 && intFloorX <= lastX) { 
+            V01 = input->data.F32[intFloorY+1][intFloorX]; 
+	    valid01 = true;
+        } 
+        if (intFloorX >= -1 && intFloorX < lastX) { 
+            V11 = input->data.F32[intFloorY+1][intFloorX+1]; 
+	    valid11 = true;
+        } 
+    } 
+    
+    /* cover likely case of all pixels being valid more efficiently */  
+    if (valid00 && valid10 && valid01 && valid11) { 
+        /* formula from the ADD */ 
+        return V00*SQUARE((1.0-fracX)*(1.0-fracY)) + V10*SQUARE(fracX*(1.0-fracY)) +
+	    V01*SQUARE(fracY*(1.0-fracX)) + V11*SQUARE(fracX*fracY);
+    } 
+    
+    /* OK, at least one pixel is not valid - need to do it piecemeal */ 
+    
+    psF64 V0; 
+    bool valid0 = true; 
+    if (valid00 && valid10) { 
+        V0 = V00*SQUARE(1-fracX)+V10*SQUARE(fracX); 
+    } else if (valid00) { 
+        V0 = V00; 
+    } else if (valid10) { 
+        V0 = V10; 
+    } else { 
+        valid0 = false; 
+    } 
+    
+    psF64 V1; 
+    bool valid1 = true; 
+    if (valid01 && valid11) { 
+        V1 = V01*SQUARE(1-fracX)+V11*SQUARE(fracX); 
+    } else if (valid01) { 
+        V1 = V01; 
+    } else if (valid11) { 
+        V1 = V11; 
+    } else { 
+        valid1 = false; 
+    } 
+    
+    if (valid0 && valid1) { 
+        return ( V0*SQUARE(1-fracY) + V1*SQUARE(fracY) ); 
+    } else if (valid0) { 
+        return V0; 
+    } else if (valid1) { 
+        return V1; 
+    } 
+    
+    return unexposedValue; 
+}
+
+
+
+psArray *stacTransform(const psArray *images, // Array of images to be transformed
+		       const psArray *maps, // Array of polynomials that do the transformation
+		       const psArray *errors, // Array of error images to be transformed
+		       psArray **outErrors, // Transformed error images for output
+		       const psArray *masks, // Masks of input images
+		       const stacConfig *config	// Configuration
+    )
+{
+    int nImages = images->n;		// Number of images
+    int nx = config->outnx, ny = config->outny; // Size of output images
+    numTransforms++;
+
+    // Check input sizes
+    if (images->n != maps->n) {
+	psError("stac.transform", "Number of maps (%d) does not match number of images (%d).\n",
+		maps->n, images->n);
+	return NULL;
+    }
+    if (errors && (images->n != errors->n)) {
+	psError("stac.transform", "Number of error images (%d) does not match number of images (%d).\n",
+		errors->n, images->n);
+	return NULL;
+    }
+
+    if (errors && (*outErrors == NULL)) {
+	// Allocate the output error images, if required
+	*outErrors = psArrayAlloc(errors->n);
+    } else if (errors->n != (*outErrors)->n) {
+	psError("stac.transform", "Number of error output images (%d) does not match number of input"
+		"images (%d).\n", (*outErrors)->n, errors->n);
+	return NULL;
+    }
+
+    if (masks != NULL) {
+	if (masks->n != nImages) {
+	    psError("stac.transform", "Number of masks (%d) does not match number of input images (%d).\n",
+		    masks->n, nImages);
+	    return NULL;
+	}
+	for (int i = 0; i < nImages; i++) {
+	    psImage *image = images->data[i];
+	    psImage *mask = masks->data[i];
+	    if ((mask->numRows != image->numRows) || (mask->numCols != image->numCols)) {
+		psError ("stac.transform",
+			 "Size of input mask (%dx%d) does not match that of input image (%dx%d).\n",
+			 mask->numCols, mask->numRows, image->numCols, image->numRows);
+		return NULL;
+	    }
+	}
+    }
+
+    // Arrays of images for return
+    psArray *outImages = psArrayAlloc(nImages);	// Output images
+
+    // Stuff for the transformations
+    psPlane *detector = psAlloc(sizeof(psPlane)); // Coordinates on the detector
+    psPlane *sky = psAlloc(sizeof(psPlane)); // Coordinates on the sky
+
+    // Iterate over the images
+    for (int n = 0; n < nImages; n++) {
+	psTrace("stac.transform", 1, "Transforming image %d....\n",n);
+
+	// Pull out the various stuff we're working on
+	psImage *image = images->data[n]; // The input image
+	psPlaneTransform *map = maps->data[n]; // The map
+	psImage *error = errors->data[n]; // The error image
+
+	// Initialise the output images
+	psImage *outImage = psImageAlloc(nx, ny, PS_TYPE_F32);
+	psImage *outError = psImageAlloc(nx, ny, PS_TYPE_F32);
+	psTrace("stac.transform", 5, "Allocating space for transformed image, %dx%d\n", nx, ny);
+	for (int y = 0; y < ny; y++) {
+	    for (int x = 0; x < nx; x++) {
+		outImage->data.F32[y][x] = 0.0;
+		outError->data.F32[y][x] = 0.0;
+	    }
+	}
+
+	// Mask
+	psImage *mask = NULL;
+	if (masks != NULL) {
+	    mask = masks->data[n];
+	}
+
+#if 0
+	// Calculate scales; could be adapted for higher order than linear by moving this into the
+	// pixel-dependent section and calculating derivatives
+	double xscale = 0.5*sqrt(SQUARE(map->x->coeff[0][1]) + SQUARE(map->x->coeff[1][0]));
+	double yscale = 0.5*sqrt(SQUARE(map->y->coeff[0][1]) + SQUARE(map->y->coeff[1][0]));
+	double areascale = 0.25 / xscale / yscale;
+#endif
+
+	// Iterate over the output image pixels
+	for (int y = 0; y < ny; y++) {
+	    for (int x = 0; x < nx; x++) {
+		// Transform!
+		// Could no doubt make this quicker by calculating derivatives and incrementing by those.
+		sky->x = (double)x + 0.5;
+		sky->y = (double)y + 0.5;
+		(void)psPlaneTransformApply(detector, map, sky);
+
+		outImage->data.F32[y][x] = (psF32)psImagePixelInterpolate(image, detector->x, detector->y,
+									  mask, 1, 0.0,
+									  PS_INTERPOLATE_BILINEAR);
+		outError->data.F32[y][x] = (psF32)p_psImageErrorInterpolateBILINEAR_F32(error, detector->x,
+											detector->y, mask, 1,
+											0.0);
+		outError->data.F32[y][x] = sqrtf(outError->data.F32[y][x]);
+	    }
+	} // Iterating over output pixels
+
+#ifdef TESTING
+	// Write error image out to check
+	char shiftfile[MAXCHAR];	// Filename of shift image
+	char errfile[MAXCHAR];		// Filename of error image
+	sprintf(shiftfile,"%s.shift.%d",config->inputs->data[n],numTransforms);
+	sprintf(errfile,"%s.shifterr.%d",config->inputs->data[n],numTransforms);
+	psTrace("stac.transform.test", 6,
+		"Output files have size: %dx%d\n",outImage->numCols,outImage->numRows);
+	psImageWriteSection(outImage,0,0,0,NULL,0,shiftfile);
+	psImageWriteSection(outError,0,0,0,NULL,0,errfile);
+#endif
+
+	// Plug the new images into arrays
+	outImages->data[n] = outImage;
+	(*outErrors)->data[n] = outError;
+
+    } // Iterating over images
+
+    // Done with transformations
+    psFree(detector);
+    psFree(sky);
+
+    return outImages;
+}
+
